Skip to content

TXT1-C wiring Phase B, part 2: fonts fixtures, the web-only chrome-dual lane, and regenerated outputs - #39

Merged
thejackshelton merged 15 commits into
masterfrom
txt1c-wiring-parity
Sep 30, 2026
Merged

thejackshelton merged 15 commits into
masterfrom
txt1c-wiring-parity

Conversation

@thejackshelton

@thejackshelton thejackshelton commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Part 2 of T038; part 1 landed as #29.

What changed

  • Fonts fixture group. Six rejects join the corpus: unmapped, quoted generic, remote URL, local(), unresolved asset, invalid map. Five web-only layout fixtures are added:
    • pinned sans-serif at 400, 700, italic and 700 italic;
    • pinned monospace;
    • Lato;
    • declared @font-face;
    • platform system-ui.
  • Web-only lane. The web-only fixtures run chrome-dual alone, in ltr and rtl, against the stated reference (packages/parity/src/font-reference.ts, shared with scripts/capture-font-reference.ts). Every element with text must render its expected face in both documents (CSS.getPlatformFontsForNode).
  • Harness hooks.
    • fixture-reader resolves @font-face assets.
    • compileFixture takes the font map.
    • Font assets are inlined into the rendered CSS; a missing or unnamed asset throws.
    • captureFixture has a stated-reference hook.
  • Capture and report. parity:capture and profile:rows include the fonts fixtures. The report counts web-only cases separately.
  • Uses master's helpers. foldFamily, outputFamilyName and the Ahem shadowing rule come from master, and so does the bare generic-name quoting in the shared reference rewrite.
  • Audit fixes, each with a test. A capture read from disk is validated before use, and an unmatched font asset throws instead of passing silently.
  • Regenerated outputs.
    • Six new web profile rows: font-family:<pinned|declared|platform>, text-in-block, ltr and rtl. <platform> is caveat.
    • Emitted header digests and expected-fonts/**.
    • north-star-check.json: two Lato web UNSUPPORTED_VALUE rows become UNPROVEN_CONTEXT. Per-target totals are unchanged (web 185, ios 219, android 690).

Changed checks, with reasons

  • parity.test's "every web row is exact" now allows caveat for font-family:<platform> only. A family left to the platform uses the host's face (font-map supportOf), so "exact" would be a false claim. Every other web row must still be exact.
  • The committed-captures check reads only the two-lane corpus, because the fonts captures live in expected-fonts.

Passed (macOS)

  • pnpm typecheck
  • pnpm test: 122 files, 2482 tests, none skipped
  • parity:report: 241/241 fixtures, 376 cases, 0 failed; web-only 10/10
  • capture-font-reference --check byte-identical, and both planted faults exit 1; capture-font-data --check byte-identical
  • Regeneration at a fixed point; a second run changed nothing
  • No new native case, so no device step

🤖 Generated with Claude Code

Note

Add web-only fonts parity fixtures with chrome-dual lane and regenerate outputs

  • Adds a fonts fixture group in fonts.ts: five layout fixtures (pinned sans-serif/monospace, Lato, declared faces, platform fonts) and six compiler-reject cases, each mapped to a shared font reference that pins generic families to vendored fonts while leaving system-ui platform-backed
  • Adds the web-only fonts lane in fonts-run.ts: it inlines vendored font URLs as data URLs, injects pinned faces and generic-family substitutions as a reference transform, and compares authored vs. stated-reference Chrome captures
  • Teaches fixtureToInput in fixture-reader.ts to scan fixture CSS for compiler-accepted @font-face URLs that resolve under vendor/fonts, and compileFixture/webCssOf in pipeline.ts to compile with the font map and embed font assets into the web CSS
  • Integrates the lane into the capture, report, and profile-row CLIs, adds web-only summary counts and a font-family:<platform> caveat row, and regenerates the emitted parity CSS and north-star check report
  • Behavioral Change: report and parity CLIs now run fonts cases and exit non-zero when any web-only case fails; the named-family diagnostic in north-star-check.json is reclassified from unsupported-value to unproven-context; profile rows report platform font-family as caveat instead of exact

Macroscope summarized 248fff7.

…n the corpus; five web-only fonts fixtures (pinned sans-serif at 400, UA bold and UA italic, pinned monospace, Lato, declared @font-face faces, platform system-ui) run the chrome-dual lane alone in both directions (fonts-run.ts) against the stated reference, and each listed element must render its expected face in both documents (CSS.getPlatformFontsForNode). Their captures and emitted CSS live in packages/parity/expected-fonts, apart from the two-lane corpus. font-reference.ts holds the in-page CSSOM rewrite shared with scripts/capture-font-reference.ts (moved unchanged; --check byte-identical, both plants still fail). fixture-reader resolves @font-face url()s naming vendored fonts to snapshot assets; compileFixture passes a fonts fixture's map with its faces as assets; the rendered web CSS inlines font assets as data: URLs (unchanged without assets); captureFixture takes a stated-reference hook; parity:capture captures the fonts fixtures; profile:rows derives their web rows, <platform> capped at caveat
…the fonts fixtures' authored captures under the stated reference and their emitted CSS
…, twice): six new web rows, font-family:<pinned|declared|platform> in text-in-block ltr and rtl (<platform> caveat); no ios or android row changes
…ile changes only in its header digest, which covers the web support profile
…un north-star:check, twice): with the pinned web rows the Lato declaration's two web UNSUPPORTED_VALUE rows become two UNPROVEN_CONTEXT rows (text-in-flex-item row and column); per-target error totals unchanged (web 185, ios 219, android 690)
…ns each fonts fixture (live capture equal to expected-fonts, chrome-dual pass, linux-dragon-layout not run, emitted CSS equal), its registry, profile-proof and direction checks read corpus and fonts cases, the committed-captures check reads the corpus only, and a web row is exact except font-family:<platform> (caveat, font-map supportOf); buildReport links rows to web-only cases and counts them apart (summary.webOnly, webOnlyCases, one summary.md row); parity:report runs the fonts fixtures and fails if one fails
…expected face, so no text node escapes the face check (with a test)
Part-1 code takes master's reviewed version. Conflicts:
- packages/parity/emitted/**, profiles/*.ts, north-star-check.json: master's files; regenerated in the next commits.
- scripts/capture-font-reference.ts: keeps the import of the shared packages/parity/src/font-reference.ts; master's
  change to the in-page rewrite (quote a bare family that ASCII case-folds to a parser generic, PARSER_GENERICS) is
  ported into font-reference.ts applyFontReference, so the script and the fonts fixtures run the same rewrite.
- packages/parity/src/fixtures.ts: master's showcase group, then fonts.
…puts

- font-reference.ts pinnedGenerics: a named family entry may pin under its own name as Chrome's FontFaceCache folds it
  (foldFamily, fonts/selection.ts), not only byte-equal; any other family name still throws.
- pipeline.ts inlineFontAssets (webCssOf): every url("fonts/...") of dragon.css must name a web output asset and every
  asset must be named, else it throws; before, a url of another shape was left as written and an unnamed asset passed.
- fonts-run.ts readFontCapture (committedFontAuthored): a committed expected-fonts capture is checked before use (its case,
  direction, viewport, Chrome version, well-formed nodes, and the exact bytes parity:capture writes); before, the JSON was cast.

Tests (fonts-fixtures.test.ts): pinnedGenerics folding and rename refusal; inlineFontAssets both failure directions;
readFontCapture on a wrong case, non-canonical text, a malformed node, no nodes and null.
…capture, profile:rows, parity:capture, parity:dpr-capture, layout:vectors, layout:dpr-vectors, native:gen, north-star:check, tw:sweep, wpt:run -- --target web, wpt:update-expectations -- --target web

Changed:
- packages/dragon/src/profiles/web.ts: six web rows, font-family:<pinned|declared|platform> at text-in-block ltr and rtl
  (<platform> caveat); no ios or android row changes.
- packages/parity/emitted/**, packages/parity/expected-fonts/emitted/**: header digests only (the digest covers the web profile).
- examples/music-player/dragon/north-star-check.json: the Lato declaration's two web DRAGON_UNSUPPORTED_VALUE rows become two
  DRAGON_UNPROVEN_CONTEXT rows (text-in-flex-item row and column); per-target error totals unchanged.
No change from grammar:gen, the captures (expected, expected-dpr, expected-fonts captures), the vectors, native:gen, tw:sweep or
the WPT web expectations.
Comment thread packages/parity/src/fixture-reader.ts Outdated
Comment thread packages/parity/src/fixture-reader.ts Outdated
@macroscopeapp

macroscopeapp Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR adds a substantial fonts parity/reference lane and regenerates extensive artifacts, while also changing production web support-profile rows used for font-map diagnostics and support results. The scope and runtime metadata change warrant human review.

No code changes detected at 248fff7. Prior analysis still applies.

You can add or adjust custom eligibility rules. Learn more.

… and resolves them to regular vendored files only (PR #39 round 1)

Macroscope 4142756157 and 4142756160 share one cause: fontFaceUrls scanned the stylesheet with regexes, so a comment before
the block hid a rule, and an existing directory counted as a font (readFileSync then threw EISDIR).
- fontFaceUrls runs Dragon's parseStylesheet and collectFontFaces, so it sees exactly the relative src URLs the compiler looks up
  (comments, case, escapes, and refused nesting as Dragon reads them); each url() token's offsets come from the same parse.
- vendoredFontId: the path must normalise under vendor/fonts, its real path must stay under vendor/fonts' real path, and it must be
  a regular file; anything else stays unresolved, which the compiler reports as DRAGON_FONT_UNRESOLVED_ASSET.
- fonts-run.ts authoredFontHtml inlines those url() tokens by offset instead of its own regex.
The other regexes over CSS in packages/parity/src: pipeline.ts inlineFontAssets reads Dragon's own emitted dragon.css and throws on
any url or asset it cannot match; font-reference.ts reads Chrome's CSSOM serialization in the page (the stated reference, T033 §1.3).

Tests (fonts-fixtures.test.ts; 5 fail on the old code): comment before the block, upper case, escaped name, @media nesting, url()
outside src, offsets; vendoredFontId on a directory, vendor/fonts itself, .. escapes, a missing file, an absolute path; a directory
src compiles to DRAGON_FONT_UNRESOLVED_ASSET; authoredFontHtml with a comment. Changed: the fontFaceUrls expectation gains spans,
and the authoredFontHtml forms are wrapped in a fixture document, because it now reads the fixture's <style> as the reader does.
Conflicts: packages/parity/src/fixtures.ts takes master's phrasing-blockified group, then fonts. Generated files (emitted/**,
profiles/*.ts, north-star-check.json) take master's copy and are regenerated in the next commit.
…capture, profile:rows, parity:capture, parity:dpr-capture, layout:vectors, layout:dpr-vectors, native:gen, north-star:check, tw:sweep, wpt:run -- --target web, wpt:update-expectations -- --target web (run twice; the second run changed nothing)

- packages/dragon/src/profiles/web.ts: the six web rows font-family:<pinned|declared|platform> at text-in-block ltr and rtl
  (<platform> caveat); no ios or android row changes.
- packages/parity/emitted/**, packages/parity/expected-fonts/emitted/**: header digests only.
- examples/music-player/dragon/north-star-check.json: the Lato declaration's two web DRAGON_UNSUPPORTED_VALUE rows become two
  DRAGON_UNPROVEN_CONTEXT rows (text-in-flex-item row and column); per-target error totals unchanged (web 174).
No change from grammar:gen, the captures (expected, expected-dpr, expected-fonts), the vectors, native:gen, tw:sweep or the WPT
web expectations.
… entry, keeping the renderer-isolation rule

parity.test's renderer-isolation check forbids relative imports of packages/dragon/src from fixture-reader.ts. The internal entry
now exports parseStylesheet, collectFontFaces, preprocessInput and the AtRuleContext type (none from analysis, emit or lower),
and fixture-reader imports them from 'dragon'. Behaviour unchanged.
@thejackshelton
thejackshelton merged commit 2fd7ddf into master Sep 30, 2026
4 checks passed
@thejackshelton
thejackshelton deleted the txt1c-wiring-parity branch September 30, 2026 12:28
thejackshelton added a commit that referenced this pull request Sep 30, 2026
…ixtures.ts puts fonts before values, which stays the last group (values.test.ts); generated outputs regenerated after
thejackshelton added a commit that referenced this pull request Sep 30, 2026
…) (regen sequence: grammar:gen, parity:capture, profile:rows, parity:capture, layout:vectors, parity:dpr-capture, layout:dpr-vectors, layout:break-vectors, parity:break-capture, parity:pixel-capture, native:gen, parity:lanes -- --run-host, node --conditions=dragon-internal examples/music-player/tools/check.ts (pnpm run north-star:check fails on master since #39: fixture-reader imports collectFontFaces from the internal entry), wpt:run --target web, wpt:update-expectations --target web, parity:glyph-b3 -- --write-bottom-pins): profiles regain the values rows, emitted CSS digests, pixel manifest and bottom pins gain the values cases, corpus-dpr.json digests; north star supported declarations 159 -> 165 on web and ios (54.6% -> 56.7%)
thejackshelton added a commit that referenced this pull request Sep 30, 2026
…ough T057 #40, T037 #34, T038 #29/#39, T112 #36); T121 grid G1a and T122 LANE-SPEED cards; HANDOFF.md moves to notes/; active T058, current lanes dispatched
thejackshelton added a commit that referenced this pull request Sep 30, 2026
#39 txt1c wiring parity) into MQ-a: pnpm run grammar:gen; pnpm run parity:capture and pnpm run profile:rows to the fixed point (a third run changes nothing); pnpm run parity:dpr-capture; pnpm run layout:vectors; pnpm run layout:dpr-vectors; pnpm run layout:break-vectors; pnpm run parity:break-capture; pnpm run parity:pixel-capture; pnpm run native:gen; node --conditions=dragon-internal examples/music-player/tools/check.ts (pnpm run north-star:check fails on master too: fixture-reader imports collectFontFaces without the dragon-internal condition); pnpm run tw:sweep; pnpm run wpt:run and wpt:update-expectations -- --target web; pnpm run parity:glyph-b3 -- --write-bottom-pins; media-sweep (--check: 18/18, 286 samples). Generated conflicts were taken from origin/master and regenerated.
thejackshelton added a commit that referenced this pull request Sep 30, 2026
…TOKENS cap; #39 fonts part 2) into v2a-value-model. fixtures.ts and pixel-reference.test.ts take master's side (phrasing-blockified and fonts before values; master's glyph-clearance pins), since V2a's side of both came only from an earlier master merge. Generated conflicts (profiles, emitted CSS, pixel manifest, bottom pins, lanes.json, corpus-dpr.json, the Tailwind snapshot) taken from master and regenerated after
thejackshelton added a commit that referenced this pull request Sep 30, 2026
…tFontSize lowering fix (regen sequence of 6ab1148: pnpm run grammar:gen, parity:capture, profile:rows, parity:capture, layout:vectors, parity:dpr-capture, layout:dpr-vectors, layout:break-vectors, parity:break-capture, parity:pixel-capture, native:gen, parity:lanes -- --run-host, node --conditions=dragon-internal examples/music-player/tools/check.ts, wpt:run -- --target web, wpt:update-expectations -- --target web, parity:glyph-b3 -- --write-bottom-pins, then tw:sweep): the 12 phrasing-blockified cases' vectors at DPR 1, 2, 3 and 2.625 gain V2a's neutral engine fields (scripts/check-additive-migration.ts origin/master on v2a-migration-check: 1769 changed files, 7659 neutral additions removed, every other byte identical), the generated harnesses follow harness.ts, corpus-dpr.json digests, lanes.json host run; profiles, emitted CSS, pixel manifest, bottom pins, north-star-check.json and the Tailwind snapshot equal master's
thejackshelton added a commit that referenced this pull request Sep 30, 2026
… parity:lanes -- --run-host --run-device) after merging origin/master (#43, #39): 438 cases; layout-vectors-host, layout-vectors-device, device-frames, device-applied and device-lines pass on ios and android with the V1 suites (snap-values 150/150, calc-goldens 17/17, engine-calc 4000/4000, units-calc 50000/50000) on V2a's engine inputs; device-pixels fails with ios 135 and android 182 failures, as on origin/master; out/device-failures-{ios,android}.json unchanged and byte-identical to master's
thejackshelton added a commit that referenced this pull request Sep 30, 2026
…-parity) into wm0-horizontal-tb; conflicted generated outputs (emitted/*.css, out/lanes.json, corpus-dpr.json) taken from master and regenerated after
thejackshelton added a commit that referenced this pull request Oct 1, 2026
…rlier) into anim-a2-translate: faults.ts keeps both sides' fault flags; the values group moves after master's phrasing-blockified and fonts groups so it stays last (values.test.ts); pixel-reference.test.ts and every generated output taken from master and regenerated after
thejackshelton added a commit that referenced this pull request Oct 2, 2026
…-parity, #40 inl-bf, board T116-T120) into size-ar

Source conflicts resolved by keeping both sides: computed-checks.ts runs checkAspectRatio and checkInlineLevel; faults.ts NO_FAULTS gains master's blockifySkipped and inlineFlexToBlock beside this branch's fields; fixtures.ts keeps master's phrasing-blockified and fonts groups, then sizing-ratio, with values last; pixel-reference.test.ts glyph-clearance pins are master's plus this branch's delta over the merge base (sizing-ratio and values cases).
Generated outputs in conflict (emitted/**, profiles ios/web, north-star-check.json, bottom-scanlines.json, pixel manifest, lanes.json, tailwind snapshot, corpus-dpr.json) are taken from master and regenerated in the next commit.
thejackshelton added a commit that referenced this pull request Oct 2, 2026
…: pnpm run grammar:gen, ua:capture, parity:capture, profile:rows, parity:capture, layout:vectors, parity:dpr-capture, layout:dpr-vectors, layout:break-vectors, parity:break-capture, parity:pixel-capture, layout:paint-vectors, native:gen, parity:lanes -- --run-host, node --conditions=dragon-internal examples/music-player/tools/check.ts (pnpm run north-star:check fails on master since #39: fixture-reader imports collectFontFaces from the internal entry), wpt:run -- --target web, wpt:update-expectations -- --target web, parity:glyph-b3 -- --write-bottom-pins, tw:sweep. node scripts/check-aspect-ratio-migration.ts origin/master exits 0: vectors 1769 of 4397 files changed, 32833 neutral aspectRatio keys; captures 1752 of 1752, 32572 keys; emitted 334 of 334, 7525 declarations; every other byte identical; new files only from the 8 sizing-ratio fixtures. Tailwind sweep web and ios 2216 supported
thejackshelton added a commit that referenced this pull request Oct 2, 2026
… parity:lanes -- --run-host --run-device) after merging origin/master (#39, #43): 448 cases; layout-vectors host and device, frames, applied and lines pass on ios and android; device-pixels ios 139, android 186 (master 135, 182); out/device-failures-{ios,android}.json unchanged by this run: master's failures plus the 8 T116 border-join-seam failures on sizing-ratio-abspos and -rtl interior:c1 at DPR 2 and 3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant