WORK-466
ID:WORK-466Status:done

Canonical layout vocabulary const (seed grid/list)

Create the shared canonical-layout-token const that ADR-018 establishes, seeded with grid and list. This is the enabling work for the whole canonical-pool model and the first thing SPEC-099 and SPEC-100 both build on.

Priority:highComplexity:simpleMilestone:v0.26.0Source:ADR-018

Criteria completion

Criteria completion: 4 of 4 (100%) checked; history from Jun 25 to Jun 250%25%50%75%100%Jun 25Jun 25
Branches 3
History 4
  1. 7328210
    • ☑ A canonical-token const exists in a shared importable location, seeded with `grid` and `list`.
    • ☑ The const composes with local literals so a rune's `matches` is `canonical picks + local values`.
    • ☑ No existing rune's values or output change as a result of this item (ADR-018 ships zero behaviour change on its own).
    • ☑ The rune-authoring guide documents the canonical pool, the two-tier model, and the graduation rule.
    by bjornolofandersson
  2. b7e08bc
    Content editedby Claude
    WORK-466: canonical layout vocabulary const (ADR-018)
  3. ad0a142
    Created (ready)by bjornolofandersson
  4. 17d2678
    Content editedby Claude
    v0.26.0: accept ADR-018 + SPEC-099/100/108, break down into 15 work item

Scope

  • Add a canonical-token const in a shared location every rune schema can import (packages/runes — alongside the other shared schema helpers). Seed set: grid, list. (carousel is added later by the carousel-token work item.)
  • Shape it so a rune's matches array is built from canonical picks plus any local string literals (e.g. LAYOUT.grid, LAYOUT.list), per ADR-018 §4.
  • No rune migrations in this item — purely introduce the const. Existing runes keep their literals until independently revisited (ADR-018 §5, lazy migration).
  • Document the two-tier model + graduation rule in the rune-authoring guide so new runes pick from the pool rather than minting private values.

Acceptance Criteria

  • A canonical-token const exists in a shared importable location, seeded with grid and list.
  • The const composes with local literals so a rune's matches is canonical picks + local values.
  • No existing rune's values or output change as a result of this item (ADR-018 ships zero behaviour change on its own).
  • The rune-authoring guide documents the canonical pool, the two-tier model, and the graduation rule.

Dependencies

None. Foundational — the first work item; the feature layout axis and the carousel token both build on it.

References

  • Decision: ADR-018 (canonical layout vocabulary, §4 single shared const, §5 lazy migration).
  • Consumers: SPEC-099 (first consumer — grid/list), SPEC-100 (adds carousel).

Resolution

Completed: 2026-06-25

Branch: claude/work-466-canonical-layout-const

What was done

  • packages/runes/src/layout-vocabulary.ts (new) — the canonical layout vocabulary const per ADR-018: LAYOUT (named tokens { grid, list }), CanonicalLayout type, CANONICAL_LAYOUTS readonly array, and a layoutMatches(canonical, ...local) helper that returns a fresh array composing canonical picks with rune-local literals. Doc comment captures the two-tier model + graduation rule. Seed set is grid/list; carousel graduates in SPEC-100 (WORK-470).
  • packages/runes/src/index.ts — re-export LAYOUT, CANONICAL_LAYOUTS, layoutMatches, and the CanonicalLayout type from the package entry.
  • packages/runes/test/layout-vocabulary.test.ts (new) — locks the seed set, the canonical+local composition, subset support, and fresh-array-per-call.
  • site/content/extend/rune-authoring/patterns.md — new "Canonical layout vocabulary" section documenting the two-tier model, the graduation rule, the import/usage pattern, and that local values are sanctioned.

Notes

  • Purely additive — no existing rune was touched, so output is byte-unchanged (AC 3). Runes migrate to importing from the const lazily as they're revisited (ADR-018 §5); feature is the first consumer in WORK-467.
  • Full packages/runes suite green (864 tests, incl. the 4 new); types/transform/runes build clean. (The repo build script's generate-examples prestep needs npm install first in a fresh clone — unrelated to this change.)