Critic Gate Protocol
This protocol is loaded on demand by the architect runtime. The architect prompt keeps only activation, action, and hard safety constraints; the full execution details live here.
Graph-first evidence contract
Before judging plan coverage, use repo_map graph_health and targeted impact_cone evidence for proposed shared surfaces. Graph evidence is advisory only. If freshness is stale or inconclusive, confidence is low, source is missing, the language is unsupported/dynamic, the graph is absent, or an action fails, inspect the direct source and searches before the verdict.
MODE: CRITIC-GATE
Delegate plan to the active swarm's critic agent for review BEFORE any implementation begins.
- Send the full plan.md content and codebase context summary
- Explicitly reference "plan.md" or "critic-gate" in the dispatch prompt text. This lets the mechanical approval-recording gate reliably detect the review and record the critic's APPROVED verdict, which the EXECUTE-phase coder gate then requires.
- APPROVED → Proceed to MODE: EXECUTE
- NEEDS_REVISION → Revise the plan based on critic feedback, then resubmit (max 2 cycles)
- REJECTED → Inform the user of fundamental issues and ask for guidance before proceeding
⛔ HARD STOP — Print this checklist before advancing to MODE: EXECUTE:
[ ] the active swarm's critic agent returned a verdict
[ ] APPROVED → proceed to MODE: EXECUTE
[ ] NEEDS_REVISION → revised and resubmitted (attempt N of max 2)
[ ] REJECTED (any cycle) → informed user. STOP.
You MUST NOT proceed to MODE: EXECUTE without printing this checklist with filled values.
Post-approval verification: Before dispatching the first coder in
MODE: EXECUTE, call get_approved_plan to confirm the critic's APPROVED
verdict was recorded. The approval-recording heuristic can fail silently
if the dispatch prompt didn't contain the expected keywords. Dispatching
coders without a recorded approval wastes cycles — the coder gate will
reject with PLAN_CRITIC_GATE_VIOLATION. One read-only call prevents
this entire failure class.
Escape hatch (issue #2012): If the critic genuinely returned APPROVED
but the mechanical recorder failed to persist the snapshot (verdict-format
mismatch, dispatch-signal miss, or a plan.json read race) AND re-running
MODE: CRITIC-GATE does not help, call approve_plan_critic with a
one-line reason (or ask the user to run /swarm approve-plan-critic <reason>). This records a manual plan_critic_gate approval snapshot
tagged method: "manual_override", audited to .swarm/events.jsonl.
Architect-only. Use ONLY when a legitimate APPROVED was lost — this is an
escape hatch, not a substitute for running the critic review. It is also the sanctioned recovery for a bookkeeping-grade hashed-field repair under PLAN FREEZE below.
CRITIC-GATE TRIGGER: Run ONCE when you first write the complete .swarm/plan.md.
Do NOT re-run CRITIC-GATE before every project phase.
If resuming a project with an existing approved plan, CRITIC-GATE is already satisfied.
Caveat: this assumption breaks if the plan lacks a plan_critic_gate-tagged approval snapshot (e.g. a plan approved before this mechanical gate existed, or one where the recording heuristic didn't fire) — in that case the first coder dispatch will fail with PLAN_CRITIC_GATE_VIOLATION. If that happens, do not assume CRITIC-GATE is satisfied; re-run it and get a fresh APPROVED verdict.
PLAN FREEZE AFTER APPROVAL (issue #1994 P1): once the critic returns APPROVED, the plan is frozen. The coder dispatch gate compares the plan against the approval snapshot via the structure hash (computePlanStructureHash), so classify post-approval changes by what that hash actually covers:
- STATUS-ONLY changes (task status transitions via
update_task_status) are excluded from the hash and never invalidate the approval — no re-critic needed.
- MATERIAL (invalidates the approval): adding or removing tasks — a removal is acknowledged via the
removed_task_ids save_plan argument, and it is the task's absence from the hashed task array (never the argument itself) that the hash captures — or changing any task's id, phase, description, acceptance, or depends. Re-run MODE: CRITIC-GATE exactly ONCE on the revised plan and get a fresh APPROVED before the next coder dispatch — the dispatch fails PLAN_CRITIC_GATE_VIOLATION against the stale snapshot otherwise.
- DEFAULT-MATERIAL CATCH-ALL: any hashed field not classified by the other bullets in this list is MATERIAL by default.
computePlanStructureHash also covers schema_version, swarm, migration_status, execution_profile, and the phase-level id, name, and required_agents; changing any of these requires a fresh re-critic, never the bookkeeping recovery.
fr_refs changes are MATERIAL on process grounds (spec traceability feeds the critic's obligation check) even though the hash deliberately excludes fr_refs — the runtime will not catch this for you; re-critic is still required.
- BOOKKEEPING-GRADE hashed fields (
size, evidence_path, blocked_reason, title, current_phase, files_touched) trip the gate mechanically even for pure bookkeeping edits. For a genuine bookkeeping repair — most commonly a files_touched-only reconciliation aligned with an active declare_scope binding (the sanctioned SCOPE_CONFLICT repair path in the execute skill) — use the gate's own recovery: approve_plan_critic with a truthful one-line reason (audited to .swarm/events.jsonl), not a full re-critic. Any substantive scope growth beyond reconciliation is MATERIAL: re-critic.
Batching rule: material changes accumulated across multiple save_plan calls since the last APPROVED count as ONE batch — re-critic that batch once, and never split material changes across separate calls to dodge the re-critic. The pre-change approval is never valid for the changed plan.
6j. SPEC-GATE (Execute BEFORE any save_plan call):
- An effective spec exists iff
/swarm sdd status reports a resolved spec (it reflects readEffectiveSpecSync, which returns null — NO effective spec — for no sources, multiple competing sources (openspec+specify), multi-feature Spec-Kit without a selected feature, or any unresolvable state). save_plan rejects (SPEC_REQUIRED) when /swarm sdd status reports no resolved spec. The gate is overridable via SWARM_SKIP_SPEC_GATE=1.
- Before calling save_plan, verify an effective spec exists (via
/swarm sdd status or lint_spec).
- If no effective spec exists: do NOT call save_plan. Generate one first — native via
/swarm specify, or via the agent-invocable /swarm sdd project (from SDD sources, after consent).
- This rule is satisfied by the save_plan tool's own spec gate — it exists as a reminder that planning requires a spec.
6k. SPEC-STALENESS GUARD:
- If _specStale or .swarm/spec-staleness.json exists, the Architect MUST stop
and SURFACE THE DRIFT TO THE USER. The user (not the Architect) then runs
either:
- /swarm clarify to update the spec and align it with the plan, OR
- /swarm acknowledge-spec-drift to acknowledge the drift and suppress further warnings
- The Architect MUST NOT run /swarm acknowledge-spec-drift itself — not via
the swarm_command tool, not via the chat fallback, and NOT by shelling out
to
bunx opencode-swarm run acknowledge-spec-drift (or any equivalent
npx/node/bun invocation). Any such self-invocation is a
control-bypass and will be refused by the runtime guardrails.
- Do NOT proceed with implementation until the user resolves the staleness.
- When re-saving a plan in response to spec drift, save_plan REQUIRES that ANY task
present in the prior plan but absent from the new args.phases be enumerated
in removed_task_ids with a removal_reason. save_plan will reject the call
otherwise (PLAN_TASK_REMOVAL_NOT_ACKNOWLEDGED). Tasks not yet finished
(status: pending, in_progress, blocked) MUST NOT be removed without explicit
user confirmation — surface the list to the user and ask before populating
removed_task_ids.
- While .swarm/spec-staleness.json exists, the runtime STRUCTURALLY BLOCKS the
following tools (SPEC_DRIFT_BLOCKED_TOOLS): save_plan, update_task_status,
phase_complete, lean_turbo_run_phase, lean_turbo_acquire_locks. If a call
returns SPEC_DRIFT_BLOCK, do NOT retry; surface the drift to the user and
WAIT for them to run /swarm clarify or /swarm acknowledge-spec-drift.
6l. OBLIGATION TRACEABILITY CHECK (FR-003):
- Before the critic's substantive rubric, the critic MUST cross-reference every
MUST/SHALL SC-### obligation in the EFFECTIVE spec against the plan tasks.
An effective spec exists iff
/swarm sdd status reports a resolved spec (it
reflects readEffectiveSpecSync, which returns null — NO effective spec — for
no sources, multiple competing sources (openspec+specify), multi-feature
Spec-Kit without a selected feature, or any unresolvable state). Obligations
are traced only against the resolved effective spec; in a null/unresolved
state there is nothing to trace (this check is not applicable).
- If ANY MUST/SHALL SC-### has zero corresponding plan tasks, the critic MUST
return VERDICT: REJECTED enumerating each unmapped obligation.
- The critic MUST evaluate coverage against the FULL plan — each task's
description AND acceptance criteria. An SC-### is "mapped" if referenced
in ANY task's description OR acceptance field. Read plan.json (the structured
plan object) rather than relying solely on plan.md, which omits acceptance
criteria.
- This is a structural-completeness failure, not a style concern.
- The detection logic mirrors the existing ANALYZE-mode SC-### coverage check:
map each spec obligation to the task(s) whose description or acceptance field
addresses it, then flag obligations with zero covering tasks as gaps — MUST
obligations with no covering task are CRITICAL severity, SHOULD obligations
with no covering task are HIGH severity, and SC-### success criteria with no
covering task are HIGH severity (untestable success criteria = unverifiable
requirement).
1---2name: critic-gate3description: Full execution protocol for MODE: CRITIC-GATE -- plan critic review, revision loops, and hard stop before execution.4---56# Critic Gate Protocol78This protocol is loaded on demand by the architect runtime. The architect prompt keeps only activation, action, and hard safety constraints; the full execution details live here.910## Graph-first evidence contract1112Before judging plan coverage, use `repo_map` `graph_health` and targeted `impact_cone` evidence for proposed shared surfaces. Graph evidence is advisory only. If freshness is stale or inconclusive, confidence is low, source is missing, the language is unsupported/dynamic, the graph is absent, or an action fails, inspect the direct source and searches before the verdict.1314### MODE: CRITIC-GATE15Delegate plan to the active swarm's critic agent for review BEFORE any implementation begins.16- Send the full plan.md content and codebase context summary17- Explicitly reference "plan.md" or "critic-gate" in the dispatch prompt text. This lets the mechanical approval-recording gate reliably detect the review and record the critic's APPROVED verdict, which the EXECUTE-phase coder gate then requires.18- **APPROVED** → Proceed to MODE: EXECUTE19- **NEEDS_REVISION** → Revise the plan based on critic feedback, then resubmit (max 2 cycles)20- **REJECTED** → Inform the user of fundamental issues and ask for guidance before proceeding2122⛔ HARD STOP — Print this checklist before advancing to MODE: EXECUTE:23 [ ] the active swarm's critic agent returned a verdict24 [ ] APPROVED → proceed to MODE: EXECUTE25 [ ] NEEDS_REVISION → revised and resubmitted (attempt N of max 2)26 [ ] REJECTED (any cycle) → informed user. STOP.2728You MUST NOT proceed to MODE: EXECUTE without printing this checklist with filled values.2930**Post-approval verification:** Before dispatching the first coder in31MODE: EXECUTE, call `get_approved_plan` to confirm the critic's APPROVED32verdict was recorded. The approval-recording heuristic can fail silently33if the dispatch prompt didn't contain the expected keywords. Dispatching34coders without a recorded approval wastes cycles — the coder gate will35reject with `PLAN_CRITIC_GATE_VIOLATION`. One read-only call prevents36this entire failure class.3738**Escape hatch (issue #2012):** If the critic genuinely returned APPROVED39but the mechanical recorder failed to persist the snapshot (verdict-format40mismatch, dispatch-signal miss, or a plan.json read race) AND re-running41MODE: CRITIC-GATE does not help, call `approve_plan_critic` with a42one-line `reason` (or ask the user to run `/swarm approve-plan-critic43<reason>`). This records a manual `plan_critic_gate` approval snapshot44tagged `method: "manual_override"`, audited to `.swarm/events.jsonl`.45Architect-only. Use ONLY when a legitimate APPROVED was lost — this is an46escape hatch, not a substitute for running the critic review. It is also the sanctioned recovery for a bookkeeping-grade hashed-field repair under PLAN FREEZE below.4748CRITIC-GATE TRIGGER: Run ONCE when you first write the complete .swarm/plan.md.49Do NOT re-run CRITIC-GATE before every project phase.50If resuming a project with an existing approved plan, CRITIC-GATE is already satisfied.51Caveat: this assumption breaks if the plan lacks a `plan_critic_gate`-tagged approval snapshot (e.g. a plan approved before this mechanical gate existed, or one where the recording heuristic didn't fire) — in that case the first coder dispatch will fail with `PLAN_CRITIC_GATE_VIOLATION`. If that happens, do not assume CRITIC-GATE is satisfied; re-run it and get a fresh APPROVED verdict.5253PLAN FREEZE AFTER APPROVAL (issue #1994 P1): once the critic returns APPROVED, the plan is frozen. The coder dispatch gate compares the plan against the approval snapshot via the structure hash (`computePlanStructureHash`), so classify post-approval changes by what that hash actually covers:54- STATUS-ONLY changes (task status transitions via `update_task_status`) are excluded from the hash and never invalidate the approval — no re-critic needed.55- MATERIAL (invalidates the approval): adding or removing tasks — a removal is acknowledged via the `removed_task_ids` `save_plan` argument, and it is the task's absence from the hashed task array (never the argument itself) that the hash captures — or changing any task's `id`, `phase`, `description`, `acceptance`, or `depends`. Re-run MODE: CRITIC-GATE exactly ONCE on the revised plan and get a fresh APPROVED before the next coder dispatch — the dispatch fails `PLAN_CRITIC_GATE_VIOLATION` against the stale snapshot otherwise.56- DEFAULT-MATERIAL CATCH-ALL: any hashed field not classified by the other bullets in this list is MATERIAL by default. `computePlanStructureHash` also covers `schema_version`, `swarm`, `migration_status`, `execution_profile`, and the phase-level `id`, `name`, and `required_agents`; changing any of these requires a fresh re-critic, never the bookkeeping recovery.57- `fr_refs` changes are MATERIAL on process grounds (spec traceability feeds the critic's obligation check) even though the hash deliberately excludes `fr_refs` — the runtime will not catch this for you; re-critic is still required.58- BOOKKEEPING-GRADE hashed fields (`size`, `evidence_path`, `blocked_reason`, `title`, `current_phase`, `files_touched`) trip the gate mechanically even for pure bookkeeping edits. For a genuine bookkeeping repair — most commonly a `files_touched`-only reconciliation aligned with an active `declare_scope` binding (the sanctioned `SCOPE_CONFLICT` repair path in the execute skill) — use the gate's own recovery: `approve_plan_critic` with a truthful one-line reason (audited to `.swarm/events.jsonl`), not a full re-critic. Any substantive scope growth beyond reconciliation is MATERIAL: re-critic.59Batching rule: material changes accumulated across multiple `save_plan` calls since the last APPROVED count as ONE batch — re-critic that batch once, and never split material changes across separate calls to dodge the re-critic. The pre-change approval is never valid for the changed plan.60616j. SPEC-GATE (Execute BEFORE any save_plan call):62- An effective spec exists iff `/swarm sdd status` reports a resolved spec (it reflects `readEffectiveSpecSync`, which returns null — NO effective spec — for no sources, multiple competing sources (openspec+specify), multi-feature Spec-Kit without a selected feature, or any unresolvable state). `save_plan` rejects (SPEC_REQUIRED) when `/swarm sdd status` reports no resolved spec. The gate is overridable via `SWARM_SKIP_SPEC_GATE=1`.63- Before calling save_plan, verify an effective spec exists (via `/swarm sdd status` or `lint_spec`).64- If no effective spec exists: do NOT call save_plan. Generate one first — native via `/swarm specify`, or via the agent-invocable `/swarm sdd project` (from SDD sources, after consent).65- This rule is satisfied by the save_plan tool's own spec gate — it exists as a reminder that planning requires a spec.66676k. SPEC-STALENESS GUARD:68- If _specStale or .swarm/spec-staleness.json exists, the Architect MUST stop69 and SURFACE THE DRIFT TO THE USER. The user (not the Architect) then runs70 either:71 - /swarm clarify to update the spec and align it with the plan, OR72 - /swarm acknowledge-spec-drift to acknowledge the drift and suppress further warnings73- The Architect MUST NOT run /swarm acknowledge-spec-drift itself — not via74 the swarm_command tool, not via the chat fallback, and NOT by shelling out75 to `bunx opencode-swarm run acknowledge-spec-drift` (or any equivalent76 `npx`/`node`/`bun` invocation). Any such self-invocation is a77 control-bypass and will be refused by the runtime guardrails.78- Do NOT proceed with implementation until the user resolves the staleness.79- When re-saving a plan in response to spec drift, save_plan REQUIRES that ANY task80 present in the prior plan but absent from the new args.phases be enumerated81 in removed_task_ids with a removal_reason. save_plan will reject the call82 otherwise (PLAN_TASK_REMOVAL_NOT_ACKNOWLEDGED). Tasks not yet finished83 (status: pending, in_progress, blocked) MUST NOT be removed without explicit84 user confirmation — surface the list to the user and ask before populating85 removed_task_ids.86 - While .swarm/spec-staleness.json exists, the runtime STRUCTURALLY BLOCKS the87 following tools (SPEC_DRIFT_BLOCKED_TOOLS): save_plan, update_task_status,88 phase_complete, lean_turbo_run_phase, lean_turbo_acquire_locks. If a call89 returns SPEC_DRIFT_BLOCK, do NOT retry; surface the drift to the user and90 WAIT for them to run /swarm clarify or /swarm acknowledge-spec-drift.91926l. OBLIGATION TRACEABILITY CHECK (FR-003):93- Before the critic's substantive rubric, the critic MUST cross-reference every94 MUST/SHALL SC-### obligation in the EFFECTIVE spec against the plan tasks.95 An effective spec exists iff `/swarm sdd status` reports a resolved spec (it96 reflects `readEffectiveSpecSync`, which returns null — NO effective spec — for97 no sources, multiple competing sources (openspec+specify), multi-feature98 Spec-Kit without a selected feature, or any unresolvable state). Obligations99 are traced only against the resolved effective spec; in a null/unresolved100 state there is nothing to trace (this check is not applicable).101- If ANY MUST/SHALL SC-### has zero corresponding plan tasks, the critic MUST102 return VERDICT: REJECTED enumerating each unmapped obligation.103- The critic MUST evaluate coverage against the FULL plan — each task's104 description AND acceptance criteria. An SC-### is "mapped" if referenced105 in ANY task's description OR acceptance field. Read plan.json (the structured106 plan object) rather than relying solely on plan.md, which omits acceptance107 criteria.108- This is a structural-completeness failure, not a style concern.109- The detection logic mirrors the existing ANALYZE-mode SC-### coverage check:110 map each spec obligation to the task(s) whose description or acceptance field111 addresses it, then flag obligations with zero covering tasks as gaps — MUST112 obligations with no covering task are CRITICAL severity, SHOULD obligations113 with no covering task are HIGH severity, and SC-### success criteria with no114 covering task are HIGH severity (untestable success criteria = unverifiable115 requirement).