Repository navigation
PNT1-effects 1/2: opacity as a native group alpha and z-index with Appendix E stacking (supersedes the opacity and stacking parts of #84-#85) - #196
thejackshelton wants to merge 36 commits into
Conversation
… byte, and z-index with CSS2 Appendix E paint order on the native tree Ported from #84 and #85 onto current master, without radius or shadow: opacity and z-index parse as Chrome 145 does (css/properties/effects.ts), opacity computes clamped, the effects module writes UIView.alpha / View.setAlpha at paint.ts opacityAlpha8, and the stacking module re-hosts and sorts layer items (lower/paint/stacking.ts). Transforms and will-change: transform or opacity (PNT2, now on master) join the stacking contexts. A z-index box that would leave the overflow clip of its containing block is refused natively. Fixtures (effects group), the paint model test against Chrome, the placement emulation test, plants alpha-ignored and order-swap, and the hit lane's refusal of stacking contexts.
…tive order differs from Appendix E's; stale-tree guard; corpus model scope pinned; dash oracle skips opacity groups
…ts on every box) and pointer-events' family order pin (effects before transform)
…lip whose native order differs, and every box a native clip view would clip outside its containing-block chain Finding 1: the order refusal covered integer z-index items only; z-index auto items (relative, absolute, opacity < 1, transformed) kept under a clip reorder the same way. Finding 2: an absolute box re-hosted under a stacking context (opacity, will-change, a flex item with z-index) inside an overflow clip outside its containing-block chain was clipped natively; stackingOf now compares every node's native clip set with its containing-block chain. Both repros are model and compile tests in paint-stacking.test. stacking-reject-clip is removed: a parity reject fixture needs blocked web output, which a native-only refusal never gives.
…applies to every box, fixed ones included
|
Landing stopped at step Fix the cause, then hand #196 back to the landing queue with the new clean head. |
…tly between 0 and 1 by name (platform compositing rounds unlike Skia; package PNT1-opacity-b); opacity fixtures take 0, 1 and clamped values, stacking-context's group is will-change: opacity
…web opacity rows against Chrome as a lane-only native case project.ts: outside the parity lanes native refuses a fractional opacity (checkTranslucent); the lanes compile it and mark the case lane-only, so it proves web rows only (pipeline.ts). pixel-reference.ts devicePoints: the device pixel lanes skip the points a translucent group paints, which only a lane-only case brings to a device. opacity-web (ltr, rtl): 0.3, 45%, an inherited 0.5, and groups with a child, text and a border, so the host model's alpha-ignored fault runs on real groups again.
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: bf86a9d Run: https://github.com/compiled-run/dragoncss/actions/runs/37499098126
# Conflicts: # packages/dragon/src/analysis/computed-checks.ts # packages/parity/src/hit-capture.ts # packages/parity/test/hit-report.test.ts
…e boxes and <br>, and the device-hit test names stacking-transform stacking.ts layoutStackTree: an inline box is an element node (z-index when positioned, opacity always); a <br> is a leaf like a text run (it paints nothing). Without it the merged tree crashed on a <br> (hit-capture in regen-on-ci: reading 'display' of undefined). lanes.test.ts: the hit lane's non-inline, non-stacking refusals are the PNT2 transform- cases and PNT1's stacking-transform, both with the transform reason. paint-stacking.test.ts: the hand-built LayoutBox gains INL1a's strut.
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: 845db75 Run: https://github.com/compiled-run/dragoncss/actions/runs/37512986344
… facts, hosted as the native tree places them
pnt1-facts failed on the merged tree: native-program.ts placed inline box and <br> nodes with facts: {} (the paint lowering runs
only on block boxes), so the device-placement check read undefined facts on inline-mixed-sizes and every other inline fixture.
stacking.ts layoutStackTree now lays inline content out flat, as the native tree does (an inline box is a childless element node
followed by its content; it never clips), and inlineStackingFacts publishes the facts of each inline box and <br>, refusing one
that would be a layer item. computed-checks.ts checkInline refuses on native an inline box with opacity below 1 or will-change:
opacity: its group would hold content the native runtime places beside its view, so it was dropped silently.
paint-stacking.test.ts: the three cases fail without the fix.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WSkSiXMPXTAsNpS9BD9LDR
# Conflicts: # packages/dragon/src/project.ts (both sides' lane-only native refusals kept: PNT1's checkTranslucent and OVFL's checkNativeScroll)
… the native tree does, and the clip refusal is lane-only OVFL made overflow auto, scroll and clip host their children in a clip view (clip.ts clipsChildren), but both stacking trees still clipped only for hidden, so a layer item inside such a box was re-hosted out of its clip view: overflow-replaced's i4 would paint unclipped on device. layoutStackTree now uses clipsChildren; resolvedStackTree clips for any overflow but visible, except an inline box and the element whose overflow the viewport takes (propagatedFrom, now exported). The stacking clip refusal moves from checkComputed to project.ts beside checkTranslucent and checkNativeScroll: a user's native compile still refuses it, and the lanes compile the item kept under its clip as a lane-only native case (overflow-end-padding's a6a and overflow-replaced's i4, both already lane-only for overflow auto), which the device pixels judge. paint-stacking.test.ts: four cases that fail without the fix. pnt1-effects.test.ts OUT pin gains overflow-replaced(-rtl): its relative image now reaches the placements and draws replaced-image, outside the model like replaced-*. 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: f3e784e Run: https://github.com/compiled-run/dragoncss/actions/runs/37840860625
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: 6f440e0 Run: https://github.com/compiled-run/dragoncss/actions/runs/37848881800
|
LAND-READY Lane receipt (PM session A): pnpm typecheck pass; 13 platform-free files (dragon expected-dump, paint-opacity, paint-seams, paint-stacking, paint-transform, pointer-events, s4b, registry-claims, profile-index, inline-lowering, overflow, interaction; layout paint-seams) pass (local, at 8a1250d); ci:regen https://github.com/compiled-run/dragoncss/actions/runs/37848881800 (regen commit 8a1250d); ci:test-files https://github.com/compiled-run/dragoncss/actions/runs/37855643718 (tested 8a1250d at 8a1250d: android-profile 5, chrome-ports 13, hit-report 9, p6a-dash-oracle 314, pnt1-effects 138, pnt1-facts 11, parity registry-claims 8 pass; lanes.test "every device lane ran" is device step pending); pr:review 196 --once exit 0 (UNREVIEWED: Macroscope spending limit). Fixes in this round: the pnt1-facts landing failure (inline stacking facts, 1ea4660) and stacking clips for OVFL auto/scroll/clip (f3e784e), each with tests that fail without the fix. Independent Claude review of the change since 83be2ed, at 8a1250d (Medium or higher only), including the OUT-pin additions and the lane-only stacking refusal: {"pr":196,"head":"8a1250d7ad1412ad3a8946a779812175bbfc8d4b","findings":[]}Generated by Claude Code |
|
Landing stopped at step Fix the cause, then hand #196 back to the landing queue with the new clean head. |
…-opacity-z # Conflicts, each resolved keeping both sides: # packages/dragon/src/css/stylesheet.ts: opacity and z-index register in #198's PAINT_VALUE_PARSERS hook (paint-parsers.ts) # packages/dragon/test/expected-dump.test.ts, packages/parity/src/native-host.ts: ExpectedEngine has opacityAlpha8 and paint.roundedShape # packages/dragon/test/pointer-events.test.ts: radius, then effects, then transform after pointer-events # packages/parity/src/device-run.ts: radius-square, alpha-ignored and order-swap plants, in registry order # packages/parity/src/hit-capture.ts: the stacking-context and border-radius hit refusals both # packages/parity/test/hit-report.test.ts, packages/parity/test/lanes.test.ts: the union of transform, stacking, radius and inline refusals # packages/parity/test/p6a-dash-oracle.test.ts: skips both an opacity group's borders and a rounded box's # scripts/gen-css-grammar.ts: both EFFECTS_LONGHANDS and RADIUS_LONGHANDS # After the merge: EFFECTS_VALUES and STACKING_VALUES gain #198's check field (null: their refusals are lane-gated in project.ts), # the NodeGeometry literals in paint-opacity and paint-stacking tests gain #198's size field, and hit-report.test pins that the # stacking and radius refusals each fire with the other present or absent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WSkSiXMPXTAsNpS9BD9LDR
…s check field and NodeGeometry size, and the radius facts pin EFFECTS_VALUES and STACKING_VALUES gain #198's check field, null: the fractional-opacity and stacking clip refusals are lane-gated in project.ts. The paint-opacity and paint-stacking applied-value calls pass #198's NodeGeometry size. paint-radius.test: a rounded box also carries PNT1's stacking facts (on every box, rt-hit reads them), so the pin checks a's radius facts and that b has only stacking, as paint-transform.test does. hit-report.test: the stacking and radius hit refusals each fire with the other present or absent. 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: 45e05ec Run: https://github.com/compiled-run/dragoncss/actions/runs/37871732935
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: a42c0bc Run: https://github.com/compiled-run/dragoncss/actions/runs/37877358100
…and counts the effects fixtures as new hit-capture-identity.test failed on the merged tree: every emitted rule gained opacity: 1 and z-index: auto with PNT1, so 2471 base files no longer hashed to the identity base. As #198 did for its corner radii, KEYS_SINCE_BASE gains opacity and z-index (the base files must still differ only by those keys and pointer-events), and IDENTITY_NEW gains the effects group's opacity-* and stacking-* fixtures (none is in the base manifest). The test fails without this and passes with it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WSkSiXMPXTAsNpS9BD9LDR
… the identity strips opacity and z-index only when neutral # Conflicts, each resolved keeping both sides: # packages/dragon/src/project.ts: checkComputed takes #218's options.faults; PNT1's lane-gated checkTranslucent (and the # checkNativeScroll and checkStackingClips calls after it) stay # scripts/gen-css-grammar.ts: EFFECTS_LONGHANDS (PNT1) then GEN-b's content and list-style longhands # Review of 9f85d98 (Medium, hit-capture.ts:217): KEYS_SINCE_BASE stripped opacity and z-index at any value, so a base fixture that # gained z-index: 3 or opacity: 0.5 would still hash to the base. They now leave KEYS_SINCE_BASE and are stripped only at their neutral # values (opacity 1, z-index auto), like #218's GEN-b longhands. hit-capture-identity.test: a new case strips the neutral pair and keeps # opacity 0.5 and 0 and z-index 3, 0 and -1; it fails with the old any-value strip. 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: eb81776 Run: https://github.com/compiled-run/dragoncss/actions/runs/37889722851
PNT1-effects, part 1 of 2: opacity and z-index with CSS2 Appendix E stacking on iOS and Android. Built from current
origin/master(6385d46) as one branch with no stack. It does not depend on radius or shadow.Supersedes the opacity part of #84 and the z-index/stacking part of #85. Both were stacked on PNT1-radius (#81) and PNT1-shadow (#82). The color-scheme and outline parts of #83, and #86/#87 (outline, foreground phase), are not covered here; outline will be a follow-up PR off master.
What changed
Source files are ported from #84/#85 and adapted to master's seams (EMS registries,
ExpectedEngine, computed checks).css/properties/effects.ts, onestylesheet.tsline,math.tsgrammars, grammar subset).autoor an integer, clamped to 32 bits at parse time as Chrome does.round(),abs()and the other math functions Dragon does not evaluate; andenv().lower/paint/effects.ts,emit/paint/effects.ts).UIView.alpha/View.setAlphato Chrome's paint alpha byte / 255.paint.ts opacityAlpha8, Skia'sgetAlphadone in float. The device runs it translated, and the host shares it.lower/paint/stacking.ts,emit/paint/stacking.ts, the state runtime'spaintOrderwrite).will-change: transform | opacity, since PNT2 is now on master.analysis/paint-values/stacking.ts, called fromproject.tsbesidecheckTranslucentsince the OVFL A: scroll containers (overflow auto, scroll, clip), viewport propagation and Chrome scroll metrics, rebuilt on master (supersedes #96/#97) #194 catch-up), on the native targets only. The root's clip is the viewport's and counts in every chain.boxes()lives in the test file, so it cannot collide with the radius lane'spaint-model.ts.Proof
opacity-basic,opacity-cascade,stacking-basic,stacking-context,stacking-escape, and the newstacking-transform(transformed andwill-change: opacityboxes against positioned ones). The rejects areopacity-reject-calcandstacking-reject-calc.paint-stacking.testcompiles each one and asserts the refusal on ios only.pnt1-effects.test: a model of Chrome's CPU raster (cc alpha folding, Skia Color32 and s32a blends, Appendix E order from the facts, whole-device-px translations) equals the committed Chrome PNGs at every non-edge sample point.OUTwith their reasons: images, rotations and scales, and a dashed border.pnt1-facts.test: emulates the device placement step by step on every layout case of the corpus. Every layer item lands in Appendix E order, and every write's[host, index]matches.paint-opacity.testandpaint-stacking.test: parsing against Chrome's computed values, the refusals, Appendix E trees (including transforms), lowering, emission, and a guard against a stale stacking tree.alpha-ignoredon opacity-basic andorder-swapon stacking-basic, both on device-pixels withinterior:rules. They run on the landing driver's device turn.Review fixes (precomputed review of 476e9bc, two Mediums)
C (overflow: hidden) > P (opacity 0.5 / relative / transformed)followed by S. It is a model test inpaint-stacking.testand a compile test, which is refused on ios only.stackingOfcompares every node's native clip set (its native ancestors' clip views) with its containing-block chain, and reports where they first differ. The repro isC (overflow: hidden) > O (opacity 0.5 / will-change / flex item with a z-index) > I (absolute). It is a model test and a compile test, also refused on ios only.stacking-reject-clipis removed: a native-only refusal can never pass the parityrejectkind, which needs blocked web output, so it was failingparity.test. Its case is a compile test now.pnt1-facts.testshows by compiling them all. The music player is unchanged at 207 of 289.Device judgement (landing driver, queue 53): native opacity limited to 0 and 1
The driver's device run found 46 iOS and 69 Android device-pixels failures, all in the opacity fixtures and
stacking-context's opacity group. Each was one off Chrome in a channel. The alpha byte is right; the compositing arithmetic is not Skia's. Both UIKit and Android blend a translucent view with exact /255 rounding:op-fold(alpha 77,rgb(230, 80, 40)overrgb(40, 60, 80)): exact /255 gives 97, 66, 68, the native capture on both platforms. Skia's folded blit gives 96, 65, 67, which is Chrome.Skia's result depends on the backdrop pixel, so no native alpha reproduces it. Ruling (PM, option 1):
analysis/paint-values/effects.tscheckOpacity, at the declaration; it names package PNT1-opacity-b).opacity-basicandopacity-cascadenow use 0, 1, 0%, 100%, 1.5, -2, 500% and calc() to 1.stacking-context's group is awill-change: opacitycontext instead of opacity 0.5. Every layout fixture must compile natively, so no fractional case stays in a fixture. The host model still pins Chrome's fractional composite bytes (pnt1-effects.test).pnpm run parity:devicesthrough/tmp/device-lease.shat ce0b8ee's source (the regen commit; 1d0a6c9 only fixes a test), on iPad (A16), iPhone 17, dragon-320, dragon-smoke and dragon-480. Every opacity and stacking case passes. The only failures are master's knownselectors-universal-rootset (28 lines, the same normalized set as master's in the driver's log), so there are zero new failures. The device outputs are not committed; the driver records its own run.Review Low (precomputed review): fractional opacity proven on web again
After the fixture change, no cited Chrome proof covered a fraction on web, so web rows overclaimed exact.
opacity-web(ltr and rtl): 0.3, 45%, an inherited 0.5, and translucent groups with a child, text and a border. The web rowsopacity:<number>,<percentage>andinheritnow cite it. No native row does: a test pins that the iOS and Android profiles never cite it.checkTranslucent). The lanes compile it and mark the case lane-only (project.ts, the same mechanism SELD-R2 uses), so it proves web rows only (pipeline.ts).pixel-reference.tsdevicePoints, used by every run file and reference). Only a lane-only case brings such a group to a device. A test pins that no other case loses a point, and that the stage and spacer points ofopacity-webstay.opacity-webis inpnt1-effects.test. The devicealpha-ignoredplant still runs onopacity-basic's opacity-0 boxes./tmp/device-lease.sh pnpm run parity:devices, on all five devices, withopacity-webincluded): zero failures beyond master's knownselectors-universal-rootset.Design note: PNT1-opacity-b, pre-compositing over a provably uniform backdrop (follow-up PR off master)
premul(colour, a8) + (dst × (256 − a8) >> 8). Otherwise each drawing composites into a premultiplied layer, which is blended withblit_row_s32a_blend. These are the modelpnt1-effects.testalready verifies byte for byte against Chrome. The result per painted region (background, each border side, text colour) becomes an ordinary opaque write. Translucent text needs the glyph coverage composite, so text inside a group stays refused at first.Rows promoted (iOS and Android, status caveat; web exact)
12 rows on each target:
opacity:<number>,opacity:<percentage>,opacity:inherit,opacity:initial, each @paint/ltrandpaint/rtl.z-index:<integer>andz-index:auto, each @paint/ltrandpaint/rtl.The coverage-rank probes (opacity
0/0.5/1; z-index1/10/-1/9999, absolutely positioned) fall in these rows. I could not reruncoverage-rank.tsfrom #146, because it rejects the current Tailwind snapshot'sna-nativeoutcome.Music player (north star)
opacity/z-indexUNSUPPORTED_PROPERTY errors are gone. The z-index ones compile, and the fractional opacities are now refused by name instead.library-button'sz-index: 40paints above the z-index 20/30 overlays outsidepage/app's overflow clip. Hosted under that clip, it would paint below them natively, so it is refused. Lifting it needs a clip-chain view (follow-up).Changed tests and checks (reasons)
paint-stacking.test: the REPL-a hand-builtLayoutBoxstyle gainsoverflowY: 'visible'. The stack tree now asksclipsChildren, which reads both axes, so the fixture needed the field the real type always has. The test's intent is unchanged.pnt1-effects.testOUTpin gainsoverflow-replacedandoverflow-replaced-rtl. OVFL's fixture has a relatively positioned image, so it now reaches the placements. It drawsreplaced-image, which puts it outside the model for the same reason asreplaced-*.paint-opacity.testcompiles its computed-value cases for web; native now has its own refusal tests. Its lowering and emission tests use opacity 0.s4b's opacity pair is 0 and 100%.paint-stacking.test's review repros useposition: relativeandwill-change: opacityin place of opacity 0.5.pnt1-effects.testchecks the alpha-ignored plant on the opacity fixtures only, sincestacking-contexthas no opacity group now.paint-seams.test: program nodes now carry the stacking facts on every box (rt-hit reads them), so "empty facts" becomes "onlystacking, on boxes".paint-transform.test: body's facts are['stacking'], not{}. The intent kept is that body has no transform facts.pointer-events.test: the paint families after pointer-events now start with effects (opacity, z-index), and transform follows them.s4b.test: opacity and z-index get value pairs, so they are checked like every other paint longhand.layout paint-seams.test: paint.ts exportsopacityAlpha8, and the index line names it.expected-dump.test,native-host.ts:ExpectedEnginegainsopacityAlpha8.p6a-dash-oracle.test: a border inside an opacity group is composited with the group alpha, which that oracle does not model.pnt1-effects.testcompares those pixels against Chrome.hit-capture.tshitRefusalandhit-report.test: the hit lane now also refuses, by name, a case with a stacking context below the root. rt-hit.ts orders positioned boxes as z-index auto. This follows the transform precedent (SELD-R2b). Only the new opacity/stacking fixtures are affected; no case the lane covered before is dropped.device-run.ts: PLANT_CASES/PLANT_RULES gain the two plants, in registry order.seams-floor.jsonandpaint-seams-floor.jsonare appended withDRAGON_FLOOR_WRITE=1. Nothing was lowered.Outside the spec
packages/dragon/src/css/paint-parsers.ts(effects registered in PNT1-radius: border-radius, its corner longhands and -webkit-border-radius drawn natively on iOS and Android (supersedes #80, #81) #198's paint value hook),packages/dragon/test/paint-radius.test.ts(facts pin),packages/parity/src/hit-capture.tsidentity keys (catch-up, 2026-10-09)packages/dragon/src/lower/native-program.ts(one line: an inline box or<br>publishes its stacking facts),packages/dragon/src/project.ts(the stacking clip refusal beside checkTranslucent),computed-checks.tspropagatedFromexported (catch-up, 2026-10-08)packages/parity/src/hit-capture.ts,packages/parity/test/hit-report.test.ts(the hit lane refusal above)packages/parity/test/p6a-dash-oracle.test.tsdocs/ports.json(cc paint_op_buffer_iterator.cc, SkPaint.h, SkBlitRow_D32.cpp, SkColorData.h, SkBlitRow_opts.h), with the notices regeneratedKnown limits (not claimed)
Catch-up after #91 (INL1a), #194 (OVFL) and #200 (CASC), 2026-10-08
The #91 catch-up (0ba1fe4, 845db75, regen 83be2ed) stopped with
pnt1-facts.testfailing on the merged tree:TypeError: Cannot read properties of undefined (reading 'layer').origin/masterwas merged twice more (#194 OVFL, then #200 CASC) and regenerated on CI.native-program.tsplaced inline box and<br>nodes withfacts: {}, because the paint lowering runs only on block boxes. 135 inline nodes had no stacking facts (inline-mixed-sizesand every other inline fixture).layoutStackTreenow lays inline content out flat, the way the native tree places it (T044 R3). An inline box is a childless element node followed by its content, and it never clips.inlineStackingFactsgives each inline box and<br>its facts. It throws if an inline box would be a layer item.checkInline(computed-checks.ts) refuses on native an inline box with opacity below 1 orwill-change: opacity. Its group would hold content the native runtime places beside its view, not inside it. Before this, the opacity was dropped silently.clip.ts clipsChildren). Both stacking trees still clipped only forhidden, so a layer item inside such a box was re-hosted out of its clip view:overflow-replaced's i4 would have painted unclipped on device.layoutStackTreenow usesclipsChildren.resolvedStackTreeclips for any overflow except visible. Two exceptions use visible: an inline box, and the element whose overflow the viewport takes (propagatedFrom, now exported).checkComputedintoproject.ts, besidecheckTranslucentandcheckNativeScroll. A user's native compile still refuses it. The lanes compile the item kept under its clip as a lane-only native case, which proves no native row, and the device pixels judge it. That isoverflow-end-padding's a6a andoverflow-replaced's i4, both already lane-only for overflow auto. Without this, those two fixtures would block native compilation, and every layout fixture must compile natively.computed-checks.ts,hit-capture.tsandhit-report.test.ts(resolved in 0ba1fe4). The OVFL A: scroll containers (overflow auto, scroll, clip), viewport propagation and Chrome scroll metrics, rebuilt on master (supersedes #96/#97) #194 merge conflicted inproject.ts, and both sides' lane-only native refusals were kept. The CASC 1: @supports decided at build time as Chrome 145 decides it; revert and revert-layer; CSS-wide keyword rows #200 merge was conflict-free.Catch-up after #208 (charset), #198 (pnt1-radius-native), #210 and #101, 2026-10-09
The driver's train merge onto af341be conflicted. Once #208 and #198 had landed (#218 failed landing and is not on master),
origin/master508db67 was merged in 949f033, then 981c068 (#210, #101) in a42c0bc. The second merge was conflict-free. Each was regenerated on CI.Conflicts in the 949f033 merge, each resolved keeping both sides:
packages/dragon/src/css/stylesheet.ts: PNT1-radius: border-radius, its corner longhands and -webkit-border-radius drawn natively on iOS and Android (supersedes #80, #81) #198 added a registry of paint value parsers (PAINT_VALUE_PARSERSincss/paint-parsers.ts). opacity and z-index (EFFECTS_VALUE_PARSERS) now register in it alongside radius, in place of a second hook. The parsers and their checks are unchanged.packages/dragon/test/expected-dump.test.tsandpackages/parity/src/native-host.ts:ExpectedEnginecarries bothopacityAlpha8and PNT1-radius: border-radius, its corner longhands and -webkit-border-radius drawn natively on iOS and Android (supersedes #80, #81) #198'spaint.roundedShape.packages/dragon/test/pointer-events.test.ts: after pointer-events come radius, then effects, then transform. All of PNT1-radius: border-radius, its corner longhands and -webkit-border-radius drawn natively on iOS and Android (supersedes #80, #81) #198's assertions are kept, plus the exact position of effects.packages/parity/src/device-run.ts:PLANT_CASESandPLANT_RULESholdradius-square,alpha-ignoredandorder-swap, in registry order.packages/parity/src/hit-capture.ts:hitRefusalkeeps the stacking-context refusal and the border-radius refusal, before the inline one.packages/parity/test/hit-report.test.tsandpackages/parity/test/lanes.test.ts: the hit lane leaves out exactly the union of the transform, stacking, radius and inline cases, each with its reason.packages/parity/test/p6a-dash-oracle.test.ts: both skips are kept, for an opacity group's borders and for a rounded box.scripts/gen-css-grammar.ts: bothEFFECTS_LONGHANDSandRADIUS_LONGHANDSare imported.Follow-ups after the merge:
EFFECTS_VALUESandSTACKING_VALUESgain PNT1-radius: border-radius, its corner longhands and -webkit-border-radius drawn natively on iOS and Android (supersedes #80, #81) #198'scheckfield, set to null. Their refusals stay lane-gated inproject.ts.NodeGeometryliterals in the paint-opacity and paint-stacking tests gain PNT1-radius: border-radius, its corner longhands and -webkit-border-radius drawn natively on iOS and Android (supersedes #80, #81) #198'ssizefield.paint-radius.testfacts pin: a rounded box also carries PNT1's stacking facts, so the pin checks a's radius facts and that b has only stacking. This is the same retargetpaint-transform.testgot.hit-report.testcases: the stacking and radius refusals each still fire when the other is present or absent.opacity: 1; z-index: autoto every emitted rule. Following PNT1-radius: border-radius, its corner longhands and -webkit-border-radius drawn natively on iOS and Android (supersedes #80, #81) #198's precedent for its radii:KEYS_SINCE_BASEgains opacity and z-index.IDENTITY_NEWgains the effects group'sopacity-*andstacking-*fixtures; none is in the base manifest.What passed
Latest, at head
9f85d98987727a5fcff05be544ac138113f75341:pnpm ci:regen:pnpm typecheck: exit 0.pnpm ci:test-files 9f85d98987…: https://github.com/compiled-run/dragoncss/actions/runs/37886639963lanes.test(native): 360 passed. 1 failed only for the missing device run (ios layout-vectors-device: expected 'not run' to be 'pass'), which is device step pending.pnpm pr:review 196 --once: exit 0. It reports UNREVIEWED, because Macroscope is at its spending limit; CI passed, and no finding is unanswered.Head
8a1250d7ad1412ad3a8946a779812175bbfc8d4b(2026-10-08, before the #198 merge):Earlier rounds:
pnpm regen: fixed point every time (last: 2 passes, at 42db25f). The outputs are in the regen commits, which hold generated files only.origin/master(88f7da8) was merged; the merge drivers resolved it cleanly. A secondpnpm regenfollowed, again a fixed point after 3 passes.pnpm typecheck: clean.parity.test): 117 files, 3632 tests at the review-Low regen. All passed except the newopacity-webtest, which compiled under the wrong project id; it is fixed in 139a827 and passes. Earlier: 117 files, 3621 tests at ce0b8ee. All pass excepts4b's fractional opacity pair, which is fixed to 0 and 100% in 1d0a6c9 and passes. Earlier, at 42db25f: dragon and layout in full, 100 files, 2316 tests; targeted, 26 files, 1441 tests. The targeted files were:pnpm native:build -- --target ios: status pass. swiftc builds the opacity and paint-order writers, and the iOS 15 availability check passes.pnpm native:build -- --target android: status pass.pnpm test(the landing driver runs it).The reviewed diff is about 160 KB, slightly over the ~150 KB guide. It is one theme (opacity groups and the stacking order they create), and splitting opacity from stacking would separate the stacking contexts that opacity creates from the code that orders them.
🤖 Generated with Claude Code
Generated by Claude Code