WORK-314
ID:WORK-314Status:done

Engine: block-and-layout projection model

Infrastructure for SPEC-080. Adds blocks and layout to RuneConfig and the engine projection that composes a rune's transform tree with projected metadata blocks, placed explicitly into named containers. Built behind the new fields so the SPEC-079 path (zones / zoneLayouts / contentSlots / order / zoneHost / zoneHostPlacement) and the legacy slots / structure shim keep working untouched during the migration.

Priority:highComplexity:complexMilestone:v0.17.0Source:SPEC-080

Criteria completion

Criteria completion: 5 of 6 (83%) checked; tracking started on Jun 2, no incremental history yet0%25%50%75%100%Jun 2Jun 15

Tracking started Jun 2 — check back for trends.

Branches 2
History 4
  1. 4ea7f14
    Created (done)by bjornolofandersson
  2. 350ec06
    Content editedby Claude
    feat(transform): SPEC-080 block-and-layout engine + bar primitive (WORK-
  3. 05caf09
    Content editedby Claude
    plan: SPEC-080 — layout addresses flat runes via reserved 'root' key
  4. 1076766
    Content editedby Claude
    plan: SPEC-080 work breakdown (WORK-314..320) for v0.17.0

Acceptance Criteria

  • RuneConfig gains blocks — named metadata blocks, each a flat fields list + layout primitive (+ bar wrap). Theme-overridable via the existing merge chain.
  • RuneConfig gains layout — ordered child block names per container (Record<containerName, string[]>). A key is either a container's data-name or the reserved root key, which addresses the rune's own top-level children so flat runes (no content/media wrapper) can place projected blocks. data-name="root" is disallowed.
  • Engine projection. Build projected blocks from blocks; compose the final tree per layout with the resolved semantics: explicit placement only (no canonical default); projected blocks appear only where named; transform-built blocks the theme didn't name append in transform order (never dropped); omitting layout renders the transform tree verbatim with no projection.
  • Legacy paths intact. A rune opts in by declaring blocks/layout and not zones; the SPEC-079 and slots/structure paths are unchanged and their tests still pass.
  • Contracts. Block names surface in contracts/structures.json as the stable addressing API.
  • Tests. Extend packages/transform/test/engine-zones.test.ts (or a new engine-blocks.test.ts) covering container placement, the root (flat-rune) case, append-unlisted, omit-layout, and media-overlay.

Approach

Build the projection alongside the SPEC-079 dispatcher rather than replacing it. The two models coexist until every rune migrates; removal of the legacy placement surface is a later cleanup (WORK-320). Field-shape and the bar layout primitive land in WORK-315.

Dependencies

  • WORK-305 — SPEC-079 engine + layout primitives (done).

References

  • SPEC-080 — the spec being implemented.
  • SPEC-079 — the model this refines.

Resolution

Completed: 2026-06-02

Branch: claude/spec-079-implementation

What was done

  • Added blocks (Record<string, BlockDef>) and layout (Record<string, string[]>) to RuneConfig.
  • Engine: assembleWithBlocks + composeContainer + updateContainerByName. Dispatch order in step 5 is now blocks/layout → SPEC-079 zones → legacy slots/structure, so a rune opts in by declaring blocks/layout; all legacy paths are untouched and their tests pass.
  • Placement semantics: explicit only (no canonical default); projected blocks appear only where named; transform children the list didn't name append in transform order (never dropped); omitting layout renders the transform tree verbatim. The reserved root key targets the rune's own top-level children (flat runes); other keys address a container by data-name.
  • Tests: packages/transform/test/engine-blocks.test.ts (10) — intrinsic shape, align, conditional fields, flat-root placement, append-unlisted, omit-verbatim, nested-container, media-overlay, def-list block.

Notes

  • One acceptance criterion deferred: "block names surfaced in the generated structure contracts." The contract generator doesn't model projected zones/blocks today, and there is no consuming rune yet — this lands with the first migration (WORK-318, api), where it becomes testable.