Skip to content

Commit f3cc2de

Browse files
committed
Fix compare_to:prompt mode not detecting committed changes
The get_changed_files_prompt() function only looked at staged changes, which meant files committed during an agent response were not detected. Changes: - capture_prompt_work_tree.sh now saves HEAD ref to .last_head_ref - get_changed_files_prompt() compares HEAD against captured ref to detect committed changes in addition to staged/untracked files This fixes rules like uv-lock-sync that use compare_to:prompt not firing when pyproject.toml is committed before the Stop hook runs.
1 parent 0f3a7d8 commit f3cc2de

File tree

4 files changed

+51
-9
lines changed

4 files changed

+51
-9
lines changed

.deepwork/jobs/deepwork_rules/hooks/capture_prompt_work_tree.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,20 @@
88
# The baseline contains ALL tracked files (not just changed files) so that
99
# the rules_check hook can determine which files are genuinely new vs which
1010
# files existed before and were just modified.
11+
#
12+
# It also captures the HEAD commit ref so that committed changes can be detected
13+
# by comparing HEAD at Stop time to the captured ref.
1114

1215
set -e
1316

1417
# Ensure .deepwork directory exists
1518
mkdir -p .deepwork
1619

20+
# Save the current HEAD commit ref for detecting committed changes
21+
# This is used by get_changed_files_prompt() to detect files changed since prompt,
22+
# even if those changes were committed during the agent response.
23+
git rev-parse HEAD > .deepwork/.last_head_ref 2>/dev/null || echo "" > .deepwork/.last_head_ref
24+
1725
# Save ALL tracked files (not just changed files)
1826
# This is critical for created: mode rules to distinguish between:
1927
# - Newly created files (not in baseline) -> should trigger created: rules

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414

1515
### Fixed
1616
- Fixed `created` mode rules incorrectly firing on modified files (#83)
17+
- Fixed `compare_to: prompt` mode not detecting files that were committed during agent response
18+
- Rules like `uv-lock-sync` now correctly fire even when changes are committed before the Stop hook runs
1719

1820
## [0.3.0] - 2026-01-18
1921

src/deepwork/hooks/rules_check.py

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -201,27 +201,59 @@ def get_changed_files_default_tip() -> list[str]:
201201
def get_changed_files_prompt() -> list[str]:
202202
"""Get files changed since prompt was submitted.
203203
204-
Returns ALL files with staged changes (modified, added, deleted).
204+
Returns files that changed since the prompt was submitted, including:
205+
- Committed changes (compared to captured HEAD ref)
206+
- Staged changes (not yet committed)
207+
- Untracked files
208+
205209
This is used by trigger/safety, set, and pair mode rules to detect
206210
file modifications during the agent response.
207-
208-
Note: The baseline file (.last_work_tree) is NOT used here - it's only
209-
used by get_created_files_prompt() to detect truly NEW files for
210-
created: mode rules.
211211
"""
212+
baseline_ref_path = Path(".deepwork/.last_head_ref")
213+
changed_files: set[str] = set()
214+
212215
try:
216+
# Stage all changes first
213217
subprocess.run(["git", "add", "-A"], capture_output=True, check=False)
214218

219+
# If we have a captured HEAD ref, compare committed changes against it
220+
if baseline_ref_path.exists():
221+
baseline_ref = baseline_ref_path.read_text().strip()
222+
if baseline_ref:
223+
# Get files changed in commits since the baseline
224+
result = subprocess.run(
225+
["git", "diff", "--name-only", baseline_ref, "HEAD"],
226+
capture_output=True,
227+
text=True,
228+
check=False,
229+
)
230+
if result.returncode == 0 and result.stdout.strip():
231+
committed_files = set(result.stdout.strip().split("\n"))
232+
changed_files.update(f for f in committed_files if f)
233+
234+
# Also get currently staged changes (in case not everything is committed)
215235
result = subprocess.run(
216236
["git", "diff", "--name-only", "--cached"],
217237
capture_output=True,
218238
text=True,
219239
check=False,
220240
)
221-
current_files = set(result.stdout.strip().split("\n")) if result.stdout.strip() else set()
222-
current_files = {f for f in current_files if f}
241+
if result.stdout.strip():
242+
staged_files = set(result.stdout.strip().split("\n"))
243+
changed_files.update(f for f in staged_files if f)
244+
245+
# Include untracked files
246+
result = subprocess.run(
247+
["git", "ls-files", "--others", "--exclude-standard"],
248+
capture_output=True,
249+
text=True,
250+
check=False,
251+
)
252+
if result.stdout.strip():
253+
untracked_files = set(result.stdout.strip().split("\n"))
254+
changed_files.update(f for f in untracked_files if f)
223255

224-
return sorted(current_files)
256+
return sorted(changed_files)
225257

226258
except (subprocess.CalledProcessError, OSError):
227259
return []

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)