Skip to content

TXT1a-1b (v2): real-font Latin through HarfBuzz in the engine, restacked onto INL1a C2 - #102

Merged
thejackshelton merged 37 commits into
masterfrom
txt1a-1b-v2
Oct 9, 2026
Merged

thejackshelton merged 37 commits into
masterfrom
txt1a-1b-v2

Conversation

@thejackshelton

@thejackshelton thejackshelton commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

TXT1a-1b (v2): real-font Latin through HarfBuzz in the engine. Second level of the text stack; #101 (its parent) has merged, so this PR's base is now master. Host-only: device lanes run in the landing driver.

What changed

  • Real-font Latin engine (TXT1a-1 phase B, T083J). A text leaf whose face is not Ahem is shaped by HarfBuzz through the host's GlyphShaper. The engine then breaks lines with Blink's LineBreaker over the shaped items (shaping.ts breakItemLines, porting ShapingLineBreaker::ShapeLine, BreakText's hyphen retry, HandleTrailingSpaces and HandleOverflow). Real-font intrinsic sizes follow LineBreaker for max-content and HandleTextForFastMinContent for min-content.
  • Line breaking for real-font text. latinOpportunities (inline.ts) gives the soft wrap opportunities without linebreak-data.ts, and is proved equal to lineBreakOpportunitiesWith on every Latin code point it covers.
  • Input and validation. TextFont.family / FontSpec.family name a face id: Ahem, or sha256:<hex>. validate.ts accepts any string.
  • Unknown faces. The engine refuses any face the measurer does not hold, with text-glyph at the node that names it, at every point that reads it: text measurement, the strut and inline boxes (inline.ts), and ex, ch, cap and lh in the environment pass (environment.ts, which now runs inside layoutWithFaults's refusal handler).
  • Post-layout passes. scrollMetrics and hitTableOf resolve the input with the caller's measurer, through layout.ts resolvedInput, the same resolution layoutWithFaults lays out with. Before, they re-resolved through zoomInput's Ahem measurer, which threw on a real-font input using ex, ch, cap or lh.
    • A refusal there comes back as scrollMetrics' typed refused result and as hitTableOf's HitError.
    • The parity hosts line-breaks.ts (engineTextLines) and expected-dump.ts still call zoomInput. T083J keeps those Ahem-only, as they mirror the device runtime, and T084 Phase F moves them to shapedMeasurerFor.
  • Measurer. TextMeasurer.shaped() exposes the shaped item that line breaking reads, and TextMeasurer.hasFace() says which faces the measurer holds. The font-data measurer holds only Ahem.
  • Refusals. New refusal text-shaping-run: text across an inline box boundary in one face and size, which Blink shapes as one run and Dragon would shape leaf by leaf.
  • Translate harness. It replays a shape transcript (R3) as its GlyphShaper, and validates the transcript: a face listed twice, or a partial glyph record, is a harness error.
  • R6 italic gate. The Inter Italic and Bold Italic gate cases are added (docs/research/text-spike/italic, 400 cases, exact).
  • docs/ports.json. shaping.ts ports line_breaker.cc (NextLine and HandleText located).

The two Latin rules (R4), on purpose

Both refuse with text-script, citing notes/T056-txt1a-spec.md R4, and the latinCheckSkipped plant skips both.

  • TXT1a-1a (v2): Ahem through HarfBuzz, and the zoomInput platform rule, restacked onto INL1a C2 #101's latinScopedMeasurer (every face, including Ahem through HarfBuzz) is the spec's literal rule: every code point is Latn, Zyyy or Zinh.
  • The engine's real-font check (inline.ts checkShapedText) runs first on real faces and is stricter. It also refuses a Common or Inherited code point whose Script_Extensions exclude Latin (for example U+060C), because Blink shapes such a code point in a run of its own.

#101's rule is left as it is, so Ahem outputs don't move.

Merges

Native coverage of the real-font path (not in this slice)

  • In this PR no committed vector or corpus line carries a shape transcript. So the translated real-font path never runs in Swift or Kotlin here; it is proven in TypeScript only. That path is the replay shaper and measurer, checkShapedText, latinOpportunities, breakShapedLines, ShapeLine and breakItemLines.
  • R3 (notes/T056-txt1a-spec.md) requires TS, Swift and Kotlin equality through transcript replay. The slice that delivers it is TXT1a-2: notes/T084-txt1a-2.md Phase F, "corpus-dpr.ts appends one text-latin suite", with the text-latin vectors from TXT1a-1's registry (TXT1a-1 (v2): the text-latin registry against Chrome, restacked onto INL1a C2 #103). TXT1a-2 (v2): native real faces and the text-latin cases in FIXTURES, restacked onto INL1a C2 #104 does this (textLatinVectorCases).
  • No profile row claims native real-font support: iOS and Android list font-family:Ahem only, and native-mode lowering still refuses other faces.

Outside the spec

  • packages/translate/src/generate.ts: one engine root, latinScopedMeasurer, so the harness may reach it (the translator lets the harness use only what the engine roots reach).
  • packages/parity/test/text-latin-engine.test.ts: new test file.

Tests changed, with reasons

  • New: packages/parity/test/text-latin-engine.test.ts.
    • The engine lays out all 1,120 Latin gate cases (Inter, Roboto, Noto Sans, Lato, Lato Bold) as Chrome 145 broke them: line count and every line width.
    • Seven plants are each caught against Chrome there: doubleAccumulation, noReshapeAtBreak, kerningDropped, wholePixelPositions, softHyphenWidthMissing, fitWithoutEpsilon and breakOffByOne. advanceNot16_16 changes no gate line; text-latin.test.ts catches it on T082's Chrome Ahem runs.
    • It covers R4 and its Script_Extensions refinement on the real-font path, the text-script refusal from shaped(), and text-shaping-run.
    • The harness replay equals the Node host on 45 inputs, with no fault and with each of the 8 shaping plants, and each plant changes at least one output. It also checks the harness errors for malformed transcripts.
    • A face the measurer does not hold is refused with text-glyph at each entry point: the strut, an inline box, ex, ch, and lh with line-height normal, all at DPR 1, plus the strut at DPR 2. It checks this on measurerFor's Ahem measurer, on a shaped measurer without the face, and on the harness with and without a transcript. These tests throw without the fix.
    • scrollMetrics, hitTableOf and the harness's scroll suffix (a line with both a shape transcript and a viewport direction) handle a real-font input with ex and lh widths. With a measurer that lacks the face, scrollMetrics returns a refusal and hitTableOf throws a HitError. All three tests fail without the fix.
    • Real-font max-content equals the gate's Chrome 145 nowrap width on all 224 combinations of face, paragraph and size.
    • Real-font min-content equals Chrome 145, measured live in the test with an absolutely positioned width: min-content block, on those 224 combinations and on 6 soft hyphen paragraphs. There, the softHyphenWidthMissing plant is caught. The live max-content also equals the gate's nowrap width, which checks the method.
  • New: packages/layout/test/inline-latin.test.ts. latinOpportunities equals lineBreakOpportunitiesWith.
  • Appended:
    • shaping-gate.test.ts: the engine decides every Latin gate line (1,200 cases) and every italic line (400).
    • text-shaper/test/gate.test.ts: the R6 italic gate.
    • font-data.test.ts: the old reference measurer gains a shaped stub.
  • text-latin.test.ts: comment only. It now says the three plants act on real-font lines (breakShapedLines), which Ahem text does not take. No assertion changed.

What passed (head d542a45)

  • Regen on CI after the post-layout fix (7550264): regen commit d542a45 (https://github.com/compiled-run/dragoncss/actions/runs/37897002598).
  • pnpm typecheck passed, locally on d542a45.
  • Platform-free tests, run locally on d542a45, all passed: all of packages/layout/test, plus packages/dragon/test/registry-claims.test.ts and profile-index.test.ts. That is 49 files and 1457 tests.
  • pnpm ci:test-files, run on CI at d542a45 (https://github.com/compiled-run/dragoncss/actions/runs/37901099669): 36 files, all passed.
    • Native files: native-swift, native-kotlin, native-dpr-swift and native-dpr-kotlin.
    • Chrome-group files: text-latin, text-latin-engine (34, including the live Chrome min-content test and the post-layout tests), text-shaper gate, translate.test, chrome-ports, parity registry-claims and android-profile.
    • Fixture-wide set: p6a-dash-oracle, parity, 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, line-breaks, pixel-reference, pnt2-quads, pnt2-samples and replaced-paint.
  • pnpm pr:review 102 --once exits 0: CI checks passed and no finding is unanswered. Macroscope skipped this head at its monthly spending limit, so the PR is UNREVIEWED.
  • Reviewed diff: about 174 KB against master, excluding the paths in .macroscope/ignore.md. That is over the ~150 KB guide; about 35 KB of it is the new test file. It is shipped as one theme rather than split.

🤖 Generated with Claude Code


Generated by Claude Code

thejackshelton and others added 14 commits October 2, 2026 05:51
… own change (txt1a-1a..txt1a-1b 926262959, without its regenerated outputs). One conflict, in translate/harness/harness.ts: the shape-transcript replay (ReplayCall, decodeShaping, replayMeasurer) inserts before runEngineCase, whose doc comment master had already deduplicated; the replay and the new comment are kept
…ixed point after 2 passes). Only the translated engines change (the shaping core, script and East Asian width tables, harness replay); every capture, vector, break, pixel, profile, corpus digest and lane output is byte-identical
…cc (NextLine and HandleText located); THIRD_PARTY_NOTICES.md unchanged (pnpm notices:gen)
…room, on master since the branch was written): '-' before a Latin-1 code point above U+007F reads the pair alone (fastBreak), not UAX #14 over the whole run; inline-latin.test.ts's equality with lineBreakOpportunitiesWith holds again ('A-ä' has no break)
…/tmp/heavy-lease.sh pnpm regen (fixed point after 2 passes; only native-gen reran). Only the translated inline engine (Inline, Unions, Strings) changes
…(inl1a-lowering with seld-lanes-v2 and the #91 and #104 fixes): pnpm regen (fixed point after 2 passes)
…he translated animator on the state machine (mount, setter event, clock step) with frame colours and patched lengths, and the display drivers

emit/runtime/anim.ts writes a state program's compiled animation tables (lower/anim-program.ts animTablesOf) as constructor calls of
the translated rt-animator.ts classes, held to the generated Swift and Kotlin constructors by test; DragonAnimator runs the
translated animatorStart/Event/Advance/Frame over them with every fault off. The state machine starts it at mount (R7, inputs
resolved at scale 1 by the engine's resolver, R14), raises one event per setter call (R4) and moves it by the script clock (R2);
build() draws the frame's colours (background, border sides, text runs, with the R9 closure) and input() patches its lengths (R16).
A mount renders a clock step when its tree is next read; the display drivers (CADisplayLink, Choreographer) run only on a mount
built with display: true and only while the animator is busy, so the lanes never read the wall clock. The host apps carry every
frame case's state program with its tables (anim-cases.ts frameEmits), so native:build compiles the literals on both targets.
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: 7a30611
Run: https://github.com/compiled-run/dragoncss/actions/runs/37397616241
…) into txt1a-1b-v2 (local prep; lane-contract queued-parent exception); no conflicts
claude and others added 4 commits October 9, 2026 00:46
…prep; lane-contract queued-parent exception)

Conflicts, resolved keeping both sides:
- layout/src/unsupported.ts: #101's text-script (after text-glyph), master's grid-layout and TextRefusalCode, and
  #102's text-shaping-run appended last; #102's duplicate text-script dropped.
- layout/src/text.ts: both imports (ShapedItem, TextRefusalCode); #102's non-Ahem refusals in the font data
  measurer carry code text-glyph.
- translate/harness/harness.ts: both import sets; runEngineCase reads both optional keys (shaping and
  viewportDirection) and keeps #102's transcript replay and master's scroll suffix.

R4 on the real-font path (#101's latinScopedMeasurer):
- ShapedItem's failure carries a TextRefusalCode; latinScopedMeasurer forwards shaped() with the same Latin
  check, so the item real-font line breaking reads refuses non-Latin text with text-script; inline.ts
  shapedItemsOf reports that code. checkShapedText's refusal uses #101's spec section.
- The harness wraps its replay measurer in latinScopedMeasurer, as shapedMeasurerFor does (engine root added
  in translate/src/generate.ts so the harness may reach it), and refuses shaping plants only for a case without
  a shape transcript: with one, every plant acts on the replayed measurer.
- decodeShaping refuses a face listed twice and a partial glyph record.

New test packages/parity/test/text-latin-engine.test.ts: the engine breaks all 1,120 Latin gate cases
(Inter, Roboto, Noto Sans, Lato, Lato Bold) as Chrome 145 does, line count and every line width; seven plants
caught against Chrome there; R4, the Script_Extensions refinement and the run refusal on the real-font path;
the harness replay equals the Node host on 45 inputs with and without each of the eight shaping plants, each
plant changing at least one.

Generated outputs are stale until a regen on CI after #101 merges.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WSkSiXMPXTAsNpS9BD9LDR
state.ts conflict: the box background write keeps master's dragonBackground
paint writer (rounded fill) and feeds it this side's animated frame colour,
as the Kotlin side already merged; anim-runtime.test pins both on both backends.
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: 5fb1369
Run: https://github.com/compiled-run/dragoncss/actions/runs/37873130074
@thejackshelton
thejackshelton changed the base branch from review/txt1a-1a-v2 to master October 9, 2026 03:22
claude and others added 10 commits October 9, 2026 03:22
…flicts

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: 9550680
Run: https://github.com/compiled-run/dragoncss/actions/runs/37877635236
`vitest list` (the test-files workflow's collection step) runs module scope
but no hooks, so their module-scope mkdtempSync left dragon-states-* in TMPDIR
and failed run 37877256593. tmpdir-guard.test now plants the module-scope case
under `vitest list`, proves the beforeAll form passes list and run, and scans
every *.test.ts for a module-scope mkdtemp.
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: 4447c5f
Run: https://github.com/compiled-run/dragoncss/actions/runs/37879039149
…ibe-scope ones into beforeAll

The review of 5e9fa90: the indentation scan missed describe bodies, which
`vitest list` runs too. tmpdir-guard.test now walks each *.test.ts with the
TypeScript AST and reports a mkdtemp/mkdtempSync (direct, or through a local
helper) that runs at module scope, in a describe body or in an inline callback,
but not one in a hook or test. Planted: scan-cases.planted.ts (7 reported, 8 not)
and describe-scope.planted.ts (leaks under `vitest list`). It reported 16 sites;
each now makes its folder in beforeAll with a guarded afterAll, no assertion
changed: floor-merge (2), sorted-merge (2), calc-probe (1), land (5),
merge-train (3), pr-review (3).
…rywhere; prove real-font min- and max-content against Chrome

Independent review of #102 at b1aa3d5:
- TextMeasurer gains hasFace. A face the measurer does not hold is refused with text-glyph at the node
  that names it before metrics() or lengths() is asked: the strut and inline boxes (inline.ts), and
  ex, ch, cap and lh in the environment pass (environment.ts, which now runs inside layoutWithFaults'
  refusal handler and tracks the node it resolves). Before, these threw an untyped Error.
- text-latin-engine.test.ts: each entry point (strut, inline box, ex, ch, lh with line-height normal,
  the strut at DPR 2) is refused on measurerFor's Ahem measurer, a shaped measurer without the face, and
  the harness with and without a transcript; real-font max-content equals the gate's Chrome nowrap width
  on all 224 face, paragraph and size combinations; min-content equals Chrome 145 measured live on those
  and on 6 soft hyphen paragraphs, where softHyphenWidthMissing is caught.

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: 1b5d816
Run: https://github.com/compiled-run/dragoncss/actions/runs/37886196195
…e 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: 5c647f7
Run: https://github.com/compiled-run/dragoncss/actions/runs/37888811923
claude and others added 5 commits October 9, 2026 06:26
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: f325e4e
Run: https://github.com/compiled-run/dragoncss/actions/runs/37889487728
…ith the caller's measurer

Re-review of #102 at 3d204e0: scrollMetricsWithFaults and hitTableOf re-resolved the input through
zoomInput's Ahem measurer, so a real-font input with ex, ch, cap or lh laid out and then threw. layout.ts
gains layoutMeasurer and resolvedInput, the resolution layoutWithFaults lays out with; both passes use it.
A refusal there is scrollMetrics' typed refused result and hitTableOf's HitError, never a throw.
text-latin-engine.test.ts: scrollMetrics, hitTableOf and the harness's scroll suffix (a line with a shape
transcript and a viewport direction) on such an input, and their refusals for a measurer without the face.

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: eda3b86
Run: https://github.com/compiled-run/dragoncss/actions/runs/37893548724
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: 7550264
Run: https://github.com/compiled-run/dragoncss/actions/runs/37897002598

Copy link
Copy Markdown
Contributor Author

LAND-READY
READY txt1a-1b-v2:102:d542a4541951f76cd31ca1478827095d44aa4cb2

Lane receipt (PM session A): base retargeted to master after #101 landed; master merged (#101, #210, #208, #198, #216, #218). pnpm typecheck pass; all of packages/layout/test plus dragon registry-claims, profile-index pass (local, 49 files, 1457 tests, at d542a45); ci:regen https://github.com/compiled-run/dragoncss/actions/runs/37897002598 (regen commit d542a45); ci:test-files https://github.com/compiled-run/dragoncss/actions/runs/37901099669 (tested d542a45 at d542a45: 36/36 files incl. native-swift, native-kotlin, native-dpr-swift, native-dpr-kotlin, translate.test, text-latin, text-latin-engine 34 (1,120 Latin gate cases equal Chrome 145; max-content equals Chrome nowrap on 224; min-content equals Chrome measured live on 230), text-shaper gate and the fixture-wide set); pr:review 102 --once exit 0 (UNREVIEWED: Macroscope spending limit). Reviewed size ~174 KB, one theme (stated in the body). Native equality for the real-font path is proven in TS only here; transcript vectors are TXT1a-2's per notes/T084-txt1a-2.md Phase F, and no profile row claims native real-font support.

Independent Claude review history (Medium or higher only): at b1aa3d5, three findings (unknown face crashed layout instead of refusing; real-font intrinsic sizing untested; translated real-font path not exercised natively), fixed in 1b5d816 with tests or scoped to TXT1a-2 with the spec citation; at 3d204e0, one finding (scroll metrics and hit tables re-resolved with the Ahem measurer and threw), fixed in 7550264 with tests that fail without it. Re-review at d542a45 is clean:

{"pr":102,"head":"d542a4541951f76cd31ca1478827095d44aa4cb2","findings":[]}

Generated by Claude Code

@thejackshelton thejackshelton added the land-ready Reviewed clean; the Mac landing driver takes it label Oct 9, 2026 — with Claude
thejackshelton pushed a commit that referenced this pull request Oct 9, 2026
…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
thejackshelton pushed a commit that referenced this pull request Oct 9, 2026
… 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
Commands: pnpm regen; pnpm run parity:devices; pnpm regen
@thejackshelton
thejackshelton merged commit a36d745 into master Oct 9, 2026
4 checks passed
@thejackshelton
thejackshelton deleted the txt1a-1b-v2 branch October 9, 2026 09:42
@thejackshelton thejackshelton removed the land-ready Reviewed clean; the Mac landing driver takes it label Oct 9, 2026
thejackshelton pushed a commit that referenced this pull request Oct 9, 2026
…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
thejackshelton pushed a commit that referenced this pull request Oct 9, 2026
…#216/#102) into ANIM-b1 part 2

Conflicts: state.ts keeps this branch's hooks-only form (the adapter in anim.ts draws the background through dragonBackground);
anim-runtime.test keeps the hooks test and carries master's check that the frame colour never goes straight to the platform
property; device-jobs.ts imports both ANIM_LANE and isBlockReason.
thejackshelton pushed a commit that referenced this pull request Oct 9, 2026
…on-runtime-evd0n6: 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_019gAHotrCwxo86PAgtrhRUT
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