A worktree created with the documented `cp -al` recipe has no `.husky/_`: the
directory is gitignored, so it never exists in a fresh worktree, and
`core.hooksPath=.husky/_` then resolves to a path that is not there. git finds no
hook, commits, and prints nothing — the identity, lint and docs gates simply do
not run. That is how the 59 commits carrying a stale identity override slipped
past scripts/check/check-git-identity.sh between 2026-08-29 and 09-02: every one
of them was made in a codex-* worktree built that way.
Two changes:
- AGENTS.md documents the missing step in the worktree recipe and states the
failure mode plainly, since a silent gate is indistinguishable from a passing
one.
- scripts/dev/new-worktree.sh performs the whole protocol (canonical
.claude/worktrees/ path, base resolved from the active release when not given,
hard-linked node_modules, `.husky/_`) and then VERIFIES the hook is executable,
exiting non-zero when it is not.
The script copies `.husky/_` before node_modules on purpose: node_modules is a
~10 GB hard-link pass that can fail partway (this repo has already hit the ext4
link ceiling), and a failure there must not leave a worktree with no hooks — the
exact defect being fixed. A partial node_modules copy is reported with its log
and left recoverable by `npm install`, rather than aborting the worktree.
It also resolves the main checkout through `--git-common-dir` rather than
`--show-toplevel`, so running it from inside a worktree does not nest the new one
inside the current one.