Project-Template/docs/architecture/scripts
null 26a2bb5e56 feat(guards): gate the claim of being finished, not only the artifact
Every guard in this template fires on an artifact -- `githooks/pre-commit` on a
commit, `audit-gate.mjs` and `preflight.sh` on a release, `verify.sh` when
somebody runs it. `GUARDS.md` §6 is the rule they follow: guards belong before
the artifact exists.

An agent that says "done" and does not commit produces no artifact and trips
none of them. That gap already has two rules pointing at it -- `WORK_CYCLE.md`
opens with *"Done" is not a close*, and the tracker convention refuses a close
under fifteen characters of evidence -- and a rule is a thing a reader can skip.
This is the same rule with an exit code.

`scripts/verify-before-done.sh` is a Claude Code `TaskCompleted` hook. Verified
against Claude Code 2.1.251: the event exists and the binary carries the string
`TaskCompleted hook prevented continuation`.

WIRED TO `verify.sh`, NOT TO THE TEST COMMAND. `npm test` in a repo with no
tests exits 0, so a gate built on it reports green having verified nothing --
`GUARDS.md` §4 and §8's whole subject. `verify.sh` already distinguishes the
three answers, and this treats exit 2 (nothing was verified) as a failure with
its own message rather than a pass. A repository with no checks yet fails this
gate loudly, which is the intended answer.

IT EXITS 2 TO BLOCK, AND THAT IS NOT THE USUAL CONVENTION. Claude Code reads a
`1` from a hook as "the hook broke" and continues, so a gate written the
ordinary way fails OPEN and lets through exactly what it was installed to catch,
looking identical from the outside. `docs/TOOLS.md` now says this beside the
exit-2-is-never-a-pass rule it inverts.

THE LIMITATION IS IN THE HEADER IN CAPITALS, because it decides whether this is
worth installing: it gates Claude Code and nothing else. A Codex session or a
human in the same checkout writes past it. It is a second layer and never the
layer -- `.githooks/pre-commit` is what git runs whoever is driving, and if a
project's real suite is not wired into that hook, wiring it there is worth more
than installing this.

Proved rather than assumed, all four outcomes, per §1: no `verify.sh` -> 2 (fails
closed); pass -> 0 with empty stderr; fail -> 2 naming the code; verified-nothing
-> 2 with the distinct message.

Docs in the same commit, per the triggers `doc-triggers.py` reported:
`architecture/README.md` gains the row its own "Adding one" rule requires,
`TOOLS.md` gains the paragraph under "Which ones can stop you", and
`DOC_TRUST_MAP.md` gains the question it now answers. `doc-claims.sh` re-run:
51 claimed paths across the three, all present.

Prompted by an XDA piece on Claude Code shipping unverified work. The idea is
theirs; the exit-2 contract, the `verify.sh` wiring and the Codex caveat are
what it needed to be true here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-29 08:42:00 -05:00
..
audit-gate.mjs chore(repo): put the template under version control 2026-08-17 22:44:26 -05:00
backup.sh chore(repo): put the template under version control 2026-08-17 22:44:26 -05:00
check-env.sh chore(repo): put the template under version control 2026-08-17 22:44:26 -05:00
commit-mine.sh chore(repo): put the template under version control 2026-08-17 22:44:26 -05:00
controls.sh feat(ops): controls.sh, which controls this project actually has 2026-08-17 23:11:52 -05:00
dead-code.py chore(repo): put the template under version control 2026-08-17 22:44:26 -05:00
deploy.py chore(repo): put the template under version control 2026-08-17 22:44:26 -05:00
dev.sh chore(repo): put the template under version control 2026-08-17 22:44:26 -05:00
doc-claims.sh fix(guards): a bare filename is a weaker claim than a path 2026-08-17 23:45:02 -05:00
doc-triggers.py fix(tools): doc-triggers could not see the documents at the repository root 2026-08-18 00:12:49 -05:00
duplication.py chore(repo): put the template under version control 2026-08-17 22:44:26 -05:00
forgejo-issue.py docs(tracker): an issue that produces a data shape names its surface 2026-08-22 14:05:11 -05:00
healthcheck.sh docs(template): the owner is _null 2026-08-17 22:47:56 -05:00
migrate.sh chore(repo): put the template under version control 2026-08-17 22:44:26 -05:00
preflight.sh feat(security): preflight.sh distinguishes present from in force 2026-08-17 23:30:37 -05:00
prove-guard.sh fix(guards): prove-guard rejected correct guards, and refused with the wrong code 2026-08-17 23:39:17 -05:00
release-notes.mjs chore(repo): put the template under version control 2026-08-17 22:44:26 -05:00
release.sh chore(repo): put the template under version control 2026-08-17 22:44:26 -05:00
restore-check.sh feat(ops): restore-check.sh, the other half of backup.sh 2026-08-17 23:07:36 -05:00
scaffold.sh fix(scaffold): new projects were missing two documents they reference 2026-08-17 23:34:12 -05:00
secrets.sh fix(secrets): the scanner printed the credential it found 2026-08-17 23:08:57 -05:00
status.sh chore(repo): put the template under version control 2026-08-17 22:44:26 -05:00
verify-before-done.sh feat(guards): gate the claim of being finished, not only the artifact 2026-08-29 08:42:00 -05:00
verify.sh chore(repo): put the template under version control 2026-08-17 22:44:26 -05:00