Skip to content

websem: close direct SVG paint-order - #133

Merged
softmarshmallow merged 1 commit into
mainfrom
rung/svg-paint-order
Sep 5, 2026
Merged

websem: close direct SVG paint-order#133
softmarshmallow merged 1 commit into
mainfrom
rung/svg-paint-order

Conversation

@softmarshmallow

Copy link
Copy Markdown
Member

Verdict

PO1 CLOSE/SPLIT: close the direct SVG paint-order presentation-attribute row at the complete standard-track grammar, while leaving the CSS property row open at the pinned Stylo boundary.

The pinned Servo-mode Stylo has no paint-order longhand. This change therefore resolves only direct SVG presentation attributes through one SVG-namespace-bounded inherited walk; authored inline and stylesheet CSS continue to refuse by a stable property name. No matcher is added beside the cascade.

What changed

  • Parse normal | [ fill || stroke || markers ] with CSS token rules, including comments, escapes, ASCII case, CSS-wide values, invalid fallback, inheritance, and normal-order completion of omitted members.
  • Preserve the established single-node frame for normal-normalized values.
  • Lower non-default values to independently owned, source-neutral fill and stroke frame facts with common source provenance, then move the already-resolved marker span into the requested order.
  • Keep opacity/filter/mask/clip around one contiguous client transaction and roll the whole client back on marker-source failure.
  • Replace the broad stroke/paint-order refusal with four focused live-substitution rows (var(), env(), attr(), experimental if()) plus the independent CSS-property row.
  • Add 30 primitive/HTML cells, one pinned-Ahem text cell, and 11 focused contract tests. The evidence estate is now 1,157 Chromium-baked primitive cells plus 16 sampled frames; the text estate has 16 exact pixel cells and eight exact-number geometry witnesses; the named refusal register has 234 rows.

Measured cruxes

Chromium 149.0.7827.55 was measured through the shared hash-pinned capture module, and every candidate also rendered through both actual n0 CLI admissions.

  • All six normalized orders are pairwise distinct; the closest pair differs by 22 pixels at maximum channel delta 198.
  • The manual LAW pass found a missed token-position class: stroke var(...), stroke env(...), typed stroke attr(...), and stroke if(...) all equal stroke markers in Chromium. The first implementation silently selected normal in both admissions, changing 816 pixels at delta 161. The parser now patrols the complete top-level token stream, and focused refusal cells place each function after stroke.
  • The manual REPRO pass found that the original all-elements atlas did not visibly exercise paint-order on <line>. A dedicated stroke/marker line witness now differs from normal by 92 pixels at delta 197 and is committed.
  • A marker whose only output comes from a transparent-source feFlood differs between markers-first and normal by 112 pixels at delta 197, with Chromium pixels [37,99,235,255] versus [220,38,38,255] at (44,25). It already reaches the registered transactional marker-source-effect refusal in strict and best-effort paths, so it remains outside this rung (measured, not celled).
  • A circular clip plus luminance-mask probe reduced to the existing declared native-circle antialiasing ring. Straight-edged committed controls isolate paint ordering; no tolerance or unrelated issue changed.

Gate sensitivity

Each deliberate defect was restored before the final green run:

  • forcing every value to normal made just gate fail 27 named cells (largest 2,017 pixels; max delta 214);
  • moving markers to the end failed eight cells, including marker-middle at 45 pixels/delta 197 and line-marker at 92 pixels/delta 197;
  • dropping the deferred client-opacity envelope changed the opacity cell by 1,936 pixels/delta 104;
  • reusing the fill identity for the stroke fragment failed the owner law before rasterization with duplicate Identity(1);
  • inspecting substitutions before proving two live operations made the inert-functions cell refuse.

Verification

  • just bake — Chromium 149.0.7827.55 verified 1,157 primitive oracles without replacing an existing oracle
  • just gate
  • just status
  • cargo test --workspace --exclude grida-canvas-wasm
  • cargo clippy --no-deps --workspace --exclude grida-canvas-wasm -- -D warnings
  • cargo fmt --all -- --check
  • pnpm fmt:check
  • pnpm exec oxlint --deny-warnings
  • pnpm --filter www types:check
  • pnpm --filter @grida/reftest typecheck
  • pnpm --filter @grida/reftest build
  • pnpm --filter @grida/reftest test — 51 passed, one skipped
  • pnpm --filter www exec next build --webpack — 177 static pages generated

The saved .agents/workflows/verify-rung.js runner is not exposed in this environment. I reproduced its independent TICK/LAW and REPRO roles manually; those passes found and fixed the two issues above. The exact local Turbopack next build remained silent in its optimized-build phase and was stopped after a bounded wait; the equivalent webpack production build passed, and hosted Node CI remains required for the exact Turbopack command.

No conformance score was produced. FLIP records, rules, and baselines are untouched. No tolerance was added.

Advances #43.

@vercel

vercel Bot commented Sep 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
nothing Ready Ready Preview Sep 5, 2026 9:52am UTC

Request Review

@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 44137379-95aa-44d2-9018-be4eba06b446

📥 Commits

Reviewing files that changed from the base of the PR and between d66d5db and fa81513.

⛔ Files ignored due to path filters (67)
  • fixtures/web-first/chromium/html-inline-svg-paint-order.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-child-override.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-clip.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-complete-grammar.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-context-paints.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-css-wide-inheritance.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-currentcolor-alpha.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-filter.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-gradient.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-group-inherited.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-inert-functions.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-invalid-inheritance.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-line-marker.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-link-inherited.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-marker-middle.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-marker-source.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-mask-source.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-mask.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-nested-inherited.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-nested-viewport.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-opacity.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-pattern-paint.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-pattern-source.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-root-inherited.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-shape-elements.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-token-grammar.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-transform-vector-effect.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-use-inherited.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-use-target.png is excluded by !**/*.png
  • fixtures/web-first/chromium/svg-paint-order-use-transformed.png is excluded by !**/*.png
  • fixtures/web-first/svg-paint-order-child-override.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-clip.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-complete-grammar.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-context-paints.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-css-wide-inheritance.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-currentcolor-alpha.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-filter.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-gradient.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-group-inherited.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-inert-functions.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-invalid-inheritance.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-line-marker.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-link-inherited.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-marker-middle.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-marker-source.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-mask-source.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-mask.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-nested-inherited.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-nested-viewport.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-opacity.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-pattern-paint.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-pattern-source.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-root-inherited.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-shape-elements.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-token-grammar.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-transform-vector-effect.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-use-inherited.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-use-target.svg is excluded by !**/*.svg
  • fixtures/web-first/svg-paint-order-use-transformed.svg is excluded by !**/*.svg
  • fixtures/web-first/text/chromium/svg-text-paint-order-inert.png is excluded by !**/*.png
  • fixtures/web-first/text/svg-text-paint-order-inert.svg is excluded by !**/*.svg
  • fixtures/web-first/unsupported/svg-paint-order-attribute-attr.svg is excluded by !**/*.svg
  • fixtures/web-first/unsupported/svg-paint-order-attribute-env.svg is excluded by !**/*.svg
  • fixtures/web-first/unsupported/svg-paint-order-attribute-if.svg is excluded by !**/*.svg
  • fixtures/web-first/unsupported/svg-paint-order-attribute-var.svg is excluded by !**/*.svg
  • fixtures/web-first/unsupported/svg-paint-order-css-property.svg is excluded by !**/*.svg
  • fixtures/web-first/unsupported/svg-stroke-paint-order.svg is excluded by !**/*.svg
📒 Files selected for processing (17)
  • crates/n0_cli/README.md
  • crates/websem/src/svg.rs
  • crates/websem/tests/marker_contract.rs
  • crates/websem/tests/paint_order_contract.rs
  • crates/websem/tests/strokes_contract.rs
  • crates/websem/tests/unsupported_corpus.rs
  • docs/wg/consolidation/svg-engine-of-record.md
  • docs/wg/consolidation/web-checklist.md
  • fixtures/web-first/README.md
  • fixtures/web-first/STATUS.md
  • fixtures/web-first/html-inline-svg-paint-order.html
  • fixtures/web-first/oracle-bake.json
  • fixtures/web-first/primitives.json
  • fixtures/web-first/text/README.md
  • fixtures/web-first/text/cases.json
  • fixtures/web-first/text/oracle-bake.json
  • fixtures/web-first/unsupported/README.md

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


Walkthrough

The change adds SVG paint-order presentation-attribute support. It parses inherited values, normalizes six orderings, reorders fill, stroke, and marker frame items, and adds contract tests, fixtures, oracle records, and documentation.

Changes

SVG paint-order support

Layer / File(s) Summary
Paint-order resolution and frame emission
crates/websem/src/svg.rs
The SVG compiler parses inherited paint-order attributes, normalizes omitted operations, splits fill and stroke items, and places markers and opacity scopes according to the resolved order.
Rendering and refusal contracts
crates/websem/tests/paint_order_contract.rs, crates/websem/tests/marker_contract.rs, crates/websem/tests/strokes_contract.rs, crates/websem/tests/unsupported_corpus.rs
Tests cover supported orderings, inheritance, substitutions, frame identity, damage, opacity, marker failures, namespace boundaries, and CSS-property refusals.
Rendering fixtures and oracle records
fixtures/web-first/html-inline-svg-paint-order.html, fixtures/web-first/primitives.json, fixtures/web-first/oracle-bake.json, fixtures/web-first/STATUS.md, fixtures/web-first/text/*
The fixture corpus adds SVG and inline-HTML paint-order cases, Chromium oracle records, refusal rows, and one inert text case.
Capability documentation and corpus accounting
crates/n0_cli/README.md, docs/wg/consolidation/*, fixtures/web-first/README.md, fixtures/web-first/text/README.md, fixtures/web-first/unsupported/README.md
Documentation records the direct presentation-attribute grammar, the separate CSS-property refusal, supported routes, substitution refusals, and updated corpus counts.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: ⚪ Minimal · up to fa815

The SVG paint-order support is internally consistent and comprehensively tested, with no actionable merge-blocking risk identified.

Sequence Diagram(s)

sequenceDiagram
  participant SVGCompiler
  participant PaintOrderResolver
  participant MarkerCompiler
  participant FrameItems
  SVGCompiler->>PaintOrderResolver: resolve inherited paint-order
  SVGCompiler->>MarkerCompiler: compile marker positions
  PaintOrderResolver->>FrameItems: normalize fill/stroke/marker order
  MarkerCompiler->>FrameItems: provide marker span
  SVGCompiler->>FrameItems: emit ordered channels with opacity scope
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 24 functions across 4 files. (13 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the main change: closing support for direct SVG paint-order.
Description check ✅ Passed The description directly explains the paint-order implementation, scope, tests, evidence, and the separate CSS-property limitation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 24 functions across 4 files. (13 skipped: 12 unsupported, 1 too large.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch rung/svg-paint-order

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@softmarshmallow
softmarshmallow merged commit f5f61d1 into main Sep 5, 2026
15 checks passed
@softmarshmallow
softmarshmallow deleted the rung/svg-paint-order branch September 5, 2026 10:20
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.

1 participant