Skip to content

feat: 3D spatial/temporal IR core (opt-in core="ir") - #1

Merged
kiyeonjeon21 merged 2 commits into
mainfrom
feat/ir-core
Jun 20, 2026
Merged

kiyeonjeon21 merged 2 commits into
mainfrom
feat/ir-core

Conversation

@kiyeonjeon21

Copy link
Copy Markdown
Owner

What

Inserts a pure-data intermediate representation between <sf-*> HTML and three.js,
behind the unchanged window.__stereoframe seek protocol. Opt-in per scene via
core="ir"; the legacy render path is untouched (no regressions).

Highlights

  • IR core — Node-safe ir/{types,compile,evaluate} (pure, no three.js/DOM).
    compile flattens a timeline algebra (seq/par/stagger/beat) into per-channel
    segments with bottom-up duration; evaluate(t) holds the active segment per channel
    • additive behaviours + two-pass reference resolution (dynamic orbit/follow centers).
  • Verb coverage in IR — turntable/float/sway/orbit/move/dolly/zoom/follow,
    bounce-in/fade-in/variant (entrance + material channels), and named-state to.
    The long-tail (path/camera-path/explode/isolate/morph/crossfade-clip/deform +
    DOM-target fades) falls through to the legacy writers, byte-identical.
  • <sf-group> — declarative hierarchy (three.js composes; a verb on the group
    moves the whole subtree).
  • Named states — <sf-state>/<sf-set> + <sf-animate verb="to"> + initial,
    lowered to per-channel tween/material segments resolved by the held model.
  • Render-free IR lint — ir_dangling_ref, ir_zero_duration, ir_unreachable,
    ir_channel_conflict, ir_unknown_state, ir_state_requires_core; schema exposes
    the IR vocabulary.

Verified

  • bun test green (195 incl. new IR compile/evaluate/lint tests).
  • Full example corpus renders byte-identical legacy↔IR (documented improvements:
    turntable+sway now compose; metaball is pre-existing GPU non-determinism — validate
    idempotency passes). New <sf-group> rig + state-toggle compositions verified.
  • No changes to the legacy path or the window.__stereoframe contract.

🤖 Generated with Claude Code

kiyeonjeon21 and others added 2 commits June 20, 2026 20:09
… lint, and <sf-group>

Insert a pure-data intermediate representation between the <sf-*> HTML surface and
three.js, behind the unchanged window.__stereoframe seek protocol. A <sf-scene> opts
in with core="ir"; the legacy render path is untouched.

- IR core (packages/runtime/src/ir/): types/compile/evaluate are Node-safe and pure
  (no three.js/DOM). compile flattens a timeline algebra (seq/par/stagger/beat) into
  per-channel segments with bottom-up duration inference; evaluate(t) holds the active
  segment per channel + additive behaviors + a two-pass reference resolution (dynamic
  orbit/follow centers) -> FrameState. from-html/backend lower the DOM and apply it.
- Hybrid coverage: IR owns turntable/float/sway/orbit/move/dolly/zoom/follow; the rest
  fall through to the legacy writers (compileAnimations skip set), byte-identical.
- <sf-group>: compileScene's element loop is now recursive (addElement); a group builds
  a real THREE.Group so a verb on the group moves the whole subtree (three.js composes
  world matrices; the IR writes locals).
- Render-free IR lint (cli): ir_dangling_ref / ir_zero_duration / ir_unreachable /
  ir_channel_conflict, from shared IR tables in vocab.ts; `schema` emits an `ir` block.

Verified: bun test green; full example corpus renders byte-identical legacy<->IR (with
one documented improvement: turntable+sway now compose additively instead of the legacy
sway clobbering the spin); zero new lint false positives across examples.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extends the opt-in core="ir" pipeline (Surface -> IR -> evaluate(t) -> three.js)
with opacity/material channels and declarative named states, all lowered to the
existing per-channel held model.

- Entrances + material (B): FrameState gains opacity + material channels.
  bounce-in (scale, entrance "hold from before window") + fade-in (opacity) +
  variant (material chain via the held model; backend lerps colour with THREE.Color
  for byte-identical parity) migrate from the legacy fallthrough into pure IR.
  DOM-target fade-in stays legacy via a skip3d set.
- Named states (C): <sf-state name><sf-set target …/></sf-state> + <sf-scene initial>
  + <sf-animate verb="to" state>. The initial + each transition resolve into
  per-channel tween (transform) + variant (material) segments (from = previous
  state's value), resolved by the held model ("latest active state wins"). Adds one
  pure `tween` driver; reuses the Phase-5 material appliers. IR-only (sf-state is
  inert in legacy).
- Lint: ir_unknown_state, ir_state_requires_core. schema/vocab expose
  sf-state/sf-set/to + the opacity/material channels and tween/fade-in/variant kinds.

Verified: bun test green; byte-identical legacy<->IR across the example corpus for
the migrated verbs; a state-toggle composition transitions move+rotate+recolour with
validate idempotency passing. No regressions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@kiyeonjeon21
kiyeonjeon21 merged commit 893e0e8 into main Jun 20, 2026
1 check passed
@kiyeonjeon21
kiyeonjeon21 deleted the feat/ir-core branch June 20, 2026 13:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant