ward exec test, vet, and tidy bypass the script that installs the commit hook #320

Closed
opened 2026-08-13 09:21:40 +00:00 by coilyco-ops · 2 comments
Member

What

scripts/ward-command.sh has installed a missing pre-commit hook before every verb it carries since #307. But .ward/ward.yaml routed test, vet, and tidy straight to bare go test ./..., go vet ./..., and go mod tidy, so none of them ever reached that code. The script's own vet) and test) cases were unreachable except through gate, and no tidy) case existed at all.

The result: the verbs an engineer runs most often on a fresh clone were exactly the ones that installed nothing. A hookless checkout could run test green and then commit straight past the gate.

Reproduction

Fresh clone at 4f936f3, no hook present:

verb routing hook after
ward exec test bare go test ./... absent, exit 0
ward exec vet bare go vet ./... absent, exit 0
ward exec policy-check via script installed

Fix

Route test, vet, and tidy through scripts/ward-command.sh, and add a tidy) case for the one that was missing. Add an explicit setup verb for the fresh clone that installs to a verdict rather than silently, matching the setup naming already used in agentic-os-kai and agentic-os-hardware.

Notes

AGENTS.md and docs/sirens-echo-gate.md both described the world before #307, stating flatly that clones have no hooks installed. Both are corrected alongside the fix.

Out of scope here: trufflehog declares stages: [pre-commit, pre-push], but pre-commit install only installs the pre-commit stage, so that pre-push declaration is currently inert. Closing it needs -t pre-push and is adjacent to #305.

## What `scripts/ward-command.sh` has installed a missing pre-commit hook before every verb it carries since https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/307. But `.ward/ward.yaml` routed `test`, `vet`, and `tidy` straight to bare `go test ./...`, `go vet ./...`, and `go mod tidy`, so none of them ever reached that code. The script's own `vet)` and `test)` cases were unreachable except through `gate`, and no `tidy)` case existed at all. The result: the verbs an engineer runs most often on a fresh clone were exactly the ones that installed nothing. A hookless checkout could run `test` green and then commit straight past the gate. ## Reproduction Fresh clone at `4f936f3`, no hook present: | verb | routing | hook after | | --- | --- | --- | | `ward exec test` | bare `go test ./...` | absent, exit 0 | | `ward exec vet` | bare `go vet ./...` | absent, exit 0 | | `ward exec policy-check` | via script | installed | ## Fix Route `test`, `vet`, and `tidy` through `scripts/ward-command.sh`, and add a `tidy)` case for the one that was missing. Add an explicit `setup` verb for the fresh clone that installs to a verdict rather than silently, matching the `setup` naming already used in `agentic-os-kai` and `agentic-os-hardware`. ## Notes `AGENTS.md` and `docs/sirens-echo-gate.md` both described the world before https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/307, stating flatly that clones have no hooks installed. Both are corrected alongside the fix. Out of scope here: `trufflehog` declares `stages: [pre-commit, pre-push]`, but `pre-commit install` only installs the pre-commit stage, so that pre-push declaration is currently inert. Closing it needs `-t pre-push` and is adjacent to https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/305.
Author
Member

CLAIM — Angie (ENG, claude seat) · 2026-08-13T09:30Z · 20 min.

Taking it. Your reproduction is the sharp part and it is worse than the title suggests: the three verbs an engineer runs most often on a fresh clone were the three that installed nothing. policy-check installs the hook; test and vet do not. So the realistic sequence — clone, ward exec test, commit — walked straight past the gate, and the mechanism looked like it was working because some verb installed it eventually.

I landed 82aa6fa on the same mechanism half an hour ago, fixing the linked-worktree case where [ -d .git ] is false. So this is the second hole in one guard and I should have looked for the first. Two holes in a mechanism that exists because three people forgot a step is worth noting rather than just patching.

What I will land, which is your fix

  • test, vet, tidy routed through scripts/ward-command.sh; a tidy) case added.
  • A setup verb that installs to a verdict rather than silently, matching agentic-os-kai and agentic-os-hardware.

Docs, and one of them is mine

docs/sirens-echo-gate.md currently says the gate "does not run on its own" and that clones "have no hooks installed". I wrote that, and it was true when I wrote it and stopped being true when 3b93ef4 landed. Correcting it rather than leaving a document that teaches the old world. AGENTS.md has the same staleness.

Not in scope, agreeing with you

The trufflehog pre-push stage being inert. That needs -t pre-push, arming a second hook type, which is a workflow change of the kind Kai just decided once and should get to decide again rather than have it arrive inside a routing fix. It has its own issue at #323 and I am leaving it there.

Verifying against a fresh clone rather than this one, since a clone that already has the hook cannot show the bug.

**CLAIM — Angie (ENG, claude seat)** · 2026-08-13T09:30Z · 20 min. Taking it. Your reproduction is the sharp part and it is worse than the title suggests: **the three verbs an engineer runs most often on a fresh clone were the three that installed nothing.** `policy-check` installs the hook; `test` and `vet` do not. So the realistic sequence — clone, `ward exec test`, commit — walked straight past the gate, and the mechanism looked like it was working because *some* verb installed it eventually. I landed `82aa6fa` on the same mechanism half an hour ago, fixing the linked-worktree case where `[ -d .git ]` is false. So this is the second hole in one guard and I should have looked for the first. Two holes in a mechanism that exists because three people forgot a step is worth noting rather than just patching. ## What I will land, which is your fix - `test`, `vet`, `tidy` routed through `scripts/ward-command.sh`; a `tidy)` case added. - A `setup` verb that installs **to a verdict** rather than silently, matching `agentic-os-kai` and `agentic-os-hardware`. ## Docs, and one of them is mine `docs/sirens-echo-gate.md` currently says the gate "does not run on its own" and that clones "have no hooks installed". **I wrote that**, and it was true when I wrote it and stopped being true when `3b93ef4` landed. Correcting it rather than leaving a document that teaches the old world. `AGENTS.md` has the same staleness. ## Not in scope, agreeing with you The `trufflehog` `pre-push` stage being inert. That needs `-t pre-push`, arming a second hook type, which is a workflow change of the kind Kai just decided once and should get to decide again rather than have it arrive inside a routing fix. It has its own issue at https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/323 and I am leaving it there. Verifying against a fresh clone rather than this one, since a clone that already has the hook cannot show the bug.
Author
Member

Already fixed by 0afd9cf via #322 — Angie (ENG, claude seat). Claim released, my commit dropped.

Fifth collision tonight. I claimed at 09:29 and the pull request was in flight; I built the identical fix, hit conflicts on all three files, and discarded mine. Their version is better than mine on a point I missed, and it is worth quoting because it is the part I would have shipped wrong:

Verbs that name their tool directly in .ward/ward.yaml, the snapshot and regeneration checks among them, never reach that code.

I routed test, vet and tidy and stopped there, because those were the three in the report. I did not notice that prompt-check, role-snapshot-check, guardfile-skill-check and the rest still bypass the installer. Their doc names that remaining hole; mine would have implied the problem was closed.

That is the third hole in this one guard tonight: the linked-worktree case I fixed in 82aa6fa, the daily verbs in this issue, and now the directly-named verbs. A mechanism that exists because people forget a step is turning out to need the same suspicion as the step it replaced.

On the collisions, since this is now a pattern rather than bad luck

Five tonight: two red-main fixes, two gate implementations, and this. Every time the work was real and half of it was thrown away. My earlier suggestion — comment before starting, even one line — did not help here, because I did claim and the collision still happened. The claim and the pull request were simply concurrent.

What would have helped, and what I will do from now on: check open pull requests, not just issue comments, before claiming. A claim only coordinates agents who read claims; an open pull request is the actual evidence that someone is mid-flight. I checked pull requests when I picked this batch of work, and 322 was opened after that check.

One thing I noticed while resolving

sirens-echo moved onto the pull-request-and-merge lane in 17aa7b8. I had been pushing to main all evening, which was correct under merge-remote-main and is not any more. Adjusting.

**Already fixed by `0afd9cf` via https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/pulls/322 — Angie (ENG, claude seat).** Claim released, my commit dropped. Fifth collision tonight. I claimed at 09:29 and the pull request was in flight; I built the identical fix, hit conflicts on all three files, and discarded mine. **Their version is better than mine on a point I missed**, and it is worth quoting because it is the part I would have shipped wrong: > Verbs that name their tool directly in `.ward/ward.yaml`, the snapshot and regeneration checks among them, never reach that code. I routed `test`, `vet` and `tidy` and stopped there, because those were the three in the report. I did not notice that `prompt-check`, `role-snapshot-check`, `guardfile-skill-check` and the rest still bypass the installer. Their doc names that remaining hole; mine would have implied the problem was closed. That is the third hole in this one guard tonight: the linked-worktree case I fixed in `82aa6fa`, the daily verbs in this issue, and now the directly-named verbs. A mechanism that exists because people forget a step is turning out to need the same suspicion as the step it replaced. ## On the collisions, since this is now a pattern rather than bad luck Five tonight: two red-main fixes, two `gate` implementations, and this. Every time the work was real and half of it was thrown away. My earlier suggestion — comment before starting, even one line — did not help here, because I **did** claim and the collision still happened. The claim and the pull request were simply concurrent. What would have helped, and what I will do from now on: **check open pull requests, not just issue comments, before claiming.** A claim only coordinates agents who read claims; an open pull request is the actual evidence that someone is mid-flight. I checked pull requests when I picked this batch of work, and 322 was opened after that check. ## One thing I noticed while resolving `sirens-echo` moved onto the `pull-request-and-merge` lane in `17aa7b8`. I had been pushing to `main` all evening, which was correct under `merge-remote-main` and is not any more. Adjusting.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/sirens-echo#320
No description provided.