Implementation#handoffs is the Sequel association; Handoff answers items and summary #591
Labels
No labels
P0
P1
P2
P3
bug
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
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#591
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?
Context
Responsibility-audit run 18 on
plugins/os-sdlc/lib/os_sdlc/runner/implementation.rbreported finding 2:handoffsis declared twice, and the Sequel association loses. The user chose Option B on 2026-09-15: repair the association, add no new record class.Observed
plugins/os-sdlc/lib/os_sdlc/runner/models.rb:87declaresklass.one_to_many :handoffs, class: handoff, key: :implementation_id.plugins/os-sdlc/lib/os_sdlc/runner/implementation.rb:76defines an instance method with the same name. The mixin is included atmodels.rb:77, before the association is wired, so the mixin method wins and the association reader has no callers. Which declaration runs depends on include order in another file. Lines 77 and 78 of implementation.rb reach two hops throughHandoff#content_objectintoHandoffContentto answerhandoff_itemsandmerge_ready_summaryforImplementation::Commit.Reproduce
n/a: design defect, no failing command. The shadowing is visible by reading
models.rb:77andmodels.rb:87againstimplementation.rb:76.Tasks
models.rb:87becomesklass.one_to_many :handoffs, class: handoff, key: :implementation_id, order: :id.implementation.rb:76-78(handoffs,handoff_items,merge_ready_summary).Handoff::InstanceMethodsinplugins/os-sdlc/lib/os_sdlc/runner/handoff.rb:def items = content_object.itemsanddef summary = content_object.summary.plugins/os-sdlc/lib/os_sdlc/runner/implementation/commit.rb:70becomes@implementation.handoffs.flat_map(&:items).filter_map { |entry| Item.new(entry).path }.uniq.commit.rb:149becomes@summary ||= @implementation.handoffs.last&.summary.to_s.strip.Handoff::ClassMethods#for_implementation(handoff.rb:49-51) once it has no caller.Class sketch
Expected test cases
Implementation#handoffsreturns the handoffs for that implementation ordered by id, oldest first, when two handoffs are inserted in reverse creation order.Implementation#handoffsreturns an empty array for an implementation with no handoffs.Handoff#itemsreturns theitemslist from the handoff content; returns[]when content has no items.Handoff#summaryreturns thesummarystring from the handoff content; returns nil when absent.Implementation::Commit::ListedPaths#callreturns the unique paths from all handoffs' items, in handoff order.Implementation::Commit::Message#summaryreturns the stripped summary of the last handoff, and""when the implementation has no handoffs.Implementationinstances do not respond tohandoff_itemsormerge_ready_summary.Handoffclass does not respond tofor_implementation.Expected
Acceptance criteria
plugins/os-sdlc/tests/runner/implementation_test.rb:103keeps passing through the association.ruby plugins/os-sdlc/tests/all.rbis green; rubocop withplugins/os-sdlc/.rubocop.ymlreports zero offenses on touched files.Constraints
Commitstages only handoff-listed paths; the staged set must not change.transition!or the terminal writers.plugins/os-sdlc/maps/poodr-ticket-implementation.yaml.Out of scope
Runnernamespace (separate decision ticket).Implementation::Stamp,Implementation::Admission, defect rows).Origin
/os-sdlc:responsibility-audit plugins/os-sdlc/lib/os_sdlc/runner/implementation.rb(run 18, artifact.sdlc/tmp/responsibility-audit/run-18/analysis.yaml)models.rb:77vs:87) ←DESIGN(ADR-0167 model mixin registry,models.rb)OsSdlc::Runner::Implementation::InstanceMethods,plugins/os-sdlc/lib/os_sdlc/runner/implementation.rb:76-78Work started via /os-sdlc:implement on branch ticket-591 (map: poodr-ticket-implementation.yaml).
Resolution
Done: Option B shipped on branch ticket-591, commit
f4fa431: one_to_many :handoffs carries order: :id and is the sole definition; Handoff#items and Handoff#summary added; Implementation#handoffs/#handoff_items/#merge_ready_summary and Handoff.for_implementation deleted; Commit reads handoffs.flat_map(&:items) and handoffs.last&.summary.Evidence: Pipeline implementation 18 (poodr-ticket-implementation map, 16 dispatches): tests red then green, behavior-verifier pass x2, suite-check pass (1200 runs, 0 failures), rubocop 7 files no offenses. Contract-auditor settled error because a programmer relaxed HandoffContent#validate_summary! out of scope to satisfy the ticket's 'summary nil when absent' case; hand-finished by restoring the validator to HEAD and deleting that one test, then suite rerun green.
Follow-ups: The ticket's expected case 'Handoff#summary returns nil when absent' contradicted the HandoffContent contract (summary required); dropped, no ticket. Contract-auditor has no route for a correction that needs a test edit and settles error instead; same shape already noted on #555, no new ticket.