Skip to content

Add core hooks support and worktree coverage#556

Closed
jwiegley wants to merge 44 commits intogit-ai-project:mainfrom
jwiegley:codex/worktree-support-corehooks
Closed

Add core hooks support and worktree coverage#556
jwiegley wants to merge 44 commits intogit-ai-project:mainfrom
jwiegley:codex/worktree-support-corehooks

Conversation

@jwiegley
Copy link
Copy Markdown
Contributor

@jwiegley jwiegley commented Feb 18, 2026

Summary

  • Core hooks support: Adds core_hooks.rs module enabling hook installation via core.hooksPath as an alternative to wrapper-binary mode, with full lifecycle handling (commit, rebase, reset, stash, push, fetch, cherry-pick, merge, checkout, switch)
  • Worktree support: Comprehensive test coverage for git worktree operations across all hook modes (wrapper, hooks, both), including worktree-aware test infrastructure (WorktreeRepo, with_worktree_mode, snapshot variants)
  • Dual skip mechanism: Internal git commands now set both GITAI_SKIP_MANAGED_HOOKS and GIT_AI_SKIP_CORE_HOOKS env vars to prevent hook re-entry in either mode

Built on top of the codex/global-hooks-dual-mode branch (repo-local hook management rewrite).

Changes

New files

  • src/commands/core_hooks.rs — Core hooks dispatch and lifecycle management (1,300+ LOC)
  • tests/corehooks_wrapper_regression.rs — Regression tests for dual-mode event recording
  • tests/worktrees.rs — 850+ LOC worktree integration test suite

Modified

  • src/commands/git_handlers.rs — Set both hook-skip env vars on child processes
  • src/git/repository.rs — Add GIT_AI_SKIP_CORE_HOOKS to exec_git* functions
  • src/commands/install_hooks.rs — Core hooks installation integration
  • src/commands/hooks/stash_hooks.rs — Stash attribution fixes for core hooks mode
  • tests/repos/test_repo.rs — Worktree-aware test infrastructure, git_with_env_using_c_flag helper
  • tests/repos/mod.rsworktree_test_wrappers! macro for mode-parameterized tests
  • Multiple test files — Added worktree variant coverage via macro wrappers

Test plan

  • cargo check passes
  • cargo clippy passes clean
  • cargo test --no-run compiles all test binaries
  • CI matrix: wrapper mode, hooks mode, both mode
  • Worktree tests pass in all three modes

🤖 Generated with Claude Code


Open with Devin

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Feb 18, 2026

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
2 out of 3 committers have signed the CLA.

✅ svarlamov
✅ jwiegley
❌ devin-ai-integration[bot]
You have signed the CLA already but the status is still pending? Let us recheck it.

@git-ai-cloud
Copy link
Copy Markdown

git-ai-cloud Bot commented Feb 18, 2026

Stats powered by Git AI

🧠 you    ███████████░░░░░░░░░  56%
🤖 ai     ░░░░░░░░░░░█████████  44%
More stats
  • 0.0 lines generated for every 1 accepted
  • 0 seconds waiting for AI
  • Top model: codex::gpt-5.3-codex (5126 accepted lines, 0 generated lines)

AI code tracked with git-ai

@git-ai-cloud-dev
Copy link
Copy Markdown

git-ai-cloud-dev Bot commented Feb 18, 2026

No AI authorship found for these commits. Please install git-ai to start tracking AI generated code in your commits.

@jwiegley jwiegley marked this pull request as ready for review February 18, 2026 21:35
svarlamov and others added 26 commits February 18, 2026 13:37
Add hook-name binary dispatch and managed global hooks installation with persisted forward state for previous global/local hooksPath. Add repo-level hook self-heal from checkpoint flow, recursion suppression for internal git subprocesses, and wrapper+hooks coexistence safeguards to avoid double execution. Extend test harness with wrapper/hooks/both modes and add hook mode regression coverage.
Bug fixes:
- Cache forward hooks dir lookup in handle_git_hook_invocation to avoid
  redundant state file reads (was reading twice per hook invocation)
- Add is_valid_git_oid_or_abbrev for sequencer done file parsing which
  may contain abbreviated commit hashes (>= 7 chars)

Simplifications:
- Extract parse_whitespace_fields to consolidate parse_hook_stdin and
  parse_reference_transaction_stdin which shared identical parsing logic
- Remove 19-line redundant no-op hook match arm in run_managed_hook that
  duplicated hook_has_no_managed_behavior; wildcard already handles this

Tests (18 new unit tests):
- is_valid_git_oid: SHA-1, SHA-256, rejects short/invalid
- is_valid_git_oid_or_abbrev: abbreviated hex acceptance
- parse_reference_transaction_stdin: 3-field extraction, incomplete lines
- parse_hook_stdin: single-field skip, extra field handling
- parse_whitespace_fields: empty input edge cases
- is_path_inside_component: nested segment detection
- is_path_inside_any_git_ai_dir: .git/ai subtree detection
- hook_has_no_managed_behavior: correct classification
- cherry_pick_batch_state: serialization roundtrip
- repo_hook_state: serialization roundtrip
- forward_mode_none: serialization format
- ensure_hook_symlink: idempotency
- rebase_hook_mask: double-enable is noop
- managed/rebase hook name subset invariants

Co-Authored-By: Sasha Varlamov <sasha@sashavarlamov.com>
devin-ai-integration Bot and others added 16 commits February 18, 2026 13:38
…anaged_behavior, share git_dir lookup, remove dead code, add tests

Co-Authored-By: Sasha Varlamov <sasha@sashavarlamov.com>
…, fix silent hook breakage in hooks-only mode

Co-Authored-By: Sasha Varlamov <sasha@sashavarlamov.com>
… original exists in forward dir

- Extract sync_non_managed_hook_symlinks to scan forward target dir and only install
  symlinks for non-managed hooks whose original script exists there
- Symlinks point to git-ai binary (not original script) so forwarding preserves
  $0/dirname for Husky-style hooks that resolve relative paths
- Stale symlinks cleaned up when original hook is removed from forward dir
- Self-healing via ensure_repo_hooks_installed re-scans and keeps in sync
- Extract remove_hook_entry helper to deduplicate cleanup logic
- 4 new tests: provisioned-only-when-original-exists, resync cleanup,
  no-forward-target skips non-managed, forward-target with empty dir

Co-Authored-By: Sasha Varlamov <sasha@sashavarlamov.com>
Co-Authored-By: Sasha Varlamov <sasha@sashavarlamov.com>
@jwiegley jwiegley force-pushed the codex/worktree-support-corehooks branch from bed3a1d to 529ba95 Compare February 18, 2026 21:39
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

jwiegley and others added 2 commits February 18, 2026 15:02
- Fix long_rev boundary output to show ^<39 hex> = 40 chars (matching git)
- Update abbrev test to expect ^<N hex> = N+1 chars for boundary commits

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When `install-hooks` sets global `core.hooksPath` to the managed
directory, only hooks listed in INSTALLED_HOOKS previously got shell
scripts.  Any user hook not in the list (e.g. commit-msg,
prepare-commit-msg, pre-merge-commit) was silently lost because git
would look for it in the managed directory and find nothing.

This commit:
1. Adds commit-msg, prepare-commit-msg, and pre-merge-commit to
   INSTALLED_HOOKS so the most commonly used hooks get full managed
   scripts with chaining logic.
2. Adds sync_non_managed_core_hook_scripts() which scans the user's
   previous hooks directory and writes lightweight passthrough scripts
   for any remaining hooks not in INSTALLED_HOOKS.  Stale passthrough
   scripts from prior installations are cleaned up automatically.

This mirrors what the repo-local hooks mode already does via
sync_non_managed_hook_symlinks in git_hook_handlers.rs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jwiegley jwiegley force-pushed the codex/worktree-support-corehooks branch from 40f27dd to 483d595 Compare February 18, 2026 23:22
@jwiegley jwiegley closed this by deleting the head repository Feb 18, 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.

4 participants