Problem
Render identifies a promoted container by the children pointer the capture side stamps on it. Once promotion stops stamping that pointer — because a promoted container's subtree stays nested in place rather than being hoisted behind a reference (#665) — nothing distinguishes a promoted container from a promoted text or glyph layer.
The consequence is that a frame captured from the Figma file renders back as a real component instance instead of a frame. Its children still land in the right place, so the result is visually close and degrades gracefully, but frame-to-frame fidelity is lost and the run warns.
This is a pre-existing gap being widened rather than a new one: an empty promoted frame already has no pointer today, so one carrying a consumed fill colour already mis-identifies as a glyph. Flattening widens the blast radius from empty frames to all promoted frames, which is what forces the fix.
Potential solution(s)
- Discriminate a promoted container by whether it has layout children, which the layout walk already knows
- Drop the pointer read rather than keeping it as a fallback. Composition output, including existing slot content and instance examples, is not being migrated in this release, so there is no older spec shape to stay compatible with — and keeping a second route to the same answer would only preserve the one that is going away
- With nothing reading it, the
children pointer in the element extension can leave the capture side entirely, rather than being written and ignored
Acceptance criteria
Case data
- Workspace: specs-testing — round-trip testing
- Territory: figma-from-specs
- Size: s
Notes
Required by #665 and deliberately out of its scope — the capture change is self-contained without it, and until this lands promoted containers render back as instances rather than frames, a known and graceful regression.
No backward compatibility is required. Composition output is allowed to break in this release and will not be migrated, so a spec carrying the old hoisted-pointer shape does not need to keep rendering.
One residue stays open after this: an empty promoted frame has neither a pointer nor layout children, so it remains undiscriminable. The durable answer is to record the promoted kind on the element extension, which is a schema change needing its own ADR. A weaker in-package stopgap keyed off a consumed layout style is container-exclusive but fails for a name-selected entry with an empty rule set, which consumes nothing (ADR-100). Noted as a boundary, not proposed.
Implementation details are tracked internally.
Problem
Render identifies a promoted container by the
childrenpointer the capture side stamps on it. Once promotion stops stamping that pointer — because a promoted container's subtree stays nested in place rather than being hoisted behind a reference (#665) — nothing distinguishes a promoted container from a promoted text or glyph layer.The consequence is that a frame captured from the Figma file renders back as a real component instance instead of a frame. Its children still land in the right place, so the result is visually close and degrades gracefully, but frame-to-frame fidelity is lost and the run warns.
This is a pre-existing gap being widened rather than a new one: an empty promoted frame already has no pointer today, so one carrying a consumed fill colour already mis-identifies as a glyph. Flattening widens the blast radius from empty frames to all promoted frames, which is what forces the fix.
Potential solution(s)
childrenpointer in the element extension can leave the capture side entirely, rather than being written and ignoredAcceptance criteria
childrenpointer to decide what a promoted element isCase data
Notes
Required by #665 and deliberately out of its scope — the capture change is self-contained without it, and until this lands promoted containers render back as instances rather than frames, a known and graceful regression.
No backward compatibility is required. Composition output is allowed to break in this release and will not be migrated, so a spec carrying the old hoisted-pointer shape does not need to keep rendering.
One residue stays open after this: an empty promoted frame has neither a pointer nor layout children, so it remains undiscriminable. The durable answer is to record the promoted kind on the element extension, which is a schema change needing its own ADR. A weaker in-package stopgap keyed off a consumed layout style is container-exclusive but fails for a name-selected entry with an empty rule set, which consumes nothing (ADR-100). Noted as a boundary, not proposed.