You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Nothing in the test suite reads a CSS custom property name. That matters
because an unresolved var(--x) is not an error anywhere in the pipeline:
the browser drops the declaration, the property falls back to its
initial/inherited value, docusaurus build succeeds, and the element simply
renders unstyled. A single-character typo in a token name ships green.
Under src/ today (verified at 00b44df, node v26.8.2, 2026-09-20):
quantity
count
stylesheets (src/**/*.css)
10
distinct custom properties declared in CSS
15
distinct var() references
15
custom properties declared from JS inline styles
1
var() references carrying a fallback
0
Every reference resolves today, so this is a guard for a clean invariant,
not a bug report — the whole contract is currently unguarded and the failure
mode is silent.
Two details make a naive scan wrong, and both are handled:
--bar-width is declared in JavaScript, not CSS. src/components/MetricsDashboard/index.js:52 sets it as a style-object key
(style={{ '--bar-width': ... }}) and src/components/MetricsDashboard/styles.module.css:16 reads it. A
stylesheet-only scan reports a false positive here.
--ifm-* / --docusaurus-* are vendor-provided by Infima. 8 distinct
vendor tokens are referenced without a local declaration, legitimately.
Why existing gates miss it
docusaurus build never resolves custom-property names; an undeclared one
is valid CSS.
onBrokenLinks: 'throw' governs page routes.
tests/validate-button-contrast.test.mjs is the only CSS-touching test. It
drives scripts/validate-button-contrast.mjs, which extracts --cncf-button-background{,-hover}hex literals to check WCAG contrast.
It never looks at whether a var() resolves, and never reads any other
token.
check:format / check:spelling do not model cross-file name resolution.
Disjointness from open PRs
No open PR reads CSS custom properties. Specifically:
Add tests/css-variables.test.mjs — one test-only file, no production
change, no new dependency, green on main. Five assertions:
extraction is non-vacuous (stylesheets, declarations and references all
non-empty), so a regression in the regexes cannot silently pass the rest;
every var(--x) resolves to a CSS declaration under src/, a JS
inline-style declaration, or the vendor namespace;
the vendor allowlist does bounded work — it may never swallow a --cncf-* token;
every declared --cncf-* token is read by at least one var() (orphan
detection, the reverse direction);
every --cncf-* token themed on :root is redeclared under [data-theme='dark'], so a new brand token cannot be added light-only and
silently inherit the wrong value in dark mode.
Assertion 5 has to match :root by substring: the selector in custom.css
carries a :not(#\#):not(#\#) specificity hack.
Verification
Mutation-tested — each mutation is caught by the intended assertion, and no
assertion is redundant:
mutation
caught by
typo var(--cncf-button-text) -> --cncf-button-txt
2, 3, 4
delete --cncf-button-text from the [data-theme='dark'] block
5
inline a var(--cncf-button-background-hover) reference to its literal
4
rename the '--bar-width' inline-style key in MetricsDashboard/index.js
Unit: node --test --experimental-test-coverage tests/ at 00b44df,
node v26.8.2, run locally 2026-09-20 -> 55 tests, 55 pass. No entry in the
coverage report corresponds to any file that reads a custom-property name.
End-to-end: unobtainable, not absent. The repo declares no playwright/cypress/puppeteer, and CI publishes no coverage artifact
(see [quality] CI publishes no coverage evidence, so coverage findings cannot be verified #186). No claim is therefore made about e2e coverage of this path — a
browser suite is exactly what would catch a silently unstyled element.
Priority
Impact: medium — 15 tokens across 10 stylesheets with no guard; the failure mode ships green and is invisible until a human looks at the rendered page
Effort: low — one test-only file, no production change, no new dependency
Finding
Nothing in the test suite reads a CSS custom property name. That matters
because an unresolved
var(--x)is not an error anywhere in the pipeline:the browser drops the declaration, the property falls back to its
initial/inherited value,
docusaurus buildsucceeds, and the element simplyrenders unstyled. A single-character typo in a token name ships green.
Under
src/today (verified at00b44df, node v26.8.2, 2026-09-20):src/**/*.css)var()referencesvar()references carrying a fallbackEvery reference resolves today, so this is a guard for a clean invariant,
not a bug report — the whole contract is currently unguarded and the failure
mode is silent.
Two details make a naive scan wrong, and both are handled:
--bar-widthis declared in JavaScript, not CSS.src/components/MetricsDashboard/index.js:52sets it as a style-object key(
style={{ '--bar-width': ... }}) andsrc/components/MetricsDashboard/styles.module.css:16reads it. Astylesheet-only scan reports a false positive here.
--ifm-*/--docusaurus-*are vendor-provided by Infima. 8 distinctvendor tokens are referenced without a local declaration, legitimately.
Why existing gates miss it
docusaurus buildnever resolves custom-property names; an undeclared oneis valid CSS.
onBrokenLinks: 'throw'governs page routes.tests/validate-button-contrast.test.mjsis the only CSS-touching test. Itdrives
scripts/validate-button-contrast.mjs, which extracts--cncf-button-background{,-hover}hex literals to check WCAG contrast.It never looks at whether a
var()resolves, and never reads any othertoken.
check:format/check:spellingdo not model cross-file name resolution.Disjointness from open PRs
No open PR reads CSS custom properties. Specifically:
tests/static-assets.test.mjs) —/imgreference paths, not token names.tests/jsx-link-image.test.mjs) — JSXhref/srchygiene.filterArchitectures,useFocusTrap; no CSS.data/*.json.scripts/.url()references incustom.cssagainststatic/fonts/; issue [quality] CSS Module class-name contract is untested; src/theme/Footer references an undeclared .iconLink and ships an orphan .orgText #319 claims*.module.cssclass names. Neitheris a custom property, and neither has a PR. This issue's test file
(
tests/css-variables.test.mjs) collides with neither of theirs.Recommendation
Add
tests/css-variables.test.mjs— one test-only file, no productionchange, no new dependency, green on
main. Five assertions:non-empty), so a regression in the regexes cannot silently pass the rest;
var(--x)resolves to a CSS declaration undersrc/, a JSinline-style declaration, or the vendor namespace;
--cncf-*token;--cncf-*token is read by at least onevar()(orphandetection, the reverse direction);
--cncf-*token themed on:rootis redeclared under[data-theme='dark'], so a new brand token cannot be added light-only andsilently inherit the wrong value in dark mode.
Assertion 5 has to match
:rootby substring: the selector incustom.csscarries a
:not(#\#):not(#\#)specificity hack.Verification
Mutation-tested — each mutation is caught by the intended assertion, and no
assertion is redundant:
var(--cncf-button-text)->--cncf-button-txt--cncf-button-textfrom the[data-theme='dark']blockvar(--cncf-button-background-hover)reference to its literal'--bar-width'inline-style key inMetricsDashboard/index.jsnpm run test:unit-> 60 tests, 60 pass (55 before).prettier --checkclean.
Coverage evidence
node --test --experimental-test-coverage tests/at00b44df,node v26.8.2, run locally 2026-09-20 -> 55 tests, 55 pass. No entry in the
coverage report corresponds to any file that reads a custom-property name.
playwright/cypress/puppeteer, and CI publishes no coverage artifact(see [quality] CI publishes no coverage evidence, so coverage findings cannot be verified #186). No claim is therefore made about e2e coverage of this path — a
browser suite is exactly what would catch a silently unstyled element.
Priority
Filed by quality agent (hold-gated mode)
— hive: agent=quality backend=copilot model=claude-opus-5