The six things this repo runs by hand
What each one is for, when you run it, who else calls it, and what it must never do.
The table#
Two of these run in CI on every push, ci-citations.mjs and build-do-nots.mjs
(the latter as a regenerate-and-diff, .github/workflows/ci.yml:23-26), so a
docs commit that skips them fails there. dev-safe runs the guard for you.
The rest you run when the row says.
| Script | What it does | Run it when | It must never |
|---|---|---|---|
build-do-nots.mjs | Regenerates docs/DO-NOTS.md from every contract doc's Banned combinations section, the design canon, and the app-patterns recipes | after editing any of those three sources | be hand-edited around; the page has no opinions of its own |
check-citations.mjs | Walks every file.ext:N citation in the docs and reports BROKEN, OUT-OF-RANGE, and ROT-SUSPECT | after any canon or doc change; the docs-wide baseline lives in citations-baseline.json | be read as pass or fail on its own; ci-citations.mjs is the gate |
ci-citations.mjs | The citation ratchet CI runs: docs-wide BROKEN and OUT-OF-RANGE may not rise above citations-baseline.json, and the canon, contract docs and breakdowns must carry zero BROKEN | in CI on every push, and locally before a docs commit | be silenced by raising the baseline; lower it when the count drops |
dev-guard.mjs with dev-guard.md | Runs the playground dev server and recycles it when it is over a memory ceiling and idle | only when a human asks for it (npm run dev-safe) | be started by an agent on its own |
push-triad.sh | Pushes the three Versable repos in one approved run, refusing any repo it cannot account for | when the owner wants all three mains pushed at once | force anything; a repo that fails a check is skipped |
check-export-drift.mjs | Compares the kit barrel's exports against the published tarball of the same version and fails on a difference (two artifacts under one version string, the 0.2.0 lesson) | in publish-kit's drift job on pushes that publish nothing; locally with a read token | pass on an auth failure; no registry read means no verdict (exit 2) |
ship-kit.sh | Pushes main and watches the publish-kit workflow until the bumped kit version is on GitHub Packages; refuses when the version is already published, the tree under packages/ is dirty, or nothing is ahead of origin | after the bump commit, the owner's one release command (--check rehearses without pushing) | publish anything itself; the workflow does |
release-kit.sh | Bumps and publishes @versable-git/ui to GitHub Packages from a laptop | superseded; the publish-kit workflow publishes on push to main | be used to publish; a hand publish races the workflow |
Each one, from its own header#
build-do-nots.mjs#
node scripts/build-do-nots.mjs
Builds docs/DO-NOTS.md by re-reading every Banned combinations section, the
design canon, and the app-patterns recipes, "so the page can only go stale by
its sources going stale, never by a fourth copy nobody updated"
(build-do-nots.mjs:3-6). Every line on that page cites the source it came
from. Named in CLAUDE.md as the step after editing a Banned section, and in
CONTRIBUTING.md section 7.
check-citations.mjs#
node scripts/check-citations.mjs [--verbose] [docs-dir ...]
Walks every file.ext:N[-M] citation in the doc corpus and reports what a
compiler never will: BROKEN (file missing), OUT-OF-RANGE (line past EOF),
ROT-SUSPECT (file committed after its citing doc; --verbose lists them).
Exits 1 on the first two only. Ambiguous bare basenames are listed, never
guessed (check-citations.mjs:3-8). Deliberately not wired into CI: it is a
reading aid for the person changing a doc, and the canon rule is that every
canon change re-runs it (CLAUDE.md, "Canon edits stay one pen"). CONTRIBUTING.md
section 3 explains the scan set and why the number does not have to be zero.
dev-guard.mjs and dev-guard.md#
npm run dev-safe (in apps/playground)
The Next dev server's memory grows with every route visited and never lets go.
The guard owns npm run dev and recycles it only when it is both over a memory
ceiling and idle, so the recompile lands while you are away from the keyboard,
never mid-edit (dev-guard.md:16-19). Tuning knobs are env vars,
DEV_GUARD_MAX_MB, DEV_GUARD_MAX_PCT, DEV_GUARD_IDLE_CPU, DEV_GUARD_IDLE_N,
DEV_GUARD_MIN_UP, DEV_GUARD_INTERVAL, all documented in dev-guard.md.
Opt-in and local: agents do not start it on their own; they may offer it when
someone hits dev-server memory pain (dev-guard.md:5).
push-triad.sh#
scripts/push-triad.sh [--dry-run]
Pushes versable-builder, walmart-mvp, and speedway in one run, "written so
a human approves once instead of three times" (push-triad.sh:4). It refuses to
push anything it cannot account for: every repo must be on main, clean of
staged work, and tracking a remote that has not moved underneath it. A repo that
fails a check is skipped, never forced, and the script still tries the others.
--dry-run shows what would go and pushes nothing. The repo paths are fixed at
the top of the file for this machine.
release-kit.sh (superseded)#
Not the release path. The kit, the toolkit and qsync publish from the
publish-kit workflow on a version bump pushed to main (packages/ui/README.md,
Releasing); a hand publish races it and the workflow then skips. This script
is the pre-workflow laptop publish, kept only as the fallback if the workflow
is down; --dry-run is safe to read, nothing else in it should run.
Adding a script#
A script here carries a header comment that says what it is for in a sentence a
human can read, a Usage: line, and any env knobs it reads; then it gets a row
in the table above and a section below it. If something else calls it (a
package.json script, a workflow, a rule in CLAUDE.md), the section names the
caller. Zero em dashes, the same as every file in this repo.
Related#
CONTRIBUTING.mdsection 3, running things, and section 7, docs.CLAUDE.md, the prose rules and the release rule these scripts serve.README.md, the repo explained for a human reader: who reads what, the map by what you came to do.