Repository navigation
BG2-a3 native on master: gradient layers drawn by Dragon on iOS and Android (supersedes #119) - #250
Merged
Merged
Conversation
… and Android Port of #119 (origin/bg2-native) onto the master port of #110: the gradient lowering, the native emitter (raster after every layout, background-layers stage), DragonBoxShape's unsnapped border box, paddings and root scroll origin, the bleed-avoidance and transformed-subtree refusals, the gradients fixture group, sample points, the two device plants (one dormant) and the bg2-reference, bg2-samples and bg2-layers tests. The interim 'background-layers-native' refusal is lifted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DE6siPvWXmHBDwbuC9zxg
… files to the seams floors Written with DRAGON_FLOOR_WRITE=1 DRAGON_PIN_WRITE=1 over paint-seams, seams and the other targeted platform-free tests; append-only. The write also appends master's radius entries and the single-run-baseline support plant, which the floors did not yet hold, and the BG2 layer longhands the compiler slice registered. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DE6siPvWXmHBDwbuC9zxg
R4's will-change refusal replaces gradientLayerOf; the lowering guards on compositesSubtree. The R13 test's synthetic elements carry will-change: auto, as every resolved element does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DE6siPvWXmHBDwbuC9zxg
…into bg2-native-prep
…se gradients under scroll containers (R4) OVFL-B compiles overflow auto and scroll natively, and Chrome scrolls such a container's contents in a composited layer of its own, so compositesSubtree counts it as a compositing reason. DragonTree.apply keeps both the gradient shape (lu, padding, rootX) and OVFL-B's scroll range and refusal writes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DE6siPvWXmHBDwbuC9zxg
…nimated colours, root overflow - RTL: the root scroller's layer starts at a whole device px (the ceiling of the overflow's left edge, as Chrome floors the negated offset into its scroll origin), on the device and in the host plans; a plan the checks should have refused (not modelled) now fails on the device and in backgroundPlans instead of drawing nothing. - Percentage paddings: contentWidth resolves a box's own paddings against its padding basis, so a child of an absolutely positioned box takes the right content width (Swift and Kotlin). - A tall gradient box rasters in strips of at most 16 MiB instead of one bitmap the size of its border box. - BG2c: an animation, or a transition a reachable state starts, of a colour a gradient box rasters (background-color, color, border colours) is refused on ios and android. - R4: the overflow the viewport takes (html's, or a propagating body's) is the root scroller, not a composited layer; the paint checks get the propagated element. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DE6siPvWXmHBDwbuC9zxg
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: 279edb2 Run: https://github.com/compiled-run/dragoncss/actions/runs/38039782352
…pos parent's paddings; plants may leave a plan unmodelled bg2-reference compared .flow's pixels where .abs (painted above it) covers them. .abs moves below .flow, and an abspos wrapper without a background now holds a gradient child whose percentage paddings take the wrapper's content box (the device's contentWidth fix). backgroundPlans throws on an unmodelled plan only when no gradient fault is planted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DE6siPvWXmHBDwbuC9zxg
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: e2eea5d Run: https://github.com/compiled-run/dragoncss/actions/runs/38043106095
…left case Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DE6siPvWXmHBDwbuC9zxg
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: 4e3675e Run: https://github.com/compiled-run/dragoncss/actions/runs/38048744983
paint-seams-floor.json and seams-floor.json take every entry of both sides: master's opacity/z-index (effects, stacking) entries and this branch's radius and gradient entries, raised to the merged registry with DRAGON_FLOOR_WRITE=1 (append-only, each side's order kept). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JzUCRZ7PRctKowaJ7qRxYa
…tays refused PNT1 made opacity a longhand, so bg2-reference's dormant-plant guard no longer reads R6(b) as refused from opacity's absence. translucencyRefusal takes no opacity: a translucent stack under opacity below 1 is refused on ios and android like any other (paint-gradient.test.ts compiles both cases), and the guard now reads that. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DE6siPvWXmHBDwbuC9zxg
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: 579173e Run: https://github.com/compiled-run/dragoncss/actions/runs/38054289835
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: b802f8a Run: https://github.com/compiled-run/dragoncss/actions/runs/38068434163
thejackshelton
pushed a commit
that referenced
this pull request
Oct 10, 2026
…XTURES pin to the batch Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JzUCRZ7PRctKowaJ7qRxYa
thejackshelton
pushed a commit
that referenced
this pull request
Oct 10, 2026
…he outline branch Source conflicts, each resolved to keep both sides: - registries and lists: box-shadow, opacity/z-index and outline coexist in paint-parsers.ts, state.ts, gen-css-grammar.ts, math.ts, s4b.test.ts, the hit-capture IDENTITY_NEW and KEYS_SINCE_BASE keys, hit-capture-identity.test.ts, hit-refusals-radius.ts (RADIUS_OUT) and paint-samples/radius.ts (clear of shadows and outline rings). - device-run.ts: the plant tables follow the paint emitter order (radius, shadow, effects, stacking, outline, transform). - engine exports: layout index.ts, paint-seams.test.ts, harness.ts, expected-dump.test.ts and native-host.ts carry the shadow and opacity exports beside the outline functions. ports.json float_rounded_rect cites both Outset and AdjustedRadiusDimension. - interaction.ts: master's OVERFLOW_AT_REST, plus the outline zeroLength. - computed-checks.ts: both imports. - profiles/types.ts, project.ts, internal.ts: OVFL-B removed nativeScrollPending (native scroll views), so only nativeOutlinePending remains. Generated files take master's side wherever both sides changed them; pnpm regen rebuilds them. Behaviour, now that master paints stacking natively: - checkOutlinePlacement asks master's stacking tree (stackingOf over resolvedStackTree) for layer items, instead of naming only positioned and transformed boxes. Opacity below 1, will-change: opacity and a flex item's z-index are refused too: Chrome paints those layers above the root's outlines, and holds the outlines inside them. - The refusal wording says Dragon draws outlines in the root view until it hosts them in their stacking context. - pointer-events.test pins outline's place in the family order, between effects and transform. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dJVP4456dCkJKMJUUf3xG
thejackshelton
pushed a commit
that referenced
this pull request
Oct 10, 2026
Catch up with #236, #250, #251, #103 and #255; generated outputs take master's side for the landing thread's batched regen. - paint-parsers, state.ts, IDENTITY_NEW: keep both sides. - paint-values: thread the new propagated argument to the checks. - shadow backdrop (#236): a box that is not visible is no backdrop for a visible descendant's shadow (Chrome paints no background there); the canvas background of html and body still is. Pinned in paint-visibility.test. - lanes.test title: a missing comma. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012dJVP4456dCkJKMJUUf3xG
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.
Requested by Jack · project thread
Before: since #235, gradients and background layers compile for web. iOS and Android refuse every one of them with "the native targets draw gradient layers from BG2-a3 on".
After: on iOS and Android, Dragon rasterises a box's background colour and gradient layers into one premultiplied bitmap, using the translated reference engine (paint-gradient.ts), and draws it in the background-layers paint stage. Gradients that Chrome draws in ways Dragon doesn't model are still refused on native at their
background-image: a transformed subtree (R13), a bleed-avoidance layer on rounded boxes, a composited layer (will-change, scroll containers), tiling, and translucent stacks.This is #119 (BG2-a3) rebuilt on current master as one unstacked PR. It supersedes #119, which is stacked on #110/#99 and was 1241 commits behind. Its source diff was applied with a 3-way merge, without the old generated outputs; regen-on-CI rebuilds them.
Deviations from #119
opacitylonghand yet (PNT1).bg2-reference.test.tscounts R6(b) as refused whileopacityis not a longhand. Its dormant-plant guard fails on purpose once opacity lands.compositesSubtree(will-change transform/opacity) replacesgradientLayerOf, and now also countsoverflow: auto | scroll. Master's OVFL-B compiles scroll containers natively, and Chrome scrolls their contents in a layer of its own. The lowering guards oncompositesSubtree.lu,padding,rootX).contentWidthmoved before the layout loop, as BG2-a3 native: gradient layers drawn by Dragon on iOS and Android (stacked on #110) #119 did.<br>get zero paddings, because master scopes their style inside a branch. Gradients on inline boxes are refused anyway.GRADIENT_EMITTERdeclares its two plants in its type.emit/runtime/state.ts: only thebackground-layersrefusal case. Master has no visibility write.device-run.ts: the two gradient plants inPLANT_CASES/PLANT_RULES, andDORMANT_PLANTS. BG2-a3 native: gradient layers drawn by Dragon on iOS and Android (stacked on #110) #119's shadow, opacity, stacking, outline and visibility entries, andPLANT_LANES, are not on master.cli/native-devices.ts: the dormant check usesisPaintPlant, because master has the line plant.fixtures.ts: thegradientsgroup is one sortedGROUPSline.pnt1-effects.test.tsis not ported. Its BG2 change extends PNT1's whole-corpus paint-order model, which master doesn't have.Changed tests and why
paint-gradient.test.ts:will-change: autoandoverflow: visible, as every resolved element does.overflow: hiddenis not refused.paint-seams.test.ts,device-run.test.ts: master's derived checks are kept; the gradient entries come from the floor files.bg2-samples.test.ts: the onePLANT_LANESassertion is removed, because master has no lanes table.plantVerdictstill checks device-pixels.paint-seams-floor.json,seams-floor.json): append-only, written withDRAGON_FLOOR_WRITE=1/DRAGON_PIN_WRITE=1.Self-review fixes (after the port)
UpdateScrollOriginflooring the negated offset; I did not re-read the source. It applies on the device and in the host plans. Before this, a fractional origin gave an empty, unmodelled plan, so gradients silently vanished and parity still passed. An unmodelled plan now fails on the device and inbackgroundPlans, except when a gradient fault is planted.contentWidthnow resolves a box's own paddings against its padding basis (Swift and Kotlin), so a child of an absolutely positioned box gets the right content width.paint-gradient.test.tsandanimations.test.ts.PaintChecknow gets the propagated element.Changed fixtures and why
gradient-abspos.html:.absand.abs-icbmoved off.flow. bg2-reference was comparing.flowpixels that a later-painted abspos box covers, in LTR and in RTL. Added.abs-wrap > .abs-kid(an abspos wrapper without a background, with a gradient child) to cover the padding fix.bg2-samples.test.tsasserts the child's paddings.Outside the spec
packages/dragon/src/analysis/paint-values/gradient.ts(R4 scroll containers, root overflow, animated colours),analysis/paint-values/types.tsandcomputed-checks.ts(the propagated element), andproject.ts(the animated-colour refusal).R6(b) after #196 (opacity)
PNT1 made
opacitya longhand. A translucent gradient stack under opacity below 1 stays refused on ios and android, like any other translucent stack, until a Chrome proof models the group.paint-gradient.test.tscompiles both cases. bg2-reference's dormant-plant guard now reads this refusal instead of opacity's absence.What passed on ec46ab8 (the current head)
pnpm typecheck: pass.pnpm -s pr:review 250 --once: exit 0. CI is green, Macroscope was skipped at its spending limit, and no findings are open.tested ec46ab83a9 at ec46ab83a9):🤖 Generated with Claude Code
https://claude.ai/code/session_015DE6siPvWXmHBDwbuC9zxg
Generated by Claude Code