Gate unexpected-pass settles verdict escalate, routing to the orchestrator escalation terminal #523

Closed
opened 2026-08-27 19:49:00 +00:00 by jared · 2 comments
Owner

Context

On #510 run 3, the test-writer node looped to bound_exhausted:test-writer/fail and killed the run because the test gate (expect: red) scored a green-on-arrival test as verdict fail — the behavior had already shipped, so red was impossible. The node's escalate: edge (validated by #513) sat unused because no gate path ever emits escalate. Decided with the user 2026-08-27: an unexpected pass settles verdict escalate on first occurrence, riding the existing escalate edge to the needs-orchestrator terminal so the orchestrator resolves it in-session; human escalation stays a last resort. Amends ADR-0147 (per-gate expect + red classifier).

Tasks

  • Gate settlement: when a gate with expect: red observes green (unexpected pass), settle verdict escalate instead of fail.
  • Escalation payload names the cause (unexpected_pass, gate, node) so the orchestrator's escalation procedure can act without inspection.
  • Regression test reproducing the #510 shape: green-on-arrival test at test-writer settles escalate on the first round, spends no fail bound.
  • Amending ADR via /os-adr:create (amends 0147; scope note against 0152).
  • History row in the os-sdlc implementation-status leaf.

Acceptance criteria

  • A test gate that expects red and sees green settles escalate; the runner returns the escalation payload, not bound_exhausted, with no fail-edge spend.
  • Existing red-for-the-right-reason and pass paths byte-identical in behavior; full suite green.

Origin

  • Trigger: /os-sdlc:implement 510 run 3 terminated bound_exhausted:test-writer/fail (2026-08-27); investigation pinned next_step.rb RoutingApplier#spent_decision + maps/poodr-implementation.yaml test-writer node.
  • Improvised this session: user manually accepted #510's completed work (override precedent #491).
  • Chain: run killed at test-writer ← gate collapses unexpected-pass into fail ← DESIGN (ADR-0147 red classifier has no unexpected-pass verdict)
  • Root candidate: this ticket
## Context On #510 run 3, the test-writer node looped to bound_exhausted:test-writer/fail and killed the run because the test gate (expect: red) scored a green-on-arrival test as verdict fail — the behavior had already shipped, so red was impossible. The node's escalate: edge (validated by #513) sat unused because no gate path ever emits escalate. Decided with the user 2026-08-27: an unexpected pass settles verdict escalate on first occurrence, riding the existing escalate edge to the needs-orchestrator terminal so the orchestrator resolves it in-session; human escalation stays a last resort. Amends ADR-0147 (per-gate expect + red classifier). ## Tasks - [ ] Gate settlement: when a gate with expect: red observes green (unexpected pass), settle verdict escalate instead of fail. - [ ] Escalation payload names the cause (unexpected_pass, gate, node) so the orchestrator's escalation procedure can act without inspection. - [ ] Regression test reproducing the #510 shape: green-on-arrival test at test-writer settles escalate on the first round, spends no fail bound. - [ ] Amending ADR via /os-adr:create (amends 0147; scope note against 0152). - [ ] History row in the os-sdlc implementation-status leaf. ## Acceptance criteria - [ ] A test gate that expects red and sees green settles escalate; the runner returns the escalation payload, not bound_exhausted, with no fail-edge spend. - [ ] Existing red-for-the-right-reason and pass paths byte-identical in behavior; full suite green. ## Origin - Trigger: /os-sdlc:implement 510 run 3 terminated bound_exhausted:test-writer/fail (2026-08-27); investigation pinned next_step.rb RoutingApplier#spent_decision + maps/poodr-implementation.yaml test-writer node. - Improvised this session: user manually accepted #510's completed work (override precedent #491). - Chain: run killed at test-writer ← gate collapses unexpected-pass into fail ← DESIGN (ADR-0147 red classifier has no unexpected-pass verdict) - Root candidate: this ticket
Author
Owner

Work started. Branch: ticket-523. Built directly (TDD agent), not via the os-sdlc pipeline, since the pipeline exhibits this very bug on greenfield/unexpected-pass shapes.

Work started. Branch: ticket-523. Built directly (TDD agent), not via the os-sdlc pipeline, since the pipeline exhibits this very bug on greenfield/unexpected-pass shapes.
Author
Owner

Resolution

Done: Gate unexpected-pass now settles verdict escalate: GateVerdict emits escalate when the red classifier yields :unexpected_pass (first occurrence, no fail-edge spend); routing rides the node's existing escalate: edge to the needs-orchestrator terminal; escalation reason names the cause unexpected_pass:/ via RoutingApplier::UnexpectedPassReason so the orchestrator acts on the payload alone. ADR-0158 records the decision (amends ADR-0147); history row added.

Evidence: Merged to main: 0ce1296 (feat), a3daaf0 (ADR-0158 + history row). New integration test test_an_expect_red_gate_unexpected_pass_escalates_on_the_first_occurrence asserts payload type escalation, reason unexpected_pass:start/test, and zero fail-edge spends; red-for-right-reason and expect:green tests untouched and green. Suite on main after merge: 1227 runs, 0 failures. Rubocop: zero offenses on changed production files.

Follow-ups: Surface unexpected_pass explicitly in the immediate agent-facing gate reply (GateReply/GateHandoff), not just the escalation payload — minor, unticketed by choice: the escalation path already carries the cause. Option-2 complement (local bound exhaustion preferring escalate: when the node has one) deliberately not built per ADR-0158 alternatives. No other follow-ups.

## Resolution **Done:** Gate unexpected-pass now settles verdict escalate: GateVerdict emits escalate when the red classifier yields :unexpected_pass (first occurrence, no fail-edge spend); routing rides the node's existing escalate: edge to the needs-orchestrator terminal; escalation reason names the cause unexpected_pass:<node>/<gate> via RoutingApplier::UnexpectedPassReason so the orchestrator acts on the payload alone. ADR-0158 records the decision (amends ADR-0147); history row added. **Evidence:** Merged to main: 0ce1296 (feat), a3daaf0 (ADR-0158 + history row). New integration test test_an_expect_red_gate_unexpected_pass_escalates_on_the_first_occurrence asserts payload type escalation, reason unexpected_pass:start/test, and zero fail-edge spends; red-for-right-reason and expect:green tests untouched and green. Suite on main after merge: 1227 runs, 0 failures. Rubocop: zero offenses on changed production files. **Follow-ups:** Surface unexpected_pass explicitly in the immediate agent-facing gate reply (GateReply/GateHandoff), not just the escalation payload — minor, unticketed by choice: the escalation path already carries the cause. Option-2 complement (local bound exhaustion preferring escalate: when the node has one) deliberately not built per ADR-0158 alternatives. No other follow-ups.
jared closed this issue 2026-08-27 19:57:46 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jared/cc-os#523
No description provided.