feat: IR-level design tokens + overlay re-skin (Phase 2a+2b)#90
Merged
Conversation
Phase 2a. A `token("color.accent")` ref is the deferred string "$color.accent"
on a color prop; unlike Phase 1's `brand.color.accent` (baked at author time),
the compiler resolves it against the scene's new `SceneIR.design` field (merged
onto the house brand) so the scene can be re-skinned later. Scoped to color
props (fill/stroke/shadowColor), so a text `content: "$5M"` is never touched;
evaluate/interpolate are unchanged (they only see resolved hex). Golden-safe:
no design + no token ref → `hasDesign` false → no resolution → byte-identical IR.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase 2b. An overlay can patch `design.color.accent` and every node that references that token re-skins on recompile. Addressed by token NAME (validated against the brand shape), so the re-skin survives an AI regen of the base and an unknown token path is reported as a loud orphan, never a crash. `sceneManifest` now surfaces the patchable `design.*` tokens. Tests cover resolution, the "$5M" content scoping, re-skin, orphan, regen-survival, and manifest. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A card whose every color is a token() ref; themed-card-reskin.json patches
design.color.{accent,bg,surface} to re-skin it with no edit to the scene.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 2 (slices 2a+2b) of the design layer. Makes the theme a first-class IR field the compiler resolves, so a scene can be re-skinned via an overlay that survives an AI regen. The CLI
--themeflag + per-brandbatch+ the 3-brand demo are the next PR (2c).2a — compile-time resolution (
packages/core)SceneIR.design?: DeepPartial<Theme>+ atoken("color.accent")DSL helper that returns the deferred string"$color.accent".$refsagainstir.design(merged onto the housebrandvia Phase 1'stheme()), in theinitialValues+pushSegmenthooks every prop value flows through.evaluate/interpolateare untouched — they only ever see resolved hex.fill/stroke/shadowColor), so a textcontent: "$5M"is never mistaken for a token (the one real collision, handled).designand no$ref→hasDesignfalse → resolution never runs → byte-identical IR. The 6 golden scenes use neither and are untouched.2b — overlay re-skin + manifest (
packages/core)OverlayDoc.design(dotted path → value).composeScenevalidates each path against thebrandshape, deep-setsir.design, and reports applied/orphan. Recompiling re-skins everytoken()ref.design.color.accentedit re-applies to any regenerated base that keeps the token; an unknown token path orphans loudly (never throws).sceneManifestsurfaces the patchabledesign.*tokens.Demo (no CLI change —
frame/renderalready take--overlay)examples/scenes/themed-card.tscolors everything viatoken();examples/overlays/themed-card-reskin.jsonpatchesdesign.color.{accent,bg,surface}.reframe frame themed-card.ts --t 1vs… --overlay …reskin.jsonvisibly re-skins, andreframe verify-overlayreports 3 applied, 0 orphaned.Verification
pnpm test— 438 pass (427 + 11 newdesign.test.ts); the 6 golden snapshots stay byte-identical;determinism.test.tsgreen.pnpm typecheck+pnpm lintclean.verify-overlay3/0/0.Next (2c)
render/frame/player --theme brand.json; theme-awarebatch(design.*rows) + the 3-brand-from-one-datafile demo; scene-backgroundtokens; numeric/type/gradient-stop tokens; teachtoken()in the guide/SKILL/DESIGN.md.🤖 Generated with Claude Code