Repository navigation
fix(server): storage cleanup keeps a retained worktree folder without .git - #31155
juliusmarminge wants to merge 4 commits into
Conversation
…e without .git (#31136) A thread's retained worktree path that still exists but has no .git (a git-removed worktree recreated with only yarn.lock and node_modules) should be kept as "Not a linked worktree". On main, cleanup stats the missing .git and reports a failed NotFound entry instead. AI-assisted; verified with the tests and tools listed above.
… .git A thread's worktree folder that exists but has no .git entry (for example one removed with `git worktree remove` and recreated by a package manager) made the unguarded stat fail with NotFound, so every cleanup run recorded a failure for it. Check for .git with fs.exists first, matching the orphan scan, so the folder is kept as "Not a linked worktree". fs.exists only maps NotFound to false, so other filesystem errors still fail the check. Fixes #31136 AI-assisted; verified with the tests and tools listed above.
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: Scenario and decoded snapshot size10 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.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — Cleanup now explicitly keeps retained worktree folders that lack .git instead of reporting an inspection failure. Existing deletion eligibility and filesystem safeguards remain unchanged. You can add or adjust custom eligibility rules. Learn more. |
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
# Conflicts: # apps/server/src/storageCleanup.ts
Dismissing prior approval to re-evaluate f745328
EvidenceBoth sides: real Linux dev server and web client, separate checkouts and fresh databases, light theme, 1280×800 CSS viewport. Synthetic data only; displayed local paths and environment names are privacy-redacted. Steps: create and settle a thread in a managed linked worktree through server RPC; remove the worktree with Git while retaining the thread; recreate its folder with
Both runs preserved identical Drivers: seed/RPC, interaction/redaction, folder preparation, filesystem verification, reproduction instructions. AI-assisted; verified with the tests and tools listed above. Not shown:
|


Problem
A thread can still point at a worktree folder that Git no longer has registered, but that still holds leftover files (for example
yarn.lockand an emptynode_modulesaftergit worktree remove). With any worktree cleanup rule on, every cleanup run recorded that folder as failed withNotFound: FileSystem.stat (<worktree>/.git)and loggedstorage cleanup failed for worktree. The expected outcome is that the folder is kept as "Not a linked worktree" and its files are left alone.Reproduced on main (7f6f47b) with a dev server on a fresh database:
git worktree removeon the worktree.yarn.lockand an emptynode_modules.The sweep then logs the
NotFoundfailure. Two other combinations fail the same way: inactive-days plus merged rules with the same folder, and deleted-thread plus unchanged rules with an empty folder.Change
StorageCleanup.cleanWorktreescalledfs.staton the worktree's.gitwithout first checking that it exists. It now checksfs.existsfirst, the same way the orphan-worktree scan in this file already does, and keeps the folder as "Not a linked worktree" when.gitis missing.fs.existsreturns false only forNotFound, so permission errors and other filesystem errors are still reported as failures.Scope and approval
Fixes #31136
Triaged via the automated issue flow.
Verification
New test
storageCleanup.test.ts› "keeps a thread's recreated worktree folder that has no .git". It uses a real linked worktree, removes it withgit worktree remove, then recreates the folder withyarn.lockand an emptynode_modules.outcome: "failed"andreason: "NotFound: FileSystem.stat (…/worktrees/feature/.git)".yarn.lockis still there.vp test run apps/server/src/storageCleanup.test.ts: 176/176 pass.vp run check:changed: format, lint, knip, graphql, and typecheck pass; tests 178/178.Runtime check with a dev server on a fresh database and a synthetic scratch repo, same steps as above, before and after:
Server-only change with no visible change in the UI, so there are no before/after screenshots. Not checked on macOS (the reporter's platform). The changed code is platform-independent filesystem handling.
AI-assisted; verified with the tests and tools listed above.