Commit Graph

39 Commits

Author SHA1 Message Date
Ben Stull cbb7c9f53d 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>
2026-06-23 09:55:35 -07:00
Ben Stull 6adb93407b 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>
2026-06-22 23:11:02 -07:00
Ben Stull 4e3b326d40 feat(pipeline): forest Right-variant baker (POC flow restyle, productionized)
Right strength curve (level 1-4 -> increasing img2img keyframe strength) is pure
and unit-tested; the restyle engine is a verbatim port of the session-0008 POC
flow_restyle.py (SD img2img keyframes + Farneback optical-flow tweens = calm,
no boiling). torch/diffusers imported lazily so the module + curve test stay light.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 06:33:04 -07:00
Ben Stull f11b9ee72d feat(ring): fast-spin blended pass past a speed threshold (scales design §3)
A multi-detent encoder spin previously chained one full transition per scale
crossed (e.g. +5 ≈ 5 placeholder morphs ≈ 12-15s), which feels sluggish for a
fast spin. Design §3 anticipates this: "transitions chain, or past a speed
threshold a faster blended pass is used."

`player.ring.advance_ring` gains an opt-in `fast_spin_threshold` (canonical
default `DEFAULT_FAST_SPIN_THRESHOLD = 3`). A spin batches its detents into one
advance() call, so `abs(delta)` is the input layer's proxy for spin speed; at or
above the threshold the move collapses to a single blended pass — one
`TransitionStep` (the arrival edge, marked `blended`, landing straight on the
destination, `RingMove.fast=True`) instead of the full chain. Landing index,
seam-crossing (`wrapped`), and arrival edge/direction are exactly the full
chain's; only the in-between transitions are dropped.

The policy is opt-in (default off) because the pure function cannot observe
wall-clock spin speed — the simulator/firmware, which can, enables it. This keeps
all existing complete-chain behavior and tests intact. The simulator passes the
default threshold and plays the blended step at 2.5× (FAST_BLEND_RATE); a
dedicated fast-blend clip can replace the accelerated arrival-edge placeholder
when real transition media exists.

- player/ring.py: TransitionStep.blended, RingMove.fast, threshold param + policy
- simulator/clips.py: serialize fast/blended in ring_move_to_dict
- simulator/app.py: apply DEFAULT_FAST_SPIN_THRESHOLD at /api/ring/advance
- simulator/static/app.js: play a blended step at FAST_BLEND_RATE
- docs: scales design §3, USER_GUIDE, ROADMAP slice-3 note

Tests: +9 (ring policy, serializer, API). Suite 224 passed / 2 skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 00:17:47 -07:00
Ben Stull 7a50ae41bb feat(sim+player): scale-ring navigation (endless encoder) + cosmos/abyss scales
Add scale-ring navigation to the simulator per the scales-library design §3:
an endless rotary-encoder control (relative, vs the absolute 0-4 experience
knobs) walks a closed ring of neutral "scales of nature" clips, with placeholder
AI zoom/warp transitions between adjacent scales and a small->large wrap (the
infinite-zoom payoff).

- player/ring.py (new, canonical pure logic): ScaleRing + advance_ring; one
  transition clip per edge, played forward zooming inward / reversed outward;
  modulo wrap both ways; chained steps for a multi-detent spin. Mirrors
  player/content.py conventions (frozen dataclasses, pure functions).
- simulator: load_ring + ring_to_dict/ring_move_to_dict; GET /api/ring and
  POST /api/ring/advance (Python owns step/wrap/transition math; the browser
  only plays the returned transition(s) then settles on the target scale).
- frontend: endless-encoder control (zoom in/out buttons + stage scroll),
  current-scale readout, multi-clip active-scale selection, transition playback.
- media: two cheap true-PD scales so the ring is demonstrable -- cosmos
  (NASA/Hubble) + abyss (NOAA Ocean Exploration), provenance recorded in the
  manifest, bytes generated as labelled placeholders by setup_scales_media.py.
  The expensive multi-strength flow-stabilized Right re-bake is DEFERRED (new
  scales carry a raw base only) until the ring is liked; Pi renderer +
  serial/firmware remain deferred (simulator-first).
- docs: ROADMAP slice-3 done; USER_GUIDE scale-ring gesture; plan doc.

Verified: pytest 215 passed / 2 skipped (+22 new); sim boots, /api/ring +
/api/ring/advance correct incl. wrap, media served, and a headless-Chrome CDP
drive walked cosmos -> forest -> abyss -> (wrap) -> cosmos with the active clip
reloading correctly.

Spec: docs/superpowers/specs/2026-06-07-scales-library-and-right-axis-pipeline-design.md (§3)
Plan: docs/superpowers/plans/2026-06-07-scale-ring-navigation.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 23:40:21 -07:00
Ben Stull 9c347d580f feat(sim+engine): lock alteration calibration + fix psychedelic dark grade
Tuning the look by eye in the simulator (design §8) surfaced that the dark
mood pole rendered a full-frame hue-rotate(-200deg) — rock orange, trees
purple: the disorienting look rejected in session 0008, not the peaceful POC
dark_frame. Replace it with darken + slight desaturate on the video filter
plus a multiply-blended deep-blue wash (#tint, below the SVG HUD so the
overlay stays legible). Dark now reads cool/somber with natural greens, like
the approved POC look; light/left/right unchanged and confirmed peaceful.

With full tilt now tasteful on every axis, LOCK DEFAULT_CALIBRATION to unity
gains + linear variant map as a deliberate by-eye choice (not placeholders),
closing the open session-0006 knob->strength decision: knobs run 0=off..4=max,
equal Dark/Light = identity, the 5 notches map 1:1 to the 5 discrete Right
bakes. Guard the locked constants with test_default_calibration_is_locked.

Resolves design §8 open questions (calibration curve shape; grade-vs-overlay
ordering) and records the dark-grade fix. Full suite 193 passed / 2 skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 23:19:53 -07:00
Ben Stull eb3aa0949d feat(simulator): /api/alteration + /api/clips; retire selection endpoints
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 22:55:10 -07:00
Ben Stull c316309fc6 feat(simulator): clips.py manifest model; retire selection fixtures
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 22:54:09 -07:00
Ben Stull 825d68c653 refactor(player): state.py tests track discrete Restyle.variant
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 22:53:40 -07:00
Ben Stull 12a8177793 feat(player): discrete Right variant + Left level + Calibration (slice design §2)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 22:53:19 -07:00
Ben Stull 9a13b01a41 feat(player): player state machine — controls stream to transitions 2026-06-05 18:08:34 -07:00
Ben Stull 79bb86c6a2 feat(player): alteration engine — knob vector to RenderPlan (design §4/§5) 2026-06-05 18:07:29 -07:00
Ben Stull 00969e2e44 feat(player): 7-way content-dial resolution (design §6) 2026-06-05 18:06:49 -07:00
Ben Stull 57597be8af feat(player): Controls panel model (serial-contract data shape)
Sub-project 3 slice 1, per ROADMAP.md §3 and design §6/§7.
2026-06-05 18:06:27 -07:00
Ben Stull c1745f0021 feat(simulator): X-ray frontend (dials, pool, brain/mood maps)
Per docs/superpowers/plans/2026-06-04-experience-simulator.md Task 5.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 03:43:34 -07:00
Ben Stull cdf36c9b57 feat(simulator): FastAPI app with /api/select and /api/catalog/meta
Per docs/superpowers/plans/2026-06-04-experience-simulator.md Task 4.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 03:42:13 -07:00
Ben Stull aadfccf32d feat(simulator): deterministic synthetic fixture catalog
Per docs/superpowers/plans/2026-06-04-experience-simulator.md Task 3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 03:41:35 -07:00
Ben Stull 98fb86840c feat(selection): expose ranked_candidates(); refactor select() onto it
Per docs/superpowers/plans/2026-06-04-experience-simulator.md Task 1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 03:40:38 -07:00
Ben Stull deb26b2575 test: end-to-end ingest+review integration (+ opt-in ffprobe)
Per sub-project-2 plan Task 13 / spec §10 test 8. Hermetic e2e: fake fetcher ->
ingest_candidate -> proposed record; approve flips it; reload + validate_catalog;
select(approved_only=True) finds it. Opt-in real-ffprobe/ffmpeg tests generate a
lavfi clip and assert mode/duration/resolution + dominant color, skipped when the
binaries are absent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 06:35:17 -07:00
Ben Stull 376edd7819 feat: interactive review CLI
Per sub-project-2 plan Task 12 / spec §8.2. Walks proposed records (fields +
coords + rationale + best-effort ffmpeg preview), prompts accept/edit/skip/quit,
and persists each approval via save_catalog rewrite. I/O seams (input_fn/now_fn/
out) and --no-preview make the walk testable hermetically; decision logic lives
in the tested review core.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 06:34:34 -07:00
Ben Stull 3e07e86187 feat: review transition core (proposed -> approved)
Per sub-project-2 plan Task 11 / spec §8.1. proposed_records filter and approve()
return an approved copy via dataclasses.replace (no in-place mutation), with
optional coordinate/rationale override and an injected reviewed_at timestamp.
Pure, no I/O, no clock.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 06:33:27 -07:00
Ben Stull 1d7f821ab8 feat: ingest CLI entry point
Per sub-project-2 plan Task 10. argparse entry wiring named fetcher +
HeuristicProposer into ingest_search/ingest_candidate; --query/--resolve,
--limit, --catalog, --media-root (env HEF_MEDIA_ROOT), --dominant-color.
Unknown archive -> exit 2, deferred archive -> exit 3. Secrets env-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 06:33:01 -07:00
Ben Stull cecc5a0f61 feat: LibriVox/NASA/Internet Archive fetchers (+ deferred stubs)
Per sub-project-2 plan Task 9 / spec §6.4. Three keyless first-ship fetchers
parse documented JSON APIs via an injected HttpClient; license/attribution go
through tools.licensing; NASA third-party + IA no-license cases are flagged in
notes for review. musopen/fma/freesound are explicit deferred stubs raising
NotImplementedError; freesound documents FREESOUND_API_TOKEN (secret, env-only).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 06:32:18 -07:00
Ben Stull 2db2b7ac16 feat: ingest pipeline (Candidate/Fetcher/ingest_candidate)
Per sub-project-2 plan Task 8 / spec §6. ingest_candidate dedupes, downloads,
mechanically tags, drafts coordinates, builds a proposed Record and appends it;
ingest_search loops over fetcher hits. All boundaries (download/prober/color_fn)
injectable, so the pipeline is fully hermetic.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 06:29:09 -07:00
Ben Stull 3d5c34491c feat: heuristic coordinate proposer (drafting)
Per sub-project-2 plan Task 7 / spec §7. HeuristicProposer seeds the brain plane
from archive priors and the mood plane from title/description keyword nudges,
clamps to 0..4, and emits a one-line rationale. Deterministic, no I/O, no ML
(honors design §11) — only a DRAFT a human reviews.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 06:27:37 -07:00
Ben Stull 222421e773 feat: per-archive license normalization
Per sub-project-2 plan Task 6 / spec §5.3. normalize_license maps CC URLs /
identifiers and public-domain markers to the LICENSES vocab, builds non-empty
attribution for cc_by/cc_by_nc, and rejects unmappable licenses at ingest.
librivox_license() helper returns public_domain.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 06:26:21 -07:00
Ben Stull d2a97823f5 feat: ffmpeg frame extraction + optional dominant_color
Per sub-project-2 plan Task 5 / spec §5.2. ffmpeg-only dominant color (no image
library), opt-in by design; extract_frame for review previews. Runners injectable
so the unit suite never shells out.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 06:25:11 -07:00
Ben Stull 542b5a5641 feat: mechanical mode/duration/resolution tagging
Per sub-project-2 plan Task 4 / spec §5.1. derive_tags(Probe) -> Tags with the
attached_pic cover-art guard so an art-bearing audio file stays mode=audio.
Duration falls back to the longest stream when format.duration is absent, and
rounds half-up so 12.5s -> 13s (Python's round() would give 12 via banker's
rounding) to match the spec's stated behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 06:24:33 -07:00
Ben Stull 19104f94cd feat: ffprobe wrapper (tools.probe)
Per sub-project-2 plan Task 3 / spec §5.1. Parses ffprobe JSON into a Probe
(streams + format); subprocess runner injectable so tests never shell out.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 06:23:24 -07:00
Ben Stull b6fb635ef4 feat: catalog-level validate_catalog + index_by_id (unique ids)
Per sub-project-2 plan Task 2 / spec §3. Purely additive to hef.catalog;
no existing symbol changes. validate_catalog runs per-record validate() then
asserts id uniqueness; index_by_id gives by-id lookup the player also wants.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 06:23:01 -07:00
Ben Stull db4f036729 chore: scaffold tools/ package + stdlib http client
Per sub-project-2 plan Task 1. Adds tools/ to setuptools packages,
gitignores media/, and a minimal injectable urllib HTTP client.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 06:22:30 -07:00
Ben Stull 062e13d42e test: end-to-end catalog+selection integration 2026-06-04 01:36:23 -07:00
Ben Stull 904c4bff52 feat: nearest-match select function 2026-06-04 01:36:07 -07:00
Ben Stull d28fb0a0a7 feat: selection mode filtering with av fallback 2026-06-04 01:35:38 -07:00
Ben Stull d1c5190bbb feat: selection Coordinate and weighted distance 2026-06-04 01:35:15 -07:00
Ben Stull 85119ed385 feat: catalog JSONL load/save/append 2026-06-04 01:34:51 -07:00
Ben Stull c36ef73342 feat: catalog Record dict conversion 2026-06-04 01:34:20 -07:00
Ben Stull 8b3d17a6aa feat: catalog Record model and validation 2026-06-04 01:33:50 -07:00
Ben Stull 1379751dda chore: scaffold catalog+selection core package 2026-06-04 01:33:23 -07:00