docs(plan): mark Phase 20 Theater Mode scoped after sign-off

This commit is contained in:
daniel-c-harvey
2026-06-20 21:40:56 -04:00
parent 021801999c
commit 835fb71337
2 changed files with 43 additions and 54 deletions
+33 -41
View File
@@ -1,6 +1,6 @@
# Phase 20 — Theater Mode (public Release Detail views)
Product spec. Status: **proposed, awaiting Daniel sign-off on the open questions in §9.**
Product spec. Status: **scoped and approved for implementation — Phase 20, Wave 1** (Daniel sign-off 2026-06-20; all §9 open questions resolved).
Surface: **public listener site only** (`DeepDrftPublic` / `DeepDrftPublic.Client`). No CMS
(`DeepDrftManager`) change. No API, data, or schema change — Theater Mode is a pure
presentation-layer feature riding data the player already carries.
@@ -72,10 +72,10 @@ this.
4. **Disabled until interactive** (`!RendererInfo.IsInteractive`) — same guard the lava-lamp button and
Play buttons already carry, so it does nothing during prerender.
**Iconography:** Material `Theaters` (a film-strip glyph) is the obvious stock choice and reads as
"theater" immediately. A bespoke `DDIcons` glyph in the hand-rolled house style is the higher-craft
option but is **not** required for v1 (this matches the Phase 17 OQ7 precedent — Material icons now,
bespoke later). **Open question OQ1 (§9).**
**Iconography:** Material `Theaters` (a film-strip glyph). A bespoke `DDIcons` glyph in the
hand-rolled house style is the higher-craft option but is **not** required for v1 (this matches the
Phase 17 OQ7 precedent — Material icons now, bespoke later). **Resolved: Material `Theaters` for v1
(OQ1, Daniel 2026-06-20).**
---
@@ -134,13 +134,10 @@ state without the detail page reaching across to it.
**Edge — Theater ON but nothing playing:** the bar's enlargement keys off `CurrentTrack?.Release`. If no
track is playing (the listener opened the page and toggled Theater without pressing play), there is no
current release to surface in the bar. **Open question OQ2 (§9):** does Theater Mode surface *the page's*
release in the bar even when not playing (the page knows its release), or only the *playing* release
(simpler, but the bar shows nothing extra until play starts)? Recommendation: **playing-release only**
keeps the bar a pure function of player state and avoids a detail-page→bar data push that would
re-entangle the two. The listener who toggles Theater is almost always already listening; the visualizer
itself is blank until a track resolves, so a blank-ish enlarged bar in that rare pre-play window is
coherent.
current release to surface in the bar. **Resolved (OQ2, Daniel 2026-06-20): playing-release only**
the bar stays a pure function of player state; no detail-page→bar data push. The listener who toggles
Theater is almost always already listening; the visualizer itself is blank until a track resolves, so a
blank-ish enlarged bar in that rare pre-play window is coherent.
---
@@ -174,11 +171,11 @@ Two viable homes for the boolean:
(`LavaEnabled || WaveformEnabled`) to know whether to show the button, so the two are coupled at the
read site anyway.
**Steer: Option A.** The visualizer-control state is already the "how the visualizer presents" object,
**Resolved (OQ3, Daniel 2026-06-20): Option A** — widen `WaveformVisualizerControlState` with a
`TheaterMode` flag. The visualizer-control state is already the "how the visualizer presents" object,
Theater Mode is a visualizer-presentation concern, and the object was explicitly designed to widen this
way. Option B is the defensible SRP-purist alternative if Daniel wants the visualizer dials kept
pristine. **Open question OQ3 (§9).** Final structural call is staff-engineer's at implementation
(matching the standing convention on `IQueueService`-shape decisions).
way. Final structural call is staff-engineer's at implementation (matching the standing convention on
`IQueueService`-shape decisions).
**Why this satisfies SOLID / the "cleanly separated concerns" constraint:**
- **Single source of truth, multiple observers.** One boolean; the three pages observe it for the
@@ -247,31 +244,26 @@ convention. **No new per-component dark overrides.** Concretely:
---
## 9. Open questions (Daniel decisions, not implementation calls)
## 9. Open questions — all resolved (Daniel, 2026-06-20)
- **OQ1 — Theater toggle icon.** Material `Theaters` (film-strip) for v1, or commission a bespoke
`DDIcons` glyph in the hand-rolled house style? *Recommend: Material `Theaters` now, bespoke deferred
(Phase 17 OQ7 precedent).* — **product call.**
- **OQ2 — bar enlargement when nothing is playing.** Surface the *page's* release in the bar even with no
current track (needs a page→bar data path), or only the *playing* release (bar stays a pure function of
player state)? *Recommend: playing-release only.* — **product + architecture call; the recommendation
keeps the SOLID seam clean, so it leans toward an implementation default unless Daniel wants the
page's release shown pre-play.**
- **OQ3 — state home.** Extend `WaveformVisualizerControlState` with `TheaterMode` (Option A,
recommended) or a dedicated `TheaterModeState` holder (Option B, SRP-purist)? — *Structural;
staff-engineer's final call, but Daniel may have a taste here.*
- **OQ4 — does the back link stay in Theater Mode?** Recommendation keeps it (it is navigation chrome,
not release content). Confirm Daniel agrees the top action row (back + lava + theater) is "controls,"
not "content." *Recommend: keep.***product call, low-stakes.**
- **OQ5 — persistence scope.** Theater Mode follows the visualizer-state convention: persists across SPA
navigation within a session, resets to OFF on a fresh page load (F5). Confirm that is the wanted
behavior (vs. a cookie that remembers Theater across reloads). *Recommend: session-scoped, reset on
reload — matches the visualizer-control-state precedent; no cookie round-trip.* — **product call.**
- **OQ6 — Theater on the home hero / NowPlaying panel?** The `WaveformVisualizerControlPopover` also
appears on the home hero's NowPlaying panel (mode C). This spec scopes Theater Mode to the **three
Release Detail views only** (Daniel's framing). Flag: should the home hero get a Theater affordance
too, or is it deliberately detail-pages-only? *Recommend: detail-pages-only for v1, as scoped.*
**product call, adjacent.**
All six open questions are resolved. Every resolution matches the spec's recommendation.
- **OQ1 — Theater toggle icon. RESOLVED: Material `Theaters` (film-strip) for v1.** Bespoke `DDIcons`
glyph deferred (Phase 17 OQ7 precedent).
- **OQ2 — bar enlargement when nothing is playing. RESOLVED: playing-release only.** The bar stays a
pure function of player state; no page→bar data path. The listener who opens Theater without pressing
play sees a blank-ish enlarged bar — coherent, because the visualizer itself is also blank.
- **OQ3 — state home. RESOLVED: Option A — widen `WaveformVisualizerControlState` with a `TheaterMode`
flag.** Theater Mode is a visualizer-presentation concern; the object was explicitly designed to widen
this way. Staff-engineer makes the final structural call at implementation.
- **OQ4 — back link in Theater Mode. RESOLVED: stays visible.** The top action row (back, lava-lamp,
theater) is controls, not release content — it remains in Theater Mode.
- **OQ5 — persistence scope. RESOLVED: session-scoped, resets to OFF on fresh page load.** Persists
across SPA navigation within a session; a full reload (F5) resets it to OFF. Matches the
visualizer-control-state precedent; no cookie round-trip.
- **OQ6 — Theater on the home hero / NowPlaying panel. RESOLVED: detail-pages-only for v1.** The three
Release Detail views are the scope; the home hero's `WaveformVisualizerControlPopover` does not get a
Theater affordance in this phase.
---
@@ -295,7 +287,7 @@ convention. **No new per-component dark overrides.** Concretely:
8. No API / data / schema change. No CMS change. The enlarged bar reads only `CurrentTrack.Release`
fields the DTO already carries.
9. Theater Mode persists across SPA navigation within a session and resets to OFF on a fresh page load
(per OQ5, if confirmed).
(OQ5, confirmed).
---