diff --git a/docs/TOOLS.md b/docs/TOOLS.md new file mode 100644 index 0000000..93ff2ed --- /dev/null +++ b/docs/TOOLS.md @@ -0,0 +1,101 @@ +# Tools — where the scripts are, and which ones can stop you + +``` +Status: Current +Owner: _null +Last reviewed: 2026-08-18 +Governs: scripts/**, .githooks/** +Review trigger: Any script added to, removed from or repurposed in scripts/; any + change to which of them gates a commit or a release +``` + +> A signpost, deliberately. Every project that adopts this template has a +> `docs/TOOLS.md`, so "read `docs/TOOLS.md` first" is an instruction that works +> without knowing anything about the project — which is the whole reason this +> file exists at a fixed path. + +## The list is not here + +**[`architecture/README.md`](architecture/README.md)** holds the table of what +this project has and what each script is. That is the one copy. + +A second table here would be two records of one fact, and the other one would +never hear that a script was renamed. So this file answers the questions that +table does not, and points at it for everything else. + +## Period has seven of them, and that is deliberate + +The template this repository adopted ships around twenty scripts. Period took +six of them and wrote one of its own. `scaffold.sh` copies none of them on purpose — *"an unconfigured +`release.sh` landing in every new repository is a loaded gun, not a head +start"* — so each one is taken having been read and configured. + +**The ones not taken were not forgotten.** `release.sh`, `deploy.py`, +`backup.sh`, `restore-check.sh`, `preflight.sh`, `healthcheck.sh`, `migrate.sh`, +`status.sh`, `dev.sh`, `audit-gate.mjs`, `release-notes.mjs`, `duplication.py` +and `dead-code.py` all assume a deployed Node or Postgres service with an npm +dependency tree and a URL. Period is an Android app that ships through Google +Play and has no server at all. A release here is an AAB and a Play Console +submission, so [`security/SECURITY_CHECKLIST.md`](security/SECURITY_CHECKLIST.md) +carries what `release.sh` would have gated. + +Two were deferred rather than declined: + +- **`verify.sh`** — worth having once there is a real check suite to aggregate. + Today `./gradlew check` is the whole answer and wrapping it would add a layer + that could only be wrong. +- **`check-env.sh`** — its SPEC ships empty and exits `2` until it has entries, + and Period has no environment variables yet. It gets taken with the first + signing or Play credential, which is exactly the moment it becomes worth + running. + +**The seventh is `schema-guard.sh`, and it is this project's own.** It clears +the bar in *Adding one* below the hard way: it exists because the check it +replaces was proved green over exactly the failure it claimed to catch. Its +header carries that proof. + +If this project later grows a script the template already has, take that one +rather than writing a new one — the arguments in its header are the part that +took the longest. + +## Which ones can stop you + +Not in a table, because the honest answer lives in each script's own header and +would go stale here. The rule that matters: + +**Exit code `2` is never a pass.** These scripts distinguish "the check ran and +found nothing" from "the check did not run", because those look identical from +the outside and only one of them is evidence. A hook or a CI step that treats a +`2` as success has quietly turned the check off. Each script states its codes at +the top; read them there. + +The hooks are the other place work gets stopped: +[`architecture/githooks/README.md`](architecture/githooks/README.md) has the one +install command and the table of what each hook runs. Note that **`post-commit` +pushes**, and that `pre-commit` here runs Gradle rather than the template's +TypeScript typecheck. + +## Where to start in a fresh clone + +1. `git config core.hooksPath .githooks` — per clone, every time, and an + uninstalled hook fails silently. +2. `bash scripts/secrets.sh --tracked` — the one-time audit of what is already + committed. The staged-diff mode is for the hook; this mode is for the day you + clone. +3. `./gradlew test` — the prediction acceptance tests run on the JVM, so this + needs no emulator and should be fast. +4. [`architecture/GUARDS.md`](architecture/GUARDS.md) — how to write a check that + can actually fail, before you write one. `scripts/prove-guard.sh` performs its + first rule. + +## Adding one + +Put it in `scripts/`, give it a header saying what it does and **which incident +motivated it**, state its exit codes, and add a row to +[`architecture/README.md`](architecture/README.md)'s table — this file's +`Review trigger` fires on exactly that. + +The bar, from the scripts that are already here: **done by hand three times, or +once with a consequence.** A script written before either of those has no +failure to describe in its header, which is the part that stops the next person +deleting it.