Skip to content

fix: make .claude/ hooks canonical, replace amplifier-bundle/ copy with symlink#2881

Open
rysweet wants to merge 2 commits intomainfrom
fix/2845-hooks-canonical-location
Open

fix: make .claude/ hooks canonical, replace amplifier-bundle/ copy with symlink#2881
rysweet wants to merge 2 commits intomainfrom
fix/2845-hooks-canonical-location

Conversation

@rysweet
Copy link
Owner

@rysweet rysweet commented Mar 4, 2026

Summary

Fixes #2845

  • Replace amplifier-bundle/tools/amplihack/hooks/ directory with a symlink to ../../../.claude/tools/amplihack/hooks (the canonical source of truth)
  • Move 4 unique files from amplifier-bundle/ to .claude/: dev_intent_router.py, routing_prompt.txt, test_dev_intent_router.py, test_pre_tool_use_cwd_protection.py
  • Add hooks symlink verification to scripts/check_drift.py (CI will fail if symlink is broken or replaced with a directory)
  • Add Makefile targets: check-drift and verify-hooks-symlink
  • Update drift-detection CI workflow name to reflect hooks coverage

Problem

Both .claude/tools/amplihack/hooks/ and amplifier-bundle/tools/amplihack/hooks/ contained copies of the same hook files with no sync mechanism. On main, 18 files had already drifted between the two locations. PRs that updated one location frequently forgot to update the other.

Approach

.claude/tools/amplihack/hooks/ is the runtime location (referenced by .claude/settings.json). Making it the single source of truth and using a symlink from amplifier-bundle/ eliminates duplication permanently. The symlink works correctly with build_hooks.py because shutil.copytree(symlinks=True) preserves symlinks, and both .claude/ and amplifier-bundle/ are copied to src/amplihack/ during wheel build where the relative symlink resolves correctly.

Test plan

  • Verified symlink resolves correctly: ls amplifier-bundle/tools/amplihack/hooks/ lists canonical files
  • Verified uv build --wheel succeeds and both hook locations appear in the wheel with identical content (126 files each)
  • Verified python scripts/check_drift.py reports "Hooks symlink OK"
  • Verified make verify-hooks-symlink reports "OK: hooks symlink is correct"
  • Verified all hooks referenced in .claude/settings.json exist and are accessible via both paths

Generated with Claude Code

Ubuntu and others added 2 commits March 4, 2026 16:51
…-bundle/ copy with symlink (#2845)

The hooks directory was duplicated between .claude/tools/amplihack/hooks/
(runtime location) and amplifier-bundle/tools/amplihack/hooks/ (distribution).
With 18 files already drifted on main and no sync mechanism, this was a
growing source of bugs.

Changes:
- Replace amplifier-bundle/tools/amplihack/hooks/ directory with a symlink
  to ../../../.claude/tools/amplihack/hooks (the canonical source)
- Move 4 files that only existed in amplifier-bundle/ to .claude/:
  dev_intent_router.py, routing_prompt.txt, test_dev_intent_router.py,
  test_pre_tool_use_cwd_protection.py
- Add hooks symlink verification to scripts/check_drift.py
- Add verify-hooks-symlink and check-drift Makefile targets
- Update drift-detection CI workflow name to include hooks

The symlink works correctly with build_hooks.py (uses symlinks=True in
shutil.copytree), so the wheel build resolves the symlink and includes
real files in both package locations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Contributor

github-actions bot commented Mar 4, 2026

🤖 Auto-fixed version bump

The version in pyproject.toml has been automatically bumped to the next patch version.

If you need a minor or major version bump instead, please update pyproject.toml manually and push the change.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 4, 2026

Repo Guardian - Passed

✅ All files in this PR are legitimate repository content.

This PR refactors hook file organization by:

  • Establishing .claude/tools/amplihack/hooks/ as the canonical source
  • Replacing duplicate directory with a symlink
  • Moving 4 unique files to the canonical location
  • Adding drift detection for the symlink structure

No ephemeral content, temporary scripts, or point-in-time documents detected.

AI generated by Repo Guardian

@github-actions
Copy link
Contributor

github-actions bot commented Mar 5, 2026

Triage Report - HIGH RISK

Risk Level: HIGH
Priority: HIGH
Status: Requires careful review

Concerns

  1. 28,298 line deletions - mostly duplicate file removal, but needs validation
  2. Symlink introduction - cross-platform compatibility must be verified (Windows/macOS/Linux)
  3. 67 files changed - wide surface area
  4. Critical path: Hook system modification

Required Validations

✅ Verify symlink works on all platforms in CI
✅ Confirm hooks execute correctly with symlink
✅ Test coverage includes symlink behavior
✅ Validate no runtime breakage in hook system

Next Steps

  • Wait for CI to pass on all platforms
  • Manual test on Windows (symlink support)
  • Review hook execution paths
  • Merge only after all validations pass

Recommendation: CAREFUL_REVIEW - do not fast-track despite being a bug fix.

AI generated by PR Triage Agent

@github-actions
Copy link
Contributor

github-actions bot commented Mar 7, 2026

⚠️ Triage Assessment: HIGH RISK

Risk Level: High
Priority: High
Category: Refactoring
Recommendation: Needs Testing

Key Metrics

  • Changes: 28,369 lines (71 additions, 28,298 deletions)
  • Files Modified: 67
  • Mergeable State: Unknown

Risk Factors

  1. Major deletions: 28k lines deleted indicates massive restructuring
  2. Symlink strategy: Replacing directory with symlink has cross-platform implications
  3. Hook system changes: Affects core amplihack hook infrastructure
  4. Filesystem assumptions: Code may assume real directories, not symlinks

Critical Testing Required

  • Verify hooks function correctly via symlink on Linux
  • Test on macOS (HFS+ symlink behavior)
  • Test on Windows (requires special permissions or may fail)
  • Confirm no hardcoded paths break with new structure
  • Check that bundled amplifier-bundle still works after symlink
  • Validate file watching tools work through symlinks

Platform-Specific Concerns

Windows: Symlinks require admin privileges or developer mode. Consider alternatives:

  • Hard links for files
  • Directory junctions (supported without elevation)
  • Keep duplicate files with sync mechanism

Recommendation

Before merge:

  1. Test on all 3 platforms (Linux, macOS, Windows)
  2. Document symlink requirements in installation guide
  3. Add fallback mechanism for Windows if symlinks fail
  4. Consider CI matrix testing across platforms

Automated PR triage - Run 22794120070

AI generated by PR Triage Agent

rysweet pushed a commit that referenced this pull request Mar 7, 2026
…a symlink (#2881)

Replace amplifier-bundle/tools/amplihack/hooks/ directory with a symlink
to .claude/tools/amplihack/hooks/, making .claude/ the single source of truth.

Changes:
- Convert amplifier-bundle/tools/amplihack/hooks/ from a directory to a
  symlink pointing to ../../../.claude/tools/amplihack/hooks/
- Move 10 files that existed only in amplifier-bundle/hooks/ to .claude/hooks/:
  dev_intent_router.py, templates/routing_prompt.txt, and 8 test files
- Update test_main_branch_protection.py to verify symlink structure instead
  of checking byte-identity of two separate copies
- Update docs/features/main-branch-protection.md to reflect symlink architecture
- Add outside-in tests (tests/outside_in/test_hooks_canonical_location.py)
  verifying the symlink structure from a user's perspective

The build system (build_hooks.py) already uses symlinks=True in shutil.copytree,
so the symlink is preserved correctly in wheel builds.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
rysweet added a commit that referenced this pull request Mar 8, 2026
…a symlink (#2881) (#2935)

* fix: make .claude/tools/amplihack/hooks/ canonical, amplifier-bundle a symlink (#2881)

Replace amplifier-bundle/tools/amplihack/hooks/ directory with a symlink
to .claude/tools/amplihack/hooks/, making .claude/ the single source of truth.

Changes:
- Convert amplifier-bundle/tools/amplihack/hooks/ from a directory to a
  symlink pointing to ../../../.claude/tools/amplihack/hooks/
- Move 10 files that existed only in amplifier-bundle/hooks/ to .claude/hooks/:
  dev_intent_router.py, templates/routing_prompt.txt, and 8 test files
- Update test_main_branch_protection.py to verify symlink structure instead
  of checking byte-identity of two separate copies
- Update docs/features/main-branch-protection.md to reflect symlink architecture
- Add outside-in tests (tests/outside_in/test_hooks_canonical_location.py)
  verifying the symlink structure from a user's perspective

The build system (build_hooks.py) already uses symlinks=True in shutil.copytree,
so the symlink is preserved correctly in wheel builds.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* [skip ci] chore: Auto-bump patch version

* docs: note canonical location in hooks README

Add note that .claude/tools/amplihack/hooks/ is the canonical source
and amplifier-bundle/tools/amplihack/hooks/ is a symlink to it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Ubuntu <azureuser@deva.ftnmxvem3frujn3lepas045p5c.xx.internal.cloudapp.net>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Quality Audit: 132 findings in non-fleet files (power_steering_checker, cli, stop, compaction_validator)

1 participant