fix(hook): do not stage fixes when fail_on_fix=true#892
Conversation
When `fail_on_fix=true` is set on a hook, the step's auto-staging would silently re-stage the fixer's output over the user's explicit `git add` choices. After the failed commit the user couldn't see the proposed fix as an unstaged change for review, and a re-commit would silently succeed with the fix baked in — defeating the entire point of `fail_on_fix`. Force `should_stage=false` during fix runs when `fail_on_fix=true`. The fixer's output stays in the worktree as an unstaged change, the user's staged changes are preserved, and a re-commit will fail again until the user explicitly accepts the fix. Closes #888 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Greptile SummaryThis PR fixes a bug (#888) where Confidence Score: 5/5This PR is safe to merge — it is a minimal, well-targeted fix with a solid regression test covering the exact bug scenario. The change is two lines touching a single, narrow condition. The logic is correct: forcing No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant Git
participant HK as hk (pre-commit)
participant Fixer
User->>Git: git add a.json
User->>Git: git commit -m "update"
Git->>HK: run pre-commit hook
Note over HK: fail_on_fix=true, run_type=Fix<br/>→ should_stage forced to false
HK->>Fixer: run fix step on a.json
Fixer-->>HK: a.json modified (spaces stripped)
Note over HK: should_stage=false → skip git add
HK-->>Git: fail (files were modified by fixer)
Git-->>User: commit rejected
Note over User,Git: After fix (correct behavior)
User->>Git: git diff --cached a.json
Git-->>User: shows user's original staged change (a.json with spaces)
User->>Git: git diff a.json
Git-->>User: shows fixer's unstaged change (spaces stripped)
Reviews (1): Last reviewed commit: "fix(hook): do not stage fixes when fail_..." | Re-trigger Greptile |
There was a problem hiding this comment.
Code Review
This pull request modifies the hook execution logic in src/hook.rs to prevent automatic staging of fixes when fail_on_fix is enabled, ensuring that fixes are surfaced for manual review. Additionally, a new integration test in test/fail_on_fix.bats verifies that existing staged changes are preserved and fixes appear as unstaged changes. I have no feedback to provide.
### 🐛 Bug Fixes - **(hook)** do not stage fixes when fail_on_fix=true by [@jdx](https://github.com/jdx) in [#892](#892) - use site domain for plausible data-domain by [@jdx](https://github.com/jdx) in [#886](#886) - make text-mode progress output usable in CI by [@jdx](https://github.com/jdx) in [#890](#890) ### 📚 Documentation - prefix GitHub star count with ★ glyph by [@jdx](https://github.com/jdx) in [#883](#883) ### 🔍 Other Changes - **(release)** dedupe sponsor section in release notes by [@jdx](https://github.com/jdx) in [#881](#881) - switch analytics from gtm/goatcounter to plausible by [@jdx](https://github.com/jdx) in [#885](#885) - migrate to namespace.so runners by [@jdx](https://github.com/jdx) in [#891](#891) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk release bookkeeping: version bumps, regenerated docs, and lockfile dependency updates with no functional code changes in this PR. > > **Overview** > Bumps `hk` to **v1.44.3** and adds the corresponding `CHANGELOG.md` release entry. > > Regenerates versioned docs/CLI artifacts to reference `1.44.3` (package URLs and generated `commands.json`/`index.md`) and updates `Cargo.lock` with dependency resolution changes (notably `jni`, `rustls*`, `reqwest`, `wasm-bindgen`, and `thiserror` unification). > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit ab7b72e. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: mise-en-dev <123107610+mise-en-dev@users.noreply.github.com>
Summary
When a hook has
fail_on_fix=true, the step's auto-staging would silently re-stage the fixer's output over the user's explicitgit addchoices. After the failed commit:fail_on_fixThis is the bug reported in #888.
Fix
Force
should_stage = falseduring fix runs whenfail_on_fix = true(src/hook.rs:828). The fixer's output stays in the worktree as an unstaged change, the user's staged changes are preserved, and a re-commit will fail again until the user explicitly accepts the fix.After the fix, the user's reproduction scenario yields exactly what they expected:
Test plan
test/fail_on_fix.batsreproducing the discussion scenariofail_on_fix.batstests pass in bothlibgit2andnolibgit2modescargo test(145 tests) passesCloses #888
🤖 Generated with Claude Code
Note
Medium Risk
Changes
pre-commit/hook execution behavior around git staging during fix runs, which can affect users’ commit contents. Scope is small and covered by a new regression test, but it touches git index/worktree semantics.Overview
Ensures
fail_on_fix=trueruns do not auto-stage fixer modifications by forcingshould_stageoff forRunType::Fix, so a failed hook leaves fixer edits as unstaged changes for review and does not overwrite the user’s staged selection.Adds a Bats regression test reproducing #888 to verify a failed
pre-commitpreserves the original staged diff while exposing the fixer’s reformatting in the working tree.Reviewed by Cursor Bugbot for commit 7a2b202. Bugbot is set up for automated code reviews on this repo. Configure here.