Plan check (a plan → a verdict)
Review a plan before it is built, the way a code review works after.
A plan is the only artefact in the flow with no independent review. Code gets a per-ticket pass and a whole-feature sweep; the plan every one of them is measured against was written once, by one model, and read once by a human seeing it for the first time. That is backwards. A wrong plan is the cheapest thing here to fix and the most expensive to miss, because everything after it is built correctly on top of the mistake.
A plan is a prediction, and nothing compiles it. Its claims about the codebase are true when written and quietly rot. So this skill spends its effort on the one thing a reader cannot do quickly by eye: checking the plan's assertions against the repository as it is now.
This repo describes itself in .agents/, at the repository root. Read the files that bind your step,
and treat them as authority over anything you would otherwise assume.
| File | Answers |
|---|---|
.agents/lifecycle.md |
which phases run, which review lenses are in use, how many rounds each loop gets, how wide a wave may be |
.agents/gates.md |
the commands that must pass, in order, and what "green" means here |
.agents/tracker.md |
where specs and tickets live, and what may be written to the board |
.agents/forge.md |
the git host, and how a branch becomes a reviewed change |
.agents/docs.md |
where architecture truth lives, the glossary, and what "docs are part of done" costs |
.agents/naming.md |
branch, commit, directory and test-name grammar |
.agents/working-agreement.md |
working hours, what may run unattended, how to report, when to stop and ask |
Three rules:
- A missing file is a real answer: that thing is not configured here. Say so in one line and take
the safest reading — do not invent the repo's conventions, and do not fall back on another project's.
If the whole directory is absent, stop and tell the user to run
/onboardinstead of guessing. .agents/beats your own judgement, and loses to the user. It was written deliberately, so a rule you disagree with is reported once, not routed around.- Read only what your step needs. Every line costs on every turn of a long run.
When NOT to use
- To review code that exists → the review lenses in
build. - On a change too small to have had a plan.
- To settle an open design question the plan rests on →
grillfirst. A plan review cannot tell you what the user wanted.
Step 1 — Read both documents
The plan and the spec it argues from. The spec is the binding authority; the plan is its argument. Where they disagree, the spec wins and the disagreement is a finding.
Step 2 — Send the lenses
Spawn change-reviewer once per axis below, all in one message,
each on sonnet unless the plan touches auth, tenancy, migrations, permissions or a wire contract —
then the coverage and risk axes go to opus.
Hand each one the plan path and the spec path. Never paste either into the prompt.
Never tell a reviewer what not to flag. If the prompt you are writing contains "do not flag", "don't treat X as a defect", "at most Minor", or "the spec chose this" — stop. You are pre-judging, and the reason is almost always to spare yourself a review round.
Let the reviewer raise it. Adjudicate it afterwards, in the open, and record the ruling.
Two rules that follow:
- Do not add open-ended directives — "check all uses", "run the race tests if useful" — without a concrete, task-specific reason. They cost a reviewer's whole budget and return nothing.
- Do not ask a reviewer to re-run tests the implementer already ran on the same code. The implementer's report carries that evidence.
Triage is the caller's job, not the reviewer's. A reviewer that filters while it looks leaves buckets empty for the wrong reason: cover first, filter second, and judge severity as a separate pass over a list that already exists.
How much a call is allowed to cost is configured, not improvised. .agents/lifecycle.md § Effort
and budget sets, per role: the model tier, the reasoning effort, and a soft output ceiling.
Read it before dispatching, and pass the tier and effort you find there.
Four levers, in the order they actually move cost:
- How many calls — the lens count. Six lenses cost three times two lenses, and this is the largest lever by a distance.
- Which tier — a cheap tier on a call whose shape is already written down.
- How much effort — reasoning effort per call, independent of tier.
- The output ceiling — how long a report may run.
The ceiling is an instruction to the callee, not an enforced limit. So it is written as a consequence, and the consequence is never "skim":
Stay under about
<n>output tokens. If the work does not fit, returnreviewer-uncertaintyand say what you did not reach — never a shallow pass inside the budget.
A truncated report that reads as complete is the one outcome worse than an expensive one, because the caller cannot tell the difference and ships on it.
Two rules that keep a budget honest:
- Report what a phase cost when the run is over: calls made, tier each ran on, and anything that hit its ceiling. A budget nobody measures is a preference.
- A budget is a default, not a cap on judgement. Where a call genuinely needs more — a diff far past what one lens can hold, a security lens over a permission change — take the higher tier and say in one line that you did and why. Silently overspending and silently underspending are the same defect.
A budget is tight because of the subscription, not the repo, so .agents/lifecycle.md records which
plan is paying and which profile was taken. When it says a lens was dropped for cost rather than
relevance, do not helpfully add it back.
If .agents/lifecycle.md sets no budget, say so once and use the defaults in this document's own model
table.
The eight axes
Coverage. The plan delivers the spec in full. Name anything the spec asks for that no task touches. A plan silent about part of its spec has not deferred that part — it has lost it.
Claims about the codebase. A plan is mostly assertions: this file exists, that handler is the template, this behaviour is missing, there are five call sites. Every one is checkable, and you are the last person who can check them cheaply. Open every
path:linethe plan cites. Report each claim with the command you ran and what it printed. Pay particular attention to:- "already exists" / "already implemented" — if true the task should not exist; if false the plan is missing work;
- counts — "the five sites" that nobody confirmed should have read "every site";
- negative claims — "nothing else calls this" needs a repository-wide search, and these are the assertions most often carried over from a stale reading.
Convention compliance. Against this repository's rules, not a generic standard — everything
.agents/docs.mdnames: the glossary, the conventions, the documented seams, the accepted decisions. A documented seam and an accepted decision are constraints, not suggestions.Executability. Every task names its files and how it will be verified. No placeholders — "implement the handler" is not a task and
TODOin a plan is a defect. Every command runnable as written, with no machine-specific path and no credential that will not exist elsewhere.Sequencing and interfaces. Task N can run once N−1 is done, and each task leaves the tree building. Cross-check every
Consumesagainst the matchingProduces— a name or a type that does not line up is the conflict that shows up at integration, and it is free to find here.Risk and blast radius. Migrations, permissions and tenancy, public contracts, message schemas, deploy ordering, backward compatibility. Ask what happens if this ships half-applied, because sooner or later something will.
Testability. The tests the plan names actually observe the behaviour, at a seam that exists or that the plan creates deliberately. Reject any test whose expected value is computed the way the code computes it — it passes by construction and can never disagree with the implementation. Check the plan clears the coverage floor in
.agents/gates.md.Scope. Work the spec did not ask for, work it asked for that is missing, and work that re-implements something the codebase already has. All three are findings, and the third is the one a plan review is uniquely placed to catch — after implementation it just looks like code.
Step 3 — The conflict table
Separately from the lenses, build one table yourself. It is cheap and it catches what per-axis review cannot see.
- One row for every pair of tasks that share a file or an interface — the two tasks, what one produces against what the other consumes, and what you found.
- One row for every task — whether its own text agrees with itself: the tests it specifies against the code it specifies, the files it creates against the files it later touches.
"The scan is clean" without those rows is not a scan you ran. Write the table into the report even when every row says "no conflict".
If you have not run the command in this message, you cannot say it passes.
Before any statement that work is done, fixed, passing or ready:
- Name the command that would prove the claim.
- Run it in full. Not a subset, not a remembered earlier run.
- Read the whole output and the exit code.
- State the claim with the evidence, or state what actually happened.
| Claim | What proves it | What does not |
|---|---|---|
| tests pass | the test command's output, 0 failures | a previous run, "should pass" |
| build succeeds | exit 0 from the build | the linter passing |
| lint clean | the linter's output, 0 errors | a partial check |
| the bug is fixed | the original symptom, retested | the code changed |
| the agent finished | git diff / git log in its tree |
the agent reporting success |
| the requirement is met | that requirement checked by name | the suite being green |
Report what happened, not what you hoped. A failing gate is reported with its output. A skipped step is reported as skipped. Words that imply success without evidence — "should", "probably", "looks right" — are the same violation as claiming it outright.
Step 4 — The verdict
Write plan-check.md beside the plan and commit it with the plan.
**Date:** YYYY-MM-DD
**Plan:** `<path to plan.md>`
**Verdict:** Ready to build | Ready with changes | Not ready
**Lenses:** coverage, claims, conventions, executability, sequencing, risk, testability, scope
**Claims checked:** <n> confirmed · <n> contradicted · <n> could not verify
## Blocking
- <finding> — <task heading it lands on> — <what to do about it>
## Changes to make first
- ...
## Claims
| Claim | Command run | Result |
|---|---|---|
| "the handler is at X" | `rg -n "class X" src/` | confirmed, `src/…:120` |
| "nothing else calls this" | `rg -n "Foo\(" -g '!**/obj/**'` | **contradicted** — 3 call sites |
## Task conflicts
| Tasks | Shared | Found |
|---|---|---|
## Not verified
- <what nobody could check, and why>
A finding cites a task heading, not a file:line. The code does not exist yet.
A reviewer that verified nothing is a failed reviewer, however well written its report. Checking claims against the repository is the axis this skill exists for; a lens that returned reasoning instead of evidence contributed neither. Say so in the report rather than counting it.
A contradicted claim is never a wording fix. The plan asserted something false, so the reasoning resting on it has not been done — that area gets re-scouted, not re-worded.
Chat summary
The verdict in the first line. Then the blocking count, the claim counts, and the single most expensive
thing found. Then: /build on Ready, /plan again on Not ready.
The re-plan cap is in .agents/lifecycle.md — typically one, then get a person. A plan that fails
twice has something wrong with its premises, and a re-plan loop is unusually cheap to get stuck in.
Dispatching the agents
These agents ship inside this plugin, so their subagent_type carries the plugin prefix:
lifecycle:code-scout, lifecycle:spec-reviewer, lifecycle:change-reviewer,
lifecycle:ticket-implementer, lifecycle:finding-fixer, lifecycle:operator-view.
A bare name may resolve, and it may also pick up a different agent the repo happens to define. Pass the prefixed form. Where this document links an agent by file, the prefixed name is what goes in the dispatch.