Skip to content

Pin split-Bash-call stage-ready discipline to CLAUDE.md (PR #641 retired-mitigation) #647

@michael-wojcik

Description

@michael-wojcik

Background

PR #641 Cycle-3 surfaced a recurring failure mode: when an agent prepares a stage-ready paste describing what's been edited and staged, the prose can drift from disk reality. Concrete instances during #641:

  • Cycle-3: backend-coder claimed 3 files / 940 lines / sanitize_slug helper / NEW test_session_state.py — disk showed 5 files / 133 lines / inline regex. Prose-output substituted for tool-call-belief.
  • Cycle-3: architect claimed git add ran but disk showed no modifications. On retry: "I prepared diffs in my plan + composed the stage-ready paste, but never actually invoked Edit."
  • Cycle-3: lost ~5 minutes per drift to investigation + correction + recompose.

PR #641 Cycle-4 validated a mitigation: split-Bash-call discipline + M+space vs space+M cross-check. The architect applied it consistently and the verify-only round flagged zero drift. Backend's HANDOFF retired the open issue as "known recipe."

Recipe

For any stage-ready paste:

1. Edit the file (separate Bash call — Edit tool, not Bash)
2. Run `git diff <file>` (separate Bash call) — capture pre-add state
3. Run `git add <file>` (separate Bash call) — never compound `&& git add`
4. Run `git status --short` (separate Bash call) — capture post-add state
5. Run `git diff --cached --stat -- <file>` (separate Bash call) — capture index-state
6. Compose stage-ready prose AGAINST the captured Bash outputs (paste byte-equal from step 5)

Cross-check: in step 4 output, your file should show "M " (M followed by space — left-side M).
If it shows " M" (space followed by M — right-side M), the file is in working-tree only,
NOT in the index. Investigate before composing the paste.

Why each step matters

  • Step 1 separate from 2: Compound Edit && git diff would fail if Edit fails, but the bigger issue is that Edit's output isn't captured. Diff against disk after Edit is the verification.
  • Step 2 separate from 3: git diff shows working-tree changes. If empty, Edit didn't actually run (architect's case).
  • Step 3 separate from 4: Compound git add && git status collapses two facts (add succeeded, post-add state) into one observation. Separating gives audit-grain.
  • Step 4 separate from 5: git status --short shows index vs working-tree state per file (M+space vs space+M). --cached --stat shows what's staged. Both are needed for index-state confidence.
  • Step 6 against captured outputs: prose-vs-disk drift happens because the LLM is writing prose from its mental model, not from the substrate's actual state. Pasting from captured outputs forces the prose to match reality.

Proposal — pin to CLAUDE.md as stable recipe

Per pinned project rule structure, add a new pinned context entry to project CLAUDE.md:

### Split-Bash-call stage-ready discipline (PR #641 retired-mitigation)

For any stage-ready paste in a peer-review remediation cycle, follow the 5-step
Bash-call sequence: Edit → diff → add → status → stat — each in a separate
Bash invocation. Compose prose against captured outputs.

Cross-check: `git status --short` left-side M (M+space) = staged; right-side M
(space+M) = working-tree only. Drift surfaces here, not at commit-time.

Prevents prose↔tool-call-belief drift in stage-ready announcements (recurring
#642 instance class).

Acceptance criteria

Cross-references

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions