So the redirect targets a path under a regular file and make hooks fails outright there.
Why it matters here
All implementation and review work on this repo happens in throwaway linked worktrees — that is a standing rule, since concurrent sessions collided in the shared checkout once already. So make hooks is broken in exactly the environment every agent actually works in. The implementer of PR #128 hit this and had to commit with --no-verify, running make check explicitly instead.
Note the hook is not entirely absent from worktrees: git resolves hooks via the common git dir, so a hook installed once from the main checkout does run in linked worktrees. The defect is specifically that install-precommit cannot be run from one. That distinction matters — it means the exposure is "agents can't install the hook", not necessarily "no agent has ever had one".
Definition of done
script/install-precommit works from the main checkout and from a linked worktree. git rev-parse --git-path hooks resolves correctly in both and is the idiomatic fix; create the directory if absent.
Verify by running it from both, and confirm the installed hook actually fires on a commit in each. A path that merely exists is not the test — make a throwaway commit and watch the hook run.
script/install-precommit stays POSIX sh (#!/bin/sh, set -eu, no bashisms); sh -n clean; keeps the $(cd "$(dirname "$0")/.." && pwd -P) idiom.
Behaviour is unchanged where it already worked — do not silently relocate the hook for existing checkouts.
make check green; TODO.md updated in the same commit.
Commit title ends with (closes #N).
Constraints
Do not modify .golangci.yml (sha256 021cc83f4e6fc7c31b95b34b846723dfcf20b66b7baeea1dc40406e643346bcb) or the golangci-lint pin.
DNS is never mocked in this repository; nothing here touches test behaviour.
Lint runs may be void (#121): void if the output says parallel golangci-lint is running, or names any path starting with ../, or any absolute path outside your worktree.
Coordination
Touches script/install-precommit only — no overlap with #115/#122 (script/cibuild), #117 (script/bootstrap), #119 (script/fmt, script/fmt-check), or #121/#128 (script/lint).
script/install-precommit is byte-identical across repos, so this belongs upstream in the shared template as well; it is already known there as one of the Scripts to Rule Them All defects.
`script/install-precommit` hardcodes the hooks path:
```sh
hook=".git/hooks/pre-commit"
printf '#!/bin/sh\nset -e\nscript/precommit\n' > "$hook"
```
In a **linked worktree** `.git` is a file, not a directory. Verified in this repo:
```
$ cat .claude/worktrees/agent-.../.git
gitdir: /srv/code/dnswatcher/.git/worktrees/agent-...
```
So the redirect targets a path under a regular file and `make hooks` fails outright there.
## Why it matters here
All implementation and review work on this repo happens in throwaway linked worktrees — that is a standing rule, since concurrent sessions collided in the shared checkout once already. So `make hooks` is broken in exactly the environment every agent actually works in. The implementer of [PR #128](https://git.eeqj.de/sneak/dnswatcher/pulls/128) hit this and had to commit with `--no-verify`, running `make check` explicitly instead.
Note the hook is not entirely absent from worktrees: git resolves hooks via the **common** git dir, so a hook installed once from the main checkout does run in linked worktrees. The defect is specifically that `install-precommit` cannot be run *from* one. That distinction matters — it means the exposure is "agents can't install the hook", not necessarily "no agent has ever had one".
## Definition of done
1. `script/install-precommit` works from the main checkout **and** from a linked worktree. `git rev-parse --git-path hooks` resolves correctly in both and is the idiomatic fix; create the directory if absent.
2. Verify by running it from both, and confirm the installed hook actually fires on a commit in each. A path that merely *exists* is not the test — make a throwaway commit and watch the hook run.
3. `script/install-precommit` stays POSIX `sh` (`#!/bin/sh`, `set -eu`, no bashisms); `sh -n` clean; keeps the `$(cd "$(dirname "$0")/.." && pwd -P)` idiom.
4. Behaviour is unchanged where it already worked — do not silently relocate the hook for existing checkouts.
5. `make check` green; `TODO.md` updated in the same commit.
Commit title ends with ` (closes #N)`.
## Constraints
- Do not modify `.golangci.yml` (sha256 `021cc83f4e6fc7c31b95b34b846723dfcf20b66b7baeea1dc40406e643346bcb`) or the golangci-lint pin.
- DNS is never mocked in this repository; nothing here touches test behaviour.
- Lint runs may be void (#121): void if the output says `parallel golangci-lint is running`, or names any path starting with `../`, or any absolute path outside your worktree.
## Coordination
Touches `script/install-precommit` only — no overlap with #115/#122 (`script/cibuild`), #117 (`script/bootstrap`), #119 (`script/fmt`, `script/fmt-check`), or #121/#128 (`script/lint`).
`script/install-precommit` is byte-identical across repos, so this belongs upstream in the shared template as well; it is already known there as one of the Scripts to Rule Them All defects.
clawbot
added this to the 1.0 milestone 2026-08-09 16:39:25 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
script/install-precommithardcodes the hooks path:In a linked worktree
.gitis a file, not a directory. Verified in this repo:So the redirect targets a path under a regular file and
make hooksfails outright there.Why it matters here
All implementation and review work on this repo happens in throwaway linked worktrees — that is a standing rule, since concurrent sessions collided in the shared checkout once already. So
make hooksis broken in exactly the environment every agent actually works in. The implementer of PR #128 hit this and had to commit with--no-verify, runningmake checkexplicitly instead.Note the hook is not entirely absent from worktrees: git resolves hooks via the common git dir, so a hook installed once from the main checkout does run in linked worktrees. The defect is specifically that
install-precommitcannot be run from one. That distinction matters — it means the exposure is "agents can't install the hook", not necessarily "no agent has ever had one".Definition of done
script/install-precommitworks from the main checkout and from a linked worktree.git rev-parse --git-path hooksresolves correctly in both and is the idiomatic fix; create the directory if absent.script/install-precommitstays POSIXsh(#!/bin/sh,set -eu, no bashisms);sh -nclean; keeps the$(cd "$(dirname "$0")/.." && pwd -P)idiom.make checkgreen;TODO.mdupdated in the same commit.Commit title ends with
(closes #N).Constraints
.golangci.yml(sha256021cc83f4e6fc7c31b95b34b846723dfcf20b66b7baeea1dc40406e643346bcb) or the golangci-lint pin.parallel golangci-lint is running, or names any path starting with../, or any absolute path outside your worktree.Coordination
Touches
script/install-precommitonly — no overlap with #115/#122 (script/cibuild), #117 (script/bootstrap), #119 (script/fmt,script/fmt-check), or #121/#128 (script/lint).script/install-precommitis byte-identical across repos, so this belongs upstream in the shared template as well; it is already known there as one of the Scripts to Rule Them All defects.