You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(server): turns recreate a worktree folder that lost its checkout - #34894
The failing Agent context budget check was not caused by this change. The PR does not change any agent context text. After the previous merge, main lowered apps/server/src/provider/agentContextBudget.json by 3 bytes in 0568a63 (#30371), so the branch's older copy looked like growth. Merging origin/main again (merge commit, no conflicts) brings the budget file to main's values. The PR diff is unchanged: four server files covering worktree recovery in the shared restoreMissingWorktree helper (clears a folder only when it has no .git and holds only node_modules/.next directories), storage cleanup keeping such folders, and their tests.
In the app, create a worktree thread in a pnpm project and let setup install dependencies. Stop the turn, record its branch, then delete everything in that worktree except node_modules, including .git; optionally run git worktree prune in the project repository. Send another message to the same thread and ask the agent to report its current directory, branch, and tracked files. On main, recovery is skipped and the folder remains without a checkout; with this change, the leftover directory is removed and the thread's checkout is recreated before provider startup. Separately, trigger storage cleanup for an eligible archived thread in the same broken-folder state: main reports a missing-.git failure, whereas this change reports the folder as kept. These steps were read from the issue and PR, not executed.
Evidence
Evidence captured in Chromium at 1280×800, light theme, against fresh isolated servers with synthetic data and Replay. Create a worktree, install pnpm dependencies, leave only node_modules, remove .git, prune, and resume the thread. Separately archive another broken-folder thread and run storage cleanup. Filesystem observations are measured by the driver and displayed in chat, not generated by Replay. Absolute paths are redacted.
scenarios:prove exited 0: failed on base and passed on head.
Not shown:
Automatic project setup and interrupting an active turn were not exercised: pnpm was invoked directly in the app-created checkout, and the initial Replay turn finished before folder corruption. A live provider's directory report was not exercised; the driver measured the actual filesystem and git state.
Tests
Compared agentContextBudget.json on the branch and origin/main (5597/7327 vs 5594/7324) and found the main commit that lowered it. After the merge, vp run check:changed passed: format, lint, knip, typecheck (3 packages), tests (3 files). The budget check itself was not rerun locally; CI runs it on the new head.
Not in this change
Already-broken folders that hold user files besides node_modules/.next are still not recovered; turns keep running there. Deciding what to do with them needs a maintainer decision.
Who did the work
Written by Claude Opus 5.5, in Claude Code
Reviewed by GPT-6.1 Sol, in Codex, and by Claude Opus 5.5, each on its own
Proof captured by GPT-6.1 Sol and checked by Claude Opus 5.5
…d kept
Repro for #24390: turn start skips recreation when the managed worktree
folder exists without a checkout, and the storage cleanup sweep fails on
the missing .git instead of keeping the folder.
AI-assisted; verified with the tests and tools listed above.
A failed removal can leave a thread's managed worktree folder behind with no
.git link. Turn start only checked that the folder existed, so the agent ran
outside any checkout and git commands reached the repository around it.
Turn start now checks for the folder's .git, clears the leftover folder, and
recreates the checkout. Storage cleanup keeps such a folder as "not a linked
worktree" instead of failing the sweep on the missing .git.
Fixes#24390
AI-assisted; verified with the tests and tools listed above.
Macroscope's review found this PR approvable — Restores managed worktrees whose checkout disappeared but left dependency or build directories behind. Recovery preserves existing checkouts and folders containing other entries, while cleanup safely skips folders missing .git.
No code changes detected at 6facbfe. Prior analysis still applies.
You can add or adjust custom eligibility rules. Learn more.
No actionable comments were generated in the recent review.
Walkthrough
Managed-worktree recovery identifies existing directories without .git that contain only node_modules or .next directories, removes eligible managed leftovers, and recreates the worktree. Storage cleanup treats a missing .git entry as a non-linked worktree and propagates other stat errors.
Changes: Managed worktree recovery and cleanup
Layer / File(s)
Summary
Detect and recreate incomplete worktrees apps/server/src/workspace/restoreMissingWorktree.ts, apps/server/src/orchestration-v2/ProviderTurnStartService.test.ts
Recovery recognizes eligible managed directories without .git, removes them before recreation, and leaves paths with other contents untouched. Tests cover leftover recovery and preservation of a user file.
Handle missing worktree links during cleanup apps/server/src/storageCleanup.ts, apps/server/src/storageCleanup.test.ts
A missing .git entry is treated as a non-linked worktree. Other stat errors still propagate. A test verifies that cleanup keeps the directory and its node_modules contents.
This change lets turn start recover a managed worktree folder that lost its checkout. It also stops storage cleanup from failing when .git is missing. No actionable merge-blocking risk remains.
Pre-merge checks: 3 · 1
Failed checks: 1 inconclusive
Check name
Status
Explanation
Resolution
Linked Issues check
[#24390] Requirement A, turn-start recovery: the whole-PR diff (merge base f313d0a to head 72db875) changes apps/server/src/workspace/restoreMissingWorktree.ts, not ProviderTurnStartService.ts. The …
1. Confirm that the turn-start path reaches makeRestoreMissingWorktree for an existing managed folder without .git. Name the call site in the explanation or the PR text. 2. Update the PR description to name restoreMissingWorktree.ts and rem…
Passed checks: 3 passed
Check name
Status
Explanation
Title check
The title names the main change: turn starts recreate a managed worktree folder that lost its checkout. It is specific and conventional, and matches the code, tests, and objectives. It does not descri…
Out of Scope Changes check
Every changed file maps to #24390. restoreMissingWorktree.ts adds leftover detection, a managed-path guard, and recursive removal before recreation. storageCleanup.ts handles NotFound for the .git sta…
Description check
The description covers the required sections: Problem, Change, Scope, and Verification. It explains that the failing Agent context budget check comes from an older copy of agentContextBudget.json, not…
Full details: Title check
Explanation
The title names the main change: turn starts recreate a managed worktree folder that lost its checkout. It is specific and conventional, and matches the code, tests, and objectives. It does not describe the storage cleanup change, but that is a secondary aspect.
Full details: Out of Scope Changes check
Explanation
Every changed file maps to #24390. restoreMissingWorktree.ts adds leftover detection, a managed-path guard, and recursive removal before recreation. storageCleanup.ts handles NotFound for the .git stat. The tests cover both behaviors. The change to restoreMissingWorktree.ts also includes a comment and a path import, which support the same behavior. No unrelated file changes appear in the whole-PR diff for these paths. The PR description is stale about ProviderTurnStartService.ts, but this is a description mismatch, not an out-of-scope code change.
Full details: Description check
Explanation
The description covers the required sections: Problem, Change, Scope, and Verification. It explains that the failing Agent context budget check comes from an older copy of agentContextBudget.json, not from this change, and that a merge of origin/main resolves it. It states the problem and reproduction steps, links the issue #24390, and describes the change to restoreMissingWorktree and storage cleanup. Verification lists focused commands, the observed results, and the items not exercised. Evidence includes before and after captures. The title is a conventional commit form in the linked PR objectives. The description has minor gaps: it does not state a conventional commit title in the description itself, and the Verification section is detailed but the wording is long. The author also states that the reproduction steps were not executed. The Who did the work section names models and harnesses, as the template asks.
Full details: Linked Issues check
Explanation
[#24390] Requirement A, turn-start recovery: the whole-PR diff (merge base f313d0a to head 72db875) changes apps/server/src/workspace/restoreMissingWorktree.ts, not ProviderTurnStartService.ts. The head adds isLeftoverFolder. It treats a folder as a leftover only when it has no .git entry and every top-level entry is a directory named node_modules or .next. Such folders are removed with fileSystem.remove(recursive) before recreateMissingWorktree runs. This matches the issue's node_modules-only reproduction. The PR description and the previous assessment cite ProviderTurnStartService.ts changes (path.join(worktreePath, ".git") check, forced remove inside recreateMissingWorktree). Those changes are absent from the reviewed diff, so the description is stale. I did not confirm that the turn-start path calls makeRestoreMissingWorktree. Requirement B, storage cleanup: storageCleanup.ts now uses Effect.catchReason("PlatformError", "NotFound") on stat(<worktree>/.git) and returns 'not a linked worktree'. This meets the issue's requirement. Open question: the issue's expected behavior covers any managed path that is not a valid checkout. A managed folder without .git that holds any other entry, such as a user file, is still not recovered. The test 'keeps user file' confirms this is intended. The issue text does not settle whether that is in scope. Tests: the test changes are reported as passing. I did not run them.
Resolution
Confirm that the turn-start path reaches makeRestoreMissingWorktree for an existing managed folder without .git. Name the call site in the explanation or the PR text. 2. Update the PR description to name restoreMissingWorktree.ts and remove the ProviderTurnStartService.ts claims, or move the change to the file the description names. 3. State explicitly whether a managed folder without .git that holds non-leftover content must stay unrecovered. If the issue requires recovery for it, extend the rule and add a test.
Finishing Touches
Generate unit tests (beta)
Commit to this branch
Create a new PR
Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Main moved worktree recovery into workspace/restoreMissingWorktree.ts, so
the turn-start change now lives in that shared helper and also covers
terminal launches. The helper only clears a folder without .git when it
holds nothing but node_modules or .next directories; any other content is
left alone and recovery is skipped.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
…6 (Running the fork's tests in apps/server)
Failing check: Running the fork's tests in apps/server
The apps/server fork tests failed in three places. Each was a fork seam that no longer fit upstream's new code, and all three now pass.
**Switchboard auth showed the native endpoint** (`fork/switchboard/claudeDriverRouting.test.ts`). Upstream now adds an `endpoint` field to Claude's custom-endpoint auth info. The fork's Switchboard seam overrode the auth type and label but still let the native auth info through, so a routed probe reported `endpoint: http://native.example`. In `ClaudeProvider.ts` I now drop the native auth info when routed, the same way the fork already drops email and workspace. That line is marked `fork: switchboard`.
**A worktree folder left with only `node_modules` was not rebuilt** (`orchestration-v2/ProviderTurnStartService.test.ts`). Upstream pingdotgg#34894 made `restoreMissingWorktree` clear a managed worktree folder that holds only `node_modules`/`.next` and recreate the checkout. The fork's project-lifecycle seam calls its own `restoreWorktree` instead, and that returned early whenever the folder existed, so upstream's new `leftover` case failed. I carried upstream's leftover check into `workspace/restoreWorktree.ts`, which is fork-only. It runs only when the caller passes `clearLeftovers`, and the turn-start seam sets that only for server-managed paths, matching upstream's guard.
**Stop on a page's first load hung for 120s** (`preview/ServerBrowser.test.ts`, 4 cases). Upstream pingdotgg#29475 lets a viewer press Stop while a tab's first page load is still pending. The fork's `browser-timeout-recovery` seam in `findTab` made every tab wait for that first load before a viewer could attach, so the viewer never connected. The wait is only needed when a tab is being rebuilt after a stall, so `findTab` now checks for that first and waits only then; new tabs behave as upstream. The marker is kept and no `seams.tsv` row changed.
Rerun results:
- The two failing test files plus `restoreWorktree.test.ts`: 93/93 pass.
- `ServerBrowser.test.ts`: 106/106 pass, including the fork's recovery tests.
- Claude provider, Switchboard and project-lifecycle tests: 191/191 pass.
- `check_seams`, the apps/server typecheck, lint and format checks on the four changed files: all clean.
I did not rerun the whole apps/server suite.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
size:M30-99 changed lines (additions + deletions).vouch:trustedAuthor is trusted by repo permissions or the VOUCHED list.
1 participant
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The failing Agent context budget check was not caused by this change. The PR does not change any agent context text. After the previous merge, main lowered apps/server/src/provider/agentContextBudget.json by 3 bytes in 0568a63 (#30371), so the branch's older copy looked like growth. Merging origin/main again (merge commit, no conflicts) brings the budget file to main's values. The PR diff is unchanged: four server files covering worktree recovery in the shared restoreMissingWorktree helper (clears a folder only when it has no .git and holds only node_modules/.next directories), storage cleanup keeping such folders, and their tests.
Fixes #24390
Reproduction on main
In the app, create a worktree thread in a pnpm project and let setup install dependencies. Stop the turn, record its branch, then delete everything in that worktree except node_modules, including .git; optionally run git worktree prune in the project repository. Send another message to the same thread and ask the agent to report its current directory, branch, and tracked files. On main, recovery is skipped and the folder remains without a checkout; with this change, the leftover directory is removed and the thread's checkout is recreated before provider startup. Separately, trigger storage cleanup for an eligible archived thread in the same broken-folder state: main reports a missing-.git failure, whereas this change reports the folder as kept. These steps were read from the issue and PR, not executed.
Evidence
Evidence captured in Chromium at 1280×800, light theme, against fresh isolated servers with synthetic data and Replay. Create a worktree, install pnpm dependencies, leave only node_modules, remove .git, prune, and resume the thread. Separately archive another broken-folder thread and run storage cleanup. Filesystem observations are measured by the driver and displayed in chat, not generated by Replay. Absolute paths are redacted.
Scenario source · Capture redaction script
scenarios:prove exited 0: failed on base and passed on head.
Not shown:
Tests
Compared agentContextBudget.json on the branch and origin/main (5597/7327 vs 5594/7324) and found the main commit that lowered it. After the merge, vp run check:changed passed: format, lint, knip, typecheck (3 packages), tests (3 files). The budget check itself was not rerun locally; CI runs it on the new head.
Not in this change
Who did the work
Run by the t3code factory in T3 Code.