Ticket 2/4 of the harness workstream (see #293). Primary source: docs/harness-review-2026-08-16.md (sections 一, A-1, A-3). No upstream blockers; independent of #293.
Problem Statement
When a review checkpoint returns REJECT, the harness terminalizes the workflow as failed — and failed workflows are immutable. That makes two of the four options in the Verdict Disposal Contract physically unreachable: additive extend (reopen requires status completed) and pause→replan→resume (replan rejects terminal workflows). The only surviving disposal is "start a new workflow", which discards accumulated evidence. This is why post-checkpoint replan has never been observed: it is structurally impossible, not a model-luck story.
Root cause chain (all evidence in the primary source):
- The review node with REJECT settles as a completed node (correct per policy: "a gate that successfully returns REVISE or REJECT is a completed node, not a failed node").
- The scheduling loop then detects unresolved review outcomes and fails the whole workflow.
- Reopen-by-extend is explicitly designed for the REJECT shape — its rationale comment names skipped dependents as non-executed so the graph "effectively ended at the checkpoint" — but only accepts
completed workflows.
The harness contradicts its own policy: node-level rule says REJECT = completed; workflow-level behaviour says REJECT = failed.
Solution
Restore the designed-but-unreachable path with the smallest guard relocation:
- The scheduling loop stops failing a workflow over unresolved review outcomes; the graph completes naturally at the REJECT checkpoint (all remaining nodes conditional-skipped → checkpoint is a reporting leaf with zero executed dependents).
- The unresolved-review guard moves from the shared completion function to the tool-layer explicit complete action, where it belongs: an agent may not shortcut an unresolved review into "done", but a naturally reached checkpoint may complete so the parent can dispose of it.
- Wake already carries verdict + findings + required_actions (review blocks report to parent by default), so loudness is preserved through the checkpoint wake, not the terminal status string.
- Workflow status output surfaces outstanding review verdicts explicitly, instead of only in a failure-reason string.
User Stories
- As a parent orchestrator, I want a REJECT verdict to leave the workflow completed and reopenable, so that I can add a bounded correction wave without starting over.
- As a parent orchestrator, I want to be woken at the review checkpoint carrying the findings, so that I can act in the same turn as mandated by the Verdict Disposal Contract.
- As a parent orchestrator, I want status to list outstanding review verdicts, so that I never misread a completed workflow as an accepted one.
- As a maintainer, I want an explicit "complete while review unresolved" shortcut to keep failing, so that agents cannot launder a REJECT into done.
- As a maintainer, I want the node-level and workflow-level treatment of REJECT to agree, so that the harness no longer contradicts its stated policy.
Implementation Decisions
- Guard relocation, not removal: the unresolved-review check moves from the shared completion path to the explicit completion tool action; natural completion is unguarded, agent shortcuts stay guarded.
- The loop's terminal failure over unresolved reviews is deleted; completion at a conditional-skipped tail is the intended terminal shape.
- Review settlement, fingerprint echo, and correction-review lifecycle remain untouched — the review surface is invariant; only workflow-level disposal changes.
- Status reporting gains explicit unresolved-verdict surfacing (structured, not parsed from a reason string).
- Tests that pinned the old failing behaviour are identified and rewritten; review-lifecycle tests remain untouched and green.
Testing Decisions
- The seam is the durable lifecycle boundary: build a graph with a review gate that settles REJECT, assert workflow status becomes completed (not failed), then assert additive reopen-extend with new node IDs is accepted, and assert the explicit-complete shortcut with unresolved review is still rejected.
- Prior art: existing DAG lifecycle and review-audit regression tests; the reopen/extend path already has its own test surface around the reporting-leaf exception.
Out of Scope
- Pause-on-REJECT with the orchestrator watchdog (variant A4): explicitly deferred until this ticket produces operational feel — then re-decide.
- The verdict-disposal classifier wording: ticket 4/4, blocked by this ticket.
- Config repository wording changes: ticket 3/4.
Further Notes
- After this lands, the REJECT loop becomes observable for the first time — capture the experience before deciding on A4 (pause + watchdog).
Problem Statement
When a review checkpoint returns REJECT, the harness terminalizes the workflow as failed — and failed workflows are immutable. That makes two of the four options in the Verdict Disposal Contract physically unreachable: additive
extend(reopen requires statuscompleted) andpause→replan→resume(replan rejects terminal workflows). The only surviving disposal is "start a new workflow", which discards accumulated evidence. This is why post-checkpoint replan has never been observed: it is structurally impossible, not a model-luck story.Root cause chain (all evidence in the primary source):
completedworkflows.The harness contradicts its own policy: node-level rule says REJECT = completed; workflow-level behaviour says REJECT = failed.
Solution
Restore the designed-but-unreachable path with the smallest guard relocation:
User Stories
Implementation Decisions
Testing Decisions
Out of Scope
Further Notes