Docs: loop re-shape to expedition-driven (DR-042) + consolidate; fix enemy health-bar fill

- DR-042 (new): canonical loop re-shape — win-driver moves from base-siege
  survival to expedition clears; blind scheduled siege retired; base siege
  becomes retaliation consequence. Build order A (coherence) -> B (retaliation)
  -> C (legibility) -> D (Slice 4 persistent meta).
- Backlog/Path_to_Fun/Home reconciled to the expedition-driven direction;
  Slice 3 + Combat Depth marked built.
- DR-036 (END-2) flagged superseded-in-part; DR-034 (END-1) repurposed (Core
  is a consequence, not the win-gate); DR-037 forward-pointer to DR-042.
- CombatFeedbackSystem: fix enemy health bar (sprite-less Filled Image ignored
  fillAmount -> size via anchorMax.x).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-25 20:07:33 -07:00
parent e32dadbc66
commit 03f778085b
8 changed files with 114 additions and 12 deletions
@@ -822,10 +822,8 @@ namespace ProjectM.Client
var fillImg = fillGo.AddComponent<UnityEngine.UI.Image>();
fillImg.material = _barFillMat;
fillImg.color = new Color(0.88f, 0.22f, 0.14f, 1f);
fillImg.type = UnityEngine.UI.Image.Type.Filled;
fillImg.fillMethod = UnityEngine.UI.Image.FillMethod.Horizontal;
fillImg.fillOrigin = 0; // left
fillImg.fillAmount = 1f;
fillImg.type = UnityEngine.UI.Image.Type.Simple; // a sprite-less UI Image ignores fillAmount (it draws a full quad) ->
fillImg.raycastTarget = false; // the bar empties by sizing the fill RectTransform (anchorMax.x = frac) in UpdateHealthBars
go.SetActive(false);
var entry = new HealthBarEntry { CanvasGo = go, Fill = fillImg, Bg = bgImg, ShowTimer = 0f, Visible = false };
@@ -882,7 +880,7 @@ namespace ProjectM.Client
}
float alpha = (!alwaysOn && entry.ShowTimer < 0f)
? 1f - math.saturate(-entry.ShowTimer / HealthBarFadeDuration) : 1f;
if (entry.Fill != null) { var c = entry.Fill.color; c.a = alpha; entry.Fill.color = c; entry.Fill.fillAmount = frac; }
if (entry.Fill != null) { var c = entry.Fill.color; c.a = alpha; entry.Fill.color = c; entry.Fill.rectTransform.anchorMax = new Vector2(frac, 1f); }
if (entry.Bg != null) { var c = entry.Bg.color; c.a = 0.82f * alpha; entry.Bg.color = c; }
}
else if (entry.Visible) { entry.CanvasGo.SetActive(false); entry.Visible = false; }
+4 -4
View File
@@ -2,7 +2,7 @@
tags:
- moc
- home
updated: 2026-06-08
updated: 2026-06-24
permalink: gamevault/00-home/home
---
@@ -14,9 +14,9 @@ Multiplayer game on **Unity DOTS** (Entities) + **Netcode for Entities** (server
- **Vision** → [[Pillars]] — design pillars & locked decisions · [[Identity]] — the fiction (sci-fi frontier colony)
- **Game Design** → [[Systems_Index]] — per-system design docs
- **Roadmap** → **[[Path_to_Fun]]** (north star — combat-first) · [[Milestones]] · [[Backlog]]
- **Sessions** → `07_Sessions/2026/` — dated work logs (latest: [[2026-06-08_Combat_Depth_Direction]] · [[2026-06-08_Equipment_Slots_Phase1]] · [[2026-06-08_Inventory_Equipment_Progression_Phase0]])
- **Decisions** → `07_Sessions/_Decisions/` — decision records DR-001 … DR-028 · [[DR-001_Netcode_Test_Harness]] · latest [[DR-028_Combat_Primary_Verb_Depth_First]] (direction: combat-first)
- **Roadmap** → **[[Path_to_Fun]]** (north star) · [[Backlog]] (committed list) · [[Milestones]] (history). **Current direction:** a co-op roguelite-ARPG, **expedition-driven loop** ([[DR-037_Procedural_Expedition_Spine_Two_Classes_Persistent_Meta]] → loop re-shape [[DR-042_Loop_Reshape_Expedition_Driven]]).
- **Sessions** → `07_Sessions/2026/` — dated work logs (latest: [[2026-06-24_Slice_Combat_Depth_Enemy_Variety_Impact_Build]] · [[2026-06-21_Slice3_Expedition_Combat_Spine_Build]] · [[2026-06-17_Design_Redirect_Coop_Roguelite]])
- **Decisions** → `07_Sessions/_Decisions/` — decision records DR-001 … DR-042 · [[DR-001_Netcode_Test_Harness]] · latest [[DR-042_Loop_Reshape_Expedition_Driven]] (loop re-shape: expedition-driven win)
- **Meta** → [[Documentation_Protocol]] · [[Tags]]
- **Templates** → [[Session_Log_Template]] · [[Decision_Record_Template]]
+14 -2
View File
@@ -21,8 +21,20 @@ Last decluttered 2026-06-08 (removed all shipped `[x]` items; their context is p
- **Slice 1 — Combat Readability & HUD Declutter** ✅ **BUILT + engineering-validated 2026-06-17 ([[DR-038_Slice1_Combat_Readability_HUD_Declutter]])** — on-damage-sticky **enemy health bars** (+fade, <25 %HP always-on) in `CombatFeedbackSystem` (`Health.Current` already replicated); **telegraph fix** (per-enemy baked `EnemyTelegraph` windup ramp replacing the hard-coded `22f` + windup 18→22 + a scale-pulse); **build-mode toggle** (client `BuildPaletteState.PaletteOpen` gates the palette + a "Tab/Y — BUILD" chip); **Charger committed-lunge tell** (`[GhostEnabledBit] IsLunging` derived once/tick — one Charger re-bake). 345/345 EditMode; Play-validated (handshake intact, bake correct, no runtime errors). **Open: operator visual fun-gate.**
- **Slice 2 — Two Classes (Warrior / Ranger)** ✅ **BUILT + validated 2026-06-18 ([[DR-039_Slice2_Two_Classes_Warrior_Ranger]])** — DRG-asymmetric (Warrior melee bruiser tankier/slower; Ranger ranged faster/squishier + co-op auto-assist hook); aim-directed Warrior cone (Cone archetype inline in `AbilityFireSystem`, server-only damage, same-tick); class carried on `GoInGameRequest.ClassId` (the per-world-`ConnectionConfig` blocker fixed) → `ClassTraits` seeds at spawn; character deltas via replicated `StatModifier` seeds on Default (no per-class blob); melee asymmetry folds in `MeleeComboSystem` (`StatTarget.MeleeDamage`/`MeleeRange`); menu class picker. 348/348 EditMode; Warrior Play-validated server==client (re-bake handshake intact). **Deferred polish:** cone client VFX + slash-arc reach. **Open: fun-gate (operator).**
- **Slice 3 — Expedition Combat Spine** 🔬 **REVIEWED + scope-locked 2026-06-18 ([[DR-040_Slice3_Expedition_Combat_Spine]]) — build is next.** Minimal v1 loop: walk gate → fight an epoch-seeded enemy wave in the expedition → clear → return + Ore → escalated base siege. New `ZoneEnemyTag`/`ZoneEnemyDirector`/`ZoneEnemyState` + `ZoneEnemySpawnSystem` (reuse Grunt/Charger prefabs, `RegionTag{Expedition}`, ring math, one-per-interval, Calm-only). **4 netcode blockers fixed:** `EnemyAISystem` per-region target lists (+ no base-structure/Core fallback for expedition husks); `WaveSystem` cleared-check → `RegionTag{Base}` only (+ ThreatDirector cull); RegionRelevancy `MaxAlive` cap; reward double-fire gated by `CycleRuntime.LastRewardedEpoch` + a real clear. **Deferred to v2:** arena-layout pool/authoring, zone-theme byte + HUD, `TimedModifier` buff, SaveData v6, mini-boss. **Open fork:** optional (default) vs required sortie.
- **Slice 4 — Persistent Meta-Progression** *(review-gated)*: **SaveData v6** (meta-currency, unlocked classes, persistent epoch); a between-runs growth surface at the hub; persist-the-seed-regenerate-the-layout (pure-function generator).
- **Slice 3 — Expedition Combat Spine** **BUILT + verified 2026-06-21 ([[DR-040_Slice3_Expedition_Combat_Spine]]).** v1 loop: walk gate → fight an epoch-seeded enemy wave in the expedition → clear → return + Ore → escalated base siege. New `ZoneEnemyTag`/`ZoneEnemyDirector`/`ZoneEnemyState` + `ZoneEnemyDirectorSystem` (reuse Grunt/Charger prefabs, `RegionTag{Expedition}`, ring math, one-per-interval, Calm-only). All 4 netcode blockers landed; 368/368 EditMode + clean Play smoke (post-impl review caught a region-blind Core-breach cull → fixed Base-only). **Open: fun-gate playtest.**
- **Combat Depth (MC-2 + MC-3)** ✅ **BUILT + post-impl-reviewed 2026-06-24 ([[DR-041_Slice_Combat_Depth_Enemy_Variety_Impact]]).** *(Inserted, not a numbered slice — operator: "the combat needs a lot more work.")* Two new enemy questions — **Spitter** (ranged reposition) + **Swarmer** (surround) — + a 4-type weighted mix in both directors (fork-4a base siege too, mandatory `MaxAlive`) + MC-3 impact (magnitude-scaled hit punch + Spitter aim-lane). Real rigged models (Spitter = re-skinned Kaiju, Swarmer = Undead-Werewolf). 388/388 EditMode + two Play smokes. **Open: fun-gate playtest.**
- **Slice 4 — Persistent Meta-Progression** — **RE-FRAMED as phase D of the Loop Re-shape ([[DR-042_Loop_Reshape_Expedition_Driven]]).** **SaveData v6** (meta-currency, unlocked classes, persistent epoch); a between-runs growth surface at the hub; persist-the-seed-regenerate-the-layout. *Builds AFTER the loop-coherence phases AC below.*
### NEXT (operative) — Loop Coherence Re-shape: Expedition-Driven ★ ([[DR-042_Loop_Reshape_Expedition_Driven]], 2026-06-24)
A 5-subsystem loop evaluation found the loop has **two conflicting win-models bolted together**: the only path to victory is "survive 4 base sieges" (passively/AFK-reachable — scheduled sieges auto-arm + a 60 s timeout auto-clears them), while the **expedition (the stated combat spine, where all the new enemy variety lives) advances nothing toward winning.** Root cause: the END-1/END-2 base-siege win is a leftover from the superseded jam slice ([[DR-035_End_Of_Month_Slice_Adoption]]/[[DR-036_END2_Final_Siege_Win_Lose]]) that DR-037 never retired. **Operator chose (2026-06-24): commit to the expedition-driven vision.** Build order:
- **A — Coherence core (first):** move the win-driver from *base sieges**expedition clears* (`GoalProgress.Charge` +1 on a cleared sortie); **kill the AFK win** (disable the blind scheduled siege as a progression source); final beat reached through the spine. *Netcode-touching → design-review first.*
- **B — Retaliation connect:** post-expedition siege becomes THE base-siege source (fix the interference) — defending what you built becomes a *consequence* of sortieing, not the goal. *Netcode-touching → design-review.*
- **C — Legibility fixes:** walls actually block (structures on the enemy collision filter); Aether-upgrade HUD button + cost; Biomass sink (or cut); cold-start ledger seed; hide dead Harvester/Conveyor/Pylon; expedition objective UI + gate prompt; reward scales with depth.
- **D — Persistent meta (= Slice 4):** SaveData v6 + between-runs growth (above).
**Consolidation:** [[DR-036_END2_Final_Siege_Win_Lose]]'s "survive-4-base-sieges" win is **superseded** (win-driver → expedition clears; the charge-cadence "siege-survived-only" lock is reversed); [[DR-034_END1_Losable_Core]]'s Core stays but as a **consequence of the retaliation siege**, not the win-gate. The health-bar fill bug-fix (sprite-less `Image.Filled` ignores `fillAmount` → size the RectTransform) rides the first commit.
**Per-slice forks to lock at each review:** expedition depth (one zone vs sequential+boss); shared expedition region vs per-party instances (shared recommended); zone-clear reward shape; class-select moment (menu vs at-base); meta unlock surface.
+3 -1
View File
@@ -7,12 +7,14 @@ tags:
- endgame
- north-star
status: active
updated: 2026-06-08
updated: 2026-06-24
permalink: gamevault/06-roadmap/path-to-fun
---
# Path to Fun — the north-star roadmap
> **[LOOP RE-SHAPED 2026-06-24 → [[DR-042_Loop_Reshape_Expedition_Driven]]]** A 5-subsystem loop evaluation found the game had **two conflicting win-models bolted together**: the only path to victory was "survive 4 base sieges" (passively/AFK-reachable — scheduled sieges auto-arm + a ~60 s timeout auto-clears them), while the **expedition combat spine — where all the new enemy variety lives — advanced nothing toward winning.** The operator locked the **expedition-driven** direction: the win-driver moves to **expedition clears**, the blind scheduled siege is retired, and base sieges become **retaliation consequence** (the reason your build-defense matters). This **supersedes the END-2 base-siege win** ([[DR-036_END2_Final_Siege_Win_Lose]]) as the progression driver and demotes END-1's losable Core ([[DR-034_END1_Losable_Core]]) to a *consequence* rather than the win-gate. Committed build order — **A** coherence core → **B** retaliation connect → **C** legibility fixes → **D** persistent-meta (Slice 4) — lives in [[Backlog]] ("Loop Coherence Re-shape" section). Everything below this banner is **historical context**; the operative plan is DR-042 + Backlog.
> **[DIRECTION EVOLVED 2026-06-17 → [[DR-037_Procedural_Expedition_Spine_Two_Classes_Persistent_Meta]]]** Path A's spine is COMPLETE and the slice [[End_Of_Month_Game_Jam_Slice]] was *playtested* — and found **stale in a single arena** ([[Scratch Notes 6152026]]). The operator **answered the [Decision Gate](#the-decision-gate-mandatory-stop-after-end-2) as *continue/expand*** (not "ship the minimum"): re-scope off the fixed deadline and build a **co-op roguelite-ARPG** — a **procedural Expedition combat spine + persistent meta-progression home base + two classes (Warrior/Ranger)**, readability fixed first. This **fulfils** the long-locked pillar-#4 "procedural expeditions" and **reverses** [[DR-031_Base_Mining_Loop_Cohesion]]'s pause; it is **pillar-safe** (Mission-as-Sortie: the base never resets). The committed milestone list now lives in [[Backlog]] (Slices 14); the build notes / netcode homework below remain the engineering substrate (the dash/`SourceTick`/`StatModifier`/region/relevancy/save patterns all carry forward). Path B's combat-depth rows (MC-2/3/5/6) are **absorbed** into the new class + expedition slices.
> **[HISTORICAL — the slice, June 1330]** Path A's spine is **COMPLETE** — all **14/14 systems shipped** (MC-0/1/4 · EB-1/2 · END-1 · **END-2 built 2026-06-13 as slice SL-3**, [[DR-036_END2_Final_Siege_Win_Lose]]). The operator answered the [Decision Gate](#the-decision-gate-mandatory-stop-after-end2) **early, as *ship the minimum***: the immediate target is the **[[End_Of_Month_Game_Jam_Slice]]** ("Awakening Engine Last Stand"), a compact single-arena base-defense demo due June 30. With END-2 in, the slice is **winnable end-to-end**; the remaining slice work is **tuning + polish, not code** (SL-1/2/4/5/6/7) — and the final-siege **fun-gate** is the one open operator validation. This doc stays the **north-star for the full game**; the slice scopes Path A to a deliverable. Milestone breakdown: [[Backlog#NEXT — Awakening Engine Last Stand (End-of-Month Slice) ★]] · adoption: [[DR-035_End_Of_Month_Slice_Adoption]]. *(Path B is untouched and provisional; the formal ship-vs-continue note is logged after June 30.)*
@@ -14,6 +14,8 @@ permalink: gamevault/07-sessions/decisions/dr-034-end1-losable-core
# DR-034 — END-1: The Base Can Be Lost (a Core with Integrity)
> **⚠️ REPURPOSED by [[DR-042_Loop_Reshape_Expedition_Driven]] (2026-06-24):** the losable Core STAYS, but as a **consequence of the post-expedition retaliation siege**, not the win-gate. Core loss costs resources/progress; it is no longer the sole lose condition of a base-defense win — the win-driver moved to **expedition clears**. The component + `CoreDamage`/`CoreRestore` systems are unchanged.
> Path A milestone (the first **Endgame** beat); forks locked in [[DR-029_Path_A_Fork_Locks]]. Continues the economy braid [[DR-032_EB1_Machines_Can_Die]] · [[DR-033_EB2_Felt_Spend_Charge_Economy]]. Spec: [[Path_to_Fun#END-1 — The base can be lost: a Core with integrity]]. Session: [[2026-06-12_END1_Losable_Core]].
## Context
@@ -15,6 +15,8 @@ permalink: gamevault/07-sessions/decisions/dr-036-end2-final-siege-win-lose
# DR-036 — END-2: The Charge Means Something (final siege, win or lose)
> **⚠️ SUPERSEDED IN PART by [[DR-042_Loop_Reshape_Expedition_Driven]] (2026-06-24):** the win-DRIVER moves from *surviving base sieges* to *clearing expeditions*. This DR's "survive 4 base sieges → final siege → Victory" is no longer the progression path (the loop evaluation found it passively/AFK-reachable and disconnected from the expedition combat spine), and the [[DR-035_End_Of_Month_Slice_Adoption#Locked fork — END-2 charge cadence (2026-06-13)|siege-survived-only charge cadence]] is reversed. The `RunPhase`/`RunOutcome`/`GoalReachedSystem` **machinery is REUSED**; only the **source of `GoalProgress.Charge`** changes (and the final beat may become a final *expedition*).
> The last un-built Path A spine mechanic and the **critical-path blocker** for the [[End_Of_Month_Game_Jam_Slice]] (slice milestone **SL-3**). Answers the slice's "no terminal win" gap. Spec: [[Path_to_Fun#END-2 — The charge means something: the cap arms a final siege, win or lose]]. Continues [[DR-034_END1_Losable_Core]] (reuses its ghost + banner pattern). Charge cadence locked in [[DR-035_End_Of_Month_Slice_Adoption#Locked fork — END-2 charge cadence (2026-06-13)]]. Session: [[2026-06-13_SL3_END2_Final_Siege_Win_Lose]].
## Context
@@ -18,6 +18,8 @@ permalink: gamevault/07-sessions/decisions/dr-037-procedural-expedition-spine-tw
# DR-037 — Procedural Expedition Spine + Two Classes + Persistent Meta (the post-playtest redirect)
> **➡️ CONCRETE LOOP in [[DR-042_Loop_Reshape_Expedition_Driven]] (2026-06-24):** Slices 13 + a Combat Depth slice ([[DR-041_Slice_Combat_Depth_Enemy_Variety_Impact]]) shipped, but a loop evaluation found the END-1/END-2 base-siege win (a leftover this redirect never retired) still drove progression while the expedition spine advanced nothing. DR-042 locks the **expedition-driven** loop this redirect implied: win-driver = **expedition clears**, base sieges = retaliation consequence, and re-frames Slice 4 (Persistent Meta) as the final phase of a coherence build (A→D). Read DR-042 for the operative plan.
> **A project-direction change, not a slice tweak.** Triggered by a real operator playtest of the shipped single-arena slice ([[Scratch Notes 6152026]], 2026-06-15). Re-scopes off the [[End_Of_Month_Game_Jam_Slice]] single-arena demo and commits Project M to a **co-op roguelite-ARPG**: a **procedural Expedition region as the required combat spine**, a **persistent meta-progression home base that never resets**, and **two classes** (Warrior melee / Ranger ranged) — with **combat readability fixed first**. **Reverses the [[DR-031_Base_Mining_Loop_Cohesion]] "focus on the base, pause the expedition" decision** deliberately, and **fulfils** the long-locked [[Pillars|pillar #4]] ("persistent buildable home base + **instanced/procedural expeditions**") that the slice had paused. Research-backed by an 8-agent design+feasibility pass (this session). Supersedes the slice as the operative target; the slice doc is kept as an optional showcase/fallback.
## Context
@@ -0,0 +1,84 @@
---
id: DR-042
title: Game-Loop Re-shape — Expedition-Driven Progression (retire the base-siege win)
status: accepted
date: 2026-06-24
tags:
- decision
- design
- loop
- endgame
- expedition
- roguelite
- north-star
permalink: gamevault/07-sessions/decisions/dr-042-loop-reshape-expedition-driven
---
# DR-042 — Loop Re-shape: Expedition-Driven Progression
> Operator (2026-06-24, after the Combat Depth slice [[DR-041_Slice_Combat_Depth_Enemy_Variety_Impact]]): *"I don't think the main game loop is complete / makes sense — evaluate it and see how the flow should be altered."* A 5-subsystem multi-agent loop evaluation (`wf_4cebbc74-216`) mapped the real end-to-end flow and found the loop has **two conflicting win-models bolted together**. The operator chose the **expedition-driven** direction (commit to [[DR-037_Procedural_Expedition_Spine_Two_Classes_Persistent_Meta]]). This DR locks the re-shape and **supersedes the END-2 base-siege win** as the progression driver.
## The problem (from the loop evaluation)
The game has **two disconnected win-models that fight each other**:
1. **The only path to victory is "survive 4 base sieges → a final siege."** `GoalProgress.Charge` (the win meter) is incremented in exactly **one** place — `CyclePhaseSystem` on surviving a *base* siege. (END-1/END-2: [[DR-034_END1_Losable_Core]], [[DR-036_END2_Final_Siege_Win_Lose]].)
2. **That win is passively / AFK-reachable.** `ScheduleEnabled` is baked true, so a base siege auto-arms every ~45 s (`ScheduleIntervalTicks=2700`) with **no player-presence check**, and `SiegeTimeoutTicks` (~60 s) culls the husks and zeroes `RemainingToSpawn` so `DefendCleared` trips next tick — a qualifying siege can be "won" by **waiting 60 s without fighting** (timeout disabled only in the final siege).
3. **The expedition — the stated "combat spine" (DR-040), where all the new enemy variety lives — advances nothing toward winning.** Clearing an expedition zone only banks flat +25 Ore on return and bumps `ThreatState.PendingReturns`. The headline combat has no purpose in the win condition.
**Root cause:** the "survive base sieges to win" goal (END-1/END-2) is a leftover from the **superseded single-arena jam slice** ([[DR-035_End_Of_Month_Slice_Adoption]] / [[DR-036_END2_Final_Siege_Win_Lose]]). When [[DR-037_Procedural_Expedition_Spine_Two_Classes_Persistent_Meta]] re-scoped to an **expedition-driven co-op roguelite** (base = persistent hub, expedition = spine, Mission-as-Sortie), the old win-model was never retired and the connecting tissue (Slice 4 persistent meta) was never built. The two visions coexist incoherently — *that* is why the loop "doesn't make sense."
### Supporting gaps the eval surfaced (full list in `wf_4cebbc74-216`)
- **Siege-arming doc/code drift:** the doc says schedule is "baked-but-inert" + post-expedition retaliation is "the only source," but BOTH `ScheduleEnabled` and `PostExpeditionEnabled` default true. Worse, the post-expedition source can only arm in Calm with no pending siege, so the ~45 s scheduler frequently pre-empts it — the DR's centerpiece source is often a silent no-op.
- **Walls don't physically block enemies:** `EnemyAISystem.SweptMove` collides only against `WorldCollisionConfig.EnvironmentMask` (boundary ring + landmarks). Structures are aggro *targets* only, with no DOTS collider — husks walk straight through walls. The fortress fantasy is absent.
- **Dead resources / subsystems:** **Biomass(3)** is harvestable + HUD-shown but consumed by NOTHING. **Aether(2)** — the only ability-upgrade currency — is gated behind an expedition trip (base nodes are forced Ore-only) AND its sink has **no HUD button** (U-key only). **Harvester/Conveyor/Pylon** + the whole MachineInput automation chain are live code but unwired/cosmetic. **Cold-start:** the ledger boots empty so a turret placed without a Fabricator silently never fires.
- Other latent items: `ThreatConfig.StartCondition`/`RequirePlayerAtBase` read by nothing; `ExpeditionsCompleted`/`CycleNumber` dead counters; `SizePerExpeditionResource` haul-scaling stubbed ×0; base-siege PAUSES expedition spawning (a remote sortie freezes when a teammate triggers a home siege); no expedition objective UI / gate prompt; terminal run reloads frozen on Continue; `CoreDamageSystem` un-region-filtered (works only by the ~1000-unit geometric gap).
### What works — KEEP (do not rebuild)
- The **macro state machine** is clean + single-writer-disciplined (`CyclePhaseSystem` sole writer of Phase/WaveState-entry/GoalProgress/RunOutcome; `ThreatDirector` owns when/how-big; one-field hand-off; wrap-safe `NetworkTick` math).
- The **region split** (per-player server-only `RegionTag` + `GhostRelevancy`) is well-executed and correctly region-scopes every base-loop query.
- The **base gather→build→survive micro-loop** is coherent when engaged; the **Charge economy** (Fabricator→turret soft-fail) is internally consistent; **persistence** is born-correct (SaveData v5).
- The **4-enemy combat substrate** (telegraphed wind-ups, weighted aggro, swept movement, Spitter projectiles, Swarmer packs, Charger lunges) is built and reused across both regions — *a solid substrate that just lacks a reason to engage.*
## Locked direction — expedition-driven (DR-037)
**Make the expedition the progression engine.** The win comes *through* expeditions, not idle base-defense.
### Target loop
> **Base (hub, Calm):** mine / build / upgrade — prep, no win here. → **Sortie (the spine):** walk the gate, fight the epoch-scaled wave (the 4 enemy types). **Clearing the expedition IS the progression beat.****Return → invest:** deposit the haul, spend it to get stronger. → **Retaliation siege:** returning provokes a base siege — *this* is where your turrets/walls matter (consequence, not the goal). → **Escalate:** each sortie is deeper/harder. → **Win:** reach the terminal through expeditions, not by idling.
## The changes (grouped by what they buy)
**A — Coherence core ("make the win make sense"):**
1. **Move the win-driver from base sieges → expedition clears.** `GoalProgress.Charge` +1's on an **expedition clear** (on return with `ClearedThisEpoch`), not on surviving a base siege. `Target` = N clears.
2. **Kill the AFK win.** Turn off the blind scheduled base siege as a *progression* source; with the win requiring active sorties there is no idle path (also closes the 60 s-timeout "win by waiting" hole).
3. **Final beat through the spine.** At `Target` clears, arm a climactic final (a final expedition, or a big final base siege as the *defense* climax) → Victory; losing the Core in the final → Loss.
**B — Connect the halves (base siege = consequence):**
4. **Post-expedition retaliation becomes THE base-siege source** (fix the interference so it actually fires). Returning loaded → a siege to defend. Core loss = lose resources/progress (real stakes), but not the win-gate. This is what makes the **build pillar** matter.
**C — Legibility dead-ends (cheap, high-impact, needed regardless of direction):**
5. **Walls actually block** — add structures to the enemy movement collision filter (or give them DOTS colliders); restores the fortress fantasy.
6. **Aether upgrade gets a HUD button + cost** (the only character progression, currently U-key-only); **Biomass** gets a sink or is cut; **cold-start** ledger seeded with a little Ore so turrets aren't a silent deadlock; **hide the dead** Harvester/Conveyor/Pylon palette entries.
7. **Expedition feedback** — gate-entry prompt + "enemies remaining / cleared / return to claim" objective UI; scale the reward with depth (flat +25 Ore today).
**D — Persistent meta = Slice 4 proper (layers on after AC):** expedition depth / `ExpeditionsCompleted` (a dead counter today) persists across runs; **SaveData v6**; a between-runs growth surface at the hub — the long arc.
## Recommended build order
**A (coherence core) first** — most contained, directly answers "the loop doesn't make sense." Then **C (legibility)****B (retaliation connect)****D (Slice 4 meta)**. The health-bar fill bug-fix (2026-06-24: a sprite-less `Image.type=Filled` ignores `fillAmount` → drive the fill RectTransform width) rides along in the first commit.
**A + B are netcode-touching** (the win-driver + arming logic move) → run the **adversarial design review BEFORE coding** them ([[validate-netcode-design-before-coding]]), then build through the `/dots-dev` ladder with a fun-gate per phase.
## Consolidation — what this supersedes / repurposes
- **[[DR-036_END2_Final_Siege_Win_Lose]] (END-2):** the "win = survive 4 base sieges + a final siege" model is **superseded** — the win-driver moves to **expedition clears** (change A1/A2). The `RunPhase`/`RunOutcome`/`GoalReached` *machinery* is reused; only the **source of `GoalProgress.Charge`** changes (and the final beat may become a final *expedition*). The "charge cadence LOCKED: siege-survived-only" decision (DR-035/DR-036) is **reversed** here.
- **[[DR-034_END1_Losable_Core]] (END-1):** the losable Core **stays**, but as a **consequence of the retaliation siege**, not the win-gate. Core loss costs resources/progress; it is no longer the sole lose condition tied to a base-defense win.
- **[[DR-037_Procedural_Expedition_Spine_Two_Classes_Persistent_Meta]]:** this DR is the concrete loop the redirect implied. Slice 4 (Persistent Meta) is **re-framed**: the loop-coherence work (AC) comes first; the meta/SaveData-v6 (D) is the final phase.
- **Roadmap:** [[Path_to_Fun]] (Path A/B) was already historical post-DR-037; this is the current operative loop plan. The committed list is in [[Backlog]] under the Co-op Roguelite Redirect.
## Open forks (operator, lock before/at the design review)
- **Final beat:** a **final expedition** (the climax IS a deep sortie — purest expression of "expedition = spine") vs a **final base siege** (a defense climax, reuses END-2's final-siege machinery). *Recommend present both at the A-phase review.*
- **Do base sieges stay in v1 at all,** or does retaliation become a later layer (B) so the first coherent build is purely sortie→reward→escalate? *(The recommendation keeps a light retaliation siege so the build pillar isn't orphaned.)*
- Expedition reward shape + depth scaling; whether a soft-loss should cost `GoalProgress` (give the run real downside).
## Status
Accepted + locked (direction). Build pending — phase A first, design-review-gated. Loop evaluation transcript: `wf_4cebbc74-216`. Combat substrate it gives purpose to: [[DR-041_Slice_Combat_Depth_Enemy_Variety_Impact]].