feat(sim): Right axis = deterministic real-time painterly dream
Replace the pre-baked SD restyle variants (too fluid — the painting re-rolled every keyframe and the flow-warp melted frames) with a deterministic, real-time dream that holds STILL across the loop; only the footage's own motion moves. Design: docs/superpowers/specs/2026-06-22-right-axis-deterministic-dream-design.md Engine (player/alteration.py): Restyle(variant) -> Dream(strength, intensity); Calibration.right_variant_map -> dream_gain. player/state.py: a Right change is a LIVE_UPDATE now, not a crossfade (only a clip swap crossfades). Plan dict restyle -> dream. Tests migrated; 233 green. (No new Python behavior for the client-render swap below.) Renderer (simulator front-end): the Right dream is a WebGL2 Kuwahara shader on a <canvas> over the live video — edge-preserving, so motion/structure stay crisp; the dream is the same footage, just stylized (no blur). Ramped by the knob; max goes "trippy" (vivid saturation + ~45deg hue drift + posterize, concentrated near max via t=intensity^2). Phase-1 luminous-haze (CSS+bloom) was built then retired by eye (blur read as out-of-focus video). Mood grade rides as a CSS filter on the canvas; bloom layer removed. Dev ergonomics that fell out of the iteration: - /dev/version + a 1s client poll = live-reload (open tab never runs stale renderer code; reloads on my edits AND server restarts). - no-cache on the dev server; an on-screen error banner + crash-proof render so a silent throw can't masquerade as "nothing is changing". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+37
-29
@@ -1,18 +1,19 @@
|
||||
"""The alteration engine: a knob vector -> a layered RenderPlan (design §4, §5).
|
||||
|
||||
Reconciled slice (2026-06-07): the Right axis is a DISCRETE selection of a
|
||||
pre-baked, flow-stabilized restyle variant (not a continuous blend), the Left
|
||||
axis carries its knob LEVEL so a runtime annotation track can pick which labels
|
||||
show, and a frozen `Calibration` parameterizes the knob->strength curves so they
|
||||
can be tuned by eye in the simulator and baked into DEFAULT_CALIBRATION.
|
||||
Right axis (reframed session 0013): a DETERMINISTIC, real-time dream applied live
|
||||
to the base footage — a STILL altered state, not the old pre-baked SD variant that
|
||||
churned across the loop (Right-axis dream design,
|
||||
docs/superpowers/specs/2026-06-22-right-axis-deterministic-dream-design.md). The
|
||||
Left axis carries its knob LEVEL so a runtime annotation track can pick which
|
||||
labels show, and a frozen `Calibration` parameterizes the knob->strength gains so
|
||||
they can be tuned by eye in the simulator and baked into DEFAULT_CALIBRATION.
|
||||
|
||||
Layers compose per §4.2:
|
||||
- Substrate: ColorGrade (Dark/Light mood, center = identity §5) + a pre-baked
|
||||
Right restyle variant.
|
||||
- Overlay: AnalyticalOverlay (Left), composited on top at runtime.
|
||||
- Substrate: ColorGrade (Dark/Light mood, center = identity §5) + the Right Dream
|
||||
(deterministic luminous haze, applied client-side from `dream.intensity`).
|
||||
- Overlay: AnalyticalOverlay (Left) + the affect channel, composited on top.
|
||||
Left and Right stack (different layers); Dark/Light are the two poles of one
|
||||
mood grade. See docs/superpowers/specs/2026-06-07-reconciled-simulator-
|
||||
alteration-slice-design.md.
|
||||
mood grade.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -33,13 +34,13 @@ class Calibration:
|
||||
"""Tunable knob->strength curves (settled by eye in the sim, then baked).
|
||||
|
||||
- mood_gain: scales the signed Dark/Light tone (result clamped to [-1, 1]).
|
||||
- overlay_gain: scales the Left overlay intensity (clamped to [0, 1]).
|
||||
- right_variant_map: knob value (0..4) -> pre-baked Right variant index.
|
||||
- overlay_gain: scales the Left overlay (and affect) intensity (clamped [0, 1]).
|
||||
- dream_gain: scales the Right deterministic-dream intensity (clamped [0, 1]).
|
||||
"""
|
||||
|
||||
mood_gain: float = 1.0
|
||||
overlay_gain: float = 1.0
|
||||
right_variant_map: tuple = (0, 1, 2, 3, 4)
|
||||
dream_gain: float = 1.0
|
||||
|
||||
|
||||
# The LOCKED calibration (session 0010, 2026-06-07) — settled by eye in the
|
||||
@@ -51,15 +52,15 @@ class Calibration:
|
||||
# full tilt is peaceful on every axis, so no softening is warranted.
|
||||
# - overlay_gain = 1.0: full Left = opacity 1.0; the HUD is legible, not
|
||||
# overwhelming, sitting above the grade.
|
||||
# - right_variant_map linear: the 5 knob notches map 1:1 onto the 5 discrete
|
||||
# pre-baked Right strengths (0 = raw base).
|
||||
# These are unity/linear by deliberate choice, not as placeholders. The curve
|
||||
# stays parameterized so a future re-bake or a different feel is one edit away;
|
||||
# test_default_calibration_is_locked guards the values from drifting silently.
|
||||
# - dream_gain = 1.0: full Right = dream intensity 1.0; the deterministic
|
||||
# luminous haze (Right-axis dream design, session 0013) reaches full strength.
|
||||
# These are unity by deliberate choice, not as placeholders. The gains stay
|
||||
# parameterized so a different feel is one edit away; test_default_calibration_is_locked
|
||||
# guards the values from drifting silently.
|
||||
DEFAULT_CALIBRATION = Calibration(
|
||||
mood_gain=1.0,
|
||||
overlay_gain=1.0,
|
||||
right_variant_map=(0, 1, 2, 3, 4),
|
||||
dream_gain=1.0,
|
||||
)
|
||||
|
||||
|
||||
@@ -98,11 +99,15 @@ class AffectOverlay:
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Restyle:
|
||||
"""Right axis (§4.1): selects a pre-baked, flow-stabilized restyle variant.
|
||||
`variant` is a discrete index (0 = raw base, no restyle)."""
|
||||
class Dream:
|
||||
"""Right axis: a deterministic, real-time dream applied live to the base
|
||||
footage — a STILL altered state (Right-axis dream design, session 0013),
|
||||
NOT the old pre-baked SD variant that churned across the loop. `strength` is
|
||||
the Right knob (0..4); `intensity` 0..1 is the dream's strength (the client
|
||||
maps it to the luminous-haze look, the way it maps `grade.tone` to a filter)."""
|
||||
|
||||
variant: int
|
||||
strength: int
|
||||
intensity: float
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -112,7 +117,7 @@ class RenderPlan:
|
||||
grade: ColorGrade
|
||||
overlay: AnalyticalOverlay
|
||||
affect: AffectOverlay
|
||||
restyle: Restyle
|
||||
dream: Dream
|
||||
|
||||
@property
|
||||
def is_identity(self) -> bool:
|
||||
@@ -122,7 +127,7 @@ class RenderPlan:
|
||||
return (
|
||||
self.grade.is_identity
|
||||
and self.overlay.level == 0
|
||||
and self.restyle.variant == 0
|
||||
and self.dream.strength == 0
|
||||
)
|
||||
|
||||
|
||||
@@ -139,8 +144,8 @@ def _affect_intensity(left: int, right: int, cal: Calibration) -> float:
|
||||
return _clamp(cal.overlay_gain * _affect_strength(left, right) / KNOB_MAX, 0.0, 1.0)
|
||||
|
||||
|
||||
def _right_variant(right: int, cal: Calibration) -> int:
|
||||
return cal.right_variant_map[right]
|
||||
def _dream_intensity(right: int, cal: Calibration) -> float:
|
||||
return _clamp(cal.dream_gain * right / KNOB_MAX, 0.0, 1.0)
|
||||
|
||||
|
||||
def _mood_tone(dark: int, light: int, cal: Calibration) -> float:
|
||||
@@ -161,7 +166,10 @@ def plan_alteration(
|
||||
strength=_affect_strength(coord.left, coord.right),
|
||||
intensity=_affect_intensity(coord.left, coord.right, calibration),
|
||||
),
|
||||
restyle=Restyle(variant=_right_variant(coord.right, calibration)),
|
||||
dream=Dream(
|
||||
strength=coord.right,
|
||||
intensity=_dream_intensity(coord.right, calibration),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -171,6 +179,6 @@ def render_plan_to_dict(plan: RenderPlan) -> dict:
|
||||
"grade": {"tone": plan.grade.tone},
|
||||
"overlay": {"level": plan.overlay.level, "intensity": plan.overlay.intensity},
|
||||
"affect": {"strength": plan.affect.strength, "intensity": plan.affect.intensity},
|
||||
"restyle": {"variant": plan.restyle.variant},
|
||||
"dream": {"strength": plan.dream.strength, "intensity": plan.dream.intensity},
|
||||
"is_identity": plan.is_identity,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user