RELEASE
planning/2.8.0/slates/RECREATION_IDEAS.md
sha256 152a0c3fe75e8587 · 18980 bytes ·
original held in the private archive
# RECREATION IDEAS — "For Fun" Analysis (RobCo U.O.S. 2.7.0)
> Analysis-only exploration. Nothing here is committed or pushed. Every idea is grounded in
> files/functions actually read on `dev` @ `027be1b`. Four distinct proposals across four
> distinct layers (boot / focused-idle visual / spatial map / ambient temporal engine),
> spread Quick → Medium → Ambitious → MEGA. No favorite — all four are serious.
## Hard constraints honored by all four
- Vanilla, global-scope JS, no build/modules/framework.
- No `APP_VERSION` bump (all are PATCH-class / additive-feel; none is a rewrite or breaking change).
- Popup-only auth untouched (none of these touch `cloud.js` auth).
- No new **precached media**. Only the MEGA adds one new precached **JS** file (code, tiny, justified — no audio/image assets anywhere).
- Each served-file change = exactly one `CACHE_NAME` `-rN` bump (Protocol 1), no APP_VERSION change.
## Grounding snapshot (what the "feel" is actually built from)
- **Boot:** `runBootSequence()` / `_bootLinesFor()` / `_pickBootFlavor()` (`js/ui-audio.js:1023 / 981 / 969`); flavors normal/cold/degraded; per-game identity line spliced at `:1049`; 120ms per-line cadence.
- **CRT layer:** `.crt-overlay` scanlines + refresh-bar + flicker + vignette (`css/terminal.css:27-82`); body-state classes drive live effects — `standby`, `time-night`, `rad-warning/critical/fatal`, `karma-*`, `crit-hp-flash` (applied in `js/ui-core.js:486/2420/2443-2446/2378/2409`).
- **Idle:** `enterStandby()/exitStandby()` on blur/visibility (`js/ui-core.js:483-530`); focused-idle only gets `_startMemCycle()` — one fixed line every 15 min (`js/ui-core.js:472-481`).
- **Audio (all synthesized, zero-byte):** geiger, tinnitus, CRT hum, radio, boot drone, heartbeat, wake tone, level-up, limb/quest/faction SFX (`js/ui-audio.js`, `AudioSettings` gated).
- **Map:** `renderWorldMap()` (`js/ui-render.js:1225`) — scroll list; coord data (`gridRow/gridCol`) + fog-of-war (`state.locationHistory`) + `markLocationVisited()` (`js/ui-render.js:1218`) + `_mapActiveZone` zoom all already exist; guarded by Suites 74/114/126/68/79.
- **Telemetry already computed but buried:** `renderOverseerLog()` + `robco_overseer_log` (boot count, longest/last session — `js/ui-core.js:138/187`); `_pendingDirectivesCount()` = active quests (`js/ui-core.js:1100`).
- **AI narrative:** Tri-Node JSON via Gemini (`getSystemDirective`/`transmitMessage`/`autoImportState`, `js/api.js`); kill-switch `isFeatureEnabled('aiChat')`.
- **Cache:** `sw.js` cache-first, `CACHE_NAME='robco-terminal-v2.7.0-r5'`, all JS/CSS/icons precached.
---
# IDEA 1 — QUICK · Diegetic Boot "MOTD" / Welcome-Back Readout
**1. WHAT.** One dynamic, state-aware line injected into the boot POST sequence — a Message-of-the-Day / session-resume readout. Examples: `> LAST UPLINK 2H14M AGO · 3 ACTIVE DIRECTIVES · RAD BUFFER NOMINAL` or, first boot, `> NEW COURIER PROFILE — NO PRIOR TELEMETRY`. Sourced from `robco_overseer_log` (boot count, last/longest session) + `robco_v8` active campaign (active-quest count via the same logic as `_pendingDirectivesCount()`, `rads`, `loc`).
**2. WHY.** Every boot is byte-identical per flavor (`_bootLinesFor`, `ui-audio.js:981`). Boot is the single most-repeated screen in the app and says nothing about *you*. Meanwhile the Overseer's Log (WU-F7) already computes rich session/device telemetry that lives in a DATA-tab panel almost nobody opens. The boot screen is exactly where "the terminal remembers me" should land.
**3. HOW (in-stack).** Add `_bootMotdLine()` to `js/ui-audio.js`: reads `localStorage.robco_v8` (→ `activeContext` → campaign → `quests`/`rads`/`loc`) and `localStorage.robco_overseer_log`, returns one game-agnostic string built purely from data. Splice it into `runBootSequence()` right beside the existing WU-T3 identity-line splice (`ui-audio.js:1049`), before the final "SECURE LINK ESTABLISHED…". Everything wrapped in `try/catch` → fail-safe to *no* line. No new files, no assets, no new listeners.
**4. BETTER.** Personalizes the most-seen screen; surfaces existing-but-hidden telemetry at the moment of attention; ~zero perf cost (boot already reads `localStorage`); reinforces the continuity fantasy. Accessible: pure phosphor text, inherits the reduced-motion-safe boot cadence, no color-only meaning.
**5. FIT.** *Visually:* rides the exact 120ms per-line cadence + phosphor style; slots beside the per-game identity line so it's uniform across normal/cold/degraded flavors. *Architecturally:* read-only, offline → **no kill-switch needed**; game-agnostic (Protocol 38 — no game literals; all from state/`GAME_DEFS`); one served file changes (`ui-audio.js`) → one cache rev (`-r6`), **no** APP_VERSION bump, **no** new precached asset. Add a Suite guard: boot renders with prior telemetry, without it (fresh profile), and with a corrupt `robco_v8` (MOTD must be omitted, boot never throws).
**6. TRADEOFF.** ~1 read on the boot hot path (negligible). Boot text slightly longer / marginally less "pure retro." Couples `ui-audio.js` to the `robco_v8` shape (mitigated: try/catch tolerates any/absent shape). If overdone it reads gimmicky — cap at one line.
**7. EFFORT/RISK.** 2 files (`js/ui-audio.js`, `sw.js` rev) + both runners at parity + 1–3 new tests. **Risk: LOW.**
**8. PIPELINE.** **Ship-direct.** Small, localized, fail-safe. (Optional 5-min Opus glance at the corrupt-`robco_v8` guard; not required.)
---
# IDEA 2 — MEDIUM · Focused-Idle "Attract Mode" CRT Screensaver + Burn-In Guard
**1. WHAT.** A diegetic screensaver that engages after true *focused idle* — no keyboard/pointer/touch input for ~90s while the tab is **still visible/focused** (distinct from the existing blur/visibility STANDBY). It dims the UI and floats a slow-drifting phosphor "attract" plate over the CRT: a wandering `◄ ROBCO U.O.S. ►` marquee / scrolling POST-diagnostic ticker whose position slowly shifts to prevent (and wink at) phosphor burn-in. Any input instantly wakes it, reusing the existing `exitStandby()` wake tone + telemetry resync.
**2. WHY.** STANDBY (`ui-core.js:483`) only fires on tab **blur/visibility** and just dims + kills geiger/hum. A user sitting *on* the tab reading — not typing — gets nothing but the 15-minute `_startMemCycle` line (`ui-core.js:472`). The terminal feels dead rather than idling. Attract loops + burn-in mitigation are exactly what CRT terminals did; it's a rich, on-brand, and currently empty gap.
**3. HOW (in-stack).** **Extend the existing standby subsystem** (Protocol 22 — no parallel idle manager). Add a focused-idle timer in `ui-core.js`, reset on the input events already observed (keydown/pointerdown/input). On timeout → add a new `body.attract` class; a fixed `<div id="attractLayer">` (one element in `index.html`) is animated purely by CSS `@keyframes` (long, slow drift) in `terminal.css`. Wake → clear timer, remove class, call the existing `exitStandby()` resync path. Gate behind a new DISPLAY/AUDIO-panel toggle **and** `prefers-reduced-motion` (→ static dim, no drift). Silent by design (no new audio); pause the animation when the tab hides.
**4. BETTER.** Fills the focused-idle void with authentic CRT behavior; the slow drift is a *real* burn-in / static-image-retention mitigation (tangible on OLED/AMOLED phones); reuses standby's wake path (no new audio node); accessible (reduced-motion → static, toggle to disable, no color-only meaning); fully offline.
**5. FIT.** *Visually:* phosphor-glow text over the existing scanline/refresh overlay; drift cadence matches the slow 7s refresh-bar feel; wake reuses `playWakeTone()`. *Architecturally:* extends standby (Protocol 22/23 — `ui-core` owns it); markup+CSS live in already-precached files → **no new precached asset**, one cache rev; no network → **no kill-switch**. Needs Protocol 20 static guards (attract markup + CSS present), a behavioral test (idle arms class; input clears it), a reduced-motion guard (Suite 94 style), and a Protocol 10/17 render-check at 360/412 (overlay must not cause horizontal overflow).
**6. TRADEOFF.** New body-state class must co-exist cleanly with `rad-*`/`standby`/`time-night` overlays (stacking arbitration, e.g. attract during `rad-critical`). Adds a timer + input listeners to `ui-core`. A CSS drift animation has a small battery cost while idle (mitigated: CSS not rAF; paused when hidden). Screensavers annoy some users → **toggle is mandatory**.
**7. EFFORT/RISK.** ~4 files (`index.html`, `terminal.css`, `ui-core.js`, `sw.js`) + toggle wiring + both runners + `test.html` suite marker + render-check. ~6–10 new tests. **Risk: MEDIUM** (body-class interaction, mobile overflow, reduced-motion).
**8. PIPELINE.** **Full Opus-plans → Sonnet-builds → Opus-audits.** It touches the shared body-state/overlay layer with multiple entry states (idle during `rad-warning`; standby↔attract handoff; reduced-motion; mobile). Protocol 8's plan-audit exists precisely to enumerate those before code lands.
---
# IDEA 3 — AMBITIOUS · Interactive "RECON GRID" World-Map Rework
**1. WHAT.** Rework the WORLD MAP panel (`renderWorldMap`, `ui-render.js:1225`) from a static scroll list into an interactive spatial grid: a coordinate-placed region grid drawn from the existing `zones[].gridRow/gridCol` data, with (a) a slow sweeping **radar line** animating across it, (b) tap/click-to-select a cell → the existing `_mapActiveZone` detail/zoom view → a "SET AS CURRENT LOCATION" action routed through `markLocationVisited()`→`recordLocationVisit()`, (c) uncollected-collectible `[?]` pings blinking on their real coordinates (data already coordinate-driven), (d) fog-of-war `[CURRENT]/[VISITED]/[UNKNOWN]` shading, all keyboard-navigable.
**2. WHY.** The map is data-rich but visually flat. Everything a living map needs already exists: coordinates for every zone + collectible (guarded by Suites 74/114/126), fog-of-war (`state.locationHistory` + WU-F11 `markLocationVisited`), and a zoom view (`_mapActiveZone`). Only the *presentation* is a list. It's the app's biggest "underdeveloped screen," and a radar-swept grid is the single highest-impact CRT-feel upgrade available.
**3. HOW (in-stack).** Rewrite `renderWorldMap` to emit a CSS-grid of cells (one per `gridRow×gridCol`) with state classes (current/visited/unknown/has-ping); add a `.radar-sweep` pseudo-element `@keyframes` over the grid container; cells are real `<button>`s (Protocol UI-5) wiring to the **existing** zoom + `markLocationVisited`. All rendering stays in `ui-render` (Protocol 23). Reuse `FALLOUT_REGISTRY.zones` + `collectibles` coords (no new data; both FNV/FO3 already carry coords → game-agnostic). Keep the list/detail as the zoomed view (Protocol 25 — preserve the existing workflow).
**4. BETTER.** Turns present-but-hidden spatial data into a real navigation screen; tap-to-travel gives the map a *function* it lacks; radar sweep is high CRT authenticity at ~zero cost (pure CSS); fog-of-war stays add-only/permanent (data-safe, per WU-F11); a keyboard-navigable grid is an a11y win over a scroll list; no new assets.
**5. FIT.** *Visually:* radar sweep + phosphor cell glow ride the scanline/overlay aesthetic; `[?]` pings reuse the `map-blink` keyframe (`terminal.css:1856`); travel reuses `markLocationVisited→recordLocationVisit→saveState` (additive, permanent). *Architecturally:* `ui-render` only (boundary intact); no network → **no kill-switch**; one served file → one cache rev, **no** new precached asset, **no** APP_VERSION bump. Must preserve/extend Suites 74/114/126/68/79 + Protocol 10/17 render-check at 360/412.
**6. TRADEOFF.** Highest regression surface of the non-MEGA ideas — 5+ dedicated suites and intricate coord/zoom logic. A 6×6 tap grid is genuinely hard to fit at 360px without dropping tap targets below the 28px Protocol-17 floor (likely needs zoom-to-region or horizontal scroll as the mobile interaction). Radar sweep must obey reduced-motion. Reworking a working screen risks Protocol 25 — must keep the existing list/detail as the zoom view.
**7. EFFORT/RISK.** ~4 files (`ui-render.js`, `terminal.css`, maybe `index.html`, `sw.js`) + both runners + `test.html` + render-check + a11y baseline. ~10–15 new/changed tests. **Risk: MEDIUM-HIGH** (mobile fit + tap targets + 5 existing suites + reduced-motion).
**8. PIPELINE.** **Full Opus-plans → Sonnet-builds → Opus-audits.** Reworks a heavily-guarded screen with real mobile-overflow/tap-target risk. The plan must enumerate 360/412/desktop, current-vs-visited-vs-unknown, FNV-vs-FO3 coords, and reduced-motion before any code.
---
# IDEA 4 — MEGA · "WASTELAND UPLINK" — Ambient Living-World Event Engine
**1. WHAT.** A brand-new standalone ambient layer: a deterministic, **offline** world-clock that makes the terminal feel *inhabited even when you're not prompting the AI*. One scheduler (running only while the tab is focused) periodically emits diegetic, state-aware world events through the **existing** feedback channels — never touching durable campaign state:
- **Ambient broadcasts** — unsolicited `> [WASTELAND UPLINK] …` sys-lines via `appendToChat(…, 'sys')`, templated from real state (current `loc`, nearest faction, active-quest count, in-game time-of-day). No AI, no network — a local template bank keyed off `GAME_DEFS[ctx]`.
- **Radiation weather** — occasional "rad-storm" sweeps that briefly drive the existing `body.rad-warning` CRT interference + a short geiger tick-up, then clear. **Visual/audio only — does NOT mutate `state.rads`.**
- **Day/night wasteland cycle** — drive the existing `body.time-night` class + subtle hum/ambient shifts off the in-game clock so dusk/dawn actually *land* on the CRT.
- **"Incoming transmission" hooks** — rare `> UNKNOWN FREQUENCY DETECTED — REPLY?` nudges that merely pre-fill the input, inviting the Courier back into play.
All four expressed through *existing* hooks (chat sys-lines, `body` CRT classes, synthesized audio), unified under one weighted/cooldown'd scheduler.
**2. WHY.** The terminal is purely reactive — it only comes alive when the AI is prompted or a stat changes; between prompts it's inert (standby just dims). A Fallout Pip-Boy/terminal should feel *plugged into a living wasteland*. There's a rich set of dormant expression hooks (`rad-*` classes, `time-night`, geiger, ambient audio, sys-line chat) that today fire only on explicit state changes — nothing drives them ambiently. This engine is the new living dimension: a wasteland that ticks on its own.
**3. HOW (in-stack).** New global-scope file `js/ambient.js`, loaded after `ui-core` in the existing script order (it only **reads** state via the established getters and **calls existing** UI/audio/`appendToChat` functions — mutates nothing durable). An `AmbientEngine` with: a focused-only `setInterval` "world tick" (paused on blur/standby, reusing the standby hooks); a weighted event table with per-event cooldowns; a template bank sourced from `GAME_DEFS[ctx]` (game-agnostic). Events call **only** existing functions (`appendToChat`, a transient `setGeigerRate`, `body.classList` for rad/time, ambient audio) — strictly transient, behind a **hard invariant that it never calls `saveState`/`pushToCloud`/writes `robco_v8`**. Deterministic (no AI). Gated by a master "Immersion" toggle + intensity slider + `prefers-reduced-motion`.
**4. BETTER.** Adds an entirely new ambient dimension with **zero new precached media** (all text + synthesized audio + CSS reuse); deterministic + offline → no kill-switch dependency and **cannot cause an outage** (reads state, drives transient UI only); strengthens the "living terminal" fantasy more than any single-screen change; fully gated (toggle + intensity + reduced-motion) so it degrades cleanly to silence; game-agnostic via `GAME_DEFS`. Because it persists nothing, it is inherently data-safe (Protocol 24/34 — never persists AI/derived state).
**5. FIT.** The *most* native idea — it's a conductor for the instruments already in the orchestra (`rad-warning` flicker, `time-night`, geiger, ambient hum, sys-lines). *Architecturally:* new file follows the global-scope load-order convention (Protocol 23 — reads via getters, drives via existing functions, writes nothing); no network/IO → Protocol 32/33 kill-switch not strictly required, but it still gets a fail-safe toggle in that spirit. The new file **is** added to `sw.js` ASSETS — one new precached **JS** file (justified: it's code, tiny, and there's no media). Heavy test coverage (Protocol 13/20): a load-bearing static+behavioral guard that it **never** calls `saveState`/`pushToCloud`/writes `robco_v8`; reduced-motion + toggle-off = fully silent; parity across both runners + `test.html`; a new dedicated Suite.
**6. TRADEOFF.** Biggest, most cross-cutting scope — it drives the shared `body`-state layer that `rad`/`standby`/`time` already use, so class-stacking conflicts (ambient rad-storm during a *real* `rad-critical`; `time-night` during attract mode) must be arbitrated. A background interval has battery cost (mitigated: focused-only, long tick, pause on blur). Risk of feeling noisy/gimmicky (mitigated: conservative cooldowns, low/ off-by-default intensity). The "never mutate state" invariant is load-bearing and easy to violate in a future edit → needs a **permanent** guard. Adds one precached JS asset (small, code not media). Ambient sys-lines could clutter the comm-link log (mitigate: 'sys' sender, don't persist them past the chat cap).
**7. EFFORT/RISK.** New `js/ambient.js` + `index.html` (script tag + toggle/slider) + `sw.js` (ASSETS + rev) + `ui-core` wiring for pause-on-standby + both runners + `test.html` + a new dedicated Suite. ~20–30 new tests. **Risk: HIGH** (new subsystem, shared-layer interaction, load-bearing no-mutation invariant, battery).
**8. PIPELINE.** **Full Opus-plans → Sonnet-builds → Opus-audits, likely multiple loops.** A new (offline) subsystem with a critical data-safety invariant and shared-state interactions. The Protocol 8 plan-audit — enumerate every event × every concurrent body-state × reduced-motion × toggle-off × mobile — is mandatory before a line is written.
---
## At-a-glance
| # | Tier | Idea | Layer | New assets | Cache | Risk | Pipeline |
|---|------|------|-------|-----------|-------|------|----------|
| 1 | Quick | Boot MOTD / welcome-back | Boot | none | 1 rev | Low | Ship-direct |
| 2 | Medium | Focused-idle attract mode | Idle visual | none | 1 rev | Medium | Full workflow |
| 3 | Ambitious | Recon-grid map rework | Spatial/map | none | 1 rev | Med-High | Full workflow |
| 4 | MEGA | Wasteland Uplink event engine | Ambient/temporal | 1 JS (code) | 1 rev | High | Full workflow ×loops |
_All four: no APP_VERSION bump, no framework, no redirect auth, vanilla global-scope, offline-safe._
STAMP · generated for RELEASE v2.8.5 commit 06e5180 (06e51801b38a) · archive input-tree hash c07fbfbdd2e1ddeb · 754 files · no wall-clock timestamp (regenerates identically when nothing changed).