Status — 2026-07-11
Tracking issue for the anchor v2 node model and its authored, file-first projection: Grida XML Draft 0 (.grida.xml).
The current proof lives on model-v2-anchor, with the language RFD under docs/wg/format. This branch changes no production runtime under crates/grida and does not change the packed .grida archive schema. It proves the model, source language, resolver, display list, and raster materialization before promotion.
Current thesis
A node is an anchored box with typed content. The file stores authored intent; resolution derives boxes, transforms, layout, text lines, paint geometry, and visual bounds.
The model decisions that remain locked are:
- declared, measured, and derived box sources stay distinct;
- the box is the sole layout negotiation surface;
- rotation and flips are visual-only post-layout intent;
- no stored general matrix exists outside the quarantined
lens operation list;
- primitives are parametric and may own ordinary children in their local box, so
<rect><text>…</text></rect> needs no combined shape-with-text node;
- free positioning and flex layout preserve authored bindings instead of baking one viewport's coordinates;
- reads materialize resolved geometry while writes retarget or reject typed intent;
- derivable state is not serialized.
Grida XML Draft 0
.grida.xml is the inspectable, diffable authored source. .grida remains the packed archive; conversion between them is explicit.
The root contract is:
<grida version="0">
<container width="960" height="540">
<!-- one authored scene tree -->
</container>
</grida>
Draft 0 uses direct semantic elements:
container, rect, ellipse, line, text, group, and lens;
- no separate
circle; equal ellipse extents express a circle;
- no render-node
kind; <shape> is reserved for a future custom-shape design;
- long, stable property names such as
width, min-width, and aspect-ratio;
- strict applicability and typed errors for unknown, contradictory, or out-of-context syntax.
Every property marked Draft 0 in the property registry is implemented by the proof reader/writer. Placeholder and Design rows remain deliberately invalid syntax.
Ordered paint, projected from Paint / Paints
The existing Grida paint variants and ordered Paints semantics are the source of truth. XML does not introduce a parallel style abstraction.
<rect width="320" height="180">
<fill>
<solid color="#101828"/>
<gradient kind="linear" from="0 0" to="1 1" opacity="0.8">
<stop offset="0" color="#7C3AED"/>
<stop offset="1" color="#2563EB"/>
</gradient>
<image src="./noise.png" fit="cover" opacity="0.15"/>
</fill>
<text>Example</text>
</rect>
<fill> owns an ordered paint channel; first paint is bottommost, last is topmost.
- Typed values are
solid, gradient kind="linear|radial|sweep|diamond", and contextual image paint.
visible, opacity, and blend-mode belong to each typed paint.
- Stops remain structured and ordered.
fill="#RRGGBB" is not legacy syntax: it is the canonical compact form for the common one-solid case and is mutually exclusive with <fill>.
<fill/> explicitly suppresses a primitive/text default.
- Inline paint definitions are canonical; reusable definitions/references are future work.
The accepted syntax alternatives are recorded in the RFD: direct typed children are accepted; a generic paint envelope is deferred; CSS-like functional paint attributes are rejected as canonical.
Native multiple strokes
stroke is repeatable. Each occurrence is an independent geometry with its own ordered Paints:
<rect width="320" height="180" fill="#101828">
<stroke width="12" align="outside" join="round">
<solid color="#111827"/>
</stroke>
<stroke width="3" align="inside">
<solid color="#2563EB"/>
<gradient kind="linear">
<stop offset="0" color="#A78BFA"/>
<stop offset="1" color="#60A5FA"/>
</gradient>
</stroke>
</rect>
This directly represents road casings, double borders, keylines, focus rings, and decorative outlines without duplicated scene geometry, nested wrappers, pseudo-elements, or shadow approximations. Strokes paint in source order after the node's children; each stroke's paints independently paint bottom to top.
This is the one intentional model extension: the proof owns Vec<Stroke>, while the current production scene/archive contract owns one stroke geometry plus one Paints. Production must adopt ordered stroke applications before claiming lossless Draft 0 support.
Materialized proof
The model-v2 proof now includes:
- a strict parser and fallible, self-validating canonical writer;
- semantic round-trip independent of arena IDs, with dead/cyclic/mis-parented tree rejection;
- direct primitive composition, responsive bindings, size constraints, free/flex layout, padding, gap, grow, alignment, clipping, opacity, flips, rotation, and lens operations;
- all existing solid, linear, radial, sweep, diamond, and image paint variants where Draft 0 can spell their state;
- ordered fill paints and repeated stroke geometries with alignment, caps, joins, miter limits, and dashes;
- per-paint visibility, opacity, and blend execution in painter order;
- node-local unit paint coordinates with the defined one-pixel fallback for a degenerate axis;
- structured text-line topology shared by measurement, fill, and repeated text strokes;
- host-relative image RID loading with authored/resolved-path diagnostics;
- conservative stroke-aware visual bounds and descendant-only container clipping;
- a thin
.grida.xml → PNG host using the same resolve → drawlist → paint pipeline.
The flagship source is source-becomes-surface.grida.xml. It exercises every Draft 0 element/property family, all four gradients, image paints, clipping, responsive bindings, nested text, lenses, and native multi-stroke composition.
cd model-v2/engine
cargo run --bin grida_xml_render -- \
rig/examples/source-becomes-surface.grida.xml \
target/grida-xml-source-becomes-surface.png 1600 1000
Evidence
All reviewed proof suites are green:
(cd model-v2/a/lab && cargo test) # 195 tests
(cd model-v2/engine && cargo test) # 59 tests
(cd model-v2/a/spike-canvas && cargo test) # 1 regression test
The example corpus is parsed, canonicalized, resource-resolved, resolved without ignored/error reports, and actually rendered in tests. XML well-formedness, Rust formatting, docs formatting, the repository pre-commit formatter, and root-workspace clippy also pass.
The legacy re-host screenshot oracle has not been silently re-blessed. Its old goldens encode implicit frame borders and the earlier parent-stroke order; reviewing/rebaselining those four screenshots is an explicit follow-up after the new semantics are accepted.
Compatibility boundary
| Surface |
Current status |
Existing Grida Paint variants / ordered Paints |
Projected directly; no parallel XML paint model |
| Model-v2 lab/engine |
Parses, canonicalizes, resolves, and renders Draft 0 |
| Multiple stroke geometry |
Implemented in the proof; incompatible with the current production single-geometry shape |
crates/grida production runtime |
Not yet a .grida.xml consumer |
Packed .grida archive |
Not extended for Draft 0 or repeated strokes |
| Image resources |
Strict file host preflights relative RIDs; the low-level paint executor expects an already-populated resource context |
| Text |
Topology is deterministic, but the proof metric is still synthetic; production promotion needs one real shared shaper/font contract |
No production model incompatibility was hidden by inventing XML-only state. Unrepresentable model values fail the writer; unsupported source syntax fails the reader.
Landed commits
0cf5b29b8 — docs(format): specify Grida XML Draft 0
6e3e7c4a8 — feat(model-v2): ingest and render Grida XML
eb22e7ec4 — test(model-v2): add canonical Grida XML showcase
Canonical reading order
- Grida XML Draft 0 RFD
- Grida XML property registry
- Anchor model statement
- Model-v2 engine guide
- Lab parser/writer boundary
Remaining promotion work
The issue remains open through production and archive promotion. Effects, editable vector networks, attributed text, components/reuse, durable IDs, scene images, masks, and animation remain later, versioned design work—not implicit Draft 0 syntax.
Status — 2026-07-11
Tracking issue for the anchor v2 node model and its authored, file-first projection: Grida XML Draft 0 (
.grida.xml).The current proof lives on
model-v2-anchor, with the language RFD underdocs/wg/format. This branch changes no production runtime undercrates/gridaand does not change the packed.gridaarchive schema. It proves the model, source language, resolver, display list, and raster materialization before promotion.Current thesis
A node is an anchored box with typed content. The file stores authored intent; resolution derives boxes, transforms, layout, text lines, paint geometry, and visual bounds.
The model decisions that remain locked are:
lensoperation list;<rect><text>…</text></rect>needs no combined shape-with-text node;Grida XML Draft 0
.grida.xmlis the inspectable, diffable authored source..gridaremains the packed archive; conversion between them is explicit.The root contract is:
Draft 0 uses direct semantic elements:
container,rect,ellipse,line,text,group, andlens;circle; equal ellipse extents express a circle;kind;<shape>is reserved for a future custom-shape design;width,min-width, andaspect-ratio;Every property marked Draft 0 in the property registry is implemented by the proof reader/writer. Placeholder and Design rows remain deliberately invalid syntax.
Ordered paint, projected from
Paint/PaintsThe existing Grida paint variants and ordered
Paintssemantics are the source of truth. XML does not introduce a parallel style abstraction.<fill>owns an ordered paint channel; first paint is bottommost, last is topmost.solid,gradient kind="linear|radial|sweep|diamond", and contextual image paint.visible,opacity, andblend-modebelong to each typed paint.fill="#RRGGBB"is not legacy syntax: it is the canonical compact form for the common one-solid case and is mutually exclusive with<fill>.<fill/>explicitly suppresses a primitive/text default.The accepted syntax alternatives are recorded in the RFD: direct typed children are accepted; a generic paint envelope is deferred; CSS-like functional paint attributes are rejected as canonical.
Native multiple strokes
strokeis repeatable. Each occurrence is an independent geometry with its own orderedPaints:This directly represents road casings, double borders, keylines, focus rings, and decorative outlines without duplicated scene geometry, nested wrappers, pseudo-elements, or shadow approximations. Strokes paint in source order after the node's children; each stroke's paints independently paint bottom to top.
This is the one intentional model extension: the proof owns
Vec<Stroke>, while the current production scene/archive contract owns one stroke geometry plus onePaints. Production must adopt ordered stroke applications before claiming lossless Draft 0 support.Materialized proof
The model-v2 proof now includes:
.grida.xml→ PNG host using the sameresolve → drawlist → paintpipeline.The flagship source is
source-becomes-surface.grida.xml. It exercises every Draft 0 element/property family, all four gradients, image paints, clipping, responsive bindings, nested text, lenses, and native multi-stroke composition.cd model-v2/engine cargo run --bin grida_xml_render -- \ rig/examples/source-becomes-surface.grida.xml \ target/grida-xml-source-becomes-surface.png 1600 1000Evidence
All reviewed proof suites are green:
The example corpus is parsed, canonicalized, resource-resolved, resolved without ignored/error reports, and actually rendered in tests. XML well-formedness, Rust formatting, docs formatting, the repository pre-commit formatter, and root-workspace clippy also pass.
The legacy re-host screenshot oracle has not been silently re-blessed. Its old goldens encode implicit frame borders and the earlier parent-stroke order; reviewing/rebaselining those four screenshots is an explicit follow-up after the new semantics are accepted.
Compatibility boundary
Paintvariants / orderedPaintscrates/gridaproduction runtime.grida.xmlconsumer.gridaarchiveNo production model incompatibility was hidden by inventing XML-only state. Unrepresentable model values fail the writer; unsupported source syntax fails the reader.
Landed commits
0cf5b29b8—docs(format): specify Grida XML Draft 06e3e7c4a8—feat(model-v2): ingest and render Grida XMLeb22e7ec4—test(model-v2): add canonical Grida XML showcaseCanonical reading order
Remaining promotion work
.grida.xmlDraft 0 and its property applicability..grida.xmlloading/saving and file association to the product surface.The issue remains open through production and archive promotion. Effects, editable vector networks, attributed text, components/reuse, durable IDs, scene images, masks, and animation remain later, versioned design work—not implicit Draft 0 syntax.