diff --git a/Docs/Vault/06_Roadmap/Lantern_Operator_Questions.md b/Docs/Vault/06_Roadmap/Lantern_Operator_Questions.md new file mode 100644 index 000000000..03260a73b --- /dev/null +++ b/Docs/Vault/06_Roadmap/Lantern_Operator_Questions.md @@ -0,0 +1,61 @@ +--- +title: LANTERN — Operator Questions (autonomous-run parking lot) +date: 2026-07-13 +tags: [roadmap, lantern, operator-questions, forks] +status: awaiting-operator +permalink: gamevault/06-roadmap/lantern-operator-questions +--- + +# LANTERN — Operator Questions + +> Parking lot for decisions I couldn't make autonomously during the 2026-07-13 autonomous build run (operator +> stepped away: "build everything you can, don't stop, create a doc of operator questions as needed"). Each +> item has my **recommendation** so you can answer in one pass. Nothing here blocked me from continuing — I +> took the recommended default in the design docs and flagged it, so answering may just confirm or redirect. +> +> **Convention:** ✅ = I proceeded on the recommendation (design assumes it; easy to change). ⛔ = I did NOT +> proceed; genuinely blocked pending your call. + +## Process / authorization + +1. **⛔ New netcode CODE implementation.** All LANTERN slice code is greenfield and netcode-touching (new + ghosts / prediction / relevancy / RPCs), so it needs (a) plan-approval per the /dots-dev gate and (b) a + **focused** Unity editor (an unfocused editor throttles MCP + breaks Burst — you're away). I did **not** + write any Unity code this run. **Recommendation:** on return, focus Unity, then greenlight implementation + phase-by-phase from the build specs I wrote. *All design/build-spec scaffolding is ready so code can move + fast.* +2. **⛔ Additional multi-agent design-review Workflows.** You explicitly greenlit the world-model review. Each + remaining ★review-first slice (Phase 1's light-relevancy prototype; Phase 2 world code; hazards; etc.) also + wants one before coding. I did **not** fire more heavy Workflows unprompted. **Recommendation:** greenlight + "run the ★ review before each netcode slice" as a standing autonomous authorization, or I run them one-by-one + on your go. +3. **✅/⛔ Blender A0 art execution.** Blender MCP is live. I wrote the art-pipeline recipes + the A0 material + spec (docs). Whether I should *autonomously attempt* the in-engine style-proof scene (needs your eyes to + judge — screenshots hide material bugs) vs. wait: I lean **wait for your eyes** on the gate judgment, but I + can build the palette atlas + a first placeholder asset as a starting point. **Recommendation:** let me + stage the palette atlas + one placeholder prop/creature/suit for the scene, but you judge the gate. + +## Phase 1 — combat gym (design forks in [[Lantern_Phase1_Combat_Gym_Build_Spec]]) + +4. **✅ Suit-frame kit specifics.** I specced the **Bathynaut** (anchor-and-crash melee) and **Harpooner** + (line-and-iron skillshots) chassis verbs + a 4-socket kit. The exact Spark list (first 4–5) and per-frame + movement feel are recommendations — see the build spec's fork table. Confirm or swap. +5. **✅ Manual-aim vs the current soft auto-target.** Design cuts soft auto-target for SoD-grade manual aim + (per Identity). Confirm you want the auto-target fully gone in the gym (I kept the reticle plumbing). + +## Economy / naming + +6. **✅ Currency re-mean mapping.** Ore/Aether/Biomass/Charge → Flame/Lumen/Gloam/Loudness/Salvage/Chum/Tallow. + Proposed mapping in the currency spec. Confirm the byte-id assignments before any save-schema work. +7. **(deferred) Shipping title.** "LANTERN" is the internal codename; a marketing naming pass is deferred + (per [[Identity_Lantern]]). No action needed now. + +## Answered this session (for the record) + +- Co-op pocket occupancy → **co-located, one active pocket** (2026-07-13). +- Light-as-information scope → **party light-union, Wicks always visible** (2026-07-13). +- Run the world-model adversarial review → **yes, full review** (2026-07-13). + +## Related + +- [[Roadmap_Lantern_Slice]] · [[Lantern_World_Model_Design_Proposal]] · [[DR-048_Lantern_Adoption_Full_Pivot]] diff --git a/Docs/Vault/06_Roadmap/Lantern_Phase1_Combat_Gym_Build_Spec.md b/Docs/Vault/06_Roadmap/Lantern_Phase1_Combat_Gym_Build_Spec.md new file mode 100644 index 000000000..a9bd93c4e --- /dev/null +++ b/Docs/Vault/06_Roadmap/Lantern_Phase1_Combat_Gym_Build_Spec.md @@ -0,0 +1,144 @@ +--- +title: LANTERN — Phase 1 Combat Gym (design/build spec, pre-review) +date: 2026-07-13 +tags: [roadmap, lantern, combat, phase-1, build-spec, netcode] +status: design-pre-review +permalink: gamevault/06-roadmap/lantern-phase1-combat-gym-build-spec +--- + +# LANTERN — Phase 1: Combat Gym (design/build spec) + +> Phase 1 of [[Roadmap_Lantern_Slice]]: *the primary verb first — two frames that feel like Shape of Dreams. +> No world, no lanterns — a gym.* This is a **design spec written from ground-truth code** (a combat/ability/ +> boon salvage pass), NOT a build contract: the 4-socket kit and light-relevancy prototype are **netcode- +> touching** (new ghost fields / input surface) so they need the ★ design review + plan-approval + a focused +> editor before any code. Phase 1 has **no world** and is **not** blocked by the Phase-0.3 world-model review. +> +> **Gate:** the gym is fun with two players for 15 minutes on kit alone; the relevancy-light prototype verifies +> server-side (gamma test: nothing to see outside your light). + +## Salvage verdict (what Phase 1 stands on) + +The combat substrate is the project's strongest asset and it ports almost whole: + +- **KEEP as-is:** the client-only feel layer — `CombatFeedbackSystem` (edge-detects replicated `Health`/tick + fields, never touches sim), `EnemyDangerTelegraphSystem` (per-kind colour/voice/shape/light), `AimReticleSystem`, + `DynamicLightSystem`. The dash — `DashSystem` (deterministic re-sim from the replicated `PlayerInput.Dash` + InputEvent; i-frame window + sharpness-override blink) is exactly the SoD dash. +- **KEEP the pipeline, REWORK the grammar:** `AbilityFireSystem` (predicted-spawn, `IsFirstTimeFullyPredictingTick` + gate, SpawnId classification, `AutoTarget` server/gamepad branch), the ability blob (`AbilityDatabase` / + `AbilityDefBlob` / `AbilityArchetype`), `StatModifier`→`StatRecomputeSystem`→`EffectiveAbilityStats` (every- + tick fold), `MeleeComboSystem` (predicted absolute-write `Step`). +- **REWORK into the socket kit:** the single `AbilityRef{[GhostField] byte Id}` → a **4-wide socket buffer** + (model on `EquipmentSlot`: `[InternalBufferCapacity(4)]`, index-is-slot, `SendToOwnerType.All`, server-sole- + writer). One `AbilityCooldown` → a 4-wide cooldown. One `PlayerInput.Fire` → **4 socket inputs**. +- **CUT (as the target):** soft auto-target as the default — SoD is manual aim. Keep the plumbing; disable + per-socket via `AutoTargetRange = 0` in the ability def (a clean existing off-switch), leaving a small + optional in-arc assist only where a specific Spark wants it. + +## The two suit-frames (chassis = class = silhouette = verb) + +Frames extend the proven class chassis (`ClassTraits` seeds 4 permanent trait `StatModifier`s per class; the +`AbilityFor(classId)` mapping). Two frames ship: + +### Bathynaut — anchor-and-crash melee (Warrior lineage) +- **Chassis verb:** a weighted tide-breaker. Reuses `MeleeComboSystem` (combo `Step`, finisher scaling, + server-only cone cleave) as the always-available primary. Movement feel: high mass, short committed lunges, + a hard **anchor** (a planted stance that trades mobility for a crash payoff). Slow turn, high poise. +- **Salvage:** Warrior seeds (`+MaxHealth`, `-MoveSpeed`, `+MeleeDamage`, `+MeleeRange`) reskin directly. + +### Harpooner — line-and-iron skillshots incl. reel/drag (Ranger lineage) +- **Chassis verb:** manual-aim line weapons. Reuses the predicted projectile path. The signature verb is + **reel/drag**: a fired iron that, on hit, **pulls** (the existing `KnockToPull` / `ProjectileEffectState` + pull hook, promoted from a mutation to a native Harpooner mechanic) — either pulling the target to you or + you to the target (design fork, see questions doc). Movement feel: light, kite-friendly, real windups. +- **Salvage:** Ranger seeds (`+MoveSpeed`, `-MaxHealth`, `+Range`, `+AutoTargetRange`) reskin; the reel reuses + the pull flag + the chain/retarget machinery in `ProjectileDamageSystem`. + +## The 4-socket skillshot kit (the netcode core — ★ review before code) + +The single-ability model becomes a **4-socket kit** (4 active + the movement/dash). Design: + +- **`AbilitySocket` buffer** on the player: `[GhostComponent(SendToOwnerType.All)] [InternalBufferCapacity(4)]`, + one row per socket = `byte SparkId` (0 = empty). Server is the sole writer (socketing happens in the + gym/hub, not predicted). Mirrors `EquipmentSlot` exactly — a proven pattern. +- **`SocketCooldown` buffer** (4-wide, `[GhostField]` `NextFireTick` per socket, `SendToOwner`). Replaces the + single `AbilityCooldown`. Each routed through `TickUtil.NonZero`. +- **Input:** add **4 socket InputEvents** to `PlayerInput` (`Socket0..3`) — OR a single `Fire` + a `byte + SocketIndex` (cheaper wire, one event). **Recommendation:** a single `InputEvent Fire` + `byte ActiveSocket` + (the player "readies" a socket; one fire verb) keeps the input surface small and the 7-type query cap + manageable; but 4 discrete buttons feel better for a MOBA bar. *Parked as a fork.* +- **The 7-type query cap is already hit** in `AbilityFireSystem` — the socket rework must move to a + `ComponentLookup`-fed restructure or an `IJobEntity` (per the CLAUDE.md 7-arg rule; hit twice already in the + boon work). This is the single biggest code-restructure of Phase 1. +- **Per-socket archetype dispatch:** the ability blob already dispatches on `AbilityArchetype` + (Projectile/Cone implemented; **Hitscan/Aoe declared-but-unhandled** — Phase 1 implements them for the zone/ + vortex Sparks). Each Spark is an `AbilityDefBlob` row; socketing writes its id into `AbilitySocket`. +- **Manual-aim grammar:** every socket fires along raw `PlayerInput.Aim` (manual). Real windups: add a + `WindupTicks` to the ability def so player abilities telegraph like enemy attacks (reuse the telegraph + vocabulary client-side). Readable hitboxes = the swept-projectile + cone math already in place. + +## First Sparks (4–5 socketables — prove kit variety) + +Each Spark = an `AbilityDefBlob` row + (if projectile/zone) a ghost prefab + an optional `ProjectileEffectState`/ +`BoonEffects`-style hook. Roadmap set: **decoy-wisp, hook/pull, vortex, blink, one zone.** + +| Spark | Archetype | Salvage hook | +|---|---|---| +| **Decoy-wisp** | Aoe/spawn | spawns a server ghost that draws aggro (reuse the enemy target-selection + a new decoy tag; a Wisp-Choir mote asset in A2) | +| **Hook / pull** | Projectile + pull | the `ProjectileEffectState` pull flag + chain retarget — a skillshot grab | +| **Vortex** | Aoe (zone) | implements the declared-but-unhandled `Aoe` archetype: a timed area that pulls/slows (reuse geyser/hazard AoE chassis) | +| **Blink** | movement | a second `DashSystem`-style deterministic teleport (re-sim from an InputEvent; no ghost) | +| **Zone (one)** | Aoe (zone) | a persistent light/damage zone — the `HazardExplosionSystem`/geyser periodic-AoE chassis, player-owned | + +Sparks are **not** mutations — mutations (Phase 4) *warp* Sparks via the `BoonEffects` substrate (3 count bytes ++ flag bits, `SendToOwner`, server-only `ProjectileEffectState` hooks). Phase 1 only needs the sockets + the +Spark defs; the mutation layer bolts on later without re-baking (its hooks already exist). + +## Light-as-information prototype (★ review-first — see [[Lantern_World_Model_Spike]]) + +The gym's version of the slice's hardest idea, proven small: **per-player lamp radius drives netcode relevancy; +entities outside the light aren't replicated.** Per the world-model design ([[Lantern_World_Model_Design_Proposal]]), +this is **hard `GhostRelevancy` (`SetIsIrrelevant`)**, party-light-union, Wicks always visible. In the gym +(no pockets) it degenerates to: a single arena + a per-player/party light-union relevancy pass over the +training dummies/enemies. **This shares the world-model review** — do not code it until that Build Spec lands +(the relevancy thrash/hysteresis + cost questions are the same). The gym is the natural first validation venue +for the relevancy-light (the roadmap's gamma test: "nothing to see"). + +## Underwater feel pass (client-only, zero netcode) + +Reuse the ambient stack (`AmbientMotionSystem` / `AmbientLifeSystem` / `WorldAtmosphereSystem`): buoyant +knockbacks (tune the existing `KnockbackUtil` decay to a slow float), slow-tumbling debris (ambient drift), +murk fog (the per-biome dark palette + fog density knob), hydrophone audio sketch (procedural `AudioClip.Create` +bed, the proven presentation pattern). No sim change — pure feel. + +## Build order (when greenlit; each step ends "compile + read_console clean") + +1. **Socket data model** (no behaviour): `AbilitySocket` + `SocketCooldown` buffers, baked 4-wide; keep the old + `AbilityRef` path working in parallel. *Wire/bake: new player ghost fields → one player-ghost re-bake.* +2. **`AbilityFireSystem` socket restructure** (the 7-type-cap fix via ComponentLookup/IJobEntity); route the + active-socket fire through the blob dispatch + per-socket cooldown. Cone + Projectile first. +3. **Implement the `Aoe`/`Hitscan` archetypes** (vortex/zone Sparks). +4. **The 5 Spark defs** + prefabs (kitbash/greybox; A1 assets replace later) + the Blink second-dash. +5. **Two frames** = the class chassis reskin + per-frame socket defaults + movement-feel tuning knobs. +6. **Manual-aim grammar:** windup telegraphs on player abilities; auto-target off by default (per-socket knob). +7. **Underwater feel pass** (client-only). +8. **Light-relevancy prototype** — ONLY after the world-model Build Spec; validated by the gamma test. + +**Wire/bake churn:** steps 1–2 re-bake the player ghost (socket + cooldown fields); the input-surface change +(socket events / active-socket byte) touches the command struct — re-mean bytes where possible, and the RPC/ +command collection hash must match across peers. Everything else is additive config + client-only. + +## Open forks (parked in [[Lantern_Operator_Questions]]) + +- Socket input model: 4 discrete buttons vs one fire + a readied `ActiveSocket` byte. +- Harpooner reel: pull the target to you, or you to the target (or a per-Spark mix). +- The exact 5 Sparks (confirm the roadmap set or swap). +- Auto-target fully gone vs a small optional in-arc assist per Spark. + +## Related + +- [[Roadmap_Lantern_Slice]] — Phase 1 · [[Lantern_Strip_Mothball_Inventory]] — the salvage verdicts +- [[Lantern_World_Model_Design_Proposal]] / [[Lantern_World_Model_Spike]] — shares the light-relevancy review +- [[DR-047_Phase17_Boon_Overhaul_Mechanic_Changers]] — the `BoonEffects` substrate the mutation layer reuses +- [[Identity_Lantern]] — the combat feel target (SoD-grade skillshots) diff --git a/Docs/Vault/06_Roadmap/Lantern_World_Model_Design_Proposal.md b/Docs/Vault/06_Roadmap/Lantern_World_Model_Design_Proposal.md new file mode 100644 index 000000000..a6d407912 --- /dev/null +++ b/Docs/Vault/06_Roadmap/Lantern_World_Model_Design_Proposal.md @@ -0,0 +1,161 @@ +--- +title: LANTERN — World-Model Design Proposal (pre-review, Phase 0.3) +date: 2026-07-13 +tags: [roadmap, lantern, netcode, world-model, design-proposal, phase-0] +status: proposal-pre-review +permalink: gamevault/06-roadmap/lantern-world-model-design-proposal +--- + +# LANTERN World-Model — Design Proposal (pre-review) + +> Phase 0.3 of [[Roadmap_Lantern_Slice]]. This is the **plan** produced from the [[Lantern_World_Model_Spike]] +> brief, grounded in the actual code (three read-only ground-truth passes + ctx7 on the Netcode relevancy/ +> importance APIs). **It is the INPUT to the ★ adversarial design review, not a build contract** — the review +> hardens it into `World_Model_Build_Spec.md`. No world code until that review passes. +> +> **Operator forks locked this session:** (1) **co-located party — one active pocket at a time**; (2) **party +> light-union relevancy — Wicks always visible to each other, world/enemies outside the party's combined light +> are never sent.** Everything else below is a recommendation for the review to stress-test. + +## The key netcode finding (grounds the whole design) + +- **`GhostRelevancy` (`SetIsIrrelevant`)** is a *hard* cull — an entity outside the set is **never serialized** + to that connection. This is the ONLY mechanism that satisfies the vision's promise: *"gamma-cranking cannot + reveal what was never sent."* So **light-as-information = hard relevancy**, not importance. +- **`GhostImportance`/`GhostDistanceImportance`** is a *soft* dial (far ghosts sent less often, still eventually + sent) with a per-connection focal point (`GhostConnectionPosition`). It composes with relevancy + (`BatchScaleWithRelevancyFunctionPointer`). Use it, if needed, only for **bandwidth within the lit set** — + never as the privacy boundary. +- The current `RegionRelevancySystem` is a brute-force `O(ghosts × connections)` rebuild every tick keyed on a + discrete `RegionTag{byte}` (Base=0 / Expedition=1), `SetIsIrrelevant` mode, no dirty-flag. The + `GhostRelevancy` singleton + `RelevantGhostForConnection{Connection,Ghost}` key + the "shared global state + rides one **untagged** always-relevant ghost" convention are the directly reusable primitives. + +## Model overview (slice scope) + +Because the party is **co-located in one active pocket**, the world model is *architecturally the current +single-active-room + ping-pong two-slot arena*, re-keyed from a 2-value region to a per-pocket key, plus two +new things: **seed-pinning** (persistence) and **light-union relevancy** (the second, finer relevancy layer). + +### 1. The seed model — pinning = freeze the salt + save deltas + +The load-bearing insight from the save ground-truth: **generation is a pure function re-derived from seed; +only player mutation is stored as deltas.** The tide-line drops out of this cleanly: + +- **`WorldSeed`** (persistent, per save) — the shelf's identity. +- **`DescentSalt`** (server-only, monotonic per descent — the `RunEpoch`/`HostSalt` lineage) — salts every + **dark** pocket so unlit geography **re-knots** each descent. +- **`PocketId`** (stable graph-node id — today's `CurrentNodeId`). +- A **dark** pocket's content = `Hash(WorldSeed, PocketId, DescentSalt, subStream)` → re-knots each descent + because `DescentSalt` changes (exactly today's `Hash(RunSeed, CurrentNodeId, constSub)` seeding). +- **Pinning a pocket = FREEZE its salt.** Planting a waypoint-lantern stores `PinnedSalt = current + Hash(WorldSeed, PocketId, DescentSalt)` to the save; thereafter the pocket regenerates **identically** every + descent from the frozen salt, **plus** its structure/harvest **deltas** replayed born-correct. +- "The dark re-knots, the light holds" is therefore: *unpinned → new salt each descent; pinned → frozen salt + + deltas.* Nearly free, and it reuses the exact deterministic-hash + born-correct-delta-replay patterns proven + in `RoomFieldSystem` + `BaseRestoreSystem`. + +### 2. The pocket-graph & muster + +- Reuse `RunMapMath` (pure integer-hash DAG, client-regenerable) as the pocket-graph generator. Rename + run→**descent**, room→**pocket**. The graph per descent is generated from the descent identity. +- **Muster at the deepest lit waypoint:** instead of always entering at node 0, the descent's entry = the + **deepest pinned pocket** (the lit frontier). The pinned prefix is persistent; the dark frontier past it is + fresh. Slice target (roadmap): 3–5 dark pockets per descent past the frontier. + +### 3. Relevancy — two hard-cull layers, both `SetIsIrrelevant` + +- **Layer A — pocket-occupancy scope (coarse):** `PocketTag{ int PocketKey }` replaces `RegionTag` (server- + only, NOT a `[GhostField]`). Party co-located ⇒ exactly one active pocket's ghosts are live; everything + tagged with a non-active pocket key is irrelevant to all. This is *today's region swap*, and the ping-pong + two-slot arena (`RegionMath`, 1000u offset + 500u stride) still gives the clean spawn-next / tear-down-prev + handoff. The **station** is the permanent "home pocket" (today's Base region). +- **Layer B — light-union relevancy (fine, party-union):** within the active pocket, an enemy/world/hazard + ghost is relevant **iff it lies within ANY party member's lamp radius** (the union). Because vision is a + party union, set-membership is **connection-independent** (relevant-to-any ⇒ relevant-to-all party conns) — + compute it once per pocket per tick over party positions, then apply to all party connections. **Wicks + (players) are always relevant to each other** (added to no irrelevant set). Cost: `O(ghosts × partySize)` + with capped ghost counts (~≤40) — trivial; `GhostImportance` held in reserve for bandwidth only. +- **Server interaction guard preserved:** relevancy is *client-visibility only* — server AI/damage still act + on ghosts in the dark (things loom out of the dark; intended). Keep an equivalent server-side pocket guard + (today's cross-region damage re-check) so cross-pocket interaction can't leak in the shared world. + +### 4. The descent lifecycle (rename + extend `RunDirectorSystem`) + +`RunDirectorSystem` stays the **sole FSM writer** (its single-writer discipline + receiver-sets-command idiom +are load-bearing). State map (append-only byte consts, ghost-stable): + +| Today | LANTERN | Note | +|---|---|---| +| Staging | **AtStation** | muster/prep/ready at the hub | +| Launching | **Descending** | Bell-down telegraph; pick descent identity | +| InRoom | **InPocket** | active pocket populated | +| RoomReward | **PocketClear** | **mutation thresholds fire here** (pocket-clear beats, never mid-combat) | +| RoomExplore | **PocketExplore** | loot + **plant-a-lantern** window | +| RouteSelect | **ChooseNext** | pick the next pocket edge | +| Returning | **Ascending** | Bell recall (teleport) or lit-road walk home; bank; → AtStation | + +- **Bell transit = teleport** (the proven portal→EnterRoom teleport). Lit-road walk-home through pinned pockets + is a stretch goal, not a slice blocker. +- **~30–40 min hard session cap** = a server descent timer that forces the Bell recall (new). +- Participant conscription/teleport/release (`RunParticipant`) reused verbatim; late-join/dead-respawn rejoin + the co-located pocket via the existing conscription path. + +### 5. Pinning, burn & the Lamp meter + +- **Plant a lantern** in PocketExplore = a placement RPC (the `BuildPlaceSystem` co-op-atomic pattern) that + freezes the salt + marks `PocketId` pinned + persists (new additive `PinnedPocketSave[]`, SaveData **v7**, + own staging carrier + born-correct one-shot replay, mirroring `PendingStructure`/`BaseRestoreSystem`). +- **Session-only burn:** fuel is a **runtime** server countdown per lit lantern (never persisted — loads full, + drains only while the session runs). Guttering telegraphs long/loud; full gutter **un-pins** the pocket + (dark reclaims it) — **only during play**, honoring "no offline punishment." Loss ceiling = frontier pockets + only, never the pinned prefix's deepest reach in a way that soft-locks. +- **Banked light** deposited at a lit lantern feeds the **Lamp meter** (the `GoalProgress`-equivalent campaign + readout on the global untagged director ghost). + +### 6. Wire contract (replicated vs server-only) + +- **Global untagged director ghost** (`DescentInfo` ≈ `RunInfo`, all `[GhostField]`): lifecycle byte, active + `PocketId`, descent seed (client regenerates graph + cosmetic dressing), **pinned-pocket set** (for map + + muster point), **Lamp meter**, **party Loudness sum**. +- **Server-only:** `DescentSalt`, per-pocket `PinnedSalt`, `PocketTag`, `RunParticipant`, lamp fuel timers, + pocket teardown tags. +- **Player ghost:** ready flag + **lamp radius** as `[GhostField] OwnerSendType.All` (clients render their own + + teammates' light cones; the server computes relevancy) + **Loudness pip**. + +### 7. Salvage map (what each new piece reworks) + +`RunMapMath`→pocket-graph gen · `RunDirectorSystem`→descent FSM · `RegionRelevancySystem`→two-layer pocket + +light-union relevancy · `RoomTag`/`RoomTeardown`→`PocketTag`/teardown · `RoomFieldSystem` `Hash(seed,id,sub)`→ +pocket content (frozen-salt for pinned) · ping-pong two-slot arena→pocket transit · `SaveData` additive + born- +correct staging/replay→seed-pin persistence (v7) · `BuildPlaceSystem`→lantern planting · `GoalProgress`→Lamp +meter · global untagged `CycleDirector` ghost→descent/lamp global state. + +## Open questions & hazards the review MUST attack + +1. **Light-relevancy thrash/hysteresis.** A ghost pops in/out as the lamp sweeps → snapshot churn + the known + relevancy-re-entry false-edge client hazard. Proposal: **once-lit-stays-relevant until pocket exit** (or a + grace window). Review the correctness + the fiction ("does re-hiding a seen enemy feel wrong?"). +2. **Relevancy rebuild cost & structure.** Confirm the per-pocket connection-independent computation; bound it; + decide if `GhostImportance` is needed at all for the slice. +3. **Determinism of the frozen salt.** `PinnedSalt` must be frozen deterministically + saved; the re-knot + `DescentSalt` must never collide with a live `PinnedSalt`. No wall-clock; `TickUtil.NonZero` for any tick. +4. **Muster-at-deepest-pin + born-correct load.** How the FSM picks the entry pocket; how load restores the + pinned prefix born-correct (the `PendingSave`/`BaseRestoreSystem` handshake extended). +5. **Session-only burn vs persistence.** Pinning persists (seed+deltas+lit); fuel is session-runtime only. + Confirm the un-pin path can't soft-lock the save (loss ceiling) and can't fire offline. +6. **Server interaction guard.** Relevancy hides only from clients; enemies act in the dark server-side. + Confirm no exploit (e.g. a player damaged by something they were never sent) and that it reads as fiction, + not a bug. +7. **Prediction/teleport.** Pocket gen + relevancy are server-authored (not predicted). The transit teleport is + server-authoritative (today's EnterRoom). Confirm no rollback issue and that predicted CC movement between + pockets is clean. +8. **Reuse vs rewrite scope.** Is renaming region→pocket the right salvage, or does the light-union layer + justify a fresh relevancy system? (The review's reuse/scope lens.) + +## Related + +- [[Lantern_World_Model_Spike]] — the brief this answers · [[Roadmap_Lantern_Slice]] Phase 0.3 & Phase 2 +- [[Lantern_Strip_Mothball_Inventory]] — the salvage verdicts this design executes +- [[DR-048_Lantern_Adoption_Full_Pivot]] · [[Identity_Lantern]] — the direction & the tide-line +- [[DR-013_M6_Aether_Cycle_Region_Split]] — the region/relevancy machinery being re-keyed