{"type":"meta","slug":"buildbox-scratch-gc","base_branch":"origin/main","gate0_mode":"strict","preset":"claudex-workflow"}
{"type":"goal","text":"Reclaim remote build-box scratch on run completion, with a crash backstop, so debian1/debian2 never wedge at 0 bytes and silently hang every gated build."}
{"type":"methodology","text":"Spec first (docs/specs/2026-08-05-buildbox-scratch-gc-design.md), then claudex-workflow with gpt-5.6-terra/medium as coder and gpt-5.6-sol/low as reviewer, waves of strictly file-disjoint tasks, then land and verify live on both hosts."}
{"type":"intent","text":"A GC already exists and did not save the box: its floor pass requires a mirror to be older than 24h before it is eligible, so on the day that fills the disk nothing is evictable. Replace clock-based policy with ownership-based policy — a mirror is garbage exactly when its local root is gone."}
{"type":"direction","verbatim":"you must build garbage collection and verify it works, these runs depend on it"}
{"type":"direction","verbatim":"there should be a mechanism that will determine that a run is finished and will clear after each run. no point for waiting 1 day or 1 hour for anything"}
{"type":"direction","verbatim":"and need to have some cleanup reaper also in addition to that, in case some run \"crashed\" just before it's cleaned up"}
{"type":"direction","verbatim":"you write the spec for it, launch /claudex-workflow to implement. this is critical, so use gpt-5.6-terra/medium instead of luna/max"}
{"type":"anchor","path":"docs/specs/2026-08-05-buildbox-scratch-gc-design.md","what":"spec"}
{"type":"anchor","path":"docs/plans/2026-08-05-buildbox-scratch-gc.md","what":"plan"}
{"type":"session_memory","note":"Run happens in worktree /home/user/Projects/overdeck/.worktrees/buildbox-gc on branch feat/buildbox-scratch-gc cut from origin/main. The main overdeck checkout is dirty with unrelated work and must not be touched."}
{"type":"session_memory","note":"Acceptance for the GC unit suite is `cd modules/workstation/claude && node tests/remote-build-gc.test.mjs` — it runs green on origin/main today, so a red after the change is a real regression signal."}
{"type":"session_memory","note":"debian1 carries 9 pre-existing candidate-* orphan mirrors. Reclaiming them via `bin/remote-mirror sweep --force` is the live acceptance evidence."}
{"type":"task","id":"t1","wave":1,"seat":"coder","tier":"medium","desc":"Read docs/plans/2026-08-05-buildbox-scratch-gc.md Task 1 (GC module) for the full contract. Add ownerRecord/releaseMirror/sweepOrphanMirrors and rewrite gcScript around the live-job guard instead of the clock. Commit only: modules/workstation/claude/lib/remote-build-gc.mjs.","requires_decision":null,"acceptance":["cd modules/workstation/claude && node --input-type=module -e \"import('./lib/remote-build-gc.mjs').then(m=>{const need=['ownerRecord','releaseMirror','sweepOrphanMirrors','gcScript','GC_DEFAULTS'];const miss=need.filter(k=>!(k in m));if(miss.length)throw new Error('missing '+miss);if('gc_interval_hours' in m.GC_DEFAULTS||'gc_retention_days' in m.GC_DEFAULTS)throw new Error('removed keys still present');if(/86400\\s*\\)\\s*\\]\\s*\\|\\|\\s*continue/.test(m.gcScript('/tmp/x',{minFreeGb:1,repoRetentionDays:30,unownedGraceHours:24})))throw new Error('floor age gate still present');console.log('T1 OK')})\" — expect exit 0 printing T1 OK"],"verify":["cd modules/workstation/claude && node --input-type=module -e \"import('./lib/remote-build-gc.mjs').then(m=>{const need=['ownerRecord','releaseMirror','sweepOrphanMirrors','gcScript','GC_DEFAULTS'];const miss=need.filter(k=>!(k in m));if(miss.length)throw new Error('missing '+miss);if('gc_interval_hours' in m.GC_DEFAULTS||'gc_retention_days' in m.GC_DEFAULTS)throw new Error('removed keys still present');if(/86400\\s*\\)\\s*\\]\\s*\\|\\|\\s*continue/.test(m.gcScript('/tmp/x',{minFreeGb:1,repoRetentionDays:30,unownedGraceHours:24})))throw new Error('floor age gate still present');console.log('T1 OK')})\""]}
{"type":"task","id":"t2","wave":1,"seat":"coder","tier":"medium","desc":"Read docs/plans/2026-08-05-buildbox-scratch-gc.md Task 2 (owner record write) for the full contract. Write .rb-owner in syncPush, exclude it both directions, and sweep orphans before syncPush. Commit only: modules/workstation/claude/lib/remote-build.mjs.","requires_decision":null,"acceptance":["cd modules/workstation/claude && node tests/remote-build.test.mjs && node tests/remote-argv.test.mjs && node --input-type=module -e \"import('./lib/remote-build.mjs').then(async m=>{const src=await (await import('node:fs/promises')).readFile('lib/remote-build.mjs','utf8');if(!src.includes('.rb-owner'))throw new Error('no owner write');console.log('T2 OK')})\" — expect exit 0 printing T2 OK"],"verify":["cd modules/workstation/claude && node tests/remote-build.test.mjs && node tests/remote-argv.test.mjs && node --input-type=module -e \"import('./lib/remote-build.mjs').then(async m=>{const src=await (await import('node:fs/promises')).readFile('lib/remote-build.mjs','utf8');if(!src.includes('.rb-owner'))throw new Error('no owner write');console.log('T2 OK')})\""]}
{"type":"task","id":"t3","wave":1,"seat":"coder","tier":"medium","desc":"Read docs/plans/2026-08-05-buildbox-scratch-gc.md Task 3 (host-side backstop) for the full contract. Ship buildbox-gc plus item_scratch_gc. Commit only: modules/buildbox/bin/buildbox-gc, modules/buildbox/lib/buildbox-checks.sh.","requires_decision":null,"acceptance":["cd modules/buildbox && bash -n bin/buildbox-gc && bash -n lib/buildbox-checks.sh && grep -q 'item_scratch_gc' lib/buildbox-checks.sh && echo 'T3 OK' — expect exit 0 printing T3 OK"],"verify":["cd modules/buildbox && bash -n bin/buildbox-gc && bash -n lib/buildbox-checks.sh && grep -q 'item_scratch_gc' lib/buildbox-checks.sh && echo 'T3 OK'"]}
{"type":"task","id":"t4","wave":2,"seat":"coder","tier":"medium","desc":"Read docs/plans/2026-08-05-buildbox-scratch-gc.md Task 4 (remote-mirror CLI) for the full contract. release/sweep --force/status subcommands. Commit only: modules/workstation/claude/bin/remote-mirror.","requires_decision":null,"acceptance":["cd modules/workstation/claude && test -x bin/remote-mirror && bin/remote-mirror --help >/dev/null && echo 'T4 OK' — expect exit 0 printing T4 OK"],"verify":["cd modules/workstation/claude && test -x bin/remote-mirror && bin/remote-mirror --help >/dev/null && echo 'T4 OK'"]}
{"type":"task","id":"t5","wave":2,"seat":"coder","tier":"medium","desc":"Read docs/plans/2026-08-05-buildbox-scratch-gc.md Task 5 (unit coverage) for the full contract. All 14 cases plus the disposition of the three existing cases. Commit only: modules/workstation/claude/tests/remote-build-gc.test.mjs.","requires_decision":null,"acceptance":["cd modules/workstation/claude && node tests/remote-build-gc.test.mjs — expect exit 0"],"verify":["cd modules/workstation/claude && node tests/remote-build-gc.test.mjs"]}
{"type":"task","id":"t6","wave":2,"seat":"coder","tier":"medium","desc":"Read docs/plans/2026-08-05-buildbox-scratch-gc.md Task 6 (release at teardown) for the full contract. Non-fatal release call at every worktree removal path. Commit only: modules/workstation/claude/workflows/lib/finish-branch.sh, modules/workstation/claude/bin/wt-reaper.sh.","requires_decision":null,"acceptance":["cd modules/workstation/claude && bash -n workflows/lib/finish-branch.sh && bash -n bin/wt-reaper.sh && grep -q 'remote-mirror' workflows/lib/finish-branch.sh && grep -q 'remote-mirror' bin/wt-reaper.sh && echo 'T6 OK' — expect exit 0 printing T6 OK"],"verify":["cd modules/workstation/claude && bash -n workflows/lib/finish-branch.sh && bash -n bin/wt-reaper.sh && grep -q 'remote-mirror' workflows/lib/finish-branch.sh && grep -q 'remote-mirror' bin/wt-reaper.sh && echo 'T6 OK'"]}
{"type":"task","id":"t7","wave":3,"seat":"coder","tier":"medium","desc":"Read docs/plans/2026-08-05-buildbox-scratch-gc.md Task 7 (CLI integration test) for the full contract. Loopback ssh against a fabricated remote_root. Commit only: modules/workstation/claude/tests/remote-mirror-cli.test.sh.","requires_decision":null,"acceptance":["cd modules/workstation/claude && bash tests/remote-mirror-cli.test.sh — expect exit 0"],"verify":["cd modules/workstation/claude && bash tests/remote-mirror-cli.test.sh"]}
