Repository navigation
FORM-a 2/3: appearance as a longhand, and <button> as a CSS-painted control (block and flex), against Chrome - #78
Open
thejackshelton wants to merge 47 commits into
Open
thejackshelton wants to merge 47 commits into
thejackshelton wants to merge 47 commits into
Conversation
… longhand (route 2a, as object-fit) appearance joins the box family after object-position (paint aspect, layout false; css-ui-4 §7.1) and the grammar subset. gen-css-grammar.ts narrows webref's appearance grammar to what Chrome 145 parses (CHROME_SYNTAX: base dropped, probed 2026-10-01: declared empty and computed none in Chrome; base-select and every <compat-auto>/<compat-special> keyword kept and computed as written), failing if webref's grammar moves. Retargeted pins: seams LONGHANDS and paint role (+appearance), paint-seams longhand count 71 -> 72, s4b paint role (+appearance, with none/auto as its two values), css-escapes twin count 13788 -> 13823 (+35 from appearance's grammar words; every twin still reads as Chrome reads it).
…mmar:gen): appearance, <compat-auto> and <compat-special>
… the UA capture plants cannot pass silently -webkit-appearance is a box-family alias of appearance (shorthands/box.ts, the grid-gap -> gap precedent; PM T052J-A2 amendment), with the same Chrome-narrowed grammar. capture-ua-defaults.ts: drop-unmodelled now deletes button's cursor, since appearance is a modelled longhand and leaves the unmodelled rows; every plant throws when its row entry is missing, so a plant that deletes nothing can no longer pass. Retargeted pins: seams SHORTHANDS order (+-webkit-appearance after padding), css-escapes twin count 13823 -> 13858 (+35 from the alias's grammar words; every twin still reads as Chrome reads it).
…mmar:gen): -webkit-appearance
…rance Blink LayoutTheme::AdjustStyle makes any element whose appearance is not none inline-block (inline, inline-table, table-row, table-cell) or block (table, list-item; probed in Chrome 145 on a span). With appearance now a declared longhand, giving it to the dragon-unstyled reference made the reference inline-block too, so button, input and input[type=range] lost their forced display: inline-block, which Chrome keeps under appearance: none as well (probed). The reference takes every declared value but appearance, and a declared appearance is never reported as forced; the forced rows are byte-identical to before.
… adds only appearance (initial none, or the UA auto moved from the unmodelled to the declared rows on button, input and input[type=range]); engine inputs, line breaks and pixel manifests unchanged; 12 plants; --ua-plant runs ua:capture --check --plant drop-unmodelled and requires it to fail naming button's cursor
…apture, 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, parity:glyph-b3 -- --write-bottom-pins, wpt:check -- --target web (every entry matches), tw:sweep (grammar:gen was committed with the source). node scripts/check-appearance-migration.ts e009c15 exits 0: captures 1850 of 1850 files changed, only by 34050 "appearance": "none" keys; emitted 366 of 366, 7929 "appearance: none;" declarations; UA 2 files, 114 entries (computed rows none, or auto on button, input and input[type=range], whose appearance moved from the unmodelled to the declared rows; forced rows unchanged); engine inputs 4623 files, line breaks 1380 and the pixel manifest unchanged; no file added. Profiles, lanes.json, native generated sources (digests 38f0cb30, d1ea5e56) and bottom pins unchanged. North star: -webkit-appearance: none moves from DRAGON_UNSUPPORTED_PROPERTY (target-independent, 1) to DRAGON_UNSUPPORTED_VALUE per target (no appearance profile row yet): errors 853 -> 854, UNSUPPORTED_PROPERTY 60 -> 58, blanked declarations 63 -> 61. Tailwind sweep: only appearance-auto and appearance-none change blocker (UNSUPPORTED_PROPERTY -> UNSUPPORTED_VALUE, profile appearance:*); supported stays web and ios 2230, android 0; the rest is the fix-table reindex.
…and lists gain appearance on button, input and input[type=range]; ua-elb2.test's unmodelled rows lose it and the declared rows pin it as auto in both directions (the forced display: inline-block pins hold unchanged); seams.test pins appearance and -webkit-appearance parsing to the Chrome 145 probe (14 keywords kept as written, base, the older -webkit- keywords, two keywords and an unknown word dropped)
…ted control - elements/controls.ts: button is a supported tag reading the ELB-2 button key; its used appearance follows Blink IsControlStyled (R11): appearance none, or auto with an author background or border, paints as CSS boxes; anything else is the platform theme, refused naming FORM-b. - datasets.ts: UaKey gains the control key button; uaRows reads the element-key tables. Its forced display: inline-block is html.css's declared display (an author display wins, probed), so it becomes a declared UA value; any other forced row throws. - computed.ts and resolve.ts (A3-1): Blink LayoutTheme::AdjustStyle: an appearance other than none makes inline, inline-table, math and the table-internal displays inline-block, and table and list-item block, before blockification (measured on every display value with appearance auto and none in Chrome 145). - computed-checks.ts: a button that is themed (FORM-b), inline-level (RF-INL), of any display but block or flex, absolutely positioned or holding an absolutely positioned box (control-out-of-flow), an auto-width flex button in block flow, or using the UA control font (R13) is refused. color-scheme is not modelled, so no dark system colour can reach a used value. - ios-layout.ts: a block button lowers to a button-block control box; a flex button is a plain flex box. - block.ts (A3/A4-1): a block button's auto width fits its content in block flow (block_layout_algorithm.cc:3341-3352). - attributes.ts: type is handled on button (it changes only activation; controls-button-type proves the boxes). - Fixture group controls: button block, flex, demo, type and the appearance display adjustment, ltr and rtl, plus 6 rejects; controls-identity.test.ts proves every earlier case unchanged.
…ws, parity:capture, profile:rows, layout:vectors, parity:dpr-capture, layout:dpr-vectors, layout:break-vectors, parity:break-capture, parity:pixel-capture, layout:paint-vectors, native:gen (block.ts fit-content hunk; P1 digest 38f0cb30 unchanged, extended digest d1ea5e56 -> 3f8c6127 from the 10 new cases' vectors), parity:lanes -- --run-host, node --conditions=dragon-internal examples/music-player/tools/check.ts, parity:glyph-b3 -- --write-bottom-pins, wpt:check -- --target web, tw:sweep; a second parity:capture and parity:dpr-capture leave every output unchanged. Every earlier capture, vector and break vector is byte-identical (no modified or deleted file under packages/layout/vectors, packages/parity/expected or expected-dpr against form-a2); emitted CSS changes only by its compilation digest header; profile rows only gain rows and proof cases (appearance auto and none in paint/ltr and rtl, font-family and font-size inherit, and the button contexts). packages/wpt/expectations/web.json: only grid-button-001's not-runnable reason, which wpt:check reported changed (its button is now supported, so it is refused at display: grid), rewritten by hand from the Chrome-free wpt:check output with its status unchanged. Tailwind sweep web and ios 2230 -> 2232 supported. North star: <button> elements 0 errors (51 -> 61 supported elements), type attributes on buttons 0.
…nce display adjustment against the Chrome 145 probe (auto and button adjust, none leaves every display), the button key's declared display: inline-block and the throw on any other or missing forced row, and the R11 used appearance (inherited background stays theme)
…d in the receipt): block-elements.test's element table lets the control tags read the ELB-2 element keys (button reads the button key's tag); pixel-reference.test's glyph-clearance pins gain only the 10 controls cases' dropped and rescued rules (button text close to button edges): with controls-* filtered out the old pins hold exactly
…pm run wpt:run -- --target web, then pnpm run wpt:update-expectations -- --target web, from form-a2's web.json): the regenerated file is byte-identical to the one committed in 5e4d1f5 (only grid-button-001's not-runnable reason differs from form-a2: DRAGON_UNSUPPORTED_VALUE:display:grid, status unchanged), and packages/wpt/snapshots is unchanged, so this commit records the regeneration and changes no file
…orm-a3, resolved by intent: ios-layout.ts refuses a control root and lowers through master's rootFontSizeOf; gen-css-grammar.ts keeps A2's CHROME_SYNTAX narrowing beside master's SYNTAX_EXTENSIONS; pins: LONGHANDS 72 (aspect-ratio, object-fit, object-position, appearance), css-escapes twins 13904 (+4, +52, +70), pixel-reference takes the merged side (recomputed after regen); generated outputs take the merged side, rebuilt by pnpm regen
…egistry) into form-a3-v2, resolved by intent: attributes.test keeps A3's button type test beside REPL-a Phase B's iframe src title; resolve.ts composes master's forcedOver with A3's button rows unchanged; generated outputs take the merged side, rebuilt by pnpm regen
… (class A), so computed.ts states the appearance display table as the Chrome 145 measurement it is (controls-button-display fixtures), with AdjustStyle as a reference only; docs/ports.json lists computed.ts APPEARANCE_DISPLAY and elements/controls.ts as references of layout_theme.cc, its AdjustStyle range, and controls-identity.test.ts as a proof
…A3's block.ts fit-content hunk cites (blockLevelInlineSize is already listed)
…nerated outputs take the merged side, rebuilt by pnpm regen
…@media writes only the longhands that differ, so it gains no appearance; count only rules outside @media (as check-object-fit-migration does) and add the emitted-media plant (an appearance declaration planted in an @media rule must fail). Before the fix the 18 media-* emitted files failed against form-a-v2
…regen, fixed point after 3 passes): grammar, captures, DPR and font captures, emitted CSS, profiles, A3's controls vectors on master's V2 input shape, pixel manifest (only the 10 controls cases added), translated engine (A3's block.ts hunk), north-star check, Tailwind sweep, glyph bottom pins, media sweep, host lanes.json. node --conditions=dragon-internal scripts/check-appearance-migration.ts 75bf9e5: every file at the base changes only by appearance (captures 1966 files, 35070 keys; emitted 395 files, 8184 declarations outside @media; UA 2 files, 114 entries); engine inputs, line breaks and pixel manifest entries unchanged; its only other failures are the 180 added controls-* files of A3 (A2 alone adds none)
…st base had): the glyph-clearance pins compose additively, REPL-a's and INL1a's terms plus the 10 controls cases' own, the same terms as on form-a3 022fcc7 (ios and android DPR 2: edge +68, edge:glyph +22, border +6, rescued edge +67; DPR 3: +66, +22, +6, rescued edge +64 and border +4; android 2.625: +68, +22, +6, rescued edge +60); with the controls cases filtered out the REPL-a pins hold exactly
…b1, PNT2 1-2, PIN-DERIVE) into form-a3-v2 Resolutions by intent: - block.ts: a block button's fit-content auto width now clamps against master's stretched size (Blink-order margins, layout opportunity). - docs/ports.json: block_layout_algorithm.cc keeps both sides' ranges (3341-3352 beside master's 2799-2804 and 3283-3304). - seams, paint-seams, s4b, css-escapes, pixel-reference tests: master's derived floor and pin checks replace FORM-a's literal lists; appearance and -webkit-appearance appended to seams-floor.json (DRAGON_FLOOR_WRITE=1); s4b's paint pair map gains appearance's two keywords. - animation-kinds.ts: appearance is discrete (Chrome 145 snapshot: interpolable false). - fixture groups: controls stays after replaced, before values and states. Generated outputs take the merged side; the following regen commit rebuilds them, and the controls cases' glyph-clearance pins are appended with DRAGON_PIN_WRITE=1 after it.
…OTSPOT-SPLIT #137/#138) into form-a3-v2 Per the HOTSPOT-SPLIT migration note: master's animation-kinds.ts and fixtures.ts are taken whole; appearance's kind (discrete, Chrome 145 snapshot) moves to animation-kinds/box.ts, and the controls group is one sorted GROUPS line (it now runs after the legacy groups, in id order). Generated outputs take the merged side, rebuilt by the following regen.
…into form-a3-v2; generated outputs take form-a-v2's side, rebuilt by pnpm regen
…ITE=1 vitest run packages/parity/test/pixel-reference.test.ts); every existing case line unchanged
…ted and floor tests): packages/parity/test/css-escapes-floor.json packages/translate/test/p1-floor.json
…erated) into form-a3-v2. Conflicts: ios-layout.ts lowerBox keeps GRID's gridParent and grid styles and FORM-a3's ControlBox return (a button lowered as a grid item keeps its placement); the root check keeps FORM-a3's control-box refusal; fixtures.ts GROUPS keeps controls and master's ctx-proof, display-legacy, env; p1-floor.json takes the larger counts (form-a-v2's)
…in/master 2c48409): pnpm regen
…ted and floor tests): packages/translate/test/p1-floor.json
…1a C2) into form-a3-v2. Conflicts: ios-layout.ts lowerBox takes INL1a's Lowerer and inline runs and still returns a block <button> as a ControlBox, with the strut INL1a gives a box (a control child is not inline content); computed-checks.ts runs INL1a's checkInline on buttons too, beside checkButton, and keeps the button walk state
…in/master d938618): pnpm regen
…ted and floor tests): packages/translate/test/p1-floor.json
This was referenced Oct 9, 2026
…rm-a3-v2 Conflicts: - computed-checks.ts: checkComputed's walk keeps #77's scroller (percent-relative inside scroll containers), the PAINT_VALUES refusals and GEN-b's faults, and A3's button walk state (the enclosing button and the parent display, which display: contents passes through); checkButton and checkInsideButton run as before. - resolve.ts: the computed.ts import takes both appearanceDisplay (A3) and computeLists (GEN-b). - attributes.ts: HANDLED_ATTRIBUTES keeps button type (A3) and GEN-c's ol start and reversed and li value. - ios-layout.ts lowerTree: lowers the root with #77's propagated viewport overflow source and still refuses a root that lowers to a control box. #77 now refuses a form control in rt-hit.ts hitRefusal and hitTableOf by name (controlRefusal), so the hit lane leaves A3's controls-* cases out with that reason. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WSkSiXMPXTAsNpS9BD9LDR
…e identity base, is removed only at its initial value none (JSON key and emitted declaration); auto and any other value stay in the text, so such a file no longer hashes to the base. hit-capture-identity.test pins it (fails without the fix: every base capture and emitted file differs by appearance: none) 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: e0ed79c Run: https://github.com/compiled-run/dragoncss/actions/runs/37968435334
…s rt-hit.ts refuses a form control by name, so the hit lane leaves out A3's 10 controls-* cases. hit-refusals-controls.ts lists them with their reason; hit-report.test and lanes.test judge the exact union of the transform, radius, INL1a inline and controls refusals, each with its own reason (hit-report failed on 66fefee, ci:test-files run 37974645063: 48 left out against the 38 the old union named) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WSkSiXMPXTAsNpS9BD9LDR
…(a pin retarget). Since A2 the alias reaches the appearance longhand, refused per target as a value, and A3's controls fixtures prove none and auto (the appearance:* profile rows), so '-webkit-appearance: none' on a div now compiles on every target (CI checks on 6507542: expected blocked, got checked). The intent is kept: -webkit-appearance never takes the not-applicable path; unproven keywords (button, textfield, menulist-button) stay refused on every target with DRAGON_UNSUPPORTED_VALUE per target, and none and auto compile only through their rows on all three profiles Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WSkSiXMPXTAsNpS9BD9LDR
…inherited longhands a UA rule resets to their default The ELB-2 declared capture kept a longhand only when it differed from "unset" under a default parent. Chrome's html.css control rules reset inherited longhands to the value a default parent passes down anyway (line-height: normal, color: ButtonText), so the button key had neither, and a button under an ancestor with another line-height or colour inherited them in Dragon while Chrome reset them. scripts/capture-ua-defaults.ts now reads every element under a parent with a non-default value for each inherited milestone longhand (INHERITED_SKEW; a guard throws if a new inherited longhand has no skew, and each skew must change the parent). An inherited longhand whose value there differs from inheriting is a UA declaration, recorded when its value is the same under every parent (else the capture throws), and the declared-versus-captured check counts these resets. The unmodelled capture does the same for the inherited properties no longhand models that the control rules reset (font: -webkit-small-control's font-* longhands, letter-spacing, word-spacing, text-transform, text-indent, text-shadow, text-rendering, cursor). Self-consistency now also reproduces every key under the skewed parent, so a missed reset fails the capture; plant drop-inherited-reset (button's line-height) must fail it. ButtonText is Chrome's own computed value in each scheme's dataset. Tests: dragon controls-inherited.test.ts (platform-free) pins the button key's line-height: normal and color in both directions, light and dark, and the review's probe resolving to them (and its contents inheriting them) under body line-height 30px and red; it fails on the committed dataset. Parity fixture controls-button-inherit (ltr and rtl) compares the probe against Chrome; the hit lane refuses it by name with the other controls cases. The probe needs an author border: the UA outset border is refused. 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: fb3cdd6 Run: https://github.com/compiled-run/dragoncss/actions/runs/37982961694
…: the button and input keys' unmodelled rows gain the inherited properties html.css's control rules reset to their defaults (font: -webkit-small-control's font-* longhands, letter-spacing, word-spacing, text-indent, text-transform, text-shadow, text-rendering) beside cursor, pinned exactly in both directions; ul's declared list-style-type: disc, a master-era row the skewed capture now finds, is pinned Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WSkSiXMPXTAsNpS9BD9LDR
…r and rtl (DRAGON_PIN_WRITE=1 through pnpm ci:test-files 5b585f1 packages/parity/test/pixel-reference.test.ts --floor-write, run 37989870975); additions only Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WSkSiXMPXTAsNpS9BD9LDR
… -> 6 with controls-button-inherit (a pin retarget; the earlier cases' identity checks are unchanged and pass) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WSkSiXMPXTAsNpS9BD9LDR
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
FORM-a part 2 of 3 (T052, A2 and A3 in notes/T052J-form-a.md):
appearanceas a real longhand, and<button>as a CSS-painted control. It is stacked on FORM-a part 1 (#77) under the contract's stacked-slice exception. Its base is nowform-a-v2(#77's review-clean head a7a3267), so this diff is only this slice; GitHub moves it to master when #77 lands.Phase 1 on #77 a7a3267 (2026-10-09)
form-a-v2at a7a3267 (carrying origin/master b97cf50) in 54c50c5. Conflicts, each keeping both sides:computed-checks.ts: checkComputed's walk keeps FORM-a 1/3: the engine's form-control box kind (range, slider thumb, block button), laid out by layout() against Chrome's boxes #77's scroller (percent-relative in scroll containers), the PAINT_VALUES refusals and GEN-b's faults, and A3's button walk state (enclosing button, parent display throughdisplay: contents).resolve.ts: the computed.ts import takes bothappearanceDisplay(A3) andcomputeLists(GEN-b).attributes.ts: HANDLED_ATTRIBUTES keeps buttontype(A3) and GEN-c'sol start/reversed,li value.ios-layout.tslowerTree: lowers the root with FORM-a 1/3: the engine's form-control box kind (range, slider thumb, block button), laid out by layout() against Chrome's boxes #77's propagated viewport-overflow source and still refuses a root that lowers to a control box.controlRefusal), so the hit lane leaves out A3's 10 controls-* cases with that reason. No hit claim is made for a control.hit-capture.ts, e0ed79c): A2'sappearancelonghand, added after the identity base, is removed only at its exact initial valuenone(JSON key and emitted declaration).autoor any other value stays in the text and fails the hash. A test pins this. Without it, every base capture and emitted file failed onappearance: none.appearance:noneandappearance:autorow (web exact; ios and android caveat, paint/ltr and rtl) names controls-* cases that pass on CI at this head. Unproven appearance keywords (button, textfield, menulist-button, ...) stay refused per target with DRAGON_UNSUPPORTED_VALUE, as do the A3 refusals listed below.Retargeted pins (this phase)
hit-refusals-controls.tswith their reason;CONTROLS_REASONis anchored and allows only HitError'shit test:prefix. Intent kept: every left-out case is named with its own reason. hit-report failed on 66fefee (run 37974645063) with 48 cases left out against the 38 the old union named.-webkit-appearance: noneon a div now compiles on every target, through A3'sappearance:nonerows, so the "off the list" entry moves to its own test. Intent kept:-webkit-appearancenever takes the not-applicable path. Unproven keywords stay blocked on every target with DRAGON_UNSUPPORTED_VALUE per target, and none and auto compile only through their rows on all three profiles. CIcheckson 6507542 failed here: expected blocked, got checked.Review fix (90ee2b2, High, ua/datasets.ts:427): inherited longhands a UA rule resets
The problem: the ELB-2 declared capture kept a longhand only when its value differed from
unsetunder a default parent. Chrome's html.css control rules reset some inherited longhands to the value a default parent passes down anyway (line-height: normal,color: ButtonText), so the capture missed them. A<button>under an ancestor with another line-height or colour therefore inherited those values in Dragon, while Chrome resets them.scripts/capture-ua-defaults.ts, fb3cdd6):INHERITED_SKEW);drop-inherited-reset(button's line-height) must fail it;ButtonTextis Chrome's own computed value in each scheme:rgb(0, 0, 0)in light, and the dark dataset's own value in dark.ulgains its declaredlist-style-type: disc. It equals the initial value, so only the skewed capture finds it; in Chrome a ul under an ancestor with another list-style-type gives its items disc.controls-button-inherit(ltr and rtl) is the reviewer's probe, compared against Chrome: body with line-height 30px and rgb(200, 0, 0), and block buttons with font: inherit sizes. It covers a button with a block child that inherits the reset, an author line-height/colour that wins, and an author line-height. The probe needs an author border: without one, the UA outset border is refused (border-style: outset), so the review's probe as written does not compile.line-height: inherithas no profile row, so the author case uses explicit values. The hit lane refuses this fixture by name with the other controls cases.packages/dragon/test/controls-inherited.test.ts(platform-free). It fails on the old dataset. It pins:userAgentTextFonts(the font-weight and font-style text fonts) is unchanged. A button inside a bold or italic UA ancestor is still refused on native, so that case stays fail-closed. The font-* resets go touserAgentUnmodelledas data. The non-milestone resets cannot reach the output, because Dragon refuses those properties when an author sets them.Retargeted pins (review fix)
list-style-type: discis pinned too.--floor-writerun https://github.com/compiled-run/dragoncss/actions/runs/37989870975). These are additions only.What passed at f19f68d
pnpm typecheck(local): pass.npx vitest run): attributes, block-elements, media-runtime, paint-seams, dragon registry-claims, s4b, seams, ua-elb2, ua, not-applicable-native, controls-inherited, layout inline, rt-hit, layout rt-vectors. 14 files, 313 tests, all pass.pnpm ci:test-fileshttps://github.com/compiled-run/dragoncss/actions/runs/37990256398: 31 Chrome files pass:ios layout-vectors-device: not run), which is the device step, still pending.checksat this head: success on attempt 3 (https://github.com/compiled-run/dragoncss/actions/runs/37990256257). Attempts 1 and 2 died at "Lint the landing workflows" on the Docker Hub pull rate limit, before any test ran.pnpm pr:review 78 --once: exit 0. It reports UNREVIEWED because Macroscope is at its spending limit, with 0 unanswered findings.form-a-v2(outside.macroscope/ignore.mdpaths): about 148 KB.Outside the spec (this phase)
The sections below describe the slice as first opened. Its "What passed" figures were measured on the host at the earlier head; the section above is the current record.
What changed
appearanceand-webkit-appearance.appearanceis a real longhand (route 2a, as object-fit), with Chrome's legacy-webkit-appearancealias.base, although webref's grammar allows it.display: inline-blockrows stay as they were.@media, because an@mediarule writes only the longhands that differ (MQ-a). A newemitted-mediaplant covers that.<button>.appearance: none, orautowith an author background or border (R11, the devolve rule, from FORM-0's probe).button-blockcontrol and centres its contents safely.block.tshunk was added (amendment A3/A4-1).display: inline-blockis an ordinary UA value that an author display overrides. Any other forced row on the button key throws.typeis handled on button: a fixture with every variant matches Chrome.layout_theme.ccis LGPL (class A). computed.ts states the display table as the Chrome 145 measurement, with LayoutTheme::AdjustStyle cited as a reference only. docs/ports.json lists computed.tsAPPEARANCE_DISPLAYand analysis/elements/controls.ts as references, adds controls-identity.test.ts as a proof, and gains theblock_layout_algorithm.cc3341-3352 range that block.ts cites.What passed (host, at the head of this PR)
pnpm regenis at a fixed point: "fixed point after 1 passes, 19 steps run", no files changed. Generated outputs are in their own commits, each naming its command.pnpm typecheckpasses.pnpm test(full suite): 161 of 166 files pass, and 3709 tests pass with 1 skipped.packages/parity/out/lanes.jsonis host-only; the train's device run for this position commits it.The controls cases pass both host lanes in ltr and rtl, and every reject passes. Turning off the fit-content hunk or the display adjustment makes them fail.
controls-identity.test: every pre-existing FIXTURES case's resolved values, native layout input and web body deep-equal part 1's. It also checks the A3 helpers on their edges.
node --conditions=dragon-internal scripts/check-appearance-migration.ts 75bf9e5c5: every file that existed at part 1 differs only by appearance:@media;Engine inputs, Chrome line breaks and the pixel manifest's existing entries are unchanged. The check's only other failures are the 180 added controls-* files, which come from A3, not A2. All 13 plants fail as required.
Profile rows only gain rows and proof cases.
North star (errors 333 → 323):
<button>element errors go 7 → 0, and thetypeerrors on buttons 7 → 0;-webkit-appearance: noneis no longer an error on web and ios;font: inheritshorthand is unsupported, so they keep Chrome's control font. This is recorded on the board as TXT-W2 (T147 part 2).Changed tests and checks, with reasons
pixel-reference.test: the glyph-clearance pins add the 10 controls cases' own terms, because their button text sits close to button edges:
With the controls cases filtered out, the earlier pins hold exactly.
block-elements.test: the element table lets the control tags read the ELB-2 element keys (button reads the button key's tag).
seams.test: LONGHANDS is 71 → 72 (appearance). Appearance and
-webkit-appearanceparsing are pinned to the Chrome 145 probe: 14 keywords kept as written; base, the older -webkit- keywords, two keywords and an unknown word dropped.paint-seams.test and s4b.test: appearance joins the paint longhands, with its two keywords.
css-escapes.test: the escaped-twin count goes 13834 → 13904 (+70, the appearance and -webkit-appearance grammar words and names).
ua.test and ua-elb2.test: the element-key longhand lists gain appearance on button, input and input[type=range]. Appearance moves from the unmodelled rows to the declared rows as auto; the forced display pins are unchanged.
attributes.test:
typeis handled on button; on other elements it stays refused, naming FORM-a.scripts/capture-ua-defaults.ts: the drop-unmodelled plant is retargeted from button appearance (now modelled) to cursor. A guard makes the plant fail loudly when its target is not an unmodelled row.
check-appearance-migration.ts: counts only rules outside
@media, plus theemitted-mediaplant. No check is removed.Catch-up onto master (2026-10-05)
Merged form-a-v2 after its catch-up (#72's last review head, then origin/master f50b6ad with HOTSPOT-SPLIT #137/#138). Regenerated in 1fa2e6c (
pnpm regen). The "What passed" section above was measured at the earlier head.packages/layout/src/block.ts: the block button's fit-content auto width now clamps against master's stretched size (Blink-order margins, layout opportunity). The3341-3352range is kept in docs/ports.json beside master's.appearanceand-webkit-appearanceinseams-floor.json(longhands, shorthands, paint role);css-escapes-floor.json;p1-floor.json;glyph-clearance-pins.json(37bd1cf,DRAGON_PIN_WRITE=1). Every existing case line is unchanged; the chain checked this before committing.none,auto).appearance: DISCRETEis inanimation-kinds/box.ts(Chrome 145's interpolable snapshot lists appearance and -webkit-appearance as not interpolable). Thecontrolsgroup is one sortedGROUPSline, so it now runs after the legacy groups, in id order. No diagnostic codes, faults or regen steps are added.Passed at c201360 (no local full test, per the lane contract):
pnpm typecheck; targeted tests (this stack's tests, the layout package, parity, values, replaced-identity, controls-identity, pixel-reference, chrome-ports, css-escapes, seams, s4b, paint-seams, registry-claims, diagnostics, animation-kinds, regen and corpus-dpr): 64 of 64 files, 1916 tests passed, 2 skipped.Reviewed size: about 104 KB (41 files) against part 1.
🤖 Generated with Claude Code
Generated by Claude Code