Route a failing required-work gate step instead of crashing on correction_rounds.gate_type #841
Labels
No labels
P0
P1
P2
P3
bug
category/code-change
category/cross-repo
category/eval-run
category/investigation
category/no-test-target
category/owner-ruling
category/prose-artifact
category/recurring-chore
category/structure
category/umbrella
crc-refactor
create
delete
enhancement
filed-by/agent
filed-by/user
frozen
lint-rule
needs-info
needs-triage
next
plugin/cc-architect
plugin/os
plugin/os-adr
plugin/os-aidd-lint
plugin/os-backlog
plugin/os-context
plugin/os-doc-hygiene
plugin/os-sdlc
plugin/os-vault
project/cc-os
ready-for-agent
ready-for-human
recurring
review
rule-proposal
update
waiting
wayfinder:grilling
wayfinder:map
wayfinder:map
wayfinder:research
wayfinder:task
wayfinder:task
wontfix
worklist/deviations
worklist/lint-rule
worklist/new-implement-build
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
jared/cc-os#841
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
A failed gate step with no violation parser crashes the gate. The Runner ends the run with
verdict:errorand does not route the failure to repair.StepOutcome#gate_type)lint,test-lint"lint"test,diff-test,suite"test"required-worknilverdict:error,implementation_failedfailedge (suite-check → programmer-repair)retired-testsnilverdict:error,implementation_failedfailedge (test-writer)Evidence:
What happened (implementation 4, #836, dispatch 30; implementation 10, #843, dispatch 61):
required-work(orretired-tests) step exits non-zero.StepOutcome#classifyreturns:failed.ViolationRecorder#callcallsrecord_round. The insert sendsgate_type: nil.Sequel::NotNullConstraintViolation: NOT NULL constraint failed: correction_rounds.gate_type.Gate::Run#callrescues it and writesVerdict::ERRORon a syntheticgatestep.What should have happened:
Gate#verdictreturns FAIL for the step. It uses@last_classificationonly and does not read thecorrection_roundsrow. The mapfailedge routes the failure.Out of this ticket: the
Errno::ENOENTfor a slash-command check (/os-adr:find). ADR-0255 (#843) replaces shell-run checks with typedpresent/absentchecks, which removes that crash class.Approach
ViolationRecorderrecords a correction round only when the failed step has a parser category. A failed step withgate_type == nilrecords its step_result as today, and no round.gate_typekeeps its ADR-0149 meaning: a parser category (lintortest), not a gate node name. Do not store the step name ingate_type. Do not relax the NOT NULL column.No other reader depends on a round for a failed dispatch. The repair brief (
query/brief/facts.rb:52-69) reads step_results, so the retry brief still shows the required-work output.lesson_relay(run.rb:101) accepts an empty violation set. Loop bounds useLoopLedgerandProgressWitness, not rounds.Amend ADR-0149 with one line: only a step with a parser category records a correction round. Amend ADR-0244 with one line: a failed required-work step records no correction round and routes through the suite-check
failedge.Required work: none beyond the acceptance criteria.
Acceptance criteria
tests/command/gate/violation_recorder_test.rb, a failedrequired-workstep (exit 1, classification:failed) records no correction round and raises no error.retired-testsstep records no correction round and raises no error.required-workstep fails returns a FAIL verdict on steprequired-work, notverdict:erroron stepgate.violation_recorder_test.rbstay green without edits.docs/implementation-status/os-sdlc.mdhas one History row for #841.Owner sketch
OsSdlc::Command::Gate::ViolationRecorder#callowns the decision to record a round.StepOutcome#gate_typestays the single source for the parser category.Gate#verdictand the mapfailedges own routing; they do not change.VERDICT: CREATE
REASON: A complete, in-policy /os-sdlc:implement run hit this. Any failing required-work step crashes the gate (correction_rounds.gate_type NOT NULL) instead of routing to a correction round. The Origin chain ends in DESIGN, not IMPROVISATION, this ticket is the root, and it blocks #836.
Scope additions from review (Codex second opinion, 2026-09-30):
retired-testshas the same gap. The test-writer gate is[diff-test, test-lint, retired-tests](poodr-ticket-implementation.yaml:53). A failedretired-testsstep reachesViolationRecorder#record_roundthrough normal gate settlement (gate.rb:65) and hits the same NOT NULL crash.StepOutcome#gate_typeis nil). Do not store the node name ingate_type. ADR-0149 limits it tolintandtest, and those are parser categories, not gate nodes.required-workandretired-tests./checks atimplementation-open.Decomposed 2026-09-30. Scope narrowed to the gate_type crash; the slash-command ENOENT half is covered by ADR-0255 (#843). Blast radius: no pinning tests to retire; ADR-0149 and ADR-0244 get one-line amendments.
Work started via /os-sdlc:implement on branch ticket-841.
Resolution
Done: ViolationRecorder records a correction round only when the failed step has a parser category. Failed required-work and retired-tests steps return FAIL on their step and route by the map fail edge, instead of verdict:error on correction_rounds.gate_type NOT NULL. ADR-0149 and ADR-0244 amended; os-sdlc History row added.
Evidence: Branch ticket-841:
da7c2643(guard, two recorder tests, run_required_work_test.rb),1fdfeefb(ADR amendments, History row). Implementation 11 complete: suite-check gate required-work exit 0, suite exit 0.Follow-ups: none (repair-node required-work gating declined by user 2026-09-30)