Replace Git::Repo#stage filter with git update-index and revise ADR-0171 decision 3 #925
Labels
No labels
P0
P1
P2
P3
bug
category/code-change
category/cross-repo
category/eval-run
category/investigation
category/no-test-target
category/owner-ruling
category/prose-artifact
category/recurring-chore
category/structure
category/umbrella
crc-refactor
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
rule-proposal
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#925
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?
Problem
ADR-0171 decision 3 names git verbs (
git add --,git commit --only) and bans others.The intent of the decision is to commit only the listed paths and to not sweep in user work.
The verb list is structure, not intent.
It blocked the one-command fix in #907, so
Git::Repo#stageshipped a filter (paths - listed("diff", "--cached", "--name-only", "--diff-filter=D")) in place ofgit update-index --add --remove -- <paths>.The #907 session rejected
update-indexfor this reason: "It works for all four states, but it replaces thegit addverb of ADR-0171 decision 3 (kept by ADR-0249). That needs a user ruling, and an option that keeps the ADR is available."Jared ruled "disagree" on closed #907 on 2026-10-03: "the simple command,
git update-indexwould resolve the more cleanly than the 'after' method that shipped. If that's the case, this is an automatic 'disagree'. IDGAF, what some ADR says. If the obvious correct answer is avoided because of an ADR, then that ADR needs to be challenged, just as we have lens challenges. My gut on that says that this ADR violates the not structure heuristic, and should either be discarded or revised."On ADR-0171 not recording the filter, he said: "I am wondering if the challenge should be that the ADR is covering structure, and preventing the programming team from writing good code as a result."
This ruling is the authority to revise decision 3.
Observed
Probe on git 2.55.0 in a scratch repository: one modified path (
mod), one new untracked path (newf), one unstaged deletion (del), one deletion staged withgit rm(staged), and one unrelated dirty file (unrel) outside the path list.The index then held
M mod,A newf,D del,D staged, andunrelstayed unstaged.The commit held all four changes and left
unrelout.The commit held all four changes and left
unrelout.Plain
git commitafterupdate-indexworks. It would also commit a path that the user staged by hand, so--onlystays in the commit step.update-indexis correct and is one command for all four states.Reproduce
n/a: design ticket. The probe above is the evidence.
Approach
Replace the filter in
Git::Repo#stagewithrun("update-index", "--add", "--remove", "--", *paths). Keepgit commit --only -- <paths>. Decision 3 intent stays: commit only the listed paths.Decision 3 of ADR-0171, quoted: "Only additive git verbs.
git add -- <paths>thengit commit --only -m <message> -- <paths>. Never-a, never-A, nevercheckout,restore, orstash.--onlypins the commit to the named paths, so a file the user staged by hand is not swept in."The stated reason is in the Context of ADR-0171: "any
git add -Awould sweep work in progress into a pipeline commit, and anycheckout/restorewould destroy it."Intent: commit only the listed paths; do not sweep in user work; do not destroy user work. This is the
--onlypin, the never--a/-Arule, and the ban oncheckout,restore, andstash.Prescribed command:
git add --as the staging verb. ADR-0249 kept it ("git add -- <paths>andgit commit --only").update-index --add --remove -- <paths>is as safe: it touches only the listed paths and never the working tree.Required work:
Git::Repo#stagewithupdate-index --add --remove— check: absent--diff-filter=Dinplugins/os-sdlc/lib/os_sdlc/git/repo.rbupdate-indexinGit::Repo#stage— check: presentupdate-indexinplugins/os-sdlc/lib/os_sdlc/git/repo.rbOrchestrator work: Amend or supersede ADR-0171 decision 3 (run
/os-adr:findfirst, then/os-adr:create; never silently reverse an Accepted ADR). The new text records the intent (commit only the listed paths, never sweep in or destroy user work,--onlypins the commit) and not the git verb for staging. Update ADR-0249's quoted line if the superseding ADR needs it. Challenge the other structure in ADR-0171 for the same fault, as with a lens challenge.Rejected: keep the filter and amend only the ADR text — the filter is a second code path that
update-indexremoves.Acceptance criteria
git rm, when the Runner stages and commits the four paths, then it does not raise and the commit holds all four changes.git mv, when the Runner stages and commits the old and the new path, then it does not raise and the commit holds the rename.Owner sketch
Non-goals
Tests for obscure index states (type changes, submodules, conflicts). A staged rename is not obscure: it stopped implementation 149 (#1284) on 2026-10-23 (occurrence comment on this ticket), so AC6 covers it. Cover the likely states in the acceptance criteria. The test for an unstaged deletion is worth one more test-reviewer to test-writer cycle, at lower importance.
Origin
Repo#stage← #907 rejectedupdate-index← ADR-0171 decision 3 namesgit add --as the staging verb (docs/adr/0171-the-runner-commits-deterministically-at-implementation-complete-staging-only-handoff-listed-paths-opt-in-per-project.md; kept by ADR-0249) ← DESIGN (ADR-0171 decision 3 covers structure)Parent: #907. VERDICT: CREATE
Occurrence: Stage the old path of a staged rename in Git::Repo#stage
Seen: plugins/os-sdlc/lib/os_sdlc/git/repo.rb:81 OsSdlc::Git::Repo#stage
Run: implementation 149 (#1284), dispatch 1274, session c1bedec6-7e01-45ab-b9db-22d63652c19f
Adds: a staged rename (git mv open_notification.rb -> document_notification.rb by the refactorer) also fails: --diff-filter=D does not list the old path of an R entry, so 'git add -- ' exits 128 (pathspec did not match). The stop saved verdict pass and completed_at but left routed_at nil, so the run stopped at await_completion. Please add the staged-rename case to the acceptance criteria. Repro: git mv a.rb b.rb; git add -- a.rb
Work started in session c1bedec6, worktree crc-os-sdlc-run-4 (branch crc-os-sdlc-run-4), through /os-sdlc:implement. Body corrected: required-work paths now name plugins/os-sdlc/lib/os_sdlc/git/repo.rb (adapter/ was removed), AC6 added for a staged rename, category umbrella -> code-change.
Resolution
Done: Git::Repo#stage runs git update-index --add --remove -- (one command for modified, new, deleted, staged-deleted, and staged-renamed paths); the --diff-filter=D skip list is gone. Commit stays git commit --only. ADR-0171 decision 3 amended to record the intent (stage only listed paths, never touch the working tree) instead of a git verb. Commits
d3ee28d1(implementation 150) and the ADR commit on crc-os-sdlc-run-4.Evidence: Pipeline implementation 150 complete: suite-check pass (60 s), contract-auditor pass; AC1-AC6 tests in tests/implementation/commit_test.rb, AC6 covers a staged rename. Scratch probe: git mv a.rb b.rb then update-index --add --remove -- a.rb b.rb and commit --only exit 0, commit shows a.rb => b.rb, unrelated dirty file left out. /os-adr:create judge accepted the amendment and trimmed the verb name as implementation detail.
Follow-ups: none