independent-review · git:20260622.59b4e31 · 2026-06-22 · sha256 b6b9ac55a4877709

independent-review git:20260622.59b4e31A

Immutable. This exact content is served forever at /api/v1/blob/b6b9ac55a4877709.

---
name: independent-review
description: >
  Build the standardized prompt for a fresh reviewer subagent that evaluates
  implemented work against its spec without access to the implementation
  conversation. Use after an implementer subagent completes a spec slice (when
  the slice is ready for REVIEWED), or after a deviation log is written (for
  reconciliation review). Do not use for ad-hoc code review unrelated to a
  spec, or for reviewing a spec's authorship (that's the READY_FOR_REVIEW step
  in spec-workflow).
user-invocable: true
---

> Spec 004 promoted this skill from stub to active. The prompt is constructed
> by `review.py`; Codex owns the Task invocation.

## What this skill does

Constructs the standardized reviewer-subagent prompt and tells Codex when /
how to spawn the Task. The skill has four modes, matching the review passes
every slice may run:

- **Implementation review** — after the implementer writes the deliverable to
  disk. The reviewer evaluates each acceptance criterion against the actual
  files; returns `pass | fail | needs-changes`. This is the **compliance
  pass** in spec-workflow's multi-pass flow.
- **Pr-review (craft pass)** — slice 031-01. After the compliance pass
  returns, the orchestrator runs a craft-pass review that produces the
  four-bucket output (scope / blockers / nits / strengths) the
  `jig:pr-review` skill emits, wrapped in the same verdict envelope as the
  compliance pass. SPECIFIC ISSUES entries are tagged `[blocker]` / `[nit]`
  / `[strength]` so the workflow can decide what blocks the REVIEWED
  transition vs. what becomes a reconciliation-log entry.
- **Arch-review (architecture pass — on-demand)** — slice 031-02. After
  the craft pass returns, the orchestrator queries the slice's
  `arch_review:` frontmatter flag via `workflow.py arch-review-needed`;
  when `true`, it runs an arch pass producing the four-bucket output
  (summary / strengths / concerns / open questions) the
  `jig:arch-review` skill emits, in the same verdict envelope. Slice
  authors set `arch_review: true` in the slice's frontmatter when the
  slice changes module boundaries, public contracts, or
  architecture-shaped concerns; the slice template at
  `templates/docs/specs/slice-template.md` ships the field commented
  out as a discoverability nudge.
- **Reconciliation review** — after the deviation log is written. The
  reviewer verifies the doc changes match reality; does NOT re-review the ACs.

`review.py` builds the prompt text; `agents/reviewer.md` defines the agent's
tool restrictions and persistent system rules.

## How to use

### Implementation review

After the implementer has written the deliverable to disk:

```bash
PROMPT=$(python3 "${PLUGIN_ROOT}/skills/independent-review/review.py" \
  implementation \
  "docs/specs/NNN-<slug>/spec.md" \
  "<slice-fragment>" \
  "<deliverable-path-1>" "<deliverable-path-2>" ...)
SUBAGENT=$(python3 "${PLUGIN_ROOT}/skills/independent-review/review.py" \
  subagent-type implementation)
```

Then feed `$PROMPT` to the `Task` tool with `subagent_type: "$SUBAGENT"`.
The helper resolves `$SUBAGENT` deterministically — `reviewer` when jig is
installed as a plugin (the real filesystem-based agent is reachable),
`general-purpose` when running from source. Wait for the verdict. Address
any `fail`/`needs-changes` findings; rerun the helper + Task as needed
until `pass`.

### Pr-review (craft pass — slice 031-01)

After the compliance pass returns `pass`, run the craft pass:

```bash
PROMPT=$(python3 "${PLUGIN_ROOT}/skills/independent-review/review.py" \
  pr-review \
  "docs/specs/NNN-<slug>/spec.md" \
  "<slice-fragment>" \
  "<deliverable-path-1>" "<deliverable-path-2>" ...)
SUBAGENT=$(python3 "${PLUGIN_ROOT}/skills/independent-review/review.py" \
  subagent-type pr-review)
```

Feed `$PROMPT` to `Task` with `subagent_type: "$SUBAGENT"`. The prompt
points the reviewer at the most-specific `pr-review` SKILL.md reachable
in the environment — Codex's skill router resolves user > project >
`jig:pr-review` precedence via the skill description hints. The pass
returns the canonical four output buckets (scope / blockers / nits /
strengths) wrapped in the same verdict envelope as the compliance
pass. SPECIFIC ISSUES entries are tagged `[blocker]` / `[nit]` /
`[strength]`; only `[blocker]` entries block the REVIEWED transition.

### Arch-review (architecture pass — slice 031-02, on-demand)

The arch pass runs only when the slice's frontmatter declares
`arch_review: true`. Query the flag via `workflow.py arch-review-needed`
before spawning:

```bash
# Capture the helper exit code — a non-zero exit means the slice lookup
# failed, not "no arch pass needed." Surface the error rather than
# silently skipping the pass.
if ! NEED_ARCH=$(python3 "${PLUGIN_ROOT}/skills/spec-workflow/workflow.py" \
    arch-review-needed \
    "docs/specs/NNN-<slug>/spec.md" \
    "<slice-fragment>"); then
  echo "arch-review-needed failed — aborting" >&2
  exit 2
fi
if [ "$NEED_ARCH" = "true" ]; then
  PROMPT=$(python3 "${PLUGIN_ROOT}/skills/independent-review/review.py" \
    arch-review \
    "docs/specs/NNN-<slug>/spec.md" \
    "<slice-fragment>" \
    "<deliverable-path-1>" "<deliverable-path-2>" ...)
  SUBAGENT=$(python3 "${PLUGIN_ROOT}/skills/independent-review/review.py" \
    subagent-type arch-review)
fi
```

When `$NEED_ARCH` is `true`, feed `$PROMPT` to `Task` with
`subagent_type: "$SUBAGENT"`. The prompt routes via the same
prose-based dispatch as `pr-review` to the most-specific `arch-review`
SKILL.md reachable. The pass returns the canonical four arch output
buckets (summary / strengths / concerns / open questions). Tag and
block semantics match the craft pass: `[blocker]` entries block the
REVIEWED transition; `[nit]` entries and `needs-changes` become
reconciliation-log items.

Slice authors set `arch_review: true` in the slice file's frontmatter
when the slice changes module boundaries, public contracts, or
architecture-shaped concerns. The slice template ships the field
commented out as a discoverability nudge.

### Reconciliation review

After the deviation log subsection has been added under the slice in
`spec.md`:

```bash
PROMPT=$(python3 "${PLUGIN_ROOT}/skills/independent-review/review.py" \
  reconciliation \
  "docs/specs/NNN-<slug>/spec.md" \
  "<slice-fragment>")
SUBAGENT=$(python3 "${PLUGIN_ROOT}/skills/independent-review/review.py" \
  subagent-type reconciliation)
```

Feed `$PROMPT` to `Task` with `subagent_type: "$SUBAGENT"`. The prompt
explicitly tells the reviewer NOT to re-evaluate against ACs — it only
verifies the deviation log matches reality.

### Recording and checking review evidence (slice 045-02)

A review pass is durable evidence, not ephemeral chat. After a pass
returns a verdict, record it as a file beside the slice it grades, at
`docs/specs/NNN-<slug>/reviews/slice-NN-<pass>.md` (ADR-0014 §1). The
schema (`pass ∈ {compliance, craft, arch, reconciliation}`,
`verdict ∈ {pass, fail, needs-changes}`, plus `reviewer`, `reviewed_at`,
`prompt_source`) lives in `skills/_common/review_evidence.py` so the
slice 045-03 transition gate validates the same shape.

Record a verdict (the freeform body comes from `--summary-file` or stdin):

```bash
python3 "${PLUGIN_ROOT}/skills/independent-review/review.py" \
  record-review \
  "docs/specs/NNN-<slug>/spec.md" \
  "<slice-fragment>" \
  --pass compliance \
  --verdict pass \
  --reviewer jig:reviewer \
  --prompt-source "review.py implementation ..." \
  --summary-file verdict.md
```

Re-recording the same `(slice, pass)` **overwrites in place** — git
history is the audit trail, there is no append (ADR-0014 §4). A
`fail`/`needs-changes` that has not been overwritten by a later `pass`
therefore still blocks the gate, which is exactly the "superseded
without a later pass" case.

Validate the evidence set for a slice at a transition stage:

```bash
python3 "${PLUGIN_ROOT}/skills/independent-review/review.py" \
  check-reviews \
  "docs/specs/NNN-<slug>/spec.md" \
  "<slice-fragment>" \
  --stage REVIEWED   # or RECONCILED
```

`check-reviews` exits `0` when the required passes for the stage all
clear (`REVIEWED` → compliance + craft, plus arch iff the slice declares
`arch_review: true`; `RECONCILED` → reconciliation), or `2` with
actionable diagnostics for missing files, malformed frontmatter, unknown
pass/verdict values, non-clearing (superseded-only) verdicts, and invalid
slice targets. The gate rule is uniform: a pass clears iff `verdict: pass`
(ADR-0014 §3). **Code-staleness** (a `pass` artifact predating a later
deliverable change) is deliberately NOT checked — it is a deferred
enhancement (ADR-0014 Scope).

**The full enforced flow.** build prompt (`review.py implementation` /
`pr-review` / `arch-review`) → spawn reviewer → `record-review` the
verdict → `check-reviews` (optional preflight) → `workflow.py transition
… REVIEWED` (or `RECONCILED` / `DONE`). The transition imports the same
validator `check-reviews` uses, so the gate and this skill agree by
construction. A refused transition names the missing/invalid artifact and
the `record-review` command to produce it; a deliberate out-of-band flow
bypasses the gate with `JIG_REVIEW_EVIDENCE_GATE=0`. **Recovering from a
failed review:** address the findings, re-run the pass, `record-review`
again (overwrites the earlier file for that `(slice, pass)` in place — git
history is the audit trail), then re-run the transition; with every
required pass now `pass`, the gate clears.

### What gets put in the prompt automatically

- Standard preamble ("You are seeing this work for the first time")
- The slice's full label (helper looks it up from the spec)
- "What you must NOT do" block (no prior reasoning, no soften, no file writes,
  no `docs/memory/` writes)
- Canonical output format (`VERDICT | REASONING | SPECIFIC ISSUES | RECONCILIATION NOTES`)

## Context isolation pattern

Implementer writes deliverable to disk → `review.py` builds a self-contained
prompt → Codex spawns the reviewer Task with that prompt → reviewer reads
only what the prompt points at. This is imperfect (parent context is
technically accessible to subagents — see GitHub issue #20304), but works
reliably when the prompt is sharp.

## Gotchas

- **`review.py` does not spawn the Task.** It only constructs the prompt
  string. Codex is responsible for invoking the `Task` tool with the prompt
  as the `prompt` parameter. This separation keeps `review.py` deterministic
  and testable.
- **Reviewer agent is read-only by definition.** `agents/reviewer.md` lists
  only `Read`, `Glob`, `Grep` in its tool set. No `Write` or `Edit`.
- **Reviewer must not write to `docs/memory/`.** Defining the glossary,
  capturing learnings, or modifying the hot cache is `memory-sync`'s job,
  not the reviewer's.
- **Reconciliation review never re-evaluates ACs.** That's done. The
  reconciliation prompt explicitly states this so the reviewer doesn't
  drift into AC-re-review.
- **Substring matching for slice fragments** is identical to `workflow.py` —
  `001-01` matches `## Slice 001-01 — greenfield-scaffold`. Ambiguous
  fragments are refused with exit 2.