Store the gate step classification in step_results #827
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#827
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
Two places derive the same gate step classification. Gate::StepOutcome classifies each step when the gate runs. step_results stores only exit_status, output and duration_ms (plugins/os-sdlc/lib/os_sdlc/adapter/db.rb:280-284). So Implementation::Landing::UnexpectedPassReason must classify the stored rows again through StepResult#outcome to build the escalation reason :/. If the two classifications diverge, the reason text names the wrong cause.
Reproduce
n/a: design ticket; no failure observed yet.
Approach
Store the classification in step_results when the gate records a step. UnexpectedPassReason reads the stored value and does not classify again.
Gate::StepOutcomegains aclassificationmember, default nil. Its custominitialize(duration_ms: nil, **rest)must also defaultclassification: nil, orDataraises a missing-keyword error.classificationcolumn inDb.add_step_result_outcome_columns.Db::SCHEMA_VERSIONgoes from 24 to 25. ADR-0129 wipe-and-recreate applies, so no migration code. ADR-0155 refuses the bump while an implementation is in flight.to_sym, becauseGate::ESCALATING_CLASSIFICATIONSholds Symbols. Without the conversion, escalation never fires.Command::CompletionIntake#stamp_gate_skip!) and error steps (Command::Gate::Run#record_failure) carry no gate classification and store nil. A nil classification never escalates.bin/runner from this branch against the linked.sdlc/pipeline.db. The schema bump wipes the shared database. Tests use tmpdir databases.Required work:
Db::SCHEMA_VERSIONto 25 — check:grep -q "SCHEMA_VERSION = 25" plugins/os-sdlc/lib/os_sdlc/adapter/db.rbStepResult#outcome, whose only caller is UnexpectedPassReason — check:! grep -q "def outcome" plugins/os-sdlc/lib/os_sdlc/model/step_result.rbplugins/os-sdlc/tests/support/cli_next_instruction_helpers.rbcarry the classification that each pipeline escalation test expects — check:grep -q "classification" plugins/os-sdlc/tests/support/cli_next_instruction_helpers.rbRejected: keep StepResult#outcome and classify on read — the two classifications can diverge, which is the defect.
Acceptance criteria
unexpected_pass.green_report_nonzero_exitand output that would classify asfailed, when UnexpectedPassReason builds the reason, then it returnsgreen_report_nonzero_exit:<position>/testfrom the stored value.Owner sketch
Non-goals
Origin
f20cc962), 2026-09-29VERDICT: CREATE — user-created ticket; storing the classification at record time removes the divergence (ticket-skeptic, 2026-09-29).
Work started on branch
ticket-827(worktree) via /os-sdlc:implement. This run is also the live test for #819.Re-decomposed 2026-09-29: added Approach code, Required work with checks, acceptance criteria 2-4, Owner sketch (implementation-open refused the missing Owner sketch). Skeptic: CREATE.
Resolution
Done: step_results stores the gate classification of record. Gate#classify returns outcome.with(classification:), Dispatch#record_step! writes it, UnexpectedPassReason reads it, and StepResult#outcome is deleted. SCHEMA_VERSION 24 -> 25. ADR-0248 records the decision and its relation to ADR-0165.
Evidence: Commit
1c5142c1on ticket-827. os-sdlc implementation 78: 8 dispatches (775-782), 0 retries, implementation_complete in 6 min 8 s. suite-check gate: required-work exit 0, suite exit 0. behavior-verifier pass on all 4 acceptance criteria.Follow-ups: #836 (os-sdlc-implementation-report refuses after implementation_complete; ticket-skeptic VERDICT: CREATE)