[AIR #1239] Surface unreaped migration backups in codev doctor#1242
Merged
Conversation
State migrations leave copies of the pre-migration state behind and nothing ever removes them — a disk audit found an 18 GB ~/.agent-farm.bak-* directory still present three weeks after the migration that created it. Adds lib/migration-backup-audit.ts, which finds both leftover families: whole-directory home copies (~/.agent-farm.bak-*, ~/agent-farm-db-backup-*) and the *.pre-merge-<timestamp> renames that db/consolidate.ts leaves behind after merging a state.db into global.db. Each is reported with age and size on disk (measured via du -sk, since a Node walk would stat tens of thousands of log files on exactly the multi-GB dirs this exists to find). codev doctor gains a quiet-by-default Migration Backups section: it prints only when a leftover exists, warns on anything past a 7-day verification window, and gives the exact rm -rf command. It never deletes — these are the user's own state copies, so the removal decision stays with the human.
mohidmakhdoomi
pushed a commit
to mohidmakhdoomi/codev
that referenced
this pull request
Jul 25, 2026
…mith#1242/cluesmith#1243 semantic merge collision
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Closes #1239.
Summary
codev doctornow surfaces leftover migration backups with age and size on disk, and gives the exact removal command. It never deletes anything.Review
What the investigation turned up (this changed the shape of the fix)
The issue proposes two arms — reap the
.bakautomatically, or at minimum havecodev doctorsurface it. I went with the second, and not just because it's cheaper: no code in this repo creates the~/.agent-farm.bak-*directory named in the issue.git grep -i backupoverpackages/**returns nothing. Those directories came from ad-hoc procedure during the #1118 state consolidation (a manualcp -R), not from a shipped code path. So "migrations that create a.bakshould record it and reap it" has no migration to attach to — there is nothing to instrument.What the codebase does create, and also never reaps, is
state.db.pre-merge-<timestamp>(plus its-wal/-shmsidecars) —db/consolidate.ts:335renameWithSidecarsdeliberately renames rather than deletes the sourcestate.dbafter merging it intoglobal.db. Those are small individually but accumulate silently and are the same class of problem. Both families are covered.Key decisions
Report, never delete. These are multi-gigabyte copies of the user's own state. Doctor prints path + age + size + the exact
rm -rf, and the removal decision stays with the human. An automatic reap would be deleting user data on a timer with no consent step, which is not something a diagnostic command should do.A 7-day verification window gates the warning, not a deletion. Backups at or past 7 days are
⚠and count toward doctor's warning total; younger ones are listed dimmed as informational, since a backup taken an hour ago is still doing its job. The dimmed line reads "within the 7-day verification window" rather than "kept until…", specifically so it doesn't imply an auto-delete that doesn't exist.du -skinstead of a Node walk. A recursivestatSyncwalk would stat tens of thousands of log files on exactly the multi-GB directories this check exists to find — the 18 GB case in the issue was large because of duplicated unrotated logs. Whenduis unavailable or times out, size reports as "size unknown" rather than a guessed number.Both a prefix and a backup marker are required to match.
isHomeCopyrequires anagent-farmprefix and abak/backmarker. A bare~/my-backups/must never appear in a list whose recommendation column containsrm -rf, and the live~/.agent-farmitself must never match (it has no separator after the prefix). There's a dedicated test for each.Quiet by default. The section prints only when a leftover exists, following the Framework Drift precedent — a clean machine sees no new output at all.
A test caught a real bug
The first pattern was
/bak/i, which reads as correct and is not:backupcontainsback, notbak, so everyagent-farm-db-backup-*directory — including both of the ones actually on the reporter's disk — was silently skipped. The test that asserts the real#1118directory names failed and pinned it. Pattern is now/bac?k/i.Verification
Unit: 14 new tests in
src/__tests__/migration-backup-audit.test.ts(both leftover families, the workspace-vs-home scan split, age→stale boundary at exactly 7 days, sort order, the negative cases above, byte formatting, unknown-size rendering).Full suite: 183 files passed / 3 skipped, 3655 tests passed / 48 skipped. Build green.
End-to-end: ran the built
codev doctoron a machine that has the real leftovers. It found all five, including the*.pre-merge-*files the codebase itself created — sizes cross-checked againstdu -sh:Follow-up worth considering
The 18 GB figure in the issue is mostly duplicated logs, so the sibling log-rotation issue is the bigger lever on disk. This change makes the leftover visible; rotation makes it small.
Files
packages/codev/src/lib/migration-backup-audit.tspackages/codev/src/__tests__/migration-backup-audit.test.tspackages/codev/src/commands/doctor.tscodev/resources/commands/codev.md+ skeleton mirror