Fix git commits re-populating dirty-files in default mode (#22)

In default mode, after the memory-updater processes files and SubagentStop
clears dirty-files, a git commit via Bash would re-trigger PostToolUse,
extract committed files via git diff-tree, and re-add them to dirty-files.
This caused the Stop hook to fire again for already-processed files.

Add early-return guard so default mode skips git commit processing (files
are already tracked via Edit/Write hooks). Also fix existing test to run
commit context enrichment in gitmode where it belongs.
This commit is contained in:
John Reilly Pospos
2026-02-14 12:57:33 +10:00
committed by GitHub
parent 58d9cbc25a
commit 408d4019b3
3 changed files with 28 additions and 4 deletions

View File

@@ -122,6 +122,8 @@ Recent design decisions from commit history:
- Template enforcement added to ensure consistent CLAUDE.md structure
- Git commit context enrichment for better change tracking
- Configurable trigger modes (default vs gitmode)
- Windows compatibility: python3/python fallback pattern in hook commands
- Default mode optimization: Skip git commit tracking (files already tracked via Edit/Write)
<!-- END AUTO-MANAGED -->

View File

@@ -9,8 +9,8 @@ Supports configurable trigger modes:
- default: Track Edit/Write/Bash operations (current behavior)
- gitmode: Only track git commits
When a git commit is detected, enriches each file path with inline commit
context: /path/to/file [hash: commit message]
In gitmode, when a git commit is detected, enriches each file path with
inline commit context: /path/to/file [hash: commit message]
"""
from __future__ import annotations
@@ -262,6 +262,10 @@ def main():
if trigger_mode == "gitmode" and not is_git_commit:
return
# In default mode, skip git commits (files already tracked via Edit/Write hooks)
if trigger_mode == "default" and is_git_commit:
return
files_to_track = []
commit_context = None

View File

@@ -336,6 +336,19 @@ class TestPostToolUseHook:
assert "deleted.py" in content
assert "/dev/null" not in content
def test_skip_git_commit_in_default_mode(self, tmp_path):
"""Hook skips git commit commands in default mode (files tracked via Edit/Write)."""
env = {"CLAUDE_PROJECT_DIR": str(tmp_path)}
subprocess.run(
[sys.executable, SCRIPTS_DIR / "post-tool-use.py"],
env={**os.environ, **env},
input=self._make_bash_input("git commit -m 'Add feature'"),
capture_output=True,
text=True,
)
dirty_file = tmp_path / ".claude" / "auto-memory" / "dirty-files"
assert not dirty_file.exists()
class TestStopHook:
"""Tests for trigger.py Stop hook behavior."""
@@ -753,10 +766,15 @@ class TestGitCommitContext:
sys.modules.pop("post-tool-use", None)
def test_commit_enriches_dirty_files_with_context(self, tmp_path):
"""Git commit command enriches dirty files with inline context."""
"""Git commit command enriches dirty files with inline context in gitmode."""
# Initialize git repo
self._init_git_repo(tmp_path)
# Set up gitmode config (commit enrichment only applies in gitmode)
config_dir = tmp_path / ".claude" / "auto-memory"
config_dir.mkdir(parents=True, exist_ok=True)
(config_dir / "config.json").write_text(json.dumps({"triggerMode": "gitmode"}))
# Create and commit a file
test_file = tmp_path / "module.py"
test_file.write_text("# module")
@@ -778,7 +796,7 @@ class TestGitCommitContext:
)
# Check dirty files contain commit context
dirty_file = tmp_path / ".claude" / "auto-memory" / "dirty-files"
dirty_file = config_dir / "dirty-files"
assert dirty_file.exists()
content = dirty_file.read_text()