Runner commit omits production files that no handoff lists #955

Open
opened 2026-10-05 13:45:44 +00:00 by jared · 4 comments
Owner

Problem

The Runner commit at implementation complete stages only the paths that the implementation's handoffs list.
A green increment can therefore pass every gate while the production files that make the tests pass stay uncommitted.
The commit then holds only the test file, and the files that make it pass stay in the working tree.

Observed

During #949 on branch crc-os-adr-2026-10-04, the Runner commit for implementation 34 held only the test file.
The ConceptCycles lint and bin/lint-concept-cycles stayed uncommitted, and the session committed them by hand in 530c98f6.
The 530c98f6 message says abandoned implementation 32 wrote those files, and they passed all gates of implementation 34.
The files were untracked, so they were in changed_paths, but no handoff of implementation 34 listed them.

Reproduce

n/a: needs a Runner run where an earlier abandoned implementation wrote production files that no handoff of the final implementation lists. Unit level: a repo with an untracked production file absent from every handoff item, then OsSdlc::Implementation::Commit.new(implementation:, root:).call returns a record whose dirty_paths includes that file.

Approach

Cause is in plugins/os-sdlc/lib/os_sdlc/command/implementation/commit.rb:34: staged_paths returns ListedPaths.new(@implementation).call & changed_paths.
ListedPaths (plugins/os-sdlc/lib/os_sdlc/query/implementation/commit/listed_paths.rb:12) reads only handoff items.
Line 27 then reports every unlisted changed file as dirty_paths.
The first guess, that dirty_paths drives the path list, is wrong: dirty_paths only reports what the commit left out. ADR-0171 and ADR-0249 chose "staging only handoff-listed paths" on purpose, to protect unrelated user work, so a fix needs a new ADR.
Decide how a file counts as part of the increment when no handoff lists it, for example a file that an abandoned implementation of the same ticket wrote, or a file the gates ran against.

Required work: none beyond the acceptance criteria.

Acceptance criteria

  1. Given an untracked production file that a prior abandoned implementation of the same ticket wrote and no handoff lists, when the Runner commits a green implementation that the file makes pass, then the commit contains the file.
  2. Given an unrelated dirty file that belongs to no implementation of the ticket, when the Runner commits, then the file is not staged and appears in dirty_paths.

Owner sketch

class OsSdlc::Implementation::Commit
  def staged_paths
  end
end

Origin

  • Trigger: /os-sdlc:implement for #949 on branch crc-os-adr-2026-10-04, implementation 34.
  • Improvised this session: the session committed the production files by hand in 530c98f6.
  • Chain: commit holds only the test ← Commit#staged_paths intersects handoff-listed paths with changed paths ← DESIGN (ADR-0171, ADR-0249).
  • Root candidate: none.
  • Where: plugins/os-sdlc/lib/os_sdlc/command/implementation/commit.rb:34
  • Session: ab599e53-dbf5-4953-b8bf-c598a9c5c16e
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-crc-os-adr-2026-10-04/ab599e53-dbf5-4953-b8bf-c598a9c5c16e.jsonl
  • Skeptic: VERDICT: CREATE
## Problem The Runner commit at implementation complete stages only the paths that the implementation's handoffs list. A green increment can therefore pass every gate while the production files that make the tests pass stay uncommitted. The commit then holds only the test file, and the files that make it pass stay in the working tree. ## Observed During #949 on branch crc-os-adr-2026-10-04, the Runner commit for implementation 34 held only the test file. The ConceptCycles lint and bin/lint-concept-cycles stayed uncommitted, and the session committed them by hand in 530c98f6. The 530c98f6 message says abandoned implementation 32 wrote those files, and they passed all gates of implementation 34. The files were untracked, so they were in `changed_paths`, but no handoff of implementation 34 listed them. ## Reproduce n/a: needs a Runner run where an earlier abandoned implementation wrote production files that no handoff of the final implementation lists. Unit level: a repo with an untracked production file absent from every handoff item, then `OsSdlc::Implementation::Commit.new(implementation:, root:).call` returns a record whose `dirty_paths` includes that file. ## Approach Cause is in `plugins/os-sdlc/lib/os_sdlc/command/implementation/commit.rb:34`: `staged_paths` returns `ListedPaths.new(@implementation).call & changed_paths`. `ListedPaths` (`plugins/os-sdlc/lib/os_sdlc/query/implementation/commit/listed_paths.rb:12`) reads only handoff items. Line 27 then reports every unlisted changed file as `dirty_paths`. The first guess, that `dirty_paths` drives the path list, is wrong: `dirty_paths` only reports what the commit left out. ADR-0171 and ADR-0249 chose "staging only handoff-listed paths" on purpose, to protect unrelated user work, so a fix needs a new ADR. Decide how a file counts as part of the increment when no handoff lists it, for example a file that an abandoned implementation of the same ticket wrote, or a file the gates ran against. Required work: none beyond the acceptance criteria. ## Acceptance criteria 1. Given an untracked production file that a prior abandoned implementation of the same ticket wrote and no handoff lists, when the Runner commits a green implementation that the file makes pass, then the commit contains the file. 2. Given an unrelated dirty file that belongs to no implementation of the ticket, when the Runner commits, then the file is not staged and appears in `dirty_paths`. ## Owner sketch ```ruby class OsSdlc::Implementation::Commit def staged_paths end end ``` ## Origin - Trigger: `/os-sdlc:implement` for #949 on branch crc-os-adr-2026-10-04, implementation 34. - Improvised this session: the session committed the production files by hand in 530c98f6. - Chain: commit holds only the test ← `Commit#staged_paths` intersects handoff-listed paths with changed paths ← DESIGN (ADR-0171, ADR-0249). - Root candidate: none. - Where: plugins/os-sdlc/lib/os_sdlc/command/implementation/commit.rb:34 - Session: ab599e53-dbf5-4953-b8bf-c598a9c5c16e - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os--claude-worktrees-crc-os-adr-2026-10-04/ab599e53-dbf5-4953-b8bf-c598a9c5c16e.jsonl - Skeptic: VERDICT: CREATE
Author
Owner

Not CRC work. No CRC action (ruling (b), 2026-10-16). This ticket stays open for its own owner ruling.

Not CRC work. No CRC action (ruling (b), 2026-10-16). This ticket stays open for its own owner ruling.
Author
Owner

Resolution

Done: Mechanism: Implementation::Commit builds the commit from handoff items and the last handoff summary, not from the diff or the ticket. Occurrence: #1116 "Runner commit leaves ticket files uncommitted when the programmer handoff items omit them".

Evidence: #1116 adds a second case: implementation 67 of #1107 left structure-changer.md and implement/SKILL.md uncommitted (reported as dirty_paths) though Required work checks R2/R3/R7 named them; fix option: stage every path a passing check named.

Follow-ups: Repeat of the earlier note on this issue (its text 'x'/'y' was a test of the command; ignore it)

## Resolution **Done:** Mechanism: Implementation::Commit builds the commit from handoff items and the last handoff summary, not from the diff or the ticket. Occurrence: #1116 "Runner commit leaves ticket files uncommitted when the programmer handoff items omit them". **Evidence:** #1116 adds a second case: implementation 67 of #1107 left structure-changer.md and implement/SKILL.md uncommitted (reported as dirty_paths) though Required work checks R2/R3/R7 named them; fix option: stage every path a passing check named. **Follow-ups:** Repeat of the earlier note on this issue (its text 'x'/'y' was a test of the command; ignore it)
Author
Owner

Occurrence: Refuse implementation_complete while required generated files are uncommitted
Seen: plugins/os-sdlc/lib/os_sdlc (Runner implementation_complete gate); implementation 230 for #1514 left plugins/os-backlog/design/generated/ uncommitted; files reached main only through merge 949375af
Run: cbb127b2-9430-4c75-9b92-185bedb457c1; implementation 230
Adds: a second case where Commit#staged_paths stages only handoff-listed paths; commit 043dd10b also used the auditor summary as its message (covered by #987)

Occurrence: Refuse implementation_complete while required generated files are uncommitted Seen: plugins/os-sdlc/lib/os_sdlc (Runner implementation_complete gate); implementation 230 for #1514 left plugins/os-backlog/design/generated/ uncommitted; files reached main only through merge 949375af Run: cbb127b2-9430-4c75-9b92-185bedb457c1; implementation 230 Adds: a second case where Commit#staged_paths stages only handoff-listed paths; commit 043dd10b also used the auditor summary as its message (covered by #987)
Author
Owner

Occurrence: Commit the reviewed test file with the Runner commit at implementation_complete
Seen: plugins/os-sdlc/lib/os_sdlc/implementation/commit.rb
Run: implementations 284 (#1709) and 285 (#1710), session 01fe836c-833b-4fd9-a7f2-6982cee53d73, 2026-11-12
Adds: the unlisted file can be the test-writer's reviewed test, not only a production file. 284 left a modified test file and 285 a new untracked test file in dirty_paths; both runs passed every gate with the file in the tree, so a merge without a hand commit (c9691f64a, a238876ed) ships the fix with no test.

Occurrence: Commit the reviewed test file with the Runner commit at implementation_complete Seen: plugins/os-sdlc/lib/os_sdlc/implementation/commit.rb Run: implementations 284 (#1709) and 285 (#1710), session 01fe836c-833b-4fd9-a7f2-6982cee53d73, 2026-11-12 Adds: the unlisted file can be the test-writer's reviewed test, not only a production file. 284 left a modified test file and 285 a new untracked test file in dirty_paths; both runs passed every gate with the file in the tree, so a merge without a hand commit (c9691f64a, a238876ed) ships the fix with no test.
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#955
No description provided.