os-sdlc: terminal payload carries a deterministic run summary #552
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#552
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
The user asked, in session d9e1984d, for a table at the end of every
/os-sdlc:implementrun: dispatched subagents, time, tokens, verdicts, and workflow issues. The orchestrator assembled it by hand twice. It must come from data. The pipeline database already holds per dispatch: agent type, created and completed timestamps, verdict, stalled timestamp, and per gate step aduration_ms(#528). Edge spends hold retry counts. Model and token data are absent from the database; that is a separate ticket (B, filed alongside).Design agreed with the user on 2026-09-11:
Implementation::Summaryowns aDispatchSummary, which owns the dispatch models. Objects are named by what they summarize, not by how the orchestrator draws them. No code comments.agent_typeis the key, notnode, because dispatches carry no node column.Observed
NextStep#base_terminal_payload(plugins/os-sdlc/lib/os_sdlc/runner/next_step.rb:88-94) emits type, node, reason, session_id, implementation_id, and the ADR-0171 commit record. No run summary.Reproduce
n/a: feature ticket
Expected
Both terminal payloads (and the escalation payload, which wraps the same base) carry
dispatchesandtotals:dispatches: [{id:, agent_type:, elapsed_s:, verdict:, stalled:, gate_steps: [{step:, ms:, exit:}]}]totals: {dispatches:, elapsed_s:, retries:}Tasks
lib/os_sdlc/runner/implementation/summary.rb: classOsSdlc::Runner::Implementation::Summarywithself.for(implementation) = new(implementation).to_h;initializestores the implementation and buildsDispatchSummary.new(implementation.dispatches);to_hreturns{ dispatches: @dispatch_summary.to_a, totals: totals }; privatetotals={ dispatches: @dispatch_summary.count, elapsed_s:, retries: };elapsed_s=DispatchSummary.seconds_between(implementation.created_at, last_stamp)wherelast_stamp=completed_at || failed_at || escalated_at;retries=implementation.edge_spends.sum { |spend| spend.spent.to_i }.lib/os_sdlc/runner/implementation/dispatch_summary.rb: classDispatchSummary;self.seconds_between(from, to)returns nil unless both, else(to.to_time - from.to_time).round(1);initialize(dispatches)storesdispatches.sort_by(&:id);count;to_amaps each dispatch to{ id:, agent_type: dispatch.agent_type, elapsed_s: seconds_between(created_at, completed_at), verdict:, stalled: dispatch.stalled?, gate_steps: }wheregate_stepsmapsstep_results.sort_by(&:id)to{ step:, ms: duration_ms, exit: exit_status }.def summary = Summary.for(self)toImplementation::InstanceMethodsnext tolatest_dispatch(implementation.rb ~line 167).base_terminal_payload, chain.merge(@row.summary)onto the base hash literal, before the commit_record guard.skills/implement/SKILL.md, after the ADR-0171 commit paragraph in theimplementation_completesection (~line 139), add one unwrapped line:Render \dispatches` as a table: one row per dispatch, followed by the `totals` line. If you observed workflow issues, list them below the table.`tests/runner/implementation_summary_test.rb(payload shape, totals count, elapsed, retries from one edge spend);tests/runner/dispatch_summary_test.rb(one entry's agent_type, elapsed_s, gate_steps from one recorded step); one case intests/runner/cli_next_instruction_test.rbasserting the completion payload'sdispatcheslength equalstotals.dispatches.agent_typestands in for node because dispatches have no node column;retriesis the sum ofedge_spends.spent. Run/os-adr:findon next_step.rb first.bin/refresh-plugins) after SKILL.md changes.Acceptance criteria
dispatchesrows and atotalshash; the row count equalstotals.dispatches.Out of scope
Model and token data (ticket B). A
nodecolumn on dispatches. A row cap for long runs.Origin
Session: 5fdd0aa3-8a9c-4c31-a5b3-d575d8e709ab
Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/5fdd0aa3-8a9c-4c31-a5b3-d575d8e709ab.jsonl
Where: plugins/os-sdlc/lib/os_sdlc/runner/next_step.rb
NextStep#base_terminal_payloadFiled by: user request, 2026-09-11. Design discussion originated in session d9e1984d.
Work started via /os-sdlc:implement on branch ticket-552 (session 5fdd0aa3).
Resolution
Done: Terminal payload carries dispatches and totals via Implementation::Summary and DispatchSummary; SKILL.md render line; ADR-0171 amended; history row added.
Evidence: Commit
61995acon branch ticket-552; full os-sdlc suite 1163 runs, 0 failures, 0 errors; rubocop clean on changed files; live escalation payload from implementation 2 rendered the summary. Pipeline deviations: implementation 1 ended on a stale-gate error (#551), implementation 2 escalated with unexpected_pass, remaining doc tasks and one bug fix (refresh cleared the commit record) finished by hand under the escalation procedure.Follow-ups: #553 model and token usage from transcripts; #554 behavior-verifier charter red-gate rule