feat(player): alteration engine — knob vector to RenderPlan (design §4/§5)

This commit is contained in:
Ben Stull
2026-06-05 18:07:29 -07:00
parent 00969e2e44
commit 79bb86c6a2
2 changed files with 178 additions and 0 deletions
+98
View File
@@ -0,0 +1,98 @@
"""The alteration engine: a knob vector -> a layered RenderPlan (design §4, §5).
Replaces the 2026-06-04 nearest-match *selection* with a *transformation* of a
neutral base clip. Given the four experience knobs, it produces three layers
that compose per §4.2:
- Substrate transforms (alter pixels, blend with each other):
* Restyle -- the Right axis: a pre-baked generative v2v dreamlike restyle.
* ColorGrade -- the mood axis (Dark/Light): a deterministic color grade.
- Overlay (composited on top of the substrate):
* AnalyticalOverlay -- the Left axis: HUD/labels/measurement.
Left and Right are NOT opposites; they live on different layers and stack
(§4.2). Dark and Light are the two poles of one mood grade whose center is the
identity (§5).
Calibration note: the knob->strength curves below are the single source of
truth for how a 0..4 position maps to a transform strength. See the session
0006 transcript Deferred decisions for the §3-vs-§4.2/§5 reconciliation.
"""
from __future__ import annotations
from dataclasses import dataclass
from hef.selection import Coordinate
KNOB_MAX = 4 # knob full-scale (0..4)
@dataclass(frozen=True)
class ColorGrade:
"""Mood-axis grade (§5). `tone` is signed: >0 warm yellow->white (light),
<0 cool blue->black (dark), 0 = identity (raw, ungraded)."""
tone: float
@property
def is_identity(self) -> bool:
return self.tone == 0.0
@dataclass(frozen=True)
class AnalyticalOverlay:
"""Left axis (§4.1): analytical HUD/annotation/labels, composited on top.
`intensity` 0..1 (0 = no overlay)."""
intensity: float
@dataclass(frozen=True)
class Restyle:
"""Right axis (§4.1): pre-baked generative v2v dreamlike substrate.
`blend` 0..1 (0 = raw substrate, no restyle)."""
blend: float
@dataclass(frozen=True)
class RenderPlan:
"""The full layered alteration for one knob vector (§4.2)."""
grade: ColorGrade
overlay: AnalyticalOverlay
restyle: Restyle
@property
def is_identity(self) -> bool:
"""True when the plan leaves the neutral base un-altered."""
return (
self.grade.is_identity
and self.overlay.intensity == 0.0
and self.restyle.blend == 0.0
)
def _overlay_intensity(left: int) -> float:
"""Left knob -> analytical-overlay intensity (0..1)."""
return left / KNOB_MAX
def _restyle_blend(right: int) -> float:
"""Right knob -> v2v restyle blend (0..1)."""
return right / KNOB_MAX
def _mood_tone(dark: int, light: int) -> float:
"""(dark, light) -> signed mood grade in [-1, 1]; equal -> 0 identity (§5)."""
return (light - dark) / KNOB_MAX
def plan_alteration(coord: Coordinate) -> RenderPlan:
"""Map a knob vector to its layered RenderPlan (design §4)."""
return RenderPlan(
grade=ColorGrade(tone=_mood_tone(coord.dark, coord.light)),
overlay=AnalyticalOverlay(intensity=_overlay_intensity(coord.left)),
restyle=Restyle(blend=_restyle_blend(coord.right)),
)
+80
View File
@@ -0,0 +1,80 @@
import pytest
from hef.selection import Coordinate
from player.alteration import (
AnalyticalOverlay,
ColorGrade,
RenderPlan,
Restyle,
plan_alteration,
)
def _coord(left=0, right=0, dark=0, light=0):
return Coordinate(left=left, right=right, dark=dark, light=light)
def test_all_zero_knobs_is_the_unaltered_base():
plan = plan_alteration(_coord())
assert plan.is_identity
assert plan.overlay.intensity == 0.0
assert plan.restyle.blend == 0.0
assert plan.grade.tone == 0.0
assert plan.grade.is_identity
def test_left_drives_the_analytical_overlay_only():
plan = plan_alteration(_coord(left=4))
assert plan.overlay.intensity == 1.0
assert plan.restyle.blend == 0.0 # Left does not touch the substrate
assert plan.grade.tone == 0.0
def test_right_drives_the_restyle_substrate_only():
plan = plan_alteration(_coord(right=2))
assert plan.restyle.blend == 0.5
assert plan.overlay.intensity == 0.0 # Right does not add overlay
def test_left_and_right_stack_not_cancel():
# design §4.2: whole-brain corner = dreamlike substrate WITH labels on top
plan = plan_alteration(_coord(left=4, right=4))
assert plan.overlay.intensity == 1.0
assert plan.restyle.blend == 1.0
def test_light_pole_grades_warm_positive_tone():
plan = plan_alteration(_coord(light=4))
assert plan.grade.tone == 1.0
assert not plan.grade.is_identity
def test_dark_pole_grades_cool_negative_tone():
plan = plan_alteration(_coord(dark=4))
assert plan.grade.tone == -1.0
def test_equal_dark_and_light_is_identity_grade():
# design §5: the mood center is the raw, ungraded footage
assert plan_alteration(_coord(dark=3, light=3)).grade.is_identity
assert plan_alteration(_coord(dark=2, light=2)).grade.is_identity
def test_dark_minus_light_sets_intermediate_tone():
assert plan_alteration(_coord(dark=4, light=2)).grade.tone == pytest.approx(-0.5)
assert plan_alteration(_coord(dark=1, light=3)).grade.tone == pytest.approx(0.5)
def test_whole_brain_dark_corner_stacks_grade_substrate_and_overlay():
# design §4.2 "Dark + analytical": cold measurement over a melancholy scene
plan = plan_alteration(_coord(left=4, right=2, dark=4, light=0))
assert plan.overlay.intensity == 1.0
assert plan.restyle.blend == 0.5
assert plan.grade.tone == -1.0
assert not plan.is_identity
def test_render_plan_is_frozen():
plan = plan_alteration(_coord())
with pytest.raises(Exception):
plan.grade.tone = 0.5 # type: ignore[misc]