From e2d516f199a7af5ec179959589d6d069e69b3434 Mon Sep 17 00:00:00 2001 From: nntrivi2001 Date: Wed, 5 Aug 2026 17:38:04 +0700 Subject: [PATCH] =?UTF-8?q?docs(lanes):=20design=20F3c=20=E2=80=94=20ccam?= =?UTF-8?q?=20lanes=20gc=20(E)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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). --- .../specs/2026-08-05-lane-gc-design.md | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 docs/superpowers/specs/2026-08-05-lane-gc-design.md diff --git a/docs/superpowers/specs/2026-08-05-lane-gc-design.md b/docs/superpowers/specs/2026-08-05-lane-gc-design.md new file mode 100644 index 0000000..bf52b87 --- /dev/null +++ b/docs/superpowers/specs/2026-08-05-lane-gc-design.md @@ -0,0 +1,30 @@ +# 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:** +1. **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). +2. **Cap oversized hook logs.** `LANES_ROOT/.state/lane/logs/*.log` (written by `runHook`) 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 -rf` a lane... destructive lane operations go through `worktree.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|purge` already 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_features` table, 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.sh` writing `scratch-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 ".*\.playwright-mcp"` to find candidate pids (scoped to CCAM's own `LANES_ROOT`, same safety scoping Shipyard's own pattern used — an adopted lane's `cwd` living outside `LANES_ROOT` is a known gap, same one Shipyard's own numbered-lane-dir pattern had). For each match, `ps -o ppid= -p `; `ppid === 1` → orphaned, kill its process tree (`pgrep -P` recursively, then `SIGKILL` each, leaves not children first — same shape as Shipyard's `kill_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-run` prints 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).