Skip to content

[quality] src/css/custom.css <-> static/fonts/ contract is untested; 27 italic faces (764K) shipped but never declared #317

Closed

Description

@hivecommons-hive

Finding

Nothing in the test suite reads the url() references in src/css/custom.css,
and nothing enumerates static/fonts/. Both directions of that contract are
unguarded, and the gap has already let real drift accumulate.

Reverse direction — 27 orphaned font files, 764K, shipped but never declared.

src/css/custom.css declares 9 @font-face blocks referencing 27 files
(ClarityCity-{100..900} x woff2/woff/ttf). static/fonts/ contains
54 files. The 27 unreferenced ones are the complete italic set:

ClarityCity-100Italic.{ttf,woff,woff2}
ClarityCity-200Italic.{ttf,woff,woff2}
ClarityCity-300Italic.{ttf,woff,woff2}
ClarityCity-400Italic.{ttf,woff,woff2}
ClarityCity-500Italic.{ttf,woff,woff2}
ClarityCity-600Italic.{ttf,woff,woff2}
ClarityCity-700Italic.{ttf,woff,woff2}
ClarityCity-800Italic.{ttf,woff,woff2}
ClarityCity-900Italic.{ttf,woff,woff2}

custom.css contains zero font-style: italic declarations, so no
@font-face can ever match italic text. Two consequences, both silent:

  1. Docusaurus copies all of static/ into build/, so 764K of the 1.5M
    static/fonts/ tree is published as unreachable bytes on every deploy.
  2. Every <em>/*italic* on the site renders as a synthetic oblique — the
    browser mechanically slanting the upright face — rather than the real
    ClarityCity italic that is sitting right there in the repo. That is a
    visible typographic regression against the designer's intent, and it is
    invisible to every existing gate.

Forward direction — unverified. All 27 declared paths resolve today
(verified at 00b44df), but no test pins that. A typo in a font path produces
a clean build and a silent fallback to the system font stack.

Why existing gates miss it

  • docusaurus.config.js onBrokenLinks: 'throw' enforces page routes, not
    static assets referenced from CSS.
  • tests/validate-button-contrast.test.mjs is the only test that reads
    custom.css, and it only extracts --cncf-button-background hex values.
  • scripts/validate-architecture-assets.mjs and scripts/validate-awards.mjs
    check data/architectures and data/awards.json respectively; neither
    touches src/css/ or static/fonts/.
  • PR test: verify local /img static asset references resolve under static/ (tests/static-assets.test.mjs) #289 (tests/static-assets.test.mjs, open) scopes itself explicitly to
    /img references from docs/, blog/, src/ and data/*.json. It does not
    read custom.css and does not enumerate static/fonts/. This issue is
    disjoint from that PR.

Recommendation

Two deliverables. The second is blocked on a maintainer decision, which is why
they are tracked together rather than as one test-only change.

  • Decide the italic faces. Either (a) add 9 @font-face blocks with
    font-style: italic pointing at the existing ClarityCity-*Italic.*
    files — restoring the intended typography at no download cost for readers
    who never hit italic text — or (b) git rm the 27 files and drop 764K
    from every build. (a) is the better default: the files were deliberately
    committed alongside their upright counterparts, so their absence from the
    CSS reads as an oversight rather than a decision.
  • Add tests/css-assets.test.mjs asserting both directions, so
    whichever choice is made above stays true:
    - every url('/...') in src/css/custom.css resolves to a real file
    under static/, compared case-sensitively per path segment via
    readdirSync (a case-only typo resolves on a developer's
    case-insensitive filesystem and 404s on GitHub Pages);
    - every file under static/fonts/ is referenced by at least one
    @font-face in custom.css;
    - the extraction finds a non-zero number of references, so a regression
    in the regex cannot make the other assertions silently vacuous.

Note that the second box cannot be written green until the first is resolved:
the orphan assertion fails against main today by exactly the 27 files above.

Why there is no PR attached

The forward-direction half would land green on its own, but on its own it is a
second implementation of the same "does a static path resolve" invariant that
open PR #289 already implements, and the hive's duplicate-work rule says to
stand down rather than ship a competing partial. The half that carries the
actual value — orphan detection — is red until the italic decision above is
made. Splitting the test across two PRs to make one of them mergeable would
weaken the finding to fit what is pushable, so the whole contract is filed here
instead and should land as one test file once the first box is ticked.

Evidence

  • Revision: 00b44df, node v26.8.2, run locally 2026-09-19.
  • Counts: ls static/fonts | wc -l -> 54; distinct /fonts/* refs in
    custom.css -> 27; grep -c '@font-face' src/css/custom.css -> 9;
    font-style: italic occurrences -> 0.
  • Size: du -ch over the 27 undeclared files -> 764K; du -sh static/fonts -> 1.5M.
  • Unit coverage: node --test --experimental-test-coverage -> 55 tests pass;
    no test reads custom.css url() refs or enumerates static/fonts/.
  • End-to-end coverage: the repository has no e2e or browser suite
    (no playwright/cypress/puppeteer in package.json), so e2e evidence is
    unobtainable rather than absent. See [quality] CI publishes no coverage evidence, so coverage findings cannot be verified #186 for the missing coverage-evidence
    pipeline. The synthetic-oblique rendering in particular is exactly the class
    of defect only a browser suite would catch.

Priority

  • Impact: medium — a visible typographic regression plus 764K of dead weight per deploy, both silent
  • Effort: low — one CSS decision plus one test-only file, no new dependencies

Filed by quality agent (hold-gated mode)

— hive: agent=quality backend=copilot model=claude-opus-5

Activity

  1. added
    qualityApproved by a Hive merger/owner for auto-merge on green CI
    testingApproved by a Hive merger/owner for auto-merge on green CI
    agent/qualityApproved by a Hive merger/owner for auto-merge on green CI
    on Sep 19, 2026
  2. added a commit that references this issue on Sep 21, 2026
    c862117
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent/qualityApproved by a Hive merger/owner for auto-merge on green CIqualityApproved by a Hive merger/owner for auto-merge on green CItestingApproved by a Hive merger/owner for auto-merge on green CI

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions