Skip to content

TXT1a-1 (v2): the text-latin registry against Chrome, engine-mode real faces and R3 vectors - #103

Open
thejackshelton wants to merge 23 commits into
masterfrom
txt1a-1-v2
Open

thejackshelton wants to merge 23 commits into
masterfrom
txt1a-1-v2

Conversation

@thejackshelton

@thejackshelton thejackshelton commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

TXT1a-1 (v2): the text-latin registry against Chrome 145, with engine-mode lowering of bundled static real faces. It is the third level of the text stack. #101 and #102 (txt1a-1b-v2) are on master, so this PR's base is now master.

What changed

  • Compiler (packages/dragon).
    • lower/ios-layout.ts: lowerTree takes a lowering mode. Native lays out Ahem only. Engine mode also lays out the bundled static face that each element's and text node's font resolves to (face id sha256:<hex>).
    • project.ts:
      • It records the native font refusals the engine lane defers (fontDeferrals).
      • When every native blocker is a deferred font refusal, it lowers the native band's cases in engine mode (engineFacesOf, engineFaceFor).
      • Engine mode refuses fallback to several faces, variable faces and synthetic styles.
      • DRAGON_SYNTHETIC_FONT_STYLE (codes/txt1a.ts) refuses native text that Chrome would draw in synthetic bold or oblique.
    • internal.ts: engineLayoutProjection.
  • Parity.
    • text-latin-run.ts and fixture-groups/text-latin.ts: the text-latin registry (6 fixtures, 7 cases, plus 3 probes). It is kept out of FIXTURES, and its GROUPS entry is empty.
    • Every case must pass all of these:
      • the engine lane, exact at 1/64 px with the Node HarfBuzz host;
      • chrome-dual;
      • the face check (CSS.getPlatformFontsForNode) in both documents;
      • the break check against Chrome, at DPR 1, 2, 3 and 2.625.
    • runCase and runDprCase take the projection as an argument.
    • referenceShapedMeasurer registers every vendored face.
    • report.ts and gen-profile-rows.ts run the registry. Its cases prove web font-family rows only.
  • Vectors (R3). packages/layout/vectors/text-latin/dpr-<d>/<case>.json holds 28 vectors: the engine input and output with the shape transcript (faces and every HarfBuzz call).
  • Merge with TXT1a-1b (v2): real-font Latin through HarfBuzz in the engine, restacked onto INL1a C2 #102's head (d542a45) and with master. Conflicts in ios-layout.ts and project.ts were resolved keeping both sides:
    • the Lowerer carries both the mode and master's propagated;
    • checkCases takes the @Property registrations and keeps the font deferrals beside checkNativeScroll;
    • native lowering is master's per-band loop in native mode, then the engine-mode lowering.
  • Fixes after the merge and the audit.
    • line-breaks.ts engineTextLines re-resolved its input with zoomInput (Ahem) after laying it out with the caller's measurer. It now uses resolvedInput with the same measurer, so a real face's ex, ch, cap or lh no longer throws text-glyph. resolvedInput is exported from @dragon/layout.
    • cli/text-latin-capture.ts:
      • An unknown argument exits 2 before anything is cleaned. A mistyped --vectors used to run the live capture, which first deletes the committed captures.
      • A case that writes nothing exits 1 instead of only logging.
    • Two new regen steps in scripts/regen-steps/txt1a.ts, each with its .gitattributes line. They replace the old MANUAL entry, which a cloud lane cannot run:
      • text-latin-capture runs after capture, on the macos-26 capture runner. It writes the live Chrome captures, breaks and emitted CSS of the registry, as capture does for expected-fonts and expected-env. The committed captures predated master's new computed keys (border--radius, content, list-style-), so every text-latin case failed chrome-dual in profile:rows and text-latin-faces lost its web output.
      • text-latin-vectors runs after dpr-vectors. It rebuilds the vectors from those captures. The vectors predated master's grid keys.
    • The generated Swift and Kotlin replays of the vectors move from text-latin.test.ts to text-latin-native.test.ts, unchanged. The old file needed both Chrome and the native toolchains, so it could pass on neither CI shard.

Outside the spec

  • scripts/regen-steps/txt1a.ts, .gitattributes: the text-latin-capture and text-latin-vectors regen steps. The captures and vectors predated master's computed keys and grid keys, and had to be rebuilt by regen.
  • packages/parity/test/text-latin-native.test.ts (new): the native-shard half of text-latin.test.
  • packages/layout/src/index.ts: exports resolvedInput.
  • packages/parity/src/line-breaks.ts: engineTextLines resolves with the caller's measurer.
  • packages/layout/test/inline-box-placelines.test.ts: see below.

Tests and pins changed, with reasons

  • packages/parity/test/text-latin.test.ts:
  • packages/parity/test/text-latin-engine.test.ts: referenceShapedMeasurer() now holds every vendored face, Lato included. So "a shaped measurer without the face" is now an explicit Ahem-only shaped measurer (ahemShapedMeasurer). A new test pins that this measurer lacks Lato and that the reference one holds it. Each refusal is still judged on a measurer without the face.
    • Adds a test that engineTextLines resolves a Lato ex width. It fails with the old zoomInput code.
  • packages/layout/test/inline-box-placelines.test.ts: the Ahem measurer refused the text-latin vectors on both sides of placeLines == placeIfcLines, so the check passed without placing a line. Those vectors are now measured by the HarfBuzz reference measurer, every placement must succeed, and the 28 shaped vectors are counted. Forcing Ahem makes the test fail.
  • packages/parity/test/parity.test.ts: the fixture-file existence check now covers the text-latin fixtures and probes, not only the font and env ones.
  • packages/layout/test/dpr-vectors.test.ts: the vectors folder also holds text-latin.

What passed (head fafd726)

  • Regen on CI: pnpm ci:regen txt1a-1-v2, https://github.com/compiled-run/dragoncss/actions/runs/37931754092. Its regen commit is 4ff2514, on top of the master merge 6bc0e63. The only later commit (fafd726) changes test files only, which are not generator inputs.

  • pnpm typecheck (local): pass.

  • Local platform-free runs:

    • packages/layout/test: 47/47 files, 1444 tests pass. This includes inline-box-placelines on the regenerated text-latin vectors.
    • packages/dragon/test: 75 of 76 files pass. The exception is native-backends, which needs the native toolchains and passed on CI below.
  • pnpm ci:test-files at fafd726, https://github.com/compiled-run/dragoncss/actions/runs/37944523853: PASSED, all 39 files with 0 failures:

    • Native shard: text-latin-native (the Swift and Kotlin vector replay), regen, native-swift, native-kotlin, native-dpr-swift, native-dpr-kotlin and native-backends.
    • Chrome shard, targeted files: text-latin, text-latin-engine, line-breaks, parity (556), translate (both), chrome-ports, parity registry-claims and android-profile.
    • Chrome shard, fixture-wide set: p6a-dash-oracle, native-host, device-lanes, dist, env-engine, fixture-reader, fonts-fixtures, inline, interaction-forced, media-runtime, media-sweep, phrasing-blockified, platform, replaced-identity, tree-faults, values, glyph-calibration, hit-report, hit-capture-identity, pixel-reference, pnt2-quads, pnt2-samples and replaced-paint.
  • pnpm -s pr:review 103 --once: exit 0. CI checks pass with 0 unanswered findings. The head is UNREVIEWED because Macroscope hit its monthly spending limit.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WSkSiXMPXTAsNpS9BD9LDR


Generated by Claude Code

…2: txt1a-1's own change (txt1a-1b..txt1a-1 9743d57c9, without its regenerated outputs; the text-latin captures, breaks and vectors, which pnpm regen does not write, are carried as committed). Two conflicts: internal.ts keeps master's SELD-R1a state-program exports beside engineLayoutProjection; ios-layout.ts lowerTree keeps master's rootFontSizeOf (which refuses a root font size that did not compute to px) and passes the engine-mode flag
…li/text-latin-capture.ts (TXT1a-1 predates pnpm regen; TXT1a-2 moves them into the regen steps)
…ES hold 489 layout cases (the INL1a stack's and master's new cases since the old inl1a-compiler base, 477); the pin still says TXT1a-1 leaves every FIXTURES layout case as its base has it
…packages/parity/src/cli/text-latin-capture.ts (live Chrome; MANUAL), /tmp/heavy-lease.sh pnpm regen (fixed point after 3 passes), text-latin-capture.ts again, pnpm regen (no change), text-latin-capture.ts --vectors, pnpm regen (no change). The committed text-latin captures predated SIZE-ar's aspect-ratio computed key, so on the C2 base every text-latin case failed chrome-dual, profile:rows proved no font-family row from them, and text-latin-faces and text-latin-flex had no web output; recaptured, each capture gains aspect-ratio: auto and nothing else, the web profile regains the text-latin font-family rows (pinned in text-in-block, text-in-inline and text-in-flex-item), emitted CSS headers move only in their compilation digest, the text-latin vectors are rewritten from the new captures, and north-star-check gains 'Lato', sans-serif on web (UNPROVEN_CONTEXT web 27 -> 25)
…into txt1a-1-v2. Conflict: internal.ts keeps engineLayoutProjection beside SELD-R1b's hit facts
…ged in (2d04d5c), whose FIXTURES hold 520 layout cases (C2 alone held 489); the pin still says TXT1a-1 leaves every FIXTURES layout case as its base has it
…inl1a-lowering with seld-lanes-v2 and the #91 and #104 fixes): pnpm regen (fixed point after 3 passes)
…packages/parity/src/cli/text-latin-capture.ts (live Chrome; MANUAL), pnpm regen, text-latin-capture.ts again, pnpm regen, text-latin-capture.ts --vectors. The text-latin captures predated SELD-R1b's pointer-events computed key, merged forward with inl1a-lowering; each gains that key, and the vectors are rewritten from the new captures
…) into txt1a-1-v2 (local prep). Conflicts: diagnostics move per feature on master, so DRAGON_SYNTHETIC_FONT_STYLE goes to codes/txt1a.ts (pinned in diagnostic-codes/txt1a.json); ios-layout lowerTree takes both REPL-a's image naturals and TXT1a-1's lowering mode; project.ts checks each SELD-R2 interaction state with TXT1a-1's font deferrals; pipeline runCase keeps TXT1a-1's projection argument and SELD-R2's lane-only native rows and interaction projection; report, gen-profile-rows and parity.test run both the ENV-SAFE and text-latin web-only registries
…de --conditions=dragon-internal packages/parity/src/cli/text-latin-capture.ts (live Chrome; MANUAL), pnpm regen, node --conditions=dragon-internal packages/parity/src/cli/text-latin-capture.ts again, pnpm regen, node --conditions=dragon-internal packages/parity/src/cli/text-latin-capture.ts --vectors
… empty 'text-latin' fixture group (master's registry-claims check: every fixture-groups file is a group; TXT1a-2 fills it), and text-latin.test's BASE pins move to the new base's 569 layout cases and their id hash (intent kept: TXT1a-1 changes no FIXTURES case; the list equals the 1b base's)
claude added 2 commits October 9, 2026 08:18
…er with #101, #210, #208, #198, #216, #218) into txt1a-1-v2 (prep, no PR changes until #102 merges). Conflicts: ios-layout's Lowerer carries both TXT1a-1's lowering mode and master's propagated viewport-overflow element, and lowerTree passes both; project.ts checkCases takes master's @Property registrations and checkComputed faults argument and keeps TXT1a-1's font deferrals beside master's native-scroll check; the band passes pass both the shared font deferrals and the registrations; native lowering runs master's per-band loop in native mode, then TXT1a-1's engine-mode lowering of the native band's cases. Generated outputs: this side's, regenerated after #102 merges.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WSkSiXMPXTAsNpS9BD9LDR
… for the text-latin vectors, and the audit's fixes

- text-latin-engine.test: #103's referenceShapedMeasurer registers every vendored face, Lato included, so "a shaped measurer
  without the face" is now an explicit Ahem-only shaped measurer (ahemShapedMeasurer); a new test pins that it lacks Lato and the
  reference one holds it. Intent kept: each refusal is still judged on a measurer that does not hold the face.
- line-breaks engineTextLines re-resolved the input with zoomInput (Ahem) after laying it out with the caller's measurer, so a real
  face's ex, ch, cap or lh in the break check threw text-glyph; it now uses layout.ts resolvedInput with the same measurer
  (exported from @dragon/layout), with a test that fails without it.
- inline-box-placelines.test (placeLines == placeIfcLines on every vector): the text-latin vectors name real faces, which the Ahem
  measurer refuses on both sides, so the check passed without placing a line; they are now measured by the HarfBuzz reference
  measurer and every placement must succeed (28 shaped vectors).
- text-latin-capture CLI: an unknown argument exits 2 before it deletes anything (a mistyped --vectors ran the live capture, which
  first cleans the committed captures), and a case that writes nothing (no web CSS, a vector of a failing case) exits 1 instead of
  logging; test added.
- The text-latin vectors get a regen step (text-latin-vectors, after dpr-vectors, from the committed text-latin captures) and a
  .gitattributes line; the captures stay MANUAL (live Chrome). The vectors predate master's grid keys, so they must be rebuilt by
  regen, which a cloud lane cannot run by hand.
- text-latin.test BASE pin: 569 -> 664 layout cases and their id hash, the FIXTURES of #102's head d542a45 (identical ids,
  checked on a d542a45 worktree); intent kept: TXT1a-1 changes no FIXTURES case.
- parity.test: the fixture-file existence check covers the text-latin fixtures and probes too, not only the font and env ones.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WSkSiXMPXTAsNpS9BD9LDR
@thejackshelton
thejackshelton changed the base branch from review/txt1a-1b-v2 to master October 9, 2026 09:56
claude and others added 6 commits October 9, 2026 09:56
…103's parent merged; no conflicts, generated files regenerate on CI

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WSkSiXMPXTAsNpS9BD9LDR
…ure, after capture, live Chrome on the capture runner)

The first regen-on-ci run on master's tree failed text-latin-vectors: the committed text-latin captures predate master's new
computed keys (border-*-radius, content, list-style-*), so every text-latin case failed chrome-dual in profile:rows, the web
profile lost their font-family rows, and text-latin-faces had no web output. The captures were MANUAL (live Chrome); like
expected-fonts and expected-env they are now written by regen on the macos-26 capture runner, so the vectors step reads current
captures. MANUAL entry removed; .gitattributes line added.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WSkSiXMPXTAsNpS9BD9LDR
Commands: pnpm regen --skip lanes-host --skip tw-sweep (macos-26) and pnpm regen --only lanes-host (xcode-27), alternated
to a fixed point, then pnpm regen --only tw-sweep (macos-26).
Base: 10ea5b1
Run: https://github.com/compiled-run/dragoncss/actions/runs/37918055076
…2: GitHub reported the PR conflicting; no source conflicts, generated files regenerate on CI

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WSkSiXMPXTAsNpS9BD9LDR
Commands: pnpm regen --skip lanes-host --skip tw-sweep (macos-26) and pnpm regen --only lanes-host (xcode-27), alternated
to a fixed point, then pnpm regen --only tw-sweep (macos-26).
Base: 6bc0e63
Run: https://github.com/compiled-run/dragoncss/actions/runs/37931754092
…atin-native.test (native shards); BASE pin at master b97cf50

- text-latin.test.ts ran on the native shards (runTarget) but also needs Chrome (the DPR 1 lane), so neither shard could pass it.
  The two generated-engine replays move unchanged to text-latin-native.test.ts, which also checks it reads all 28 vectors;
  text-latin.test.ts is now a Chrome-group file.
- BASE pin 664 -> 666 layout cases, hash d989c528... -> caefcdb7... : master's FIXTURES after #232 and #233 (ids checked identical
  on an origin/master worktree). Intent kept: TXT1a-1 changes no FIXTURES case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WSkSiXMPXTAsNpS9BD9LDR
@thejackshelton thejackshelton changed the title TXT1a-1 (v2): the text-latin registry against Chrome, restacked onto INL1a C2 TXT1a-1 (v2): the text-latin registry against Chrome, engine-mode real faces and R3 vectors Oct 9, 2026
thejackshelton pushed a commit that referenced this pull request Oct 9, 2026
#103 was moved to master and caught up through b97cf50, then gained the text-latin-capture and text-latin-vectors regen
steps, text-latin-native.test.ts and a 666-case BASE pin. Conflicts, each keeping both sides' intent:
- TXT1a-2 folds the text-latin cases into FIXTURES, so its captures come from capture, dpr-capture and break-capture and its
  vectors from vectors and dpr-vectors: text-latin-capture.ts stays deleted, and scripts/regen-steps/txt1a.ts drops #103's two
  steps and instead adds the text-latin vector outputs to vectors and dpr-vectors (as ENV-SAFE adds expected-env to capture), so
  regen.ts's LEGACY_STEPS stay master's. .gitattributes lists the four per-DPR vector outputs, sorted, and drops
  expected-text-latin/** and the text-latin/** line; text-latin.test drops the CLI's unknown-argument test with the CLI.
- computed-checks.ts: checkComputed and checkUserAgentDefaults take TXT1a-2's realFaceAt and master's GEN-b faults; project.ts
  passes both, and lowers each MQ-R1 band's cases (with SELD-R2's interaction states) with TXT1a-2's real faces.
- pipeline.ts runCase keeps TXT1a-2's nativeProven rule (laneOnlyNative now also covers T078 R14).
- targets.ts, corpus-dpr.ts and the corpus and native-dpr tests: master's engine-overflow suite, then TXT1a-2's text-latin.
- parity.test: #103's fixture-file check over the web-only fixtures and the text-latin probes.
- text-latin.test BASE pin: 569 cases at 3c0c5d0b... -> 666 at caefcdb7..., #103's FIXTURES at b97cf50; the new cases are
  filtered out first, so the intent (every BASE case kept in order, only NEW_IDS added) is unchanged.
- Retargeted for TXT1a-2's 11 shaped cases: text-latin-native.test 28 -> 44 vectors and inline-box-placelines 28 -> 44 shaped
  vectors (11 cases at DPR 1, 2, 3 and 2.625, which text-latin.test already pins as NEW_IDS.length * 4).
Generated outputs regenerate on CI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WSkSiXMPXTAsNpS9BD9LDR

This branch has not been deployed

No deployments
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.

2 participants