---
name: housekeep
description: "Reclaim the build's operational debris in one guarded pass — orphaned isolated-build and headless-browser processes (never kill-by-name; targeted by the kit's own isolation markers + age), persistent build-server nodes, stale obj/_v* output dirs, aged scratch screenshots, unreferenced APPROVAL_INBOX captures past retention, and pruned/merged worktrees. Dry-run by default; presents the report and applies only on approval. Skips process/dir reclamation entirely while a run is active. Usage: /housekeep [scope] [--apply]"
argument-hint: "[all|processes|screenshots|builddirs|worktrees] [--apply] (omit --apply for dry run)"
---
> **Specialization:** Read `CLAUDE.md` first and bind every `<…>` placeholder and every "per `CLAUDE.md`" reference from it — the housekeeping block (§0/§2: retention days, scratch screenshot dirs, protected dirs — visual-regression baselines + reference screenshots, process-age threshold, CDP/browser markers), the approval-inbox path, and the run-state convention. This file hard-codes no project value. If a needed value is missing from `CLAUDE.md`, use the kit defaults baked into `housekeep.ps1` and SAY SO in the report. See `SPECIALIZE.md`.

You are the **orchestrator** for a housekeeping pass and the **single writer** (Law 3) of its effects. The mechanical work is `\.claude/hooks/housekeep.ps1` — you bind its parameters from `CLAUDE.md`, run it, present the evidence, and record the outcome. You write no production code.

## Hard boundaries (what housekeeping may NEVER do)
- **Never kill by process name.** Only processes carrying the kit's isolation marker (`obj/_v` in the command line) or the agent headless-browser signature (`--headless` + `--remote-debugging-port`), **and** older than the bound age threshold. A bare `dotnet`/browser process is someone else's.
- **Never touch protected dirs:** visual-regression baselines, reference screenshots, the prototype tree, anything `CLAUDE.md` lists under protected paths. Deleting a baseline silently disables the Law-1 fidelity gate — that is a process violation, not cleanup.
- **Never delete an APPROVAL_INBOX capture still referenced by an inbox note** (a pending sign-off is evidence, not debris).
- **Never run process/builddir reclamation during an active run.** If a `RUN_STATE*.json` is open or extra worktrees exist, those scopes are skipped — report it and offer to re-run after the wave closes.
- **Worktree removal is never automatic.** The script prunes registrations (`git worktree prune`) and *reports* merged/stale worktrees; you remove one only with explicit human approval in this session, and only after confirming its branch is merged (`git branch --merged main`).

## The pass (in order)
1. **Bind + guard.** Read `CLAUDE.md`'s housekeeping block; resolve scope from `$ARGUMENTS` (default `all`). Check for open run state / extra worktrees and say up front which scopes the guard will skip.
2. **Dry run first, always:**
   ```
   powershell -NoProfile -File .claude/hooks/housekeep.ps1 -Scope <scope> `
     -ScreenshotMaxAgeDays <n> -InboxRetentionDays <n> -BuildDirMaxAgeDays <n> `
     -ProcessMaxAgeHours <n> -ScratchDirs <bound> -ProtectDirs <bound>
   ```
3. **Present the report** grouped by area, with counts and reclaimed-size estimates for dirs. Flag anything surprising (e.g. an isolated-build process only 3 hours old — a crashed sweep? cross-file to the approval inbox rather than just killing it).
4. **■ Approval** — on `--apply` in `$ARGUMENTS` or explicit human yes, re-run with `-Apply`. Partial approval is fine: re-run per scope.
5. **Single-writer record:** append one `PROGRESS.md` line (`housekeep: <scope> — <n> processes reaped, <n> dirs, <n> screenshots, <size>`); if the run surfaced a recurring debris source (e.g. an agent that never kills its browser), file it as a LESSONS row (*Mistake / Trigger / Rule*) — a stable one graduates into the agent's hard rules (Law 12).

## Prevention beats reclamation (recommend these when debris recurs)
- **Sweep-end shutdown:** the reconstruct/build orchestrators should run `dotnet build-server shutdown` as the last line of single-writer integration for every batch — persistent MSBuild/Roslyn/Razor nodes are the primary RAM pile, and this releases them gracefully without losing node-reuse speed *during* the batch.
- **Agent hygiene rule (graduate into CLAUDE.md):** *every agent kills every process it starts (app host, headless browser) before reporting Done, and lists spawned PIDs in its report's Evidence line* — housekeeping is the safety net, not the plan.
- If node piling persists on constrained machines, `MSBUILDDISABLENODEREUSE=1` in the sweep environment trades some build speed for zero persistent nodes; prefer sweep-end shutdown first.

## Report shape you return
```
Housekeep: <scope> | mode: dry-run|applied | guard: clear|active-run (skipped: …)
Processes: build-server shutdown ✓ · reaped <n> (PIDs + markers) · flagged <n>
Screenshots: scratch <n> deleted · inbox <n> deleted / <n> kept (referenced)
Build dirs: <n> obj/_v* removed (<size>)
Worktrees: pruned ✓ · <n> reported for removal (awaiting approval)
Recorded: PROGRESS ✓ · LESSONS <n>
```
