Skip to content

The legacy seam program — modularize crates/grida for v2 promotion #27

Description

@softmarshmallow

Status — 2026-07-18

Umbrella for the legacy seam program: reorganizing crates/grida into modular, model-agnostic shape so the v2 engine promotion (#9) consumes modules, not forks. Migration by extraction, not reimplementation.

All work lands on main. The model-v2-anchor branch is locked — design reference only. Its WG spec overlay is landed on main by #26; those specs are what the seams build against.

Thesis

The legacy engine is already mostly IR-mediated. v1-model entanglement is confined to three choke points:

  1. crates/grida/src/import/svg/pack.rs — walks the existing IRSVG IR but emits v1 node schema records directly.
  2. crates/grida/src/import/html/mod.rs — walks Stylo ComputedValues and emits v1 records directly (no IR; duplicates the htmlcss cascade front-end verbatim).
  3. The painter's model→display-list compilation (painter/layer.rs, geometry.rs, painter_debug_node.rs) — the draw loop itself has zero model references.

Already agnostic: the htmlcss/ renderer (own StyledElement→LayoutBox→Skia pipeline), the cg/ leaf vocabulary (one skia From impl from standalone), Skia-textlayout shaping, and the foundation crates (math2, csscascade, fonts).

Each seam gets: a name first, an architecture test locking the boundary, behavior-preserving refactors, and pixel/snapshot gates. The v2 engine is treated as a foreign consumer we cannot rewrite — contracts stay agnostic, never legacy-shaped or v2-shaped.

The deciding rule (standing doctrine for this program)

A module becomes a workspace crate when its second consumer appears in the workspace — and not before. Until then it stays an in-crate module whose boundary is locked by an architecture test enforcing the same import rules cargo would enforce after extraction, so extraction later is a git mv plus a Cargo.toml, not a design event.

Naming exercises are per-extraction gates (the name comes first), scheduled at extraction time — not now.

Milestones

Milestone Contents Status
M0 — bootstrap WG spec overlay on main (#26); this issue + seam issues; gate baseline recorded (comment below) done
M1/M2 — mechanical seams cg decouple (#34); SVG sink inversion (#35); HTML gate + front-end share (#36, #41) done
M3 — design tracks resolved-text artifact (#40); paint/display-list vocabulary RFDs (#38); painter narrowing (#39) done
M4 — extraction-readiness review per candidate module: dependency closure verified, governing spec on main, naming exercise scheduled done — see the M4 comment

Seam issues (each carries its exit criterion and gate commands): filed as follow-ups and linked in the checklist below.

Gate baseline

Recorded in a comment below after the baseline run. Every seam's exit criterion appends "…and the M0 baseline is unchanged."

  • cargo test -p grida
  • cargo run --release -p grida_dev -- reftest run --suite-dir fixtures/local/resvg-test-suite --renderer iosvg --threshold 0.1 (⚠️ iosvg, not the reftest-run.sh default htmlcss — the htmlcss renderer bypasses pack.rs entirely)
  • grida_wpt fixtures/test-html/suites/L0.exact.json at 100% vs the Chromium oracle
  • @grida/canvas-wasm builds (crates/grida-canvas-wasm && just build)

Non-goals (locked for the whole program)

  • No format/grida.fbs changes (the SCHEMA_VERSION lockstep with gridaco/grida holds; see The engine migration — history & the consolidation guideline (residue from gridaco/grida) #1).
  • No wasm-surface changes@grida/canvas-wasm publishing is untouched throughout.
  • No type reshaping of Paint/Stroke/Color/TextStyleRec — vocabulary convergence is spec-first work whose implementation belongs to the promotion program.
  • No geometry-IR convergence (v2 PathArtifact vs legacy d: String) — no legacy-side choke point exists; doing it now would be v2 promotion in disguise.
  • No tree-level HTML convergence (importer consuming collected StyledNode trees / LayoutBox) — baked positions and inline-merge semantics are intentional pixel changes, out of scope.
  • No edits to model-v2/** — the branch is locked.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    canvaslegacyApplies to the archived pre-n0 implementationmigration

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions