yzhao062/anywhere-agents/skills/implement-review/SKILL.md
implement-review
Review loop for staged changes. Detects content type, prepares a review request for Codex (Terminal-relay manual default, opt-in Auto-terminal codex-exec subprocess, or IDE plugin), categorizes feedback, revises, and iterates. Works for code, papers, proposals, or any text-based output.
- Source repository stars
- 239
- Declared platforms
- 1
- Static risk flags
- 4
- Last source update
- 2026-08-24
- Source checked
- 2026-08-25
Decision brief
What it does: where it fits
Review loop for staged changes. Detects content type, prepares a review request for Codex (Terminal-relay manual default, opt-in Auto-terminal codex-exec subprocess, or IDE plugin), categorizes feedback, revises, and iterates.
Not for
- Trivial changes where review adds no value (typo fixes, config tweaks).
- Changes that require running tests or builds to validate -- run those first, then review.
Compatibility matrix
Platform support, with evidence labels
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Declared | Source record | Install path and trigger |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
Inspect first. Install second.
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/yzhao062/anywhere-agents --skill "skills/implement-review"Inspect the Agent Skill "implement-review" from https://github.com/yzhao062/anywhere-agents/blob/753d0c47afe1a6e77b21bc682adc6ff8b7c7337e/skills/implement-review/SKILL.md at commit 753d0c47afe1a6e77b21bc682adc6ff8b7c7337e. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
What the source asks the agent to do
- 01
When to plan-review first
Any complex task benefits from a plan review BEFORE execution, not only writing or code. Plan-first catches architectural holes while they are still cheap to fix. The scope includes: system design, refactors, paper outlines, proposal structure, data-pipeline redesigns, multi-sta…
Blast radius is large -- multiple files, cross-cutting concerns, shared state, multiple stakeholders, or the organizing structure of a deliverable.Irreversible once executed -- publishes, submissions, deployments, immutable packages, paper submissions, external commitments.History shows a pattern -- "got the structure wrong, redo next cycle" has happened on this track before. - 02
Process
1. Write the plan to a scratch file PLAN-.md in the most natural location for the task (repo root for code, paper-repo root for Overleaf-style docs, a local scratch directory beside the deliverable for tasks that do not live in git). If the plan lands inside a git worktree, add…
Write the plan to a scratch file PLAN-.md in the most natural location for the task (repo root for code, paper-repo root for Overleaf-style docs, a local scratch directory beside the deliverable for tasks that do not li…Content varies by task but at minimum include: purpose, non-goals, structure, regression or failure analysis, validation plan, open questions. Keep it terse -- 1 to 3 pages.Send the plan through a plan-review prompt (not the staged-change template). Make clear this is a pre-execution design review and that the plan file path or pasted contents are what the reviewer should read; instruct th… - 03
Adversarial scope challenge (mandatory in plan-review)
Plan-review must be adversarial about plan purpose and shape, not about low-probability edge cases. The single biggest plan-review failure mode in this maintainer's history was not "the plan had a bug" — it was "the plan's scope was over-conservative, deferring user value across…
Conservative scope (v0.5.7 = ref bump only; defer compact to v0.6.0) → the user's real projects would have stayed on large AGENTS.md files for another release cycle. The apparent product ask was a one-line bundled manif…Conservative deferrals also defer the validation that proves the next-step works in real consumers, so the next release inherits the same uncertainty plus a longer review chain.Why this exact scope? What user pain (or user opportunity) does THIS scope close? Could a strictly smaller scope close most of it? Could a marginally larger scope close all of it for low marginal cost? - 04
Pre-Review Checks (optional)
Before sending staged changes for review, run automated checks that catch mechanical issues locally. This lets reviewers focus on content and judgment calls instead of issues a script could find. Skip this phase if the user says to proceed directly, or if the project has no rele…
Before sending staged changes for review, run automated checks that catch mechanical issues locally. This lets reviewers focus on content and judgment calls instead of issues a script could find. Skip this phase if the…Report any findings to the user before proceeding to Phase 1. Findings here do not go to the reviewer; fix them locally first. - 05
Phase 1: Prepare and Send Review
Inspect the file extensions in the staged diff to classify the change:
Summary -- one to three sentences on what changed and why.Diff scope -- choose the exact diff command before assembling the prompt, and list the changed files. If every staged path is in scope, use git diff --cached. If staging is broader than the review scope, use git diff --…Splitting the round -- use a single pass by default. Split only when no shared contract crosses the boundary; keep mirrored platform files, a script and its tests, and a source and its generated or vendored copies insid…
Permission review
Static risk signals and limitations
Reads files
The documentation asks the agent to read local files, directories, or repositories.
*Plan-review is a Phase 0 before the staged-change loop below.** If the user asks for a plan review, or if the task clearly meets the signals below, do not apply the staged-change prerequisite in Phase 1 yet. Tell the reviewer to read the pWrites files
The documentation asks the agent to create, modify, or delete local files.
Write the plan to a scratch file `PLAN-<identifier>.md` in the most natural location for the task (repo root for code, paper-repo root for Overleaf-style docs, a local scratch directory beside the deliverable for tasks that do not live in gWrites files
The documentation asks the agent to create, modify, or delete local files.
After the work ships or is submitted, delete the PLAN file.Runs scripts
The documentation asks the agent to run terminal commands or scripts.
The primary Auto-terminal dispatch preserves the byte-identical prompt invariant with Terminal-relay: the assembled prompt bytes are the same regardless of channel. The extra `-c developer_instructions=...` value is a Codex CLI configuratioReads files
The documentation asks the agent to read local files, directories, or repositories.
The primary Auto-terminal dispatch preserves the byte-identical prompt invariant with Terminal-relay: the assembled prompt bytes are the same regardless of channel. The extra `-c developer_instructions=...` value is a Codex CLI configuratioRuns scripts
The documentation asks the agent to run terminal commands or scripts.
*Embedded-diff retry for Codex tool-sandbox failure (sandbox-strict environments only)**: With the default `--sandbox danger-full-access` Codex can inspect the repo directly and this retry path should never fire. The retry exists as a defenNetwork access
The documentation includes network, browsing, or remote request actions.
**Trust posture**: a narrow allow-list -- `--allow-tool=read`, `--allow-tool=write`, `--allow-tool='shell(git:*)'`, plus `--add-dir <repo>`, scoped to the repo. This is tighter than the Codex backend's `danger-full-access`: Copilot may readEvidence record
Why each signal appears
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 91/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 239 | Source | Repository attention, not individual Skill quality |
| Compatibility | 1 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Provenance and original SKILL.md
- Repository
- yzhao062/anywhere-agents
- Skill path
- skills/implement-review/SKILL.md
- Commit
- 753d0c47afe1a6e77b21bc682adc6ff8b7c7337e
- License
- Apache-2.0
- Collected
- 2026-08-25
- Default branch
- main
View the original SKILL.md
Implement-Review
Overview
A review loop for staged changes. Claude Code detects the content type, sends the changes to one or more reviewers, categorizes the feedback, revises, and iterates. Codex is the primary reviewer via three channels: terminal relay (manual copy-paste, default on every platform), Auto-terminal (opt-in codex exec subprocess dispatch), or IDE plugin. Other reviewers (Copilot, Gemini, Claude Code, etc.) are driven ad-hoc by the user through their own UI and only need to honor the Review-<AgentName>.md save contract defined in Phase 1c. Cross-vendor exception: when Claude Code is unavailable and Codex (or the user) is the primary implementer, the Auto-terminal channel can dispatch GitHub Copilot CLI as the reviewer through a parallel dispatch-copilot backend (opt-in; see Codex Channels > Auto-terminal Copilot backend). Bare /implement-review auto is unchanged and still selects Codex.
When to plan-review first
Any complex task benefits from a plan review BEFORE execution, not only writing or code. Plan-first catches architectural holes while they are still cheap to fix. The scope includes: system design, refactors, paper outlines, proposal structure, data-pipeline redesigns, multi-stage debugging strategies, teaching / curriculum planning, release-process changes, migration plans, and anything else where the shape of the work precedes and constrains the execution.
Plan-review is a Phase 0 before the staged-change loop below. If the user asks for a plan review, or if the task clearly meets the signals below, do not apply the staged-change prerequisite in Phase 1 yet. Tell the reviewer to read the plan file directly (or paste the plan contents via the terminal path when the reviewer cannot access the file) and critique the design, not git diff --cached. After the plan has no High findings and no new design blockers, execute the work and resume the normal staged-output review flow at Prerequisites / Phase 1.
When to plan-first
Signals that the round-trip pays off:
- Blast radius is large -- multiple files, cross-cutting concerns, shared state, multiple stakeholders, or the organizing structure of a deliverable.
- Irreversible once executed -- publishes, submissions, deployments, immutable packages, paper submissions, external commitments.
- History shows a pattern -- "got the structure wrong, redo next cycle" has happened on this track before.
- Uncertainty in the approach -- the user is weighing alternatives and wants the design validated, not the execution reviewed.
- Context is unfamiliar -- new codebase, domain, audience, agency, collaborator workflow, or external constraint set, where a wrong assumption can shape the rest of the work.
When to skip plan-first
- Change is small, local, reversible.
- The design is already worked out and only execution feedback is wanted.
- Plan and execution would be the same artifact (three-line bug fix, one-sentence footnote).
Process
- Write the plan to a scratch file
PLAN-<identifier>.mdin the most natural location for the task (repo root for code, paper-repo root for Overleaf-style docs, a local scratch directory beside the deliverable for tasks that do not live in git). If the plan lands inside a git worktree, add it to.git/info/excludesogit add -Adoes not accidentally stage it; outside git, keep it as a clearly named scratch file outside the final deliverable and delete it after review. - Content varies by task but at minimum include: purpose, non-goals, structure, regression or failure analysis, validation plan, open questions. Keep it terse -- 1 to 3 pages.
- Send the plan through a plan-review prompt (not the staged-change template). Make clear this is a pre-execution design review and that the plan file path or pasted contents are what the reviewer should read; instruct the reviewer to critique the design rather than to run
git diff --cached. Use the normal "Save your complete review to Review-.md" save-contract from Phase 1c. - Reviewer must answer the scope-challenge questions (see "Adversarial scope challenge" below) before any in-scope correctness review.
- Iterate until the review has no High findings and no new design blockers.
- Then execute (code, draft, revise, deploy).
- Run the normal review cycle on the staged output. It is typically smaller because the architecture was already validated.
- After the work ships or is submitted, delete the PLAN file.
Adversarial scope challenge (mandatory in plan-review)
Plan-review must be adversarial about plan purpose and shape, not about low-probability edge cases. The single biggest plan-review failure mode in this maintainer's history was not "the plan had a bug" — it was "the plan's scope was over-conservative, deferring user value across an extra release cycle worth of process tax." Examples:
- Conservative scope (
v0.5.7 = ref bump only; defer compact to v0.6.0) → the user's real projects would have stayed on largeAGENTS.mdfiles for another release cycle. The apparent product ask was a one-line bundled manifest flip, but existing-consumer delivery also required bundled-default drift detection in aa plus real-project upgrade tests. The scope challenge should force reviewers to price both parts: user value now, and the smallest code path that actually delivers it. - Conservative deferrals also defer the validation that proves the next-step works in real consumers, so the next release inherits the same uncertainty plus a longer review chain.
The plan-review prompt must instruct the reviewer to take an explicit position on:
- Why this exact scope? What user pain (or user opportunity) does THIS scope close? Could a strictly smaller scope close most of it? Could a marginally larger scope close all of it for low marginal cost?
- Are deferrals justified? Every "out of scope / deferred to vNext" carries process tax: another full plan-review + implement + execution-review + CI + publish cycle. Quantify the deferral. If the deferred axis is 1 line of code and the user pain is real, the deferral is probably wrong.
- Is this plan the simplest path? Are there simpler approaches the plan didn't consider — including doing nothing if the user pain is hypothetical?
Plan-review must not default to "no blocker, ready to implement" on the first round when scope is multi-axis or when the plan defers a user-facing axis. The reviewer must either raise a scope challenge OR explicitly state why the scope is calibrated. Skipping the explicit position on these three questions counts as an incomplete review.
Anti-patterns the reviewer must NOT pursue:
- Edge-case fishing: "what if user has unusual config Y?" — only matters when realistic probability × impact > review cost.
- Process ritual: "should this also do Z?" without grounding in user pain or opportunity.
- Adversarial-for-its-own-sake: rejecting plans whose scope IS calibrated, or proposing scope expansion that adds cost without proportional user benefit.
The Phase 1c prompt template Scope-challenge focus: line below carries this contract into every plan-review send.
Illustrative examples (not exhaustive; the category is less important than the pattern)
- System / code: hook or infra design, cross-cutting refactor, state-file schema, cross-platform behavior, release runbook revisions.
- Research output: paper outline with specific aims, contribution claims before methods is written, figure-placement vs argument flow, reviewer response strategy, experiment design across multiple methods, ablation plan.
- Proposal: full outline (aims alignment with merit-review criteria), budget-narrative coupling, broader-impacts framing.
- Operational: migration plan, incident-response playbook, data-pipeline redesign.
- Administrative / teaching: course syllabus structure, lab policy document, committee process design.
The point is not which category -- it is whether the shape of the work precedes and constrains the execution.
Empirical note
In the agent-config 0.1.9 release cycle, two plan-review rounds caught a High-severity design flaw before implementation. The later execution-review rounds were limited to documentation and test polish, avoiding a likely post-ship hotfix.
Codex Channels
Three paths to Codex are supported. Default is Terminal-relay (manual copy-paste). Auto-terminal (codex exec subprocess) is opt-in via the trigger rules in Path selection below. Plugin is user-initiated. The skill picks the channel based on those rules.
Terminal path (default)
The user has a Codex interactive terminal window open alongside Claude Code. Claude Code prepares a copy-pasteable review prompt (summary, diff, lens, round number) and presents it as a fenced text block. The user copies it into the Codex terminal, then relays the feedback back to Claude Code.
Auto-terminal path (opt-in, codex exec subprocess)
When the user opts in via the trigger rules in Path selection below, Claude Code dispatches Codex via codex exec --sandbox danger-full-access as a background subprocess (Bash on POSIX, a transient <state-dir>/run-codex.cmd helper invoked through cmd /c on Windows; see the Script contract invariants subsection for the rationale). The dispatch script writes the prompt to a per-dispatch temp file under %TEMP% / $TMPDIR, feeds it on stdin (codex exec -), and emits a state-dir path to stdout for Phase 2 to consume. Codex writes its review to Review-Codex.md per the save contract; the same Phase 1d auto-watch fires on file appearance.
Trust model and the sandbox flag: Auto-terminal aligns its trust model with Terminal-relay by passing --sandbox danger-full-access to codex exec. In Terminal-relay the user is typing into their own Codex window with full fs / network / shell access; in Auto-terminal Claude Code starts the same Codex on the user's behalf, so granting the same access keeps the two channels behaviorally equivalent. The sandbox flag is also a hard requirement for the channel to work on Windows: Codex 0.130.0's default workspace-write sandbox runner hits CreateProcessAsUserW failed: 1312 when Codex spawns its own git / grep / pwsh subprocesses, which makes the review come back as "could not access files" and surfaces through Phase 2.0 Check 7 / 8 / Substance-2 as a tool-sandbox failure. Scope discipline (review-only, save findings to Review-Codex.md, no commits / pushes / branch operations) is enforced at the prompt level, identical to how Terminal-relay enforces it. For CI / shared / multi-tenant environments where this trust posture is too broad, set CODEX_DISPATCH_SANDBOX to a stricter mode (workspace-write / read-only); the dispatch script honors the env var.
The primary Auto-terminal dispatch preserves the byte-identical prompt invariant with Terminal-relay: the assembled prompt bytes are the same regardless of channel. The extra -c developer_instructions=... value is a Codex CLI configuration argument, separate from the review prompt on stdin, so it does not change those bytes. The dispatch script must NOT call codex exec review, codex exec review --uncommitted, or any other Codex exec subcommand, because those carry Codex's own built-in review prompt template which would compete with the skill's lens-aware prompts. The embedded-diff retry described below is the explicit exception: it is used only after a health-checked Auto-terminal run shows that Codex's own shell tool cannot inspect the repo, usually because CODEX_DISPATCH_SANDBOX has been narrowed in a CI / sandbox-strict environment, but also for the same class of failure if a future Codex version regresses under the relaxed default sandbox.
The Auto-terminal path requires codex on PATH. Probe before dispatch; if absent, warn and downgrade to Terminal-relay for the round. On non-zero codex exec exit, timeout, or stdin-pipe failure (rare on Windows with PowerShell quirks or Bitdefender input-stream interception), downgrade to Terminal-relay for that round; do NOT add a truncated positional-argument fallback, which would break the prompt invariant. Sticky downgrade applies session-wide once Auto-terminal fails: subsequent rounds default to Terminal-relay until the user re-opts-in explicitly.
Auto-terminal has no incremental-checkpoint guarantee. The save contract requires a complete per-round review published atomically, but it does not require intermediate checkpoints. The Codex dispatcher snapshots the prior review mtime and propagates codex exec's exit code, and it does not validate that a fresh review was published. A child that exits 0 without saving therefore leaves <state-dir>/tail and no fresh review, which Phase 2 health checks 1 through 3 reject as missing, stale, or wrong-round. That rejection costs a full Codex run.
Configuration boundary: the dispatched Codex does NOT inherit the user's config.toml. Under the default MCP isolation, the dispatch script passes --ignore-user-config and re-passes -c model_reasoning_effort=$CODEX_DISPATCH_REASONING (default xhigh). Independently of that isolation choice, every dispatch passes a separate -c developer_instructions=... argument telling the child reviewer to skip bootstrap and shared configuration refresh commands and to use the configuration already on disk. The child still reads and follows AGENTS.md; all other project instructions, including the agent-style banned-word list and any NSF rules, remain in force. Everything else in ~/.codex/config.toml is dropped for the dispatched run: model (so the review runs on Codex's built-in default model, not the user's configured one), service_tier, [features].fast_mode, and any custom provider settings. This is a deliberate consequence of the MCP-isolation fix, not an oversight, but it is easy to misread: a user who has tuned config.toml for maximum reasoning will find that none of it reaches their reviews, and the only user-controlled config knob that does is CODEX_DISPATCH_REASONING. To raise the dispatched reasoning effort, set that variable rather than editing config.toml. To hand the dispatched run the full user config instead, set CODEX_DISPATCH_ISOLATE_MCP=off, which is the documented opt-out and also restores the user's MCP servers and plugins.
Reasoning effort is a one-way ratchet: xhigh is the floor, not a target. The dispatching agent may raise a single round to max by passing CODEX_DISPATCH_REASONING=max on that dispatch when it judges the change under review hard enough to earn deeper reasoning: changes that span mirrored copies of one file, touch caching or state lifetime, or would fail silently rather than loudly. It must never pass a value below xhigh. Raising the tier is not free: it roughly doubles wall-clock, so raise the dispatch timeout in the same step, or the round is killed before it writes anything. The asymmetry is deliberate. An agent choosing how hard to review its own work creates a self-grading loop, and its confidence is highest exactly where a quiet error hides. Its discretion therefore runs upward only, so the worst case is a round that was not deepened rather than one that was weakened.
Depth against another round: when the budget would buy either one deeper round or two at the floor, prefer another round while the artifact is still changing. The later round reads the revised state and carries the prior findings with it, so its budget is spent on what the last round actually produced. Raise the tier for the closing round, or when the change is subtle enough that a first read is unlikely to reach it. The relative yield of the two has not been measured, so treat this as a default rather than a finding.
Python interpreter resolution and the verification contract: Before it creates dispatch state or spends a Codex round, dispatch-codex finds a working Python interpreter in this order: ANYWHERE_AGENTS_PYTHON; project .venv or venv; the activated VIRTUAL_ENV; active and discovered conda or Miniforge roots and environments; py -3; then every python3 and python entry on PATH. A configured but broken ANYWHERE_AGENTS_PYTHON is a hard preflight failure. Every candidate must run an isolated probe, return an absolute sys.executable, pass the nonempty-file and non-WindowsApps checks, and execute successfully again through the resolved path. The dispatcher writes the absolute path to <state-dir>/python-interpreter and includes it in the child developer_instructions; the reviewer must use that exact path for Python commands. Resolving nothing at all is a degradation rather than a dispatch failure: the dispatcher warns on stderr, omits the marker file so its absence is unambiguous, tells the reviewer that no interpreter was pre-resolved, and proceeds. The probe exists to keep a reviewer from claiming verification it never ran, and check 10 enforces that independently by refusing a PASS or BLOCK verdict without a VERIFIED status. Reviews also run on repositories whose verification is not Python at all, so a missing interpreter must not make those repositories unreviewable.
PowerShell 7 (pwsh) resolution: The probe enumerates PATH only because Codex's tool router shells out to pwsh by name. It rejects a candidate when its path contains WindowsApps or when the file has zero length. This is a structural check rather than an execution probe because a Microsoft Store App Execution Alias succeeds from an interactive shell and fails only under the dispatched spawn context, where it dies with NTSTATUS 0xC0000142 (-1073741502) in about 30 ms and is retried indefinitely. The dispatcher writes a resolved absolute path to <state-dir>/pwsh-interpreter and names it in the child developer_instructions. Finding nothing is a soft degradation that tells the reviewer to prefer bash, Windows PowerShell 5.1 (powershell.exe), or plain git, as it does for a missing Python interpreter. The Copilot and Claude reviewer backends pass no developer instructions today, so they carry neither the Python nor the pwsh probe; extension to those backends is deferred.
Every saved review must include one standalone Verification status: VERIFIED or Verification status: UNVERIFIED line. VERIFIED is permitted only after at least one relevant verification command completed, and Verification notes must list the exact commands and outcomes. A run with no completed verification uses Verification status: UNVERIFIED together with Commit verdict: UNVERIFIED; it cannot issue PASS or BLOCK. Health check 10 rejects an UNVERIFIED status or verdict, a PASS or BLOCK verdict without VERIFIED, conflicting markers, and VERIFIED paired with notes that explicitly report no execution. A caller can therefore distinguish an execution-backed block from an unsupported one: PASS check-10 verdict=BLOCK verification=VERIFIED plus concrete command outcomes is admissible; FAIL check-10 verdict=BLOCK verification=MISSING or FAIL check-10 verdict=BLOCK verification=UNVERIFIED is a hard intake failure. Review formats that give no commit verdict remain backward compatible in the health check.
Embedded-diff retry for Codex tool-sandbox failure (sandbox-strict environments only): With the default --sandbox danger-full-access Codex can inspect the repo directly and this retry path should never fire. The retry exists as a defensive fallback for two cases: (1) CODEX_DISPATCH_SANDBOX has been narrowed to workspace-write or read-only in a CI / shared environment, and Codex hits windows sandbox: runner error: CreateProcessAsUserW failed: 1312 or a similar internal sandbox error; (2) some future Codex version regresses the same class of failure under the relaxed sandbox. Symptom: dispatch exits 0 and Review-Codex.md is fresh, but the review body says Codex could not run git diff --cached or inspect files; Phase 2.0 flags this through Check 7, Check 8, or Substance heuristics. Procedure: retry Auto-terminal once with an embedded-diff prompt before downgrading to Terminal-relay. Generate the diff from Claude Code's shell by running the exact diff command chosen in Phase 1b, and include it after the normal save contract, summary, lens, focus, and prior findings. Mark the round line with this content: Round N (RETRY: codex-exec sandbox blocked tool access; diff is embedded inline below.) Then add this sentence: Do NOT run git diff or any shell command -- use the embedded diff as the source of truth. The retry may be larger than the primary prompt; keep it limited to the Phase 1b in-scope paths and do not include unrelated staged or working-tree content. Run the same dispatch, auto-watch, and health-check sequence on the retry. Important quality caveat: the retry sees only the embedded diff hunks, not the surrounding file context. Treat retry findings as diff-scoped — they are reliable for hunk-self-contained issues (test coverage gaps, naming, in-hunk regressions) but prone to false positives for claims that depend on non-diff code (e.g., a "this is missing X" finding when X actually exists elsewhere in the file). Because of this elevated false-positive rate, Medium findings from a retry-channel review are subject to mandatory Phase 2.5 verification before being applied (see Phase 2.5 trigger). If the retry produces a usable review, proceed with that review under the Medium-verify discipline; if it also fails or only records blocked verification, downgrade to Terminal-relay.
Script presence is also required: if any of the dispatch-codex / health-check / stall-watch scripts for the current platform is missing (e.g., Phase B has not landed yet in a given checkout), this path is documented-only — Phase 1c automatically downgrades to Terminal-relay without setting sticky downgrade, because the absence is design state, not a runtime failure. See the "Auto-terminal path (opt-in)" subsection in Phase 1c for the script-presence probe specifics.
Auto-terminal Copilot backend (cross-vendor reviewer, opt-in)
The Auto-terminal channel has a second dispatch backend that runs GitHub Copilot CLI as the reviewer instead of codex exec. It exists for the agent-fungibility case in AGENTS.md § "Agent Fungibility": when Claude Code is unavailable and Codex (or the user) is the primary implementer, Codex cannot review its own work and Claude is absent, so Copilot is the reviewer. It is opt-in only via the triggers in Path selection below; a bare /implement-review auto still selects Codex.
The backend is a drop-in. Apply the entire Auto-terminal path (opt-in) mechanics below — script-presence probe, prompt assembly, dispatch invocation, STATE-DIR capture, Phase 1d auto-watch, the Phase 2.0 Health checks, Substance heuristics, and Phase 1d coordination — with two substitutions and one probe swap:
dispatch-codex.{ps1,sh}→dispatch-copilot.{ps1,sh}- expected review file
Review-Codex.md→Review-GitHub-Copilot.md - the
codexPATH probe → acopilotPATH probe (falling back togh copilot)
Everything else is reviewer-agnostic: the STATE-DIR contract, the flags passed to health-check and to await-review (--state-dir, --round, --review-file Review-GitHub-Copilot.md), the stopped-task resolution rule, the silent-advance gating, and the downgrade / sticky-downgrade rules are identical. The save contract already normalizes GitHub Copilot → Review-GitHub-Copilot.md (Phase 1c), so Phase 2 intake needs no change.
Copilot-specific dispatch details, all handled inside dispatch-copilot (no caller change):
- Deployed-script release: Before argument parsing, preflight, or reviewer work,
dispatch-copilotre-executes from a private temp copy. It uses the sharedIMPLEMENT_REVIEW_DISPATCH_REEXECsentinel andIMPLEMENT_REVIEW_DISPATCH_SOURCE_DIRsource-directory handoff, removes the copy after exit, and propagates the child status. Preflight and the main run still resolvestall-watchfrom the deployed source directory. - Prompt delivery: the assembled prompt (byte-identical to the Terminal-relay block) is written to a temp file and passed as
-p "@<prompt-file>"; Copilot reads the file as its prompt. A long literal-pargument fails, so the file reference is mandatory -- this replaces Codex'sexec -stdin feed. - Binary resolution: prefer standalone
copilot; fall back togh copilotwhencopilotis not on PATH. Override withCOPILOT_BIN/GH_BIN. - Trust posture: a narrow allow-list --
--allow-tool=read,--allow-tool=write,--allow-tool='shell(git:*)', plus--add-dir <repo>, scoped to the repo. This is tighter than the Codex backend'sdanger-full-access: Copilot may read files, run git, and write its review, nothing more. It also stays offline: the Copilot CLI gates URLs only through an all-or-nothingurl()permission (a scoped allow-list cannot anticipate which citation or documentation domains a reviewer needs), so for this auto-launched fallback the URL grant is withheld and--no-ask-userdenies any un-granted fetch. The Working-method web-verification line is therefore a no-op on the Copilot backend; the Codex backend (network viadanger-full-access) and the Claude backend (built-inWebSearch/WebFetch) carry web verification instead. Copilot writesReview-GitHub-Copilot.mditself per the prompt's save contract, exactly as Codex writesReview-Codex.md. - Pager:
GIT_PAGER=catis set so Copilot's owngit diffdoes not stall on a pager. - Auth preflight: With the official CLI and the default
COPILOT_PREFLIGHT=auto, each dispatch first sends a small live prompt that runsgit --versionand must returnCOPILOT_PREFLIGHT_OKbefore the full review starts. This checks the stored credential, network path, JSON stream, and git-shell permission. It costs one small Copilot request per dispatch because Copilot CLI 1.0.78 exposes no non-interactive auth-status command.COPILOT_PREFLIGHT=forceapplies the same check to a wrapper;COPILOT_PREFLIGHT=offskips it. - Non-interactive stream:
--no-ask-user --no-auto-update --stream on --output-format json --no-colorkeep the run unattended and expose live tool events tostall-watchand postflight.--no-auto-updateprevents an in-flight CLI self-update. - Postflight: For official CLI runs, and wrappers checked with
COPILOT_PREFLIGHT=force, a tool permission denial or known authentication or shell-runner failure rejects the review with exit 70. A nominally successful run also exits 70 unless the expected review file exists, is at least 500 bytes, starts with the exact<!-- Round N -->marker, and has an mtime strictly newer than both dispatch start and any pre-dispatch copy.
With read + git access Copilot inspects the repo directly, so there is no embedded-diff retry unique to Copilot; the same Phase 2.0 checks apply with the review-file name swapped.
Auto-terminal Claude backend (cross-vendor reviewer, opt-in)
A second cross-vendor backend mirrors the Copilot one with the reviewer swapped: Codex (or the user) implements, headless Claude Code (claude -p) reviews. Use when Claude is preferred as the reviewer voice, the human orchestrator runs Codex as the primary implementer, or fungibility scenarios where Codex cannot self-review and Copilot is absent. The Claude backend is opt-in only: a bare auto / cli token still selects Codex.
Self-review guard (mechanical). Path selection treats the invoking runtime as authoritative. When this skill is running inside Claude Code, the orchestrator is claude; /implement-review auto claude is rewritten to Codex (or Copilot if Codex is unavailable on PATH) BEFORE any dispatch-claude script is launched, with one user-visible line: Claude backend skipped: Claude Code cannot review its own implementation; using <backend> instead.
The script-level guard in dispatch-claude.{sh,ps1} enforces the same refusal for direct callers that bypass SKILL.md path selection. The scripts exit 2 with the message dispatch-claude: refusing to dispatch (orchestrator=claude; self-review) when ANY of these holds:
IMPLEMENT_REVIEW_ORCHESTRATOR=claude(case-insensitive), ORIMPLEMENT_REVIEW_ORCHESTRATORis unset/empty ANDCLAUDECODE=1(Claude Code's documented subprocess marker, set in Bash / PowerShell / hook / tmux / status-line subprocesses).
IMPLEMENT_REVIEW_ORCHESTRATOR=codex and IMPLEMENT_REVIEW_ORCHESTRATOR=user proceed regardless of CLAUDECODE. The CLAUDECODE=1 fall-through exists so a direct script launch from a Claude Code session without setting IMPLEMENT_REVIEW_ORCHESTRATOR does not bypass the guard. The path-selection rewrite + script-level env exit together make the refusal mechanical at both layers; prose alone is not enforceable.
Dispatch detail mirrors the Copilot backend with a relay-save variant:
- Probe:
claudeon PATH (override viaCLAUDE_BIN); no fallback binary. - Deployed-script release: Before it creates dispatch state or starts a preflight,
dispatch-claudere-executes from a private temp copy.IMPLEMENT_REVIEW_DISPATCH_REEXECprevents a loop, andIMPLEMENT_REVIEW_DISPATCH_SOURCE_DIRretains sibling-script lookup at the deployed source directory. The wrapper removes the copy and propagates the child exit status. - No-model preflight:
CLAUDE_PREFLIGHT=auto(the default) runsclaude auth status --jsonfor the official CLI and skips opaque wrappers. API-key, gateway, Bedrock, Vertex, Foundry, and bare modes useclaude --versionas an availability probe because first-party login state does not describe those credentials.forceapplies the probe and strict postflight checks to a wrapper;offskips the probe.CLAUDE_PREFLIGHT_TIMEOUT_SECONDSsets the positive-integer timeout, default 60 seconds. A rejected preflight exits 70, or 124 on timeout, before a model request is sent. - Invocation:
claude -p --permission-mode bypassPermissions --tools "Read,Bash,WebSearch,WebFetch" --add-dir <staged-snapshot> --setting-sources project,local --strict-mcp-config --mcp-config <state-dir>/empty-mcp-config.json --output-format text. The empty MCP config is required for cross-agent review: a user-level Codex MCP server must not auto-start inside the Claude reviewer backend, or the reviewer can recurse into Codex and hang with empty output. Excluding user settings also keeps user-level hooks out of the headless review path.CLAUDE_DISPATCH_BARE=1may opt into--bareonly in environments that provideANTHROPIC_API_KEYor an explicitapiKeyHelper; do not enable it by default because Claude Code 2.1.153 disables OAuth and keychain auth in bare mode. No--sandboxflag (Codex-only). The long prompt is fed via stdin (POSIX redirection; PowerShellProcessStartInfo.RedirectStandardInput, avoiding ARG_MAX), butdispatch-claudefirst wraps it in a relay prompt. This embedded diff covers every staged path, because the dispatcher has no scope argument; use the Claude backend only when the entire staged set is in scope. The dispatcher exports the Git index to<state-dir>/staged-snapshotwithgit checkout-index -aand launches Claude from that directory; if export fails or the directory is not a git worktree, it falls back to the original working directory and records the reason ingit-diff.stderr. The relay prompt tells Claude not to use Write/Edit tools, permits Bash verification commands in the current directory, appends a dispatcher-providedgit diff --cached --no-ext-diff, and asks Claude to return the complete review as its final answer. The dispatcher writes Claude stdout toReview-Claude-Code.md; stderr remains in<state-dir>/tail.stderr-tmpfor diagnostics. On save, the dispatcher trims any preface before<!-- Round N -->; if Claude omitted the marker, the dispatcher inserts it so Phase 2 intake has a stable first line. This is intentional: live probes showed current Claude Code can hang under unattendeddontAskwhen given path-scopedWrite(...)or exactBash(...)preapproval patterns on Windows, whilebypassPermissionswith--tools Read,Bash,WebSearch,WebFetchlets Claude run tests and verify external facts without exposing Write/Edit tools. The addedWebSearch/WebFetchare Claude Code built-in tools, not MCP tools, so--strict-mcp-configplus the empty MCP config still keeps a user-level Codex MCP server out of the reviewer; the relay prompt also forbids network shell commands (curl/wget) so network access stays scoped to the two built-in tools. Do not re-add Write/Edit or--allowedToolsBash patterns unless a live probe and contract test cover the exact CLI version and platform. PowerShell side note:dispatch-claude.ps1decomposes its self-review env-check into a sibling_claude_guard.ps1helper alongside it. Some Windows AV products (e.g., Bitdefender) score the combination of env-check + stderr-write + non-zero exit + cmdBody construction in a single.ps1as a malicious-orchestration signature and AMSI-block the file at parse time. Splitting the guard into a tiny helper file decouples the two patterns and clears the block on a typical Bitdefender install.dispatch-claude.shkeeps the guard inline because POSIX AV scanners do not have the same heuristic. - Live tails and transport rejection: stdout and stderr flow into
<state-dir>/tailand<state-dir>/tail.stderr-tmpwhile Claude is running, sostall-watchsees liveness before process exit. After a nominal exit 0 from an official or forced run, known authentication, API, stream, connection, timeout, rate-limit, and overload errors in stderr write<state-dir>/transport-failure, reject the review, and exit 70. - Atomic publication: Claude stdout stays in the state directory until the process exits successfully. The dispatcher builds and validates a candidate beside the expected review file, then uses a same-directory rename or replacement. Auto-watch therefore sees the old review or the complete new review, never a partially written target.
- Codex stream-death classifier is Codex-specific: It requires a
chatgpt.com/backend-api/codex/responseserror followed by Codex'stokens usedtrailer. Claude's--output-format textstream has no equivalent terminal record, so that immediate classifier was not ported. Claude uses the stderr transport postflight after process exit. The shared watcher still records 600 seconds of silence and performs identity-checked reaping when the dispatcher exits. - Expected review file:
Review-Claude-Code.md. Phase 1c name normalization already mapsClaude CodetoReview-Claude-Code.md; Phase 2 intake needs no change. - No embedded-diff retry. The primary Claude relay already includes the staged diff, so the Codex retry pattern for narrowed sandbox failures is not applicable.
State-dir, stdout contract (STATE-DIR <abs-path> single line), state files (pre-mtime / timestamp / tail / tail.stderr-tmp), and the stall-watch launch match the shared dispatch contract. For Claude, tail growth supplies liveness; the Codex-only terminal suffix is not a Claude completion record.
Plugin path (IDE sidebar)
Codex runs as an IDE plugin with direct access to the repo. The user tells Codex to review in the plugin sidebar (e.g., "review the staged changes"). Codex can see the repository and run the exact diff command chosen in Phase 1b, so no diff needs to be copy-pasted. Plain git diff shows the working tree against the index rather than the staged patch this skill reviews. The user relays Codex's feedback back to Claude Code.
Path selection
- Default: Terminal-relay (manual copy-paste) on every platform. Users who do not opt into another channel get the current Terminal-relay flow without modification.
- User-scoped default override: when the environment variable
IMPLEMENT_REVIEW_DEFAULT_CHANNELis set (case-insensitive) toauto,cli, orauto-terminal, which is the same synonym set the slash args accept, Auto-terminal becomes that user's default and no per-invocation opt-in token is needed. Read the variable once at Phase 1c entry. This is a per-user, per-machine setting; set it in theenvblock of~/.claude/settings.json. It is deliberately not a change to the shipped default: a consumer that does not set it sees today's behavior unchanged, channel line included. Follows theIMPLEMENT_REVIEW_ORCHESTRATORprecedent of a documented, case-insensitive env var read. - When the variable is unset, empty, or holds an unrecognized value, the shipped Terminal-relay default applies and the variable is never treated as an opt-in, so a typo degrades to today's behavior rather than silently selecting a channel the user did not ask for. The three cases differ only in what is reported: unset and empty are fully unchanged, including the channel line, while an unrecognized value keeps the same channel selection and the same dispatch side effects but adds one clause to the channel line naming the value that was ignored. That added clause is the single intentional deviation from pre-W3 output, and it exists because a silently ignored typo would otherwise leave the user believing Auto-terminal is their default when it is not.
- The override changes only which channel is the default. Every rule in item 2 still applies on top of it: manual override tokens still win, the
codexPATH probe and the dispatch-script presence check still run, and a failed probe still warns and downgrades to Terminal-relay for the round.
- User-scoped default override: when the environment variable
- Auto-terminal opt-in triggers, evaluated in detection order at Phase 1c entry:
- Mid-flow override toward manual: "back to manual" / "next round manual" / "use terminal-relay" in the user's most recent message forces Terminal-relay.
- Mid-flow opt-in toward auto: "next round use cli" / "next round auto codex" forces Auto-terminal.
- Slash-arg opt-in:
/implement-review cli,/implement-review auto, and/implement-review auto-terminalare equivalent synonyms;autois the most natural keyword and is accepted. When.claude/commands/implement-review.mdforwards slash arguments throughCommand arguments from the slash invocation: $ARGUMENTS, evaluate that forwarded argument string the same way as the original slash invocation. Manual override tokens still win before Auto-terminal opt-in tokens. - Plain-phrase opt-in in the invoking message: case-insensitive substring match on any of
cli mode,use cli,auto codex,use codex exec, AND no negation word (do not,don't,no,not,avoid,manual) within 4 words before the matched phrase. - Reviewer-backend selection (Copilot cross-vendor backend, opt-in): when an Auto-terminal opt-in ALSO names Copilot, the backend is GitHub Copilot instead of
codex exec. Triggers: slash args/implement-review auto copilot,/implement-review copilot auto, or/implement-review copilottogether with anauto/clitoken; plain phrasesuse copilot as reviewer,copilot as reviewer,auto copilot,review with copilot, under the same negation guard; and role-reversal wording naming Codex as the implementer and Copilot as the reviewer. A bareauto/cliopt-in with no Copilot token selects Codex, unchanged. When Copilot is the backend, dispatch usesdispatch-copilot.{ps1,sh}and the expected review file isReview-GitHub-Copilot.md(see Auto-terminal Copilot backend above). - Reviewer-backend selection (Claude, with mechanical self-review guard): select
dispatch-claudeonly when BOTH of the following hold: (1) the slash args includeclaudetogether with anauto/clitoken (e.g.,/implement-review auto claude,/implement-review claude auto,/implement-review claudewith anauto/clicontext), OR a plain phrase matches the patternsuse claude as reviewer,claude as reviewer,review with claude, or role-reversal wording naming Codex as implementer and Claude as reviewer, all under the same negation guard on the line above; AND (2) the orchestrator running this skill is NOT Claude Code. Bareauto/cliwith noclaude/copilottoken still selects Codex. Orchestrator detection keys on a single documented signal: when this skill is interpreted by Claude Code, the orchestrator isclaudeby definition (the skill is running INSIDE the CC session). The script-level dispatch guard separately checksCLAUDECODE=1so a script launched as a Bash / PowerShell subprocess from a CC session also detects it. When orchestrator isclaudeand the slash args / phrase ask for the Claude backend, rewrite the selection to Codex (or Copilot if Codex is unavailable on PATH) BEFORE any dispatch script is launched, and emit one user-visible line:Claude backend skipped: Claude Code cannot review its own implementation; using <backend> instead.Pair this with the script-levelIMPLEMENT_REVIEW_ORCHESTRATOR/CLAUDECODE=1exit-2 indispatch-claude.{sh,ps1}so direct callers that bypass path-selection cannot self-dispatch either. The script-level test covers the four enforceable cases intests/test_dispatch_claude.py::_DispatchContractMixinguard methods; the path-selection rewrite itself is prose-level (no parser / selector function exists to call), so its verification is the negative live test in Task 4.7, not a unit test. Dispatch usesdispatch-claude.{ps1,sh}and the expected review file isReview-Claude-Code.md.
- Plugin path is available on every platform when the user initiates it (e.g., "use the plugin") but is never a default. The user can override at any time (e.g., "use the plugin", "use the terminal").
- MCP forward-compat slot: when an MCP-based Codex channel is later added (currently out of scope), it follows the same trigger pattern:
/implement-review mcpslash arg + analogous plain phrases (use mcp,mcp mode) under the same negation guard. The trigger UX is a single extensible mechanism across all channels.
Emit one line at Phase 1c entry stating which channel was picked and why (e.g., Channel: Auto-terminal (triggered by "/implement-review auto"; codex on PATH at C:\...\codex.cmd)), so the user can immediately override if it picked wrong. When the channel came from the user-scoped default rather than a per-invocation token, name the variable as the reason, e.g. Channel: Auto-terminal (IMPLEMENT_REVIEW_DEFAULT_CHANNEL=auto; codex on PATH at C:\...\codex.cmd). When the variable held an unrecognized value, say so and state that the shipped default applied, e.g. Channel: Terminal-relay (IMPLEMENT_REVIEW_DEFAULT_CHANNEL="plugin" not recognized; shipped default applied). Naming the source matters because a user-scoped default is invisible at the call site: without it, a user who set the variable months ago cannot tell why a round dispatched itself.
Prerequisites
Begin each run by showing the cross-agent usage snapshot, so the quota situation is visible at this run (Codex has no statusLine, so an implement-review run is where a Codex-primary session surfaces it). Invoke agent-quota with a real Python interpreter matched to your shell. Do not execute the bare ~/.claude/agent-quota.py path (it hits the Windows Store launcher shim), and do not call the extensionless ~/.claude/hooks/_python wrapper from PowerShell (it is a Bash script and runs there as a silent no-op). In Bash or Git Bash, use "$HOME/.claude/hooks/_python" "$HOME/.claude/agent-quota.py". In PowerShell, run the script with your project Python directly, for example & <project-python> "$HOME/.claude/agent-quota.py". In either shell you may instead run the repo copy with the project's Python (scripts/agent-quota.py, or .agent-config/repo/scripts/agent-quota.py in a consumer). Show its two-row Claude / Codex · 5h / 7d output. Read the percentages as remaining quota (headroom left), not consumed: a high value such as 93% left means plenty of quota is still available and is not a reason to downgrade the channel or stop the review; only a low remaining figure near 0% left signals real quota pressure. It is a local disk read with no API or token cost (about 0.1s), so it is fine to run every time; if neither the script nor a Python runner is available, skip silently and never block the review on it.
At skill start, check for staged changes (git diff --cached). If nothing is staged but unstaged or untracked changes exist, list them and ask the user whether to stage all (git add -A), stage specific files, or abort. Do not auto-stage without confirmation — untracked files may be sensitive or unrelated. If there are no changes at all, there is nothing to review -- inform the user and stop.
Pre-Review Checks (optional)
Before sending staged changes for review, run automated checks that catch mechanical issues locally. This lets reviewers focus on content and judgment calls instead of issues a script could find. Skip this phase if the user says to proceed directly, or if the project has no relevant tooling.
| Content type | Checks |
|---|---|
| LaTeX paper or proposal | Compile. Scan the log for overfull/underfull box warnings and undefined references. Report counts. |
| Anonymized submission | Grep staged files for author names, GitHub/lab URLs, institutional names, and tool names. Source these from the project's de-anonymization checklist if one exists; otherwise use the git user name, institution domain, and any names in the paper's author metadata or \author{} block. |
| Code | Run the project linter and type checker if configured. |
Prose (.md / .rst / .txt / .tex, or prose-heavy diff) | Run agent-style review --audit-only <staged prose files> if the CLI is on PATH; report deterministic hits with line numbers. The plain CLI reports the semantic rules (including RULE-07 antithesis) as skipped, so also audit the staged prose for those, especially RULE-07 antithesis (not just ... but, it is not ... it is, and clause-level X, not Y): use the style-review host pass when available, otherwise grep those templates. Fix locally before sending to the reviewer. |
Report any findings to the user before proceeding to Phase 1. Findings here do not go to the reviewer; fix them locally first.
Phase 1: Prepare and Send Review
1a. Detect content type
Inspect the file extensions in the staged diff to classify the change:
| Extensions | Content type |
|---|---|
.py, .js, .ts, .go, .rs, .java, .c, .cpp, .h, .sh, .yaml, .json, .toml | code |
.tex, .bib (in a paper or manuscript directory) | paper |
.tex, .bib (in a proposal or grant directory) | proposal |
.md, .rst, .txt (in a proposal or grant directory) | proposal |
| Everything else or mixed | general |
If the diff spans multiple types, pick the dominant one. The user can override by saying, e.g., "review this as a proposal." For proposals, also ask which agency lens to apply (NSF or NIH) since they use different evaluation frameworks.
1b. Build the review context
Prepare a review request with:
- Summary -- one to three sentences on what changed and why.
- Diff scope -- choose the exact diff command before assembling the prompt, and list the changed files. If every staged path is in scope, use
git diff --cached. If staging is broader than the review scope, usegit diff --cached -- <in-scope paths>and list the staged paths that are explicitly out of scope, so the reviewer is not left inferring the boundary. This command applies to Terminal-relay, Plugin, Codex Auto-terminal, and Copilot Auto-terminal. The Claude Auto-terminal backend cannot honour it: its dispatcher embeds a baregit diff --cachedin the relay prompt and has no scope argument, so use that backend only when every staged path is in scope. Path scoping keeps unrelated staged content out of the primary review input before the run; health checks 1 through 3 catch a missing or stale review only after one has been spent. Do not paste the diff inline in the primary prompt; this keeps the prompt compact and avoids bloat across rounds. The only exception is the Auto-terminal embedded-diff retry (a sandbox-strict-environment fallback when Codex's own shell tool cannot read the repo), described in Codex Channels, which must embed the same in-scope diff selected here. - Splitting the round -- use a single pass by default. Split only when no shared contract crosses the boundary; keep mirrored platform files, a script and its tests, and a source and its generated or vendored copies inside one reviewer's scope. Independence is a judgement made before the split, so verify it afterwards rather than assuming it held: re-read the boundary you drew, and run the mechanical checks that apply, such as
scripts/check-parity.sh. See anywhere-agents#41. - Review lens -- the content-type-specific criteria from references/review-lenses.md. If a focused sub-lens or agency-specific lens fits better than the full lens, use it (e.g.,
paper/formattingfor a layout-only change,proposal/nsfwhen the agency is known). See the lens tables in that file. - Additional focus -- specific concerns beyond the generic lens. This is often the highest-value part of the prompt because it catches real bugs that generic criteria miss. Always ask the user explicitly rather than guessing. Recurring project concerns belong here: phased-development coupling, anonymization checks, page-limit compliance, budget-to-narrative consistency, terminology drift, benchmark-claim calibration, overclaim flagging. If there are no project-specific concerns this round, write "none" rather than padding the line. Examples: "check that all appendix URLs are anonymized", "verify Year 3 budget matches the narrative", "flag any overclaim in intro / conclusion", "watch for Phase 1 / Phase 2 coupling issues".
- Round number -- which iteration this is (starting at 1).
- Variant targets (multi-target reviews) -- if the staged files cover two or more variant targets that should be reviewed separately (long + short paper version, narrative + appendix tracker, internal + external report, primary + supplement), list each target by directory or file pattern. Tell the reviewer to review each target in its own top-level section and then add a cross-variant drift check at the end (tables that should match, claims that should be consistent, terminology that should align).
- Round history (rounds 2+ only) -- a one-line-per-finding summary of what prior rounds raised and how each was resolved. Tag each finding as
Resolved,Still open,Deferred,Refuted, orInconclusive. The last two come from the Phase 2.5 verification step (see below); they let the reviewer see when a prior factual claim did not hold up under verification, with a pointer to the evidence so the reviewer can either retract or sharpen the claim. This prevents the reviewer from re-litigating closed decisions and lets them verify that fixes landed instead of re-reviewing from scratch. Example:Prior findings: - DMP listed wrong project name (Resolved — fixed in round 1) - Budget table exceeds page width (Still open) - Consider reordering Section 3 (Deferred — user decision) - Citation [Smith2023] does not exist (Refuted in round 2 — arxiv.org/abs/2023.XXXXX confirms paper) - Compile error in section 4 (Inconclusive in round 2 — could not run latexmk in this env)
1c. Send to reviewer
All review prompts sent to the reviewer (regardless of channel) must include a save instruction at the very top of the prompt, before the summary or diff, so the reviewer sees it first. This lets Claude Code read the feedback directly from the file, and lets the user read or forward it without copy-pasting from chat. The save instruction is:
IMPORTANT: Save your complete review to
Review-<YourAgentName>.mdin the repository root. Normalize<YourAgentName>as follows: choose the stable agent or product name visible to the user (not a transient model/version list unless that is the only identity available); convert any run of whitespace to a single dash; delete every character except ASCII letters, digits, and dashes; collapse repeated dashes; trim leading and trailing dashes. Examples:Codex→Review-Codex.md,GitHub Copilot→Review-GitHub-Copilot.md,Gemini 3.1 Pro→Review-Gemini-31-Pro.md,Claude Code→Review-Claude-Code.md. If the normalized result is empty or you cannot identify your own name with reasonable confidence, useReview-Unknown.mdand note the uncertainty at the top of the file. Publish each round atomically: write the complete review to a temporary file in the same directory, then rename that file overReview-<YourAgentName>.md. Do not clear the target first, and do not append across rounds. A reader then sees either the previous complete review or this one, and never a hole. A round interrupted before it finishes leaves the previous round's review intact, which is when it matters most. Use plain Markdown. Start the file with a<!-- Round N -->comment (matching the round number below) so the reader can verify freshness. Begin the review with a short "Verification notes" section (paragraph or short bulleted list; "Validation notes" is also an accepted name) stating the exact commands and outcomes (e.g.,latexmk built cleanly,pytest pyod/test/... 5 passed,checked citation X against arXiv:YYYY). Then add one standaloneVerification status: VERIFIEDorVerification status: UNVERIFIEDline. UseVERIFIEDonly when at least one relevant verification command actually completed. If no relevant command completed, writeVerification notes: none.,Verification status: UNVERIFIED, andCommit verdict: UNVERIFIED; do not issuePASSorBLOCK. Separate findings into New (raised for the first time) and Previously raised (with status: Fixed, Still open, Reopened, or Deferred) sections. On Round 1, the Previously raised section may be omitted or shown as "None." Then include the file/diff scope, review lens, findings in priority order, and concrete recommended changes. For any finding flagged High priority, include an exact suggested rewrite with file path and line range. Use a fenced code block for multi-line rewrites. Do not skip this step. For examples of the expected depth and format, seeskills/implement-review/references/example-reviews/.
Recording the expected reviewer set: Before presenting the prompt, record two pieces of Claude-side state that Phase 2 will use:
- Expected reviewer set: the reviewers the user intends to invoke this round. Infer from, in order of preference: (1) explicit user statement in this or a recent turn (e.g., "I'll run Codex and Copilot", "just Gemini", "only Codex"); (2) prior-round pattern with no change announced; (3) channel default of
{Codex}when only Terminal-relay, Auto-terminal, or Plugin has been engaged and no other reviewer is in scope. If none of these produces a confident set, ask the user which reviewers they plan to invoke before presenting the prompt; do not guess. - Phase 1c emission time: the timestamp when the prompt is shown to the user. Used as an mtime tiebreaker in Phase 2 for files that cannot be classified by expected set alone.
Phase 2 uses the expected set as a scope partition axis and the emission time as a freshness tiebreaker.
Terminal path: Present a compact, copy-pasteable review prompt as a fenced text block. Keep the prompt under 20 lines. Tell the reviewer to run the exact diff command chosen in Phase 1b rather than pasting the diff inline; this prevents prompt bloat as rounds accumulate. The abbreviated save instruction below inherits the full contract stated above (statuses, Round 1 behavior, required sections).
IMPORTANT: Save your complete review to Review-<YourAgentName>.md in the repo root. Normalize your name: pick the stable product name, whitespace → one dash, keep only ASCII letters/digits/dashes, collapse repeated dashes, trim edge dashes. Examples: Codex → Review-Codex.md, GitHub Copilot → Review-GitHub-Copilot.md, Gemini 3.1 Pro → Review-Gemini-31-Pro.md, Claude Code → Review-Claude-Code.md. Use Review-Unknown.md if the result is empty or you cannot identify yourself, and note the uncertainty at the top of the file. Write the complete review to a temporary file in the same directory, then rename it over that filename rather than clearing the target first. Start with <!-- Round N -->. Begin with Verification notes listing exact commands and outcomes. Add one standalone Verification status: VERIFIED or Verification status: UNVERIFIED line. Use VERIFIED only after at least one relevant verification command completed. With no completed verification, write Verification notes: none., Verification status: UNVERIFIED, and Commit verdict: UNVERIFIED; do not issue PASS or BLOCK. Include file/diff scope and review lens. Separate findings into New and Previously raised (Fixed / Still open / Reopened / Deferred) sections. For High-priority findings, include an exact rewrite with file:line. See skills/implement-review/references/example-reviews/ for expected depth.
Review staged changes in <repo path>. Round <N>.
Run `<diff command chosen in Phase 1b>` to see the diff. Files changed: <in-scope file list>.
<When staging is broader than the review scope, add:> Staged but out of scope: <excluded staged paths>.
Summary: <one to three sentences>
Lens: <content type> — <abbreviated criteria, sub-lens, or agency-specific lens name>
Focus: <additional focus if any, or omit line>
Working method (optional, only if your runtime supports it): for a large or multi-file diff, you may parallelize across scopes that satisfy Phase 1b item 3, keeping every shared-contract pair in one reviewer's context and re-reading that boundary while consolidating; for any finding that rests on a checkable external fact (citation, link, library or API behavior, version), use web search to verify it before asserting, and record what you checked in Verification notes.
Scope-challenge focus (mandatory; reviewer must take an explicit position): (a) Why exactly this scope — what user pain or opportunity does it close, could a smaller scope close most of it, could a marginally larger scope close all of it for low cost? (b) Is each "out of scope / deferred to vNext" worth its process tax (extra plan-review + implement + execution-review + CI + publish cycle) versus inclusion now? (c) Is this plan the simplest path? Be adversarial about purpose and shape; do NOT fish for low-probability edge cases.
<When the staged diff spans two or more variant targets:>
Variant targets:
- TARGET A: <path or pattern>
- TARGET B: <path or pattern>
(Review each target in its own top-level section and add a Cross-variant drift check at the end.)
<For rounds 2+:>
Prior findings:
- <finding> (Resolved | Still open | Deferred | Refuted | Inconclusive)
Then wait for the user to relay the reviewer's feedback or confirm that the reviewer has finished (see Phase 2 for how Claude Code picks up the review).
Auto-terminal path (opt-in): When the user has opted in per the trigger rules in Codex Channels > Path selection, first check whether the required Auto-terminal scripts exist. Look up all three script pairs in this order: repo-local skills/implement-review/scripts/, then pack-deployed .claude/skills/implement-review/scripts/, then bootstrapped .agent-config/repo/skills/implement-review/scripts/. Required scripts are dispatch-codex.{ps1,sh}, health-check.{ps1,sh}, stall-watch.{ps1,sh}, and await-review.py. The last one is required because a stopped task is resolved through it. Without it the round cannot tell a live reviewer from a dead one, which is the failure this channel is most exposed to. await-review.py is Python and has no shell variant, so the probe also has to find an interpreter that runs it. Check <state-dir>/python-interpreter when a previous dispatch recorded one, otherwise resolve one the way dispatch-codex does. A missing interpreter is the same class of absence as a missing script. Say Auto-terminal needs a Python interpreter for await-review.py and none was found; using Terminal-relay for this round. and downgrade without setting sticky downgrade. This matters beyond Python projects: the Copilot and Claude backends never write python-interpreter, and dispatch-codex itself proceeds after failing to resolve one. If any required script for the current platform is missing, say Auto-terminal is documented but unavailable until the Phase B scripts are present; using Terminal-relay for this round. Then downgrade to Terminal-relay without setting sticky downgrade (the absence is design state, not failure; sticky should kick in only for real Auto-terminal runtime failures).
If the scripts are present, Claude Code does NOT present a copy-paste prompt block. Instead, the skill:
- Probes
codexon PATH (Get-Command codexon Windows,command -v codexon POSIX). If absent: warn the user and downgrade to Terminal-relay for this round. - Probes session sticky-downgrade state. If active: downgrade to Terminal-relay (silent unless the user asks why).
- Assembles the prompt: byte-identical to the fenced Terminal-relay block above (same save contract, lens, focus, scope-challenge focus, prior findings).
- Writes the prompt to a temp file under
%TEMP%/$TMPDIR. - Invokes
skills/implement-review/scripts/dispatch-codex.{ps1,sh}(repo-local first, then pack-deployed under.claude/skills/implement-review/scripts/, then bootstrapped under.agent-config/repo/skills/implement-review/scripts/) with--prompt-file <temp-path>,--round <N>,--expected-review-file Review-Codex.md. Run in the background, and size the timeout to the reasoning tier rather than to one number: about 20 minutes (1200000) atxhigh, and about 45 minutes (2700000) atmax, because raising the tier roughly doubles wall-clock. On POSIX use the Bash tool. On Windows the script isdispatch-codex.ps1, and the PowerShell tool caps a single call at600000, which is below both figures; dispatch through the Bash tool there as well, or expect the harness to background the call at its cap. The dispatch script internally launchesstall-watch.{ps1,sh}in the background to monitor tail-file growth. Its default 600-second silence threshold records<state-dir>/stall-warningwithout killing any process. A terminal Codex response-stream suffix records<state-dir>/stream-deathand invokes the bounded reap contract below. - Reads the dispatch script's stdout: it emits exactly one line
STATE-DIR <abs-path>(the only stdout line). Capture this path for Phase 2 to pass tohealth-check --state-dir <abs-path> --round <N> --review-file Review-Codex.md. All three flags are required byhealth-check.py's argparse (--roundhas no default,--review-filedefaults toReview-Codex.mdbut pass it explicitly so the invocation is unambiguous when read fresh from SKILL.md); omitting--rounderrors out before any check runs. All other dispatch diagnostics plus the last-80 codex-exec lines go to the script's stderr. - Phase 1d auto-watch runs unchanged; it polls for
Review-Codex.mdwith the current round marker. Phase 2 prologue (defined in Phase 2 below) adds Auto-terminal-specific gating before silent advance.
Bounded retry after confirmed Codex stream death: IMPLEMENT_REVIEW_STREAM_RETRY_LIMIT sets the maximum number of automatic redispatches, default 1; 0 disables them. The dispatcher records the effective limit and current count in the state directory. A retry begins only when both <state-dir>/stream-death and <state-dir>/stream-retry-request exist, the count is below the limit, and <state-dir>/stream-reap-complete confirms the old worker tree has been reaped. The dispatcher archives the failed attempt under <state-dir>/attempt-N, clears the active attempt markers, updates the timestamp and count, and runs the same prompt again. It reuses the original state directory, so the initial STATE-DIR <abs-path> remains the only dispatcher stdout line. Each redispatch writes AUTO-REDISPATCH attempt=N/M reason=codex-response-stream-disconnected state-dir=<abs-path> to dispatcher stderr; auto-watch mirrors that schema in its own output after the count advances. Silence can write stall-warning and wake the coordinator, but it never requests or starts a retry.
On Auto-terminal failure (non-zero exit, timeout, missing fresh review file, or Health check fail): downgrade to Terminal-relay for that round AND set sticky downgrade for the rest of the session. A harness notification that the background task was stopped is not one of these triggers, and neither is a watcher that stopped with it. Resolve that case with await-review first (see Phase 1d); only its DEAD verdict is an Auto-terminal runtime failure. With the default --sandbox danger-full-access Codex can inspect the repo directly and tool-sandbox failures should be vanishingly rare; if one does occur (typically only when CODEX_DISPATCH_SANDBOX has been narrowed in a CI / shared environment) and Phase 2.0 surfaces it via Check 7 / 8 / Substance heuristics with dispatch exit 0, use the embedded-diff retry once before setting sticky downgrade (see "Embedded-diff retry for Codex tool-sandbox failure" in Codex Channels for the procedure and the diff-scoped-findings caveat). Do not add a truncated positional-argument fallback.
Script contract invariants (apply to all dispatch-codex / health-check / stall-watch .sh and .ps1 variants):
- State-dir lifecycle: created once per logical dispatch by
dispatch-codexunder%TEMP%/$TMPDIR; preserved on anyWARNorFAILoutcome so the user can inspect; deleted only after a clean Phase 2 intake completes silently. State-dir names carry<pid>-<nonce>and are unique across unrelated dispatches. Automatic stream-death attempts reuse the same directory and preserve each failed attempt underattempt-N, which keeps the singleSTATE-DIRstdout contract stable. - Deployed-script release: before it creates dispatch state or starts the reviewer,
dispatch-codexre-executes from a private temp copy.IMPLEMENT_REVIEW_DISPATCH_REEXECprevents a loop, andIMPLEMENT_REVIEW_DISPATCH_SOURCE_DIRkeeps sibling-script lookup at the original deployed directory. The wrapper removes the temp copy after the dispatch and propagates its exit status. This releases the deployeddispatch-codex.shpath before Bash can block a composer replacement. - Timestamp units: all values in
<state-dir>/timestampand<state-dir>/pre-mtimeare integer Unix epoch seconds. Every producer writes integers (date +%s,ToUnixTimeSeconds()), and both readers parse withint()and reject a float spelling as a state-contract failure, so a fractional value is not a permitted alternative spelling. mtime comparisons happen in UTC; cross-platform stat is the implementer's responsibility. POSIX may usestat -c %Y(GNU) orstat -f %m(BSD/macOS). PowerShell must convertLastWriteTimeUtcto Unix epoch seconds, for example$utc = (Get-Item -LiteralPath <path>).LastWriteTimeUtc; ([DateTimeOffset]$utc).ToUnixTimeSeconds()(two-step form, avoids cast-precedence confusion) or an equivalent Unix-epoch conversion. Do NOT write Windows FILETIME values fromToFileTimeUtc()(FILETIME is 100-nanosecond ticks since 1601-01-01, not Unix epoch; mixing units across.ps1and.shwould silently break Health check 2 freshness comparisons). - stdin invocation shape: POSIX uses redirection with the prompt file as stdin (
codex exec --sandbox "$CODEX_DISPATCH_SANDBOX" [isolation args] -c "developer_instructions=..." - < <prompt-file>). PowerShell writes a transient<state-dir>/run-codex.cmdhelper with the same argument order and< <prompt-file>handle redirection, then invokes it through& $cmdHelper. These shell-level redirections preserve the byte-identical prompt invariant and let Codex child processes inherit the logon-session token cleanly. The--sandboxvalue comes from$env:CODEX_DISPATCH_SANDBOX(defaultdanger-full-access); see the Auto-terminal Trust-Model paragraph above for why. By default both variants pass--ignore-user-config -c model_reasoning_effort=<R>(R from$env:CODEX_DISPATCH_REASONING, defaultxhigh) so a user-level Codex MCP server, plugin, or hook does not auto-start inside the headless reviewer and recurse into a nested codex, the failure recorded as agent-config#1; setCODEX_DISPATCH_ISOLATE_MCP=offto opt out and run with the full user config (do this if the review needs the user'sservice_tieror a custommodel_provider, which isolation drops and does not re-pass). Independently of isolation, both variants pass the separate-c developer_instructions=...argument before the trailing-. That argument suppresses only bootstrap and shared configuration refresh in the child session; it leavesAGENTS.mdand all other project rules active. Because it is CLI configuration and the prompt still arrives only through input redirection, it does not modify the prompt-file bytes.--ignore-user-configis used because the narrower-c mcp_servers={}is deep-merged by Codex 0.139 and leaves the configured servers running. It also resets the reasoning effort, so the re-pass restores the dispatcher's cross-model compatibility floor (xhighby default) while the model stays Codex's built-in default. SetCODEX_DISPATCH_REASONING=maxon GPT-5.6 for maximum single-agent reasoning; useultraon GPT-5.6 Sol or Terra only when automatic task delegation is intended. Re-passingservice_tieris deliberately skipped: hardcoding the maintainer's tier would make every round fail for a consumer whose account lacks it, so a temp-CODEX_HOMEsanitizer (config minus the MCP tables) is the documented path to full config-preserving isolation. This shape replaced an earlierGet-Content -Raw <prompt-file> \| codex exec -and aStart-Process -RedirectStandardInputvariant: the pipe form could inject a BOM under PS 5.1, andStart-Processroutes throughCreateProcessAsUserWwhich strips the token (Codex's git subprocess then failed with Windows error 1312). Neither variant may use command substitution (codex exec "$(cat <file>)") or positional-arg passing of the full prompt, because both hit ARG_MAX on Windows. Path values interpolated into the cmd helper must escape%to%%so cmd does not env-expand them, and the helper is written as UTF-8 (no BOM) with achcp 65001prefix so non-ASCII paths survive cmd's codepage layer. stall-watchsilence, stream death, and bounded reaping: the silence threshold isSTALL_THRESHOLD_SECONDS, default 600 seconds. A no-growth interval writesSTALL <timestamp> tail-no-growth-for-<seconds>sto<state-dir>/stall-warning. Silence NEVER kills a process. Stream-death detection runs only after tail growth, reads only the last 16 physical lines, removes empty lines, and requires the terminal suffix to contain the Codex response URL error followed bytokens usedas the penultimate non-empty line and a bare numeric final line. A match writesSTREAM-DEATH <UTC timestamp> codex-response-stream-disconnectedto<state-dir>/stream-death. The watcher records the dispatcher's start identity and the worker roots' process-creation identities. It may reap only forstream-deathorparent-exited, and only after a recorded worker identity still matches; unrelated processes are never targeted. Ifstall-watchitself errors, it exits silently.- Stream-death retry handoff:
stall-watchwritesstream-retry-requestbeforestream-death, performs the identity-checked reap, then writesstream-reap-complete. The dispatcher waits up to 10 seconds for that completion marker before archiving and retrying. Missing handoff or archive evidence stops redispatch and emits anAUTO-REDISPATCH-SKIPPEDdiagnostic. The configured retry count is a hard bound. Silence never enters this handshake. - Exit codes:
dispatch-codexpropagates the final Codex exit code unchanged.health-checkexits non-zero when Phase 2 must refuse to read the review file (Check 1-6 or Check 10 FAIL, or required dispatch state missing/stale); WARN-only outcomes (Check 7/8/9 hit, Substance heuristic flag) exit 0 with WARN lines on stdout. Phase 2 must parsehealth-checkstdout and treat anyWARNline as a silent-advance blocker; exit code 0 alone is NOT sufficient to proceed silently.stall-watchexits 0 regardless of what it detected.await-review(Python only, no shell variants) writes one terminal line to stdout and exits 0 forREVIEW-READY, 3 forALIVE, 4 forDEAD, 2 for a checkpoint (TIMEOUTorREAP-UNKNOWN), and 1 for a state-contract failure. It reads the samepre-mtime,timestamp,tail, and retry-marker files as the checks above, and applies the same state contract, freshness rule, and round-marker rule. ItsREVIEW-READYtherefore cannot contradict Health checks 1 to 3 or the state contract. It says nothing about Checks 4 to 10: size, verification notes, and the commit-verification contract stay Phase 2's job, and aREVIEW-READYreview can still fail them. - Check 8 breakdown emission: when Check 8 fires (any TOOL_FAILURE_PATTERNS hits in
<state-dir>/tailafter backtick-code-span exclusion),health-check.pyemits a per-pattern count breakdown after the marker total so downstream Claude can recognize known-noise shapes without re-grepping the tail. Form:WARN check-8 N tool-failure-markers breakdown=label1:n1 label2:n2 ...with labels derived from the longest word run in each pattern, sorted by count descending. See the FP-tuning principle subsection for the catalogue of known-noise shapes (WSL-stub-bash 1312 burst, etc.) that Claude should fast-Proceed when Substance heuristics also pass.
Evidence for latency claims
<state-dir>/tail is a transcript for a human to read. It has no timestamps, and the reviewer's prose can quote the same error strings that appear in real diagnostics. Counting occurrences in a tail therefore does not measure elapsed time, call count, or failure frequency. For any claim about where time goes, use ~/.codex/sessions/**/rollout-*.jsonl. Rollout records carry per-event millisecond timestamps and token counts, and a run can be joined to them by session id. A latency claim without rollout evidence should not be acted on.
Two corollaries matter when reading retained tails. A single tail block can represent one call within a parallel batch; repeated material inside that block does not establish several separate calls. When the diff under review includes this skill, the skill's own diagnostic strings appear in the tail as reviewed content. Any cross-tail scan must exclude that case.
Plugin path: Tell the user the changes are ready for review and provide the same review prompt content used by the Terminal-relay path (save contract first, then round, diff scope, summary, lens, focus, scope-challenge focus when applicable, variant targets when applicable, prior findings for rounds 2+). The user pastes the same content into the plugin sidebar; the surrounding Markdown fence may be omitted if the plugin UI does not need it, but the prompt content itself must match Terminal-relay byte-for-byte (after the optional fence-strip). This preserves the cross-channel prompt invariant: Codex receives the same instructions regardless of channel.
Example instruction to the user:
Paste the same review prompt shown for Terminal-relay into the Codex plugin sidebar. The plugin can inspect the repository directly (so the diff is visible without copying), but the prompt content itself must still include the save contract, round number, files changed, summary, lens, focus, scope-challenge focus when applicable, variant targets when applicable, and prior findings when applicable. Ask the plugin reviewer to save the complete review to
Review-<YourAgentName>.mdin the repo root using the normal Phase 1c save contract.
Then wait for the user to relay the reviewer's feedback or confirm that the reviewer has finished.
1d. Auto-watch (Terminal-relay and Auto-terminal channels)
After Phase 1c emits the Terminal-relay prompt or dispatches Auto-terminal (and records the expected reviewer set + emission/dispatch time), the skill automatically launches a background watcher that detects when the reviewer writes Review-<expected>.md and resumes Phase 2 — eliminating the manual "done" relay. The watcher runs by default for both channels; the user does not need to confirm. To opt out, the user can say so explicitly (e.g., "stop auto-watch", "manual mode this round") and the skill terminates the background process and falls through to the wait-for-user path. Plugin path skips this subsection entirely (IDE plugins typically have the file open and gain little from auto-watch).
Launch the platform-appropriate watcher script immediately after emitting the prompt, using positional arguments (FILE_GLOB, ROUND_NUMBER, EXPECTED_REVIEWERS). Look up the script in this order: skills/implement-review/scripts/auto-watch.{sh,ps1} (repo-local), then .claude/skills/implement-review/scripts/auto-watch.{sh,ps1} (pack-deployed), then .agent-config/repo/skills/implement-review/scripts/auto-watch.{sh,ps1} (bootstrapped). Use the Bash variant on macOS / Linux and the PowerShell variant on Windows. FILE_GLOB is Review-<expected>.md for a single expected reviewer or Review-*.md for multiple; EXPECTED_REVIEWERS is the comma-separated normalized name list from Phase 1c (e.g., Codex or Codex,GitHub-Copilot). Run the watcher in the background so the skill can keep accepting user input while it polls. On the Auto-terminal path, set IMPLEMENT_REVIEW_STATE_DIR to the absolute path from the dispatcher's STATE-DIR line when launching the watcher. That hands the directory over instead of leaving the watcher to find it. Its fallback is a 30-second window around its own start time, which a contended process launch can miss.
The watcher polls every 5 seconds. It fires when (a) the file's mtime has advanced past the snapshot taken at watcher startup, (b) the file has been quiet for 10 seconds (mtime is at least 10 seconds in the past), AND (c) its first line equals <!-- Round N --> after stripping trailing \r and whitespace. Hard timeout is 60 minutes. Stdout starts with WATCH-START round=N reviewers=<csv> timeout=3600s. Each confirmed retry may add AUTO-REDISPATCH attempt=N/M reason=codex-response-stream-disconnected state-dir=<abs-path>. One terminal line then follows: DONE <absolute-path> (exit 0), TIMEOUT (exit 2), REAP-UNKNOWN <state-dir> (exit 2), STREAM-DEAD <state-dir> (exit 3), or STALL <state-dir> (exit 3). Output remains bounded by the configured retry limit.
When the watcher emits DONE <path>, resume Phase 2 immediately. The watcher's path output is informational; Phase 2 still re-lists Review-*.md itself and applies the freshness + scope partition described below. If the expected set has multiple reviewers and only one fired, Phase 2's reviewer-specific follow-up handles the rest.
When the watcher emits AUTO-REDISPATCH ..., the bounded retry has started; keep watching the same logical dispatch and state directory. No user action is required.
When the watcher emits STREAM-DEAD <state-dir>, stall-watch has recorded the terminal stream-disconnect suffix AND written stream-reap-complete, so the identity-checked worker-tree reap finished and no further retry started. The watcher waits for that completion marker before it emits, because stream-death is written before the reap runs and this output costs the session its channel. The bound may be exhausted, disabled, or blocked by an incomplete handoff. Treat exit 3 as an Auto-terminal runtime failure and apply the existing downgrade and sticky-downgrade rules.
When the watcher emits REAP-UNKNOWN <state-dir>, stall-watch recorded the stream disconnect and then never confirmed its reap. Both variants swallow a failed write of stream-reap-complete, so the proof STREAM-DEAD requires may never arrive, and waiting the remaining hour for it buys nothing. A missing confirmation is not a death certificate either. Exit 2 is a checkpoint, so resolve the round with await-review as below, and do not set sticky downgrade from this line.
When the watcher emits STALL <state-dir>, surface the silence warning and inspect or continue monitoring the dispatch. Exit 3 wakes the coordinator; it does not mean the worker was killed or that the review cannot still complete. Do not terminate the dispatch or set sticky downgrade from silence alone.
When the harness reports the dispatch or the watcher as stopped: a background-task notification carrying killed, whose summary reads Background command "..." was stopped, is a statement about the harness's task wrapper. It is not evidence about the reviewer, which runs detached and outlives its wrapper. Do not conclude failure, do not redispatch, and do not set sticky downgrade from that notification. It routinely arrives for the dispatch and the watcher in the same second, so a lost watcher is not corroboration; await-review replaces the watcher for the rest of that round.
Resolve the round from state-dir evidence instead. await-review.py has no .sh or .ps1 wrapper and is not executable by filename, so invoke it through an interpreter: <python> <scripts-dir>/await-review.py --state-dir <abs-path> --round <N> --review-file Review-<Reviewer>.md. Resolve <scripts-dir> through the same lookup order as the other scripts. Take <python> from <state-dir>/python-interpreter when the dispatcher resolved one. Use the backend's own review filename: Review-Codex.md, Review-GitHub-Copilot.md, or Review-Claude-Code.md. Run it in the foreground. Its default budget stays under the 600-second cap a single tool call gets, and a background probe would be exposed to the same stop it exists to diagnose. Three verdicts and two checkpoints:
REVIEW-READY <path>(exit 0): the round's review is published, fresh againstpre-mtime, carries this round's marker, and has gone quiet. Continue into the Phase 2.0 health check exactly as if the dispatch had reported exit 0.ALIVE <state-dir> reason=working|tail-idle-unproven|round-marker-mismatch ...(exit 3): the round has not provably ended. Run it again; the round deadline below is what stops the loop.tail-idle-unprovenmeans the tail has been silent past the idle threshold.round-marker-mismatchmeans a review was published for this dispatch carrying another round's marker. Both are reasons to look, never verdicts.DEAD <state-dir> reason=stream-death(exit 4):stall-watchrecorded the terminal stream disconnect and its identity-checked reap completed, so the worker tree is gone. Only this verdict counts as an Auto-terminal runtime failure and may set sticky downgrade.TIMEOUT <state-dir> round-deadline=<epoch>(exit 2): the round outlived the deadline below, and nothing observed says the reviewer died. Stop callingawait-review, printAuto-watch timed out after 60 min; reply 'done' when the reviewer finishes., and fall through to the wait-for-user path.REAP-UNKNOWN <state-dir> tail-idle=<s>(exit 2): the state the watcher reports under the same name, reached from the resolver. Treat it the same way, as a checkpoint for a person.
Neither exit-2 line may set sticky downgrade. Both say the evidence ran out, which is the opposite of the evidence DEAD requires.
The round's deadline outlives the session that started it. The stop took the wrapper holding the dispatch timeout, and it usually takes the watcher's 60-minute timer with it. So await-review stamps <state-dir>/round-deadline on its first call, at the round's origin plus 60 minutes, and reads that file back on every later call. The origin is the earliest readable timestamp in the state directory. That is the root timestamp, unless an automatic redispatch archived an earlier one into attempt-N/timestamp and rewrote the root. The archived value is then the round's real start. The stamp is never rewritten. An automatic redispatch therefore cannot buy the round a second hour, whether or not a resolver ran before it, and an agent that lost the dispatching session's context still inherits the original bound. Pass --timeout at or below 540 seconds to stay inside the 600-second cap on one tool call; the resolver ends the call at the round deadline when that comes first. Repeat on ALIVE until a verdict or a checkpoint arrives; the deadline is what guarantees one does. A round-deadline file that exists and cannot be read as an integer epoch is a state-contract failure (exit 1), never a reason to stamp a fresh hour.
Silence is never terminal here. DEAD requires evidence that the round ended: stream-death paired with a completed stream-reap-complete. A review published under the wrong round marker is not that evidence either, because a reviewer can publish twice in one round, and the second write is the one worth having. A quiet tail is not that evidence, which is why stall-watch treats even 600 seconds of it as a soft signal, and why a shorter idle window may not be promoted to a death certificate. When the reviewer dies in a way that writes no marker, await-review keeps returning ALIVE and the round's own timeout is what ends it. That is the intended shape. The timeout is a bounded wait with a human at the end of it, and an unproven death is the judgement this rule exists to prevent.
This rule exists because the alternative was measured and it was wrong every time. On 2026-08-21, six such notifications arrived across two repositories. In all six the detached reviewer was still running. Every one of those rounds published its review afterwards, the latest about sixteen minutes after the stop. One session read two of them as consecutive dispatch failures, set sticky downgrade, and stopped. The review it was waiting for landed ten minutes later and was never read.
When the watcher emits TIMEOUT, print Auto-watch timed out after 60 min; reply 'done' when the reviewer finishes. and resume the existing wait-for-user path. On explicit opt-out, user interrupt, or watcher launch failure, also fall through to the same wait-for-user path. The fallback is the unchanged Phase 1c to Phase 2 flow, so no Phase 2 logic depends on whether auto-watch was used.
Phase 2: Intake Feedback
Phase 2.0 prologue: Auto-terminal Health check (Auto-terminal channel only; Terminal-relay and Plugin skip)
For the Auto-terminal channel only, run 10 structural Health checks plus 3 Substance heuristics on Review-Codex.md before the existing freshness + scope partition begins. Required dispatch state files (<state-dir>/pre-mtime, <state-dir>/timestamp, <state-dir>/tail, plus optionally <state-dir>/stall-warning when stall-watch wrote it) come from the dispatch-codex and stall-watch scripts via dispatch-codex's stdout STATE-DIR <abs-path> line. Health checks 2, 7, 8, 9 and the Substance heuristics depend on these files.
| # | Check | Failure → |
|---|---|---|
| 1 | Review-Codex.md exists at repo root | Surface failure; offer downgrade-retry via Terminal-relay |
| 2 | File mtime is later than the Phase 1c dispatch timestamp AND later than <state-dir>/pre-mtime (catches stale file from prior round or task) | Same as 1 |
| 3 | First line equals <!-- Round N --> | Same as 1 |
| 4 | File size ≥ 500 chars | Same as 1 |
| 5 | "Verification notes" section present (Verification notes: paragraph form OR ## Verification notes / **Verification notes** heading) | Same as 1 |
| 6 | If the dispatch prompt named a plan file or staged file list, the review's file scope mentions that current scope | Same as 1 |
| 7 | Review-text suspicious-phrase scan: case-insensitive match in the saved review body on any of could not, i cannot, failed to, permission denied, rate limit, unable to access, unable to execute, unable to run, not able to execute, not able to run, do not have access, not authenticated, authentication failed, unauthorized, timed out, timeout, quota, command not found, no such file, sandbox.*fail. Exclude content inside backtick code spans (Codex meta-discussing the pattern list is not failure narration). | Do not hard-fail; block silent advance and surface: Auto-terminal review-text scan: N suspicious phrases (lines L1, L2, ...) -- review may be partial. Proceed? |
| 8 | Dispatch-tail tool-failure scan: case-insensitive regex match in <state-dir>/tail (full codex-exec stdout+stderr, NOT the review body) for tool ... failed, mcp tool failed, HTTP/status 429/5xx, rate limit, quota exceeded, insufficient_quota, connection refused/reset/timed out, context_length_exceeded, maximum context length, Windows sandbox launch failures such as CreateProcessAsUserW failed: 1312 or windows sandbox: runner error, the Windows NTSTATUS spawn-failure family -107374\d{4} (signed-decimal 0xC000xxxx exit codes printed when a spawned shell dies before entry), and errno forms ENOSPC / EACCES / ETIMEDOUT / ECONNRESET / ECONNREFUSED. The scan is line-level (Fix A + Fix B; see health-check.py): strip backtick code spans, then skip modeled pattern-echo lines (a line-numbered source citation, or a line quoting a literal regex-source fragment such as \bENOSPC\b or sandbox.*runner error), then on the surviving lines count intrinsic failure forms (HTTP/status 429/5xx, Too Many Requests, rate limit exceeded, quota / insufficient_quota, context_length_exceeded, the 1312 / sandbox-runner shapes, signed-decimal NTSTATUS exits, errno forms) on their own, and generic words (bare rate limit) only when an error-frame token sits on the same or an adjacent line. A bare line-number prefix or a backslash never suppresses a line, so a real line-numbered or Windows-path failure still surfaces. This check also runs when Check 1 fails. See health-check.py for the canonical pattern lists. | Do not hard-fail; block silent advance and surface: Auto-terminal dispatch-tail scan: N tool-failure markers -- Codex's CLI / OS / network layer leaked errors. Proceed? |
| 9 | Stall-watch check: <state-dir>/stall-warning file does NOT exist. The stall-watch background daemon (launched by dispatch-codex alongside codex exec) appends to this file when <state-dir>/tail has zero growth for at least 600 seconds (10 minutes by default). This is a low-confidence silence signal that can reflect long model generation as well as a CLI or network stall; it never kills the worker. File present = at least one silence period occurred. | Do not hard-fail; block silent advance and surface: Auto-terminal stall-watch: N silence period(s) detected (first at T+<min>); output paused for 10+ min during run, and the worker was left running. Proceed? |
| 10 | Commit-verification contract: A labeled PASS or BLOCK commit verdict has a standalone Verification status: VERIFIED marker. An UNVERIFIED status or verdict, conflicting status or verdict values, PASS or BLOCK with a missing status, or VERIFIED with Verification notes that explicitly report no execution is invalid. A review with no commit verdict remains accepted for compatibility. | Hard-fail intake and surface the exact FAIL check-10 ... detail. Do not treat the commit verdict as execution-backed. |
Implementer note: pipes inside Check 7 and Check 8 regex patterns are escaped as
\|where Markdown-table parsing requires it. The runtime regex engine (Pythonre, PowerShell-match, etc.) must receive unescaped alternation (|). The health-check script should compile patterns from a source-of-truth list rather than from the rendered Markdown.
Outcomes:
- Checks 1-6 and 10 all pass AND Checks 7, 8, and 9 all clear (0 suspicious phrases, 0 tool-failure markers, no stall-warning file present) → eligible for silent proceed (still subject to Substance heuristics and Phase 1d coordination below).
- Checks 1-6 and 10 all pass AND Check 7, 8, OR 9 hit (any marker or stall-warning present) → emit the corresponding one-line note(s); block silent advance; ask user to Proceed or Downgrade.
- Any of Checks 1-6 or Check 10 fails → refuse intake; surface specifically which check failed; offer Terminal-relay retry.
Required dispatch state contract: Missing or stale <state-dir>/pre-mtime or <state-dir>/timestamp is FAIL (Health check 2 freshness and the time-floor heuristic cannot be trusted). Missing <state-dir>/tail is WARN check-8 1 missing-dispatch-tail and blocks silent advance; it must NOT be silently treated as Check 8 hit 0. When Review-Codex.md is missing, Check 1 hard-fails while Check 8 and Check 9 still run against <state-dir>/tail and <state-dir>/stall-warning. A missing review file is exactly the case Check 8 exists to diagnose: a dispatch can spend a round retrying a shell spawn that always fails, write no review, and leave a growing tail. Reporting that state as tail-present-but-unscanned is incorrect. This replaces the pre-fix PASS check-8 tail-present-not-scanned and check-9 stall-warning-present output shapes; Check 9 now reports N stall-periods in both branches.
Windows state-dir diagnostics: In a PowerShell session, inspect state-dir files by running PowerShell code directly in the current shell, or by writing a temporary .ps1 and invoking it with -File. Do not wrap diagnostics as pwsh.exe -Command "foreach($f in ...) { ... }" from inside an existing PowerShell shell. The outer shell expands $f, $_, and $cutoff before the inner process sees them, producing errors such as Missing variable name after foreach or =: The term '=' is not recognized. If a nested PowerShell process is unavoidable, use a temp .ps1 file instead of inline -Command.
Substance heuristics (Auto-terminal only; soft signals; ANY hit blocks silent advance; never hard-fails)
The 10 structural Health checks above verify the file shape, dispatch signals, and commit-verification marker. They do NOT catch a review that is structurally clean but substantively shallow (Codex's tools silently failed mid-run; rate limit; context overflow; or the model did not engage). Three lens-aware heuristics fire after the 10 Health checks and surface independently. Any hit blocks silent advance: the user is prompted "Proceed? / Downgrade?" before Phase 2 reads the file.
| Heuristic | Signal | Surface format |
|---|---|---|
| Time-to-completion floor | Elapsed wall time from <state-dir>/timestamp to Review-Codex.md finalization is less than 30s, when the dispatched prompt is ≥ 2000 chars | Substance heuristic: review completed in <T>s for <P>-char prompt -- Codex may have bailed early. Spot-check before trusting. |
| Anchor density | Review body > 1000 chars AND zero file-line anchors matching :\d+, \bline \d+\b, \blines? \d+\s*[-–]\s*\d+\b, or <file>:<line> patterns | Substance heuristic: review has <N> chars and 0 file:line anchors -- may be generic prose without code/line grounding. Spot-check High findings. |
| Scope-challenge engagement (plan-review lens only) | Review does NOT contain visible evidence of ALL three scope-challenge axes. Evidence per axis = (a) / (b) / (c) enumeration OR keyword coverage (case-insensitive): Axis 1 (scope AND one of smaller / larger), Axis 2 (one of deferral / process tax / release cycle), Axis 3 (one of simplest / do nothing / doing nothing / smaller path / shrink / docs only / document only / script only / no-op). Axis-3 keyword set is intentionally broad to avoid false positives on substantive reviews. | Substance heuristic: plan-review did not visibly engage scope-challenge axes <missing-axis-numbers>. May be incomplete per skill mandate. |
Substance heuristics are skipped for Terminal-relay and Plugin path (the user has direct eyes on the run).
Phase 1d coordination (Auto-terminal-specific silent-intake rule)
For Terminal-relay, auto-watch DONE is sufficient signal to silently advance into Phase 2. For Auto-terminal, DONE is necessary but not sufficient. Phase 2 may silently advance only when ALL of the following hold:
- Auto-watch emits
DONE <path>(file appeared with current round marker). - The dispatch subprocess exited 0 (Bash background task notification reports
exit code 0), or the harness reported the task stopped andawait-reviewthen returnedREVIEW-READY. - Health checks 1-6 all pass.
- Health check 10 passes the commit-verification contract.
- Health check 7 hits 0 phrases.
- Health check 8 hits 0 markers.
- Health check 9 (stall-warning file absent) holds.
- Substance heuristics flag 0 signals.
If 2, 3, or 4 fails, refuse intake and offer Terminal-relay retry. If 5 hits at least 1 phrase, 6 hits at least 1 marker, 7 detects the stall-warning file, or 8 flags at least 1 signal, Phase 2 stops at a human checkpoint with Proceed? / Downgrade?; no silent advance. Auto-watch TIMEOUT, REAP-UNKNOWN, and STALL also stop at a human checkpoint. STREAM-DEAD is an Auto-terminal runtime failure handled by the downgrade rules above.
False-positive tuning principle
The Health checks (especially Check 7) and Substance heuristics are intentionally soft (surface + block silent advance, never hard-fail) because false positives are expected. Observed FP modes during dogfooding:
- Check 7 firing on Codex's own meta-discussion of the regex pattern list. Mitigated: Check 7 excludes content inside backtick code spans.
- Check 8 firing on Codex stdout echoing pattern strings, especially when /implement-review reviews the implement-review skill itself or any review prompt that names the patterns. Observed 12-152 markers across 4 dogfood runs (ac self-review r2/r3, random, NSF, Letter-) with 0 real tool failures in the same runs. Mitigated in three layers: (1) backtick-code-span exclusion, as Check 7; (2) Fix A, a line-level echo classifier that skips line-numbered source citations and literal regex-source lines; (3) Fix B, an intrinsic/generic split so terse real failures (a bare
Rate limit exceededorHTTP/1.1 429line) still count while bare ambiguous words need an error frame nearby. After these, a normal review whose tail has no failure vocabulary scans to 0 markers. A review whose subject IS the failure vocabulary (the implement-review skill itself) still surfaces a reduced count: prose discussion of intrinsic terms is indistinguishable from real failures, so the residual is the safe floor (real-failure-wins), recognized downstream via the breakdown shape. A live run on the preserved R1 self-review tail dropped 48 markers to 40 under this rule while every injected real-failure line still surfaced. - Check 8 firing on WSL-stub-bash 1312 burst (Windows hosts only). When Codex's tool dispatcher tries
bash <script>and PATHbashresolves to the WSL launcher stub (C:\Windows\System32\bash.exeor the Microsoft Store WSL alias underWindowsApps\), the stub brokers a syscall to the WSL service and requires elevation-token resolution thatCreateProcessAsUserWcannot supply from Codex's spawn context. Result: bursts ofCreateProcessAsUserW failed: 1312+windows sandbox: runner errorenvelope lines (typically 20-30 hits within <100 ms). This is a DISTINCT 1312 class from the workspace-write sandbox bug fixed by--sandbox danger-full-access; Codex falls back to alternative tools (PowerShell, Git native, or explicit Git Bash absolute path) and the review completes substantively. NOT mitigated in code: PATH-prepend approaches (PowerShell$env:PATHassignment and cmdSET PATH=...;%PATH%injected via the helper) both trigger Bitdefender's PATH-hijacking heuristic and blockdispatch-codex.ps1from loading entirely, which is strictly worse than the noise. Mitigation is at the SIGNAL layer instead: Check 8 emits a per-pattern breakdown so downstream Claude can recognize the WSL-stub shape -- if the breakdown is dominated bycreateprocessasuserw:N+windows:M+sandbox:M(envelope co-occurrence) AND Substance heuristics pass AND review-mtime is fresh, treat as known graceful-fallback noise and Proceed without escalation. User-side resolution (optional): remove the WSL stub from PATH (Get-Command bashshowingSystem32\bash.exeorWindowsApps\-> uninstall WSL or moveC:\Program Files\Git\binahead ofSystem32in PATH); Auto-terminal then emits 0 WSL-stub 1312 markers on subsequent runs. - Check
8breakdown dominated by107374:NwithFAIL check-1. This is real signal: a spawned shell died during process initialization and was retried for the whole round. On Windows, the common cause is apwshcommand that resolves only to a Microsoft Store App Execution Alias. Install PowerShell7from the MSI on the PowerShell GitHub releases page, or remove the alias fromPATH. The winget package now ships only the MSIX bundle, sowinget install Microsoft.PowerShellcreates this state. The dispatcher'spwshprobe in the Auto-terminal section prevents the round from being spent this way; this signal remains relevant for tails created before the probe or for other spawn-init failures. - Substance axis-3 firing on synonym phrasings (
shrink to docs onlyrather thansimplest path). Mitigated: axis-3 keyword set broadened. - Anchor density firing on a precise convergence review with low anchor count. Accepted as rare; one-click Proceed.
Operational principle: better to under-flag a real signal than to cry wolf so often the user clicks through every flag without reading. Alarm fatigue is not recoverable; once the user trains themselves to click past every surface, the silent-failure mitigation collapses. Track FP rate per check during the first ~10 Auto-terminal runs; if any check class exceeds 30% FP, tune the trigger criteria (broaden keywords, exclude additional contexts, raise size threshold) until signal-to-noise is workable.
Phase 2.1: Partition and classify (all channels)
Reviewers are instructed to write their review to a Review-<AgentName>.md file in the repository root, using their own self-reported name (see Phase 1c). When the user says a reviewer is done, or when multiple reviewers have been run in parallel for the same round, list the files matching Review-*.md at the repo root. Apply the two-axis partition described below (freshness + scope) to decide which files to read, and report any ignored files to the user.
Multi-reviewer consolidation: if two or more current-round review sources are available (current-round Review-*.md files and/or reviewer feedback the user relays directly), classify each new finding as:
- Convergent -- two or more reviewers raise substantially the same point. High confidence; treat as "will fix" unless wrong on the merits. If reviewers agree on the underlying problem but differ on severity, scope, or recommended remedy, classify as Convergent with differences: preserve each reviewer's severity and recommended fix in the consolidation report, and use the highest severity until the user or implementer resolves the difference.
- Single-source -- only one reviewer raises the point. Label the source (e.g., "from Review-Codex.md") when presenting.
- Divergent -- reviewers take opposite positions on the same finding. Flag the disagreement explicitly; present both sides; ask the user to decide.
Before trusting any file, verify that its <!-- Round N --> comment matches the current round number. Partition matching Review-*.md files along two axes.
Freshness axis: current-round (first line is <!-- Round N -->), stale-round (a different round marker), empty, or unreadable (cannot be read, or has a malformed or missing round marker).
Scope axis (if the expected reviewer set from Phase 1c is known): expected (the reviewer name extracted from the filename is in the expected set) or unexpected (the name is not in the set, possibly a leftover artifact from an earlier task that happens to share the round number).
Read and consolidate only files that are both current-round and expected. Report every ignored file by filename, grouped by reason (stale-round, empty, unreadable, unexpected), before presenting findings, so the user sees which reviewers produced usable output this round.
If a file is current-round but unexpected, flag it to the user before inclusion or exclusion: it may be a leftover from another task, or an additional reviewer the user invoked without announcing. Treat the file mtime against the recorded Phase 1c emission time as a secondary signal only, subject to clock skew, filesystem timestamp granularity, and editor-touch noise: mtime clearly older than emission weakly suggests a prior-task artifact; mtime at or after emission is consistent with a current-round file. Require at least one corroborating signal before including (e.g., file/diff scope matching current staged files, verification notes referencing current commands or files, the reviewer being named in the conversation). Do not silently include or exclude.
If the expected reviewer set is unknown, treat mtime as weak evidence only: use it to rank candidates, not to auto-classify. Ask the user to confirm which current-round files belong to this review before consolidating.
If the expected reviewer set is known and any reviewer in it is not represented in the current-round + expected bucket (absent entirely, or its file is stale, empty, unreadable, or unexpected):
- Present a reviewer-specific follow-up prompt the user can paste back into that reviewer, identifying which reviewer is missing so the user knows where to paste it:
Save your review to Review-<YourAgentName>.md in the repo root. Normalize your name: pick the stable product name, whitespace → one dash, keep only ASCII letters/digits/dashes, collapse repeated dashes, trim edge dashes. Examples: Review-Codex.md, Review-GitHub-Copilot.md, Review-Gemini-31-Pro.md, Review-Claude-Code.md. Use Review-Unknown.md if the result is empty or you cannot identify yourself, and note the uncertainty at the top. Write the complete review to a temporary file in the same directory, then rename it over that filename rather than clearing the target first. Start with <!-- Round N -->. Begin with a "Verification notes" paragraph or short bulleted list. Separate findings into New and Previously raised (Fixed / Still open / Reopened / Deferred) sections. For High-priority findings, include an exact rewrite with file:line. - If the file is still missing, still empty, or still carries a stale round marker after the follow-up, ask the user to paste that reviewer's feedback directly.
If only one current-round source remains after retry and direct-paste handling when multiple reviewers were expected, proceed with single-reviewer intake and label every finding as Single-source (no Convergent classification is possible without a second source). If the user did not invoke multiple reviewers this round, treat the single current-round source as the complete intake.
- When feedback arrives (from any
Review-*.mdfile or relayed by the user), acknowledge each point. - If a reviewer separated findings into "New" and "Previously raised" sections, verify the classifications. If a reviewer did not separate them (older prompts or non-compliance), do the separation yourself based on the round history.
- Categorize each new point as:
- Will fix -- clear, actionable, and correct.
- Needs discussion -- ambiguous or potentially wrong; ask the user before acting.
- Disagree -- explain why and let the user decide.
- For previously raised points, check the status the reviewer assigned:
- Fixed -- the reviewer confirms the prior finding was addressed. No action needed.
- Still open -- the fix did not land or was incomplete. Treat as "will fix" unless the user overrides.
- Reopened -- the reviewer re-raises a point that was marked Resolved. Flag to the user: this needs a decision, not silent re-litigation.
- Deferred -- the user chose not to address this. The reviewer acknowledges it as unchanged. No action unless the user reconsiders.
- Verify factual claims (Phase 2.5) for High-priority findings, and for Medium findings produced via the Auto-terminal embedded-diff retry channel, that make checkable factual assertions (citation existence, code behavior, link reachability, count or size, compile error). Verification outcomes (
Verified/Refuted/Inconclusive) override or augment the categorization above: a Refuted finding is not applied, regardless of its originalWill fix/Needs discussioncategory. - Present the categorized list (including verification outcomes from Phase 2.5) and confirm with the user before making changes.
- For follow-up questions within the same review round, prepare a short prompt the user can paste into the reviewer.
Phase 2.5: Verify Factual Claims (when triggered)
After Phase 2 categorization but before the user is presented with the categorized list, verify any High-priority finding that makes a checkable factual claim, and also verify any Medium finding from the Auto-terminal embedded-diff retry channel that makes a checkable factual claim. Reviewer assertions are not always correct; verifying first prevents revising in a wrong direction and produces an evidence trail when the claim is refuted. This phase is the inverse failure mode of "blindly accept reviewer feedback": a confidently-worded but wrong finding can otherwise propagate into the next round and waste both sides' time.
Trigger
Verification fires for a finding when all of the following hold:
- The finding is tagged High priority, OR the finding is tagged Medium and the review was produced via the Auto-terminal embedded-diff retry channel (see Phase 1c), OR the user explicitly requests verification on a Medium / Low finding.
- The finding makes an objectively checkable factual claim — citation existence, code behavior, link reachability, page-limit or word-count assertion, compile or type error, anonymization leak, etc.
- The reviewer's "Verification notes" section did not already cover this specific claim with a method that resolves it. If the reviewer ran a check that covers the claim, trust it unless contradicting evidence appears during fix application.
- The cost of verification is reasonable relative to the cost of applying the fix blindly. Skip verification when the proposed fix is trivially correct (a one-line typo) or when the cheapest verification path takes longer than the user can wait on a single finding.
Skip entirely for stylistic, opinion-based, or structural findings (term choice, paragraph order, tone, organization). Those have no factual ground truth to verify against.
Why Medium-from-retry-channel is mandatory-verify: the embedded-diff retry hands Codex only the staged diff hunks, not the surrounding file context. A retry-channel reviewer that flags "X is missing" or "X is wrong" may be reasoning correctly from the visible hunks while X actually exists or is correct in a non-diff line. Refuted findings of this shape have already been observed in dogfooding (e.g., a Medium claim that a regex set was case-sensitive, which turned out to be Refuted because the scanner applied re.IGNORECASE at compile time in a non-diff line). Phase 2.5 verification on every Medium from the retry channel turns this Refuted class into a hard pre-apply step instead of relying on the implementer to remember.
Methods
Pick the cheapest applicable method per claim type:
| Claim type | Verification method |
|---|---|
| Citation / paper / author existence | WebSearch for title and author; WebFetch arXiv / DOI URL; cross-check against the project's .bib file |
| Code behavior assertion | Run the targeted test (pytest path::test_name); read the source to trace; eval a small repro snippet |
| Link reachability | WebFetch of the URL; HEAD request via curl |
| Page limit / word count / file size | wc -w, wc -l, ls -la; compile and read the LaTeX log |
| Compile-time / type error | Run the compiler (latexmk, tsc, etc.) or type checker (mypy, pyright) on the affected file |
| Anonymization or leak claim | Grep for the alleged term; cross-check against the project's de-anonymization checklist |
If no listed method applies, ask the user before either accepting the claim or pushing back.
Outcome
Record one of three outcomes for each verified claim:
- Verified — the reviewer's claim is correct. Proceed with the fix as a normal
Will fixitem. - Refuted — the reviewer's claim is wrong, or the issue does not reproduce. Do not apply the fix. Push back via a follow-up reviewer prompt that cites the verification evidence (command run, output, URL fetched, file path inspected). The user may override this by asking to apply anyway, but the default is to push back.
- Inconclusive — verification could not run (no internet, no test runner, claim under-specified) or returned ambiguous results. Surface the ambiguity to the user and let them decide.
Round history integration
Findings flagged Refuted or Inconclusive enter the next round's Prior findings block (see Phase 1b item 8) so the reviewer sees the evidence and can either retract the claim or sharpen it. Refuted findings appear as (Refuted in round N — <one-line evidence>). Inconclusive findings appear as (Inconclusive in round N — <reason>), prompting the reviewer to supply a more specific or pre-verified check.
Example
Round 2 of a paper review. Reviewer flags High: "Citation [Smith2023] does not exist; could not find this paper on arXiv or Google Scholar."
- Trigger fires (High priority + checkable factual claim).
- Verification path:
WebSearch "Smith 2023 <topic keywords>", thenWebFetch arxiv.org/abs/<id>if a candidate surfaces. - Outcome:
- If a real paper is found → Refuted. Reply to the reviewer with the URL and arXiv ID, ask them to confirm before re-flagging. Do not edit the citation.
- If no paper is found after a reasonable search → Verified. Remove the citation or replace it with a real one.
- Record in round history:
[Smith2023] reference (Verified in round 2 — not present on arXiv or Google Scholar)or[Smith2023] reference (Refuted in round 2 — arxiv.org/abs/2023.XXXXX confirms paper).
Root Review Sink (per reviewer)
When a review produces substantial written feedback, each reviewer saves the latest review to Review-<AgentName>.md in the repository root. Normalize <AgentName> as follows: choose the stable agent or product name visible to the user (not a transient model/version list unless that is the only identity available); convert any run of whitespace to a single dash; delete every character except ASCII letters, digits, and dashes; collapse repeated dashes; trim leading and trailing dashes. Examples: Codex → Review-Codex.md, GitHub Copilot → Review-GitHub-Copilot.md, Gemini 3.1 Pro → Review-Gemini-31-Pro.md, Claude Code → Review-Claude-Code.md. If the normalized result is empty or a reviewer cannot identify itself with reasonable confidence, it uses Review-Unknown.md and notes the uncertainty at the top of the file.
One file per reviewer, one round per file. Treat each file as a reusable scratch file for the current review round, not as a permanent archive. By default, publish each new round by writing a complete temporary file beside the target and atomically renaming it over the reusable review file; do not create per-directory review files, and do not append multiple rounds, unless the user explicitly asks to preserve history. Running two reviewers in the same round produces two files (e.g., Review-Codex.md and Review-GitHub-Copilot.md), which Phase 2 reads together and consolidates.
Legacy CodexReview.md files from pre-upgrade sessions are ignored by Phase 2 intake. If one is present in the repo root or under docs/, treat it as stale scratch output from the old single-reviewer flow unless the user explicitly asks to inspect it.
The purpose of the Review-*.md files is to let the user and Claude Code read, reuse, and forward the latest review(s) without copy-pasting from chat. Keep each file in plain Markdown and make it directly useful on its own. Include:
- a
<!-- Round N -->HTML comment on the first line (used by Phase 2 to verify freshness) - a
Verification notesparagraph or short bulleted list at the top of the review (immediately after# Review), stating what was compiled, run, or verified; write "none" if nothing at runtime - the file or diff scope reviewed
- the review lens or context
- findings separated into New and Previously raised sections (previously raised items tagged Fixed, Still open, Reopened, or Deferred; on Round 1 the Previously raised section may be omitted or shown as "None")
- concrete recommended changes, with exact values when relevant
- for any finding flagged High priority, an exact suggested rewrite with file path and line range (use a fenced code block for multi-line rewrites)
Do not stage, commit, or move Review-*.md files unless the user explicitly asks. Before the first review round, check whether Review-*.md is excluded from git. Look in .gitignore and .git/info/exclude. If the pattern is not excluded anywhere, append Review-*.md to .git/info/exclude (a local, untracked ignore file) so that git add -A during the revision flow does not accidentally stage scratch files. A repo that already ships Review-*.md in the committed .gitignore (as this repo does) satisfies the exclusion requirement without a local edit.
Phase 3: Revise
- Address all "will fix" points and any "needs discussion" points the user approved.
- Update the round history: mark addressed findings as
Resolved, keep unaddressed ones asStill open, and tag user-deferred items asDeferred. This history carries forward into the next round's prompt (Phase 1b, item 8). - Stage the revised changes.
- Return to Phase 1 with an incremented round number.
Phase 4: Conclude
The loop ends when:
- The user says the review is done or approved.
- No reviewer raises actionable issues.
- The user decides to stop iterating.
At conclusion, present a short summary: total rounds, key changes made, and any unresolved points from the last review.
When Not To Use
- Trivial changes where review adds no value (typo fixes, config tweaks).
- Changes that require running tests or builds to validate -- run those first, then review.
- When the user wants a single-shot review with no revision loop; just ask a reviewer directly.
Frequently asked questions
What to verify before installation and use
What does the implement-review source document cover?
Review loop for staged changes. Detects content type, prepares a review request for Codex (Terminal-relay manual default, opt-in Auto-terminal codex-exec subprocess, or IDE plugin), categorizes feedback, revises, and iterates.
How do I install implement-review?
The source record exposes this install command: npx skills add https://github.com/yzhao062/anywhere-agents --skill "skills/implement-review". Inspect the command and pinned source before running it.
Which Agent platforms does the source record declare?
The pinned source record declares support for: codex.
Which permission-related actions were detected?
Static rules flagged read-files, write-files, exec-script, network in the source; the page lists the matching lines and excerpts.
Alternatives
Compare before choosing
vasilyu1983/AI-Agents-public
agents-hooks
Configures Claude Code hooks and Codex hooks.json/notify callbacks. Use when adding guardrails, preflight, audit trails, worktree automation, or budget enforcement.
vasilyu1983/AI-Agents-public
qa-testing-ios
Guides iOS testing with XCTest, XCUITest, Swift Testing, simctl, and xcresult. Use when choosing destinations, controlling flakes, or parsing test artifacts for native apps.
samber/cc-skills-golang
golang-samber-mo
Monadic types for Golang using samber/mo — Option, Result, Either, Future, IO, Task, and State types for type-safe nullable values, error handling, and functional composition with pipeline sub-packages. Apply when using or adopting samber/mo, when the codebase imports `github.com/samber/mo`, or when considering functional programming patterns as a safety design for Golang.
xiaolai/nlpm
conventions
Universal NL programming conventions — SKILL.md open spec (agentskills.io), AGENTS.md as canonical universal memory file, vague-quantifier list, prompt engineering layers, naming conventions, the override system. Tool-specific schemas live in nlpm:conventions-claude / nlpm:conventions-codex / nlpm:conventions-antigravity.