From d314c440435b55886414ac35b5505805922ea9a2 Mon Sep 17 00:00:00 2001 From: Doxa Maps Date: Tue, 29 Sep 2026 04:28:58 +0000 Subject: [PATCH] internal/ keeps the reason and drops the speaker: no gate quotes or cites the Driver Every reference to the Driver in internal/ is reworded the same way as in library/: the reason stays, the speaker and the quote go, an open decision reads "provisional, pending a product decision", and agent names and decision- sheet rows are dropped. Where a gate printed the word, its message now names the reviewer or the ruling instead. Three spots were code, not comments, and changed with their callers: - the element census's allowlist field `driver` is now `ruling`, in the gate and both presets (same validation: match, ruling, date and card required); - check:i18n-never-translated's DRIVER-GATED marker is DECISION-PENDING, in the entries and in the regex that counts them (its output is otherwise byte-identical); - the package.json description of the census says "ruling". public-hygiene-check keeps its two patterns for the word: they are what keep it out of the served folder. --- internal/_composed-tiers.mjs | 2 +- .../acceptance/big-picture-acceptance.mjs | 2 +- internal/acceptance/interop-harness.mjs | 4 +- internal/backend-dev-plugin.mjs | 2 +- internal/check-capability-citations.mjs | 2 +- internal/check-capability-derived.mjs | 4 +- internal/check-csv-export-shape.mjs | 10 ++--- internal/check-dxlife-untouched.mjs | 2 +- internal/check-element-census-vs-live.mjs | 18 ++++----- internal/check-embed-url-absolute.mjs | 4 +- internal/check-embedded-rtl.mjs | 2 +- internal/check-facet-cascade.mjs | 19 +++++----- internal/check-facet-changes-map.mjs | 14 +++---- internal/check-facet-one-field.mjs | 4 +- internal/check-filter-width-stable.mjs | 2 +- internal/check-fits-the-screen.mjs | 10 ++--- internal/check-fixed-anchoring.mjs | 2 +- internal/check-hardcoded-english.mjs | 4 +- internal/check-heartbeat-threshold.mjs | 20 +++++----- internal/check-i18n-never-translated.mjs | 12 +++--- internal/check-i18n-stopped-scope.mjs | 2 +- internal/check-legend-export-reachable.mjs | 4 +- internal/check-legend-info-localized.mjs | 5 +-- internal/check-legend-matches-source.mjs | 4 +- internal/check-legend-top-offset.mjs | 8 ++-- internal/check-list-selection.mjs | 10 ++--- internal/check-manifest-covers-discovery.mjs | 4 +- internal/check-map-menu-anchor.mjs | 8 ++-- internal/check-nav-reachable-mobile.mjs | 2 +- internal/check-no-orphan-gates.mjs | 2 +- internal/check-no-public-binds.mjs | 7 ++-- internal/check-one-scroll-container.mjs | 2 +- internal/check-optional-t-equivalence.mjs | 4 +- internal/check-packet-render.mjs | 24 ++++++------ internal/check-packet-strings-parity.mjs | 2 +- internal/check-poster-action-print.mjs | 2 +- internal/check-poster-card-fits.mjs | 38 +++++++++---------- internal/check-poster-raster.mjs | 4 +- internal/check-prayer-walk-planner.mjs | 6 +-- internal/check-print-geometry.mjs | 7 ++-- internal/check-provide-shadowing.mjs | 2 +- internal/check-series-isolation.mjs | 4 +- internal/check-setup-order.mjs | 2 +- internal/check-share-policy.mjs | 4 +- internal/check-shot-fidelity.mjs | 2 +- internal/check-spa-tab-order.mjs | 24 ++++++------ internal/check-square-map-controls.mjs | 2 +- internal/check-studio-rail.mjs | 6 +-- internal/check-tab-radius-token.mjs | 6 +-- internal/check-universal-props.mjs | 8 ++-- internal/check-upg-map-data-painted.mjs | 4 +- internal/check-url-resolver.mjs | 2 +- internal/check-verification-tags.mjs | 18 ++++----- internal/check-zoning-declared.mjs | 2 +- internal/clean.mjs | 2 +- .../element-census/people-groups-grid.json | 4 +- .../element-census/regions-dashboard.json | 10 ++--- internal/generate-gallery.mjs | 8 ++-- internal/generate-tree.mjs | 12 +++--- internal/generate-wagf-region-names.mjs | 2 +- internal/lib/facet-walk.mjs | 2 +- internal/long-frames-probe.mjs | 2 +- internal/measure-map-load.mjs | 2 +- internal/mobile-sheet-probe.mjs | 2 +- internal/plugin-gallery/dev-plugin.mjs | 29 +++++++------- internal/public-hygiene-check.mjs | 20 +++++----- internal/readme-shots.mjs | 6 +-- internal/settled-tree-gate.mjs | 2 +- internal/share-roundtrip-smoke.mjs | 4 +- internal/smoke-studio.mjs | 4 +- internal/sync-app-shells.mjs | 2 +- internal/theme-flash-probe.mjs | 4 +- internal/verify-5-capabilities.mjs | 2 +- internal/verify-browser-all.mjs | 6 +-- internal/verify-map-paint.mjs | 2 +- internal/verify-shell-scroll.mjs | 16 ++++---- package.json | 2 +- 77 files changed, 254 insertions(+), 261 deletions(-) diff --git a/internal/_composed-tiers.mjs b/internal/_composed-tiers.mjs index 2d4b2c9a7..4e9ebbb5d 100644 --- a/internal/_composed-tiers.mjs +++ b/internal/_composed-tiers.mjs @@ -17,7 +17,7 @@ /** * Derive the composition tier from the `composes` edges, and refuse to disagree with an author. * - * ★ WHY DERIVE AT ALL (Driver, 2026-09-27). Tiers 3-5 were AUTHORED ONLY — discover.mjs infers just + * ★ WHY DERIVE AT ALL (2026-09-27). Tiers 3-5 were AUTHORED ONLY — discover.mjs infers just * `single` and `parameterized`, so a composite with no meta.json shipped as capability 1. That is not * hypothetical: research-dashboard did exactly that while nesting ten views, and the warning in * detectProfileType exists because of it. A missing file is indistinguishable from a deliberate choice. diff --git a/internal/acceptance/big-picture-acceptance.mjs b/internal/acceptance/big-picture-acceptance.mjs index 724946a2e..0205d9f10 100644 --- a/internal/acceptance/big-picture-acceptance.mjs +++ b/internal/acceptance/big-picture-acceptance.mjs @@ -19,7 +19,7 @@ const API = 'https://pray.doxa.life/api/people-groups/list?fields=name,slug,wagf // ── mirror of people-groups-grid.vue applyDropdownFilters + the Fuse-ish search keys ────── // Dropdown axes match by VALUE (u[field].value === selection) — the exact contract the header -// dropdown -> grid prop coupling relies on. Country is excluded per Driver. +// dropdown -> grid prop coupling relies on. Country is excluded by decision. function dropdownFilter(recs, { wagfRegion = '', wagfBlock = '', rop1 = '', religion = '' } = {}) { let out = recs for (const [f, sel] of Object.entries({ wagf_region: wagfRegion, wagf_block: wagfBlock, rop1, religion })) { diff --git a/internal/acceptance/interop-harness.mjs b/internal/acceptance/interop-harness.mjs index 0fbbb7fb6..8a90e9c3d 100644 --- a/internal/acceptance/interop-harness.mjs +++ b/internal/acceptance/interop-harness.mjs @@ -18,8 +18,8 @@ * API. Camera motion in particular (fitBounds/flyTo) has NO API equivalent to mirror; the only * way to prove "select rows, the map flies to the selection" is to select rows and read the map. * - * ── THE COMBINATION MATRIX (Driver: "EVERY SINGLE COMBINATION ... log whether it DISPLAYED, - * pass/fail only") ───────────────────────────────────────────────────────────────────────── + * ── THE COMBINATION MATRIX (EVERY SINGLE COMBINATION, logging only whether it DISPLAYED, + * pass/fail) ───────────────────────────────────────────────────────────────────────── * One line per combination, BOTH halves recorded, pass/fail only. "Displayed" is never inferred * from a click firing or an element existing — see WHAT COUNTS AS DISPLAYED per pair below. * diff --git a/internal/backend-dev-plugin.mjs b/internal/backend-dev-plugin.mjs index 3e31766c7..556506144 100644 --- a/internal/backend-dev-plugin.mjs +++ b/internal/backend-dev-plugin.mjs @@ -52,7 +52,7 @@ export function devBackends(env = process.env) { // This server is SUPPOSED to run the engine (a server deployment with the engine switched on): while it // is down, the plugin says "not running yet" instead of "runs on your own computer". expected: () => process.env.RUDDER_ENGINE === '1' || process.env.RUDDER_AUDIO === 'browser', - // RUDDER_ENGINE=0 (a server where Rudder is laptop-only, the Driver 2026-09-27): never start it, even if a + // RUDDER_ENGINE=0 (a server where Rudder is laptop-only, 2026-09-27): never start it, even if a // binary built by an earlier engine-on deploy is still there — it would offer to record a server's mic. disabled: () => process.env.RUDDER_ENGINE === '0', }, diff --git a/internal/check-capability-citations.mjs b/internal/check-capability-citations.mjs index e6bd30e17..e338c02fb 100644 --- a/internal/check-capability-citations.mjs +++ b/internal/check-capability-citations.mjs @@ -54,7 +54,7 @@ const MANIFEST = join(ROOT, 'public', TREE_NAME, 'manifest.json') // defect recur unnoticed in a second place. // // NOT COVERED, and it cannot be: the /plugin-designer SKILL carries the same stale citation and -// lives outside this repo, so no gate here can reach it. That is why the fix is a Driver edit; the +// lives outside this repo, so no gate here can reach it. That is why the fix is an edit outside this repo; the // repo's job is to hold the checkable half (see BUILD-PLUGIN-DESIGNER-SKILL-MEANS-REAL-WORK). const DOC_DIR = join(ROOT, 'documentation') const DOC_FILES = existsSync(DOC_DIR) diff --git a/internal/check-capability-derived.mjs b/internal/check-capability-derived.mjs index 6e9d42f55..63f364aec 100644 --- a/internal/check-capability-derived.mjs +++ b/internal/check-capability-derived.mjs @@ -10,8 +10,8 @@ * * WHAT THIS ASSERTS, and why each half is here: * 1. Every profile resolves to a capability 1-5. A 0 or a null means some surface will render a - * tier that does not exist; the Driver saw exactly that as "the Research Gallery shows as - * capability 0". + * tier that does not exist; that is exactly how the Research Gallery came to show as + * capability 0. * 2. A profile that composes anything derives cap-4, or cap-5 if it composes a cap-4 — and an * EXPLICIT type must AGREE with that. The declaration stays authoritative; it is not * overridden, it is checked. A meta that contradicts the structure means the meta or the diff --git a/internal/check-csv-export-shape.mjs b/internal/check-csv-export-shape.mjs index 33d054569..ac2115214 100644 --- a/internal/check-csv-export-shape.mjs +++ b/internal/check-csv-export-shape.mjs @@ -2,8 +2,8 @@ /** * check-csv-export-shape.mjs — the exported CSV must OPEN correctly in a spreadsheet. * - * THE DEFECT THIS CATCHES (Driver-reported 2026-09-22: "this is me exporting the CSV directly without - * making any edits... it does look a little bit glitched out"). The generator emitted a one-column + * THE DEFECT THIS CATCHES (reported 2026-09-22: a CSV exported directly, with no edits, looked a + * little glitched out). The generator emitted a one-column * provenance comment ABOVE the header: * line 0 ... 1 column "# Research Dashboard export — scope: ..." * line 1 ... N columns slug,name,religion,... @@ -13,8 +13,8 @@ * * ★ WHAT WAS *NOT* WRONG, AND MUST NOT BE "FIXED" ON SUSPICION — three plausible theories, all * refuted by measurement before a line was changed: - * - "it is tab-separated" — FALSE. The generator joins with commas; the tabs in the Driver's paste - * were his terminal rendering, not the bytes. + * - "it is tab-separated" — FALSE. The generator joins with commas; the tabs in the pasted report + * were a terminal's rendering, not the bytes. * - "quoting is broken" — FALSE. esc() is genuinely RFC-4180: it quotes when , " CR or LF appear and * doubles internal quotes. Embedded commas, quotes AND newlines survive a strict parser round trip. * - "CSV injection" — already handled; a leading = + - @ is prefixed with a single quote. @@ -128,7 +128,7 @@ const first = parsed[0] || [] if (first.length === 1 && String(first[0]).startsWith('#')) { fail('line 0 is a one-column "#" comment, so a spreadsheet will use it AS THE HEADER.', ' The scope sentence becomes the column names and the real header becomes data row 1 — which is\n' + - ' what the Driver saw as a "glitched" export. Put the provenance line LAST; a trailing one-column\n' + + ' what read as a "glitched" export. Put the provenance line LAST; a trailing one-column\n' + ' row is harmless, a leading one destroys the column mapping for the whole sheet.') } if (first[0] !== cols[0]) { diff --git a/internal/check-dxlife-untouched.mjs b/internal/check-dxlife-untouched.mjs index 9d6c5d1c2..4a2b40fa3 100644 --- a/internal/check-dxlife-untouched.mjs +++ b/internal/check-dxlife-untouched.mjs @@ -5,7 +5,7 @@ * ★ WHY THIS IS NOT `git status` (a real false-pass, 2026-09-20) * I verified the invariant for several ticks with: * cd root-dx-life && git status --porcelain | wc -l # -> 0 - * and reported that 0 to the Driver as proof. root-dx-life IS NOT A GIT REPOSITORY — it is a + * and reported that 0 as proof. root-dx-life IS NOT A GIT REPOSITORY — it is a * plain directory clone. `git status` prints "fatal: not a git repository" to STDERR and nothing * to stdout, so `wc -l` counts 0. THE CHECK RETURNED THE PASS VALUE *BECAUSE IT FAILED*. * Identical in shape to the settled-tree churn bug (bfs rejected the argument, stderr discarded, diff --git a/internal/check-element-census-vs-live.mjs b/internal/check-element-census-vs-live.mjs index 98b6db1b0..5799da819 100644 --- a/internal/check-element-census-vs-live.mjs +++ b/internal/check-element-census-vs-live.mjs @@ -5,15 +5,15 @@ * ★ WHY. Every clone-fidelity gate here compares PROPERTIES of NAMED selectors ("the region card * matches on 37 of 37 properties"). All of them are blind to an element that exists on only one side, * because an element nobody named is an element nobody measured. Regions found an extra control and - * an invented bar chart by eye, past eight green gates. The Driver's scope ruling is binary — "it - * exists on their page and must MATCH, or it is a sanctioned addition" — and this executes it. + * an invented bar chart by eye, past eight green gates. The scope ruling is binary: it exists on + * their page and must MATCH, or it is a sanctioned addition. This executes it. * (Promoted from regions' _probe-element-census-vs-live.mjs, 2026-09-25.) * * HOW, per page pair (our leaf vs the live URL): harvest every VISIBLE TEXT NODE through every shadow * root on both sides (text nodes, not leaf elements — a leaf-element walk lost every country name that * shares its anchor with a count span and passed vacuously), then diff the two SETS: * OURS-ONLY, unaccounted an invention — a scope violation → FAIL - * OURS-ONLY, sanctioned on the preset's allowlist, which carries the Driver's words + date + card + * OURS-ONLY, sanctioned on the preset's allowlist, which carries the ruling + date + card * THEIRS-ONLY a clone omission — something of theirs never ported → FAIL * DATA DRIFT the same label with different digits (their pages are SSR snapshots, ours * is live) — reported, not failed @@ -25,9 +25,9 @@ * CENSUS IS BLIND and exits 75. No preset or ad-hoc run is accepted without one. * * PRESETS: internal/element-census/.json — { owner, pages:[{name, leaf, live}], neg:{leaf, text}, - * sanctioned:[{match, flags, what, driver, date, card, theirs?, theirsFlags?}] }. `theirs` makes the entry a + * sanctioned:[{match, flags, what, ruling, date, card, theirs?, theirsFlags?}] }. `theirs` makes the entry a * SANCTIONED PAIR: their string for the same control (e.g. our "Hide Filters" / their "Show Filters"), - * excused as an omission only while our half is on the page. An allowlist entry without the Driver's words, + * excused as an omission only while our half is on the page. An allowlist entry without the ruling, * a date and a card is REFUSED (exit 2): it is evidence, not an ignore list. * * USAGE node internal/check-element-census-vs-live.mjs every preset @@ -63,7 +63,7 @@ function validate(p, from) { p.neg.leaf = p.neg.leaf || p.pages[0].leaf if (!p.pages.some((pg) => pg.leaf === p.neg.leaf)) p.pages.push({ name: 'neg control page', leaf: p.neg.leaf, live: p.pages[0].live, negOnly: true }) p.sanctioned = (p.sanctioned || []).map((s, i) => { - for (const k of ['match', 'driver', 'date', 'card']) if (!s[k]) bad(`${from}: sanctioned[${i}] has no "${k}" — every allowance carries the Driver's words, the date and the card`) + for (const k of ['match', 'ruling', 'date', 'card']) if (!s[k]) bad(`${from}: sanctioned[${i}] has no "${k}" — every allowance carries the ruling, the date and the card`) if (!/^\d{4}-\d{2}-\d{2}$/.test(s.date)) bad(`${from}: sanctioned[${i}].date must be YYYY-MM-DD`) let re; try { re = new RegExp(s.match, s.flags || '') } catch (e) { bad(`${from}: sanctioned[${i}].match is not a regex: ${e.message}`) } // A SANCTIONED PAIR: `theirs` names THEIR string for the same control in its other state (their @@ -145,7 +145,7 @@ const read = async (url) => { let violations = 0, omissions = 0, unmeasured = 0, blind = 0 for (const [name, p] of presets) { console.log(`\n══ ${name} (owner: ${p.owner || '?'}) ══`) - const sanctionedBy = (s) => { const hit = p.sanctioned.find((x) => x.re.test(s)); return hit ? `${hit.what || hit.card} — Driver ${hit.date}: "${hit.driver}"` : null } + const sanctionedBy = (s) => { const hit = p.sanctioned.find((x) => x.re.test(s)); return hit ? `${hit.what || hit.card} — ruled ${hit.date}: ${hit.ruling}` : null } const oursByLeaf = new Map() let negSeenInOursOnly = null for (const pg of p.pages) { @@ -193,7 +193,7 @@ for (const [name, p] of presets) { console.log(` DATA DRIFT (same label, different figure — their page is an SSR snapshot, ours is live): ${drift.length}`) for (const [o, t] of drift.slice(0, 10)) console.log(` ~ ours ${JSON.stringify(o.slice(0, 44))} vs theirs ${JSON.stringify(t.slice(0, 44))}`) } - for (const [t, x] of pairedTheirs) console.log(` ok their "${t.slice(0, 50)}" — the other half of a sanctioned pair (${x.what || x.card}, Driver ${x.date})`) + for (const [t, x] of pairedTheirs) console.log(` ok their "${t.slice(0, 50)}" — the other half of a sanctioned pair (${x.what || x.card}, ruled ${x.date})`) console.log(` THEIRS-ONLY (ported nowhere on our side): ${theirsOnly.length}`) for (const s of theirsOnly.slice(0, 25)) console.log(` !! "${s.slice(0, 80)}"`) if (theirsOnly.length > 25) console.log(` … and ${theirsOnly.length - 25} more`) @@ -207,7 +207,7 @@ await browser.close(); stopSrv() console.log(`\n── ${violations} unaccounted addition(s) · ${omissions} omission(s) · ${unmeasured} page(s) not measured · ${blind} blind preset(s) ──`) if (violations || omissions) { - console.log('ELEMENT-CENSUS: FAIL — an unaccounted addition is a scope violation under the Driver\'s binary test; an omission is a clone gap. Read the lists: this reports, the owner adjudicates.') + console.log('ELEMENT-CENSUS: FAIL — an unaccounted addition is a scope violation under the binary scope test; an omission is a clone gap. Read the lists: this reports, the owner adjudicates.') process.exit(1) } if (blind || unmeasured) { console.log('ELEMENT-CENSUS: NOT MEASURED — a page did not render or the census could not see its own negative control.'); process.exit(NOT_MEASURED) } diff --git a/internal/check-embed-url-absolute.mjs b/internal/check-embed-url-absolute.mjs index b81e80856..bb0f2546d 100644 --- a/internal/check-embed-url-absolute.mjs +++ b/internal/check-embed-url-absolute.mjs @@ -2,7 +2,7 @@ /** * check-embed-url-absolute — a share/embed url must never be relative. * - * THE DEFECT (Driver, 2026-09-28, testing live): the link copied from Simple Research was + * THE DEFECT (2026-09-28, found testing live): the link copied from Simple Research was * `research-map-plus-grid/research-map-plus-grid/index.html` while the page was * `http://127.0.0.1:5192/#f=…` — "the perfect example of how embeddability is not working". * @@ -42,7 +42,7 @@ const LEAF = 'research-map-plus-grid/research-map-plus-grid/index.html' const got = absoluteEmbedUrl(LEAF) if (!/^https?:\/\//i.test(got)) { fails.push(`absoluteEmbedUrl returned a RELATIVE url with no tree root: "${got}".\n` - + ' That is the exact value the Driver copied. It must resolve against the runtime origin.') + + ' That is the exact value that was copied. It must resolve against the runtime origin.') } if (got !== 'http://127.0.0.1:5192/' + LEAF) { fails.push(`absoluteEmbedUrl did not resolve against the page origin: "${got}"`) diff --git a/internal/check-embedded-rtl.mjs b/internal/check-embedded-rtl.mjs index 28ed3bf9f..cd55c3abc 100644 --- a/internal/check-embedded-rtl.mjs +++ b/internal/check-embedded-rtl.mjs @@ -59,7 +59,7 @@ const BASE = process.argv.slice(2).find((a) => !a.startsWith('--')) || process.env.BASE_URL || 'http://127.0.0.1:4173' const HOST_PORT = Number(process.env.RTL_HOST_PORT || 47393) // ★ --emit WRITES THE PARTNER PAGE TO DISK INSTEAD OF MEASURING IT. -// Under the Playwright policy (Driver, 2026-09-25) only rega runs a browser, so this check's +// Under the Playwright policy (2026-09-25) only the browser seat runs a browser, so this check's // result now has to be produced by someone else's eyes. But the partner page only ever existed // INSIDE this process — two createServer calls on ephemeral ports — so "open a partner page at a // foreign origin" was not a thing anyone could actually do. NEEDS-EYES rows 3, 4 and 6 name a diff --git a/internal/check-facet-cascade.mjs b/internal/check-facet-cascade.mjs index 5ee1e673c..abd0f1c88 100644 --- a/internal/check-facet-cascade.mjs +++ b/internal/check-facet-cascade.mjs @@ -2,10 +2,9 @@ /** * check-facet-cascade.mjs — A CHILD FACET SELECTION MUST NOT OUTLIVE ITS PARENT. * - * THE DEFECT THIS CATCHES (Driver-reported 2026-09-22): "if you have a language selected and then - * you deselect the language family, it does not deselect the language of that language family that - * was selected... because of that I tried to go and select a new language family and it does not - * show up on the map. And I cannot see the reason why unless I look at the selected section header." + * THE DEFECT THIS CATCHES (reported 2026-09-22): with a language selected, deselecting its language + * family did not deselect the language. Selecting a new language family then showed nothing on the + * map, and the only visible reason was in the selected section header. * * ★ WHY THIS IS A DATA-TRUST BUG, NOT A NIT. filterSet is AND-stacked — filteredRows keeps a row * only when EVERY active key matches. An orphaned child keeps filtering, so after the parent is @@ -25,7 +24,7 @@ * leaving the identical orphan one rung down, so depth is asserted explicitly. * B. NO ORPHANS — for each hierarchy, set every tier, clear the TOP, and assert no descendant * key survives in filterSet. - * C. THE DRIVER'S ACTUAL SEQUENCE, asserted on counts (the step that reproduces what he saw): + * C. THE REPORTED SEQUENCE, asserted on counts (the step that reproduces what was seen): * 1. select parent P, then child C within P -> record N1 (must be > 0) * 2. clear P -> assert C is gone from filterSet * 3. select a DIFFERENT parent Q -> assert count > 0 AND == Q-alone count @@ -42,7 +41,7 @@ * NEGATIVE-TESTED, and the negative test is part of this file: `--self-test` copies the bus, strips * the cascade line back out, re-runs every assertion against the reverted copy and requires the * gate to FAIL. Measured: 13 assertions fail, including "after switching to Q=… the map is EMPTY - * (Showing 0)" for all three hierarchies — i.e. it reproduces the Driver's report exactly. A gate + * (Showing 0)" for all three hierarchies — i.e. it reproduces the report exactly. A gate * nobody has broken is a gate nobody knows works. * * ── HERMETIC BY CONSTRUCTION (it runs inside build:unlocked) ────────────────────────────────── @@ -55,7 +54,7 @@ * * A MISSING FIXTURE IS A FAILURE, NOT A SKIP. An earlier draft fetched live rows and skipped the * count assertions when offline — so on a fresh clone with no network, C3 (the assertion that - * reproduces the Driver's empty map) silently did not run and the build still went green. That is + * reproduces the reported empty map) silently did not run and the build still went green. That is * a gate that cannot fail, which is worse than no gate. Now every assertion runs everywhere. */ import { readFileSync, writeFileSync, existsSync, mkdirSync, rmSync, cpSync } from 'node:fs' @@ -166,7 +165,7 @@ const EXPECT = { // // WHY A FIXTURE AND NOT "fetch, else skip". The earlier version fetched live rows and SKIPPED the // count assertions when offline — which meant that on a fresh clone with no network, C3 (the -// assertion that actually reproduces the Driver's empty map) silently did not run and the build +// assertion that actually reproduces the reported empty map) silently did not run and the build // still went green. That is the "a gate that cannot fail is worse than no gate" shape: decorative // in exactly the situation where it matters. With the fixture committed, every assertion runs // everywhere, always, in ~1s. @@ -328,11 +327,11 @@ async function run(busPath) { } } - // ── C. the Driver's sequence, asserted on RESULT COUNTS ───────────────────────────────────── + // ── C. the reported sequence, asserted on RESULT COUNTS ─────────────────────────────────── if (!rows) { // NOT a skip. The committed fixture is what makes C/D run everywhere, so its absence is a // BROKEN GATE, not an excusable environment gap — silently skipping the assertions that - // reproduce the Driver's bug is how a gate becomes decorative. Only --offline with LIVE=1 + // reproduce the reported bug is how a gate becomes decorative. Only --offline with LIVE=1 // (an explicit opt-in to the live dataset with no cache) is allowed to degrade. if (process.env.LIVE && OFFLINE) notes.push(' SKIP C/D — LIVE=1 --offline with no cache (explicitly opted out of the fixture)') else bad('C/D count assertions could not run', `missing fixture ${FIXTURE} — regenerate with --refresh-fixture`) diff --git a/internal/check-facet-changes-map.mjs b/internal/check-facet-changes-map.mjs index 97e578b8e..ee9af37fb 100644 --- a/internal/check-facet-changes-map.mjs +++ b/internal/check-facet-changes-map.mjs @@ -5,14 +5,14 @@ * ★ WHAT IT ASSERTS, and why each assertion exists rather than the obvious one. * * THE OBVIOUS ASSERTION — "selecting a facet changes the map's feature COUNT" — PASSES TODAY AND - * PASSED WHILE THE DRIVER COULD SEE THE BUG. That is measured, not hypothetical: selecting + * PASSED WHILE THE BUG WAS PLAINLY VISIBLE. That is measured, not hypothetical: selecting * "Has Prayer" already narrowed rd-bubbles 2107 -> 689 features, disjoint from "Needs Prayer" * (1418), summing exactly to 2107 and round-tripping on clear. The filter was never broken. * What was broken is that every dot was painted the SAME flat orange ('circle-color' read back * off the live layer as the bare string '#ef6c00', not an expression), so a prayer question got - * an answer with no prayer information in it. The Driver's words are a COLOUR request: - * "when I sort by has prayer it needs to SHOW ME WHICH ONES HAVE PRAYER AND WHICH ONE… - * The dots are not changing based on that filter." + * an answer with no prayer information in it. The report was a COLOUR request: + * sorting by Has Prayer must SHOW WHICH ONES HAVE PRAYER AND WHICH DO NOT, and the dots + * were not changing with that filter. * So this gate asserts BOTH halves, because either one alone is a false pass: * 1. SET — the selection changes WHICH dots are on the map (count + identity). * 2. MEANING — the surviving dots all genuinely satisfy the selected level. @@ -20,14 +20,14 @@ * not a flat literal, and it reads the property the features actually carry. * * ★ ASSERTION 3 IS THE ONE THAT WOULD HAVE CAUGHT THE REPORTED BUG. Assertions 1 and 2 were - * already green when the Driver reported it. + * already green when it was reported. * * ★ IDENTITY, NOT JUST COUNT. The first five slugs are BYTE-IDENTICAL before and after, because * the filter removes from the tail of an alphabetical list. A gate that eyeballed the head of the * list, or that compared only counts, would report "looks the same" / "looks fine" for the wrong * reason. We compare SETS of slugs and require a strict, non-empty subset relation. * - * ★ WHY THE COLOUR CHECK IS CONDITIONAL. Orange (#ef6c00) is a Driver decision with a contrast + * ★ WHY THE COLOUR CHECK IS CONDITIONAL. Orange (#ef6c00) is a product decision with a contrast * analysis behind it and is correct with NO prayer filter active; the 3-tier prayer ramp is * correct WITH one. So the gate requires a literal before and an expression after — asserting the * SWITCH, which is the actual contract, rather than hardcoding either colour as always-right. @@ -96,7 +96,7 @@ const PATH_ = process.env.PROBE_PATH || '/' const TAB = process.env.PROBE_TAB || 'research-dashboard' const SELF_TEST = process.argv.includes('--self-test') // WHICH HALF OF THE FIX TO REVERT in --self-test. Default 'colour' reverts ONLY the paint, leaving -// the feature properties intact — that is the EXACT bug the Driver reported (a correct filter whose +// the feature properties intact — that is the EXACT bug reported (a correct filter whose // dots all look the same), and it isolates assertion 3, the one assertions 1-2 cannot catch. // 'props' strips peoplePraying instead; 'both' does the lot; 'frozen' blocks the source update // entirely, simulating "the filter never reaches the map" and negative-testing assertion 1. diff --git a/internal/check-facet-one-field.mjs b/internal/check-facet-one-field.mjs index 66004933d..3cb5b6078 100644 --- a/internal/check-facet-one-field.mjs +++ b/internal/check-facet-one-field.mjs @@ -8,8 +8,8 @@ * controls for one axis — a "People" dropdown beside an "Affinity Bloc" tree tier — which could * never recognise each other, because filteredRows byte-matches each key against its OWN accessor. * The tree stored affinity_bloc='A012' while the dropdown stored rop1='South Asian Peoples', and - * neither ever saw the other's selection. Driver, from behaviour alone: "there are duplicate - * affinity blocks, one called People, one called Affinity Bloc... they are the same thing." + * neither ever saw the other's selection. Seen from behaviour alone: there were duplicate + * affinity blocks, one called People and one called Affinity Bloc, and they are the same thing. * * ★ WHY THIS GATE ASSERTS ON OUTPUT VALUES AND NOT ON FIELD READS — THE MEASUREMENT THAT DECIDED IT. * The obvious gate is "no two facets may read the same r.". THAT GATE WOULD FAIL CORRECT diff --git a/internal/check-filter-width-stable.mjs b/internal/check-filter-width-stable.mjs index 087e0568b..b530057f5 100644 --- a/internal/check-filter-width-stable.mjs +++ b/internal/check-filter-width-stable.mjs @@ -7,7 +7,7 @@ * `{{ selectedOption.label }}` appeared in the label. Measured before the fix: the * row grew 960 → 1294px and individual triggers reached 240px. * - * ★ WHY IT IS NOT COSMETIC, in the Driver's own reasoning: the selections row with Clear All sits + * ★ WHY IT IS NOT COSMETIC: the selections row with Clear All sits * UNDERNEATH the filters. If a filter grows on selection, the row below re-flows and the whole group * stops being the aligned block he asked for. The stable width is what makes the centred stack hold * still — so this is a layout invariant, not a preference about widths. diff --git a/internal/check-fits-the-screen.mjs b/internal/check-fits-the-screen.mjs index b65cfdf3c..49017a7cf 100644 --- a/internal/check-fits-the-screen.mjs +++ b/internal/check-fits-the-screen.mjs @@ -4,10 +4,10 @@ * * ★ WHY THIS EXISTS (LL-the-user-found-three-bugs-my-gates-could-not-see, 2026-09-23). The suite * was 56/58 green, verify:gate1 13/13, verify:map-paint 11/11, verify:interop 4/4, 363 done cards - * — and the Driver opened the product and found FIVE real defects in one sitting, several caused + * — and opening the product found FIVE real defects in one sitting, several caused * by a change a gate had certified. NOT ONE was visible to any gate, because every gate up to this * one asserts STATE (does it mount, does it fetch, do the counts agree, does a canvas paint). The - * Driver assesses FITNESS FOR USE: is it slim, can I see it at once, does the wheel do what I + * product is judged on FITNESS FOR USE: is it slim, can I see it at once, does the wheel do what I * expect, does it tell me what I'm looking at. A suite of the first kind can be perfectly green * while the second kind fails completely. This gate encodes the second kind, as five clauses: * @@ -233,7 +233,7 @@ async function runComposite() { // ── CLAUSE A — ONE-VIEWPORT RULE ───────────────────────────────────────────────────────────── // .stl-sec (StackLayout's own section wrapper, library/layouts/StackLayout.vue:62) is the band - // the Driver actually sees stacked above the grid — measuring .rd-shell alone would miss a + // a reader actually sees stacked above the grid — measuring .rd-shell alone would miss a // regression in the SECTION wrapper around it (exactly what the self-test above pokes). // // ★ THE CAUSAL TEST, NOT A STATIC SIZE COMPARISON (rewritten 2026-09-23, BUG-DASHBOARD-BAND- @@ -290,8 +290,8 @@ async function runComposite() { record('A', TARGET, fitsViewport, detail) if (!fitsViewport) fail('a', `dashboard band is ${band.bandH}px, taller than the ${VIEWPORT_H}px viewport — it sizes to its own content instead of the screen. ` + detail) - // Driver, verbatim: "the dashboard rendering to the full height of the tree legend" is the - // bug — i.e. the band TRACKING the legend's content, not merely being numerically larger + // THE BUG: the dashboard rendering to the full height of the tree legend, i.e. the band + // TRACKING the legend's content, not merely being numerically larger // than it. Test that directly: expand every section (worst case, ~2100px of rows) and assert // the band does not grow past the viewport with it. GROWTH_TOLERANCE_PX is generous enough to // absorb a scrollbar-width reflow, tight enough that the original 2325px regression (a ~1400px diff --git a/internal/check-fixed-anchoring.mjs b/internal/check-fixed-anchoring.mjs index c1a4f41c4..8251a32e1 100644 --- a/internal/check-fixed-anchoring.mjs +++ b/internal/check-fixed-anchoring.mjs @@ -10,7 +10,7 @@ * component read: * STANDALONE research-dashboard ....... dLeft=0 dTop=4 (six of six) * INSIDE plugin-studio dashboard tab .. dLeft=256 dTop=111 (every one) - * The Driver reported the menu appearing "in a random spot further down to the right" for days. It + * The menu was reported for days as appearing in a random spot further down to the right. It * was never random. 256 is the rail width, 111 the header height. * * ★ WHY NO EXISTING GATE SAW IT, AND WHY THAT IS THE INTERESTING PART. A probe DID exist and it DID diff --git a/internal/check-hardcoded-english.mjs b/internal/check-hardcoded-english.mjs index 162f285fa..3393d6592 100644 --- a/internal/check-hardcoded-english.mjs +++ b/internal/check-hardcoded-english.mjs @@ -499,7 +499,7 @@ function scanBoundExpr(expr, file, attrName, out, line = 0, decls = '') { } // ★ dir="ltr" MARKS TEXT THAT IS MEANT TO STAY ENGLISH. gospel's plugins use it as the island -// marker for content the Driver ruled stays English (a BLUF, a source citation), so flagging it as a +// marker for content ruled to stay English (a BLUF, a source citation), so flagging it as a // leak would ask someone to "fix" a deliberate decision. Such findings are marked deliberate, listed // SEPARATELY, and excluded from the count a gate would fail on — visible, but not a defect. // Inherited down the subtree: a dir="ltr" wrapper covers everything inside it. @@ -964,7 +964,7 @@ if (composed.length) { for (const f of leaks) console.log(` ${f.kind.padEnd(16)} ${f.file.replace(/^.*plugin-designs\//, '')}:${f.line ?? 0} ${JSON.stringify(f.text).slice(0, 90)}`) if (deliberate.length) { // Listed so nobody wonders where they went, but NOT counted: dir="ltr" is the plugin's own marker - // for content the Driver ruled stays English. Asking someone to "fix" these would be asking them + // for content ruled to stay English. Asking someone to "fix" these would be asking them // to undo a decision. // PER ISLAND, LARGEST FIRST. A big island is not automatically wrong, but it is the shape an // over-broad one has, and a flat total cannot show it. Size is reported in LINES as well as diff --git a/internal/check-heartbeat-threshold.mjs b/internal/check-heartbeat-threshold.mjs index 566dba87a..65a8512e4 100644 --- a/internal/check-heartbeat-threshold.mjs +++ b/internal/check-heartbeat-threshold.mjs @@ -3,16 +3,14 @@ * check-heartbeat-threshold.mjs — THE HEARTBEAT THRESHOLD MUST COME FROM CONFIG, NOT A LITERAL. * * WHAT A HEARTBEAT ZONE IS. The top bin of the research-dashboard choropleth: the countries - * holding the most people groups. Driver: "the heartbeat zones are the most people groups in - * them... that's going to be 150 plus people groups in those heartbeat zones." + * holding the most people groups: 150 or more in each heartbeat zone. * * ★ THE DEFECT THIS CATCHES, AND WHY NOTHING ELSE COULD. The ramp's edges were a 5-stop array * literal — `upTo: 5, 20, 60, 150, Infinity` — sitting in DashboardMapPanel.vue. Those numbers are * not a property of choropleths; they are a property of THIS DATASET (~2000 people groups). Point * the dashboard at a 200-group dataset and every country falls in the bottom bin: the map renders - * uniformly pale and says nothing. Driver: "that filter of 150 ... should be a variable. It - * shouldn't be a static ... I need to be able to reuse this dashboard for other maps, other data - * sets." A dataset assumption wearing the costume of a constant. + * uniformly pale and says nothing. The 150 has to be a variable, not a static, so the dashboard can + * be reused for other maps and other datasets. A dataset assumption wearing the costume of a constant. * * That failure is INVISIBLE to every other gate in this repo. The code is correct, it parses, it * builds, it renders, it throws nothing, and the screenshot looks like a map. Only the MEANING is @@ -71,7 +69,7 @@ * ★ THE FIRST VERSION OF THIS GATE SHIPPED WITH [literal] ONLY, and its header said it had been * "negative-tested" — true of that case, misleading overall. Testing that THE FEATURE WORKS (a * configured threshold moves the edge) is NOT testing that THE REGRESSION IS CAUGHT (the default - * silently changing), and only the second protects the Driver. One negative test per regression + * silently changing), and only the second protects the shipped map. One negative test per regression * claimed. A gate that cannot fail is worse than no gate — this repo has shipped one. * * NOT COVERED, deliberately: this gate reasons about BIN ASSIGNMENT and LABELS only. It says @@ -93,8 +91,8 @@ const SELF_TEST = process.argv.includes('--self-test') // // ★ THE TOP LABEL IS MATCHED BY PROPERTY, NOT BY EQUALITY — a correction this gate earned on its // FIRST RUN. It originally demanded the top label equal exactly "150+", and immediately failed -// CORRECT code: the label reads "150+ · heartbeat zone", because naming the band in the Driver's -// own words is a requirement of this work, not a defect. An over-strict gate that fires on correct +// CORRECT code: the label reads "150+ · heartbeat zone", because naming the band in the +// specified words is a requirement of this work, not a defect. An over-strict gate that fires on correct // code gets switched off, and then the real regression walks through. So the assertion is the // property that actually matters: the top label must CARRY THE CURRENT THRESHOLD (so a moved edge // can never leave a stale number on the legend) and must NAME THE ZONE. Any prose around those is @@ -127,7 +125,7 @@ function makeResolver(mapCfg, srcOverride) { const body = srcOverride !== undefined ? srcOverride : resolverSource() // The slice calls the panel's `T(key, en)` (DashboardMapPanel.vue: `const T = (key, en) => tStatic(key) // || en`), which lives above the slice. Hand it the same shape answering in English, so the "names - // the zone" assertion still reads the Driver's words. + // the zone" assertion still reads the specified words. const fn = new Function('cfg', 'T', body + '\nreturn resolveBins;') return fn({ map: mapCfg }, (key, en) => en) } @@ -218,7 +216,7 @@ function run(srcOverride) { expectHistorical(def, 'A', 'With no config supplied the panel must fall back to EXACTLY the historical ramp.') // ── A2. THE SHIPPED CONFIGURATION RENDERS THE HISTORICAL RAMP ─────────────────────────────── - // ★ THIS IS THE ASSERTION THAT PROTECTS THE DRIVER, AND IT WAS MISSING. A alone proves the + // ★ THIS IS THE ASSERTION THAT PROTECTS THE SHIPPED MAP, AND IT WAS MISSING. A alone proves the // PANEL'S FALLBACK is intact — a strictly weaker property than "the map still looks the same", // because the running app resolves with dashboard.config.js's map.* layered ON TOP of that // fallback. Assertion F only checked that heartbeatThreshold was DECLARED, never what it was @@ -293,7 +291,7 @@ function run(srcOverride) { // ★ TWO CASES, BECAUSE THERE ARE TWO DISTINCT REGRESSIONS AND THEY ARE NOT THE SAME ASSERTION. // This gate originally shipped with case 1 only, and its header claimed it was "negative-tested". // That was true of case 1 and MISLEADING overall: case 2 — the one that actually protects the -// Driver's "today's map must not change" requirement — was unasserted, and a one-line edit to +// "today's map must not change" requirement — was unasserted, and a one-line edit to // dashboard.config.js changed the shipped ramp while the gate printed PASS. Verified by // reproducing it, not by reasoning about it. // diff --git a/internal/check-i18n-never-translated.mjs b/internal/check-i18n-never-translated.mjs index 4e3619995..c7f382204 100644 --- a/internal/check-i18n-never-translated.mjs +++ b/internal/check-i18n-never-translated.mjs @@ -65,7 +65,7 @@ const ALLOWED = new Map([ 'file-format name — "JSON" names the format the button downloads; the file extension is the same in every locale'], ['poster.json:dpi', 'unit symbol — "DPI" is how print resolution is labelled in every one of these locales\' print dialogs; kept as-is by project decision (the poster-strings landing)'], - // ── DRIVER-GATED, NOT RESOLVED ────────────────────────────────────────────── + // ── DECISION-PENDING, NOT RESOLVED ─────────────────────────────────────────── // ⚠ THESE ARE ALLOWED SO THE GATE CAN GO GREEN ON THE THINGS IT HAS ACTUALLY SETTLED, NOT // because the defect is fixed. "UUPGs" really is an English acronym wedged into an otherwise // localized row, in Arabic and Chinese included, while `population` beside it translates @@ -76,11 +76,11 @@ const ALLOWED = new Map([ // an acronym produced invented initialisms (PNA, UEVG, ННГ, GNA) with no source, and a wrong // term looks AUTHORITATIVE to a reader who cannot check it. // See DECIDE-UUPGS-COLUMN-HEADER-IS-ENGLISH-IN-ALL-ELEVEN-LOCALES, which carries the priced - // options. REMOVE THESE TWO LINES when the Driver rules — they are a bookmark, not a verdict. + // options. REMOVE THESE TWO LINES when the decision lands — they are a bookmark, not a verdict. ['legend.json:columns.upgs', - 'DRIVER-GATED: needs the field\'s term per locale, not an invented acronym — see DECIDE-UUPGS-COLUMN-HEADER'], + 'DECISION-PENDING: needs the field\'s term per locale, not an invented acronym — see DECIDE-UUPGS-COLUMN-HEADER'], ['prayerLaps.json:upgs', - 'DRIVER-GATED: same term as legend.json:columns.upgs — see DECIDE-UUPGS-COLUMN-HEADER'], + 'DECISION-PENDING: same term as legend.json:columns.upgs — see DECIDE-UUPGS-COLUMN-HEADER'], // ⚠ SETTLED, NOT A BOOKMARK — unlike the two above, this one is not waiting on a ruling; it IS // the ruling. "UPG 100" is the product's chosen NAME for the prayer list, so it is a brand // designation and correctly identical in every locale, exactly like a version number. The @@ -171,10 +171,10 @@ if (findings.length) { process.exit(1) } // ★ "ALLOWED" IS NOT ONE THING, and collapsing the two would make this gate lie. A proper noun -// is SETTLED — it is correct English forever. A DRIVER-GATED key is an OPEN DEFECT parked so the +// is SETTLED — it is correct English forever. A DECISION-PENDING key is an OPEN DEFECT parked so the // gate can still catch the next regression; calling it "identical on purpose" would turn a // deferral into a verdict, which is exactly how an open item stops being visible. -const deferred = allowedHits.filter((a) => /DRIVER-GATED/.test(a.why)) +const deferred = allowedHits.filter((a) => /DECISION-PENDING/.test(a.why)) if (deferred.length) { console.log(`\n ⚠ ${deferred.length} DEFERRED, NOT SETTLED — these ARE untranslated and are waiting on a ruling:`) for (const a of deferred) console.log(` ${a.id} = "${a.value.slice(0, 40)}"`) diff --git a/internal/check-i18n-stopped-scope.mjs b/internal/check-i18n-stopped-scope.mjs index 0e7bc7788..73d812c30 100644 --- a/internal/check-i18n-stopped-scope.mjs +++ b/internal/check-i18n-stopped-scope.mjs @@ -2,7 +2,7 @@ /** * check-i18n-stopped-scope.mjs — createAppI18n() must succeed while a STOPPED effect scope is current. * - * WHY (P0, the Driver's console, 2026-09-27): in Plugin Studio's gallery every tab after the first threw + * WHY (P0, seen in a live console, 2026-09-27): in Plugin Studio's gallery every tab after the first threw * "SyntaxError: Unexpected error" from createI18n inside createAppI18n. vue-i18n's createGlobal() runs in * scope.run() and throws UNEXPECTED_ERROR when that returns undefined; Vue 3.5 creates a new EffectScope * INACTIVE when the currently active one is stopped; and a custom element's connectedCallback -> diff --git a/internal/check-legend-export-reachable.mjs b/internal/check-legend-export-reachable.mjs index 2e0b7667a..90265b1da 100644 --- a/internal/check-legend-export-reachable.mjs +++ b/internal/check-legend-export-reachable.mjs @@ -7,8 +7,8 @@ // browse the UPG-100 lists and cannot export a packet or a poster. No error, nothing to click; the // failure is invisible rather than broken, which is why it survived. // -// The packet IS the product for this profile. The Driver: "print options at the top right of the -// legend... that's the only way that map would be usable." +// The packet IS the product for this profile, so the print options sit at the top right of the +// legend: without them that map is not usable. // // ⚠ THE CONTROL IS GATED ON A SELECTION. `v-if="SHOW_EXPORT_BUTTON && exportEnabled && selectedNode"` // — so a probe that merely loads the page finds nothing at EITHER width and concludes "no export diff --git a/internal/check-legend-info-localized.mjs b/internal/check-legend-info-localized.mjs index 509e8e910..a729090c9 100644 --- a/internal/check-legend-info-localized.mjs +++ b/internal/check-legend-info-localized.mjs @@ -14,9 +14,8 @@ // LABEL beside it went through the catalog. Measured 2026-09-24 on the served leaf: // ?lang=es changed 2 of 76 rendered strings ("POPULATION" -> "POBLACIÓN") and left all // three tabs AND all three info popovers in English. The mechanism worked; the strings -// were never catalogued. The Driver named this affordance specifically — "the tab itself -// gives you a little information button that will explain what a UPG-100 list is" — -// which is exactly the sentence a reader who does not read English cannot use. +// were never catalogued. This affordance was named specifically — the tab carries a small +// information button that explains what a UPG-100 list is — which is exactly the sentence a reader who does not read English cannot use. // // ⚠ IT RENDERS THE REAL PAGE. A catalog-only check cannot tell a shipped translation // from a dead one, and a reimplemented lookup cannot tell you the component actually diff --git a/internal/check-legend-matches-source.mjs b/internal/check-legend-matches-source.mjs index c556baf78..e7b753d0d 100644 --- a/internal/check-legend-matches-source.mjs +++ b/internal/check-legend-matches-source.mjs @@ -87,8 +87,8 @@ const EXPECT = { // and 5 have FOUR each. The "or Resources" clause is not literally true in the data, so that phrase // must never be repeated to a mission team as fact. // -// NOT asserted as a gate condition here, deliberately: which figure is OFFICIAL is a Driver decision -// (DRIVER-DECISIONS-gospel-resources.md, Decision 1), and a gate must not quietly canonise one answer +// NOT asserted as a gate condition here, deliberately: which figure is OFFICIAL is provisional, +// pending a product decision, and a gate must not quietly canonise one answer // to a question that is still open. Recorded so the next reader inherits the measurement, not the // task of re-deriving it. diff --git a/internal/check-legend-top-offset.mjs b/internal/check-legend-top-offset.mjs index 48f18b045..42140d365 100644 --- a/internal/check-legend-top-offset.mjs +++ b/internal/check-legend-top-offset.mjs @@ -2,12 +2,12 @@ /** * check-legend-top-offset — the legend only reserves room for a toolbar that is actually drawn. * - * THE DEFECT (Driver, 2026-09-28): on Simple Research's Regions and Languages tabs under MapLibre, the + * THE DEFECT (2026-09-28): on Simple Research's Regions and Languages tabs under MapLibre, the * search bar is gone but the legend does not rise into the vacated space. The other tabs are fine. * * ★ THE TWO-TAB SPLIT WAS A PREDICATE, NOT A COINCIDENCE. With no geocoder the legend rises to 14px * unless showsFlyTools() is true, and that returns true for exactly 'doxa-regions', 'language-family' - * and 'language-families' — the Driver's two tabs. It stops at 56px to avoid a MEASURED collision on + * and 'language-families' — the two reported tabs. It stops at 56px to avoid a MEASURED collision on * country-posters, where LegendTools renders at top:14px, the legend's own slot. * * ★ BUT showsFlyTools() DESCRIBES THE LEGEND TYPE, NOT WHETHER THE TOOLBAR EXISTS. Fly + Clusters are @@ -17,7 +17,7 @@ * of empty map on both tabs, no toolbar anywhere in the strip. * * So the offset must be keyed on the toolbar's PRESENCE. Keying it on the tab name would have fixed the - * Driver's two tabs and reintroduced the country-posters collision the moment the tools were shown. + * two reported tabs and reintroduced the country-posters collision the moment the tools were shown. * * Exit 0 pass · 1 fail. */ @@ -42,7 +42,7 @@ if (!m) { } if (!/showLegendTools/.test(body)) { fails.push('legendTopVar does not consult showLegendTools, so it reserves space for a toolbar that\n' - + ' may never be drawn. That is the Driver-reported dead band on the Regions and Languages\n' + + ' may never be drawn. That is the reported dead band on the Regions and Languages\n' + ' tabs: the composite passes legendTools:false and the 56px held a slot for nothing.\n' + ' Key the offset on the toolbar\'s PRESENCE, not on the legend type alone.') } diff --git a/internal/check-list-selection.mjs b/internal/check-list-selection.mjs index f56ade3ef..e3514afc1 100644 --- a/internal/check-list-selection.mjs +++ b/internal/check-list-selection.mjs @@ -22,8 +22,8 @@ import { leavesOf, zoneIdsIn, withUnassigned, selectedId, UNASSIGNED_ID } from ' // groupings.json now live in data/tables/ — the shared asset pool the tree copies into // public/dx-maps/assets/tables/ — because gospel's legend renders IN THE BROWSER and needs them at // runtime; a build-time import path would not reach the bundle. admin-to-list.json stays in the -// plugin until the Driver rules row 87 (the "zones fold" regeneration), so it is read from the old -// root. Collapsing these to one constant silently breaks whichever file is not where you pointed. +// plugin, provisional, pending a product decision on the "zones fold" regeneration, so it is read +// from the old root. Collapsing these to one constant silently breaks whichever file is not where you pointed. const REPO = join(dirname(fileURLToPath(import.meta.url)), '..') const TABLES = join(REPO, 'data', 'tables') const PLUGIN_DATA = join(REPO, 'plugin-designs', 'my-upg-100-list', 'data') @@ -122,9 +122,9 @@ ok(withUnassigned(EMPTYZONE, ['z9']).length === EMPTYZONE.length, // evidence lives — after catching the identical shape in their own work. // // This does NOT resolve the three disagreeing lists (33 in zone-regions, 12 reachable via -// admin-to-list, 14 in groupings, disagreeing in BOTH directions). That is a data-ownership ruling -// for upg100 and the Driver, and picking a winner here would be exactly the silent join we have both -// refused. It only compares the region tree's own source against the joinable set and RECORDS the +// admin-to-list, 14 in groupings, disagreeing in BOTH directions). That is a data-ownership question, +// provisional, pending a product decision, and picking a winner here would be exactly the silent join +// this repo refuses. It only compares the region tree's own source against the joinable set and RECORDS the // difference, so the disagreement cannot drift without someone being told. const regionOf = readJson('zone-regions.json') // the region tree's source: zone id -> region const adminToList = readJson('admin-to-list.json') // admin name -> zone id; its VALUES are joinable diff --git a/internal/check-manifest-covers-discovery.mjs b/internal/check-manifest-covers-discovery.mjs index ed8b63293..4bd1c31be 100644 --- a/internal/check-manifest-covers-discovery.mjs +++ b/internal/check-manifest-covers-discovery.mjs @@ -8,8 +8,8 @@ * discovered but MISSING .... 1 key-cities * in manifest, not real ..... 1 template-bundle * `key-cities` had its compiled key-cities.js on disk but ZERO profile leaf directories, so its four - * profiles vanished from manifest.json and from the studio's tab list. The Driver was reviewing a tree - * that silently omitted a whole plugin. + * profiles vanished from manifest.json and from the studio's tab list. A tree under review + * silently omitted a whole plugin. * * ★ WHY EVERY EXISTING GATE PASSED — this is the interesting part, and the reason for a new file: * - the settled-tree LEAF FLOOR counts index.html recursively (44, floor 40). A bundle that loses diff --git a/internal/check-map-menu-anchor.mjs b/internal/check-map-menu-anchor.mjs index 77bec6806..b25a89aab 100644 --- a/internal/check-map-menu-anchor.mjs +++ b/internal/check-map-menu-anchor.mjs @@ -3,7 +3,7 @@ * check-map-menu-anchor — a map control menu must always have an anchor, so it can never fall to its * static position off the edge of the page. * - * THE DEFECT (Driver, 2026-09-28, mobile): the share/embed menu opens OFF-SCREEN to the right on Cities + * THE DEFECT (2026-09-28, mobile): the share/embed menu opens OFF-SCREEN to the right on Cities * with Internet and Gospel Resources, while Simple Research and Prayer Progress are correct. * * ★ THE SPLIT WAS AN ALLOWLIST, NOT A PLUGIN DIFFERENCE. MapControlMenu resolved its containing area @@ -14,8 +14,8 @@ * that happened to be named in a string literal in another component. * * MEASURED: cities-internet, gospel-resources, key-cities and upg-neighbor carry NO map-area class and - * no data-map-area. The Driver reported two; the allowlist made it four. A gate that only checked the - * two he named would have passed the other two. + * no data-map-area. Two were reported; the allowlist made it four. A gate that only checked the + * two reported would have passed the other two. * * SO THIS ASSERTS THE PROPERTY, NOT THE LIST: whatever a plugin calls its map area, the menu resolves * SOMETHING to anchor against. The fallback is the toolbar's own offsetParent — the containing block the @@ -45,7 +45,7 @@ if (!m) { + ` ${expr.trim()}\n` + ' A plugin whose map area is not named in that list gets a null area, place() returns an\n' + ' EMPTY style, and the menu renders at its static position — off the page. That is the\n' - + ' Driver-reported mobile bug, and it is decided by a string literal rather than by geometry.') + + ' reported mobile bug, and it is decided by a string literal rather than by geometry.') } } diff --git a/internal/check-nav-reachable-mobile.mjs b/internal/check-nav-reachable-mobile.mjs index fdb4c8723..f109edf2f 100644 --- a/internal/check-nav-reachable-mobile.mjs +++ b/internal/check-nav-reachable-mobile.mjs @@ -4,7 +4,7 @@ * * THE BUG THIS EXISTS TO PREVENT (real, found 2026-09-22 by resizing the cap-5 SPA to 414px). * VerticalTabsLayout renders its drawer toggle inside `
`. The cap-5 DX-Maps - * SPA runs header-OFF by default (the Driver's no-stacked-headers rule for embedding). At mobile + * SPA runs header-OFF by default (the no-stacked-headers rule for embedding). At mobile * width the rail becomes an off-canvas drawer at translateX(-100%) with navOpen=false. So: the * drawer was off screen, the header holding the toggle did not exist, and the only other control * (.vtl-collapse) lives INSIDE the drawer — measured off screen at x:-244. diff --git a/internal/check-no-orphan-gates.mjs b/internal/check-no-orphan-gates.mjs index 9499add44..da418e029 100644 --- a/internal/check-no-orphan-gates.mjs +++ b/internal/check-no-orphan-gates.mjs @@ -3,7 +3,7 @@ * check-no-orphan-gates.mjs — a gate that nothing can run is not a gate. * * THE DEFECT THIS CATCHES. `internal/verify-shell-scroll.mjs` was written, negative-tested, and - * proved a real Driver-reported bug with hard numbers (2586px of mounted grid, a real wheel gesture + * proved a real reported bug with hard numbers (2586px of mounted grid, a real wheel gesture * moving 0px). Then it sat unreachable: no `package.json` entry, no importer. It would never have * run again. The repo has already carded this once — * BUILD-BROWSER-GATES-WERE-ALL-ORPHANS-ONE-COMMAND-RUNS-THEM — and it recurred anyway, because diff --git a/internal/check-no-public-binds.mjs b/internal/check-no-public-binds.mjs index 457b233cb..232f967ec 100644 --- a/internal/check-no-public-binds.mjs +++ b/internal/check-no-public-binds.mjs @@ -14,10 +14,9 @@ * ★ WHY THIS IS THE INTERESTING CLASS. The standing rule "keep the box closed" lived in prose, in * instructions to an agent. The actual behaviour lived in a FLAG in package.json. Prose cannot * constrain a flag. The rule was never violated by a decision — it was violated by a default that - * nobody re-read, and it stayed violated because nothing ever asked the question out loud. The - * Driver stated it plainly: "we don't need any open ports on this box because you push your changes - * to Forgejo and I pull them from my laptop... use Playwright for yourself internally for testing, - * not for public access." + * nobody re-read, and it stayed violated because nothing ever asked the question out loud. It was + * stated plainly: this box needs no open ports, because changes are pushed to Forgejo and pulled + * onto a laptop; Playwright is for internal testing, not for public access. * * Loopback is sufficient for the entire test suite: verify-browser-all, check:a11y-button-names, * check:nav-reachable and smoke:share-all all already default to 127.0.0.1. The wide bind bought diff --git a/internal/check-one-scroll-container.mjs b/internal/check-one-scroll-container.mjs index d45ed4ae5..47a75dd77 100644 --- a/internal/check-one-scroll-container.mjs +++ b/internal/check-one-scroll-container.mjs @@ -3,7 +3,7 @@ * check-one-scroll-container — a plugin pinned into the gallery's pane must not assert a height FLOOR * the pane cannot honour. * - * THE DEFECT THIS EXISTS FOR (Driver, 2026-09-28, "one of my least favorite bugs"): on DX Life's + * THE DEFECT THIS EXISTS FOR (2026-09-28, a much-disliked bug): on DX Life's * research page a capability-4 plugin with tabs at the top had an EXTRA element-level scrollbar, and * scrolling it scrolled the TAB HEADER out of view — on top of the plugin's own content scroll. * diff --git a/internal/check-optional-t-equivalence.mjs b/internal/check-optional-t-equivalence.mjs index 32a95640e..41aeb061a 100644 --- a/internal/check-optional-t-equivalence.mjs +++ b/internal/check-optional-t-equivalence.mjs @@ -141,8 +141,8 @@ const SITES = [ // wave 3d — all-people-groups. Treated as UNOWNED (studio agreed), so the conservative reading wins: // its inline EN map stays the fallback rather than switching to the catalogue, because nobody is // available to decide that this bundle should start honouring the locale on a bare host -- THEN - // dx-shepherd RULED the locale-honouring fallback everywhere (2026-09-27; the Driver's goal (d), a - // bare-host embed with ?lang=ar must render Arabic, now the embed contract in COMMON.md). So it takes + // the locale-honouring fallback was RULED for everywhere (2026-09-27; the goal: a bare-host + // embed with ?lang=ar must render Arabic, now the embed contract in COMMON.md). So it takes // the catalogue default, its duplicate EN map is deleted, and section 9 keeps the ruling's PRECONDITION // true rather than measured once. // First site on the {t, te, locale} form: it needs locale for toLocaleString. diff --git a/internal/check-packet-render.mjs b/internal/check-packet-render.mjs index dfbb8a2f2..43317df6e 100644 --- a/internal/check-packet-render.mjs +++ b/internal/check-packet-render.mjs @@ -20,7 +20,7 @@ // black with no error of any kind. Asserted as a WHOLE-MAP property, because the first // attempt at this check tested one hand-picked (the one just repaired) and went // green while 647 others were still black. -// 3. Content the Driver specified explicitly: Mark 5:1-20 in full, 12 wheel segments, +// 3. Content specified explicitly: Mark 5:1-20 in full, 12 wheel segments, // the prayer rhythms, and exactly two minimal metacamp.org attributions. // // Usage: node internal/check-packet-render.mjs [path/to/packet.html] @@ -167,8 +167,8 @@ const translated = lang !== 'en' // ── THE LARGEST BLOCK OF READER-FACING TEXT, REPORTED SEPARATELY ──────────── // point4_passage is Mark 5:1-20 in full — 2,141 characters, by far the longest string -// in the packet and the one the Driver singled out ("prayer point number four is -// actually read the word"). It is ABSENT from all ten non-English blocks, so every +// in the packet and the one singled out: prayer point four is reading the word +// itself. It is ABSENT from all ten non-English blocks, so every // translated packet prints its longest passage in English. The per-locale "19 strings // translated" headline looked healthy while this was true, because 19 short keys and // one 2,141-character one count the same. @@ -202,7 +202,7 @@ const r = await page.evaluate(() => { // gate reporting "map: palette resolves, not black — PASS, map painted", because the // query silently retargeted to the PRAYER WHEEL's svg two sheets later. The wheel has no // CSS variables to leave unresolved and no black fills, so both checks passed vacuously - // while page 1 — "the map one-pager", the first line of the Driver's packet spec — was + // while page 1 — the map one-pager, the first line of the packet spec — was // blank. The sheet count stayed 8 because the empty sheet still exists. // The packet's page order is the product spec and does not vary: sheet 0 IS the map page. const sheet0 = document.querySelector('.sheet') @@ -369,7 +369,7 @@ const r = await page.evaluate(() => { // "12 segments, 11/11 rhythms, content intact — PASS" on a prayer wheel that was a // twelve-colour pie chart with no words on it. Both numbers stayed true: the // segments are elements and survive, and the words were still on the points - // page. The Driver's spec names the wheel as one of the packet's four sections. + // page. The spec names the wheel as one of the packet's four sections. // // COUNT ELEMENTS, NOT DISTINCT WORDS. `order` renders 12 segments from 12 keys, but // `praise` and `praise_end` collapse to the same word in English (which is why the @@ -517,15 +517,15 @@ if (r.wheelLabels !== WHEEL_LABELS) { + 'and cannot see an unlabelled wheel') } if (r.rhythms !== r.rhythmsTotal) fails.push(`only ${r.rhythms}/${r.rhythmsTotal} prayer rhythms present`) -// Mark 5:1-20 in full is a Driver requirement for point 4: "it actually lists out the -// full scripture, because prayer point number four is actually read the word." The +// Mark 5:1-20 in full is a requirement for point 4: it lists out the full scripture, +// because prayer point four is reading the word itself. The // English passage is 2,141 chars; 1,200 is a floor that no truncation or placeholder // survives while leaving room for languages that render the same text more compactly // (zh is typically ~40% shorter in characters). const MARK5_MIN = 1200 if (r.mark5Len < MARK5_MIN) { fails.push(r.mark5Len === 0 - ? 'Mark 5:1-20 is NOT printed in full (Driver requirement for point 4) — no .p4-passage block' + ? 'Mark 5:1-20 is NOT printed in full (a requirement for point 4) — no .p4-passage block' : `Mark 5:1-20 looks truncated: ${r.mark5Len} chars, expected at least ${MARK5_MIN}`) } // THE PRODUCT IS NAMED FOR THIS NUMBER. The page header says "12 Prayer Points" in every @@ -673,7 +673,7 @@ if (!boxes.length) { // this assertion exists to catch SILENTLY DROPPED PEOPLE GROUPS, and a ±1 tolerance is exactly the // slack a lost list page would hide in. So the funnel is DETECTED (.funnel-title) and added as a // known term, leaving the list-page arithmetic as strict as it was. -// ⚠ AND THE SAME FOR THE LIFE-CALENDAR PAGES (2026-09-27, Driver's page order). Two more structural +// ⚠ AND THE SAME FOR THE LIFE-CALENDAR PAGES (2026-09-27, the specified page order). Two more structural // sheets — a 100-year life in weeks, then the SAME grid shaded by the evangelical share of these // groups' population — so they are DETECTED and added as known terms for exactly the reason the // funnel was, and for the reason stated above: a tolerance here would hide a dropped list page. @@ -687,7 +687,7 @@ const expectedSheets = 1 + lifeSheets + funnelSheets + Math.ceil(r.cards / PER_P // ── THE LIFE-CALENDAR PAGES, asserted rather than merely counted ────────────────────────────────── // A page that EXISTS is not a page that is RIGHT: an empty grid, a grid of the wrong size, or a // christian page whose shading silently fell to zero would all still be one sheet. 5,200 is the -// Driver's own arithmetic (100 years x 52 weeks) and is the only number here that may not drift. +// spec's own arithmetic (100 years x 52 weeks) and is the only number here that may not drift. if (r.lifeSheets) { const EXPECT = 5200 const perGrid = r.lifeCells / (r.lifeSheets + (r.christianSheets || 0)) @@ -698,8 +698,8 @@ if (r.lifeSheets) { } // ⚠ AND THE SHADE MUST BE SCATTERED, NOT STACKED — the assertion that would have caught what three gates // and a passing suite did not. rega's contact sheet (2026-09-28) showed page 3 reading as ONE SOLID BAR: -// 32 contiguous cells fill most of row 1 of 52, so the page said "a big green block" where the Driver's -// intent is "32 boxes lost in 5,200". Every assertion passed, because they all measured the COUNT. +// 32 contiguous cells fill most of row 1 of 52, so the page said "a big green block" where the +// intent is 32 boxes lost in 5,200. Every assertion passed, because they all measured the COUNT. // Half the grid height is a deliberately loose floor: a genuine scatter of even a few cells spans most of // the page (measured: 32 cells over 26 rows, 95% of the height), and a bar spans ~1%. Anything in between // is worth a human look. diff --git a/internal/check-packet-strings-parity.mjs b/internal/check-packet-strings-parity.mjs index 916f644be..83ed5b00e 100644 --- a/internal/check-packet-strings-parity.mjs +++ b/internal/check-packet-strings-parity.mjs @@ -55,7 +55,7 @@ const DECLARED_ABSENT = { // wearing more confidence. This entry shrinks as each locale's text is cited, not as a batch. point4_passage: 'Mark 5:1-20 — awaiting a CITED public-domain translation for hi/zh/pt/it/ro', point4_passage_credit: 'the attribution line for the passage above', - // ── The Driver's new packet pages, 2026-09-27: a 100-year life calendar, the same grid shaded by + // ── The new packet pages, 2026-09-27: a 100-year life calendar, the same grid shaded by // the evangelical share of these groups' population, and the funnel's equation sidebar + tip. // ENGLISH-ONLY ON PURPOSE, and declared rather than back-filled: English text copied into ten // locale blocks would make them read as TRANSLATED to this gate and to a reader, which is worse diff --git a/internal/check-poster-action-print.mjs b/internal/check-poster-action-print.mjs index 191b90315..e90506301 100644 --- a/internal/check-poster-action-print.mjs +++ b/internal/check-poster-action-print.mjs @@ -2,7 +2,7 @@ /** * check-poster-action-print — a poster button prints unless its consumer says why it downloads. Headless. * - * Driver rule 2026-09-28: an export-poster button opens the PRINT DIALOG with a preview, never a direct + * The rule since 2026-09-28: an export-poster button opens the PRINT DIALOG with a preview, never a direct * download. PosterWall defaults posterAction to 'print'; this asserts that (a) the default stays 'print', * and (b) any consumer passing posterAction 'download' has a `posterAction-download:` comment with its * reason within the 3 lines above. diff --git a/internal/check-poster-card-fits.mjs b/internal/check-poster-card-fits.mjs index 7f74e14b1..1a1aae019 100644 --- a/internal/check-poster-card-fits.mjs +++ b/internal/check-poster-card-fits.mjs @@ -37,8 +37,8 @@ const LEAF = process.argv[2] || DEFAULT_LEAF const WIDTHS = (process.env.CARD_FIT_WIDTH || '390,768,1024,1440,1920') .split(',').map((n) => Number(n.trim())).filter(Boolean) -// ★ AND SWEEP LOCALES, for exactly the same reason the widths are swept. The Driver's requirement -// was "full words visible AND support localization"; this gate only ever ran in English, which is +// ★ AND SWEEP LOCALES, for exactly the same reason the widths are swept. The requirement was full +// words visible AND localization supported; this gate only ever ran in English, which is // the shortest of the eleven. MEASURED 2026-09-24 at 1440px, the three print labels: // en Prayer List 76px · Card Deck 72px · Poster Map 79px // ro Listă de rugăciune 122px · Pachet de cartonașe 133px · Harta afișului 92px (+75%) @@ -217,13 +217,13 @@ async function measure(width, lang) { worst = Math.max(worst, Math.round(Math.max(rb.right - b.right, b.left - rb.left))) } // ⚠ THE VERTICAL AXIS TOO — this measured only left/right, which is exactly how it passed a - // driver-visible regression. Fixing the horizontal overflow with flex-wrap grew the row + // visible regression. Fixing the horizontal overflow with flex-wrap grew the row // 35px -> 78px, and because it sits at bottom:-14px the extra height pushed its TOP from // 216px up to 173px in a 238px card: over the preview image and the card's outline. // Horizontal clean, card visibly broken, gate green. // COUNT THE PREVIEW, do not merely guard on it. An if-guard protects this loop from a // placeholder card — and also means a card with NO preview passes the over-preview assertion - // perfectly. The driver reported BOTH a missing-previews symptom AND the overlap; + // perfectly. BOTH a missing-previews symptom AND the overlap were reported; // measuring only the overlap leaves the first unasserted. // NOTE: no backticks in this block — it lives inside a JS template literal. const img = c.querySelector('img') @@ -252,7 +252,7 @@ async function measure(width, lang) { worstY = Math.max(worstY, Math.round(ib.bottom - rb.top)) } } - // ★ A STICKER STRADDLES THE EDGE IT TAPES (Driver 2026-09-25, the sticker/banner brief). + // ★ A STICKER STRADDLES THE EDGE IT TAPES (2026-09-25, the sticker/banner brief). // The card is a BANNER displaying a map; each sticker sits centred on a banner edge, part // on the banner's own white space and part overhanging. Three things were each true while // this gate was green, so all three are now asserted: @@ -264,8 +264,8 @@ async function measure(width, lang) { if (frame) { const fb = frame.getBoundingClientRect() // STRADDLE: some of the sticker on the banner, some off it. Requiring a near-even split - // would encode a ratio the Driver explicitly left open ("probably an equal or more - // overlap"); requiring BOTH sides to be non-trivial is the property actually stated. + // would encode a ratio the brief explicitly left open (probably an equal or larger + // overlap); requiring BOTH sides to be non-trivial is the property actually stated. const onBanner = Math.round(fb.bottom - rb.top) const offBanner = Math.round(rb.bottom - fb.bottom) if (onBanner < 4 || offBanner < 4) { @@ -274,9 +274,9 @@ async function measure(width, lang) { worstTape = Math.abs(d) > Math.abs(worstTape) ? d : worstTape } } - // ★ NO NATIVE DROPDOWN IN THE DEFAULT ROW (same ruling). The Driver's reason is not - // cosmetic: "I don't want to add the dropdown for the card because it makes it hard for - // others to have dropdowns too" — a here + // collides with the host page's own // selects. The size picker is a disclosure, revealed by the Card Deck button. A