| name | maintain-verification-skill |
| description | A repo's verification skill, feature map, or .claude/verify.sh gate has drifted from the app. Audits every feature from source and live, ships proven fixes. Use for 'audit the verify skill'. |
Maintain a verification skill
A feature map rots the moment the app changes, and a verify.sh gate rots more quietly: it keeps exiting 0 while checking less and less. This skill is the upkeep loop for a project's verification setup — the skill generated by create-verification-skill, or any project-local verification skill with a feature map, plus the .claude/verify.sh Stop-hook gate that sits alongside it.
The unit of rigor is the feature, not every sentence: cover every feature file from source and exercise every feature live, without terminalising every bullet.
Outcomes
Pick one, and say which:
- clean — every feature got source and live coverage, the gate was audited; nothing worth shipping. No branch, no PR.
- changed — one PR ships proven doc, harness, gate, or map corrections.
- blocked — coverage could not finish or a proven fix could not ship safely. Say exactly what blocked it.
Edit scope
Only edit the verification skill's own directory (its SKILL.md, features/, any harness scripts it owns) and .claude/verify.sh. Never edit product code during a run: a behavior the map describes that the app no longer does is either doc drift (fix the map) or a product regression (report it, don't paper over it in docs).
Pass
-
Locate the targets. Find the verification skill: the project-local skill whose body has launch/drive sections and a feature map (usually .claude/skills/verify-*/). Several candidates → ask which one; none → stop and point at create-verification-skill instead of inventing a target. Also locate .claude/verify.sh; its absence is itself a finding, since the Stop hook is a silent no-op without it.
-
Index hygiene. Read the feature map README and glob its sibling files. Fix missing, extra, duplicate, or dead entries. Lightweight; no generated inventory.
-
Gate audit. Before anything expensive, establish whether the gate still bites. Four questions, all cheap:
- Armed?
test -x .claude/verify.sh. Not executable → the hook ignores it entirely → the repo has had no gate since whenever that broke. Fix and note it.
- Green on a clean tree? Run it with no local changes. It must exit 0. A gate that is red on arrival trains the agent to route around it.
- Still checking anything? Read its output. Every line
skip means it is a no-op that exits 0 forever — the single worst state, because it looks installed. Each skip needs a reason that is still true (tool genuinely absent) rather than a script that was renamed or deleted six commits ago.
- Does it still fail? Introduce one deliberate breakage of a kind this repo actually produces (a type error in a real source file, not a scratch file), re-run, confirm non-zero exit and that the message alone locates the fault, then revert. An unfalsifiable gate is not a gate.
Also check drift the other way: new package.json scripts, new test suites, or a new language added to the repo since the gate was written, none of which it covers. Adding a check is in scope; it must pass on a clean tree and obey the same skip-don't-fail and no-server rules as generation.
-
Source wave. One read-only subagent per feature file. Send them as multiple Agent tool calls in a single message so they actually run concurrently — one call per message serialises the whole wave and is the most common way this step silently degrades into a slow sequential read. Use subagent_type: "explorer". Each explains "how does this user-facing feature work?" from source, flags likely doc drift with citations, and returns one concise live-verification recipe. Children never drive the app and never edit files. Return shape: feature summary / source entry points / likely drift or none / one recipe.
Note on independence: these readers are the same model family as you, so their agreement is weaker evidence than a genuinely independent second opinion would be. Their value here is fresh context and parallelism, not vendor diversity — which is why step 4's live pass is non-optional even when every reader returns clean.
-
Reconcile. Every feature file has a returned summary. Merge overlapping recipes into as few app states as practical. Spot-check cited drift; don't re-prove clean claims. Sweep recent churn for user-facing surfaces missing from the map — require a concrete source path before calling one missing.
-
Live pass. Required even when source looks clean. The coordinator owns all driving; follow the verification skill's own launch model — one long-lived instance driven serially for servers and UIs, or a fresh isolated session per drive for short-lived CLIs (the skill's Launch section decides, not this one). Exercise every feature at least once, and hold three invariants the whole pass, whatever the failure:
- Never drive an instance you haven't health-checked since it last did something surprising — doctor before first drive, doctor on each fresh session where sessions are the unit, doctor again after any failed drive; and where doctor can't see the failure (a wedged UI state on a healthy process), reset to a known state or relaunch rather than hoping.
- Evidence captured so far survives every cleanup, checked at its named location, not assumed.
- Nothing a drive started outlives that drive's usefulness — failed-iteration residue is cleaned whether the session is stuck, exited, or shared (for a shared instance, clean the residue, not the instance).
A doctor failure caused by skill drift is drift: fix it under edit scope and retry once — restart whatever the fix invalidated, nothing more — before calling the pass blocked. A feature that can't be reached is verified-unreachable only with the concrete prerequisite (auth, entitlement, OS, external state) and the route attempted; if the map omits that prerequisite, that's drift. Any harness or gate fix from triage gets re-driven live before it ships. Final teardown happens after the last drive of the run — including those re-proofs — so nothing outlives the run (evidence stays, per the skill).
-
Triage. Wrong or missing user-POV description → doc drift, fix it. Working behavior the harness can't drive → harness gap, fix it; a harness fix follows the same helpers rule as generation (scripts executable, invocation documented in the skill body). A check the gate should have caught but didn't → gate gap, fix .claude/verify.sh and re-prove it fails on a real breakage. App behavior that's actually broken → product gap; record it for the user, keep it out of this PR.
-
Ship or stop. For changed: one PR of proven corrections via gh, re-read every changed file first, and re-run .claude/verify.sh before opening it. For clean or blocked: no PR, report the outcome and the coverage honestly.
Keep concise run notes (features covered, gate audit result, unreachable prerequisites, confirmed drift, outcome) in a scratch location; don't commit them.