From 0f3a7d83597062155e236cf1e9d3b4290e1e8f73 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 20 Jan 2026 21:46:27 +0000 Subject: [PATCH 1/3] Bump version to 0.3.1 Add changelog entry for `created` rule mode support which allows rules to match only newly created files, not modifications to existing files. --- CHANGELOG.md | 11 +++++++++++ pyproject.toml | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50a76c10..15747bb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,16 @@ All notable changes to DeepWork will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.3.1] - 2026-01-20 + +### Added +- `created` rule mode for matching only newly created files (#76) + - Rules with `mode: created` only fire when files are first added, not on modifications + - Useful for enforcing patterns on new files without triggering on existing file edits + +### Fixed +- Fixed `created` mode rules incorrectly firing on modified files (#83) + ## [0.3.0] - 2026-01-18 ### Added @@ -100,6 +110,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Initial version. +[0.3.1]: https://github.com/anthropics/deepwork/releases/tag/0.3.1 [0.3.0]: https://github.com/anthropics/deepwork/releases/tag/0.3.0 [0.1.1]: https://github.com/anthropics/deepwork/releases/tag/0.1.1 [0.1.0]: https://github.com/anthropics/deepwork/releases/tag/0.1.0 diff --git a/pyproject.toml b/pyproject.toml index f3d38afd..dd0111a5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "deepwork" -version = "0.3.0" +version = "0.3.1" description = "Framework for enabling AI agents to perform complex, multi-step work tasks" readme = "README.md" requires-python = ">=3.11" From f3cc2de02daa1ac504f49d798ff1cc3500ac828a Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 20 Jan 2026 21:55:06 +0000 Subject: [PATCH 2/3] 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. --- .../hooks/capture_prompt_work_tree.sh | 8 ++++ CHANGELOG.md | 2 + src/deepwork/hooks/rules_check.py | 48 +++++++++++++++---- uv.lock | 2 +- 4 files changed, 51 insertions(+), 9 deletions(-) diff --git a/.deepwork/jobs/deepwork_rules/hooks/capture_prompt_work_tree.sh b/.deepwork/jobs/deepwork_rules/hooks/capture_prompt_work_tree.sh index 3f2cefad..c9cedd82 100755 --- a/.deepwork/jobs/deepwork_rules/hooks/capture_prompt_work_tree.sh +++ b/.deepwork/jobs/deepwork_rules/hooks/capture_prompt_work_tree.sh @@ -8,12 +8,20 @@ # The baseline contains ALL tracked files (not just changed files) so that # the rules_check hook can determine which files are genuinely new vs which # files existed before and were just modified. +# +# It also captures the HEAD commit ref so that committed changes can be detected +# by comparing HEAD at Stop time to the captured ref. set -e # Ensure .deepwork directory exists mkdir -p .deepwork +# Save the current HEAD commit ref for detecting committed changes +# This is used by get_changed_files_prompt() to detect files changed since prompt, +# even if those changes were committed during the agent response. +git rev-parse HEAD > .deepwork/.last_head_ref 2>/dev/null || echo "" > .deepwork/.last_head_ref + # Save ALL tracked files (not just changed files) # This is critical for created: mode rules to distinguish between: # - Newly created files (not in baseline) -> should trigger created: rules diff --git a/CHANGELOG.md b/CHANGELOG.md index 15747bb1..239c98de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fixed `created` mode rules incorrectly firing on modified files (#83) +- Fixed `compare_to: prompt` mode not detecting files that were committed during agent response + - Rules like `uv-lock-sync` now correctly fire even when changes are committed before the Stop hook runs ## [0.3.0] - 2026-01-18 diff --git a/src/deepwork/hooks/rules_check.py b/src/deepwork/hooks/rules_check.py index 0dae0777..38a37606 100644 --- a/src/deepwork/hooks/rules_check.py +++ b/src/deepwork/hooks/rules_check.py @@ -201,27 +201,59 @@ def get_changed_files_default_tip() -> list[str]: def get_changed_files_prompt() -> list[str]: """Get files changed since prompt was submitted. - Returns ALL files with staged changes (modified, added, deleted). + Returns files that changed since the prompt was submitted, including: + - Committed changes (compared to captured HEAD ref) + - Staged changes (not yet committed) + - Untracked files + This is used by trigger/safety, set, and pair mode rules to detect file modifications during the agent response. - - Note: The baseline file (.last_work_tree) is NOT used here - it's only - used by get_created_files_prompt() to detect truly NEW files for - created: mode rules. """ + baseline_ref_path = Path(".deepwork/.last_head_ref") + changed_files: set[str] = set() + try: + # Stage all changes first subprocess.run(["git", "add", "-A"], capture_output=True, check=False) + # If we have a captured HEAD ref, compare committed changes against it + if baseline_ref_path.exists(): + baseline_ref = baseline_ref_path.read_text().strip() + if baseline_ref: + # Get files changed in commits since the baseline + result = subprocess.run( + ["git", "diff", "--name-only", baseline_ref, "HEAD"], + capture_output=True, + text=True, + check=False, + ) + if result.returncode == 0 and result.stdout.strip(): + committed_files = set(result.stdout.strip().split("\n")) + changed_files.update(f for f in committed_files if f) + + # Also get currently staged changes (in case not everything is committed) result = subprocess.run( ["git", "diff", "--name-only", "--cached"], capture_output=True, text=True, check=False, ) - current_files = set(result.stdout.strip().split("\n")) if result.stdout.strip() else set() - current_files = {f for f in current_files if f} + if result.stdout.strip(): + staged_files = set(result.stdout.strip().split("\n")) + changed_files.update(f for f in staged_files if f) + + # Include untracked files + result = subprocess.run( + ["git", "ls-files", "--others", "--exclude-standard"], + capture_output=True, + text=True, + check=False, + ) + if result.stdout.strip(): + untracked_files = set(result.stdout.strip().split("\n")) + changed_files.update(f for f in untracked_files if f) - return sorted(current_files) + return sorted(changed_files) except (subprocess.CalledProcessError, OSError): return [] diff --git a/uv.lock b/uv.lock index c4091ca4..249bb418 100644 --- a/uv.lock +++ b/uv.lock @@ -126,7 +126,7 @@ toml = [ [[package]] name = "deepwork" -version = "0.3.0" +version = "0.3.1" source = { editable = "." } dependencies = [ { name = "click" }, From cde73fc673f6acdf2a51e16cdaff56129efe68bd Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 20 Jan 2026 21:56:19 +0000 Subject: [PATCH 3/3] Add DeepWork runtime artifacts to .gitignore --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index 323bd21d..93694a7d 100644 --- a/.gitignore +++ b/.gitignore @@ -83,3 +83,8 @@ dmypy.json *.tmp .temp/ tmp/ + +# DeepWork runtime artifacts +.deepwork/.last_work_tree +.deepwork/.last_head_ref +.deepwork/tmp/