fix(gate): install the hooks on setup and the daily verbs, and arm pre-push #322

Merged
coilysiren merged 1 commit from fix/ward-hook-install-on-daily-verbs into main 2026-08-13 09:30:17 +00:00
Member

Closes #320
Closes #323

Two commits. The first arms the hook on the verbs people actually run. The second makes the pre-push stage real.

1. The installer was wired to the wrong verbs

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 their bare go commands, 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 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.

Measured on a fresh clone at 4f936f3, before any edit:

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, 3.5s

Fixed by routing test, vet, and tidy through the script, adding the tidy) case that never existed, and adding a setup verb that installs to a verdict rather than silently. Named setup to match agentic-os-kai and agentic-os-hardware.

2. The pre-push stage was inert, and the obvious fix was a trap

trufflehog has declared stages: [pre-commit, pre-push] for as long as it has existed here. That second stage never fired, because pre-commit install writes only the pre-commit hook.

Adding -t pre-push alone would have been wrong. The config set no default_stages, so under pre-commit 4.6.0 every hook naming no stage ran at every stage:

hooks firing at pre-push
before 21, including go mod tidy, gofmt, go vet, prompt snapshots, actionlint, shellcheck
after default_stages: [pre-commit] 9, every one of which names pre-push in its own definition

So the naive change would have bought a secret scan and silently paid for a near-complete second suite on every push.

default_stages goes above the repos: block, outside the region apply-agentic-os-hooks.py manages, so a hook rollout will not clobber it. The silent guard also widened to fire when either hook is missing rather than only pre-commit, so a half-installed checkout repairs itself.

Verification

Driven through the real ward exec interface on a genuinely fresh clone, not through the script:

  • hook absent, ward exec test exit 0, hook present afterward. Same for vet and tidy
  • ward exec setup installs both stages from hookless, and re-runs clean over existing hooks
  • deleting only .git/hooks/pre-push is repaired by the next routed verb
  • setup under PATH=/usr/bin:/bin exits 1 with its message
  • go.mod and go.sum untouched by the routed tidy
  • check-merge-conflict and mixed-line-ending, which declare no stages, are correctly absent from pre-push
  • full gate passes all six steps
  • the push of the second commit ran the new pre-push hook live: 9 hooks, all green

Reviewer note

The second commit changes when trufflehog runs, which is the part worth a second opinion. Everything else only changes when a hook gets installed.

Closes https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/320 Closes https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/323 Two commits. The first arms the hook on the verbs people actually run. The second makes the pre-push stage real. ## 1. The installer was wired to the wrong verbs `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 their bare `go` commands, 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 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. Measured on a fresh clone at `4f936f3`, before any edit: | 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, 3.5s | Fixed by routing `test`, `vet`, and `tidy` through the script, adding the `tidy)` case that never existed, and adding a `setup` verb that installs to a verdict rather than silently. Named `setup` to match `agentic-os-kai` and `agentic-os-hardware`. ## 2. The pre-push stage was inert, and the obvious fix was a trap `trufflehog` has declared `stages: [pre-commit, pre-push]` for as long as it has existed here. That second stage never fired, because `pre-commit install` writes only the pre-commit hook. Adding `-t pre-push` alone would have been wrong. The config set no `default_stages`, so under pre-commit 4.6.0 every hook naming no stage ran at *every* stage: | | hooks firing at pre-push | | --- | --- | | before | 21, including `go mod tidy`, `gofmt`, `go vet`, prompt snapshots, actionlint, shellcheck | | after `default_stages: [pre-commit]` | 9, every one of which names `pre-push` in its own definition | So the naive change would have bought a secret scan and silently paid for a near-complete second suite on every push. `default_stages` goes above the `repos:` block, outside the region `apply-agentic-os-hooks.py` manages, so a hook rollout will not clobber it. The silent guard also widened to fire when *either* hook is missing rather than only `pre-commit`, so a half-installed checkout repairs itself. ## Verification Driven through the real `ward exec` interface on a genuinely fresh clone, not through the script: - hook absent, `ward exec test` exit 0, hook present afterward. Same for `vet` and `tidy` - `ward exec setup` installs both stages from hookless, and re-runs clean over existing hooks - deleting only `.git/hooks/pre-push` is repaired by the next routed verb - `setup` under `PATH=/usr/bin:/bin` exits 1 with its message - `go.mod` and `go.sum` untouched by the routed `tidy` - `check-merge-conflict` and `mixed-line-ending`, which declare no stages, are correctly absent from pre-push - full `gate` passes all six steps - **the push of the second commit ran the new pre-push hook live**: 9 hooks, all green ## Reviewer note The second commit changes when `trufflehog` runs, which is the part worth a second opinion. Everything else only changes when a hook gets installed.
fix(gate): install the commit hook on setup and on the daily verbs
All checks were successful
ci / test (pull_request) Successful in 35s
ci / publish-echo-image (pull_request) Has been skipped
ci / publish-observed (pull_request) Has been skipped
ci / image-build (pull_request) Successful in 17s
0afd9cf1b9
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 their bare go commands, so the verbs an engineer actually runs on
a fresh clone never reached that code. The script's own vet) and test) cases
were unreachable except through gate, and no tidy) case existed at all. A
hookless checkout could run test green and commit past the gate.

Route test, vet, and tidy through the script, add the missing tidy) case, and
add an explicit setup verb for the fresh clone that installs to a verdict
instead of silently. setup rather than init, matching agentic-os-kai and
agentic-os-hardware.

AGENTS.md and docs/sirens-echo-gate.md both still described the world before
#307 and are corrected here.

closes #320

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
coilyco-ops changed title from fix(gate): install the commit hook on setup and on the daily verbs to fix(gate): install the hooks on setup and the daily verbs, and arm pre-push 2026-08-13 09:32:33 +00:00
Sign in to join this conversation.
No reviewers
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!322
No description provided.