Connect typed Homeworld custody, transport, battle, income, revival and Caladan reinforcement flows with private multiplayer recovery and controls. Preserve the optimized test workflow and keep unfinished rules modes gated. Verified with 3682 offline tests, typecheck, lint, production build and 40 HTTP tests; existing saved games remain unchanged.
19 KiB
Homeworld runtime readiness
This is the pre-integration architecture audit. For the later implemented boundary and remaining work, see HOMEWORLD_RUNTIME_IMPLEMENTATION.md.
Read-only architecture audit, 9 September 2026. No Homeworld rules are enabled by this document. The current public start still rejects Advanced and expansion configurations; there is no Homeworld state, option, card registry, or action handler. Source verification of all thirteen cards and faction interactions is a separate workstream. This is an implementation plan, not evidence of completed gameplay.
Source boundary
The independent source review has confirmed these architectural requirements from Ecaz & Moritani rulebook pages 9–10: native reserves occupy Homeworlds; cards start on their high side and react to their printed reserve thresholds; occupation has turn-start/end and immediate sole-alien-occupation conditions; occupied natives retain their low penalty. Homeworlds are not territories. Ecaz Occupy does not merge factions there, BG cannot use advisor stance there, and Homeworld advantages/penalties are immune to Karama. Emperor has distinct Kaitain regular-force and Salusa Sardaukar custody in Advanced, with a movement transfer and combined shipment selection. Native low effects include additional free revival and bank charity, with printed exceptions.
These are constraints for the interfaces below. Exact card thresholds, high/low effects, invasion rewards and victory effects must come from the source catalog before implementation. In particular, do not infer that every Homeworld is a stronghold, yields ordinary stronghold income, or contributes to Ecaz's three jointly occupied Arrakis strongholds. The source reviewer is checking those distinctions. Transport permission is directional: the reviewed general text permits Homeworld-to-Homeworld shipment, with the Guild's special Arrakis-to-Homeworld access; it does not create ground movement edges from Arrakis. Preserve the exact final source interpretation for exceptions.
Existing seams and assumptions
| Surface | Current implementation | Required integration |
|---|---|---|
| Configuration/setup | engine.ts Game around 1160, createGame around 2093, start/initializeSetup around 3403, initializeStartingForces around 3457 |
Add an explicit optional module configuration/state and prerequisite validation. Initialize Homeworld custody at the actual force-placement step, without exposing cards before prediction/traitor stages or silently activating other modules. |
| Physical custody | Player around 385 has scalar reserves, tanks, board forces, and parallel elite zones |
Homeworld native and invading groups need one authoritative physical inventory. Emperor's two native pools cannot be represented by one unqualified source. Do not count native reserves twice as both reserves and board forces. |
| Location registry | board.ts territory, validLocation, gameTerritories, splitLocation, gameDistance recognize printed Arrakis and HMS only |
Introduce an explicit Homeworld location kind and validation/display functions. Keep Arrakis path geometry and storm sectors separate. |
| Ordinary transport | validatePhysicalShipment around 12902, offerShipment, commitShipment around 13030; guildShip action around 16700 |
Quote exact source custody, typed quantities, destination kind, rate, contributor split and income. Preserve the declaration-before-payment Guild window and normal combined-turn ownership. |
| Entry/movement | allowedEntry around 5822, forceGroup, completeMove, finishMovementTurn around 6417; occupancy.ts |
A Homeworld entry branch must enforce its own alliance/occupancy rules. Current Ecaz shared occupation, storm, territory capacity and end-movement allied separation are explicitly planet rules. Emperor's internal transfer needs its own quoted movement action. |
| Battle discovery | board-resolution-quote.ts quoteBattleBoard; engine battles around 8460 and phase 6 initialization |
Add Homeworld conflicts to the battle frontier without running gameDistance or storm connectivity. Source-approved attacker selection/order must be explicit. |
| Plans/results | combatForces around 3347, battle-resolution-quote.ts, resolveBattle around 10995, takeBattleLosses/kill |
Reuse sealed plans, cards, leaders, traitors, support and casualty arithmetic through a location-aware adapter. Casualties on a native Homeworld must debit its reserve pool; invader losses debit its invading pool. |
| Battle aftermath | battle-aftermath-quote.ts, cleanup context, Face Dancers, captures, tech transfer, Auditor and discard continuations |
Carry the same typed battle location into every receipt/validator. Homeworld control/rewards must settle at the correct point once, including traitor, explosion, replacement and retreat outcomes. |
| Revival/card returns | revival.ts, revival-resume.ts, revival-cancellation.ts; finishRevival around 11658 and applyGholaEffect around 10081 |
Resolve dynamic free allowances and actual return pools through one custody/capability quote. This includes Emperor extras, foreign gholas where relevant, Ghola force returns and existing prepared revival receipts. |
| Economy/capabilities | charity.ts; faction-only handLimit(p) around 2055; movement/support helpers; faction-specific checks throughout engine |
Derive current Homeworld modifiers centrally and consume them at actual eligibility, payment, view and bot call sites. Keep bank-paid Homeworld charity separate from CHOAM payment receipts. |
| Collection/victory | quoteSpiceCollection, quoteBattlePhaseAdvance, victory-progress.ts, victory-quote.ts, stronghold-cards.ts |
Keep Arrakis spice extraction/Stronghold Cards separate. Compose only source-defined Homeworld income/victory effects, using a shared public progress quote; BG prediction remains private inside final victory. |
| Player view/UI | viewGame around 17395; game-table.tsx source/destination controls around 350–700, forces around 880, map/details around 1129–1290 |
Add inspectable Homeworld cards/discs and location-specific owned actions. Numerous direct territory(id).name calls need a location label adapter for Homeworld battle/action messages. |
| AI | bots.ts destinations around 176, plans around 520, revival around 2600, shipment around 2786; bot-mobility.ts, transport-quote.ts |
Consume public Homeworld status and owner-only legal action descriptors. Current map destination lists and scalar reserve policies cannot choose or defend Homeworlds. |
| Recovery | applyAction, normalizeAutomaticGame, viewGame; db/rooms.ts needsAutomaticRoomRecovery around 401 |
Bind pending invasion/control/reward choices to the current module, location and event. Persist automatic threshold/control transitions through the existing CAS path. No read-side resource effects. |
Recommended state and shared interfaces
Keep gameTerritories(g) as the Arrakis/HMS enumeration. Introduce GameLocation = {kind:'territory', id, sector} | {kind:'homeworld', id} at new transport, battle and display boundaries. Existing saved territory strings can be decoded as the first variant; new Homeworld actions should be explicit, rather than making an invented :0 key valid in every old consumer. A separate combatLocations frontier can combine both types. The existing ecaz-occupy.ts already has a kind:'homeworld' identity case which deliberately does not merge allies; occupancy.ts currently wraps only territory semantics and cannot itself serve as the Homeworld entry rule.
The coordinator's proposed custody model retains Player.reserves as the authoritative total native Homeworld forces and Player.elites.reserves as its elite subset. Homeworld state stores only foreign occupants and Emperor's secondary Salusa allocation {normal, elite}; Kaitain is derived by subtraction. Both unit types can be transferred between Emperor's Homeworlds, so the secondary allocation must not be an elite-only number. Do not duplicate native tokens in Player.forces. Keep occupation history where rules require a turn receipt, separate from derived threshold/capability values.
Every custody quote must validate secondary.normal <= reserves - eliteReserves and secondary.elite <= eliteReserves, with safe whole-number nonnegative counts. Withdrawals debit explicit per-home typed quantities; never silently clamp Salusa when a generic reserve decrement makes it inconsistent. Mixed shipment sums those debits once. Revival credits its prescribed native pool; battle losses debit the actual home under attack rather than any convenient global reserves. Foreign visitor return debits a foreign pool and credits the appropriate native pool without counting visitors as the host's reserves. Return the before/after home counts for threshold/control processing, but keep the custody helper itself free of reward effects, RNG and occupation-rule invention. Every old direct reserve mutation must be audited when wiring this model.
Suggested focused interfaces, with names illustrative rather than prescribed:
homeworldStatus(publicState)returns native/occupier identity, current threshold side, public force/elite totals, and source-defined public effects. Separate current physical presence from the persisted occupation entitlement for the turn.reservePools(state, player)andquoteForceTransfer(state, intent)define exact normal/elite debits and credits, source location, destination and conservation. Ordinary planet shipment, Guild return, revival, Ghola, No-Field revelation and Emperor transfer must all use this boundary when the module is active.homeworldCapabilities(state, player)returns specific modifiers and eligibility values consumed by existing rule helpers. Avoid a blanketfactionDisabledflag: low, high, occupation and Karama have distinct scopes, and printed Homeworld effects are not cancellable faction response windows.quoteHomeworldShipment(state, intent)returns validated custody/payment/arrival facts and the compulsory successor. Existing shipment prices/contributor bounds and physical elite min/max are reusable components; territory type pricing is not the complete Homeworld rule.quoteCombatLocation(state, location)resolves participants and typed force inventories. Feed its result into existing plan/result arithmetic. Return casualties through location-aware transfer receipts, thenquoteHomeworldAftermathdetermines control/benefit changes without rerunning the battle.homeworldActionOptions(view)contains only public legal locations and the acting seat's entitled quantities/choices. Share these descriptors between bots and controls; keep hidden cards, traitors, predictions and concealed marker values out of the common status object.
Do not derive an automatic public opportunity from a hidden modifier or card holder. Threshold flips, loss of high advantage, unconditional gains and occupation updates are automatic transitions with log/animation receipts, not new confirmation decisions. A genuine source-required allocation, target, transfer or reward choice gets an owned event-bound decision. Automatic follow-on work can pause behind existing responses, Box, Truthtrance, or discard frames without replaying an already committed payment or casualty.
Consumers that must remain location-specific
- Arrakis-only geometry and environment: storm sectors, worms, sandtrout, spice blows, Harvester, Hajr/Ornithopter routes, Fremen reinforcement radius, HMS pointer adjacency, and desert collection. Keep their enumerations planet-only unless a particular printed rule explicitly extends them.
- Planet strongholds: occupation capacity, ornithopter access from Arrakeen/Carthag, stronghold income/cards and copy effects, Ecaz shared desert/bank collection, Ecaz joint-three victory, Moritani Duke qualification, Ambassador placement/entry and Terror placement/entry. A Homeworld may have a source-defined victory effect without inheriting this entire bundle.
- Alliances: formation by Nexus, Moritani Enemy of My Enemy, and the newly implemented Ecaz consent branch must all enforce occupation-based alliance restrictions through shared validation.
finishMovementTurncurrently grants Ecaz permanent cooccupation only overgameTerritories; do not extend that benefit to Homeworlds. Ally shipment funding permission is distinct from permission to land on an ally's Homeworld. - Force returns and removals: ordinary/extra revival, Ghola, disasters, No-Field materialization, Face Dancer replacement, Tleilaxu and Moritani force effects, Ambassador grants, Guild returns and battles. Existing
reserves +=/-=operations must be inventoried against the chosen custody model, including non-normal-phase effects that can cross a threshold immediately. - Sealed commitments: battle plans, Prescience/Voice, Truthtrance battle promises and ordinary shipment promises currently encode territory-oriented destinations/force pools. Homeworld adapters must preserve their established scope rather than silently treating a new destination as an old legal promise. The current structured shipment promise feature is Basic classic only, so Homeworlds do not automatically join that feature.
- Card-specific geography: Harass & Withdraw already documents the own-Homeworld prohibition in
ecaz-cards.ts; implementation must check the battle location's native owner, not a territory name. Other card/leader/faction Homeworld modifications remain source-catalog work. A missing card implementation is not fixed merely by extending the battle location type. - Validation/receipts: board settlement rejects all unknown force keys today; victory/advisor validation enumerates
gameTerritories; multiple cancellation and discard signatures bind current force maps and battle territory. These need the chosen domain explicitly. Never relax canonical board validation globally to admit arbitrary Homeworld-looking strings. - AI and diagnostics: force-conservation checks in the three calibration runners currently assert
reserves + tanks + sum(board forces) === 20. Update them to the canonical physical inventory once, including foreign Homeworld troops and Emperor split pools. Strategic scores need threshold retention, home defense, invasion reward/cost and eligible victory progress rather than applying the Arrakis stronghold bonus indiscriminately.
Coherent delivery sequence
The next production milestone should be a complete Homeworld lifecycle behind the module gate, not a catalog-only or transport-only release.
- Component rules and custody foundation: verify all thirteen card/disc identities and effects; implement optional module state, setup, source-qualified locations, native/foreign typed inventory, occupation receipts and dynamic capabilities. Cover all seated factions and Emperor's two-card case. Preserve old saves and default games unchanged.
- End-to-end invasion and defense: wire source-permitted shipment/Emperor transfer, exact payments and counters, Homeworld battle discovery/choice, existing sealed combat adapters, casualties/replacement/retreat, occupation effects and return routes. Deliver player controls and all four bot levels concurrently. This supplies a playable complete turn rather than accepting arrivals that cannot fight or leave.
- Whole-turn and faction/card integration: route revival/charity/bidding/hand limits and every source-defined high/low reward through capabilities; update thresholds after all custody mutations. Integrate occupation-limited alliances, Karama immunity, conquest rewards and victory. Test interaction families that cross phases and suspended continuations, with location-specific exclusions visible to players.
- Release validation: actual setup-to-endgame simulations, module toggles/prerequisites, source component inventory, human desktop/mobile inspection and controls, 2–6 players/all four AI levels, and production SQLite CAS/recovery for paid invasion, sealed Homeworld battle and control/reward continuation. Enable only configurations whose complete rules and interactions pass; existing unrelated incomplete expansions do not become enabled by this work.
Concrete acceptance cases include native reserve shipment lowering then revival raising a threshold; foreign invasion and complete battle on a Homeworld without storm geometry; occupation entitlement after an invader leaves where the source preserves it; simultaneous reserve depletion and casualty control changes; Emperor mixed shipment and paid-movement internal transfer; rejected ally arrival/alliance; BG fighter-only Homeworld presence; Karama affecting an ordinary faction power while preserving independent Homeworld modifiers; JSON reload between payment and combat aftermath; and duplicate final submissions applying one casualty/reward/occupation receipt.
Findings and limits
There is no reproduced live Homeworld regression: all relevant starts remain gated and no Homeworld action is accepted today. The concrete incompatibilities above are verified code assumptions that would become defects if the module were enabled or Homeworld IDs were appended to planet enumeration without adapters. This audit did not modify state, execute hypothetical effects, run a new game, or claim full source coverage. It makes no decision on unresolved card interactions, Homeworld victory text, concealed No-Field custody, or broader Ecaz combined combat. The source catalog and coordinator's agreed contracts must settle those before the relevant paths are activated.