From cross-agent-reviews
State-driven cross-agent spec/plan review pipeline. Use `/cr` to advance the active pipeline. Reads `.cross-agent-reviews/<slug>/state.json`, dispatches the next round (1a → 1b → 2a → 2b → 3a → 3b → 3c), terminating early when round 3a is clean and running final verification 3c only when round 3b corrects accepted blockers. Audit rounds (1a, 2a, 3a) and the verification round (3c) require fresh sessions; settle rounds (1b, 2b, 3b) do not. Supports cross-host paste-import for distributed reviews.
How this skill is triggered — by the user, by Claude, or both
Slash command
/cross-agent-reviews:crThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
[Full attribution](_shared/attribution.md)
_helpers/_cr_lib.py_helpers/cr_helpers/cr_extract_placeholders.py_helpers/cr_profile_suggest.py_helpers/cr_routing.py_helpers/cr_state_init.py_helpers/cr_state_pick_slug.py_helpers/cr_state_read.py_helpers/cr_state_status.py_helpers/cr_state_write.py_helpers/cr_validate.py_helpers/cr_validate_finding.py_shared/attribution.md_shared/cross-artifact-slice.md_shared/dispatch-template.md_shared/model-tier-rubric.md_shared/preflight.md_shared/schema/adjudication.schema.json_shared/schema/changelog-entry.schema.json_shared/schema/final-verification.schema.jsonCR_HELPER is the executable helper wrapper adjacent to this skill:
plugin/skills/cr/_helpers/cr in the installed plugin tree. Resolve the
currently loaded cr skill directory from the host-provided skill location
(the directory containing this SKILL.md). If the host does not expose that
path, ask the operator for the installed cr SKILL.md path and derive the
directory from it.
Before every shell tool call that invokes a helper, define CR_HELPER in that
same shell tool call, then invoke helpers as "${CR_HELPER}" <subcommand> ...:
CR_HELPER="<absolute path to the loaded cr skill directory>/_helpers/cr"
"${CR_HELPER}" state-pick-slug
Do not use host-specific plugin-root environment variables in shared prompt
material. Do not rely on export CR_HELPER persisting across shell tool calls.
Operator's input is one of:
/cr suggest <artifact-path>) — read-only; match this
first. When the operator's input begins with the literal token suggest
followed by an artifact path, run "${CR_HELPER}" profile-suggest --artifact-path <path> (add --artifact-type spec|plan when the path is not
under docs/specs/ or docs/plans/ and lacks a -design/-spec/-plan
suffix). Present the printed suggestion + evidence to the operator and
stop — this writes no state and starts no review. To act on it, the
operator re-runs /cr <path> <suggested-profile> [<suggested-mode>], which
locks the chosen values at init."${CR_HELPER}" state-pick-slug to pick the slug.docs/specs/foo-design.md) — start a new review or augment an existing slug. Run "${CR_HELPER}" state-pick-slug --input <path>.fast/thorough or patch/feature/greenfield
alongside an artifact path or slug (e.g. /cr docs/specs/foo-design.md fast patch), pass the operator's entire input string to
cr_state_pick_slug.py --input. The picker extracts them deterministically
and returns optional mode / review_profile fields. Reserved tokens with
no path/slug are rejected by the picker. --mode/--review-profile (and
= forms) are accepted aliases. A bare reserved word is always the
mode/profile token, never a lone artifact name — an operator whose artifact
is genuinely named fast (etc.) must pass an unambiguous path form such as
./fast, which routes as a path."${CR_HELPER}" state-pick-slug --input <slug>./cr status) — run "${CR_HELPER}" state-status [--slug <slug>] and present its output. For each block, state-status renders a Suggested: line (the recorded advisory profile/mode and its resolution rule) below the Mode:/Profile: line; when the suggestion diverges from the locked profile it adds a follow-up line noting that routing follows the locked value.If cr_state_pick_slug.py returns {"action": "ask_for_artifact_path"}, ask the operator for the artifact path or a state.json paste, then re-run.
If cr_state_pick_slug.py returns {"default": <slug>, "alternatives": [<slug>, ...]} (two or more active slugs), surface the disambiguation to the operator: list <default> first (most recent activity, with any pending_import slug surfaced ahead of recency per Phase 7) and the alternatives below it, then ask which slug to advance. After the operator answers, re-invoke "${CR_HELPER}" state-pick-slug --input <chosen-slug> to obtain {"slug": <chosen-slug>, "artifact_type": <spec|plan>} (the picker derives artifact_type from the latest block in state.json for slug-name input — see Phase 7). Use the result for §1 / §2; never proceed without artifact_type because §1's cr_state_init.py and §2's cr_state_read.py both require it.
Run cr_state_init.py when either of these holds:
.cross-agent-reviews/<slug>/state.json does not exist (first invocation for this slug), orstate.<artifact_type> block is absent (e.g., a completed spec review is being augmented with a plan, or a restart resolution from §2's spec-drift table is replacing the prior plan block under the same slug)."${CR_HELPER}" state-init --artifact-path <ARTIFACT_PATH> --artifact-type <spec|plan>
When cr_state_pick_slug.py returned mode and/or review_profile, pass
them to cr_state_init.py as --mode <value> / --review-profile <value>.
They are recorded into the new artifact block and locked — init is the only
place they are written.
cr_state_init.py already handles both cases (a fresh state file and adding a missing block to an existing one — see Phase 4). It writes/updates state.json, derives the slug, hashes the artifact, prompts to add .cross-agent-reviews/ to .gitignore (operator confirms [y/N]), and (for plan-only init) prints the warning per §11.3 of the spec.
<ARTIFACT_TYPE> is the artifact_type returned by cr_state_pick_slug.py. The picker derives it from the path's docs/specs/ vs. docs/plans/ directory (falling back to suffix -design/-spec/-plan per §5.5) when the input is an artifact path; for slug-name input and no-input single-active advance, it derives type from the latest block in state.json (most-recent last_updated_at, with ties going to spec). When the operator gave only a slug name and the relevant block is missing, the picker omits artifact_type and the router asks the operator for the artifact path before invoking the script.
The script's stdout is the state.json payload — capture it for cross-host scenarios.
At init, cr_state_init.py also records a deterministic, advisory
suggested_review_profile / suggested_mode / suggestion_evidence derived
from the artifact text. This is audit data only: it never changes routing, and
locked mode/review_profile still come solely from explicit operator tokens.
Accepting a suggestion means passing the suggested token on the first init —
there is no post-init accept path.
Take this branch only when §0 classified the input as outbound cross-host cue + artifact path (artifact path supplied alongside one of the outbound trigger phrases). This is the matching half of §3's inbound paste-import: §1.5 emits the bootstrap payload on Host A; §3 receives it on Host B. Do NOT take this branch for cues alone (those route to §3) or for artifact paths alone (those continue through §1 → §2 → §4 normally).
Run init with the gitignore prompt suppressed — the operator only wants the bootstrap JSON, not an interactive [y/N] confirmation:
"${CR_HELPER}" state-init --artifact-path <ARTIFACT_PATH> --artifact-type <spec|plan> --no-gitignore-prompt
When cr_state_pick_slug.py returned mode and/or review_profile, append
--mode <value> / --review-profile <value> to the command above — exactly
as §1 does. This bootstrap is a separate branch from §1, so the mode/profile
contract is not forwarded automatically: omitting the flags here emits a
bootstrap state.json with no locked contract, and Host B would silently run
legacy thorough behavior. Init is the only place mode/profile are written,
so a token dropped here cannot be recovered downstream.
Capture the script's stdout — that IS the canonical state.json payload (§1 already notes this). Present it to the operator with explicit copy instructions, then halt:
Bootstrap state.json for Host B (copy below). On Host B, run
/crand paste this JSON when prompted; that host will validate the paste and run round 1a.{ …captured stdout… }
After emitting the message, stop. Do NOT proceed to §2 (read state) or §4 (dispatch round 1a). Round 1a runs on Host B once the paste is validated there — running it on Host A would defeat the cross-host handoff. The operator's next /cr on Host A will be either a status query or an inbound paste cue (§3) when round 1a returns from Host B.
Read state:
"${CR_HELPER}" state-read --slug <slug> --artifact-type <spec|plan>
Parse the JSON output. The next stage is state.<artifact_type>.current_stage minus the round_ prefix and _pending suffix.
If integrity == "STATE_INTEGRITY_ERROR", halt with BLOCKED:state-integrity and surface to the operator. (Check this before any other branch — an integrity error invalidates every subsequent decision.)
Mode/profile tokens on non-mutating paths. The pending_import and ready_for_implementation branches below are non-mutating continuations — they sync state or report status, and neither re-runs init, so a post-init mode/profile token cannot change the locked contract there. When cr_state_pick_slug.py returned a mode or review_profile token and the next step is one of those two branches, reconcile the token non-fatally before continuing:
"${CR_HELPER}" state-read --slug <slug> --artifact-type <type> --assert-mode <value>
"${CR_HELPER}" state-read --slug <slug> --artifact-type <type> --assert-profile <value>
Zero exit — the token matches the locked value; continue silently, no notice.
Non-zero exit whose stderr is a BLOCKED:mode-conflict / BLOCKED:profile-conflict diagnostic — a genuine conflict. Do NOT halt. Emit a one-line NOTICE naming the ignored token and the locked value, then continue with the branch (pending-import proceeds to §3; a terminal artifact proceeds to its status query). The helper diagnostic already names the locked value, and shows legacy/unset when the block predates the mode/profile contract — reformat it into the NOTICE:
NOTICE: mode token `fast` ignored; this spec block is locked to `thorough`, and mode/profile cannot change after init.
NOTICE: review_profile token `feature` ignored; this plan block is locked to `patch`, and mode/profile cannot change after init.
NOTICE: review_profile token `patch` ignored; this spec block is locked to `legacy/unset`, and mode/profile cannot change after init.
If both the mode and profile tokens conflict, emit one NOTICE per conflicting token, then continue.
Any other non-zero exit — unexpected state/block absence or an argument error (rare after the successful state-read above). This is NOT a conflict: surface the helper diagnostic as an unexpected failure and halt; do not reformat it into a NOTICE.
If pending_import: true in the read output, the operator switched hosts; route to §3 paste-import. This check runs before the ready_for_implementation check below: a terminal cross-host handoff can leave state.<artifact_type>.current_stage == "ready_for_implementation" with completed_rounds including 3b while round-3b.json has not yet been pasted on this host (see Phase 6's _classify: pending_import flips true whenever any completed stage's round file is missing). Reading final_status from round-3b.json in that case would fail — the paste-import branch is what supplies the missing round file.
If state.<artifact_type>.current_stage == "ready_for_implementation", the pipeline has already terminated for this artifact. Do NOT proceed to §3 or §4. Classify the terminal shape from state.<artifact_type>.completed_rounds:
completed_rounds is the seven-round set {1a, 1b, 2a, 2b, 3a, 3b, 3c}. Read final_status from <state-dir>/<slug>/<artifact_type>/round-3c.json (always CORRECTED_AND_READY), then emit §5's via-3c terminal message.completed_rounds is the six-round set {1a, 1b, 2a, 2b, 3a, 3b}. Read final_status from round-3b.json; it MUST be READY_FOR_IMPLEMENTATION. If it is CORRECTED_PENDING_VERIFICATION, cr_state_read.py reports STATE_INTEGRITY_ERROR (caught by the integrity check above) — halt with BLOCKED:state-integrity.completed_rounds is the five-round set {1a, 1b, 2a, 2b, 3a} (no 3b). final_status is the constant READY_FOR_IMPLEMENTATION; do NOT read round-3b.json.completed_rounds is none of these sets. cr_state_read.py reports integrity == "STATE_INTEGRITY_ERROR"; halt with BLOCKED:state-integrity.A rerun of /cr after completion is a status query, not a new dispatch.
For plan rounds only, run a spec-drift check before dispatch:
"${CR_HELPER}" state-read --slug <slug> --check-spec-drift
Exit code 2 with SPEC_DRIFT_DETECTED on stderr means the spec file changed on disk vs. state.plan.spec_hash_at_start. Surface the three options from §7.8 of the design and translate the operator's choice into a scripted action; do not dispatch any sub-agent until drift is resolved.
| Operator choice | Router action |
|---|---|
restart (re-init the plan against the current spec) | "${CR_HELPER}" state-read --slug <slug> --resolve-drift restart. Then prompt the operator for the plan path and re-enter §1 to re-init the plan block under the same slug. |
accept-drift (assert the plan still matches the new spec) | "${CR_HELPER}" state-read --slug <slug> --resolve-drift accept. The script atomically refreshes state.plan.spec_hash_at_start to the current hash. Re-enter §2 with the new state. |
abort (resolve out of band) | Halt with BLOCKED:spec-drift and surface the diagnostic. The operator decides what to do; rerunning /cr after manual edits resumes the pipeline. |
Mode/profile conflict check. When cr_state_pick_slug.py returned a
mode or review_profile token and the artifact block already exists
(init was skipped), reconcile the token against the locked value before
dispatch:
"${CR_HELPER}" state-read --slug <slug> --artifact-type <type> --assert-mode <value>
"${CR_HELPER}" state-read --slug <slug> --artifact-type <type> --assert-profile <value>
A zero exit means the token matches the locked value (a no-op). A non-zero
exit means a conflict — halt with BLOCKED:mode-conflict or
BLOCKED:profile-conflict and surface the diagnostic (it names the locked
value). Mode and profile are fixed at init and cannot be changed mid-pipeline. This strict halt governs the active dispatch path only — when the router is proceeding to dispatch a real round. Conflicting tokens on the terminal and pending-import branches are handled by the Mode/profile tokens on non-mutating paths rule above, which emits a NOTICE and continues instead of halting.
If next stage is an audit round (1a, 2a, 3a) or the verification round (3c), execute the fresh-session preflight from _shared/preflight.md BEFORE doing anything else. If next stage is a settle round (1b, 2b, 3b), skip the preflight (per §5.4 of the spec).
If the operator's cue indicates a cross-host transition or local-only signal #2 (a completed_rounds entry whose round file is missing locally), enter paste-import:
.cross-agent-reviews/<slug>/ for any candidate slug): parse the pasted JSON's top-level slug field and use it. Bootstrap (state.json) and round payloads both carry slug per their schemas, so this is deterministic. If the parse fails or slug is missing, halt with a diagnostic and ask the operator to repaste."${CR_HELPER}" state-read --paste --slug <slug>, with the pasted JSON on stdin.state.json) vs round (round-<stage>.json) shape. Bootstrap: refuses to clobber an existing local state.json for the slug (§10.3). Round: enforces schema, identity (slug, artifact_type, artifact_path), and round-order (pasted stage matches the next-expected stage per local state, with the pending-import override).stage mismatch, slug mismatch, clobber refused).Map the derived stage token to its round file by suffix — audit rounds (1a, 2a, 3a) live in rounds/<stage>-audit.md; settle rounds (1b, 2b, 3b) live in rounds/<stage>-settle.md; the verification round (3c) lives in rounds/3c-verify.md. Read that file and execute the procedure there. Each round file:
_shared/dispatch-template.md."${CR_HELPER}" state-write --slug <slug> --artifact-type <type> --artifact-path <path> --input <payload-file> to persist.The script validates schema + cross-round invariants, atomically writes
round-<stage>.json + updates state.json, and emits byte-identical JSON
to stdout.
Exception: after a
1aor2awrite infastmode, a clean audit triggers auto-settle (§5). In that case stdout is a{"written_rounds": [<audit>, <settle>]}wrapper instead of a single envelope; the round files handle it.
If validation fails, the script exits 1 with a specific
diagnostic; you may auto-retry once with the LLM error context, then
halt with BLOCKED:validation for operator intervention (§6.5 of spec).
After cr_state_write.py succeeds, emit one of these messages to the
operator (per §9.2 of the spec):
blocker_found agents):
Round Na complete (M findings). Run /cr to continue with round Nb. A fresh session is not required for settle rounds; you may continue in this session or open a new one.
1a/2a in fast mode — cr_state_write.py returned a
{"written_rounds": [...]} wrapper, meaning the audit was clean and the
paired settle was auto-generated:
Round Na complete — clean audit, 0 findings. Round Nb was auto-generated as a no-op settle (fast mode). Open a fresh session and run /cr to continue with round (N+1)a (a fresh session is required before audit rounds). For a cross-host review, paste both round files shown above on the destination host, in order.
cr_state_write.py printed an
AUTO_SETTLE_FAILED: marker on stderr:
Round Na complete (0 findings). Auto-settle of round Nb failed (); the pipeline is at the manual-settle boundary. Run /cr to complete round Nb manually.
ship_ready, zero findings) — the pipeline terminates without round 3b:
Round 3a complete — final reviewer audit found zero blockers. Pipeline complete. final_status: READY_FOR_IMPLEMENTATION (clean 3a — round 3b skipped). The artifact is ready for implementation.
Round Nb complete (P accepted, Q rejected). Open a fresh session and run /cr to continue with round (N+1)a (a fresh session is required before audit rounds).
Round 3b complete (P accepted, Q rejected) — final blockers corrected. Final verification (round 3c) is required. Open a fresh session and run /cr to verify the corrections.
Pipeline complete. final_status: READY_FOR_IMPLEMENTATION (round 3b rejected all final blockers). The artifact is ready for implementation.
Final verification passed. Pipeline complete. final_status: CORRECTED_AND_READY — every accepted final blocker was independently verified as resolved. The artifact is ready for implementation.
Final verification FAILED (attempt N): K accepted blocker(s) still unresolved, R regression(s) introduced. See round-3c-attempt-NNN.json. Fix the artifact, then run /cr to re-verify. BLOCKED:final-verification
If the operator asks for a status view (/cr status, "show status", "what round are we on?"), run:
"${CR_HELPER}" state-status [--slug <slug>]
Present its output verbatim.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub j7an/cross-agent-reviews --plugin cross-agent-reviews