Skip to content

[AIR #1239] Surface unreaped migration backups in codev doctor#1242

Merged
waleedkadous merged 6 commits into
mainfrom
builder/air-1239
Jul 25, 2026
Merged

[AIR #1239] Surface unreaped migration backups in codev doctor#1242
waleedkadous merged 6 commits into
mainfrom
builder/air-1239

Conversation

@waleedkadous

Copy link
Copy Markdown
Contributor

Closes #1239.

Summary

codev doctor now 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 .bak automatically, or at minimum have codev doctor surface 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 backup over packages/** returns nothing. Those directories came from ad-hoc procedure during the #1118 state consolidation (a manual cp -R), not from a shipped code path. So "migrations that create a .bak should 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 / -shm sidecars) — db/consolidate.ts:335 renameWithSidecars deliberately renames rather than deletes the source state.db after merging it into global.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 -sk instead of a Node walk. A recursive statSync walk 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. When du is 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. isHomeCopy requires an agent-farm prefix and a bak/back marker. A bare ~/my-backups/ must never appear in a list whose recommendation column contains rm -rf, and the live ~/.agent-farm itself 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: backup contains back, not bak, so every agent-farm-db-backup-* directory — including both of the ones actually on the reporter's disk — was silently skipped. The test that asserts the real #1118 directory 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 doctor on a machine that has the real leftovers. It found all five, including the *.pre-merge-* files the codebase itself created — sizes cross-checked against du -sh:

Migration Backups (leftover copies of pre-migration state)

  ⚠ /Users/…/agent-farm-db-backup-20260702-113930 — 22 days old, 4.5 MB
  ⚠ /Users/…/agent-farm-db-backup-premulti-20260702-115840 — 22 days old, 4.2 MB
  ⚠ /Users/…/.agent-farm/state.db.pre-merge-2026-07-02T19-00-46-382Z — 22 days old, 52.0 KB
  ⚠ /Users/…/.agent-farm/state.db.pre-merge-2026-07-02T19-00-46-382Z-shm — 22 days old, 32.0 KB
  ⚠ /Users/…/.agent-farm/state.db.pre-merge-2026-07-02T19-00-46-382Z-wal — 22 days old, 0 B

  8.7 MB reclaimable across 5 backup(s).

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

File Change
packages/codev/src/lib/migration-backup-audit.ts New — scan, size, age, formatting (~165 LOC)
packages/codev/src/__tests__/migration-backup-audit.test.ts New — 14 tests
packages/codev/src/commands/doctor.ts New quiet-by-default Migration Backups section
codev/resources/commands/codev.md + skeleton mirror Document the new doctor section

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.
@waleedkadous
waleedkadous merged commit 25b2ef9 into main Jul 25, 2026
6 checks passed
waleedkadous added a commit that referenced this pull request Jul 25, 2026
…lision

hotfix(doctor): resolve formatBytes duplicate-identifier collision from #1242 × #1243
mohidmakhdoomi pushed a commit to mohidmakhdoomi/codev that referenced this pull request Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

agent-farm: migration backups (~/.agent-farm.bak-*) are never reaped

1 participant