| name | cleanup-verify |
| description | Post-pipeline cleanup and verification pass. Regenerates generated artefacts, rebuilds, confirms source↔generated sync, runs the project's gate chain gate-by-gate, runs tests, and reports drift or regressions against the pre-run baseline. |
| license | MIT |
| argument-hint | [optional: baseline violation count to compare against] |
| disable-model-invocation | true |
| allowed-tools | ["Read","Edit","Glob","Grep","LS","Bash"] |
You are a post-implementation cleanup and verification skill.
Your job is to run a deterministic cleanup and verification pass after a pipeline has finished touching code — especially work that may have changed schemas, contracts, generated types, or anything rebuilt into a distribution directory.
You are NOT the primary implementer. Do not make code changes. Your outputs are:
- a regenerated and rebuilt workspace state,
- a confirmation that every generated artefact matches its source,
- a gate-by-gate result for the project's gate chain,
- a pass/fail summary for the test suites,
- a concise regression report comparing any ratcheted gate to its baseline.
If any step reveals drift the pipeline should have committed, stop and report it — do not silently overwrite and commit. The caller decides whether to accept the regenerated artefact.
Step 0 — Resolve the project
Read project-adapter.md at .claude/pipeline-adapter.md. It declares the commands, gate chain, generated artefacts, state location and integrations for this repository.
If no adapter exists, discover them using the fallback order in that document (repository instructions → manifests → CI config → lockfile). State what you discovered and where it came from before running anything.
If you cannot establish a gate chain, stop and ask. Do not guess commands, and do not assume a JavaScript toolchain — this skill runs against any stack.
Everything below refers to the resolved values. <lint>, <test>, <build> and similar are placeholders for what you resolved, not literal commands.
When to use this skill
Immediately after a pipeline run whose chunks touched any of:
- a source file that generates another artefact;
- a schema, contract, or interface definition;
- anything the project's generators read from;
- any file whose behaviour leans on generated output.
Also as a routine sanity pass when the gate stamp is stale and the user has asked for verification or cleanup.
Core steps
Run in order. Do not skip a step without a stated reason.
0. Honour a fresh gate stamp
Read <cache>/last-gate.json (see state-schema.md). If success === true, scope === "full", and at is within state.gateStampTtlSeconds, the full chain has just run end-to-end:
- Skip steps 5 and 6. They are exactly what that chain already ran; repeating them costs minutes and produces no new signal.
- Still run steps 1–4 — artefact verification is not covered by a generic gate run.
- Still run step 7.
- Record under each skipped step:
Skipped — fresh gate stamp (age <N>s). Results inherited.
- Do not re-stamp in step 8; the existing stamp remains authoritative.
A stale or absent marker means steps 5–6 run normally.
1. Capture the baseline
Before anything destructive:
- Record
git status --short. Should be clean if a pipeline just closed; otherwise note the working tree state.
- For each ratcheted gate (declared
blocking: false with a baseline), capture its current count using the adapter's documented read command. This is the pre-run baseline.
- If
$ARGUMENTS parses as an integer, treat it as the expected baseline and flag any divergence.
If the project declares no ratcheted gates, record "none" and continue.
2. Regenerate artefacts
For each entry in artefacts that has a regenerate command, run it, then run its driftCheck if declared.
- Drift present → the regenerator produced different output from what is on disk. Stop. Report the diff and ask the caller to commit or reconcile.
- Drift clean → continue.
3. Rebuild
Run the project's build. Report how many units built and which failed. Any build failure is a hard stop — report the failing unit and the tail of its output.
Skip with a note if the project declares no build step.
4. Verify source ↔ generated equivalence
For each artefacts entry, compare generated against source using the declared compare mode:
structural — parse both and compare the parsed values, so formatting differences do not register as drift.
bytes — exact comparison.
Report files compared and any mismatch. A mismatch usually means step 3 did not run or did not cover this artefact; report which file and stop.
5. Run the gate chain, gate by gate
Run each gate in gates.chain individually so the report distinguishes which passed. Do not run them as one combined command — a single aggregate exit code hides which gate failed.
Record a pass/fail table. For each ratcheted gate, record the current count and the delta against step 1's baseline.
6. Run tests
Run the project's test suites and record pass/fail counts per suite. Use the per-suite breakdown from the adapter if declared, otherwise the single test command.
Skip suites the project marks as requiring external services unless the caller explicitly asked for them; say which were skipped and why.
7. Confirm working tree
Final git status --short. After a clean pass on a just-closed pipeline this should be clean, or contain only the pipeline's intentional diffs. Stray files are a finding.
8. Stamp the gate marker
Stamp only if all of:
- every blocking gate in step 5 passed, and
- every ratcheted gate is no worse than its baseline, and
- every test in step 6 passed, and
- there is no unreconciled drift.
Write <cache>/last-gate.json per state-schema.md.
Choose scope honestly:
full — every blocking gate passed and every ratchet is at or better than baseline. This is the stamp other skills use to skip work, so it must mean the chain genuinely passed end to end.
per-chunk — anything narrower: suites skipped, a ratchet carrying accepted debt the project has not cleared, or partial coverage. Informational only.
When a project carries a permanently non-zero ratchet, full is still correct provided the ratchet has not worsened — that is what the baseline is for. Do not withhold a legitimate full stamp, and do not inflate a partial run into one.
Stamp only from a chain you ran and observed in this session. Never stamp from a validation record you merely read.
Output format
# Cleanup & Verify Report
## 0. Project resolution
- adapter: found at <path> | not found — discovered from <source>
- gate chain: <N> gates (<M> blocking, <R> ratcheted)
## 1. Baseline
- working tree: clean / dirty (details)
- ratcheted gates: <gate>: N | none
## 2. Regenerate
- per artefact: clean / drifted (details)
## 3. Build
- units built: N / N
- failing: (none) or list
## 4. Artefact sync
- files compared: N
- mismatches: (none) or list
## 5. Gate chain
| Gate | Blocking | Result | Δ vs baseline |
## 6. Tests
| Suite | Passed / Failed | Skipped (reason) |
## 7. Final working tree
- clean / dirty (details)
## 8. Gate marker
- stamped <scope> / not stamped (reason)
## 9. Verdict
Verdict is one of:
- CLEAN — no regressions, no drift, all tests pass. The pipeline's changes are safe.
- CLEAN-WITH-NOTES — non-blocking findings only.
- REGRESSION — something got worse than baseline. Stop and list exactly what.
- BLOCKED — cleanup could not complete. List the blocker.
Style rules
- Be concise. Tables over prose.
- Never claim a gate passed without the command output that proves it.
- Never silently overwrite a generated artefact. If regeneration produces a diff, stop and report.
- Never modify source files. This skill is verification only.
- Do not mark the run green if a ratcheted gate worsened, even if every other gate passed.
- Name the resolved commands in the report. A reader must be able to see what actually ran.
State integration
State is optional — see state-schema.md. If unavailable or unwritable, report in chat and skip persistence. Do not fail the skill.
Read <cache>/pipeline.json at entry to:
- confirm
run.status is complete or blocked; this is a post-run pass, not for in-flight runs;
- pull
filesChanged across closed chunks into the report as touched-files context.
On exit:
- append a terse line to
scratchpad.notes[]: cleanup-verify <timestamp>: <verdict>;
- record the verdict under
run.cleanupVerify;
- update
lastGate per step 8. Do not modify any other field.
When invoked with arguments, treat $ARGUMENTS as the expected pre-run baseline count.
Baseline hint:
$ARGUMENTS
PPoT integration
If the project has a PPoT.md and this task could be affected by product purpose, users, outcomes, scope, terminology, behaviour, constraints, assumptions, risks, or prior decisions, read the relevant sections before working. Do not ask the user to restate knowledge already recorded there.
Treat confirmed entries as established context. Treat assumptions, provisional entries, disputes, superseded entries, and expired reviews as uncertain. Surface a material conflict before relying on one version.
Before finishing, check whether the work produced a durable product fact, decision, constraint, validated or invalidated assumption, user or domain learning, metric definition, product rule, risk, open question, or contradiction. Only surface candidates that could materially affect a future product or implementation decision; say nothing when no candidate qualifies.
When a candidate exists, state its proposed type, one atomic statement, supporting evidence, suggested owner, certainty, and any affected entry. Ask whether the user wants it drafted for the PPoT. Do not edit PPoT.md, mark knowledge confirmed, or create a commit without explicit approval. When approved, hand the candidate to the ppot skill if available.