Regenerate the library index during the build, so it cannot fall behind

check:library-index existed, was correct, and had been failing for about 19.6
hours. Nothing noticed because it runs only when a person types it:
build:unlocked chains 24 gates and this was not one of them.

check:no-orphan-gates passes on it, which is worth understanding rather than
treating as a gap in that gate. It asks whether every gate is REACHABLE — "named
in package.json or imported by something that is" — and check:library-index is
named there. Reachable and wired are different properties. 64 gate-shaped files
exist; 24 run on every build; the rest only run on request.

The fix is to regenerate rather than to check harder. check:composite is also
mtime-based and is in the chain, but it guards build output whose freshness
depends on build ORDER — a real invariant only a human can resolve.
reference-library-index.md is DERIVED from library/, so a staleness failure has
exactly one remedy: run the generator. Wiring the check alone would fail builds
and hand the author a chore; wiring the generator makes the staleness
impossible, which is the only way the file's own header — "DERIVED — cannot
drift from the code" — can be true.

Both are now in the pre-build group, generator then check, beside the other
source-only gates and before `clean`. Safe to run unconditionally: measured
deterministic (byte-identical on re-run) and 237ms. The check is kept after it
so a generator that silently writes nothing still fails the build rather than
passing quietly.

Updating package.json made check:quoted-scripts fail, which is the gate doing
its job, and it surfaced that the quoted copy in README-SECTION-3 was ALREADY
stale before this change: it omitted check:tab-radius, check:synced-css,
check:wp-embed and check:doc-scripts. An omitted step in a quoted list is
invisible — there is no wrong character to notice, only a check the reader
believes is not in the chain. The doc now matches what runs.

Verified by a full build: the generator ran, the check passed, vite built every
bundle, exit 0. The index is not dirty afterwards, which is the determinism
claim holding inside the real chain rather than in an isolated test. Five lines
in the build log match /error|FAIL/ and all five are gate DESCRIPTIONS
containing those words, not results.
This commit is contained in:
doxa-maps-88655c70 2026-09-23 07:25:01 +00:00
parent 18b3366c2b
commit 4b39abf126
2 changed files with 3 additions and 3 deletions

View file

@ -25,7 +25,7 @@ The scripts these commands are grounded in (from this branch's `package.json`):
// claiming to be ground truth, and this one had silently stopped being it.
"dev": "bun x vite",
"build": "bash internal/build-lock.sh",
"build:unlocked": "bun run check:template-literal && bun run check:mjs-parse && bun run check:sfc-parse && bun run clean && bun run token && for d in plugin-designs/*/; do BUNDLE=$(basename \"$d\") bun x vite build || exit 1; done && bun run tree && bun run check:drop && bun run check:parse && bun run verify && bun run check:sri && bun run check:public-hygiene && bun run check:label-joins && bun run check:facet-cascade && bun run check:facet-one-field && bun run check:heartbeat && bun run check:kpi-unit && bun run check:composite-reg && bun run check:descriptions && bun run check:no-abs-paths && bun run check:no-codename && bun run check:dep-names && bun run check:composite-srcs && bun run check:embed-targets && bun run check:nested-token && bun run gallery",
"build:unlocked": "bun run check:template-literal && bun run check:mjs-parse && bun run check:sfc-parse && bun run check:tab-radius && bun run check:synced-css && bun run check:wp-embed && bun run check:doc-scripts && bun run library-index && bun run check:library-index && bun run clean && bun run token && for d in plugin-designs/*/; do BUNDLE=$(basename \"$d\") bun x vite build || exit 1; done && bun run tree && bun run check:drop && bun run check:parse && bun run verify && bun run check:sri && bun run check:public-hygiene && bun run check:label-joins && bun run check:facet-cascade && bun run check:facet-one-field && bun run check:heartbeat && bun run check:kpi-unit && bun run check:composite-reg && bun run check:descriptions && bun run check:no-abs-paths && bun run check:no-codename && bun run check:dep-names && bun run check:composite-srcs && bun run check:embed-targets && bun run check:nested-token && bun run gallery",
"preview": "bun x vite preview",
"serve": "node internal/serve-strict.mjs", // 404s a directory, like production
"cap:sync": "./node_modules/.bin/cap sync android",

View file

@ -54,7 +54,7 @@
"check:facet-changes-map:self-test": "node internal/check-facet-changes-map.mjs --self-test # reverts the fix IN THE LIVE PAGE and requires the gate to FAIL. SELF_TEST_MODE=colour (default, isolates the colour assertion — the reported bug) | props | both | frozen (blocks the source update, isolating the set assertion). All four modes verified caught.",
"check:heartbeat": "node internal/check-heartbeat-threshold.mjs # the HEARTBEAT ZONE threshold (the choropleth's top bin) must come from config AND the shipped config must still render today's ramp. Two sides: (B) a configured threshold must MOVE the edge — catches re-hard-coding; (A2) dashboard.config.js's own map.* must still resolve to 5/20/60/150/Infinity — catches the shipped default silently changing. A2 was MISSING at first and heartbeatThreshold:999 shipped past this gate printing 'default ramp unchanged'. A grep for '150' cannot do either job: it false-positives on the legitimate default and false-negatives on a re-hard-coding at 200. run check:heartbeat:self-test for the NEGATIVE tests (3 cases).",
"check:heartbeat:self-test": "node internal/check-heartbeat-threshold.mjs --self-test # THREE regression cases, each required to fire ITS OWN assertion: [literal] resolver replaced by the old hard-coded array -> B; [shipped-default] dashboard.config.js heartbeatThreshold changed -> A2; [shipped-mode] heartbeatMode flipped to quantile -> A2. Poisons IN MEMORY, never the file. Testing that the FEATURE works is not testing that the REGRESSION is caught — this gate shipped with only the first and missed the second.",
"build:unlocked": "bun run check:template-literal && bun run check:mjs-parse && bun run check:sfc-parse && bun run check:tab-radius && bun run check:synced-css && bun run check:wp-embed && bun run check:doc-scripts && bun run clean && bun run token && for d in plugin-designs/*/; do BUNDLE=$(basename \"$d\") bun x vite build || exit 1; done && bun run tree && bun run check:drop && bun run check:parse && bun run verify && bun run check:sri && bun run check:public-hygiene && bun run check:label-joins && bun run check:facet-cascade && bun run check:facet-one-field && bun run check:heartbeat && bun run check:kpi-unit && bun run check:composite-reg && bun run check:descriptions && bun run check:no-abs-paths && bun run check:no-codename && bun run check:dep-names && bun run check:composite-srcs && bun run check:embed-targets && bun run check:nested-token && bun run gallery",
"build:unlocked": "bun run check:template-literal && bun run check:mjs-parse && bun run check:sfc-parse && bun run check:tab-radius && bun run check:synced-css && bun run check:wp-embed && bun run check:doc-scripts && bun run library-index && bun run check:library-index && bun run clean && bun run token && for d in plugin-designs/*/; do BUNDLE=$(basename \"$d\") bun x vite build || exit 1; done && bun run tree && bun run check:drop && bun run check:parse && bun run verify && bun run check:sri && bun run check:public-hygiene && bun run check:label-joins && bun run check:facet-cascade && bun run check:facet-one-field && bun run check:heartbeat && bun run check:kpi-unit && bun run check:composite-reg && bun run check:descriptions && bun run check:no-abs-paths && bun run check:no-codename && bun run check:dep-names && bun run check:composite-srcs && bun run check:embed-targets && bun run check:nested-token && bun run gallery",
"check:template-literal": "node internal/template-literal-check.mjs",
"verify:map-paint": "node internal/verify-map-paint.mjs",
"check:sri": "node internal/sri-consistency-check.mjs",
@ -146,4 +146,4 @@
"engines": {
"node": ">=18.0.0"
}
}
}