Files
human-experience-filter-art/docs/ROADMAP.md
T

10 KiB
Raw Blame History

Human Experience Filter — Roadmap

The installation is built as five independent sub-projects, each producing working, testable software on its own. Each gets its own spec → plan → implement cycle. This file is the index and dependency map; it is the source of truth for "what's left."

Design reference: specs/2026-06-04-human-experience-filter-design.md.


Status at a glance

# Sub-project Status Unblocks
1 Catalog & Selection Core Done everything
2 Ingest & Tagging / Review tools Done a real library
3 Player Runtime (Pi) In progress the room runs
4 Arduino Firmware (control panel) ◻ Not started real knobs
5 Procedural Side Walls Dropped — (superseded)

Dependency order: 1 → 2, and 1 → 3. Sub-projects 3 and 4 share a serial protocol contract and can then proceed in parallel. Sub-project 5 was dropped (2026-06-04): the move to a single panoramic projector showing real video across the three walls removes the procedural side walls — see the design spec §6/§7.

        ┌─────────────────────────┐
        │ 1. Catalog & Selection  │ ✅
        └───────────┬─────────────┘
                    │
        ┌───────────┴───────────┐
        ▼                       ▼
┌───────────────┐      ┌─────────────────────┐
│ 2. Ingest /   │      │ 3. Player Runtime   │
│    Review     │─────▶│    (Pi) → 1 pano     │
└───────────────┘ feeds│    projector         │
   (fills catalog)      └──────────┬──────────┘
                          serial   ▼
                       ┌────────────────┐
                       │ 4. Firmware    │
                       └────────────────┘

(5. Procedural Side Walls — dropped 2026-06-04, single pano projector)

1. Catalog & Selection Core

Done — merged to main, 37 tests. The dependency root every other sub-project imports.

  • hef/catalog.pyRecord model, validation, JSONL load/save/append.
  • hef/selection.py — weighted-Euclidean distance, mode filtering with A+V fallback, nearest-match select().

Plan: 2026-06-04-catalog-and-selection-core.md.


2. Ingest & Tagging / Review tools

Done — merged to main via PR #1 (session 0002, 2026-06-04); 111 tests pass (2 opt-in real-ffprobe tests skip when the binaries are absent). The tools/ package turns the manual catalog into the assisted draft-then-review flow from the spec, and can populate the library from public-domain sources.

Delivers (tools/):

  • Ingest — per-archive fetchers (Internet Archive / Prelinger, Musopen, LibriVox, NASA, Free Music Archive, Freesound) that download a candidate and write a catalog record.
  • Mechanical tagging — auto-fill mode (probe streams with ffprobe), license / attribution / source_* (from origin), duration_s, resolution, and dominant_color (computed from the video).
  • Coordinate drafting — propose left/right/dark/light with a one-line rationale, written as review_status: proposed.
  • Review CLI — walk unreviewed records one at a time (show proposed coordinates + rationale + a preview frame), accept or correct, flip to approved and stamp reviewed_at.

Spec: 2026-06-04-ingest-tagging-review-tools.md.

Depends on: sub-project 1 (hef.catalog). Done when: you can run ingest against a source, get proposed records, review them to approved, and load_catalog/validate_catalog validate the result — covered by tests on the mechanical-tagging and review state transitions. External deps: ffmpeg/ffprobe only (no image lib — dominant_color, when requested, is ffmpeg-only and opt-in), per-archive download access. Decisions settled: first-ship archives = LibriVox, NASA, Internet Archive (Musopen/FMA/Freesound deferred stubs); media under a --media-root with file_path stored relative to it (spec §6.3); only additive hef.catalog change was validate_catalog + index_by_id.


3. Player Runtime (Pi) (in progress)

Goal: the thing that makes the room run — read the controls, alter the neutral base footage toward the knob state, and play it across the single panoramic projector. Per the machine-altered-perception revision the knobs no longer select a pre-tagged clip; they drive an alteration engine (design §4/§5) over a small neutral base library.

Slice 1 — alteration engine + player core (pure logic) Done. Merged to main (session 0006); 56 tests. The new player/ package, with all I/O (video/audio/serial) behind injected interfaces:

  • player/controls.pyControls, the full panel state (7-way content dial + 4 experience knobs + volume + brightness); the serial-contract data shape shared with sub-project 4.
  • player/content.pyresolve_content, the §6 7-way dial → (audio source, video on/off) table.
  • player/alteration.pyplan_alteration, knob vector → RenderPlan (mood ColorGrade with center=identity §5; Left AnalyticalOverlay; Right Restyle), encoding the §4.2 layering rule (substrate vs overlay; Left & Right stack).
  • player/state.pyPlayer, the state machine that diffs successive controls into transitions (FADE_TO_BLACK/FADE_FROM_BLACK on video on/off, CROSSFADE on clip/restyle-variant swap, LIVE_UPDATE for the continuous grade/overlay/level ops per §4.3, NONE when unchanged).

Plan: 2026-06-05-player-alteration-core.md.

Remaining slices (not started):

  • Runtime renderer — drive the single panoramic projector via mpv/ffmpeg; GPU shaders for the luma-keyed mood grade + analytical-overlay compositing; realize crossfade/fade timing and the 515 min loop. (Open decision: player stack — mpv via IPC vs. ffmpeg vs. custom.)
  • Serial input — real USB-serial reader on the Pi + the 3⇄4 framing contract with the firmware (the keyboard/serial stand-in already works via a Controls stream).
  • White-noise generation — runtime white/pink noise for that content position.
  • Offline v2v variant pipeline — author the pre-baked Right restyle variants (the only paid AI step, design §9) + the multilingual label/string tables + TTS.
  • Catalog model changes — audio source + "neutral base" vs "altered variant" flag (sub-project 2 territory, design §13).

Depends on: sub-project 1 (Coordinate); a neutral base library from sub-project 2 to be meaningful, but developable against a hand-authored library and a keyboard/serial stand-in before firmware exists. Done when: given a base library and a stream of control values, it plays the correct altered segment, loops, crossfades, and goes dark on Off — the decision logic is covered (slice 1, serial mocked); the renderer realizes it. Hardware: Raspberry Pi 5 (holds the drive + base library + variants). Open decisions: player stack (mpv via IPC vs. ffmpeg vs. custom); whether the player hard-restricts to approved records (the approved_only flag is plumbed but inert until backed by a real catalog); knob→strength calibration (the §3 vs §4.2/§5 reconciliation — see the slice-1 plan / session 0006 transcript).


4. Arduino Firmware (control panel) ◻

Goal: the physical panel — turn knob/selector positions into serial messages.

Delivers (firmware/):

  • Read four knobs (left, right, dark, light) and the 4-way content-mode selector.
  • Quantize/debounce analog inputs to the 0..4 integer scale.
  • Send the five values to the Pi over USB serial in a defined framing.

Depends on: only the serial protocol contract shared with sub-project 3 — agree that first, then 3 and 4 proceed in parallel. Done when: turning a knob produces the expected serial message (verifiable on a serial monitor) and the Pi player reacts. Hardware: Arduino + pots/encoders + a 4-position selector. Open decisions: pots vs. detented encoders; exact serial framing.


5. Procedural Side Walls Dropped (2026-06-04)

Superseded. The move to a single panoramic projector showing the real selected video across the three walls (design spec §6/§7) removes the procedural ambient renderer entirely — the mood axis is felt through the chosen content itself. With it goes the only consumer of dominant_color, which becomes optional/opt-in in the ingest tooling (sub-project 2 spec §5.2).

Original goal (for the record): render a slow color wash on the three non-primary walls — hue from the playing piece's dominant_color, brightness from the dark/light knobs — to make the mood axis felt in peripheral vision.


Cross-cutting decisions to settle as we go

Carried from the design spec's open-questions list — none block sub-project 2:

  • Serial protocol framing between Arduino and Pi (needed before 3 ⇄ 4).
  • Player stack on the Pi (mpv / ffmpeg / custom) and how the single panoramic output is driven.
  • approved-only enforcement in the player.
  • Side walls on the primary Pi vs. a second Pi — resolved: side walls dropped.
  • Media storage layout on the drive — settled by the sub-project-2 spec §6.3: media under a media-root, file_path stored relative to it; the player joins it with its drive mount.