diff --git a/documentation/README-SECTION-3-cli-commands.md b/documentation/README-SECTION-3-cli-commands.md index 770c1427d..9c83d9c77 100644 --- a/documentation/README-SECTION-3-cli-commands.md +++ b/documentation/README-SECTION-3-cli-commands.md @@ -49,7 +49,7 @@ The scripts these commands are grounded in (from this branch's `package.json`): "build": "bash internal/build-lock.sh", "build:unlocked": "bun run gates:pre && bun run library-index && bun run check:library-index && bun run clean && bun run token && bun run build:bundles && bun run tree && bun run gates:post && bun run gallery", "gates:pre": "node internal/run-parallel.mjs --label=pre -- check:template-literal check:mjs-parse check:sfc-parse check:tab-radius check:synced-css check:wp-embed check:doc-scripts", -"gates:post": "node internal/run-parallel.mjs --label=post -- check:drop check:parse verify check:sri check:public-hygiene check:label-joins check:facet-cascade check:facet-one-field check:heartbeat check:kpi-unit check:composite-reg check:descriptions check:no-abs-paths check:no-codename check:dep-names check:composite-srcs check:embed-targets check:nested-token check:i18n-parity check:tabs-localized check:packets-all check:packet-strings-parity check:zone-census check:share-policy check:library-index check:csv-shape check:capability-citations check:catalog-identity check:no-orphan-gates check:quoted-scripts", +"gates:post": "node internal/run-parallel.mjs --label=post -- check:drop check:parse verify check:sri check:public-hygiene check:label-joins check:facet-cascade check:facet-one-field check:heartbeat check:kpi-unit check:composite-reg check:descriptions check:no-abs-paths check:no-codename check:dep-names check:composite-srcs check:embed-targets check:nested-token check:i18n-parity check:tabs-localized check:packets-all check:packet-strings-parity check:zone-census check:share-policy check:library-index check:csv-shape check:capability-citations check:catalog-identity check:no-orphan-gates check:quoted-scripts check:done-evidence", "build:bundles": "node internal/run-parallel.mjs --bundles", // the 22 vite builds, 4 at a time "preview": "bun x vite preview", "serve": "node internal/serve-strict.mjs", // 404s a directory, like production diff --git a/internal/check-done-evidence.mjs b/internal/check-done-evidence.mjs index 943b1278c..27e76949e 100644 --- a/internal/check-done-evidence.mjs +++ b/internal/check-done-evidence.mjs @@ -59,19 +59,18 @@ const BACKLOGS = [ ] // Pre-existing, from before the rule. Verified 2026-09-21. SHRINK ONLY. +// ★ THE BASELINE IS NOW EMPTY, and that is the strongest state this gate can be in. +// All ten exemptions had since gained evidence — the gate reported every one of them +// as STALE on 2026-09-24 — so the list was pure dead weight: ten ids that exempted +// nothing while implying ten cards still owed a record. +// An EMPTY set is not an unset one: every done card must now carry evidence, with no +// exemptions, and the gate fails outright for a single card that does not. Keeping +// `{ ... }` full of satisfied ids would mean the same today and quietly permit a +// regression the moment someone "reused" an entry. +// If a genuinely un-reconstructable card ever needs an exemption, add its id here WITH +// the reason — and the gate will tell you the day it becomes stale. const BASELINE = new Set([ - 'BUILD-AGENT-SKILLS', - 'BUILD-CAP1-SINGLE-ELEMENT-SHOWCASE', - 'BUILD-PLUGIN-STUDIO-VUE-SPA', - 'BUILD-README-CLI-COMMANDS', - 'BUILD-README-DEDUP-BLUF', - 'BUILD-README-SCREENSHOT-MATRIX', - 'BUILD-RENAME-PLUGIN-DESIGNS', - 'BUILD-RESTORE-MOBILE-SPA', - 'BUILD-STARTER-TEMPLATE', - 'BUILD-UNIFIED-RESEARCH-DASHBOARD', ]) - let checked = 0, done = 0 const offenders = [] const staleBaseline = [] @@ -87,7 +86,19 @@ for (const rel of BACKLOGS) { done++ const hasBluf = String(c.bluf || '').trim().length > 0 const hasFields = c.fields && Object.keys(c.fields).length > 0 - if (hasBluf || hasFields) { + // ★ THE BOARD USES TWO CARD SCHEMAS, and this gate only knew one. Older cards carry + // `bluf` + `fields`; a second family carries `one_line` (what was done), `why`, and + // `verify` (the artifact and how it was checked). MEASURED 2026-09-24 across 443 done + // cards: 40 carry `verify` and 41 carry `one_line`, and ALL THREE cards this gate was + // failing had one or both — with named probes, assertion counts and negative tests. + // They were among the best-evidenced cards on the board. + // `verify` is if anything the STRONGER signal: it names how the claim was checked, + // which is exactly what "evidence" means here. Demanding a redundant `bluf` alongside + // it would have taught the next agent to pad the field the checker reads rather than + // write the record — the gate training the behaviour it exists to prevent. + const hasVerify = String(c.verify || '').trim().length > 0 + const hasOneLine = String(c.one_line || '').trim().length > 0 + if (hasBluf || hasFields || hasVerify || hasOneLine) { // A baselined id that now HAS evidence is stale — report it so the list shrinks. if (BASELINE.has(c.id)) staleBaseline.push(`${c.id} (${rel})`) continue @@ -104,13 +115,15 @@ for (const s of staleBaseline) { } if (offenders.length) { - console.error(`\nDONE-EVIDENCE: FAIL — ${offenders.length} card(s) are done with NO bluf and NO fields:`) + console.error(`\nDONE-EVIDENCE: FAIL — ${offenders.length} card(s) are done with NO evidence in any field:`) for (const o of offenders) console.error(` ✗ ${o}`) console.error( - '\n Add ONE of: a `bluf` saying what was done, or a `fields` entry naming the artifact and how\n' + + '\n Add ONE of: `bluf` or `one_line` saying what was done, `verify` naming how it was checked,\n' + + ' or a `fields` entry naming the artifact. Any ONE of the four is enough — the point is a\n' + + ' record a reader can reconcile against the code, not a particular field name.\n' + ' it was verified. Write it now, while the work is fresh — reconstructing it later produces a\n' + ' plausible story indistinguishable from a real record.' ) process.exit(1) } -console.log('DONE-EVIDENCE: PASS — every newly-done card carries a bluf or fields.') +console.log('DONE-EVIDENCE: PASS — every done card carries evidence (bluf, one_line, verify or fields).') diff --git a/package.json b/package.json index eb0c8eca7..d64675150 100644 --- a/package.json +++ b/package.json @@ -141,7 +141,7 @@ "check:doc-scripts:self-test": "node internal/check-doc-quotes-scripts.mjs --self-test", "check:legend-source": "node internal/check-legend-matches-source.mjs # the numbers the maps SHOW must match the numbers the live SOURCE has. Every other gate checks INTERNAL consistency — a page can agree with itself perfectly while its legend has stopped describing reality. Offline SKIPs (exit 0); only a reachable endpoint that disagrees fails.", "gates:pre": "node internal/run-parallel.mjs --label=pre -- check:template-literal check:mjs-parse check:sfc-parse check:tab-radius check:synced-css check:wp-embed check:doc-scripts", - "gates:post": "node internal/run-parallel.mjs --label=post -- check:drop check:parse verify check:sri check:public-hygiene check:label-joins check:facet-cascade check:facet-one-field check:heartbeat check:kpi-unit check:composite-reg check:descriptions check:no-abs-paths check:no-codename check:dep-names check:composite-srcs check:embed-targets check:nested-token check:i18n-parity check:tabs-localized check:packets-all check:packet-strings-parity check:zone-census check:share-policy check:library-index check:csv-shape check:capability-citations check:catalog-identity check:no-orphan-gates check:quoted-scripts", + "gates:post": "node internal/run-parallel.mjs --label=post -- check:drop check:parse verify check:sri check:public-hygiene check:label-joins check:facet-cascade check:facet-one-field check:heartbeat check:kpi-unit check:composite-reg check:descriptions check:no-abs-paths check:no-codename check:dep-names check:composite-srcs check:embed-targets check:nested-token check:i18n-parity check:tabs-localized check:packets-all check:packet-strings-parity check:zone-census check:share-policy check:library-index check:csv-shape check:capability-citations check:catalog-identity check:no-orphan-gates check:quoted-scripts check:done-evidence", "build:bundles": "node internal/run-parallel.mjs --bundles", "check:maplibre-drops": "node internal/check-maplibre-layer-drops.mjs", "check:tabs-localized": "node internal/check-tabs-localized.mjs # a chosen locale must CHANGE the rendered tab text. check:i18n-parity compares catalogs to each OTHER, so it cannot tell a shipped translation from a dead one; tabs.json is reached only via a DYNAMIC key (SemanticTreeLegend.vue:40), invisible to any grep. Renders it and reads the result.",