feat(sim): analytical Left HUD redesign + affect channel + no-cache

Left-brain HUD look-and-feel pass (judged by eye in the sim):
- corner-bracket targeting reticles (capped arms) replace plain boxes
- translucent label chips, legible over any frame
- two sensor channels: cyan detections (with deterministic confidence
  scores) vs amber measurements (center crosshair)
- bbox-sized "ANALYSIS . L{n} . {k} OBJ" status tag, escalating with Left

Affect channel (emotions in the HUD), per
docs/superpowers/specs/2026-06-22-affect-channel-hud-design.md:
- surfaces only when BOTH knobs up; strength = min(left, right)
- stable per-scene palette, more words appear with combined strength
- soft glowing violet words on their own opacity layer (the dream
  leaking into the machine's read); math in player/alteration.py
- forest/cosmos/abyss palettes in the manifest; 5 new unit tests

Simulator no-cache middleware so by-eye iteration never serves a stale
app.js / api response (fixes the latent "plan has affect but clip.affect
empty" stale-/api/clips bug).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ben Stull
2026-06-22 23:11:02 -07:00
parent 9cf6324bb4
commit 6adb93407b
9 changed files with 315 additions and 16 deletions
+3
View File
@@ -26,6 +26,7 @@ class Clip:
source: str
right_variants: dict # {"1": {"file": ...}, "4": {...}} (no "0")
annotations: list # [{"key", "box":[x,y,w,h], "min_level"}, ...]
affect: list # [{"key", "at":[x,y], "min_level"}, ...] (Left x Right)
strings: dict # {"en": {key: text}}
def variant_file(self, strength: int) -> str:
@@ -46,6 +47,7 @@ class Clip:
"source": self.source,
"right_variants": variants,
"annotations": self.annotations,
"affect": self.affect,
"strings": self.strings,
}
@@ -59,6 +61,7 @@ def _clip_from_dict(d: dict[str, Any]) -> Clip:
source=d.get("source", ""),
right_variants=d.get("right_variants", {}),
annotations=d.get("annotations", []),
affect=d.get("affect", []),
strings=d.get("strings", {}),
)