fix(import): carry Figma strokes through real stroke channels instead of dropping them#6419
Merged
Merged
Conversation
… of dropping them
The material audit showed strokes as the only property family losing
material on the Triaz files (decode-stage emitted/declared 42/65, 42/65,
33/83). Three root causes, all fixed generally:
1. Gradient strokes dropped. GRADIENT_LINEAR strokes ("Oval" / "knob
base" rims) had no channel to ride: the box border is solid-only and
SvgPathWidget had no gradient stroke. Added the full mirror of the
fill-gradient path: SvgPathWidget::set_stroke_gradient (parsed
per-frame, solid stroke as the parse-failure fallback, painted via
Canvas::set_stroke_gradient_linear), a setSvgStrokeGradient bridge fn
+ manifest/oracle rows, codegen emission from svg_stroke_gradient,
native-materializer wiring, and decoder lowering to a new envelope
strokeGradient channel. design_ir_json captures the stroke channels
unconditionally (not path_data-gated) so an ellipse whose path is
synthesized later keeps its rim.
2. No geometry at all for the FX knobs' "Oval" rim: master AND every
instance carry EMPTY fillGeometry/strokeGeometry, leaving only the
authored vector network. paths.mjs now decodes
vectorData.vectorNetworkBlob (layout self-validated by exact byte
consumption; refused for regions, branching vertices, or
BOOLEAN_OPERATIONs) into the shape's centerline, which the stroke
channels above paint at the declared weight.
3. INSIDE/OUTSIDE stroke bands render double-width. Figma bakes those
bands UNCLIPPED — the boundary outlined at ±weight (verified: a
weight-2 INSIDE "Polygon 5" carries a 4px band) — and painting the
blob verbatim drew the XY-pad triangle fat and bright (#373737 vs
Figma's #2b2b2b, dE 3.84). The decoder now prefers the fill outline
with a centered stroke channel (right width/color, half a weight off
in position) and raises stroke-align-approximated.
A filled vector's separate stroke also rides the same path as stroke
channels now (SvgPathWidget fills then strokes one path; exact for
CENTER align) instead of a whole-px CSS border.
Audit accuracy fixes that the counts depended on: pushDiag records the
instance-path node id (the master guid never joined against the
per-instance materials sidecar, so the diagnosed column read 0), and
the stroke tally recognizes every legitimate survival channel — border,
stroke/strokeGradient, and a stroke-only vector's band fill (48
sequencer step-cell ticks were rendering correctly while counted as
silent drops).
Decode-stage stroke counts on the three Triaz files close to 65/65,
65/65, 83/83 (was 42/65, 42/65, 33/83) with codegen-stage 46+20, 46+20,
33 of the same — zero unaccounted. thumb_parity: the (1006,189)
triangle block clears in both FX files; no block regresses; the
reference mixer frame stays at 43/43 with only sub-pixel AA shifts from
fractional stroke widths.
Hotspot-Grow: test/test_design_import_codegen.cpp reason="new end-to-end test: synthesized ellipse carries its gradient stroke onto the path"
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014e8kbMn8Sf4mF8ozsy1Jot
# Conflicts: # tools/import-design/fig/paths.mjs # tools/import-design/fig/paths.test.mjs
auto-merge was automatically disabled
July 23, 2026 08:40
Pull request was closed
shipyard-local
Bot
removed this pull request from the merge queue due to a manual request
Jul 23, 2026
shipyard-local
Bot
removed this pull request from the merge queue due to a manual request
Jul 23, 2026
shipyard-local
Bot
removed this pull request from the merge queue due to a manual request
Jul 23, 2026
github-merge-queue
Bot
removed this pull request from the merge queue due to invalid changes in the merge commit
Jul 23, 2026
shipyard-local
Bot
removed this pull request from the merge queue due to a manual request
Jul 23, 2026
shipyard-local
Bot
removed this pull request from the merge queue due to a manual request
Jul 23, 2026
shipyard-local
Bot
removed this pull request from the merge queue due to a manual request
Jul 23, 2026
shipyard-local
Bot
removed this pull request from the merge queue due to a manual request
Jul 23, 2026
shipyard-local
Bot
removed this pull request from the merge queue due to a manual request
Jul 23, 2026
shipyard-local
Bot
removed this pull request from the merge queue due to a manual request
Jul 23, 2026
github-merge-queue
Bot
removed this pull request from the merge queue due to invalid changes in the merge commit
Jul 23, 2026
github-merge-queue
Bot
removed this pull request from the merge queue due to invalid changes in the merge commit
Jul 23, 2026
danielraffel
force-pushed
the
fix/svg-stroke-survival
branch
from
July 23, 2026 14:37
7de2d11 to
6f9c5bf
Compare
Hotspot-Grow: test/test_design_import_ir.cpp reason="focused DesignIR stroke channel round-trip regression coverage" Hotspot-Grow: core/view/src/design_ir_json.cpp reason="serialize and parse SVG stroke channels" Hotspot-Grow: core/view/src/design_import_native_common.cpp reason="materialize SVG stroke channels in native imports" Hotspot-Grow: core/view/src/design_codegen.cpp reason="emit SVG stroke channel bridge calls"
danielraffel
force-pushed
the
fix/svg-stroke-survival
branch
from
July 23, 2026 14:57
6f9c5bf to
9066bc1
Compare
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.
Item #2 of the Figma-import hardening plan. Stacked on #6416 (fill-rule) — its diff reduces to only the stroke changes once #6416 merges.
Strokes were the only material property the audit showed losing (96 across the 3 files). Ground truth differed from the plan in useful ways:
SvgPathWidget::set_stroke_gradient→Canvas::set_stroke_gradient_linear,setSvgStrokeGradientbridge + manifest + oracle, codegen, IR capture, native, decoder lowering). Caveat: all 20 rims are paint-opacity-0 (designer-disabled; Figma renders them invisible too) — verified by audit + Skia raster proof.Verification
svg|path|import|design|native|canvasall pass except the known pre-existing PulpSampler SEGFAULT. JS 136/136. New tests: gradient-stroke unit ×3 + Skia raster proof + bridge/IR round-trips + ellipse-synthesis e2e + vector-network/INSIDE-band/instance-diag scene tests.🤖 Generated with Claude Code
🔎 Provenance
codexm3/Volumes/Workshop/Code/pulp019f8d7d-1d7b-7b00-b48a-e4c4213b1161Resume
Jump to this tab
Relaunch (any agent)
stamped 2026-07-23 14:37 UTC