fix: make .claude/ hooks canonical, replace amplifier-bundle/ copy with symlink#2881
fix: make .claude/ hooks canonical, replace amplifier-bundle/ copy with symlink#2881
Conversation
…-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>
|
🤖 Auto-fixed version bump The version in If you need a minor or major version bump instead, please update |
Repo Guardian - Passed✅ All files in this PR are legitimate repository content. This PR refactors hook file organization by:
No ephemeral content, temporary scripts, or point-in-time documents detected.
|
Triage Report - HIGH RISKRisk Level: HIGH Concerns
Required Validations✅ Verify symlink works on all platforms in CI Next Steps
Recommendation: CAREFUL_REVIEW - do not fast-track despite being a bug fix.
|
|
…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>
…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>
Summary
Fixes #2845
amplifier-bundle/tools/amplihack/hooks/directory with a symlink to../../../.claude/tools/amplihack/hooks(the canonical source of truth)amplifier-bundle/to.claude/:dev_intent_router.py,routing_prompt.txt,test_dev_intent_router.py,test_pre_tool_use_cwd_protection.pyscripts/check_drift.py(CI will fail if symlink is broken or replaced with a directory)check-driftandverify-hooks-symlinkProblem
Both
.claude/tools/amplihack/hooks/andamplifier-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 fromamplifier-bundle/eliminates duplication permanently. The symlink works correctly withbuild_hooks.pybecauseshutil.copytree(symlinks=True)preserves symlinks, and both.claude/andamplifier-bundle/are copied tosrc/amplihack/during wheel build where the relative symlink resolves correctly.Test plan
ls amplifier-bundle/tools/amplihack/hooks/lists canonical filesuv build --wheelsucceeds and both hook locations appear in the wheel with identical content (126 files each)python scripts/check_drift.pyreports "Hooks symlink OK"make verify-hooks-symlinkreports "OK: hooks symlink is correct".claude/settings.jsonexist and are accessible via both pathsGenerated with Claude Code