trufflehog's pre-push stage is inert, and arming it naively would run the whole suite on every push #323

Closed
opened 2026-08-13 09:27:44 +00:00 by coilyco-ops · 1 comment
Member

What

The local trufflehog hook declares:

stages: [pre-commit, pre-push]

That declaration does nothing today. pre-commit install only writes .git/hooks/pre-commit, so no pre-push hook exists in any checkout and the second stage never fires.

Why the obvious fix is wrong

Adding -t pre-push alone is not enough. .pre-commit-config.yaml sets no top-level default_stages, and under pre-commit 4.6.0 a hook with no explicit stages key runs at every stage. Measured on the current config:

pre-commit run --hook-stage pre-push --all-files

21 hooks fire, including go mod tidy, gofmt, go vet, the rendered prompt snapshots, actionlint, and shellcheck. Only one of them asked for pre-push.

So the naive change buys a secret scan on push and silently pays for a near-complete second suite on every push. The explicit stages key on trufflehog reads as an author who expected that key to be doing the selecting. It is not.

Fix

Set default_stages: [pre-commit] at the top of .pre-commit-config.yaml, so the stage list means what it looks like it means, then install both stages. After that only the hook that opted in runs at push time.

The key goes above the repos: block, outside the region managed by apply-agentic-os-hooks.py, so a hook rollout will not clobber it.

Notes

Split out of #322, which routed the daily verbs through the installer but deliberately left stage selection alone. Adjacent to #305.

## What The local `trufflehog` hook declares: ```yaml stages: [pre-commit, pre-push] ``` That declaration does nothing today. `pre-commit install` only writes `.git/hooks/pre-commit`, so no `pre-push` hook exists in any checkout and the second stage never fires. ## Why the obvious fix is wrong Adding `-t pre-push` alone is not enough. `.pre-commit-config.yaml` sets no top-level `default_stages`, and under pre-commit 4.6.0 a hook with no explicit `stages` key runs at every stage. Measured on the current config: ``` pre-commit run --hook-stage pre-push --all-files ``` 21 hooks fire, including `go mod tidy`, `gofmt`, `go vet`, the rendered prompt snapshots, actionlint, and shellcheck. Only one of them asked for pre-push. So the naive change buys a secret scan on push and silently pays for a near-complete second suite on every push. The explicit `stages` key on `trufflehog` reads as an author who expected that key to be doing the selecting. It is not. ## Fix Set `default_stages: [pre-commit]` at the top of `.pre-commit-config.yaml`, so the stage list means what it looks like it means, then install both stages. After that only the hook that opted in runs at push time. The key goes above the `repos:` block, outside the region managed by `apply-agentic-os-hooks.py`, so a hook rollout will not clobber it. ## Notes Split out of https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/pulls/322, which routed the daily verbs through the installer but deliberately left stage selection alone. Adjacent to https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/305.
Author
Member

Fixed and merged to main in 3cf1c59 via #322. Closing by hand: the merge auto-closed #320 from the first commit but did not pick up the closes keyword in the second.

default_stages: [pre-commit] now sits above the repos: block. Measured effect on the pre-push stage:

hooks firing
before 21
after 9, every one naming pre-push in its own definition

check-merge-conflict and mixed-line-ending, which declare no stages, are correctly absent from pre-push, which confirms the default is doing the selecting rather than something else.

Both stages are installed by ward exec setup and by the silent guard, which now fires when either hook is missing rather than only pre-commit, so a half-installed checkout repairs itself. The push of the second commit exercised the new hook live: 9 hooks, all green. Main CI is green across test, image-build, publish-echo-image, and publish-observed.

Fixed and merged to `main` in `3cf1c59` via https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/pulls/322. Closing by hand: the merge auto-closed https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/320 from the first commit but did not pick up the `closes` keyword in the second. `default_stages: [pre-commit]` now sits above the `repos:` block. Measured effect on the pre-push stage: | | hooks firing | | --- | --- | | before | 21 | | after | 9, every one naming `pre-push` in its own definition | `check-merge-conflict` and `mixed-line-ending`, which declare no stages, are correctly absent from pre-push, which confirms the default is doing the selecting rather than something else. Both stages are installed by `ward exec setup` and by the silent guard, which now fires when either hook is missing rather than only `pre-commit`, so a half-installed checkout repairs itself. The push of the second commit exercised the new hook live: 9 hooks, all green. Main CI is green across `test`, `image-build`, `publish-echo-image`, and `publish-observed`.
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#323
No description provided.