fix(t3code): read environment capabilities; stop polling the Keychain while unpaired - #98
fix(t3code): read environment capabilities; stop polling the Keychain while unpaired#98DevVig wants to merge 1 commit into
Conversation
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 50 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
Comment |
There was a problem hiding this comment.
Pull request overview
Updates the T3 Code adapter (crates/microbridged) to better reflect what a paired T3 environment actually supports (via .well-known/t3/environment) and to reduce unnecessary secure-store reads while the adapter is unpaired.
Changes:
- Deserialize and track
capabilitiesfrom the environment descriptor; reset them on disable/unpair and surface advertised-but-unwired surfaces in the adapter diagnostic. - Back off Keychain re-reads while unpaired (from every 900ms tick to every 3s).
- Add unit tests covering decoding of a live descriptor shape (including unknown key types) and the new diagnostic behavior.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if credential.is_none() { | ||
| credential = load_credential().ok(); | ||
| if credential.is_none() { | ||
| // Unpaired. `load_credential` reads the macOS | ||
| // Keychain, so retrying on the 900 ms tick means | ||
| // thousands of Keychain hits an hour for a state | ||
| // only the user can change. Back off; pairing is | ||
| // picked up on the next attempt. | ||
| retry_after = tokio::time::Instant::now() + UNPAIRED_RECHECK; | ||
| continue; | ||
| } | ||
| } |
… while unpaired Two independent fixes found while checking the paired contract against a live T3 Code (Nightly) 0.0.29-nightly.20260725.899 environment. Environment capabilities were being discarded. The descriptor at `.well-known/t3/environment` now returns a `capabilities` object (`threadSettlement`, `threadSnooze`, `connectionProbe`, `repositoryIdentity`, `serverSelfUpdate`) that `EnvironmentDescriptor` did not deserialize at all, so the adapter could not tell what this environment supports — a nightly can gain or lose a surface without the base version moving. It is now read, reset on unpair/disable, and reported in the adapter diagnostic, which names advertised-but-unbound surfaces instead of implying T3 offers nothing more. `capabilities()` is deliberately unchanged: it still advertises only what `dispatch_action` implements. Reading a flag is not implementing a lever. The Keychain was polled on every tick while unpaired. `load_credential()` is a macOS Keychain read, and it ran on the 900 ms interval whenever no credential was stored — thousands of reads an hour for a state only the user can change. Now backs off 3 s, short enough that pairing still feels immediate. Contract findings recorded for the follow-up (docs land with the controller-lock PR, which owns docs/adapters.md): - No navigation/selection command exists. `thread.jump.1…9` are THREAD_JUMP_KEYBINDING_COMMANDS, local UI keybindings, not dispatchable. - No reasoning-effort concept exists: `reasoningEffort` appears nowhere and `ModelSelection.options` is still an untyped bag — the "provider option descriptors" the existing comment waits on. `RuntimeMode` is an autonomy ladder and `ProviderInteractionMode` is default/plan; neither is effort. - `new_session` needs `bootstrap.createThread` with projectId + title + a model id we have no registry for, so it stays unadvertised. Tested: `cargo test --workspace` (84 tests, 2 new — one decodes the verbatim live descriptor and asserts unknown keys like `serverSelfUpdate` do not break decoding; one covers the diagnostic). Verified against the live environment on port 3774. Not exercised against a paired environment end to end: the stored credential is revoked, so `apply_snapshot` could not be reached. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
953f09a to
a7fe05d
Compare
Two independent fixes found while checking the paired contract against a live
T3 Code (Nightly)
0.0.29-nightly.20260725.899environment.1. Environment capabilities were discarded
.well-known/t3/environmentnow returns acapabilitiesobject thatEnvironmentDescriptordid not deserialize at all:{ "repositoryIdentity": true, "connectionProbe": true, "threadSettlement": true, "threadSnooze": true, "serverSelfUpdate": "desktop-managed" }So the adapter had no way to tell what this environment supports — and a
nightly can gain or lose a surface without the base version moving. Now read,
reset on unpair/disable, and surfaced in the diagnostic so the Settings card
names advertised-but-unbound surfaces rather than implying T3 offers nothing more.
capabilities()is deliberately unchanged — it still advertises only whatdispatch_actionimplements. Reading a flag is not implementing a lever.2. The Keychain was polled every 900 ms while unpaired
load_credential()is a macOS Keychain read, and it ran on the adapter's normaltick whenever no credential was stored — thousands of reads an hour for a state
only the user can change. Now backs off 3 s.
Contract findings, for the record
No version bump needed:
0.0.29-nightly.…is already inside the pinned range.thread.jump.1…9areTHREAD_JUMP_KEYBINDING_COMMANDS— local UI keybindings, not dispatchable.Binding them would be the keystroke synthesis this adapter refuses.
reasoningEffortappears nowhere;ModelSelection.optionsis still an untyped bag — literally the "provideroption descriptors" the existing comment waits on. The near-misses are
different things:
RuntimeModeis an autonomy ladder(
approval-required→full-access) andProviderInteractionModeisdefault/plan.new_sessionstays unadvertised.thread.turn.startneeds an existingthreadId, orbootstrap.createThreadwithprojectId+title+ amodelSelection.modelwe have no registry for.thread.settle/unsettle,thread.snooze/unsnooze,thread.archive/unarchive.How this was tested
cargo test --workspace— 84 tests, 2 new: one decodes the verbatim livedescriptor and asserts unknown keys (
serverSelfUpdate, a string not a bool)don't break decoding; one covers the diagnostic.
cargo clippy --workspace --all-targets -- -D warningsandcargo fmt --all --checkclean.3773 in the unit-test fixture).
Not verified
The stored credential is revoked, so
apply_snapshot— and therefore the newdiagnostic on a real snapshot — could not be reached end to end. Needs a re-pair.
Docs for these findings land with the controller-lock PR, which owns
docs/adapters.md; kept out of here to avoid a merge conflict between the two.🤖 Generated with Claude Code