feat(release-prep): auto-stage hook-modified tracked files (eliminate the hooks-must-git-add footgun) #236

Closed
opened 2026-06-28 14:36:16 +02:00 by quartermaster · 0 comments

Why

Surfaced by Engineer during #209 recon (bus id 2911):

release-prep.sh's git commit is explicit-staged-only (no -a). Hooks that modify tracked files must currently call git add themselves, or their edits are silently left uncommitted. This is a footgun for hook authors: the documented mechanism says "hooks modify files," but the staging requirement is undocumented + non-obvious.

#209 (the post_bump_hooks dogfood) ships the convention "hooks must git-add their own changes" as the immediate-scope LEAN A. This tracker proposes the structural fix.

Proposal — ALT B (from #209 fork-2)

Enhance release-prep to auto-stage hook-modified tracked files: snapshot the working tree state before the hook loop, run hooks, then git add any tracked files the hooks modified before the commit.

  • Hooks become "just modify files" — no git add boilerplate needed
  • Eliminates the footgun class (a hook author can never forget to stage)
  • New tracked files (created by a hook) are intentionally NOT auto-staged (those require explicit hook decision; the snapshot-diff only catches modifications to pre-existing tracked files)
  • Untracked files stay untracked (hooks don't accidentally swallow non-related working-tree state)

Implementation surface

  1. Snapshot tracked-file modtimes (or sha256) before the hook loop
  2. Run hooks (existing behavior unchanged)
  3. After hooks: diff snapshot vs. current state; git add any tracked files whose state changed
  4. Existing commit proceeds with the union of hook-staged + auto-staged changes
  5. Bats coverage: hook that modifies a tracked file without git add → auto-staged + committed
  6. Docs: update docs/integration.md § Post-bump hooks to drop the "must git-add" requirement once this lands

Composition

  • Depends on: nothing — purely additive
  • Supersedes: the "hooks must git-add their own changes" convention #209 ships (once this lands, that documentation becomes "auto-staged for you")
  • Engineer-shape: small scope (~30 lines + bats), release-prep is well-tested, low risk

What this PR does NOT do

  • Does NOT auto-stage untracked files (intentional — keeps hooks scoped to existing tracked files)
  • Does NOT change the order of staged vs. unstaged behavior (hook-explicit-staged still wins; auto-staging is additive)
  • Does NOT silently swallow hook errors (set -e propagation unchanged)

Refs

  • Engineer recon: bus 2911 (the surfacing during #209 dogfood implementation)
  • #209 (sibling: ships LEAN A convention; this PR ships ALT B structural fix)
  • #157 walkthrough audit lineage (the parent thread that surfaced "documented but not dogfooded")

priority/low · size/S

## Why Surfaced by Engineer during #209 recon (bus id 2911): `release-prep.sh`'s `git commit` is explicit-staged-only (no `-a`). Hooks that modify tracked files must currently call `git add` themselves, or their edits are silently left uncommitted. This is a **footgun for hook authors**: the documented mechanism says "hooks modify files," but the staging requirement is undocumented + non-obvious. #209 (the post_bump_hooks dogfood) ships the convention "hooks must git-add their own changes" as the immediate-scope LEAN A. This tracker proposes the structural fix. ## Proposal — ALT B (from #209 fork-2) Enhance release-prep to **auto-stage hook-modified tracked files**: snapshot the working tree state before the hook loop, run hooks, then `git add` any tracked files the hooks modified before the commit. - Hooks become "just modify files" — no `git add` boilerplate needed - Eliminates the footgun class (a hook author can never forget to stage) - New tracked files (created by a hook) are intentionally NOT auto-staged (those require explicit hook decision; the snapshot-diff only catches modifications to pre-existing tracked files) - Untracked files stay untracked (hooks don't accidentally swallow non-related working-tree state) ## Implementation surface 1. Snapshot tracked-file modtimes (or sha256) before the hook loop 2. Run hooks (existing behavior unchanged) 3. After hooks: diff snapshot vs. current state; `git add` any tracked files whose state changed 4. Existing commit proceeds with the union of hook-staged + auto-staged changes 5. Bats coverage: hook that modifies a tracked file without `git add` → auto-staged + committed 6. Docs: update `docs/integration.md` § Post-bump hooks to drop the "must git-add" requirement once this lands ## Composition - **Depends on**: nothing — purely additive - **Supersedes**: the "hooks must git-add their own changes" convention #209 ships (once this lands, that documentation becomes "auto-staged for you") - **Engineer-shape**: small scope (~30 lines + bats), release-prep is well-tested, low risk ## What this PR does NOT do - Does NOT auto-stage untracked files (intentional — keeps hooks scoped to existing tracked files) - Does NOT change the order of staged vs. unstaged behavior (hook-explicit-staged still wins; auto-staging is additive) - Does NOT silently swallow hook errors (set -e propagation unchanged) ## Refs - Engineer recon: bus 2911 (the surfacing during #209 dogfood implementation) - #209 (sibling: ships LEAN A convention; this PR ships ALT B structural fix) - #157 walkthrough audit lineage (the parent thread that surfaced "documented but not dogfooded") priority/low · size/S
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
frankenbit/release-toolkit#236
No description provided.