Scopes lane-gc.sh down to the two pieces that match CCAM's actual architecture (orphan Playwright MCP reap, oversized-log capping). Drops auto-removing stale worktrees by age — that's exactly the kind of automatic destructive action this repo's own CLAUDE.md forbids (destroy always goes through the three-check guard, never automatic). State archiving and scratch-debris sweep don't apply either (different storage architecture; CCAM doesn't generate those files).
3.3 KiB
F3c — ccam lanes gc: orphan MCP reap + log capping
Status: approved 2026-08-05. Roadmap it belongs to: E (found auditing E1-F3b for Shipyard parity).
Problem
Shipyard's lane-gc.sh does 5 things. Two match CCAM's actual architecture; three don't (see Decisions). No CCAM equivalent exists for either of the two that do.
Scope
In scope:
- Reap orphaned Playwright MCP processes. A
.playwright-mcp-scoped process whose parent Claude Code session died gets reparented to pid 1 (init). Live sessions' MCP processes keep their real parent and are left alone. Kill the orphan's whole process tree (a browser process it spawned would otherwise also leak). - Cap oversized hook logs.
LANES_ROOT/.state/lane<slot>/logs/*.log(written byrunHook) grow unbounded across many boots/hooks; cap anything over 10MB to its last 2MB, in place (write-then-replace, not a truncate-while-open, so a concurrent writer's fd stays valid).
Explicitly out of scope (architecture mismatch, not an oversight):
- Auto-removing stale worktrees by age. This is the piece that actually conflicts with a hard CCAM rule: "Never
rm -rfa lane... destructive lane operations go throughworktree.js/lanes.js, never a raw filesystem delete." An age-based automatic worktree removal is exactly the kind of automatic destructive action this repo's own CLAUDE.md forbids.ccam lanes reset|remove|purgealready exist for a human to call explicitly. - Feature-state archiving. Shipyard's version moves flat JSON state files to an archive dir. CCAM's lane/feature state lives in the SQLite DB (
lane_featurestable, from subsystem B) — there's no flat-file equivalent to archive. - Scratch-debris sweep (
scratch-lane*.log,manual-*.png,state.bak.*). These are artifacts of Shipyard's own scripts (lane-add.shwritingscratch-lane*.log, manual QA screenshots named that way,state.sh's own backup rotation). CCAM doesn't generate any of these — nothing to sweep.
Design
ccam lanes gc [--dry-run] — no lane argument; this scans the whole machine's CCAM footprint, not one lane. Pure local operation (process listing + file I/O), no HTTP route — same shape as ccam skills install.
- Orphan reap:
pgrep -f "<LANES_ROOT>.*\.playwright-mcp"to find candidate pids (scoped to CCAM's ownLANES_ROOT, same safety scoping Shipyard's own pattern used — an adopted lane'scwdliving outsideLANES_ROOTis a known gap, same one Shipyard's own numbered-lane-dir pattern had). For each match,ps -o ppid= -p <pid>;ppid === 1→ orphaned, kill its process tree (pgrep -Precursively, thenSIGKILLeach, leaves not children first — same shape as Shipyard'skill_tree). - Log cap: walk
LANES_ROOT/.state/lane*/logs/*.log; for any file over 10MB, read its last 2MB and rewrite the file in place. --dry-runprints what would happen without doing it (same flag Shipyard's version has).
Verify
Manual smoke check (no automated test for OS process listing/killing — this is inherently environment-dependent, same reasoning routes with no HTTP harness already use): run with --dry-run against the current machine's real state and confirm the output looks sane (no crash, no false-positive kill of a live process — verify a currently-live lane's MCP process, if any, does NOT appear in the orphan list).