Merge origin/main (session-history commits 0023-0025) into 0024 feature work

This commit is contained in:
BenStullsBets
2026-06-27 15:22:13 -07:00
4 changed files with 210 additions and 0 deletions
@@ -0,0 +1,83 @@
# Session 0023.0 — Transcript
> App: human-experience-filter-art
> Start: 2026-06-26T09-05 (PST)
> End: 2026-06-26T09-20 (PST)
> Type: executing-plans (operator-driven debugging — "still can't hear" / "video didn't come on")
> Posture: yolo
> Claude-Session: e0cc053a-41fa-416d-a4f5-493f14984e75
> Status: FINALIZED
## Launch prompt (the thread)
> "I still can't hear" → (after diagnostics) operator screenshot: `audio: on, PAUSED
> (readyState 0)` and "the audio check works" with `ring=server · url=NONE` → "the
> video didn't come on when I turned it on" → after the fix: **"yes, both"** (video
> and audio confirmed working).
## Pre-state
- Sessions 00200022 had shipped the audio/video feature + three "Safari autoplay"
fixes that were verified only in headless browsers and **did not work** for the
operator. Audio was silent; this session set out to find the real cause.
## Session arc — the debugging
1. **Stop guessing; instrument.** Three blind fixes had failed because headless
Playwright (Chromium *and* WebKit) relaxes autoplay, so the bug was never
reproducible. Added a **live `#audio-status` readout** (surfacing the previously
*swallowed* `play()` errors + `aud.error`) and a **native `<audio controls>` test
player** that plays the file with zero app code involved. Confirmed the server
already honors HTTP Range (`206`) + `audio/mpeg` — not a serving problem.
2. **The decisive readout.** Operator reported: the **native player works** (file +
codec + browser audio all fine), but the toggle showed
**`ring=server · url=NONE`** with `readyState 0` and no media error — meaning my
code never set a source because `soundtrackUrl()` returned null.
3. **Root cause = a STALE uvicorn server.** The operator's Python process predated the
0020 audio/video work, so it (a) returns `/api/ring` without the per-scale `audio`
field, and (b) requires the old 7-way `content` — it **422s** the new
`{visual,audio}` payload and returns `{content:{video}}` instead of
`{render:{video:{shown}}}`. So audio had no url AND the Video toggle's POST failed
(→ "video didn't come on"). Reloading never fixes it (only refreshes static assets,
not the Python process).
4. **Fix = make the client resilient to a stale server** (so no restart is needed):
- `soundtrackUrl()` falls back to a scale-id→file map (`SCALE_AUDIO_FALLBACK`,
mirrors `build_pool_manifest.SCALE_AUDIO`).
- `controls()` also sends a back-compat `content` field (current server ignores it;
an old one ignores visual/audio).
- `update()` reads "video shown" from **either** response shape.
Verified end-to-end against a **simulated fully-stale server** (routed old
`/api/alteration` shape + stripped ring audio) in Chromium **and** WebKit: Video on
→ video shows + soundtrack plays, zero errors. **Operator confirmed "yes, both".**
5. **Cleanup.** Tucked the audio diagnostics (status readout + native player) under the
**Dev Mode** panel — kept for future debugging, out of the installation UI.
## Deferred decisions
_No low-confidence calls. One judgment worth noting: I added permanent client
back-compat for a pre-release internal API to unblock the operator without a server
restart. The clean long-term fix is restarting the dev server; the shim is harmless and
removes the dependency. Flagging in case a future cleanup wants to drop it once servers
are reliably current._
## Cut state
- `main` @ `6427ab4`, clean, pushed. **292 tests + 7 Playwright E2E pass** (2 skipped).
- Audio + Video experience **works and is operator-confirmed** on the real device.
- New E2E regressions: stale-ring soundtrack fallback, audio-then-video ordering.
- The operator's actual server is still stale — recommended (not required) they restart
it so the API is current; the client no longer depends on it.
## Operator plate / lesson
- **The big lesson (recorded in memory):** headless Playwright relaxes BOTH autoplay and
GPU compositing, so it cannot reproduce real-browser/real-server issues. When a fix
"passes headless" but the operator still sees the bug, **instrument with on-screen
readouts + a native control** to get their real data — don't ship another blind guess.
Three rounds were lost to this before instrumenting.
## Next /goal
```
/goal source/compose the deferred per-altitude music layer (the reserved Audio dial position) per docs/audio-candidate-pool.md — the Audio+Video experience is working & operator-confirmed; OR re-enable white-noise as a 3rd Audio position if wanted
```
@@ -0,0 +1,22 @@
# Session 0024.0 — Transcript
> App: human-experience-filter-art
> Start: 2026-06-26T21-12 (PST)
> Type: writing-plans
> Posture: careful
> Claude-Session: e0aea412-c853-4236-9536-cfd85cbc4975
> Status: **PLACEHOLDER — claimed at session start; finalized at session end.**
>
> This file reserves session ID 0024 for human-experience-filter-art. The driver replaces this
> body with the full transcript and renames the file to its final
> SESSION-0024.0-TRANSCRIPT-2026-06-26T21-12--<end>.md form at session end.
## Launch prompt
_(launch prompt not captured at claim time)_
## Deferred decisions
_Autonomous-mode low-confidence calls the driver made and would have
liked operator input on. Appended as the session runs; surfaced at
finalize. Empty if none._
@@ -0,0 +1,96 @@
# Session 0025.0 — Transcript
> App: human-experience-filter-art
> Start: 2026-06-27T06-05 (PST)
> End: 2026-06-27T07-05 (PST)
> Type: capture
> Posture: careful
> Claude-Session: d6ed1203-92b6-471f-80a4-4c773b645ca1
> Status: **FINALIZED**
## Launch prompt
```
capture this as an issue. We'll implement the network feature later but want it as an Epic, then the remote simulator (e.g. ipad) as a feature with this design
```
## Pre-state
- Immediately followed session 0019 (brainstorming), which merged the
**networked control surface** design SPEC to `main`
(`docs/superpowers/specs/2026-06-26-networked-control-surface-design.md`).
- Operator wants the work captured as backlog (deferred — "implement later"): an
**Epic** for the whole networked feature, and a **Feature** for the iPad remote
twin anchored to that spec.
- Single-repo app: tracker = `benstull/human-experience-filter-art` on
git.benstull.org; no separate content repo (`CONTENT_REMOTE` empty).
- Checkout shared with concurrent sessions (0024 live on its own branch).
## Arc
1. **Routing.** Classified the request as **capture**; invoked `wgl-capture`,
claimed tracked-lite session **0025** (capture / careful).
2. **Target resolve.** Single-repo app → drafted into this repo's working-tree
`issues/` (ephemeral, INV-8); tracker is this repo on git.benstull.org.
3. **Two asks identified** (per handbook §4.3 sizing): an **Epic** (multi-Feature
umbrella — the networked control surface) and a **Feature** (single increment —
the iPad web remote twin, the spec's v1 scope). Both type-fit cleanly.
4. **Drafted both** in the content repo's `issues/` at business altitude (Epic +
Feature business sections free of implementation specifics; the design spec
referenced as orientation). Presented for review; operator approved filing both
at **P2** via `AskUserQuestion`.
5. **Filing.** Label-ensure first hit a **401** — the default issue-token service
resolved to the wrong host. Fixed by pointing `WGL_CAPTURE_TOKEN_SERVICE` at the
host-specific Keychain entry `wgl-gitea-issues-readwrite-token-git.benstull.org`.
Then ensured capture labels (9 created) and filed:
- **Epic #26** — "Networked control surface — drive the experience from a
separate control device" (`type/epic`, P2).
- **Feature #27** — "Remote controller simulator — drive the experience from an
iPad web twin over wifi" (`type/feature`, P2; parent #26).
(Typecheck advisory labels 401'd — fail-open, skipped; no effect on the issues.)
6. **Cleanup.** Deleted both filed drafts (Gitea = system of record, INV-8);
removed the now-empty `issues/` dir; working tree carries no drafts.
## Cut state
- Filed: **Epic #26**, **Feature #27** (parent #26), both `priority/P2`, deferred.
- No repo commits this session (capture is tracked-lite; drafts ephemeral). The
dirty tree on branch `session-0024` is the **concurrent session's** work
(`build_pool_manifest.py` + a test) — left untouched.
- Memory updated: `networked-control-surface-spec.md` records the filed issues +
a deferred "when resumed" pointer; `MEMORY.md` index refreshed.
## Deferred decisions
_None — no autonomous low-confidence calls. Type assignment and P2 priority were
operator-approved in-session._
## Type-fit tally
`type-fit: judged 2, mismatch 0, overridden 0` (judged against §4.3 informally;
the typecheck-label markers could not be stamped — advisory token 401, fail-open).
## Operator plate
- The networked-control work is now backlog: **#26** (Epic) / **#27** (Feature),
deferred per "implement later".
- Token note for future capture on this host: use
`WGL_CAPTURE_TOKEN_SERVICE=wgl-gitea-issues-readwrite-token-git.benstull.org`
(the unscoped default resolves to the wrong host and 401s).
## Next /goal
No new immediate next from this capture — the work is parked on the tracker
(#26/#27, deferred). When the operator resumes hardware:
```
/goal Write the implementation plan for the remote controller simulator, per docs/superpowers/specs/2026-06-26-networked-control-surface-design.md (Feature #27)
```
The active project frontier remains the per-altitude music layer (see the
`audio-soundtrack-sourcing` memory), not this deferred thread.
+9
View File
@@ -64,5 +64,14 @@
},
"0022": {
"title": ""
},
"0023": {
"title": ""
},
"0024": {
"title": ""
},
"0025": {
"title": ""
}
}