How a scratch file turned 171 hooks into 150
count-hooks.sh redirected grep's stderr into a file from a bare
mktemp. Deny that one write and the count silently shrinks. Toggle
the two conditions to walk the chain.
Why rc=1 is the trap
The function must treat "no match" as zero, because zero agent-scoped hooks is a legitimate state since #3461 removed all 45 of them:
if [ "$rc" -ge 2 ]; then # real error, fail loudly
...
fi
# rc of 0 or 1 falls through and counts
A failed redirect also produces rc=1. So the one code path deliberately kept quiet is the exact path a broken scratch file lands on. The guard was correct; the thing it depended on was not guarded.
Verification note
The obvious repro reports success and hides the bug:
$ TMPDIR=/unwritable mktemp
/var/folders/7v/.../T/tmp.iGOVlVqii5 <-- TMPDIR ignored
macOS mktemp with no template ignores TMPDIR. Driving
this needs a real denial of /var/folders or a PATH shim, which is
what the regression test uses.
Measured
| script | mktemp | output |
|---|---|---|
| origin/main | healthy | GLOBAL=150 AGENT=0 SKILL=21 TOTAL=171 |
| origin/main | denied | GLOBAL=150 AGENT=0 SKILL=0 TOTAL=150 |
| fixed | denied | GLOBAL=150 AGENT=0 SKILL=21 TOTAL=171 |
tests/ci/test-count-hooks-temp-failure.sh asserts the counts are
identical with and without a writable temp dir. Issue #3564.