os-sdlc-implementation-report refuses after implementation_complete #836

Closed
opened 2026-09-29 17:07:27 +00:00 by jared · 4 comments
Owner

Problem

The implement skill's Finish step says: "On any terminal payload, run os-sdlc-implementation-report SESSION_ID". After implementation_complete, the report CLI refuses. The report looks up only unfinished rows (Implementation.active_for, command/dispatch_commands.rb:127-136). The terminal step has already stamped completed_at (command/implementation/landing.rb:27), so the lookup finds nothing. The CLI also parses --help as a session id.

Observed

Implementation 78 (#827) returned implementation_complete from dispatch 782 on 2026-09-29. The next report call failed:

os-sdlc-implementation-report eb87bf9f-0ece-444a-a016-5eaa5c739c98
os-sdlc-implementation-report no active implementation for session "eb87bf9f-0ece-444a-a016-5eaa5c739c98"
os-sdlc-implementation-report --help
os-sdlc-implementation-report no active implementation for session "--help"

Reproduce

/os-sdlc:implement <ticket>     # run to implementation_complete
os-sdlc-implementation-report SESSION_ID

Approach

Decided 2026-09-30. The report looks up one implementation by id, in any state. The orchestrator calls it after /os:worktree finish, not inside the worktree before-remove hook.

def self.implementation_report(root, id)
  implementation = Implementation[id] ||
    exit_loudly("implementation-report no implementation #{id}")
  implementation.record_usage!
  implementation.refresh.summary
end

New Finish order in plugins/os-sdlc/skills/implement/SKILL.md:

terminal payload
→ /os:worktree finish                              # merge and remove only
→ os-sdlc-implementation-report IMPLEMENTATION_ID  # id from the open payload

This depends on four facts, each verified 2026-09-30:

  • The orchestrator receives implementation_id in the open payload (presenter/implementation/open_payload.rb:16).
  • Agent rows store an absolute transcript_path (model/agent.rb:8-13). git worktree remove does not delete ~/.claude/projects/<worktree-slug>/; 11 such directories for removed worktrees exist on disk.
  • The worktree's .sdlc/pipeline.db is a symlink to the main database (plugins/os/lib/worktree/start_command.rb:105-112), so the row survives removal.
  • record_usage! skips rows that already have usage (model/dispatch/usage.rb:6), so a later report does not change stamped data.

The sweep in the worktree before-remove hook (ADR-0193, ADR-0240) exists only to stamp usage before removal. The facts above make it unnecessary.

Required work:

  1. os-sdlc-implementation-report takes an integer implementation id, parsed with strict Integer(arg), and looks it up with Implementation[id].
  2. Delete --sweep-only from controller/boot/inputs.rb and command/dispatch_commands.rb — check: grep -rn "sweep-only\|sweep_missing_usage" plugins/os-sdlc/lib plugins/os-sdlc/bin prints nothing.
  3. Delete the worktree-before-remove=…--sweep-only {implementation} line from .cc-os/config — check: grep -n sweep-only .cc-os/config prints nothing.
  4. In plugins/os-sdlc/skills/implement/SKILL.md Finish, run os-sdlc-implementation-report IMPLEMENTATION_ID after /os:worktree finish, with the id from the open payload — check: grep -n "implementation-report" plugins/os-sdlc/skills/implement/SKILL.md.
  5. In plugins/os-sdlc/skills/responsibility-refactor/SKILL.md:81, pass the implementation id — check: grep -n "implementation-report" plugins/os-sdlc/skills/responsibility-refactor/SKILL.md.
  6. Record a new ADR that amends ADR-0175 (report argument), ADR-0193 (--sweep-only), and ADR-0240 (sweep in the before-remove hook) — check: /os-adr:find implementation-report.

Rejected: fall back to Implementation.current_for(session_id) — the report stays keyed by session, and the orchestrator already holds the implementation id.
Rejected: the skill stops calling the report and renders the terminal payload — the payload is built before the last dispatch's usage is in its transcript (ADR-0175), so the last dispatch's model and tokens stay NULL.

Acceptance criteria

  1. Given a completed implementation, when os-sdlc-implementation-report <id> runs, then it exits 0 and prints the summary JSON with dispatches, totals, and lens.
  2. Given a failed, escalated, or abandoned implementation, when the report runs with its id, then it prints that implementation's summary JSON.
  3. Given an active implementation, when the report runs with its id, then it prints that implementation's summary JSON.
  4. Given an id with no implementation row, when the report runs, then it exits 3, prints nothing on stdout, and names the id on stderr.
  5. Given the argument --help or any other non-integer argument, when the report runs, then it fails with a usage error and does not look up an implementation.

Owner sketch

module OsSdlc
  module DispatchCommands
    def self.implementation_report(root, id)
  end
end

class OsSdlc::Implementation
  def record_usage!
  def summary
end

Non-goals

  • The generic worktree-before-remove feature in os:worktree stays.
  • The report can stamp a partial count for the last dispatch if it runs within 9–39 seconds of settling (ADR-0193 timing). Running the report after finish makes this less likely. It is not addressed here.

Retired tests

plugins/os-sdlc/tests/model/implementation_report_cli_test.rb#test_sweep_missing_usage_stamps_usage
plugins/os-sdlc/tests/model/implementation_report_cli_test.rb#test_sweep_missing_usage_leaves_another_implementation_untouched
plugins/os-sdlc/tests/model/implementation_report_cli_test.rb#test_sweep_missing_usage_prints_nothing_via_the_cli
plugins/os-sdlc/tests/model/implementation_report_cli_test.rb#test_sweep_missing_usage_exits_loudly_for_an_unknown_implementation_id
plugins/os-sdlc/tests/model/implementation_report_cli_test.rb#test_implementation_report_exits_loudly_for_a_session_with_no_active_implementation
plugins/os-sdlc/tests/controller/process_io_seam_test.rb#test_a_loud_refusal_reaches_the_invocation_stderr_and_returns_3

Origin

  • Trigger: /os-sdlc:implement 827 (implementation 78), 2026-09-29
  • Improvised this session: the orchestrator rendered the dispatch table from the terminal payload's dispatches and totals
  • Chain: report missing ← the report looks up only the active implementation (command/dispatch_commands.rb:127-136) ← the terminal step closes the implementation before the skill calls the report (command/implementation/landing.rb:27) ← DESIGN (ADR-0175 report keyed by session id)
  • Root candidate: this ticket
  • Where: plugins/os-sdlc/bin/os-sdlc-implementation-report; plugins/os-sdlc/lib/os_sdlc/command/dispatch_commands.rb; plugins/os-sdlc/skills/implement/SKILL.md (Finish)
  • Session: eb87bf9f-0ece-444a-a016-5eaa5c739c98
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/eb87bf9f-0ece-444a-a016-5eaa5c739c98.jsonl
  • Triage session: 61db8071-7255-4d2c-8436-5f9c6ac52caa (2026-09-30)

VERDICT: CREATE — real defect; the documented Finish step calls a CLI that refuses after implementation_complete; chain ends in DESIGN; no duplicate (ticket-skeptic, 2026-09-29).

## Problem The implement skill's Finish step says: "On any terminal payload, run `os-sdlc-implementation-report SESSION_ID`". After `implementation_complete`, the report CLI refuses. The report looks up only unfinished rows (`Implementation.active_for`, `command/dispatch_commands.rb:127-136`). The terminal step has already stamped `completed_at` (`command/implementation/landing.rb:27`), so the lookup finds nothing. The CLI also parses `--help` as a session id. ## Observed Implementation 78 (#827) returned `implementation_complete` from dispatch 782 on 2026-09-29. The next report call failed: ``` os-sdlc-implementation-report eb87bf9f-0ece-444a-a016-5eaa5c739c98 ``` ``` os-sdlc-implementation-report no active implementation for session "eb87bf9f-0ece-444a-a016-5eaa5c739c98" ``` ``` os-sdlc-implementation-report --help ``` ``` os-sdlc-implementation-report no active implementation for session "--help" ``` ## Reproduce ``` /os-sdlc:implement <ticket> # run to implementation_complete os-sdlc-implementation-report SESSION_ID ``` ## Approach Decided 2026-09-30. The report looks up one implementation by id, in any state. The orchestrator calls it after `/os:worktree finish`, not inside the worktree before-remove hook. ```ruby def self.implementation_report(root, id) implementation = Implementation[id] || exit_loudly("implementation-report no implementation #{id}") implementation.record_usage! implementation.refresh.summary end ``` New Finish order in `plugins/os-sdlc/skills/implement/SKILL.md`: ``` terminal payload → /os:worktree finish # merge and remove only → os-sdlc-implementation-report IMPLEMENTATION_ID # id from the open payload ``` This depends on four facts, each verified 2026-09-30: - The orchestrator receives `implementation_id` in the open payload (`presenter/implementation/open_payload.rb:16`). - Agent rows store an absolute `transcript_path` (`model/agent.rb:8-13`). `git worktree remove` does not delete `~/.claude/projects/<worktree-slug>/`; 11 such directories for removed worktrees exist on disk. - The worktree's `.sdlc/pipeline.db` is a symlink to the main database (`plugins/os/lib/worktree/start_command.rb:105-112`), so the row survives removal. - `record_usage!` skips rows that already have usage (`model/dispatch/usage.rb:6`), so a later report does not change stamped data. The sweep in the worktree before-remove hook (ADR-0193, ADR-0240) exists only to stamp usage before removal. The facts above make it unnecessary. Required work: 1. `os-sdlc-implementation-report` takes an integer implementation id, parsed with strict `Integer(arg)`, and looks it up with `Implementation[id]`. 2. Delete `--sweep-only` from `controller/boot/inputs.rb` and `command/dispatch_commands.rb` — check: `grep -rn "sweep-only\|sweep_missing_usage" plugins/os-sdlc/lib plugins/os-sdlc/bin` prints nothing. 3. Delete the `worktree-before-remove=…--sweep-only {implementation}` line from `.cc-os/config` — check: `grep -n sweep-only .cc-os/config` prints nothing. 4. In `plugins/os-sdlc/skills/implement/SKILL.md` Finish, run `os-sdlc-implementation-report IMPLEMENTATION_ID` after `/os:worktree finish`, with the id from the open payload — check: `grep -n "implementation-report" plugins/os-sdlc/skills/implement/SKILL.md`. 5. In `plugins/os-sdlc/skills/responsibility-refactor/SKILL.md:81`, pass the implementation id — check: `grep -n "implementation-report" plugins/os-sdlc/skills/responsibility-refactor/SKILL.md`. 6. Record a new ADR that amends ADR-0175 (report argument), ADR-0193 (`--sweep-only`), and ADR-0240 (sweep in the before-remove hook) — check: `/os-adr:find implementation-report`. Rejected: fall back to `Implementation.current_for(session_id)` — the report stays keyed by session, and the orchestrator already holds the implementation id. Rejected: the skill stops calling the report and renders the terminal payload — the payload is built before the last dispatch's usage is in its transcript (ADR-0175), so the last dispatch's model and tokens stay NULL. ## Acceptance criteria 1. Given a completed implementation, when `os-sdlc-implementation-report <id>` runs, then it exits 0 and prints the summary JSON with `dispatches`, `totals`, and `lens`. 2. Given a failed, escalated, or abandoned implementation, when the report runs with its id, then it prints that implementation's summary JSON. 3. Given an active implementation, when the report runs with its id, then it prints that implementation's summary JSON. 4. Given an id with no implementation row, when the report runs, then it exits 3, prints nothing on stdout, and names the id on stderr. 5. Given the argument `--help` or any other non-integer argument, when the report runs, then it fails with a usage error and does not look up an implementation. ## Owner sketch ```ruby module OsSdlc module DispatchCommands def self.implementation_report(root, id) end end class OsSdlc::Implementation def record_usage! def summary end ``` ## Non-goals - The generic `worktree-before-remove` feature in `os:worktree` stays. - The report can stamp a partial count for the last dispatch if it runs within 9–39 seconds of settling (ADR-0193 timing). Running the report after finish makes this less likely. It is not addressed here. ## Retired tests plugins/os-sdlc/tests/model/implementation_report_cli_test.rb#test_sweep_missing_usage_stamps_usage plugins/os-sdlc/tests/model/implementation_report_cli_test.rb#test_sweep_missing_usage_leaves_another_implementation_untouched plugins/os-sdlc/tests/model/implementation_report_cli_test.rb#test_sweep_missing_usage_prints_nothing_via_the_cli plugins/os-sdlc/tests/model/implementation_report_cli_test.rb#test_sweep_missing_usage_exits_loudly_for_an_unknown_implementation_id plugins/os-sdlc/tests/model/implementation_report_cli_test.rb#test_implementation_report_exits_loudly_for_a_session_with_no_active_implementation plugins/os-sdlc/tests/controller/process_io_seam_test.rb#test_a_loud_refusal_reaches_the_invocation_stderr_and_returns_3 ## Origin - Trigger: /os-sdlc:implement 827 (implementation 78), 2026-09-29 - Improvised this session: the orchestrator rendered the dispatch table from the terminal payload's dispatches and totals - Chain: report missing ← the report looks up only the active implementation (`command/dispatch_commands.rb:127-136`) ← the terminal step closes the implementation before the skill calls the report (`command/implementation/landing.rb:27`) ← DESIGN (ADR-0175 report keyed by session id) - Root candidate: this ticket - Where: plugins/os-sdlc/bin/os-sdlc-implementation-report; plugins/os-sdlc/lib/os_sdlc/command/dispatch_commands.rb; plugins/os-sdlc/skills/implement/SKILL.md (Finish) - Session: eb87bf9f-0ece-444a-a016-5eaa5c739c98 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/eb87bf9f-0ece-444a-a016-5eaa5c739c98.jsonl - Triage session: 61db8071-7255-4d2c-8436-5f9c6ac52caa (2026-09-30) VERDICT: CREATE — real defect; the documented Finish step calls a CLI that refuses after implementation_complete; chain ends in DESIGN; no duplicate (ticket-skeptic, 2026-09-29).
Author
Owner

Second reproduction 2026-09-30: session cbf5e0d7-f339-4520-ad90-e032956bdca4, implementation 3 (#826). After implementation_complete, os-sdlc-implementation-report <session> printed no active implementation for session. The Orchestrator used the dispatches and totals from the terminal payload instead.

Second reproduction 2026-09-30: session cbf5e0d7-f339-4520-ad90-e032956bdca4, implementation 3 (#826). After implementation_complete, `os-sdlc-implementation-report <session>` printed `no active implementation for session`. The Orchestrator used the dispatches and totals from the terminal payload instead.
Author
Owner

Work started via /os-sdlc:implement on branch ticket-836 (worktree .claude/worktrees/ticket-836).

Work started via /os-sdlc:implement on branch `ticket-836` (worktree .claude/worktrees/ticket-836).
Author
Owner

Blocked by #841. Implementation 4 failed.

  • Failed step: dispatch 30, suite-check, gate [required-work, suite].
  • Gate details: verdict:error. The gate crashed with Sequel::NotNullConstraintViolation: NOT NULL constraint failed: correction_rounds.gate_type. The trigger was os-sdlc-required-work-check 4, which exits 3 with harness error: Errno::ENOENT - /os-adr:find. Required-work item 6 uses a slash command as its check, and the check runner cannot execute it.
  • Before the crash, all earlier gates passed: test-writer red, test-reviewer, programmer green (diff-test and lint), behavior-verifier.
  • Required-work item 6 (the new ADR) seems not yet written. docs/adr has nothing newer than 0250.
  • The uncommitted diff stays in worktree .claude/worktrees/ticket-836 (branch ticket-836), 8 files. I did not merge it.

To continue: fix #841, or rewrite item 6's check as a runnable command. Then start a new implementation-open.

Blocked by #841. Implementation 4 failed. - Failed step: dispatch 30, `suite-check`, gate `[required-work, suite]`. - Gate details: `verdict:error`. The gate crashed with `Sequel::NotNullConstraintViolation: NOT NULL constraint failed: correction_rounds.gate_type`. The trigger was `os-sdlc-required-work-check 4`, which exits 3 with `harness error: Errno::ENOENT - /os-adr:find`. Required-work item 6 uses a slash command as its check, and the check runner cannot execute it. - Before the crash, all earlier gates passed: test-writer red, test-reviewer, programmer green (diff-test and lint), behavior-verifier. - Required-work item 6 (the new ADR) seems not yet written. `docs/adr` has nothing newer than 0250. - The uncommitted diff stays in worktree `.claude/worktrees/ticket-836` (branch `ticket-836`), 8 files. I did not merge it. To continue: fix #841, or rewrite item 6's check as a runnable command. Then start a new `implementation-open`.
Author
Owner

Resolution

Done: os-sdlc-implementation-report takes a strict integer implementation id and reports an implementation in any state; --sweep-only, sweep_missing_usage, Accounting#sweep deleted; implement skill runs the report after /os:worktree finish on completion; responsibility-refactor skill passes the id; ADR-0251 amends ADR-0175/0193/0240. Implementation 4 reached suite-check with all earlier gates green, then failed on a gate crash (#841); hand-finished: ADR written, SKILL.md Finish wording limited to completion, suite and lint rerun.

Evidence: main 063075f1 (fast-forward from ticket-836). ruby plugins/os-sdlc/tests/all.rb: 1337 runs, 2954 assertions, 0 failures, 0 errors, 9 skips, 18.0s. rubocop on the 6 changed Ruby files: no offenses. Live: os-sdlc-implementation-report 4 printed the 9-dispatch summary for the failed implementation after worktree removal; os-sdlc-implementation-report --help exits 3 with the usage line. .cc-os/config has no sweep-only line.

Follow-ups: #841 gate crash on a failed required-work/retired-tests step (P1); #842 delete worktree-before-remove and --implementation from os:worktree (user decision B); #843 Required-work ownership rule and slash-command check refusal.

## Resolution **Done:** os-sdlc-implementation-report takes a strict integer implementation id and reports an implementation in any state; --sweep-only, sweep_missing_usage, Accounting#sweep deleted; implement skill runs the report after /os:worktree finish on completion; responsibility-refactor skill passes the id; ADR-0251 amends ADR-0175/0193/0240. Implementation 4 reached suite-check with all earlier gates green, then failed on a gate crash (#841); hand-finished: ADR written, SKILL.md Finish wording limited to completion, suite and lint rerun. **Evidence:** main 063075f1 (fast-forward from ticket-836). ruby plugins/os-sdlc/tests/all.rb: 1337 runs, 2954 assertions, 0 failures, 0 errors, 9 skips, 18.0s. rubocop on the 6 changed Ruby files: no offenses. Live: os-sdlc-implementation-report 4 printed the 9-dispatch summary for the failed implementation after worktree removal; os-sdlc-implementation-report --help exits 3 with the usage line. .cc-os/config has no sweep-only line. **Follow-ups:** #841 gate crash on a failed required-work/retired-tests step (P1); #842 delete worktree-before-remove and --implementation from os:worktree (user decision B); #843 Required-work ownership rule and slash-command check refusal.
jared closed this issue 2026-09-30 14:16:25 +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#836
No description provided.