feat(lanes): add ccam lanes gc — orphan MCP reap + log capping (E, F3c)

Ports the two pieces of Shipyard's lane-gc.sh that match CCAM's actual
architecture: kill Playwright MCP processes reparented to pid 1 (owning
session died), cap hook logs over 10MB back to their last 2MB in place.
Drops auto-removing stale worktrees by age (conflicts with the
never-automatic-destroy rule), state archiving, and scratch-debris
sweep (different storage architecture / files CCAM doesn't generate) —
see docs/superpowers/specs/2026-08-05-lane-gc-design.md.
This commit is contained in:
2026-08-05 17:44:46 +07:00
parent e2d516f199
commit 5e620bd8ab
3 changed files with 239 additions and 0 deletions
+38
View File
@@ -1541,6 +1541,36 @@ function cmdSkillsInstall() {
console.log(`${c.green("✔")} installed ship-feature-lane skill -> ${dest}`);
}
/**
* `ccam lanes gc [--dry-run]` — reap orphaned Playwright MCP processes
* (owning session died) and cap oversized hook logs, across every lane on
* this machine. Machine-wide, not one lane's; pure local process/file
* action, no HTTP round-trip.
*/
function cmdLanesGc(args) {
const dryRun = args.includes("--dry-run");
const laneGc = require(path.join(REPO_ROOT, "server", "lib", "lane-gc.js"));
const reaped = laneGc.reapOrphanMcp({ dryRun });
if (reaped.length) {
console.log(
`${dryRun ? "would reap" : "reaped"} ${reaped.length} orphaned MCP process(es): ${reaped.join(", ")}`
);
} else {
console.log("no orphaned MCP processes found");
}
const capped = laneGc.capOversizedLogs({ dryRun });
if (capped.length) {
for (const { path: logPath, sizeBefore } of capped) {
const mb = (sizeBefore / (1024 * 1024)).toFixed(1);
console.log(`${dryRun ? "would cap" : "capped"} ${logPath} (${mb}MB -> 2MB)`);
}
} else {
console.log("no oversized logs found");
}
}
/**
* `ccam lanes profile init <repo>` — detect a Node.js project and scaffold
* `.ccam/profile/`. Pure filesystem action against the SOURCE repo; does not
@@ -2433,6 +2463,11 @@ const COMMAND_GROUPS = [
"<name> [<id>]",
"Check whether a named integration (tracker, dev_qc, ci_wait) is on for this lane — exit 0/1",
],
[
"lanes gc",
"[--dry-run]",
"Reap orphaned Playwright MCP processes + cap oversized hook logs, across every lane",
],
[
"skills install",
"",
@@ -3265,6 +3300,9 @@ async function runCommand(argv) {
if (rest[0] === "integration") {
return cmdLanesIntegration(rest.slice(1));
}
if (rest[0] === "gc") {
return cmdLanesGc(rest.slice(1));
}
return cmdLanes();
case "skills": {
if (rest[0] === "install") return cmdSkillsInstall();