Skip to content

Comments

Refactor rules_check.py git operations#98

Closed
nhorton wants to merge 17 commits intomainfrom
claude/refactor-git-operations-2WxqO
Closed

Refactor rules_check.py git operations#98
nhorton wants to merge 17 commits intomainfrom
claude/refactor-git-operations-2WxqO

Conversation

@nhorton
Copy link
Contributor

@nhorton nhorton commented Jan 21, 2026

  • Create GitComparator abstract base class with get_changed_files(), get_created_files(), and get_baseline_ref() methods
  • Implement CompareToBase, CompareToDefaultTip, and CompareToPrompt classes with encapsulated git comparison logic
  • Add get_comparator() factory function for selecting the right comparator
  • Update rules_check.py to use the new comparator interface
  • Add detailed header comments documenting call sites and related files
  • Extract ~200 lines of git operations into reusable, testable module

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors approximately 200 lines of git comparison logic from rules_check.py into a new reusable module git_utils.py. The refactoring introduces an object-oriented design using abstract base classes and factory pattern to encapsulate different git comparison strategies.

Changes:

  • Created GitComparator abstract base class with three concrete implementations (CompareToBase, CompareToDefaultTip, CompareToPrompt)
  • Added factory function get_comparator() for selecting the appropriate comparator
  • Updated rules_check.py to use the new comparator interface, removing duplicate git operation code
  • Enhanced module documentation with detailed call sites and related files information

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/deepwork/core/git_utils.py New module containing GitComparator abstraction and implementations for three comparison strategies (base, default_tip, prompt) with helper functions for git operations
src/deepwork/hooks/rules_check.py Removed ~350 lines of git operation functions, replaced with calls to get_comparator(); updated header documentation with CALL SITES and RELATED FILES sections

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…s.py

- Create GitComparator abstract base class with common interface
- Add RefBasedComparator intermediate class to eliminate duplication between
  CompareToBase and CompareToDefaultTip (they now only define _get_ref())
- Extract helper functions: _parse_file_list(), _run_git(), _collect_all_files()
- CompareToPrompt remains separate due to its file-based baseline approach
- Update rules_check.py to use the new comparator interface
- Add detailed header comments documenting call sites and related files

The refactored code reduces ~370 lines of repetitive git operations to ~275 lines
with proper abstraction and DRY principles applied.
@nhorton nhorton force-pushed the claude/refactor-git-operations-2WxqO branch from 5da6c0d to 8921236 Compare January 21, 2026 17:18
nhorton and others added 16 commits January 21, 2026 10:31
- Fix CompareToPrompt.get_created_files() to include files added in commits
  since the baseline ref (was only checking staged/untracked files)
- Simplify git operations by using a single `git diff --cached ref` command
  after staging all changes, instead of multiple separate commands
- Add _get_all_changes_vs_ref() helper that captures committed, staged, and
  untracked changes in one command
- Add comprehensive test suite for git_utils module (35 tests)
The new code was incorrectly using .last_head_ref for created files detection
when available. This caused uncommitted files from before the prompt to be
incorrectly flagged as "created".

The fix restores the original behavior: always use .last_work_tree for created
files detection, since it contains the actual list of files that existed at
prompt time (including uncommitted files).

Added a test that explicitly verifies this behavior.
Reorganize test_git_utils.py to clearly separate requirements tests
from implementation tests, following the pattern in test_install_requirements.py:

Requirements tested:
- REQ-001: All comparators MUST implement GitComparator interface
- REQ-002: get_comparator() MUST return correct comparator for each mode
- REQ-003: CompareToPrompt.get_created_files() MUST use .last_work_tree
- REQ-004: Created files are those NOT present in baseline

The requirements tests are placed at the top with DO NOT MODIFY warnings,
while implementation tests are grouped separately below.
- Fix misleading comments about "current files" to clarify they are
  files that differ from HEAD
- Add defensive programming comments for _get_untracked_files() calls
- Remove incomplete test_get_changed_files_in_real_repo test
- Fix weak assertion in test_strips_outer_whitespace_only
Use Git plumbing commands (temporary index + write-tree + diff-tree) for
detecting changes since prompt submission. This is more reliable than the
previous approach because:

- FAST: Git is optimized for tree comparisons
- SAFE: Uses temporary index, doesn't touch actual staging area
- COMPLETE: Handles all cases (modified, new, deleted, staged, unstaged)
- ACCURATE: git diff-tree is Git's native tree comparison

Changes:
- capture_prompt_work_tree.sh: Creates tree object at prompt time
- git_utils.py: Add _create_tree_from_working_dir() and _diff_trees() helpers
- CompareToPrompt: Uses tree-based comparison as primary method with
  fallback to file-list comparison for backwards compatibility
- install.py: Add .last_tree_hash to .gitignore config
- test_git_utils.py: Add tests for tree-based functions and update
  existing tests to cover both primary and fallback paths
- Changed ambiguous "❌ No" to "✅ Excluded" for ignored files row
- Added "(gitignore)" label to make it clear what "ignored" means
- Updated explanation to "Correctly excluded - rules don't trigger"
- Added `unset GIT_INDEX_FILE` after temp index cleanup for defensive coding
@nhorton nhorton closed this Feb 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants