Runner auto-commit must accept already-staged deletions #907

Closed
opened 2026-10-02 16:31:49 +00:00 by jared · 3 comments
Owner

Problem

The Runner auto-commit step stages changed paths with git add -- <paths>.
When an agent already staged a deletion with git rm, the path is in neither the index nor the working tree.
Then git add exits 128 and the Runner raises OsSdlc::HarnessError.

Observed

The Runner raised OsSdlc::HarnessError at contract-auditor dispatch 63, so os-sdlc-subagent-stop exited 3.

git add -- plugins/os-sdlc/maps/drafts/.gitkeep
fatal: pathspec 'plugins/os-sdlc/maps/drafts/.gitkeep' did not match any files (exit 128)

Reproduce

git rm plugins/os-sdlc/maps/drafts/.gitkeep && git add -- plugins/os-sdlc/maps/drafts/.gitkeep

Approach

Git::Repo#stage does not send a path whose deletion is already staged to git add. The deletion is already in the index, and git commit --only -- <paths> commits it. Implementation::Commit and ADR-0171 do not change: the verbs are still git add -- and git commit --only.

Probe on git 2.55.0, in a scratch repository with one modified file, one new file, one unstaged deletion, and one staged deletion:

  • git add -- <all>, git add -A -- <all>, git add -u -- <all>: each exits 128 on the staged deletion.
  • git diff --cached --name-only --diff-filter=D lists the staged deletion.
  • git add -- <the other three> and then git commit --only -- <all four> exits 0. The commit contains all four changes.
  • git add -- with no paths exits 0 and adds nothing. stage does not run add when no paths remain.

The git knowledge stays in the adapter, which owns the git process (lens-architecture: adapter/ talks to a process).

Required work:

  1. Leave out the staged deletions before add — check: present "--diff-filter=D" in plugins/os-sdlc/lib/os_sdlc/adapter/git/repo.rb

Rejected:

  • git add -A -- <paths> (the first approach). It also exits 128 on a staged deletion, and ADR-0171 decision 3 says "never -A".
  • git update-index --add --remove -- <paths>. It works for all four states, but it replaces the git add verb of ADR-0171 decision 3 (kept by ADR-0249). That needs a user ruling, and an option that keeps the ADR is available.
  • A prompt rule that agents must not run git rm. The Runner must accept any index state that an agent or the user leaves (feedback-lens-request-is-a-design-symptom).
  • git reset -- <path> before add (the workaround used in this session). ADR-0171 decision 3 allows only additive verbs.

Relation to #906: #906 changes only agents/refactorer.md. No overlap, no dependency. Either order works.

Acceptance criteria

  1. Given a path whose deletion is already staged, when the Runner auto-commit stages and commits the run's paths, then it does not raise and the commit includes the deletion.
  2. Given a modified path, a new untracked path, and a staged deletion in one implementation, when the implementation completes, then the commit contains all three and commit.paths lists all three.
  3. Given that the only listed path is a staged deletion, when the Runner stages, then it does not run git add with no paths, and the commit includes the deletion.

Owner sketch

class OsSdlc::Git::Repo
  def stage(paths)
    pending = paths - listed("diff", "--cached", "--name-only", "--diff-filter=D")
    run("add", "--", *pending) unless pending.empty?
  end
end

Origin

  • Trigger: #904 implementation 8 deleted plugins/os-sdlc/maps/drafts/.gitkeep with git rm; Runner failed at dispatch 63.
  • Improvised this session: git reset -q -- <path> then os-sdlc-next, which committed.
  • Chain: HarnessError at dispatch 63 ← git add exit 128 on staged deletion ← Repo#stage runs add -- (plugins/os-sdlc/lib/os_sdlc/adapter/git/repo.rb:72-73, called from plugins/os-sdlc/lib/os_sdlc/command/implementation/commit.rb:28) ← IMPROVISATION (reset workaround)
  • Root candidate: none
  • Where: plugins/os-sdlc/lib/os_sdlc/adapter/git/repo.rb:72
  • Session: e4b9d6c0-7a98-4bf5-af70-22c15827a8c4
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/e4b9d6c0-7a98-4bf5-af70-22c15827a8c4.jsonl

Parent: #904. VERDICT: CREATE

## Problem The Runner auto-commit step stages changed paths with `git add -- <paths>`. When an agent already staged a deletion with `git rm`, the path is in neither the index nor the working tree. Then `git add` exits 128 and the Runner raises `OsSdlc::HarnessError`. ## Observed The Runner raised `OsSdlc::HarnessError` at contract-auditor dispatch 63, so `os-sdlc-subagent-stop` exited 3. ``` git add -- plugins/os-sdlc/maps/drafts/.gitkeep fatal: pathspec 'plugins/os-sdlc/maps/drafts/.gitkeep' did not match any files (exit 128) ``` ## Reproduce ``` git rm plugins/os-sdlc/maps/drafts/.gitkeep && git add -- plugins/os-sdlc/maps/drafts/.gitkeep ``` ## Approach `Git::Repo#stage` does not send a path whose deletion is already staged to `git add`. The deletion is already in the index, and `git commit --only -- <paths>` commits it. `Implementation::Commit` and ADR-0171 do not change: the verbs are still `git add --` and `git commit --only`. Probe on git 2.55.0, in a scratch repository with one modified file, one new file, one unstaged deletion, and one staged deletion: - `git add -- <all>`, `git add -A -- <all>`, `git add -u -- <all>`: each exits 128 on the staged deletion. - `git diff --cached --name-only --diff-filter=D` lists the staged deletion. - `git add -- <the other three>` and then `git commit --only -- <all four>` exits 0. The commit contains all four changes. - `git add --` with no paths exits 0 and adds nothing. `stage` does not run `add` when no paths remain. The git knowledge stays in the adapter, which owns the git process (lens-architecture: `adapter/` talks to a process). Required work: 1. Leave out the staged deletions before `add` — check: present `"--diff-filter=D"` in `plugins/os-sdlc/lib/os_sdlc/adapter/git/repo.rb` Rejected: - `git add -A -- <paths>` (the first approach). It also exits 128 on a staged deletion, and ADR-0171 decision 3 says "never `-A`". - `git update-index --add --remove -- <paths>`. It works for all four states, but it replaces the `git add` verb of ADR-0171 decision 3 (kept by ADR-0249). That needs a user ruling, and an option that keeps the ADR is available. - A prompt rule that agents must not run `git rm`. The Runner must accept any index state that an agent or the user leaves (feedback-lens-request-is-a-design-symptom). - `git reset -- <path>` before `add` (the workaround used in this session). ADR-0171 decision 3 allows only additive verbs. Relation to #906: #906 changes only `agents/refactorer.md`. No overlap, no dependency. Either order works. ## Acceptance criteria 1. Given a path whose deletion is already staged, when the Runner auto-commit stages and commits the run's paths, then it does not raise and the commit includes the deletion. 2. Given a modified path, a new untracked path, and a staged deletion in one implementation, when the implementation completes, then the commit contains all three and `commit.paths` lists all three. 3. Given that the only listed path is a staged deletion, when the Runner stages, then it does not run `git add` with no paths, and the commit includes the deletion. ## Owner sketch ```ruby class OsSdlc::Git::Repo def stage(paths) pending = paths - listed("diff", "--cached", "--name-only", "--diff-filter=D") run("add", "--", *pending) unless pending.empty? end end ``` ## Origin - Trigger: #904 implementation 8 deleted `plugins/os-sdlc/maps/drafts/.gitkeep` with `git rm`; Runner failed at dispatch 63. - Improvised this session: `git reset -q -- <path>` then `os-sdlc-next`, which committed. - Chain: HarnessError at dispatch 63 ← `git add` exit 128 on staged deletion ← `Repo#stage` runs `add --` (plugins/os-sdlc/lib/os_sdlc/adapter/git/repo.rb:72-73, called from plugins/os-sdlc/lib/os_sdlc/command/implementation/commit.rb:28) ← IMPROVISATION (reset workaround) - Root candidate: none - Where: plugins/os-sdlc/lib/os_sdlc/adapter/git/repo.rb:72 - Session: e4b9d6c0-7a98-4bf5-af70-22c15827a8c4 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/e4b9d6c0-7a98-4bf5-af70-22c15827a8c4.jsonl Parent: #904. VERDICT: CREATE
Author
Owner

PREDICTED RULING: REVISE

a. Accept as written? No.

b. Reasons.

  • The approach does not work. A probe on git 2.55.0 showed that git add -A -- <staged-deleted path> also exits 128 ("pathspec did not match any files"). add -u -- also exits 128.
  • -A conflicts with ADR-0171 decision 3 ("never -A"), which ADR-0249 kept. The memory file feedback-os-sdlc-runs-afk-decide-and-report says: prefer the option that keeps the ADR when one is viable.
  • A prompt rule such as "agents must not run git rm" is a design symptom (feedback-lens-request-is-a-design-symptom). The Runner must accept any index state.

c. What is lazy or wrong. The ticket proposes a git verb without running it. I did the research in a scratch repo. git commit --only -- <paths> already commits a staged deletion. Only git add fails. git diff --cached --name-only --diff-filter=D lists staged deletions. add -- <the other paths> followed by commit --only -- <all paths> commits all four states: modified, new, staged deletion, and unstaged deletion. git update-index --add --remove also works, but it changes the verb in ADR-0171 decision 3, so the user must rule on it.

d. Predicted approach. Git::Repo#stage removes the staged deletions from its argument and runs add -- on the remaining paths. If no paths remain, it does not run add. ADR-0171 is unchanged. The fix is in the adapter, which owns the git process. Commit is unchanged.

e. Not read. Full lens skills; commit_test.rb bodies. #906 changes only refactorer.md: no overlap, no dependency.

PREDICTED RULING: REVISE **a. Accept as written?** No. **b. Reasons.** - The approach does not work. A probe on git 2.55.0 showed that `git add -A -- <staged-deleted path>` also exits 128 ("pathspec did not match any files"). `add -u --` also exits 128. - `-A` conflicts with ADR-0171 decision 3 ("never `-A`"), which ADR-0249 kept. The memory file feedback-os-sdlc-runs-afk-decide-and-report says: prefer the option that keeps the ADR when one is viable. - A prompt rule such as "agents must not run `git rm`" is a design symptom (feedback-lens-request-is-a-design-symptom). The Runner must accept any index state. **c. What is lazy or wrong.** The ticket proposes a git verb without running it. I did the research in a scratch repo. `git commit --only -- <paths>` already commits a staged deletion. Only `git add` fails. `git diff --cached --name-only --diff-filter=D` lists staged deletions. `add -- <the other paths>` followed by `commit --only -- <all paths>` commits all four states: modified, new, staged deletion, and unstaged deletion. `git update-index --add --remove` also works, but it changes the verb in ADR-0171 decision 3, so the user must rule on it. **d. Predicted approach.** `Git::Repo#stage` removes the staged deletions from its argument and runs `add --` on the remaining paths. If no paths remain, it does not run `add`. ADR-0171 is unchanged. The fix is in the adapter, which owns the git process. `Commit` is unchanged. **e. Not read.** Full lens skills; `commit_test.rb` bodies. #906 changes only refactorer.md: no overlap, no dependency.
Author
Owner

Work started on branch ticket-907 through /os-sdlc:implement (poodr-ticket-implementation map).

Work started on branch ticket-907 through /os-sdlc:implement (poodr-ticket-implementation map).
Author
Owner

Resolution

Done: Git::Repo#stage now leaves out paths whose deletion is already staged (diff --cached --name-only --diff-filter=D) and skips the staging call when nothing remains; commit --only still commits the deletion. ADR-0171 decision 3 (never -A) kept.

Evidence: Implementation 22 complete, 8 dispatches all pass, suite gate exit 0. Three new tests in tests/command/implementation/commit_test.rb: staged deletion alone, staged deletion with modified and new paths, no raise. Commits 10b106ef, 80362511 on main.

Follow-ups: none

## Resolution **Done:** Git::Repo#stage now leaves out paths whose deletion is already staged (diff --cached --name-only --diff-filter=D) and skips the staging call when nothing remains; commit --only still commits the deletion. ADR-0171 decision 3 (never -A) kept. **Evidence:** Implementation 22 complete, 8 dispatches all pass, suite gate exit 0. Three new tests in tests/command/implementation/commit_test.rb: staged deletion alone, staged deletion with modified and new paths, no raise. Commits 10b106ef, 80362511 on main. **Follow-ups:** none
jared closed this issue 2026-10-02 20:01:53 +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#907
No description provided.