Purpose
Stage: Ship — per-slice workhorse. The autonomous span ends here.
Source: QRSPI p.2/p.7 — after six months of "don't read the code," Dex's team had to rip out and replace large parts of their system. The PR is the enforcement point for the read-the-code principle, and — under the autonomy model — the last thing the agent does before handing the slice to a human. With the per-wave Verify gate gone, the async human merge is the suite's sole independent oracle, so the PR is not a formality: it is the curated, design-anchored, risk-banded brief that decides whether a human can merge safely without re-reading the entire diff cold.
Three reasons this is its own skill, not a cleanup step inside implement/review:
- The code-reading gate is skipped under pressure if it's a footnote. A dedicated skill with fresh focus makes the reviewer checklist non-optional.
- The PR body's job is human communication, not step-execution. It anchors the diff to upstream
design (
prd.md+ ADRs), narrates the slice end-to-end, and lists the highest-risk files to read. - The internal gates are already closed.
quality-verification+ the Review fan-out + the evaluator floors ran before this skill;pull-requestis the handoff to humans, not a second evaluation pass.
When to use / when to skip
Use to close a slice: its code is committed on the slice branch and all three agent-internal
gates are green — qa.md ## Verdict = pass · the Review fan-out is clear · the evaluator floors
are met (correctness≥8, testing_strategy≥7, plan_adherence≥8, regression_surface≥9).
Skip / refuse:
- Any internal gate is not green → no PR (route back per
qa.md/ Review findings). - A security CRITICAL/HIGH or a secret in the diff → hard halt, no PR ever (safety rails 2 and 3,
references/safety-rails.md); top the report, and for a committed secret fire PushNotification + freeze the next barrier. depth: lite— a docs-only or config-only slice still gets a PR, but the code-reading checklist may name fewer than 3 files: name what is actually risky, do not pad.
Never gh pr merge, push to main, or trigger a deploy — those are fenced behind the human
(safety rail 1, references/safety-rails.md).
Inputs
Resolve each in order: (1) inline in the prompt, (2) a path in the prompt, (3) the canonical per-feature/repo path. Refuse to run, naming the missing input, if any required value cannot be resolved from any source.
| Input | Source artifact (path) | Used for |
|---|---|---|
| Verify ledger | qa.md (docs/features/<slug>/qa.md): ## Behavioral ledger · ## Verdict |
the Test plan + the human-ack lines; ## Verdict = pass is a hard gate |
| Product anchor | prd.md (## Solution / ## User Stories) + referenced ADRs by id |
the Summary "why" — never from commit messages |
| Plan + slice | plan.md + the slice row (id · Story-ref · Blocked by; the human title lives in STATE.md, not plan.md) |
the Diff narration + the slice id in the title |
| Behavioral contract | acceptance.md (scenario ids, e.g. PWR-A1) |
cross-check the ledger; each not-reachable id ⇒ a human-ack line |
| The slice diff | git diff <base>..HEAD + git log --oneline <base>..HEAD (base = the slice branch's base; --base <ref> overrides) |
highest-risk-file selection + secret scan + the blast-radius input to the risk band (Step 2) — what the diff touches is read off the diff itself, so no upstream skill has to hand it over |
Evaluator floors (a gate, not a pull-request input) |
orchestrator-enforced agent-internal gate — there is no evaluator skill in the roster; the orchestrator checks correctness≥8 · testing_strategy≥7 · plan_adherence≥8 · regression_surface≥9 before dispatching pull-request |
the hard refuse-to-run gate below — pull-request reads the verdict, it does not compute the floors |
Refuse-to-run gate (hard): the resolved qa.md ## Verdict records pass, the Review fan-out
is clear, and the evaluator floors are met. Without a passing internal-gate set, pull-request opens no PR.
Recovery message names the missing/failing gate and points at qa.md / the Review findings.
Process
Step 1 — Identify the highest-risk files
Read the diff. Pick the 3-5 files most likely to hide a subtle correctness defect: new abstractions, complex logic, side effects, or the largest line-count changes. These become the reviewer code-reading checklist. "All changed files" is not a checklist.
Step 2 — Compute the risk band (inverted risk report)
The load-bearing addition over cr-pr. This skill owns the risk-band rule; the rule is stated here and nowhere else, and every other file points at this step rather than restating it — a band computed one way in the producer and described another way in a doc is a band nobody can trust.
Two independent inputs feed it: what the diff touches, and how the slice passed. The band is the higher of the two.
Input 1 — blast radius: what the diff touches. Read the diff. Each row below is a fact you settle by reading it, exactly as the orchestrator's reviewer-trigger rows are, and any row that fires makes the band HIGH:
| The fact about the diff that fires the row | Why it outranks a clean record |
|---|---|
| It changes authentication, authorization, session, or permission logic — the code deciding who may do a thing | the mistake grants rather than denies, and it grants to everyone at once |
| It changes payment, billing, or pricing code — anything that moves money | the money has already moved by the time anyone reads the log |
| It reads, writes, exports, or deletes personal or user data, or changes a schema that holds it | disclosed data cannot be un-disclosed, and deleted data is not restored by reverting the commit |
| It handles a credential — reading, storing, rotating, or transmitting a secret, token, or key | the blast radius is the whole repo and it outlives the slice |
| It carries a destructive or irreversible migration — a dropped column or table, a backfill that cannot be replayed, a bulk delete | reverting the merge does not undo it |
| It changes deploy, rollout, or infrastructure configuration — anything that acts on production the moment it lands | the merge is the deploy, so the human's click is the last gate there is |
A row you cannot settle fires. If reading the diff does not tell you whether it touches one of these, band it as though it does. Raising a band wrongly costs the human one closer read; leaving it low wrongly costs the one signal the band exists to carry, and nothing downstream re-reports it. This is the opposite default from the orchestrator's reviewer-trigger table, and deliberately so: an unfired trigger row still leaves four floor axes reading the diff, while an unraised band leaves nothing.
Input 2 — the quiet greens: how this slice passed. Collect from qa.md ## Verdict and the
evaluator result:
- which evaluator floors landed at the line (e.g.
regression_surface = 9exactly); - qa coverage derived from the ledger as exercised ÷ total scenarios (
qa.mdemits no coverage %, only the## Behavioral ledger), plus any scenario id classified not-reachable there; - rounds consumed (of the 3 implement→verify→review cycles);
- whether any test or
acceptance.mdline was touched during retries (must be none — the frozen-artifact invariant); - whether the declared
regression_surfacenarrowed (must be none).
None of those → LOW. Floors at the line / a not-reachable id / 3-of-3 rounds / a non-empty "frozen artifacts touched" → MEDIUM.
Then take the higher input, and name the rows that fired. A slice that touches auth is HIGH however clean its record is — that is the whole point of computing blast radius separately, since a high-blast slice that passed on the first round is exactly the one a floors-and-rounds band would call LOW. The body lists which rows fired and where, so a person triaging a queue of HIGH PRs can tell an auth change from a migration without opening a diff.
A HIGH band never stops the stage and never halts a slice. Inside a run nothing pauses for high-risk
work — orchestrator, High-risk work is not one of these, says so — and the band is where that risk
surfaces instead, for the person at the merge gate. Do not invent a halt here; a HIGH PR opens like any
other. Surface narrowing and a frozen-artifact edit are the separate case
and should already have HALTED upstream — if seen here, HALT and open no PR (gate-erosion).
A HIGH band is not a HIGH security finding, and the shared word is the trap. security-and-hardening
grades findings CRITICAL/HIGH/MEDIUM/LOW, and a CRITICAL/HIGH there is a hard halt with no PR ever (Red
flags below). That is a different scale applied to a different object: a finding says something is wrong,
a band says how much rides on it being right. Auth work done correctly carries a clean security verdict
and a HIGH band — that is the normal case, not a contradiction. Read which of the two you are holding
before you act on the word.
Step 3 — Push the slice branch
git push -u origin <slice-branch> # e.g. cluster/C-007 or feat/<slug>; NEVER push to main
Step 4 — Open the DRAFT PR (fail-closed)
The terminal state of a passing slice is a DRAFT PR. pull-request itself never marks it ready;
promotion to ready-to-merge is done by a separate fresh code-cold verifier with no test-write
access (see Outputs & handoff).
gh pr create --draft \
--title "<type>(<scope>): <slice-id> <description under 70 chars>" \
--body "$(cat <<'EOF'
## Summary
- <why this slice exists — drawn from prd.md ## Solution / a referenced ADR, NOT commit messages>
## Upstream artifacts
- PRD: [prd.md](<path>) · ADRs: <ADR-007, …> · Structure: [architecture.md](<path>) · Plan/slice: [plan.md](<path>) (<slice id>)
- Acceptance: [acceptance.md](<path>) · Verify ledger: [qa.md](<path>)
## Diff narration
**<slice-id> — <title>:** <what this slice does end-to-end, layer to layer — not a file list>
## Test plan
**Exercised (from qa.md ## Behavioral ledger):**
- <PWR-A1>: <the behavior this test proves>
**Not reachable — REQUIRED human ack, do not leave blank:**
- [ ] <PWR-A3>: <why unreachable in this slice> — human must acknowledge before merge
## Code-reading checklist
**Reviewers: check each file before approving.**
- [ ] `<file 1>` — <one sentence: why highest-risk>
- [ ] `<file 2>` — <one sentence>
## Risk band: <LOW|MEDIUM|HIGH>
- blast radius: <none | auth: `src/auth/session.ts` · user data: `migrations/007_drop_email.sql`>
- floors at the line: <none | regression_surface=9, …>
- qa coverage (exercised/total from qa.md ## Behavioral ledger): <e>/<t> · rounds consumed: <n/3> · frozen artifacts touched (tests · acceptance.md): <none | …> · surface narrowed: <none>
EOF
)"
Return the PR URL.
PR body anatomy (the design-anchored contract)
Each section earns its place; none is decorative:
- Summary = the why, traced to
prd.md/ADRs. A commit-message restatement is a failure. - Upstream artifacts = the links that let a reviewer open the design behind the diff (the PR references ADRs by id; it never restates their rationale).
- Diff narration = end-to-end prose ("this slice wires the token endpoint and persists the 1-hour TTL"), never "changed auth.ts, added test".
- Test plan = the
qa.mdledger, made human-legible — exercised behaviors + the not-reachable acks. The agent does not invent a scenario↔test map here; it transcribes the ledger. - Code-reading checklist = the 3-5 highest-risk files with a one-line rationale each. This is the proof a human read the code — the gate whose absence cost Dex's team a rip-and-replace (QRSPI p.7).
- Risk band = the inverted risk report, and the only place blast radius reaches a human. It draws
their scarce attention two ways at once: to what the diff touches (the named blast-radius rows), and
to the quiet greens where unattended defects actually ship — both surfaced alongside, not buried
under, the halts. A band with no
blast radius:line has not been computed, only asserted.
Rationalizations
- "The commit messages already explain it." → No. Summary bullets come from
prd.md/ADRs (the why), not agit logdump. - "Reviewers can just open the files tab." → The curated 3-5 highest-risk checklist is the deliverable; an unfiltered diff is exactly what made Dex's team rip-and-replace (QRSPI p.7).
- "
quality-verificationmarked one scenario not-reachable; I'll just omit it." → Everynot-reachableid is a REQUIRED human-ack line in the body; silently absorbing it defeats the human-anchored oracle it came from: theacceptance.mda person signed, and nobody else. - "All gates passed, I'll open it ready-to-merge to save a step." → Fail-closed: the terminal state is DRAFT; only the fresh code-cold verifier promotes. Marking it ready yourself is gate-erosion.
- "A retry tweaked a test to make it pass." → That is a frozen-artifact violation; HALT, open no PR.
- "Every gate passed first time, so this is LOW." → Only if no blast-radius row fired. The band is the higher of the two inputs, and a clean record is exactly what makes an auth or migration diff look safe. Read the diff for what it touches before you read the ledger for how it passed.
- "The slice is called
PWR-2 expire stale tokens, and nothing in the title says auth." → The rows are facts about the diff, not about the slice title or the plan's description of it. Open the diff. - "The diff touches auth, so I should halt and let a human decide." → No. A HIGH band opens a PR like any other; inside a run nothing pauses for high-risk work. Inventing a halt here removes the slice from the human's queue instead of flagging it in the queue.
Red flags (STOP)
- A security CRITICAL/HIGH or a secret in the diff → no PR, hard halt, top the report; a committed secret → PushNotification + freeze the next barrier (safety rail 2's literal STOP).
- An internal gate (
quality-verification/ Review / an evaluator floor) is not green → no PR. - The
regression_surfacenarrowed, or a frozen test /acceptance.mdline changed during retries → HALT (gate-erosion); do not ship. Name the artifact in the report — "gate erosion" alone tells nobody which guarantee went. - The diff edits
docs/design.md→ HALT (the same gate-erosion, safety rail 4); do not ship. - You are about to
gh pr merge, push tomain, or trigger a deploy → STOP; the human owns the merge. - The code-reading checklist is empty, generic, or says "all files" → rewrite before opening.
- About to band a diff without having read it for blast radius, or to leave the
blast radius:line off or blank → STOP, compute it. A missing line reads as "none fired", and the person triaging the merge queue has no other channel for it. - About to halt, hold, or refuse a PR because the band came out HIGH → STOP. High blast radius raises the band; it never stops the stage.
Verification (ending criteria)
Done when ALL hold:
- A DRAFT PR is open on the slice branch (never on
main); URL returned. - Summary bullets trace to
prd.md/ADRs; no commit-log dump. - Code-reading checklist names 3-5 (or fewer, if
lite) highest-risk files, each with a one-line rationale. - Test plan reflects
qa.md## Behavioral ledger; everynot-reachableid has a REQUIRED human-ack checkbox. - Risk band computed from both inputs and attached (LOW/MEDIUM/HIGH): the
blast radius:line names every row that fired and the file that fired it, or readsnone; the quiet-green line carries floors-at-line · qa % · rounds · frozen-artifacts-touched · surface-narrowed. The band is the higher of the two, and no diff that fired a row is banded below HIGH. - Secret scan clean; build + tests green; diff ≤ 400 LOC.
Outputs & handoff contract
Emits: PR (open, draft, risk-banded) — stable body sections ## Summary · ## Upstream artifacts · ## Diff narration · ## Test plan (with human-ack lines) · ## Code-reading checklist
· ## Risk band (LOW|MEDIUM|HIGH, carrying its blast radius: line). Anchored to prd.md/ADRs.
Change a stable section's shape → update the consumer (the human merge gate + any release skill) in the
same commit. The band's rule lives in Step 2 above and only there — the orchestrator's run-terminal
risk report reproduces the bands this skill computed and does not compute its own.
STATE.md update: the slice row → State: ship then done; Gate: you (the async human merge is
the surviving final gate); Artifacts: += PR #<n>.
Handoff (fail-closed promotion): pull-request stops at the DRAFT PR. A separate fresh code-cold
verifier with no test-write access (a NEW checker each round, seeing only acceptance.md) promotes
draft → ready-to-merge after the integration gate on the connected DAG component passes.
Cohesion: loose feature → promoted greens become individual ready PRs (partial delivery); tight
feature → if any sibling slice halted, hold this PR DRAFT (atomic; never hand a human half a
feature).
Merge is the human's — never auto-merge to main; auto-deploy is OUT of v1 (safety rail 1;
ci-cd/shipping-and-launch deploy actions are fenced behind the human merge).
Neighbor skills
- Curating the reviewer's focused context: the
code-reviewReview fan-out, whose findings must be clear beforepull-requestruns. - Branch-push / worktree-cleanup lifecycle is owned by the
orchestrator;pull-requestexecutes the push, the orchestrator reclaims the worktree.