doxa-maps/internal/check-provide-shadowing.mjs
Doxa Maps d314c44043 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.
2026-09-29 05:26:25 +00:00

102 lines
5.3 KiB
JavaScript

#!/usr/bin/env node
/**
* check-provide-shadowing — a nested custom element keeps its OWN pinia, i18n and profileModules, and
* says so deliberately instead of tripping Vue's overwrite warning 24 times.
*
* THE DEFECT (seen in a live console, 2026-09-28): 24 Vue warnings —
* 'App already provides property with key "profileModules" / "appI18n" / "Symbol(pinia)" inherited
* from its parent element. It will be overwritten with the new value.'
* eight of each, from a composite mounting child custom elements.
*
* ★ THE OVERWRITE IS THE POINT, WHICH IS WHY SILENCING IT WOULD HAVE BEEN WRONG AND FIXING IT BY NOT
* PROVIDING WOULD HAVE BEEN WORSE. `profileModules` is the plugin's own .vue glob — a child rendering
* its parent's components is a different bug; pinia is per-instance so two embeds never bleed state;
* and the i18n instance is the one ProfileLoader drives from THIS element's profile-config, which is
* the whole of the permanently-English fix landed the same day. Inheriting any of the three would be
* the regression.
*
* So this asserts BOTH halves: the child still ends up with its OWN value (the fix is not undone), and
* the inherited chain is left intact afterwards (the parent's OTHER values still resolve).
*
* Exercised against the REAL exported helpers, not a copy — a copied helper would pass while the
* shipped one rotted. Exit 0 pass · 1 fail.
*/
import { resolve, dirname } from 'node:path'
import { fileURLToPath } from 'node:url'
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..')
const { provideOwn, withoutInheritedProvides } =
await import(resolve(ROOT, 'library/elements/provide-own.js'))
const fails = []
const ok = (what, cond, d = '') => { if (!cond) fails.push(`${what}${d ? `\n ${d}` : ''}`) }
// A Vue-shaped app: provides inherits from the parent ELEMENT's provides, and app.provide() warns
// exactly as runtime-core does when the key is already reachable.
const makeApp = (parentProvides = {}) => {
const provides = Object.create(parentProvides)
const warnings = []
return {
warnings,
_context: { provides },
provide(key, value) {
if (key in provides) warnings.push(String(key))
provides[key] = value
},
}
}
// ── provideOwn: an inherited key is shadowed WITHOUT a warning ───────────────────────────────────
{
const parent = { appI18n: 'PARENT-I18N', somethingElse: 'keep-me' }
const app = makeApp(parent)
provideOwn(app, 'appI18n', 'MY-I18N')
ok('the child ends up with its OWN i18n', app._context.provides.appI18n === 'MY-I18N')
ok('...as an OWN property, not the parent\'s', Object.hasOwn(app._context.provides, 'appI18n'))
ok('...without a warning, because the shadow is deliberate', app.warnings.length === 0,
`warned about: ${app.warnings.join(', ')}`)
ok('the parent\'s OTHER values still resolve', app._context.provides.somethingElse === 'keep-me')
ok('and the parent is NOT mutated', parent.appI18n === 'PARENT-I18N')
}
// ── provideOwn: an ABSENT key takes the ordinary public path ─────────────────────────────────────
{
const app = makeApp({})
provideOwn(app, 'profileModules', { a: 1 })
ok('a key nobody provided is set through the public API', app._context.provides.profileModules.a === 1)
ok('...and still does not warn, because there was nothing to overwrite', app.warnings.length === 0)
}
// ── withoutInheritedProvides: for a key we cannot name (pinia's symbol) ──────────────────────────
{
const SYM = Symbol('pinia')
const parent = { [SYM]: 'PARENT-PINIA', other: 'x' }
const app = makeApp(parent)
withoutInheritedProvides(app, () => app.provide(SYM, 'MY-PINIA'))
ok('the child ends up with its own pinia', app._context.provides[SYM] === 'MY-PINIA')
ok('...with no warning', app.warnings.length === 0, `warned about: ${app.warnings.map(String).join(', ')}`)
ok('★ the inherited chain is RESTORED — the parent\'s other values resolve again',
app._context.provides.other === 'x')
ok('the parent is not mutated', parent[SYM] === 'PARENT-PINIA')
}
// ── and it restores the chain even when the callback throws ──────────────────────────────────────
{
const parent = { other: 'x' }
const app = makeApp(parent)
try { withoutInheritedProvides(app, () => { throw new Error('install blew up') }) } catch { /* expected */ }
ok('a throwing install still leaves the element able to see its parent',
app._context.provides.other === 'x')
}
// ── the control: the naive call MUST warn, or these assertions prove nothing ─────────────────────
{
const app = makeApp({ appI18n: 'PARENT' })
app.provide('appI18n', 'MINE')
ok('a plain app.provide() over an inherited key DOES warn (the behaviour being avoided)',
app.warnings.length === 1)
}
if (fails.length) {
console.error('PROVIDE-SHADOWING: FAIL')
for (const f of fails) console.error(` ✗ ${f}`)
process.exit(1)
}
console.log('PROVIDE-SHADOWING: PASS — a nested element keeps its own pinia, i18n and profileModules with no '
+ 'overwrite warning, the parent\'s other provides still resolve, and the chain is restored even if install throws.')