WORK-337
ID:WORK-337Status:draft

Enforce parent nesting at build time

Turn RuneConfig.parent into a validated, self-declared requiresParent constraint (SPEC-084). A child rune that declares it must live inside a given parent, but appears outside it, surfaces a diagnostic instead of rendering silently-broken output. Crucially this is open-world: only a rune that self-declares a requirement is ever checked — the framework keeps no registry of allowed children, so third-party runes on either side just work.

Priority:mediumComplexity:moderateMilestone:v0.19.0Source:SPEC-084
changeset-release/main View source

Criteria completion

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

Tracking started Jun 5 — check back for trends.

Branches 3
History 3
  1. e1084e4
    Created (draft)by github-actions[bot]
  2. 33c6175
    Content editedby Claude
    plan: revise SPEC-084 to an open-world composability model
  3. 33e11b7
    Content editedby Claude
    plan: shape v0.19.0 around polish, composability & rollups

Acceptance Criteria

  • RuneConfig exposes a self-declared requiresParent (formalizing parent); there is no container-side allowedParents/forbiddenParents.
  • The pipeline detects a rune that declares requiresParent: X appearing without an X ancestor and reports it with the rune name and location.
  • Severity: warning by default; error for the structurally-meaningless set (accordion-item, tab, tab-panel, breadcrumb-item, juxtapose-panel, bento-cell, definition, step, tier, map-pin, itinerary-day, itinerary-stop).
  • A rune that declares no constraint is never flagged (open composition is unrestricted).
  • Tests cover: a valid nesting, an error case (strict child stranded), a warning case, a third-party-style child requiring a known parent, and an unconstrained rune nested freely (no diagnostic).

Approach

The engine already threads parentRune through the recursive walk (packages/transform/src/engine.ts), so the immediate-ancestor chain is available. Either check during that walk or in a dedicated validation pass over the transformed tree. The check is purely "does this rune's self-declared required parent appear among its ancestors" — no cross-rune knowledge, no allow-list. Default non-breaking; gate the strict set as errors.

References

  • packages/transform/src/engine.ts (parentRune propagation)
  • packages/content/src/pipeline.ts
  • Contract: SPEC-084