Watch only the directories the library index is generated from

check:library-index failed, naming library/scripts/research/build-trade-languages.mjs
as the reason the component menu was stale. That file is a build script. The
menu is a catalogue of reusable components, composables and utilities, and
generate-library-index.mjs reads exactly three directories — components/,
composables/, utils/ — so a change to a build script cannot alter one byte of
the output.

The gate walked all of library/. Measured: 75 files are indexed, 173 are not —
scripts/ 58, i18n/ 98, plus data/, layouts/, api/ and constants/. It watched 2.3
times more than the thing it guards, while its own comment said "Newest source
the generator actually scans", which is exactly what it did not do.

It fired for real: adding a comment to a build script two commits ago turned it
red. That is the expensive kind of false positive, because the remedy looks
cheap — regenerate and move on — and a gate that asks for a pointless
regeneration teaches the reader to do it on reflex, which is how a staleness
check stops being read at all.

Now scoped to the three indexed directories, with a note that the scope must be
extended in the same commit if the generator ever adds a section().

Negative-tested both directions rather than only confirming the fix: touching
library/composables/useMapFly.js still FAILS and names it; touching the build
script again PASSES. The gate discriminates where it could not before.

Worth recording that the regenerated index came out byte-identical — git reports
only the gate file as modified. That is the claim made concrete: the change
which had been failing this gate could not affect its output.

Five gates pass.
This commit is contained in:
doxa-maps-88655c70 2026-09-23 11:41:55 +00:00
parent 1ddfde6b6b
commit d08edbc957

View file

@ -39,6 +39,22 @@ if (!existsSync(INDEX)) {
}
// Newest source the generator actually scans.
//
// ★ AND THAT NOW MEANS WHAT IT SAYS (fixed 2026-09-23). This walked ALL of library/, while
// generate-library-index.mjs reads exactly three subdirectories — components/, composables/ and
// utils/ (see its section() calls). MEASURED: 75 files are indexed, 173 are not — scripts/ 58,
// i18n/ 98, plus data/, layouts/, api/, constants/. So the gate watched 2.3x more than the thing it
// guards, and a change anywhere in that surplus demanded a regeneration that could not alter one
// byte of the output.
//
// It fired for real: adding a COMMENT to library/scripts/research/build-trade-languages.mjs turned
// this gate red, naming a build script as the reason the component MENU was stale. A gate that
// fails for a change it can prove is irrelevant teaches the reader to regenerate on reflex, which
// is how a staleness check stops being read.
//
// Keeping the scope in step is the price of this design: if generate-library-index.mjs ever adds a
// section(), add its directory here in the same commit.
const INDEXED_DIRS = ['components', 'composables', 'utils']
let newest = 0, newestFile = null
const walk = (d) => {
for (const e of readdirSync(d, { withFileTypes: true })) {
@ -50,7 +66,10 @@ const walk = (d) => {
if (m > newest) { newest = m; newestFile = p.slice(ROOT.length + 1) }
}
}
walk(LIB)
for (const d of INDEXED_DIRS) {
const p = join(LIB, d)
if (existsSync(p)) walk(p)
}
const idxMs = statSync(INDEX).mtimeMs
console.log(`LIBRARY-INDEX: index vs ${newestFile ? 'newest library source' : 'library/'}.`)