The key words MUST, MUST NOT, SHOULD, SHOULD NOT and MAY in this skill are to be interpreted as described in BCP 14 (RFC 2119, RFC 8174) when, and only when, they appear in all capitals.
Stand up the verify→repair loop in a repository that doesn't have one: a
single discoverable command per rail — format, build, test — and a CI workflow
that runs the same commands. This is the action-taking sibling of
agent-ready-rails: rails audits and reports that the loop is missing (its
load-bearing R1/R2 finding); this skill installs it. The evidence behind why
this rail matters most is in that skill's grounding — a verify loop the agent
cannot skip is the single highest-leverage change for agent success.
Locating this skill's helpers (do this first). The steps below run bundled scripts. You execute from the target repo, not from this skill's directory, so a path written relative to this skill will not resolve. Resolve the base directory once and use it everywhere — including in any subagent prompt, which MUST receive the literal absolute path:
SKILL_DIR="<this skill's base directory>" # your harness provides it when the skill loads
# If you don't have it, discover it:
SKILL_DIR=$(find ~/.claude ~/.config ~/.agents -type d -name 'verifier-installer' 2>/dev/null | head -1)
test -d "$SKILL_DIR/assets" || test -d "$SKILL_DIR/scripts" # verify before proceeding
When to use
Reach for this when a repo needs the loop built: no test command, no CI, an
undocumented build, or an agent-ready-rails scorecard with R1/R2 at 0–1. Do
not use it to referee style — installing a formatter check is in scope
when the repo already adopts a formatter, choosing tabs-vs-spaces is not
(prefer whatever the repo already leans toward). When no formatter is
adopted, this skill does not invent a style opinion: the format rail becomes
an honest placeholder that stays red until the owner picks one. Do not use
it on a repo whose verify+CI loop is already green;
agent-ready-rails will say so, and re-installing over a working loop only
adds noise. When only part of the loop is missing (say, tests exist but CI
doesn't), install just the missing rails.
What gets installed
Python interpreter. Most commands in this skill and its references are written with python3.
Find the interpreter once, before the first of them. If $SKILL_PYTHON is set, use it. Otherwise,
on macOS, if command -v python3 prints /usr/bin/python3 and xcode-select -p fails, that
python3 is the install stub: skip it without running it. Use the first of python3, python and
py -3 that is not skipped and for which
<interpreter> -c 'import sys; sys.exit(sys.version_info < (3, 10))' exits 0. Write the interpreter
you found in place of python3 in every command, and in any Bash(...) permission rule you
suggest. Commands that start with uv run or {python} keep their own form. In a session resumed
under a Bash(...) allowlist, skip this lookup and use the interpreter that the allowlist names. If
none passes, follow this skill's own fallback for running without Python where it gives one;
otherwise stop and tell the user that this skill needs Python 3.10 or newer.
Per the confirmed plan, some subset of:
| Rail | Typical form | Exercised by |
|---|---|---|
| format | formatter/lint check command or script (only when the repo already adopts one; otherwise an honest placeholder) | e.g. npm run format, ruff format --check ., test -z "$(gofmt -l .)" |
| build | compile/typecheck command | e.g. npm run build, go build ./... |
| test | test-runner command (+ a smoke test if none exists) | e.g. python3 -m pytest, npm test |
| ci | one workflow running the rails above | .github/workflows/verify.yml on push/PR |
Exact per-stack files, commands, and snippets live in
references/install-playbooks.md — load the section for the detected stack
rather than inventing config from memory.
Workflow
- Detect the stack. Run
python3 "$SKILL_DIR/assets/detect_stack.py" <repo>(offline, read-only). It emits a deterministic JSON plan: detectedstacks,existing_verifiers(format/build/test/ci with the command or workflow path found),missingrails, concreteproposals(rail/command/file_to_create), pluslockfilesand anyerrors(e.g. malformedpackage.json— reported, never fatal). Read the plan; spot-check anything surprising against the repo itself. - Confirm the plan with the user. Show which rails exist, which are
missing, and what you propose to create. Ask which verifiers they want and
which CI provider — GitHub Actions is the default; if they name another,
translate the workflow per the CI section of
references/install-playbooks.md. If the plan lists errors (broken manifest files), surface them here — fixing a corruptpackage.jsonis a decision the user makes, not you. You MUST NOT write anything before this confirmation, because installing rails changes the user's repo and CI, unlesspython3 "$SKILL_DIR/assets/contract_check.py" check-grant --root <repo> --action local_reversibleexits 0 (an autonomy grant the user approved covers it); then you MAY proceed, and MUST name the grant id and action class in the report. Any other exit (3 ASK/NONE, 2 INVALID, 1 usage error) means ask as usual. Under a grant you MUST install only the plan's proposals for the missing rails, with GitHub Actions as the CI provider, and MUST report manifest errors (a corruptpackage.json, say) for the user instead of fixing them. The grant lifts this confirmation and nothing more: the playbook's prove-the-loop rule to stop and ask before fixing pre-existing debt still applies. The workflow you write under a grant stays local; pushing it asks, because CI runs with the repository's secrets (check-grantanswers ASKci-configfor that push). - Install per the playbook. For each approved missing rail, follow the
matching stack section in
references/install-playbooks.md: write the verifier config/scripts (Makefile targets, package scripts, smoke test) and the CI workflow. Extend existing files rather than replacing them, and you MUST NOT add a second workflow when one already exists, because two workflows drift apart and CI stops being one ground truth; you MUST extend the existing one. Keep the diff small and reviewable. - Prove the loop (verify and repair). For each installed rail, run its
command and record the result. Then follow the prove-the-loop protocol in
references/install-playbooks.md: introduce one trivial, reversible break, watch the verifier go red, revert, and watch it return green. If a rail fails for a pre-existing reason, or a toolchain isn't available to run it, repair what the install broke, report what it didn't, and mark that rail installed-but-unproven rather than claiming it works. - Hand back the install summary. Deliver the summary below: each rail installed, the exact command that exercises it, the red→green proof (or the honest "unproven" tag), and the recommended follow-ups you deliberately did not do yourself (branch protection, replacing placeholder targets).
Deliverable — the install summary
Step 5 hands back this report:
## Verifier loop installed: <repo>
Gate: confirmed by user | grant <id> (<class>)
| Rail | Command | File(s) | Proven |
|------|---------|---------|--------|
| format | <cmd> | <path> | red→green demonstrated / unproven (<why>) |
| build | ... | ... | ... |
| test | ... | ... | ... |
| ci | push/PR triggers <workflow path> | ... | ... |
Skipped (already present): <rails the plan found existing, with their commands>
Follow-ups for the owner: <branch protection, wire a real formatter — `make verify`
and CI stay red on the format step until then, …>
detect_stack.py's plan marks this mechanically: every proposal carries a placeholder
field, true for a fallback (the make format/make build/make test skeleton, or a
python format rail with no adopted formatter) and false for a real, stack-specific
command. Read that field rather than guessing. When a rail's proposal was placeholder: true — most commonly format on a python repo with no adopted formatter — it was never
watched go red and back to green; report it as unproven (no formatter adopted), not
red→green demonstrated, and say plainly that make verify and CI stay red on that step
until the owner wires one. That is not the same as a rail you proved catches a violation,
and reporting it as demonstrated is a false claim the next agent will trust — put wiring
it in "Follow-ups for the owner" instead.
The loop now runs, but its test rail proves only the smoke test this skill wrote — it does not
mean the codebase is netted. Point the owner at test-safety-net to fill it with real,
change-detecting tests.
Output style. Write reports and explanations for the user in about 80% ASD-STE100 Simplified Technical English. Use short sentences, common words, active voice and one action per step.
Guardrails
- Read-only until step 2's confirmation (or a covering grant) — detection never writes;
installs MUST happen only after the user approves the plan, or after
check-grantexits 0 forlocal_reversibleas step 2 describes. - One ground truth. Local
verifyand CI MUST run the same commands; have CI call theverifyentrypoint rather than restate its commands, so the two cannot drift. - Prove, don't presume. A rail counts as installed when it was watched failing and recovering, not when its file exists. You MUST leave the tree clean after the demonstration.
- Stay off the style battlefield. Wire checks for whatever formatter/tooling the repo already implies; you MAY propose, but SHOULD NOT impose, new tools.
Contract
This skill follows skill-contract v1. It consumes autonomy grants, which only lift step 2's confirmation, and it provides no kind of its own: the install summary is prose.
{"provides": [], "consumes": ["https://github.com/dhanesh/agent-skills/skill-contract/autonomy-grant/v1"]}