fix(server): show Claude project skills before command discovery completes#23114
Problem
After a Claude thread's workspace snapshot is evicted by scans of 16 other folders, its $ picker temporarily shows only personal skills. Project skills wait for a fresh Claude capability probe even though filesystem skill discovery has already finished.
Change
Publish discovered Claude workspace skills before the capability probe, with slash commands pending. Partial and final results use the same registry ownership and freshness guards. The final result replaces its own partial publication; the 16-workspace cap remains.
Other providers keep their existing one-result discovery path. No wire schema or client rendering changes.
Scope and approval
Fixes #22429 GitCafe: https://git.cafe/pingdotgg/t3code/issues/22429 Triaged bug via the automated issue flow. One reproduced cache-eviction timing defect; no authentication, permission, mode, sandbox, or MCP changes.
Verification
- Main reproduction: 17 real worktrees of one repository, each with a project-only Claude skill. Returning to the first after scanning the other 16 temporarily showed personal skills only; repeated with a filtered skill query.
- Red test committed before the fix: the registry had no project skills while a Deferred held command discovery after eviction. After the fix, the same test observes skills with commands pending, then final commands and cleared pending state.
- Post-merge
vp run check:changed: formatting, targeted lint, Knip, generated GraphQL verification, affected-package typechecks, and the full registry test file (38/38) passed. - Additional implementation checks: Codex/Antigravity discovery test files (29/29), Pi driver tests (5/5), server and provider-core typechecks passed.
- Two isolated code reviews returned MERGE. The actual PR diff after merging current main is byte-identical to the reviewed diff.
Evidence matrix
Before: beec3c8b30ce. After: 26c41f4c7fa8.
Formal static render matrix: empty ([]). The changed paths are server/provider internals; the four rows below are supplemental interaction recordings. No still-image/pixel-diff claim is made. The pass-1 matrix and audit are in the linked support bundle; independent pass-2 proof audit passed all six required evidence rows.
Script and observed ordering
Same 17 stopped fixture threads and project skill on both isolated servers. A is folder 02. Prime A, type $triage, visit 03–17 then 01 sequentially and await each real settled snapshot, prove A absent with 16 cached folders, return A within 15–21 seconds, keep $triage visible through discovery, then show / and query /compact. No turns sent. The actual /compact query suggests /autocompact on both sides; the unchanged final provider snapshot contains 70 command names.
Before: the project row is missing while the personal skill remains, then appears only after final command publication. After: the project row becomes visible with slashCommandsPending:true, 448–744 ms before final publication in these runs. A brief filesystem-discovery gap remains; this eliminates the slow CLI interval, not every millisecond of absence. All recorded snapshot lists stay at or below 16.
| Width / theme | Before: pending at project visibility | After: project visible before final publication |
|---|---|---|
| 1440 / light | No | 562 ms; pending=true |
| 1440 / dark | No | 744 ms; pending=true |
| 390 / light | No | 448 ms; pending=true |
| 390 / dark | No | 573 ms; pending=true |
Rebuild, transcript and audit metadata
Rebuild guide · Support bundle: scripts, fixture creation data, pass-1 audit/matrix, provenance, probe spans, red/green logs · Ordered live runtime transcript · Capture audit metadata
The transcript subscribes to the real appAtomRegistry / serverEnvironment.providersValueAtom and observes actual DOM mutations. It records cwd, skill/pending/count milestones and the final real command names. Server workspace-probe spans are correlated by timestamp; they lack cwd attributes and an independent CLI subprocess span, so no exact CLI launch/completion claim is made. Parent-provided green log labels the final head and reports 38 focused tests passing. Historical red output lacks an in-band invocation/SHA; its provenance limit is retained in metadata.
What else changed and rendering
The intended visible difference is the transient project row during discovery. Final command names match across all eight runs. Live age badges differ with capture time, and caret/text selection plus recording frame sampling vary while typing; no pixel-identity claim is made. The same responsive route navigation, viewport, theme, fixture, provider and scroll position are used per pair. Sidebar filtering hides unrelated threads; update notifications were dismissed. A02 avoids a separate active A01 client refreshing its own evicted cwd.
Tool/browser: T3 collaborative Browser, Chrome 154 on Linux. No device emulation; freeform 1440×900 or 390×900 CSS viewport, DPR 2, visual viewport scale 1, root font 16px, text-size-adjust 100%. Complete native viewport footage is 2880×1800 or 780×1800. A 240-native-pixel caption band sits outside the app; the original recording is uncut and retains its speed, with a labelled four-second final-frame hold. Captions narrate script and browser-clock milestones; compositor/video frames are not perfectly synchronized to DOM subscription timestamps. No artificial provider delays, fake snapshots or synthetic component fixtures were used.
Served Vite source-map originals for five relevant runtime/client files per checkout match the exact git refs. Server cwd/start times and observed partial/final behavior support runtime provenance; no in-process build hash endpoint exists. The before server predates the merge-base checkout, but all four changed runtime files are byte-identical between its original base and the final base.
Limits and publication
Native iOS/Android, desktop shell, remote/relay and multi-device runtime timing remain unverified. Clean-room reseeding was not executed: rebuild scripts were syntax/source checked and captures reused the parent’s fixture. Personal skill source files and unrelated data are excluded. Independent pass-2 proof audit passed; this is evidence for review, not merge approval.
Before upload, both required cafe issue reads succeeded with zero comments and complete pagination; no recent MEMBER/OWNER comment existed. No repository edits, commits, pushes, issue/PR writes, new dev servers or agent turns were made by this capture task.
Unverified: Electron shell, native iOS/Android, remote/relay/tunnel, multi-device, cancellation and instance replacement at runtime. Their code paths are unchanged. Filesystem discovery still takes its normal time; this removes the wait on the slow command probe.
Implementation: Claude Opus 5.5 via Claude Agent SDK; triage, integration and evidence: GPT-6.1-Sol via Codex; independent code/proof reviews: GPT-6.1-Sol via Codex and Claude Opus 5.5 via Claude Agent SDK.
Checks
Failing3
- Build and TypecheckGitHubFailed
- CheckGitHubFailed
- Test WebGitHubFailed
Added 3 commits
Approvability
Verdict: Approved at 26c41f4
Macroscope's review found this PR approvable — This is a focused server bug fix that exposes already-discovered Claude project skills during the existing slow command probe, then preserves the established final snapshot behavior. The change is localized, backward-compatible for other providers, and covered by a regression test.
You can add or adjust custom eligibility rules. Learn more.
Thread transfer impact
✅ Thread transfer remains within every enforced ceiling.
ℹ️ The exact PR base did not have a successful artifact. Baseline uses the latest successful
mainmeasurement shown below.
| Provider | Metric | Main baseline | This PR | Impact | PR ceiling | |
|---|---|---|---|---|---|---|
| Codex | Total thread wire | 5.0 KiB | 5.0 KiB | −7 B (−0.1%) | 6.8 KiB | ✅ |
| Codex | Thread snapshot wire | 3.8 KiB | 3.8 KiB | 0 B (0.0%) | 4.9 KiB | ✅ |
| Codex | Live turn WebSocket wire | 1.2 KiB | 1.2 KiB | −7 B (−0.6%) | 2.0 KiB | ✅ |
| Codex | Live turn WebSocket decoded | 20.9 KiB | 20.9 KiB | 0 B (0.0%) | 29.3 KiB | ✅ |
| Codex | Live turn messages | 2 | 2 | 0 (0.0%) | 8 | ✅ |
| Claude | Total thread wire | 5.0 KiB | 5.0 KiB | 0 B (0.0%) | 6.8 KiB | ✅ |
| Claude | Thread snapshot wire | 3.8 KiB | 3.8 KiB | 0 B (0.0%) | 4.9 KiB | ✅ |
| Claude | Live turn WebSocket wire | 1.2 KiB | 1.2 KiB | 0 B (0.0%) | 2.0 KiB | ✅ |
| Claude | Live turn WebSocket decoded | 21.2 KiB | 21.2 KiB | 0 B (0.0%) | 29.3 KiB | ✅ |
| Claude | Live turn messages | 2 | 2 | 0 (0.0%) | 8 | ✅ |
Baseline: 159f2b8 · PR result: 26c41f4 · Source CI: failure
Scenario and decoded snapshot size
10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
- Codex decoded thread snapshot: 108.5 KiB
- Claude decoded thread snapshot: 108.8 KiB
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.
No actionable comments were generated in the recent review. 🎉
ℹ️ Recent review info
⚙️ Run configuration
- Configuration used: Path: .coderabbit.config.ts
- Review profile: CHILL
- Plan: Team
- Run ID:
87d35d61-838e-43b7-b429-4072849f9263
📥 Commits
Reviewing files that changed from the base of the PR and between 2333f168845f853f9ef358d1c4e6cf75189f4e8b and 26c41f4c7fa8721d1fa2fee9b4de2e026e049ac8.
📒 Files selected for processing: 5
apps/server/src/provider/ClaudeProvider.tsapps/server/src/provider/Drivers/ClaudeDriver.tsapps/server/src/provider/ProviderRegistry.test.tsapps/server/src/provider/ProviderRegistry.tspackages/provider-core/src/server/driver.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 0 remain after this review.
📝 Walkthrough
Claude workspace scans now publish discovered skills before slash-command probing completes. The provider registry then publishes the final snapshot and retains ownership checks for partial and final updates.
Changes: Workspace snapshot updates
Layer / File(s) Summary Claude partial snapshot callback
packages/provider-core/src/server/driver.ts,apps/server/src/provider/Drivers/ClaudeDriver.ts,apps/server/src/provider/ClaudeProvider.tsThe driver accepts and forwards an optional partial-publication callback. Claude probing calls it after skill discovery with slash-command discovery marked pending. Registry snapshot updates
apps/server/src/provider/ProviderRegistry.ts,apps/server/src/provider/ProviderRegistry.test.tsThe registry publishes partial and final results through an ownership-checked path. The integration test verifies that discovered skills are published before slow command probing finishes, then checks the final command result. Priority: ⬇️ Low
Estimated code review effort: 3 (Moderate) | ~20 minutes
Change: Bug fix
Sequence Diagram(s)
mermaid1 sequenceDiagram 2 participant ProviderRegistry 3 participant ClaudeDriver 4 participant ClaudeProvider 5 ProviderRegistry->>ClaudeDriver: Start snapshotForCwd with publishPartial 6 ClaudeDriver->>ClaudeProvider: Probe workspace with publishPartial 7 ClaudeProvider->>ProviderRegistry: Publish skills with slashCommandsPending true 8 ClaudeProvider-->>ClaudeDriver: Return final workspace snapshot 9 ClaudeDriver-->>ProviderRegistry: Return final workspace snapshot Suggested reviewers:
maria-rcks,t3dotgg
Merge Risk: ⚪ Minimal · up to 26c41
Workspace skills can appear before command discovery completes, without an established issue that needs correction before merge.
Pre-merge checks: Passed 4
Check name Status Explanation Title check Passed The title clearly and concisely describes the main change: showing Claude project skills before command discovery completes. Linked Issues check Passed Check skipped because no linked issues were found for this pull request. Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request. Description check Passed The pull request description includes all required sections: Problem, Change, Scope and approval, and Verification. It explains the defect, implementation, issue reference, approval context, focused t… Full details: Description check
Explanation
The pull request description includes all required sections: Problem, Change, Scope and approval, and Verification. It explains the defect, implementation, issue reference, approval context, focused tests, observed results, limitations, and agent details. The description is complete and relevant.
✨ Finishing Touches: 💡 1
-
🛠️ Fix failing CI checks: 💡
- Commit to this branch
- Create a new PR
📝 Generate docstrings
- Commit to this branch
- Create a new PR
🧪 Generate unit tests (beta)
- Commit to this branch
- Create a new PR
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Comment @coderabbitai help to get the list of available commands.