Reviews a finished implementation plan before code: units, dependencies, parallel safety, grades, coverage. Runs after plan, or for «проверь план», «отревьюй план». Not documents or code.
Resources
2Install
npx skillscat add idontlikedrinkpivo/web-dev-pipeline-codex-plugin/plan-review Install via the SkillsCat registry.
Codex runtime. Before using this skill, read
../executor-catalog/references/codex-runtime.md. It defines tool mappings, named-agent dispatch and stage-chat orchestration; use it for inherited Claude Code terms below.
Plan Review
A plan is the cheapest place in the pipeline to be wrong and the most expensive
place to stay wrong. Every defect here is multiplied by execution: a
mis-graded unit gives a rename design latitude or hands a state machine the
apply-the-shape packet, a false Параллельно: yes turns into a merge fight, an
uncovered invariant ships untested, a citation that does not resolve makes an
executor invent the design it was supposed to follow.
plan runs its own quality gate before closing. This skill is the independent
pass over the result — the same relationship code-review-unit has to work.
Self-checks catch what the author remembered to look for; this catches what the
author's own framing hid.
Write findings in Russian. Do not translate U-ids, executor names, file paths,
verdict tokens, or the report's Verdict: line and headings (doc-versioning
→ references/writing-rules.md → Document language).
Not this skill's job
| Not here | Owner |
|---|---|
| Re-slicing units or re-grading them | plan — this skill proposes, that skill edits |
| Whether the design decision behind a unit is right | the design documents, then doc-review and the user |
| Reviewing a written document's coherence, feasibility, or premise | doc-review |
| Reviewing code or a diff | code-review-unit · code-review-full |
| Deciding which model a tier maps to | executor-catalog and its agent files |
| Executing anything | work |
Inputs
| Input | Required | Read for |
|---|---|---|
Plan document documentation/plans/<version>/plan.md |
yes | §1 digest and its version line, the unit table, every unit's fields, §5 критерии готовности, open-questions.md beside the plan, version pins |
| Cited design documents | yes | resolving every Документы citation to a real section or id — a citation nobody checked is the plan's most common silent defect. Every part of a split document: srs.md and areas/*.md, openapi.yaml with paths/ and components/ |
The report a fix plan answers — test-run.md or security-audit.md beside the plan, or documentation/plans/code-audit-<date>.md |
on a fix plan | the rows its units cite and must cover |
executor-catalog/references/assignable-implementers.md |
yes | the only legal Исполнитель / Вложенный names |
plan/references/complexity.md |
judgment half | the cascade, the six signals, both floors, the anti-inflation and anti-deflation gates — the standard grades are checked against |
| The iteration's changes | yes | the manifest's current version; the iteration's typed changes — changelog rows whose Версия is the folder's version (OpenAPI: info.x-changelog), plus changes not stamped yet, from the diff of the versioned documents since the last tag v<version>; whether the API has external consumers (the foundation's Full trigger "versioned partner API", a /vN path) — what the level is checked against, and what the coverage ledger holds (Step 1) |
Repo file tree (git ls-files, run by the reviewer) |
yes | whether a unit's Файлы paths are plausible and whether a unit recreates something the scaffold already produced |
| Prior plan-review findings | when re-reviewing after a fix | so a closed finding is not re-opened |
The plan's mode decides what is in scope: a greenfield plan answers for
everything the documents hold; an increment for what this version
added or changed; a fix plan (units appended after a DEFECTS or FIX
report, or born from a code audit's rows, plan → references/modes.md) for the report rows, and only its
appended units are reviewed; a brownfield plan with no design
documents cites code:<path> and answers for the request §1 names.
Without the cited documents this degrades into proofreading: every coverage and
citation lens needs the source it cites. Say so and stop rather than reviewing
the plan against itself. A brownfield plan is not that case: its sources are
the files its code:<path> citations name, and they are in the repository.
The tree and the cited documents are the whole context. Do not go reading the
repo: a reviewer that explores produces findings about code no unit in this
plan touches. The one exception is Files completeness: a repository
search (grep) for each symbol a unit removes or changes, and the config
file names of a tool a unit changes — nothing beyond.
Workflow
Step 0. Classify the artifact
Filename and body decide what the file is. The user's "review this as
a plan" does not change the type.
| This is | Then |
|---|---|
| Architecture, domain model, scenarios, SRS, screen spec, OpenAPI, or DB schema | Stop. Name doc-review as the skill that reviews it now. Do not apply the lenses below. Do not issue PASS / RETURN_TO_PLAN / FIX_THEN_PROCEED on it. |
A finished plan (unit map, Зависит от, grades, Документы) |
Continue with Step 1 |
| Missing, or neither a plan nor a design document | Say so and stop |
"Not doc-review" means those personas do not review a work order.
It does not mean "never send the user to doc-review." An architecture
file submitted as a plan still goes to doc-review.
Step 1. Establish the standard before reading the units
The judgment half reads complexity.md before the units (its packet's
GRADING STANDARD); the executor names come fromexecutor-catalog/references/assignable-implementers.md. A reviewer that forms
an opinion about a grade before reading the cascade is applying taste, and taste
is exactly what the cascade exists to replace. So every calibration finding
cites the cascade rule or floor it rests on; "feels like Mid" is not a finding.
Extract from the design documents, once, a coverage ledger in two parts:
covered by a test — invariant rows and acceptance criterion ids;
covered by a unit — use cases, operations, screens, foundation §1
«Решения по NFR» rows, and §4 configuration variables. Only the ids in
scope go in: on an increment, the ones this version added or changed —
named in the changelog rows whose «Версия» is this version, or in the
unstamped diff since the last tag; a document whose only row of this
version is «первый выпуск» brings all its ids (greenfield). An id an
earlier version built is not this plan's to cover — demanding it buries
every second iteration under P0s for work that shipped long ago. A fix
plan's ledger is its report rows, a brownfield plan's the items of the
request. The units are checked against both parts. Build the ledger even
when the plan says it covered everything — that claim is what is being
checked.
Step 2. The lenses
Each lens's full wording is in references/reviewer-prompt.md (Structural lenses, Judgment lenses) and only
there, so the session's copy and the packet cannot drift; the session dispatches, the reviewers apply them.
| Lens | Half | Asks, in one line |
|---|---|---|
| Commit atomicity | judgment | does each unit land green alone? |
| Dependency graph | structural | is Зависит от a DAG whose every dependency exists? |
| Parallel safety | structural | is each Параллельно: yes pair disjoint in files, contracts and runtime resources? |
| Grade calibration | judgment | does the cascade on the unit's own fields give its grade, floors and gates included? |
| Files completeness | structural | is every use of a changed symbol in Файлы or «Не затрагивается» (plan/references/files-field.md)? |
| Citation integrity | structural | does every Документы entry resolve — a report row (TC-n, F<n>, code-audit-<date>.md A<n>) included? |
| Coverage | structural | does every in-scope ledger line have its unit, once? |
| Test-first writability | judgment | can each scenario's expected outcome be written before the code? |
| Executor validity | structural | is every Исполнитель / Вложенный on the assignable list, with no model slug? |
| Existing work | structural | does a unit recreate what exists, and does every Образец resolve? |
| Service version | structural | do §1's version and level match the typed changes, with the bump unit last when needed? |
| Plan hygiene | structural | unique U-ids, no progress state, repo-relative paths, pins, open questions blocking named units? |
Step 3. Dispatch
Resolve each half's row through executor-catalog and dispatch that pair
under that file's Dispatch contract (read the section with the rows), without
asking which model. Two dispatches, in
parallel, because the two halves fail differently:
| Executor | Carries |
|---|---|
plan-review-medium |
the structural lenses — dependency graph, parallel safety, files completeness, citation integrity, coverage, executor validity, existing work, service version, plan hygiene. These are checkable against the text, the tree and a search for the changed symbols, and they are where volume lives. |
plan-review-hard |
the judgment lenses — commit atomicity, grade calibration, test-first writability. Deciding that a unit cannot land alone, or that a Low unit is really Mid, is the same kind of reasoning that graded it, so it needs a tier that can hold the cascade and argue with it. |
Fill the structural packet's LINT with plan_lint.py's lines: fields, executors, the dependency graph, parallel
pairs sharing a file, model names, citations of missing ids — decided by code, so the reviewer starts from them
instead of re-deriving them. When plan invoked this review, its Orchestrator step 7 already reached exit 0, so
LINT is that run's warnings; when the user opened this review directly, runpython3 "<folder of this SKILL.md>/../plan/scripts/plan_lint.py" <plan> yourself first.
Build both from references/reviewer-prompt.md. Each packet names its
inputs by path and pastes only the ledger, which exists nowhere on disk
(executor-catalog → Dispatch contract → Paths, not pasted documents);
the grading standard goes only to the judgment half, which is the one that
runs the cascade. On a fix plan or a re-review, UNITS names the units to
review. Do not merge the halves into one
dispatch to save a call: the structural half is mechanical and the judgment half
is adversarial, and one packet holding both reliably produces a reviewer that
skims the calibration it was supposed to challenge.
Both halves run on every plan, small ones included: the structural half onplan-review-medium is the cheap row, and running it on the session model
would be the "do the row's work on the session" the catalog forbids.
Step 4. Judge the findings
| Level | Meaning | Effect |
|---|---|---|
| P0 | the plan cannot execute as written: a dependency cycle, a unit that cannot land green alone, a floor violation, a Документы citation that does not resolve, an invariant or AC covered by no unit, an Исполнитель or Вложенный name absent from the assignable list |
blocks the handoff to work |
| P1 | the plan will execute but buy avoidable rework: a false Параллельно: yes, a grade off by one tier without a floor breach, a scenario whose expected outcome is not yet decided, a unit duplicating scaffold output, a PATCH over «добавляет» / «ломает» changes, a partner API broken inside its major, or no bump unit |
blocks the handoff |
| P2 | ordering or naming that a maintainer would improve — a wave that could be wider, a Почему that names a weak signal |
recorded, does not block |
| P3 | nit | recorded, does not block |
Three dismissal rules:
- The design decided it. A unit that looks odd because the architecture is
odd is not a finding here — cite the section and dismiss. Arguing with the
design isSTOP. - The plan already flagged it. A row in
open-questions.mdthat blocks a
named unit is the plan working correctly, not a defect. - A grade the cascade genuinely permits. When two signals point at
different tiers and the plan'sПочемуnames the one it followed, that is a
judgment inside the cascade, not a miscalibration. A grade is only wrong when
a floor, a gate, or the unit's own filled fields contradict it.
Step 5. Verdict
Exactly one:
| Verdict | When | Next move |
|---|---|---|
PASS |
no P0/P1 | the plan may proceed to the next stage per pipeline; P2/P3 recorded in the review report |
FIX_THEN_PROCEED |
P0/P1 fully specified and mechanical in the plan text — a wrong Параллельно, a mistyped executor name, a missing citation whose target is obvious, a grade the floor decides |
plan applies them in place, then this review re-runs over the changed units only |
RETURN_TO_PLAN |
P0/P1 needing the planner's judgment — a dependency cycle, a unit that has to be split, a re-grade with knock-on executor changes, coverage that has no obvious home | plan re-opens with the findings attached; re-review after |
STOP |
the finding is upstream: the design has a gap, a document contradicts another, or the plan cannot be fixed without a product decision | do not proceed to work; take it to the user, and the fix lands in the document, not the plan. A finding whose fix would reverse a decision a document made on purpose is STOP too, with the decision quoted, whatever its severity (pipeline → references/decision-changes.md → A finding against a settled decision) |
Every P0/P1 row carries a Вид правки (the one name of this field, in
the report and in the reviewers' FINDINGS), so plan can pick the revise
writer without re-reading the findings (plan-complexity.md → Grading a
revise):
| Вид правки | When |
|---|---|
mechanical |
the Fix cell is the finished edit — a citation, a Параллельно value, an executor name, a grade a floor dictates, a scenario line spelled out |
local |
a local decision is left: change a grade and its implementer, move units between waves, add Файлы after checking the code, write scenarios for a changed document, a service version the session re-asks the user |
reslice |
split or merge units, add a unit, change Зависит от across several units, change a security, money, or migration decision |
FIX_THEN_PROCEED means every blocking row is mechanical. P2/P3 rows
leave the cell —.
This skill never edits the plan. It reviews a decision artifact, and an artifact
a reviewer silently rewrote is no longer a decision anyone made. Proposing a
better slicing in a finding's Fix is fine; rewriting the unit table is not.
Report
The report is documentation/plans/<version>/plan-review.md, beside the
plan, overwritten on each review. Its first line is the verdict alone, e.g.Verdict: PASS; work and pipeline read that line as the gate. The
second line is checked: <sha256 of plan.md>: work compares it with the
plan on disk and sends a plan changed since — units appended by a fix, a
hand edit — back here, because a verdict covers the text it read, not the
file's name. This file is the only thing this skill writes — the plan
itself is never edited.
Two reports, one file — by the script. Save each half's report, as it
came back, to a file under $(git rev-parse --path-format=absolute --git-common-dir)/pipeline-work/
(plan-review-structural.md, plan-review-judgment.md), then run
python3 "<folder of this SKILL.md>/scripts/merge_review.py" documentation/plans/<version>/plan.md <structural file> <judgment file>It writes both header lines, one findings table (P0 → P3, structural rows
first within a level, the same units and lens from both halves one row at
the stricter level) and the verdict computed from the merged rows: STOP
if either half returned STOP; otherwise any P0/P1 → FIX_THEN_PROCEED
when every blocking row's «Вид правки» is mechanical, elseRETURN_TO_PLAN; none → PASS. Merging by hand drifts from those rules,
and a hand-typed hash is a gate that never matches. Read the file back; a
half that returned no VERDICT line is re-asked, not guessed.
Verdict: <verdict>
checked: <sha256 of plan.md>
## Ревью плана — <plan path> — <verdict>
| # | Важность | Юниты | Аспект | Находка | Исправление | Вид правки |
|---|---|---|---|---|---|---|
**Coverage ledger** — invariant rows and ACs with no unit, or the explicit clean
line.
**Grade table** — every unit whose cascade result differs from its stated grade,
with the signal that decides it; plus the tier distribution as written.
**Dismissed** — findings ruled out, and which rule applied.
**Not blocking** — P2/P3, for the record.
**Open** — doubts about the design itself, for the user.A filled report, for calibration — match its density, not its domain:
Verdict: FIX_THEN_PROCEED
checked: 3f5a0c9e1b7d4a62c8e0f1a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e6
## Ревью плана — documentation/plans/1.3.0/plan.md — FIX_THEN_PROCEED
| # | Важность | Юниты | Аспект | Находка | Исправление | Вид правки |
|---|---|---|---|---|---|---|
| 1 | P0 | U6 | Citation integrity | `Документы` ссылается на `api POST /orders/{order_id}/refund`, в OpenAPI такой операции нет; возврат описан как `operationId refundPayment` | заменить цитату на `api refundPayment` | mechanical |
| 2 | P1 | U4, U5 | Parallel safety | обе правят `src/orders/domain/order.ts`, но U5 помечен `Параллельно: yes` и стоит в волне 2 вместе с U4 | U5: `Параллельно: no — U4`, перенести в волну 3 | mechanical |
| 3 | P2 | U9 | Plan hygiene | `Почему` пересказывает цель, а не сигнал | «rule 5 — прецедент `src/invoices/adapters/invoice-repository.ts`» | — |
**Coverage ledger** — все инварианты и AC версии 1.3.0 покрыты.
**Grade table** — U8: заявлено Mid; если считать signal 6 дешёвым, каскад даёт Low (rule 5), но `Почему` называет rule 6 — сценарий ретрая требует управления временем. Каскад это допускает, не находка. Распределение: 0:1 Low:4 Mid:3 High:1.
**Dismissed** — U3 правит 6 файлов, но foundation §5 кладёт репозиторий и маппер в один модуль (правило 1: решил дизайн).
**Not blocking** — #3.
**Open** — нет.The grade table is the part a run cannot reconstruct later: once work starts,
a wrong grade shows up only as cost.
Before you finish
The reviewers' reports show:
- every lens with a finding, an explicit clean line, or a stated reason it
has no surface in this plan — Step 2; - every invariant row and AC from the ledger with a named unit or a P0 — Step 1;
- every
Документыcitation resolved against the actual document — Step 2; Исполнитель/Вложенныйnames checked against the assignable list, not
the full catalog Name column — Step 2;- the version's level checked against the iteration's typed changes,
and the bump unit last — Step 2.
The session checks:
- Exactly one verdict, no P0/P1 left unclassified; a design defect is
STOP,
not a finding — Steps 4–5. - The plan file is byte-identical to how the review found it — Step 5.
- The ledger held only the ids in scope — this version's, the report's,
or the request's — Step 1. plan-review.mdexists beside the plan withVerdict: <verdict>on its
first line andchecked: <sha256>of the reviewedplan.mdon its
second; two halves merged into one table and one verdict — Report.
References
references/reviewer-prompt.md— the packet each reviewer receives, every
lens's full wording, and the report it returns.scripts/merge_review.py— merges the two reports intoplan-review.md
with its verdict andchecked:lines (Report).plan(skill) — its writer settles the plan this reviews, owns every fix, and runs its own quality gate first. The session re-dispatches that writer and does not edit the file.plan/references/complexity.md— the cascade and floors every calibration
finding must cite.executor-catalog/references/assignable-implementers.md— the legal
implementer names; the parent catalog only for the twoplan-review-*rows this skill dispatches.pipeline(skill) — where this gate sits. Whenplaninvoked this
review, report and return;planasks the next stage. When the user
opened this review directly, ask the next transition perpipeline
→ "Asking before a transition".