GENERATED VIEW · PRIVATE ARCHIVE · DO NOT SERVE
RobCo Industries · Archive Museum

PLANNED_FEATURES_DETAILED.md



RELEASE

planning/2.8.0/slates/PLANNED_FEATURES_DETAILED.md

sha256 5571f875ee712f39 · 59826 bytes · original held in the private archive

# PLANNED_FEATURES_DETAILED.md — Precise, Version-by-Version Roadmap (Steps 2 / 3 / 4) > **ANALYSIS ONLY. Nothing implemented, committed, or pushed. No served code written. No parked plan modified.** > Started clean from `origin/dev` (`git fetch && git checkout dev && git reset --hard origin/dev`). > Baseline: `dev` @ `90ff0f4` (v2.7.0, cache `robco-terminal-v2.7.0-r9`, **1557 tests / 130 suites**). `planning/` is gitignored — this file is untracked. > > **Purpose.** The parked roadmap (`ROADMAP_REBASELINE.md` and its sibling audits) is an authoritative but high-level end-state doc. The owner wants it **much more precise** — a per-version plan grounded in the real code, with the exact build order, per-feature "what exists today → what it becomes → how, in-stack," the hard constraints each feature triggers, and the invariants each version must hold. This document delivers that. It **supersedes nothing**; it is the precise expansion of `ROADMAP_REBASELINE.md`, which remains the dependency spine. > > **Sources ground-truthed this pass:** `ROADMAP_REBASELINE.md` (the spine), `ROADMAP_AUDIT.md` (the 15 enhancements), `IMMERSION_AUDIT.md` (the 15 immersion items), `WASTELAND_UPLINK_SPEC.md` (the U0–U5 engine), `FEATURE_REMAKES.md` (the 4 screen rebuilds), plus direct reads of `js/api.js`, `js/state.js`, `js/ui-core.js`, `js/ui-render.js`, `js/ui-audio.js`, `js/cloud.js`, `sw.js`, `index.html`, `firestore.rules`, `scripts/gate.js`, `tests/robco-diagnostics.js`, `manifest.json`, and `CLAUDE.md`/`RULES.md`. --- ## 0. How to read this document Each version gets five things the owner asked for: 1. **Codename + theme** — a one-line identity for the release. 2. **Build order** — the exact sequence, **with the dependency reason for every ordering** (why this must precede that). 3. **Per-feature detail** — what EXISTS today (named file/function/panel + its current limitation), what it BECOMES, the in-stack technical approach (vanilla, global-scope, no build), the data/state involved (named fields; Protocol-4 handling where relevant), the hard constraints it triggers, and the test/gate implication. 4. **Hard rules / invariants** — the load-bearing contracts the version must never violate. 5. **End state** — what "done" looks like. ### 0.1 Load-bearing facts verified against live code this pass (`dev` @ 90ff0f4) | Claim | Verdict | Precise evidence | |---|---|---| | **App Check is live in code** (not a placeholder) | **TRUE** — it initializes | `cloud.js` holds a real reCAPTCHA-v3 site key; the recent commits (`90ff0f4`, `1352237`, `3d1be9e`) already scoped the debug token to localhost, fixed the site key, and restored the init guard. The remaining gap is **`firestore.rules` App-Check enforcement + a `remoteTransmissions`/`aiIntercept` posture note**, NOT client wiring. | | **`getSystemDirective()` is a ~195-line monolith** | **TRUE** | `api.js:23–218` (ends where `_validateTriNode` begins at `:219`). | | **`GAME_DEFS[ctx].ai` already exists as data** | **TRUE** | `state.js` FNV block `ai:` at ~`:369`, FO3 at ~`:454`, carrying `skillSystemText` / `factionSystemText` / `irreversibleTriggers`. The directive already reads these as data. | | **The last GA-5 two-game literals are 3 tracker ternaries** | **TRUE — precisely located** | `api.js:179` (`ctx === 'FO3' ? …Lincoln… : ''`), `:187` (`ctx === 'FNV' ? …Traits…`), `:195` (`ctx === 'FNV' ? …Magazines…`). These are the **only** remaining Protocol-38 residual in the directive; everything else already routes through `GAME_DEFS[ctx].ai`. | | **`window.onload` boot block is a ~568-line monolith** | **TRUE** | `ui-core.js:330–898`. | | **`autoImportState` has no headless behavioral test** | **TRUE** | `autoImportState` at `api.js:441`, explicit field-mapping; `_validateTriNode` at `api.js:219`; exercised only in-browser by `tests/test.html`, never in a Node VM sandbox (TS-GAP-7). | | **The gate compares only TOTAL counts across runners** | **TRUE** | `scripts/gate.js:~228` fails only when `nodeTotal !== psTotal` — no per-suite parity (H1-7b). | | **`js/ambient.js` does not exist** | **TRUE** | Not on disk — the UPLINK engine is greenfield. | | **Manifest name/version-less** | **TRUE** | `manifest.json` `"name": "RobCo U.O.S."`, `"short_name": "RobCo"` — no version string (Protocol 2). | | **State fields present today** | **TRUE** | `state.js:534+`: `karma`, `ticks`, `loc`, `rads`, `inventory`, `squad`, `locationHistory`, `skillBooks`, `traits` (FNV), `lincolnItems` (FO3), `magazines` (FNV), `mapView`, `playthroughType`, `gameContext`, `stats`, `factions`, `equipped`, `ammo`, `collectibles`. | ### 0.2 The Steps ↔ versions map (owner's naming) | Owner "Step" | Version | Theme | Semver note (Protocol 2) | |---|---|---|---| | **Step 2** | v2.8.0 | AI-residue + ambient living-world + client infra + the foundations everything later stands on | MINOR — automatic | | **Step 3** | v2.9.0 | Gameplay-system overhauls into native tools + the hacking-gated dev/debug console | MINOR — automatic | | **Step 4** | v3.0.0 | Fallout 4 as a data-only third game + the moved-in heavies | **MAJOR — requires explicit owner confirmation** | ### 0.3 The governing principles the owner folded in (applied throughout) - **WASTELAND UPLINK is ONE engine.** Radio + map-encounter rolls + INTERCEPT + Remote Transmissions all merge into it. **Day/night is RE-INSTATED** (the earlier "removed" decision is reversed): the world-clock, rad-storm weather, and Dusk/Dawn are back in scope. The engine **writes nothing durable** — no `saveState`, no `state.rads`/`state.ticks` mutation, no cloud, disjoint `ambient-*` classes, no-persist render path — enforced by a permanent gate guard. - **IN-GAME vs IN-TERMINAL clarity.** Every ambient/broadcast signal must read as *terminal-side* and never be mistaken for a game event. **Dev/staging must be able to force-fire every time- or probability-gated ambient feature.** - **ONE map.** The single geographic per-game SVG map (Phosphor Cartography inline-SVG as the low-risk first cut); **Recon Grid is dropped.** Exploration is the data/journal layer on top. - **Per-game identity baseline** for FNV + FO3 lands in Step 2; a post-FO4 parity retrofit follows in Step 4. - **The hacking minigame unlocks a full dev/debug console**, with a staging bypass so devs never have to play the minigame to test. - **Onboarding is skippable + persistent**, with a new-feature-highlight protocol for returning users. - **"Adding a new game is easy and non-breaking — not dogmatic zero-code."** Content (data files, registry, CSVs) is *expected labor*; what must never recur is feature-code search-and-replace of game literals. - **Moved to Step 4:** Streaming Two-Phase Narrator, Companion Memory, Web Workers, DLC map zones (and FO4 itself). - **App Check is already done and enforced in code** — Step 2 only verifies console registration + `firestore.rules` enforcement + a posture note. It is *not* new wiring; do not schedule it as a build. --- # STEP 2 — v2.8.0 · Codename **"WASTELAND UPLINK"** **Theme: the living terminal, and the foundations it stands on.** The terminal stops being a static tactical webapp and starts to *breathe* — an ambient wasteland ticks around the operator, the boot screen remembers them, places sound different, their deeds echo back as news. But none of that gets built until the two monoliths that block it are decomposed, the AI-write path has a behavioral guard, and the parallel data lane is under way. Step 2 is **foundations first, then the one ambient engine, then its consumers.** ## S2.1 — DONE-ALREADY / STRIP (do not re-plan these) Shipped in the 2.7.0 program and Suite-guarded; the parked plan's "BUILD-NOW" for them is closed: - All **6 native calculators** (VATS/TRADE/THREAT/CONSULT/BIO-SCAN/LOOT) — Suites 105–110. Only the optional **AI-augment garnish** on top remains. - All **9 device capabilities** + F10 session-stats merge + F11 mark-visited — Suites 115–126. Step-2 device cluster shrinks to the **4 SPEC-FIRST caps not yet pulled in** (Tier 6). - **Per-game theming GT-1/2/3** (`THEMES` table + `GAME_DEFS[ctx].theme` + per-game default optics + identity strings) — Suites 124/127/130. Theming remainder = GT-4 + GT-5, folded into the per-game EXPERIENCE seam (Tier 4). - **App Check client wiring** — initializes with a real key; the 3 most recent commits already corrected the key/token/guard. Remainder = console registration + `firestore.rules` + a posture note (S2-F1). - **`loadUI` dirty-diff perf** + the **a11y baseline** (`:focus-visible`, reduced-motion, `aria-live`, sysModal focus-trap) — Suites 60/91/92/94. Only the a11y **deep** pass (S2-C7) remains. - **WU-B5 cloud-pull round-trip VM test** — Suite 46/101. This is the *cloud-pull* path; the **`autoImportState` AI-path VM test (TS-GAP-7) is still missing** (S2-F4). **Moved OUT of Step 2:** Streaming Two-Phase Narrator, Companion Memory, Web Workers, DLC map zones → **Step 4**. The hacking minigame + its debug-panel unlock → **Step 3**. SW background-sync → **dropped** (no workload; re-evaluate only if one appears). ## S2.2 — Build order (with the dependency reason for each ordering) The build is tiered. Within a tier, items marked **∥** touch disjoint files and can run in parallel. Later tiers depend on earlier ones. The two serial hazards are the **`api.js` cluster** and the **`ui-core.js` boot cluster** (below). ### TIER 0 — Preconditions & foundations (must come first — they unblock everything) 1. **S2-F1 ∥ — App Check verification** *(not new code)*. **Why first:** it is the precondition for *every* networked residue (INTERCEPT AI-augment, Remote Transmissions). Because the client already initializes, this is verification: confirm Firebase-console registration, enforce App-Check in `firestore.rules`, replace the last stale placeholder comment, and record a posture note for the future `aiIntercept` / `remoteTransmissions` flags. **Files:** `cloud.js`, `firestore.rules`. **Risk: Low.** 2. **S2-F2 ∥ — Decompose `getSystemDirective()` + retire the GA-5 ternaries.** **Why before features:** every new AI directive (INTERCEPT/OVERSEER/SCAN) injects text *here*, and it is the **#1 FO4 blocker**. The precise work is smaller than the audit implies because `GAME_DEFS[ctx].ai` already carries `skillSystemText`/`factionSystemText`/`irreversibleTriggers` as data — the residual is only the **three tracker-directive ternaries at `api.js:179` (Lincoln, FO3) / `:187` (Traits, FNV) / `:195` (Magazines, FNV)**. Move those into `GAME_DEFS[ctx].ai.trackerDirectives` (per-game data), split the ~195-line string into named `_directiveSection_*()` builders, and land a **Protocol 14 AI-contract test in the same commit**. **Files:** `api.js`, `state.js`. **Risk: Medium.** 3. **S2-F3 ∥ — Decompose the ~568-line `window.onload`** (`ui-core.js:330–898`) into named boot seams (`_hydrateStateFromStorage` / `_restoreMuteToggles` / `_wirePanelPersistence` / `_wireKeyboardShortcuts` / `_startSessionTimers`). **Why before features:** Step 2 attaches Boot-MOTD, ambient-init, the attract layer, standby-watch extension, and wake/radio restore directly onto this block — decompose *before* piling on. Protocol 8 plan-audit must enumerate every boot path; Suite 56 load-order must stay green. **File:** `ui-core.js`. **Risk: Medium.** 4. **S2-F4 ∥ — `autoImportState` VM-sandbox behavioral test (TS-GAP-7)** + settle numeric clamping (TS-COV-1). **Why before AI-residue:** the AI→state write path every residue feature depends on has *no* headless behavioral guard today (only in-browser `test.html`). This establishes the behavioral-test tier. **Files:** `tests/*` (both runners at parity). **Risk: Medium.** 5. **S2-F5 ∥ — Per-suite parity check + merge-time full-gate discipline.** **Why now:** the gate compares only TOTAL counts (`scripts/gate.js:~228`), so the two runners can drift per-suite and still pass. Step 2/3 add hundreds of tests — tighten before the volume lands. **File:** `scripts/gate.js`. **Risk: Low–Med.** *All five are mutually parallel (disjoint files). F2 + F3 are hard prerequisites for the feature tiers; F1/F4/F5 are gating infra. Land Tier 0 as one coordinated foundation wave.* ### TIER 1 — DATA LANE (the only genuinely parallelizable work — start immediately, run the whole window) 6. **S2-D1 ∥ — Per-vendor `VENDOR_STOCK` dataset (WU-D4d)**, fallout.wiki-sourced (Protocol 3). **Unblocks** Step-3 TRADE realism, faction vendor lock/unlock, and Build-Planner economy. **Files:** `db_nv.js`/`db_fo3.js` + `VENDORS.CSV`, Suite 78 sync. 7. **S2-D2 ∥ — FNV DLC quest lines** (Dead Money / Honest Hearts / Lonesome Road; Old World Blues' 5 already exist — ~30–35 quests, `dlc` schema already present). **Unblocks** the Step-3 Quest Tracker overhaul, which otherwise ships half-empty. **Files:** `reg_nv.js`, Suite 82 sync. *This lane has **zero collision** with UI/api/cloud and takes **no `APP_VERSION` bump**. Formally a v2.9.0 content dependency, but START it in the v2.8.0 window so Step 3 isn't blocked.* ### TIER 2 — The WASTELAND UPLINK substrate (owner decision #1 — the ONE engine, **day/night RE-INSTATED**) Built substrate-up per `WASTELAND_UPLINK_SPEC` §11. The new file is `js/ambient.js`, loaded **after `api.js`, before the `cloud.js` module** (§3 of the spec), self-booting on `DOMContentLoaded` after `loadUI()` runs once. 8. **S2-U0 — Seeded-roll engine + the permanent no-write gate guard.** `js/ambient.js` skeleton: a mulberry32/xorshift PRNG + `rollTable(seed, table)`, zero side-effects, **plus the world-clock read** (`hour = Math.floor((state.ticks % 240) / 10)`, phase = day/dusk/night/dawn — reinstated). Establish the load-bearing **"writes-nothing-durable" Suite NOW** so every later phase inherits it. **Depends on:** F2/F3/F4. 9. **S2-U1 — UPLINK push channel + static broadcast bank.** `GAME_DEFS[ctx].ambient.broadcasts` surfaced via `appendToChat(txt, 'sys', true)` (the no-persist push); focused-only 45 s tick; master toggle + intensity device prefs (`robco_ambient_*`); **+ the dev/staging force-fire hook** (owner decision #2). **Depends on:** U0. 10. **S2-U2 — Day/night substrate + rad-storm / interference weather.** Transient `ambient-dusk`/`ambient-dawn` transition tints layered *under* the authoritative `time-night`; `ambient-radstorm` (cosmetic flicker + transient geiger blip) with **real-hazard suppression at `rads ≥ 200`** and geiger-rate restore on storm end. **Day/night reinstated → weather may be night-weighted.** **Depends on:** U1. 11. **S2-U3 — Radio tuner (PULL).** Extend the shipped `startRadio()` synth bed (WU-F5, Protocol 22 — no parallel radio) with the shared `bulletins` + `djGreetings` bank; day/night greetings reinstated ("good evening, wastelanders" = the world-clock phase rendered as speech). **One radio, two directions (push/pull).** **Depends on:** U1 bank + U2 clock. 12. **S2-U5 — INTERCEPT AI-augment (optional, flagged).** `enrichSignal()` seam + `aiIntercept` kill-switch + fail-safe fallback to the static bank; injection-hardened; Tri-Node contract; pull-only. **Depends on:** F1 (App Check), F2 (directive), F4 (test), U1. *U4 (map-encounter rolls) is **deferred to Step 3** — the roll engine ships here (U0); the map **consumes** it in S3-M2 (consolidation C1: one seeded-roll engine, many consumers).* ### TIER 3 — Immersion consumers of UPLINK (all ride the substrate; all terminal-side) 13. **S2-I1 — Session-Resume Continuity Readout** (IMMERSION #2) — boot MOTD block. **Depends on:** F3 boot seams. 14. **S2-I2 — Location-Aware Ambience** (IMMERSION #3) — zone-type → ambience profile. **Depends on:** U1/U2. 15. **S2-I3 — Personal-Legend News Callbacks** (IMMERSION #4) — deterministic milestone → templated bulletin. **Depends on:** U1/U3 bank + seeded-roll. 16. **S2-I4 — INTERCEPT Inbox** (IMMERSION #10) — `[INTERCEPT]` native command + static bank + occasional ambient intercepts. **Depends on:** U1; AI layer = U5. 17. **S2-I5 — Focused-Idle Attract Mode** (IMMERSION #6) — telemetry attract layer with burn-in guard. **Depends on:** F3, standby subsystem. 18. **S2-I6 — Standby "Powered-Down Watch"** (IMMERSION #15) — extend `enterStandby`/`exitStandby`; report real elapsed on return. **Depends on:** standby subsystem. 19. **S2-I7 — Chassis Feedback Choreography** (IMMERSION #14) — signature table over shipped haptic (WU-F2) + synth SFX. **Depends on:** WU-F2 (shipped) + UPLINK events. 20. **S2-I8 — Diegetic Cold-Boot Onboarding** (IMMERSION #11) + **Playthrough/RNG UX clarity** (ROADMAP #13). First-cold-boot handshake reusing the WU-E2 idle banner template. **Skippable + persistent** (fires once, never again). **Depends on:** F3, WU-F6 boot, WU-E2 template. 21. **S2-I9 — Dusk/Dawn That Lands + Time-of-Day Voice** (IMMERSION #8) — **REINSTATED** with day/night. Transition tints + DJ greeting + night-weighted tables. **Depends on:** U2/U3. 22. **S2-I10 — Wasteland Calendar & Anniversaries** (IMMERSION #1) — date-keyed observances from the in-world calendar (`_resolveGameDateTime`, per-game epochs in `GAME_DEFS[ctx].calendar`). With day/night reinstated, the in-world date is again a legitimate read. **Depends on:** UPLINK bank + calendar helpers. ### TIER 4 — Per-game EXPERIENCE data seam (the connective tissue for Tier 3) 23. **S2-E1 — Per-game EXPERIENCE as `GAME_DEFS` data** (ROADMAP #12 + IMMERSION #12). Extend `GAME_DEFS[ctx].voice`/`.ambient`: terminology, faction framing, ambient bank, CRT character. **Folds in GT-4** (per-game accent CSS) **+ GT-5** (game-styled save layout, partly shipped via WU-T3 `saveLabel`). A Suite-89-style guard fails the build on any new `=== 'FO3'` literal. **This is the per-game identity baseline for FNV + FO3** the owner wants in Step 2. **Depends on:** F2 (per-game AI voice) + U1 (ambient seam). Scope-guard: keep to terminology/faction-framing/ambient/CRT-character — do NOT expand to "all 10." ### TIER 5 — Remote Transmissions (the online content-drop source of UPLINK) 24. **S2-R1 — Remote Transmissions = the third source** feeding the SAME offline UPLINK bank (alongside static + AI-INTERCEPT). Read-only public Firestore + `remoteTransmissions` kill-switch + graceful offline fallback (Protocol 32/33). The offline bank is the fail-safe. **This is the only genuinely-undesigned Step-2 item — it needs a data-model + security-rules spec pass before build (OPEN Q3).** **Depends on:** F1 (App Check) + U1 bank. ### TIER 6 — SPEC-FIRST device capabilities not pulled into 2.7.0 25. **S2-V1 — CRT-tilt / gyro parallax** (DeviceOrientation) — reduced-motion + permission-gated fallback. 26. **S2-V2 — `share_target` receiver** (PWA manifest share target) — pairs with S2-A6. 27. **S2-V3 — TTS audio-log** (SpeechSynthesis) — opt-in; pairs with S2-A3. 28. **S2-V4 — Ambient-light optic calibration** (AmbientLightSensor) — auto-nudge High-Lumen; graceful fallback. *(The 5th SPEC-FIRST cap — the hacking minigame — moved to Step 3.)* ### TIER 7 — AI generative-residue (all gated behind F1 + F2 + F4; each needs a kill-switch flag + static fallback) 29. **S2-A1** — INTERCEPT AI-augment = U5 (already ordered). 30. **S2-A2** — RADIO banter — optional online garnish on the Personal-Legend news bank (S2-I3). 31. **S2-A3** — AUDIO-LOG / TTS narration — ties to S2-V3. 32. **S2-A4** — SCAN-AREA encounter generation — optional AI enrichment feeding the Step-3 map encounter table. 33. **S2-A5** — OVERSEER quest hook — injects via the decomposed `getSystemDirective` (F2). 34. **S2-A6** — SHARE-TARGET → AI vision parse — ties to S2-V2. 35. **S2-A7** — TRADE / BIO-SCAN banter — optional flavor over the shipped natives. *(Companion Memory → Step 4; HACK-FAIL AI taunt → Step 3. AI-routed console commands remain permanently SKIPPED — redundant, highest injection surface.)* ### TIER 8 — Client-infra bundle (standalone units) 36. **S2-C1 — IndexedDB migration** as a standalone reversible unit (dual-read shadow + checksum/version + rollback). **HIGH risk; test-first; NOT bundled.** Must preserve the beforeunload-flush guard (Suite 95). 37. **S2-C2 — Migration test harness** (supports C1; build alongside). 38. **S2-C3 — Cloud-save conflict resolution + version history.** 39. **S2-C4 — Full backup export/import.** 40. **S2-C5 — Diagnostics export.** 41. **S2-C6 — Unified settings / profile hub** (SETUP hub merging onboarding + settings; reuses `_openSysModal`). 42. **S2-C7 — a11y DEEP pass** (beyond the shipped baseline). 43. **S2-C8 — Native procedural flavor-text engine.** 44. **S2-C9 — Offline shell hardening.** 45. **S2-C10 — New-game-readiness / game-agnostic audit** — validate the seam is FO4-ready. **Run LATE in Step 2 (de-risks Step 4).** *Moved out: list virtualization → folds into the Step-3 Manifest & Loadout remake. Web Workers → Step 4 (no workload). Onboarding tour → folds into S2-I8.* ## S2.3 — Per-feature detail (the code-grounded core) ### The two decompositions (the foundation) **S2-F2 — `getSystemDirective()` decomposition + GA-5 retire.** - **Exists today:** one ~195-line template-literal function, `api.js:23–218`, called every AI turn from `transmitMessage()` (`api.js:1441`). It *already* reads `GAME_DEFS[ctx].ai.skillSystemText`/`factionSystemText`/`irreversibleTriggers` as data — so most of it is game-agnostic. The **only** remaining hardcode is three inline tracker ternaries: Lincoln at `api.js:179` (`ctx === 'FO3' ? … : ''`), Traits at `:187` (`ctx === 'FNV' ? …`), Magazines at `:195` (`ctx === 'FNV' ? …`). - **Becomes:** those three strings move into `GAME_DEFS[ctx].ai.trackerDirectives` (per-game data, empty for a game that lacks a tracker), and the monolith splits into named `_directiveSection_*()` builders assembled by `getSystemDirective()`. A new game contributes directive text purely as a `GAME_DEFS[ctx].ai` block — **no string surgery**. - **In-stack:** vanilla, global scope; the assembled output is byte-identical to today's for FNV/FO3 (regression-guarded). - **State/data:** no `state` change; extends the read-only `GAME_DEFS[ctx].ai` seam. - **Hard constraints:** **Protocol 14 AI-contract test in the same commit** (schema + `autoImportState` round-trip); Suite 89 agnosticism guard extended to fail on any new `ctx === 'FO3'`/`'FNV'` literal in `api.js`; served-file change → **Protocol 1 cache bump**. - **Gate implication:** the AI-contract round-trip test is mandatory; Suite 89 tightens. **S2-F3 — `window.onload` decomposition.** - **Exists today:** ~568-line block, `ui-core.js:330–898`, doing state hydration, mute-toggle restore, panel-persistence wiring, keyboard-shortcut wiring, session-timer startup, and boot sequencing — the single most regression-prone block. - **Becomes:** five named seams (`_hydrateStateFromStorage` / `_restoreMuteToggles` / `_wirePanelPersistence` / `_wireKeyboardShortcuts` / `_startSessionTimers`) called in order. Every Step-2 boot feature (MOTD, ambient-init, attract, standby-watch, wake/radio restore) attaches to a *named* seam, not the monolith. - **In-stack:** pure extraction; no behavior change. - **Hard constraints:** Protocol 8 plan-audit enumerating every load / reload / cache-clear / saved-value / desktop-vs-mobile / new-vs-migrated boot path; Suite 56 load-order guards stay green; boot-smoke + render-check at the push boundary; **Protocol 1 cache bump.** - **Gate implication:** boot-smoke is the safety net; add a static guard that the five seams exist and are called from boot. ### The UPLINK engine (the centerpiece) **S2-U0 — seeded-roll engine + world-clock + no-write guard.** - **Exists today:** nothing — `js/ambient.js` is greenfield. The hooks it will ride exist: `appendToChat(txt,'sys',true)` no-persist push (`ui-core.js`), `setGeigerRate()` (`ui-audio.js`), the `hour = floor((state.ticks%240)/10)` read (`ui-core.js` `updateMath`), `getGameContext()`/`GAME_DEFS[ctx]` (`state.js`). - **Becomes:** a plain global-scope `AmbientEngine` with a mulberry32 PRNG, `rollTable(seed, table)`, and a read-only world-clock (`getPhase()`), zero side-effects. - **In-stack:** vanilla; `Math.random()`/`Date.now()` used ONLY to derive a fresh seed at dispatch time, never inside a testable roll (so `rollTable` is deterministic and unit-testable). - **State/data:** reads `state.ticks` (never writes); no new `state` field. Device prefs `robco_ambient_on` / `robco_ambient_intensity` are localStorage-only (not campaign state). - **Hard constraints:** the **permanent static "writes-nothing-durable" Suite** ships HERE — asserts `ambient.js` contains zero `saveState`/`pushToCloud`/`pullFromCloud`/`localStorage.setItem('robco_v8'|'robco_chat')`/`setDoc`/`addDoc`/`updateDoc`/`signInAnonymously`/`state.rads =`/`state.ticks =` and never adds `'rad-warning'`/`'time-night'`/`'standby'` via `classList.add`; every `appendToChat(` in the file passes a truthy 3rd arg. New precached JS file → add to `sw.js` ASSETS + **one `-rN` cache bump.** - **Gate implication:** seeded-roll determinism tests + the load-bearing no-write guard, established now so every later phase inherits it. **S2-U1 → U3 — push channel, day/night + weather, radio tuner.** - **Exists today:** `startRadio()` synth bed (WU-F5, `ui-audio.js`) — a station bed with no bulletin content; `time-night` toggled by `updateMath` from `state.ticks`; `ambient-*` classes unused. - **Becomes:** ambient `> [WASTELAND UPLINK] …` sys-lines on a focused-only 45 s tick; `ambient-dusk`/`ambient-dawn` transition tints + `ambient-radstorm` weather with real-hazard suppression; the radio extended (Protocol 22) with the shared `bulletins`/`djGreetings` bank and day/night greetings. - **In-stack:** all copy templated from live state at emit time; body-class arbitration keeps `ambient-*` disjoint from the real `rad-*`/`time-night`/`standby` names; `ambient-*` CSS lives in the already-precached `terminal.css`. - **State/data:** `GAME_DEFS[ctx].ambient = { broadcasts, bulletins, encounters, djGreetings, almanac, news }` — a new **read-only per-game data seam** (Protocol 38). No campaign `state` field. - **Hard constraints:** reduced-motion hard-block (storm → static dim, tints → instant); focused-only + paused on blur/hidden (battery); low-frequency so `aria-live` (Suite 94) isn't spammed; **the dev/staging force-fire hook (owner #2) lands in U1** and is later subsumed by the Step-3 debug console. - **Gate implication:** behavioral no-persist guard (a broadcast appends a `.msg-sys` node but `chatHistory`/`localStorage.robco_chat` are unchanged); class-arbitration + storm-suppression + reduced-motion tests; per-game bank-presence guard. **S2-U5 — INTERCEPT AI-augment.** - **Exists today:** nothing; the Tri-Node contract + `responseMimeType:'application/json'` lock + `_validateTriNode` (`api.js:219`) exist to ride. - **Becomes:** a single optional `enrichSignal(staticEntry) → Promise<string>` seam behind the `aiIntercept` kill-switch; pull-only (`[INTERCEPT]`); on any failure/timeout/flag-off/no-key → the static bank renders as-is. - **Hard constraints:** Protocol 32 (kill-switch) + Protocol 33 (fail-safe read) + Protocol 24 (validated before display) + Protocol 14 (contract test) + Protocol 30/31 (auth untouched); AI output still displayed via `appendToChat(…,'sys',true)` → not persisted; injection-hardened (player/state text delimited as data). Free / BYO-key: only the optional augment uses the user's own Gemini key. ### Remote Transmissions (the undesigned item) **S2-R1.** - **Exists today:** nothing — no design doc; the parked bullet is one line. - **Becomes:** an owner-pushed read-only public Firestore collection whose docs feed the SAME offline UPLINK bank as a third source. Requires an owner-approved doc shape, a read-only public security rule, cache/offline behavior, and a render surface **before** it can be built. - **Hard constraints:** App Check-gated; `remoteTransmissions` kill-switch + graceful offline fallback to the static bank (the fail-safe); **additive writes only** on the owner side (Protocol 34); **needs a thin spec pass (OPEN Q3) before scheduling.** ### Client-infra highlight: IndexedDB migration (the risk one) **S2-C1.** - **Exists today:** all persistence is `localStorage` (`robco_v8` container, debounced 500 ms writes, flushed on `beforeunload` — Suite 95). - **Becomes:** IndexedDB-backed persistence via a **dual-read shadow** (read IDB, fall back to localStorage) + checksum/version + explicit rollback, delivered as a standalone reversible unit — NOT bundled. - **Hard constraints:** must preserve the beforeunload-flush guard (Suite 95); test-first via S2-C2; **HIGH risk** — a single mis-migration silently erases a save. This is the one Step-2 item that can cause data loss; treat it with the Protocol 8 full three-stage pipeline. ## S2.4 — Hard rules / invariants for v2.8.0 1. **The UPLINK engine writes nothing durable.** No `saveState`, no `pushToCloud`/`pullFromCloud`, no `robco_v8`/`robco_chat` write, no `state.*` mutation (especially never `state.rads`/`state.ticks`). Every emitted line uses `appendToChat(txt,'sys',true)`. Enforced by the permanent static + behavioral gate guard shipped in U0. 2. **Disjoint class namespace.** The engine owns only `ambient-*` classes; the real `rad-warning`/`rad-critical`/`rad-fatal`/`time-night`/`standby` names are untouched. Real hazards outrank cosmetic ones (`ambient-radstorm` suppressed when `rads ≥ 200`; geiger rate restored on storm end). 3. **IN-GAME vs IN-TERMINAL clarity.** Every ambient/broadcast signal reads as terminal-side and never implies a game event the player didn't cause. **Every time- or probability-gated ambient feature exposes a dev/staging force-fire entry** (owner #2). 4. **Fail-safe & offline.** The deterministic core needs no network and can't cause an outage; the AI-augment degrades to the static bank; nothing blocks boot. Any networked residue (INTERCEPT, Remote Transmissions) has a kill-switch flag + graceful fallback (Protocol 32/33), and the kill-switch read itself is fail-safe (Protocol 33). 5. **Foundations before features.** No AI-residue ships before F1 (App Check verified) + F2 (directive decomposed) + F4 (autoImportState VM test). No boot feature ships before F3 (onload decomposed). 6. **Auth untouched.** Popup-only (Protocol 30); `signInAnonymously` stays guarded (Protocol 31); no redirect path added. 7. **Every served-file change bumps `CACHE_NAME`** (Protocol 1); the full gate + both-runner parity + Protocol 2/2a docs sync apply on **every `dev` commit** (Protocol 43). 8. **Game-agnostic (Protocol 38).** All ambient copy/tables live in `GAME_DEFS[ctx].ambient`/`.voice`; a Suite-89-style guard fails the build on any new game literal. ## S2.5 — End state The terminal is alive: an ambient wasteland ticks around the operator (broadcasts, day/night, weather, radio), the boot screen greets them by their own campaign, places sound different, and their deeds echo back as deterministic news — all terminal-side, all offline-safe, writing nothing durable. The two monoliths are decomposed into testable seams, the AI-write path has a headless behavioral guard, per-suite parity is enforced, App Check is verified and rules-enforced, and FNV vs FO3 read as **different machines**. The per-vendor stock and FNV DLC quest data are landed, unblocking Step 3. The seam is confirmed FO4-ready (S2-C10). Optional online garnish (INTERCEPT, Remote Transmissions, banter) rides kill-switches over the offline core. --- # STEP 3 — v2.9.0 · Codename **"G.E.C.K."** **Theme: rebuild the gameplay systems into real native tools — and unlock the creation kit.** Step 3 is **mostly overhaul, not greenfield** (Protocol 25 risk): `renderInventory`, `renderWorldMap`, `renderQuests`, `renderCraft`/`doCraft`, `renderSquad`, `recomputeVATS`, the 2D faction matrix, and `state.karma` all already exist in basic form. The work is to turn them into the best versions of themselves — the Manifest & Loadout foundation, the ONE Phosphor-Cartography map, the unified Combat Encounter loop, build planning — and to ship the RobCo hacking minigame that **unlocks a comprehensive dev/debug console** (with a staging bypass so devs never have to play to test). ## S3.1 — DONE-ALREADY / PARTIAL (extend, don't greenfield) | System | Shipped state | Step-3 work | |---|---|---| | Inventory | `renderInventory` (`ui-render.js:64`) + `lookupItemInDb` + carry-weight math (`updateMath`) | **Rebuild** as Manifest & Loadout (the FOUNDATION); keep `state.inventory` schema unchanged. | | Map | fog-of-war (`recordLocationVisit`/`markLocationVisited`) + coordinate guards (Suites 74/114/126) | **Rebuild** as ONE Phosphor-Cartography SVG map; drop Recon Grid. | | VATS | native calc (`recomputeVATS`/`showVATSOverlay`, `ui-core.js:1746`/`1723`) + GA-7/GA-10 (Suite 105) | **Extend**: Targeting-Silhouette SVG front-end + AP-across-turns + auto-DT from bestiary. Math core stays. | | THREAT / LOOT | native (Suites 107/110) | **Reuse** inside the unified Combat Encounter loop. | | Crafting | `renderCraft`/`doCraft` + recipe registry (Suite 83) | **Extend**: workbench stations UI on the Manifest base. | | Faction rep | 2D matrix (`getFactionStanding`/`adjustFaction`, Suites 77/88) | **Extend**: Consequence Engine (mechanical) + ambient layer. | | Quests | `renderQuests` + `dlc` schema | **Extend**: overhaul + consume Step-2 DLC quest data (S2-D2). | | Squad | `renderSquad` + `state.squad` | **Extend**: companion management (AI Companion Memory → Step 4). | | Karma | `state.karma` field + editable input | **Add** the timeline/cause-log (greenfield on the existing field). | | Radio | absorbed into UPLINK (Step-2 U3) | **STRIP** as a standalone item — no separate v2.9.0 radio. | **Stripped by consolidation:** standalone Radio (→ UPLINK), Recon Grid map (dropped), separate loadout/aid managers (→ Manifest & Loadout, C6), separate VATS-resolver/THREAT/combat-log/LOOT (→ one Combat Encounter loop, C5). ## S3.2 — Build order (with dependency reasons) ### TIER 0 — Cross-cutting foundation (codify FIRST) 1. **S3-F0 — "Native input path required" protocol.** **Why first:** every gameplay data system must have a native, no-AI way to enter/edit its data; codify once so it isn't re-litigated per feature. Process/protocol, no code. 2. **S3-F1 — FOUNDATION: Inventory "Manifest & Loadout" overhaul.** **Why the tallest pole:** crafting, loadout, and aid all sit on it (consolidation C6). Sort/search/inspect-drawer/loadout-header + **list virtualization** + per-row equip. **Keep `state.inventory` schema unchanged** (no Protocol 4 surface). Suites 40/61/75 stay green. ### TIER 1 — The ONE map (owner decision #3) 3. **S3-M1 — Geographic per-game SVG map** via Phosphor Cartography inline-SVG (low-risk first cut). Consolidates the three competing map designs; drop Recon Grid. Reuse the shipped fog-of-war + coordinate guards. Retire/repurpose `state.mapView` (migration note, Protocol 25). **Depends on:** shipped map helpers. 4. **S3-M2 — World-Map Exploration overhaul** = the data/journal layer ON TOP of S3-M1. Travel-time model + encounter journal; **on-arrival encounter roll consumes the Step-2 U0 seeded-roll engine** (C1). Encounters that mutate state apply in the **map layer** (allowed to write), never in `ambient.js`. **Depends on:** S3-M1 + S2-U0. ### TIER 2 — Unified Combat Encounter loop (consolidation C5) One loop: **assess (THREAT) → queue shots (VATS) → log kill (combat log) → loot (LOOT).** 5. **S3-CE1 — VATS "Targeting Silhouette"** — SVG body-part picker + AP-across-turns budget bar + weapon picker + auto-DT from bestiary (manual fallback, Protocol 3). Reuse `recomputeVATS` math (Suites 104/105 stay green). No new persisted state. **Depends on:** shipped VATS. 6. **S3-CE2 — Combat log / kill feed** — manual + registry autocomplete; native input (S3-F0). **Depends on:** S3-F0. 7. **S3-CE3 — Wire the loop** — THREAT → Silhouette → combat log → LOOT as one encounter surface, sharing `GAME_DEFS[ctx].vats` coefficients + the U0 roll engine for drops. **Depends on:** CE1/CE2 + shipped THREAT/LOOT + S2-U0. ### TIER 3 — Character build systems (share the Manifest base) 8. **S3-B1 — Build Planner / Respec** (SPECIAL + skills + perks). Greenfield on shipped data. 9. **S3-B2 — Perk planner / build-up timeline** — extends B1. 10. **S3-B3 — Build-code sharing via Web Share** — encode a build as a shareable/importable versioned string, reusing shipped WU-F3 (Eject Holotape) + clipboard fallback. **Depends on:** B1 + WU-F3. ### TIER 4 — Faction & progression 11. **S3-FC0 — Faction Consequence: ambient layer** (IMMERSION #9) — the sensory half (UPLINK pushes friendly/hostile signals on threshold crossings; map ping). Can **precede** the mechanical engine. **Depends on:** Step-2 UPLINK push + rep matrix. 12. **S3-FC1 — Faction Consequence Engine (mechanical)** — rep thresholds → vendor lock/unlock (**needs S2-D1 VENDOR_STOCK**), bounty hunters, map markers (needs S3-M1). **Depends on:** S2-D1 + S3-M1. 13. **S3-KR1 — Karma & rep timeline** — native cause-logging, NO AI; extends `state.karma`. **Depends on:** S3-F0. ### TIER 5 — Quest & crafting (need the Step-2 data lane + Manifest base) 14. **S3-Q1 — Quest Tracker overhaul** — extend `renderQuests`; **consumes S2-D2 DLC quest lines.** **Depends on:** S2-D2. 15. **S3-CR1 — Crafting & Workbench Stations** — extend `renderCraft`/`doCraft` on the Manifest base; recipe data shipped (Suite 83). **Depends on:** S3-F1. ### TIER 6 — Companion & dialogue 16. **S3-CO1 — Companion / Squad Management** — extend `renderSquad` + `state.squad` (AI Companion Memory → Step 4). **Depends on:** S3-F0. 17. **S3-DL1 — Dialogue / speech-check helper** — native + optional AI; native input path required. **Depends on:** S3-F0. ### TIER 7 — Immersion polish (need earlier layers) 18. **S3-IM1 — Overseer's Incident Log** (IMMERSION #5) — **MERGE with the existing session-stats / Overseer telemetry (WU-F7/F10), NOT a parallel system.** Device-local milestone ring + purge control. **Depends on:** the S2-I3 milestone-detection layer. 19. **S3-IM2 — Emergent CRT "Condition"** (IMMERSION #7) — cumulative-condition `ambient-*` layer; **toggleable OFF; dev-testable via the debug console.** Highest gimmick risk — ship after the UPLINK arbiter is proven. **Depends on:** Step-2 UPLINK arbiter + THEMES. ### TIER 8 — Hacking minigame + DEV/DEBUG PANEL (owner decision #7 — the big one) 20. **S3-HK1 — RobCo Hacking Minigame as a locked subsystem** (IMMERSION #13) — self-contained DOM module (garbage grid + candidate words + likeness scoring + keyboard nav). Surfaced by rare UPLINK/INTERCEPT "ENCRYPTED PARTITION" events. Success unlocks flavor **and** the debug panel; failure → diegetic taunt (AI-C static, optional AI-augment). 21. **S3-HK2 — DEV/DEBUG PANEL (MUST BE BUILT)** — the comprehensive in-terminal debug/test console. **Depends on:** HK1 for the prod unlock; usable directly in staging. ## S3.3 — Per-feature detail (the code-grounded core) **S3-F1 — Manifest & Loadout (the foundation).** - **Exists today:** `renderInventory()` (`ui-render.js:64`) — a flat, insertion-order list with one active category filter (`_invFilter`); `[USE]` + type tag + `qty×Name (wgt·val)` + delete rows; DB auto-fill via `lookupItemInDb`; carry weight shown only in BIO-METRICS (`updateMath`, `maxWeight = 150 + s*10`). No sort, no search, no in-panel total, no inspect, no per-row equip. - **Becomes:** a real item-manifest — per-row inspect drawer (full DB stats/effect), sort (name/weight/value/type), in-list search, a live loadout header (total weight vs `maxWeight`, value, count) *in the inventory panel*, and per-row equip/unequip. Plus **list virtualization** (the only unbounded list). - **In-stack:** `map().join('')` + single `innerHTML` assignment (never `+=` in a loop); all text through `escapeHtml()`; DB lookups memoized per render; gated by the shipped dirty-check (`_isDirty`, Suite 91). - **State/data — the load-bearing rule:** sort/search are **module-level view-state** (`_invSort`/`_invQuery`), exactly like `_invFilter` — **`state.inventory` schema stays unchanged.** Derive everything from the DB at render time. **No Protocol 4 surface, no sanitizer change, no cloud round-trip risk** (Suite 46 untouched). Resist the temptation to enrich the state model. - **Hard constraints:** Suites 40/61/75 stay green; DB-miss items degrade gracefully (name/qty/wgt/val only, never blank); Protocol 10 render-check at 360/412/desktop; **Protocol 1 cache bump.** **S3-M1 — Phosphor Cartography (the ONE map).** - **Exists today:** `renderWorldMap()` (`ui-render.js:1225`) — an HTML CSS-grid of boxed cells (6×6, default cropped to 4×4 via `state.mapView`), `[CURRENT]`/`[VISITED]`/`[UNKNOWN]` tags, name-matching heuristic (`scoreZoneForLoc`), a `_mapAbbrev` maintenance table, generic `[?]` collectible pip. Fog-of-war via `recordLocationVisit` → `state.locationHistory`. - **Becomes:** one inline-SVG phosphor minimap — glyph nodes at each zone's `gridRow`/`gridCol`, a radar sweep, route lines between discovered zones, a blinking `[YOU]` reticle, keyboard arrow-key nav, typed collectible glyphs. Same data, same fog-of-war single-source; only the presentation layer is rebuilt as vectors. - **In-stack:** SVG string via `map().join('')`, one assignment; sweep is a CSS `@keyframes` gated by `prefers-reduced-motion`; per-game color from `THEMES` (FO3 green3 vs FNV `#14fdce`); deletes `_mapAbbrev`, softens `scoreZoneForLoc`. - **State/data:** retire/repurpose `state.mapView` (an SVG shows all nodes at once) — trivial migration (ignore the stale value) but a Protocol-25 muscle-memory change; needs a migration note. - **Hard constraints:** Suites 74/114/126/68/79 stay green + new SVG-contract guards; Protocol 10 render-check; **Protocol 1 cache bump.** **S3-CE1 — Targeting Silhouette VATS.** - **Exists today:** `recomputeVATS()` (`ui-core.js:1746`) prints a pre-wrapped ASCII table into `#sysModal`; manual DT entry (`#vatsTargetDT`); only the equipped weapon feeds the calc; coefficients from `GAME_DEFS[ctx].vats` (regions/apBase/apPerAgility/critBonus/hit-clamp — GA-7, no hardcoded table). - **Becomes:** an inline-SVG humanoid with tappable region hot-zones (`data-region` keyed to `GAME_DEFS[ctx].vats.regions`), a draining AP budget bar for a queued shot sequence, a weapon picker over the player's carried weapons (`lookupWeaponStats`), and enemy DT auto-filled from `lookupBestiaryEntry` (manual fallback). - **In-stack:** `recomputeVATS` stays the math core (Protocol 22, Suites 104/105 stay green); the AP queue is **overlay-local scratch state — no new persisted `state` field, no Protocol 4 surface**; SVG built once; reduced-motion-gated animation. - **Hard constraints:** bestiary-miss falls back cleanly (Protocol 3, never invent a DT); 360px render-check (taller panel); **Protocol 1 cache bump.** **S3-HK1/HK2 — Hacking minigame + dev/debug console (the big one).** - **Exists today:** nothing. - **Becomes:** (HK1) a self-contained hacking DOM module (garbage grid, candidate words, likeness scoring, keyboard nav) surfaced by rare "ENCRYPTED PARTITION" UPLINK/INTERCEPT events; success unlocks flavor + the debug panel, failure → diegetic taunt. (HK2) a comprehensive debug/test console: **force-fire every ambient/UPLINK feature** (the dev-testability affordance from owner #2 — it subsumes the minimal Step-2 U1 force-fire hook), inspect+edit state, dump save/version/checksum, toggle every optic/audio/effect, simulate rad/faction/karma thresholds + CRT condition, force boot variants, view telemetry/Overseer log. - **In-stack, staging bypass:** in staging (the Protocol-43 build-injected staging flag) the console is reachable **directly**, without playing the minigame, so devs can test Step-2/3 ambient features every time; **prod requires the hack** (OPEN Q6 — confirm this model). - **Hard constraints:** **all debug writes are additive/confirm-gated (Protocol 34) — the console can't corrupt saves;** unlocks are additive device-prefs/flavor, never campaign-state writes; reduced-motion + keyboard-nav + 360/412 render. ## S3.4 — Hard rules / invariants for v2.9.0 1. **Overhaul discipline (Protocol 25).** Every rebuild (map, inventory, quests, squad, VATS) keeps the existing workflow as a fallback/zoom view and passes its existing suites. Muscle memory is preserved. 2. **Manifest & Loadout keeps `state.inventory` unchanged** — derive from the DB at render time; view-state only; no Protocol 4 surface; Suite 46 round-trip untouched. This is the single biggest data-safety guarantee of the version. 3. **Native input path for every gameplay data system** (S3-F0) — the user can always enter/edit their own campaign data offline, no AI required (reinforces Protocol 24). 4. **One seeded-roll engine, many consumers** — map encounters (S3-M2) and combat loot (S3-CE3) consume the Step-2 U0 engine; encounters that mutate state apply in the **map/combat layer** (allowed to write), never in `ambient.js` (the no-write invariant holds). 5. **The debug console is additive/confirm-gated only** (Protocol 34) and prod-gated behind the hack; staging bypass for dev testability. It can never corrupt a save. 6. **Emergent CRT Condition ships last, default-off, dev-testable** — highest gimmick risk; must never imply a rad/weight state the user doesn't have (UPLINK §4 arbitration). 7. **Every served-file change bumps `CACHE_NAME`; full gate + parity + docs sync on every `dev` commit** (Protocol 1/2/2a/43). Every bug fix ships a regression test in the same commit (Protocol 13). ## S3.5 — End state The gameplay systems are real native tools: a searchable, sortable, inspectable Manifest & Loadout that is also the loadout + aid manager; ONE spatial phosphor map with a radar sweep and keyboard nav; a coherent Combat Encounter loop (THREAT → Silhouette VATS → combat log → LOOT) sharing one coefficient set and one roll engine; a Build Planner with shareable build codes; a Faction Consequence engine (mechanical + ambient); an overhauled DLC-complete Quest Tracker; workbench crafting; companion management; and a karma/rep timeline — all with native input paths, all preserving the existing workflows. The RobCo hacking minigame gates a comprehensive dev/debug console (staging-bypassable) that can force-fire every ambient feature and inspect/simulate state without ever corrupting a save. --- # STEP 4 — v3.0.0 · Codename **"COMMONWEALTH"** **Theme: prove the N-game seam — Fallout 4 as a (near) data-only third game — plus the moved-in heavies.** The 2.7.0 agnostic seam (Protocol 38, Suite 89, the `GAME_FILES` boot manifest) plus the A9 refactor mean FO4 is a new `GAME_DEFS` block + two data files + one manifest line — **no feature-code search-and-replace.** The one genuine architecture stretch is FO4's skill-less model. This version also lands the heavies parked out of Steps 2/3: the Streaming Two-Phase Narrator and Companion Memory. **v3.0.0 is a MAJOR bump and requires explicit owner confirmation (Protocol 2).** ## S4.1 — DONE-ALREADY (what makes FO4 near data-only) - The **game-agnostic seam** (Protocol 38 + Suite 89 + the `GAME_FILES` boot manifest) + the A9 refactor (GA-1…4/6/7/10). FO4 = a new `GAME_DEFS` block + two data files + one manifest line. - **FO3 already added as the 2nd game** — proves the two-game → N-game path end to end. - **Per-game theming foundation** (`THEMES` + `GAME_DEFS[ctx].theme`, data-driven) — FO4 theme = one `THEMES` row + one `GAME_DEFS.FO4.theme` entry. - **The 6 native calculators** read per-game `databaseCSVs` + registry via `lookupItemInDb()` — they extend to an FO4 data set with zero logic change. **Step-2 prerequisites that must be verified before Step 4 starts:** S2-F2 (directive decomposed → FO4 injects via `GAME_DEFS[ctx].ai`), S2-E1 (per-game EXPERIENCE seam), S2-C10 (new-game-readiness audit). **The "adding a game is easy, not zero-code" principle applies:** the data files, registry, and CSVs are expected labor — what must never recur is feature-code literal edits. ## S4.2 — Build order (with dependency reasons) ### TIER 0 — Prereq verification 1. **S4-P1 — Confirm S2-F2 + S2-E1 + S2-C10 landed.** **Why first:** any residual two-game literal is a Step-4 blocker. ### TIER 1 — FO4 data lane (fully parallel, data-only) 2. **S4-D1 ∥ — `db_fo4.js`** — WEAPONS/ARMOR/AMMO/CHEMS/MISC/QUEST_ITEMS CSVs (fallout.wiki, Protocol 3). 3. **S4-D2 ∥ — `reg_fo4.js`** — quests / items / perks / locations / companions / collectibles. 4. **S4-D3 ∥ — `GAME_DEFS.FO4` entry** — theme, seedInventory, calendar epoch, combatSkills, vats, barter, `ambient` bank. 5. **S4-D4 ∥ — FO4 no-data warning template** (WU-E2-style) for features FO4 lacks (e.g. skill books). ### TIER 2 — FO4 model specifics (depend on the data lane) 6. **S4-M1 — FO4 skill-less model.** **The one genuine architecture stretch:** FO4 has no skills (perk-chart based); the agnostic seam must handle `getSkillKeys() === []` cleanly across the skills panel, VATS combat-skill resolution, and `syncStateFromDom`. Front-load a spike that proves every `getSkillKeys()` consumer degrades. **Depends on:** S4-D3. 7. **S4-M2 — Settlements system** (FO4-specific panel). 8. **S4-M3 — Perk chart** (SPECIAL-perk grid, replaces skill books). 9. **S4-M4 — Legendary effects.** 10. **S4-M5 — FO4 theme + boot wiring** (`GAME_FILES.FO4` manifest line + one `THEMES` row). ### TIER 3 — Moved-in heavies (owner decision #4) 11. **S4-H1 — Streaming Two-Phase Narrator** (FEATURE_REMAKES MEGA). Split the single Tri-Node JSON call into (A) streamed narrative + (B) strict-validated state/modal delta. **New persisted context-summary state field (Protocol 4).** **Keep the single-JSON path as fallback.** **HIGH risk** — AI-contract change (Protocol 14 test same commit); real-device mobile verify of the stream reader. 12. **S4-H2 — Companion Memory** (AI-K). Persistent operator-linked Firestore; needs schema + eviction policy + `PRIVACY.md` update + App Check. Extends S3-CO1 squad. **HIGH** — the only new operator-linked persistent cloud system; AI_SLATE flags it "heaviest, last." 13. **S4-H3 — Web Workers offload** — **build ONLY if a concrete workload exists** (e.g. FO4's larger data joins or the streaming assembly). Re-justify before scheduling (OPEN Q5). 14. **S4-H4 — DLC map zones** (FNV Sierra Madre/Zion/Big MT/Divide; FO4 DLC) — a zone-grid extension beyond the 6×6 Mojave, and a grid-design decision, not a data add. ## S4.3 — Per-feature detail (the code-grounded core) **S4-M1 — the skill-less model (the only real risk).** - **Exists today:** `getSkillKeys()` (`state.js`) always returns a non-empty array for FNV (13 skills) / FO3; `renderSkills`, VATS combat-skill resolution (`GAME_DEFS[ctx].combatSkills`), and `syncStateFromDom` all assume skills exist. - **Becomes:** FO4 sets `getSkillKeys() === []`; the skills panel hides/degrades, VATS resolves combat via the perk model, `syncStateFromDom` no-ops on skills. - **In-stack:** data-driven degradation — no game literal; the spike verifies every consumer. - **Hard constraints:** Suite coverage for the empty-skill path; Protocol 38 (no `ctx === 'FO4'` branches). **S4-H1 — Streaming Two-Phase Narrator.** - **Exists today:** `transmitMessage()` (`api.js:1308`) is request → wait → parse whole Tri-Node JSON → typewriter-replay; the model is locked to `responseMimeType:'application/json'`, so nothing prints until the full blob validates (`_validateTriNode`, `api.js:219`). Full `chatHistory` (cap 200) resent every request. - **Becomes:** Phase A streams plain narrative token-by-token into the existing `getTypewriterSpeed` typewriter (reuse, Protocol 22); Phase B is a strict `responseMimeType:'application/json'` call returning only `{state, modal}`, run through the unchanged `_validateTriNode` + `autoImportState` before persistence. Plus a bounded summarized context window, a retry HUD, and a labelled degraded offline mode. - **State/data:** ONE new persisted context-summary field — the **full Protocol 4 surface** (default + migrate in `state.js`, import in `autoImportState`, sanitize entry, cloud round-trip serialized-whole — Suite 46). - **Hard constraints:** **Protocol 24 preserved** (state never lands unvalidated — only prose streams); **Protocol 14 AI-contract test in the same commit**; **keep the single-JSON path as the fallback** (a streaming failure can never brick the comm-link); kill-switch `aiChat` (Protocol 32/33); CSP unchanged (same Gemini origin, Suite 55 — verify); **real-device mobile verification** of the stream reader. **S4-H2 — Companion Memory.** - **Becomes:** a persistent operator-linked Firestore store for companion memory, extending S3-CO1. - **Hard constraints:** schema + eviction policy + `PRIVACY.md` update + App Check; additive writes only (Protocol 34); kill-switch + graceful fallback (Protocol 32/33); the only new operator-linked persistent cloud system — build it last. ## S4.4 — Hard rules / invariants for v3.0.0 1. **FO4 is data, not feature-code.** A new game = a `GAME_DEFS.FO4` block + `db_fo4.js` + `reg_fo4.js` + one `GAME_FILES` manifest line + one `THEMES` row. **No `ctx === 'FO4'` literal may appear in feature code** (Suite 89 fails the build). Content is expected labor; search-and-replace is banned. 2. **The skill-less model degrades cleanly** — every `getSkillKeys()` consumer handles `[]`; proven by a front-loaded spike before M2–M5. 3. **The heavies keep their fallbacks + kill-switches.** Streaming keeps the single-JSON path; Companion Memory and any networked heavy have a kill-switch + graceful offline fallback (Protocol 32/33) and additive-only cloud writes (Protocol 34). 4. **AI-contract safety** — H1 changes the contract shape → Protocol 14 test in the same commit; Protocol 24 (validated, explicitly field-mapped) is preserved. 5. **MAJOR bump requires explicit owner confirmation** (Protocol 2); the full gate + parity + docs sync + real-device auth/mobile verification (Protocol 29, if any auth surface is touched) apply. ## S4.5 — End state Fallout 4 runs as a third game dropped in almost entirely as data — a `GAME_DEFS.FO4` block, two data files, a manifest line, a theme row — with the skill-less model handled cleanly by the agnostic seam and no feature-code literals added. The moved-in heavies land behind fallbacks and kill-switches: a streaming two-phase narrator that turns dead air into live teletype while still validating all state, and operator-linked Companion Memory. The N-game seam is proven; a fourth game would follow the same data-only path. --- # CROSS-STEP: consolidations, invariants, open questions ## The "one engine, many consumers" spine (do not fork these) - **WASTELAND UPLINK is the substrate** for Radio + map-encounters + INTERCEPT + Remote Transmissions (owner #1, day/night reinstated). Radio and map-encounter items are struck from Step 3 as standalone — they consume the Step-2 engine. - **One seeded-roll engine (S2-U0)** feeds UPLINK broadcasts, Step-3 map encounters (S3-M2), and combat loot drops (S3-CE3). - **One inventory overhaul (S3-F1)** = loadout + aid + crafting base. - **One Combat Encounter loop (S3-CE1–3)** = VATS + THREAT + combat-log + LOOT. - **App Check done once (S2-F1)** gates all networked residue across Steps 2–4. - **Overseer Incident Log MERGES with existing telemetry (S3-IM1)** — never a parallel logger. ## The serial-cluster hazards (serialize `api.js` and `ui-core.js` edits) - **`api.js` cluster (three-way-merge hazard):** `S2-F2 (directive decomp + GA-5) → U5 (INTERCEPT) → S2-A5 (OVERSEER) → S2-A7 (banter) → S4-H1 (streaming)`. Serialize; full gate after each merge. - **`ui-core.js` boot cluster:** `S2-F3 (onload decomp) → S2-I1 (MOTD) → S2-I5 (attract) → S2-I6 (standby watch) → S2-I8 (onboarding)`. All attach to the seams F3 creates. Serialize. - **`state.js` GAME_DEFS additive sequence:** `S2-F2 (ai block) → S2-E1 (voice/ambient block) → S2-U1 (ambient bank consumed) → S4-D3 (FO4 block)`. - **The only clean parallel lane is `reg_*/db_*` data** (S2-D1/D2, S4-D1/D2). Everything else funnels through both test runners + count + docs + `sw.js`. ## Governing principle (owner) **Adding a new game must be easy and non-breaking — not dogmatically zero-code.** The data files, registry entries, and CSVs are expected labor. What the architecture guarantees is that no feature-code search-and-replace of game literals is ever required (Protocol 38 / Suite 89). A new game is a `GAME_DEFS` block + data files + one manifest line + one theme row. ## Open questions for the owner (carried from ROADMAP_REBASELINE, updated for day/night reinstated) 1. **OPEN Q3 — Remote Transmissions data model (S2-R1).** The only genuinely undesigned Step-2 item. Needs an owner-approved Firestore doc shape, read-only public rule, cache/offline behavior, and render surface **before** it can be built. Recommend a thin spec pass before scheduling. 2. **OPEN Q4 — `APP_VERSION` batching.** Confirm the many additive Step-2 features accumulate under one 2.8.0 bump (recommended, per the changelog-batching memo) rather than shipping as incremental 2.7.x patches. **v3.0.0 (MAJOR, FO4) requires explicit confirmation.** 3. **OPEN Q5 — Web Workers (S4-H3).** No workload currently justifies it. Confirm: drop entirely, or hold as conditional-on-a-workload. 4. **OPEN Q6 — Debug-panel unlock model (S3-HK2).** Confirm the staging bypass (dev opens the console directly via the Protocol-43 staging flag; prod requires the hack). Without a bypass, testing Step-2 ambient features in dev would require playing the minigame each time. *(Note: the earlier OPEN Q1 "rad-storm weather without day/night" and OPEN Q2 "calendar without in-game time" are **resolved** by the owner's reinstatement of day/night — weather, Dusk/Dawn, and the Wasteland Calendar are all back in Step-2 scope.)* ## What changed vs the parked (v2.6.0-era) plans - **Struck as SHIPPED:** all 6 native calculators, all 9 device caps + F10/F11, GT-1/2/3 theming, the agnostic seam, dirty-diff perf, a11y baseline, App Check client wiring (now also key/token/guard-corrected in the last 3 commits), WU-B5 cloud-pull VM test. - **Struck by consolidation:** standalone Radio, Recon Grid map, separate loadout/aid managers, separate VATS-resolver/combat-log/THREAT/LOOT panels. - **REINSTATED (this doc):** Day/Night cycle, rad-storm weather, Dusk/Dawn (#8), Wasteland Calendar (#1) — all back in Step-2 scope per the owner's reversal. - **Moved to Step 4:** Streaming Narrator, Companion Memory, Web Workers, DLC map zones. - **Moved to Step 3:** hacking minigame (+ its debug-panel unlock), list virtualization (into Manifest & Loadout). - **New foundations inserted first (owner #5):** getSystemDirective decomposition, window.onload decomposition, autoImportState VM test, per-suite parity gate, App Check verification, the data lane. --- *END — analysis only. Nothing implemented, committed, or pushed. Baseline `dev` @ `90ff0f4` untouched; parked plans untouched; `planning/` is gitignored. Awaiting owner review + explicit approval before anything folds into a MASTER_PLAN.*
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).