feat(sim): Dev Mode — pool clip picker + live analysis under one toggle
Adds a single "Dev Mode" switch at the bottom of the control panel (off by default, persisted in localStorage). When on, a panel appears below it with all dev controls and data; when off the default view is just the experience + the three control fieldsets. Dev panel: - Pool picker: a <select> of the current altitude's pool members — choose any clip to override the random landing pick; a "Re-roll random" button re-runs the server-canonical pick. Rebuilds on each landing. - Active clip metadata (id, title, source, license, base_file). - Annotations & affect: keys with salience/window/tier counts (read-only; editing stays in /author.html). - RenderPlan JSON — relocated here from the always-visible panel. - Cache & playback: preload status (N/total), memory-vs-network for the active clip, live resolution/duration/loop position. Frontend only — no API changes; everything is read from data the renderer already has. Factored pickRandomMember() out of landScale() so the initial landing, ring advances, and the re-roll button share one pick. Design: docs/superpowers/specs/2026-06-25-simulator-dev-mode-design.md 269 passed, 2 skipped; node --check + server smoke clean. Frontend behavior to be verified by-eye by the operator (no headless browser in repo yet). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
# Simulator Dev Mode — design
|
||||
|
||||
> 2026-06-25 · session 0017 · planning-and-executing
|
||||
> Anchor: leaf task (simulator dev-tooling — R2b, no upstream design needed)
|
||||
|
||||
## Problem
|
||||
|
||||
While previewing the experience, the operator can't choose *which* clip in an
|
||||
altitude's rotating pool is shown — the server picks a random pool member on each
|
||||
landing (content-pipeline §11.1). For by-eye review they want to step through every
|
||||
clip in a pool on demand, and to see the engine/clip data behind what's on screen.
|
||||
The RenderPlan JSON readout is also always visible, cluttering what should read as
|
||||
an audience-facing preview.
|
||||
|
||||
## Goal
|
||||
|
||||
A single **Dev Mode** toggle at the bottom of the control panel. Off by default
|
||||
(persisted in `localStorage`). When on, a panel appears directly below it with all
|
||||
dev controls and data; when off, the normal view is just the experience + the three
|
||||
control fieldsets.
|
||||
|
||||
## Scope
|
||||
|
||||
Frontend only — `simulator/static/{index.html,app.js,style.css}`. No API changes:
|
||||
every datum Dev Mode shows is already available client-side (`/api/clips`,
|
||||
`/api/ring`, the `/api/alteration` response, and the in-memory preload cache). The
|
||||
separate `/author.html` remains the place to *edit* labels; Dev Mode is
|
||||
inspect-and-select only.
|
||||
|
||||
## Dev panel contents (top → bottom)
|
||||
|
||||
1. **Pool picker** — a `<select>` of the current altitude's pool members
|
||||
(`clip_id · title`), its value reflecting the clip currently playing. Choosing a
|
||||
member sets `activeClipId` to it and reloads the base media, overriding the random
|
||||
landing pick. A `🎲 Re-roll random` button re-runs the server-canonical random
|
||||
pick for the current scale. The dropdown is rebuilt on every scale landing, so it
|
||||
always lists the current pool; single-clip scales (cosmos/orbit) show one entry.
|
||||
2. **Active clip** — `id`, `title`, `source`, `license`, `base_file`.
|
||||
3. **Annotations & affect** — each annotation key with salience (or legacy
|
||||
`min_level`), time window (`appear`–`disappear`), and tier count; each affect key
|
||||
with `min_level` and tier count. Read-only.
|
||||
4. **RenderPlan** — the relocated `#readout` (the `/api/alteration` JSON).
|
||||
5. **Cache & playback** — preload status (`N/total cached`), whether the active
|
||||
clip is served **from memory** (a preloaded blob) vs the network, and live video
|
||||
resolution / duration / loop position.
|
||||
|
||||
## Behavior
|
||||
|
||||
- **Pool override is per-landing.** Changing altitude re-rolls randomly as today;
|
||||
the operator then picks again from the new scale's pool. The pick is not persisted
|
||||
across landings (YAGNI — "select any video while on an altitude").
|
||||
- **Refresh points.** Pool picker + clip metadata + annotations rebuild whenever the
|
||||
scale lands (hooked into `renderScaleReadout()`) and after a manual pick/re-roll.
|
||||
The RenderPlan readout updates on each `update()` (knob change) as today. The
|
||||
cache/playback stats refresh on a light interval (~500 ms) while Dev Mode is on,
|
||||
and the cache count also ticks up as the preloader fills.
|
||||
- **`pickRandomMember()`** is factored out of `landScale()` so the initial landing,
|
||||
ring advances, and the Re-roll button all share the one server-canonical pick.
|
||||
|
||||
## Testing
|
||||
|
||||
No JS unit harness in the repo and no API change, so verification is: `node --check`
|
||||
on `app.js`, the Python suite stays green (unaffected), and by-eye review by the
|
||||
operator (no headless browser yet — §9 E2E policy noted, machinery pending).
|
||||
Reference in New Issue
Block a user