Skip to content

Plan-critic dispatch is recorded as a per-task critic required gate that no later step can satisfy #2757

Description

@andrewjfiore

Summary

A critic dispatch made before or during a task, whose prompt text contains a single plan task id, is recorded as a required critic gate on that task. The next accepted coder mutation clears the gate proof but keeps the requirement, and no later step ever re-records it. The task can then never reach complete, even on an otherwise perfect run.

The common trigger is the default plan critic (critic_pre_plan: true): the architect pastes the plan text into the critic prompt, the plan contains 1.1, and the review of the plan becomes a per-task gate on task 1.1.

Version

opencode-swarm@7.179.1 on OpenCode 1.18.21, Windows 11. The relevant source files are byte-identical on the 7.180.0 release branch (diffed 2026-09-13), so this is expected to reproduce there too.

Reproduction

  1. One-task plan (task 1.1). Leave critic_pre_plan at its default (true).
  2. Architect dispatches critic for the plan review and inlines the plan text (which contains the string 1.1) in the prompt, without an explicit task_id.
  3. The critic returns APPROVED.
  4. .swarm/evidence/task-gate-requirements/1.1.jsonl now holds a gate_recorded row for critic.
  5. Coder implements task 1.1; the mutation is accepted.
  6. check_gate_status for 1.1 now lists critic in required_gates with no proof. Nothing the architect can call re-records it: a second critic dispatch during the open task records again and is cleared again by the next mutation, and approve_plan_critic is scoped to the plan gate, not the per-task gate.
  7. update_task_status to complete is refused for the missing critic gate.

Reproduced twice in live runs and once with an offline replay against the 7.179.1 reducer (script available on request).

Observed

ci --json on such a run:

"task 1.1 gates": "missing gate evidence: critic, reviewer, test_engineer; workflow state rework_required is not terminal"

Where it happens

  • src/hooks/task-id-resolver.ts (around lines 54-56 and 255-271): the plan policy resolves a task id from free text in the dispatch prompt.
  • src/hooks/delegation-gate.ts (around lines 6204-6259): every gate agent, including critic and critic_sounding_board, is recorded through recordGateEvidence against the resolved task id.
  • src/hooks/gate-evidence.ts: clearWorkflowGateProof (around 520-531) drops the critic proof on accepted_mutation (around 869-871), while maybeExpandRequiredGates (around 474-486) keeps the requirement.

Expected

Either a plan-level critic review is not attributed to a task at all (it reviews the plan, not the task), or an attributed critic gate that was already satisfied survives an accepted mutation, or the architect has a tool to re-satisfy it. Any of the three would remove the dead end.

Impact

A one-task plan with the default gate profile can wedge at completion after correct, reviewed, tested work. The only workaround we found is critic_pre_plan: false plus a rule that the architect never dispatches critic or critic_sounding_board while a task is open, which removes the plan review entirely.

Related: #2703 (a critic verdict that has nowhere to be persisted; that one now has approve_retry_sounding_board, but it does not cover this gate).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions