Implement Homeworld mechanics through Caladan reinforcement checkpoint

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.
This commit is contained in:
Quintine committed 2026-09-10 08:12:26 +10:00
1 parent 3be49512f7
commit 28ba1618ba
266 files changed
+47680 -16851

No files matched your search

+2
View File
@@ -1,5 +1,7 @@
# Component inventory and verification ledger
**Homeworld update, 9 September 2026:** all 13 cards and 26 physical faces are verified, including native population/battle values and occupied income symbols. The internal gallery supplies both faces, complete original gameplay prose, enlarged inspection and thirteen original bundled illustrations. Separate typed custody and population helpers are tested; actual Homeworld gameplay, occupation and effect integration remain unfinished and gated. See [HOMEWORLD_IMPLEMENTATION.md](HOMEWORLD_IMPLEMENTATION.md) and [HOMEWORLD_COMPONENT_AUDIT.md](HOMEWORLD_COMPONENT_AUDIT.md). Earlier missing-Homeworld statements below are historical.
**Auditor update, 7 September 2026:** the separate strength-2 Advanced CHOAM disc and matching traitor are now represented, with one original portrait alongside Duke Prad Vidal in the special registry. Ordinary leader inventory remains 60. Root inspected Auditor at normal and enlarged sizes on desktop and phone; its inspector supplies complete original gameplay prose. Private audited-card faces, payment controls, setup identity, capture/foreign-ghola exclusions and first native revival have focused tests. Repeat/sixth-disc revival cycles and full module combinations remain unresolved. See [CHOAM_AUDITOR.md](CHOAM_AUDITOR.md); earlier missing-Auditor artwork/runtime statements below are historical.
+102
View File
@@ -0,0 +1,102 @@
# Development workflow
Start with [README](../README.md) for installation and saved-game behavior and
[AGENTS.md](../AGENTS.md) for project invariants. This page is a navigation and
verification guide, not a second implementation-status log.
## Architecture map
| Concern | Entry points |
| ---------------------------------- | -------------------------------------------------------------------------------------------------- |
| Authoritative state and actions | `game/engine.ts`: `Game`, `applyAction`, `viewGame`, `normalizeAutomaticGame` |
| Rule validation and calculations | Feature modules in `game/`; `*-quote.ts` modules compute validated outcomes before mutation |
| AI | `game/bots.ts`: `botActions`, `runBots`; `game/bot-*.ts` and shared rule modules |
| Persistence, concurrency, recovery | `db/rooms.ts`; D1 schema in `db/schema.ts`, additive SQL in `drizzle/` |
| HTTP and session boundary | `app/api/rooms/route.ts`, `app/api/rooms/[code]/route.ts`, `app/api/rooms/[code]/control/route.ts` |
| Table UI | `components/game-table.tsx` orchestrates feature components; `app/page.tsx` is the route entry |
| Client request/retry state | `lib/client-request.ts`, `lib/room-entry.ts`, `lib/seat-recovery.ts` |
| Player reference and evidence | `game/reference.ts`, `game/faction-reference.ts`, `app/rules/`; feature docs in `docs/` |
| Tooling | `package.json`, `tools/test.ts`, `tools/test-discovery.ts`, `vite.config.ts` |
For a rule change, locate its helper, engine action/continuation, projected player
view, bot policy, UI and existing tests before editing. Keep server legality
authoritative and reuse helpers across those consumers. Test rejection without
mutation, physical resource conservation, interrupted decisions and saved JSON
restoration where relevant. See `tests/fixture-hand.ts` for physical card fixtures.
## Fast feedback
```sh
# Inspect selection without loading the engine or starting a server.
npm test -- ecaz-collection ecaz-spice --list
# Run related files, optionally narrowing test names.
npm test -- ecaz-collection ecaz-spice
npm test -- ecaz-spice --name 'fallback|conserves'
# Broad offline validation once the change is coherent.
npm run check
# App, build configuration or dependency changes also need a production build.
npm run build
```
| Command | Scope | Live server? |
| -------------------------- | --------------------------------------------------------------------------------- | ------------ |
| `npm test` | All offline tests: rules, bots, client/components, tooling and in-memory recovery | No |
| `npm run test:unit` | Rules, bots, client/components and tooling | No |
| `npm run test:recovery` | In-memory SQLite persistence and recovery | No |
| `npm run test:integration` | Explicitly marked HTTP/session tests | Yes |
| `npm run test:multiplayer` | Recovery plus HTTP tests; preserves the previous command's scope | Yes |
| `npm run test:all` | Every discovered test | Yes |
| `npm run check` | Typecheck, lint, then all offline tests | No |
All test commands accept filename fragments, `--list`, `--name REGEX`, and
`--concurrency NUMBER` after npm's `--`. Filename filters are literal substring
matches, combined with OR; every supplied filter must match its selected suite.
Name patterns are Node test-runner regular expressions and may skip every case,
so check the reported results when using them.
The runner discovers `tests/**/*.test.{ts,tsx,mts,js,mjs}` recursively and sorts
the paths. New offline tests require no manifest entry. HTTP files carry the
first-line annotation `// @dune-suite integration`; in-memory recovery tests
are identified by their single-line `node:sqlite` import. A file referencing
`process.env.DUNE_TEST_URL` without the HTTP annotation fails discovery. Tests
that introduce a different network helper must also carry the HTTP annotation.
The default offline suite includes every test without that annotation regardless
of its unit/recovery classification.
Offline test files run in isolated processes with at most four workers, avoiding
Node's machine-sized default on large hosts. Suites containing HTTP tests default
to one worker to avoid competing for the same development Worker. The launcher
uses `node --import tsx`, which avoids the tsx CLI's extra IPC listener. The exact
tsx version is declared directly and locked for clean installs.
## HTTP testing and stored games
Start the existing development environment with `npm run db:local`, then
`npm run dev`. Reuse a server already serving this checkout. Tests default to
`http://localhost:3000`; `DUNE_TEST_URL` can select a dedicated test server:
```sh
DUNE_TEST_URL=http://localhost:3000 npm run test:integration
```
The runner checks server availability before starting any selected HTTP suite.
HTTP tests create their own rooms in that server's database; use a development
or dedicated test instance. In-memory recovery tests execute production room
code and migrations against disposable SQLite databases and do not touch
`.wrangler/state`. Preserve that directory and existing human games.
## Keeping future changes small
TypeScript keeps incremental metadata under `node_modules/.cache/dune/`; build
outputs and Wrangler state are excluded from typechecking. `*.tsbuildinfo` and
patch backups are ignored. Git history preserves prior source versions.
Use feature docs for rule decisions and evidence, and keep new evidence concise.
The large [implementation status](IMPLEMENTATION_STATUS.md) log contains historical
checkpoints; a previous green count is not proof that the current source passes.
Full AI studies and browser acceptance belong to changes in their respective
behavior, not every edit. Runtime optimizations should follow a measured bottleneck
and retain legality, secrecy and saved-game invariants.
+107
View File
@@ -0,0 +1,107 @@
# Ecaz Ambassador alliance formation
Development checkpoint, 9 September 2026. The reusable Ecaz Ambassador now has
an alliance offer and consent flow alongside direct Duke acquisition. Full Ecaz
and expansion starts remain gated. The optional Duke loan remains unavailable
pending a ruling on its origin, tenure and return destination.
[Publisher evidence and unresolved loan questions](ECAZ_ALLIANCE_RULES.md) and
[the runtime review](ECAZ_ALLIANCE_RUNTIME_READINESS.md) define this boundary.
## Runtime and controls
An actual eligible arrival opens the existing Ecaz-owned Ambassador decision.
When Ecaz and the entrant are both unallied, Ecaz can offer an alliance. Choosing
the offer returns the reusable token to supply immediately without changing the
five random tokens. The entrant alone then accepts or refuses. Acceptance forms
the reciprocal pair, records the current turn, clears obsolete proposals to or
from either participant, and resets Ready. Refusal forms no alliance and grants
no replacement Duke effect. Both outcomes resume the original entrant’s remaining
actions; a worm rider continues its original remaining-ride sequence.
Alliance eligibility uses only public seated identities and alliance links. It
is independent of Duke availability, including the separate Advanced Harkonnen
acquisition gate. The engine does not alter Duke, native leaders, private cards,
spice or committed shipment counters when resolving this alliance. The ordinary
Nexus action retains its phase restriction; the new permission belongs only to
the current Ambassador event.
A pure quote in `game/ecaz-alliance.ts` validates the public roster and produces
the reciprocal links and cleaned offer record. Engine integration binds the
entry’s owner, entrant, turn, phase, returned physical token and reply owner.
The existing arrival-continuation validator also protects worm provenance.
Action, view and automatic-recovery entry points reject orphaned or corrupted
controls. Supported Nullentropy Box and other card suspensions preserve the
reply until their own decisions finish. Room version checks allow only one
competing acceptance/refusal to commit.
The owner sees separate Duke and alliance choices, each with its own availability
reason. The entrant sees explicit accept/refuse controls. Other seats see who
must act. All four AI profiles prefer an available alliance offer, otherwise use
the existing Duke/decline path, and accept valid owned replies. The chronicle
explains token return, consent and continuation; successful formation emits the
existing configurable house-colored automatic notice.
## Coverage checklist
| Area | Evidence | Remaining |
| --- | --- | --- |
| Implementation | Public quote, actual arrival, token commitment, consent, reciprocal links, continuation and saved-control integrity | Optional Duke loan; full faction and module combinations |
| Player controls | Independent blocked reasons, owner offer, entrant accept/refuse, public decision ownership | Full multi-human mobile faction journey |
| AI | All four levels propose/accept via their own projected state; existing Duke fallback tested | Relative negotiation strength and complete expansion games |
| Documentation | Internal Ambassador guide and five-area checklist, source contract, runtime and implementation reports | Loan ruling and complete expansion guidance |
| Verification | 8 pure, 18 engine and 4 production-room SQLite tests; mobile keyboard proposal, real AI acceptance and refresh | Loan lifecycle, full Advanced/expansion acceptance |
The engine tests cover Basic/Advanced actual shipment, either already-allied
participant, unavailable Duke, valid Moritani and BG fighter entrants, BG advisor
exclusion, refusal, private prediction independence, worm continuation, all four
AI levels, genuine paid Box suspension and invalid live/suspended receipts.
SQLite tests use production migrations, authentication and room code. Duplicate
and opposing accept/refuse requests race at the actual compare-and-swap; exactly
one wins. Reload preserves seats and private data, while stale, duplicate and
corrupted commands reject before a write. Unrelated rooms are preserved.
## Browser evidence
Isolated QA room `8S3MRDEK` was backed up at version 126. A staged Advanced
position retained the three authenticated QA seats and used an actual engine
shipment to create version 127’s Ambassador offer. Duke was deliberately in the
Tanks and an Advanced Harkonnen seat was present, so his acquisition remained
unavailable while the alliance action remained enabled.
At 390×844, the browser displayed the distinct actions and availability text,
with visible keyboard focus and no clipped action text. Keyboard Enter submitted
the offer. The Medium AI entrant accepted and made its remaining movement.
Version 132 retained reciprocal Ecaz/Emperor links, the same dead Duke, unchanged
spice, an unchanged random Ambassador cohort and the reusable token in supply.
Refresh restored the alliance. The chronicle contains one offer, one acceptance
and subsequent movement. The normal viewport was restored. This verifies the
owner’s browser flow and AI reply; human reply behavior is covered by engine and
SQL tests, not claimed as a separate authenticated browser session.
All **2,586** pre-existing non-QA room versions and state hashes remained unchanged
before the new HTTP test fixtures. QA snapshots and evidence are local under
`/tmp/dune-ecaz-alliance-qa-*.json` and
`/tmp/dune-ecaz-alliance-browser-evidence.json`.
## Validation status
`npm run check` passed typecheck, lint and **3,058 offline tests**, including all
30 new alliance cases. `npm run build` passed. `npm run test:integration` passed
**40 tests** against the local development server. The independent review found
no remaining concrete defect in the implemented consent flow.
Twenty public-start Basic AI games across two through six players and all four
levels completed **12,186 accepted actions** and **545 JSON round trips** with
zero rejected candidates, stalls or invariant failures. Seed: `20261025`.
Game-source fingerprints stayed unchanged throughout. These homogeneous-level
Basic games check shared-engine regressions; they neither exercise gated Ecaz
starts nor measure relative AI strength.
Logs: `/tmp/dune-ecaz-alliance-check-final.log`,
`/tmp/dune-ecaz-alliance-build-final.log`,
`/tmp/dune-ecaz-alliance-http-final.log`, and
`/tmp/dune-ecaz-alliance-fullgames.json`.
The full goal remains active. No Advanced, expansion or optional-module start
gate was opened. The removed maintenance automation was not recreated.
+68
View File
@@ -0,0 +1,68 @@
# Ecaz Ambassador alliance and Duke control
Primary-source audit, 9 September 2026. Scope: the reusable Ecaz Ambassador’s alliance alternative and subsequent optional Duke transfer. No runtime changes. [Direct acquisition](ECAZ_DUKE_ACQUISITION.md) is already implemented; [Duke lifecycle](DUKE_VIDAL_RULES.md) records separate unresolved custody and revival combinations.
## Source contract
The publisher’s [E3 rulebook pp.7–9](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=7), checked against `/tmp/dune-rules/ecaz-audit.txt`, establishes:
- Ecaz chooses whether to trigger an eligible entry. Advisors, its existing ally and the matching faction cannot trigger the token.
- Direct Duke acquisition and alliance formation are alternatives. Alliance requires “if neither of you are allied and they agree to form an alliance”.
- After that alliance, Ecaz may give the new partner Duke control “for this turn”. This is optional and is not permission for arbitrary standing allied transfers.
- The reusable Ecaz token returns to available supply. It is not one of the five random tokens whose exhaustion replenishes the cohort.
- Ecaz’s acquired Duke lasts until battle use or Moritani takeover. Moritani has one-battle tenure and can qualify again on a later turn.
E3 p.6’s Moritani alliance power is different: it expressly breaks existing alliances. Do not import that permission into the Ecaz token. The Moritani power’s exclusion of Ecaz is also not a prohibition on an unallied Moritani accepting Ecaz’s offer.
## Entry, consent and token commitment
Recommended direct composition of the printed trigger and consent rules:
| Point | Authoritative result |
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Ecaz declines to trigger | Leave the placed token and Duke unchanged; resume entry. |
| Ecaz chooses direct acquisition | Apply that separately validated effect; no alliance offer follows automatically. |
| Ecaz chooses alliance | Commit this trigger and return the reusable token to supply; record the entrant-owned consent decision. Do not acquire Duke merely because the offer was made. |
| Entrant refuses | Neither alliance nor Duke control changes. Resume the original entry. |
| Entrant accepts | Establish the reciprocal alliance, then resolve Ecaz’s optional Duke-control choice if available, then resume entry. |
The token-return sentence is not conditioned on successful consent. There is no retrieved refusal exception restoring the token to its former stronghold, reopening the direct-acquisition choice or refunding placement. Returning the token when the offer is declared follows the existing trigger/commit model; it must remain returned through a saved pending reply. This is a composition of the general trigger and specific return instructions, not a separate publisher worked example.
Consent is needed from the actual entering faction; Ecaz cannot answer for it. Both parties must still be unallied at commitment. This branch grants no new Nexus, phase transition or extra movement. Preserve the triggering movement, worm ride or nested arrival’s continuation. The alliance is immediate rather than deferred to the next Nexus; subsequent effects must consult the new relation without replaying the completed arrival.
**Duke availability is not an alliance prerequisite.** The alternative can form an alliance while Duke is dead, elsewhere, concealed or otherwise unavailable. Such states may remove the optional transfer choice, but must not expose private custody through the availability of the alliance itself. A successful alliance with no loan leaves the shared disc exactly where it was.
## Existing alliance rules that still apply
[Base p.12](https://www.gf9games.com/dunegame/wp-content/uploads/Dune-Rulebook.pdf#page=12) requires public alliances, limits each player to one partner and grants only the stated shared advantages. Acceptance should announce both factions, update both links together and invalidate superseded offers. It does not transfer hands, expose private spice or change other players’ alliances. Ordinary breakup remains a Nexus action unless another specific power permits it. Ecaz Occupy subsequently handles legal co-occupation; formation does not merge physical force owners.
**Bene Gesserit:** a fighter can be the eligible entrant; an advisor cannot. An alliance does not flip its other advisors, unlock a current-turn stance restriction, reveal/reset prediction or transfer prediction ownership. Base p.18 keeps prediction secret and permits it to win against an allied faction too. Shared occupation and the new three-stronghold win must retain that existing prediction precedence. [Base p.18](https://www.gf9games.com/dunegame/wp-content/uploads/Dune-Rulebook.pdf#page=18)
**Fremen:** an eligible worm-riding entrant can consent through the same interruption. No alliance-specific territorial exclusion is printed for this choice. Formation does not itself replay a worm, refund losses or create another ride. Keep established Fremen alliance protection and victory predicates separate; this task does not settle the previously identified Fremen victory combinations.
**No-Field and optional modules:** an unrevealed marker remains a force under [E2 p.10](https://www.gf9games.com/dune/wp-content/uploads/2021/11/CHOAM-Rulebook-low-res.pdf#page=10), so do not inspect its hidden value to determine faction consent. If the Nexus-card module is enabled, E3 p.10 requires a held Nexus card to be discarded before entering an alliance; that is a real future integration obligation, not permission to turn on the unfinished module. Homeworlds are not ordinary Ambassador destinations.
## Duke transfer: established limits and genuine gaps
The transfer must use the existing unique Ecaz-identity disc, preserving death history and `usedAt`. It does not manufacture a native sixth leader or a Traitor card. Dead Duke cannot be made playable through an alliance; revival remains separate. The printed grant is a time-limited control transfer, not a change of native faction.
Moritani’s p.6 acquisition can take Duke from a current controller when its own end-of-movement conditions are met. A normal living loan therefore cannot silently immunize Duke against that later power. A takeover must supersede the earlier loan receipt so its later expiry cannot steal Duke back from the new controller. Captured/concealed and ghola combinations retain the existing material custody boundary.
| Unresolved point | Why it changes actual play |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Origin of the optional transfer | The alliance sentence does not explicitly require prior Ecaz control, nor does it say the alliance alternative first acquires an available set-aside or Moritani-held Duke. Requiring prior control and permitting direct assignment produce different available choices. |
| Unused loan expiry | The turn limit ends the ally’s permission, but the paragraph names neither Ecaz nor the set-aside pool as the destination. Returning to a previous controller is a third, distinct policy. |
| Battle use during the loan | Ecaz and Moritani have explicit battle-use tenure. The ally clause states a turn duration; it does not expressly settle whether loan use consumes Duke’s temporary tenure or only follows ordinary same-territory leader-use restrictions. |
| Alliance broken during the loan | Its permission is created by acceptance, but the text does not explicitly say whether a subsequent legal breakup terminates that permission immediately. |
These are the existing loan/custody questions, not newly asserted prohibitions. They should be resolved together as a coherent loan lifecycle before activating transfer. Preserve the previous unresolved revival and Harkonnen capture rulings; nothing about a consensual alliance decides them.
## Cancellation and implementation boundary
The E3 p.16 Ambassador row prevents placement for the turn; it does not list cancellation of an already triggered alliance effect. Its separate Moritani Enemy of My Enemy row is not an Ecaz response. Do not add a generic cancellation window merely because the new decision forms an alliance. Existing printed/BG conversion machinery remains relevant only to an actually specified cancelable opportunity.
The substantial implementable branch is the complete reusable-token consent lifecycle across genuine arrivals: owner choice, token return, entrant acceptance/refusal, immediate public reciprocal alliance, private-safe descriptors, saved continuation and all AI profiles. Preserve pending consent through disconnects and reject duplicate/stale replies before any token or alliance mutation. Tests should cover either participant already allied, a valid Moritani partner, BG fighter versus advisor, Fremen worm entry, unavailable Duke with successful no-loan alliance, refusal, and subsequent Occupy movement/collection/victory. Optional Duke control needs the explicit lifecycle ruling above; exposing it with an invented expiry would not complete the feature.
## Fresh clarification search and provenance limits
Official GF9 indexed p.9 was retrieved again and agrees with the local Duke paragraph. [Future Pastimes’ expansion page](https://futurepastimes.com/dune-ecaz-moritani) corroborates the faction’s alliance purpose but supplies no loan endpoint. Public metadata verifies Jack Reda – Future Pastimes Games as the author of [Alliance antics with Ecaz and Moritani](https://www.youtube.com/watch?v=jSiGgD2k3sI); the caption request returned no transcript, so this audit attributes no spoken ruling to it. The indexed [Duke Vidal recap](https://boardgamegeek.com/thread/3626139/duke-vidal-recap) returned only a title/loading shell. No retrievable, author-verified designer answer resolved the loan cases. Community summaries, search snippets without author boundaries and the known misattributed Occupy-rounding comment were not used as errata.
+45
View File
@@ -0,0 +1,45 @@
# Reusable Ecaz Ambassador alliance readiness
Read-only architecture audit, 9 September 2026. This records the contract before the alliance branch is integrated. It does not claim optional Duke loans, full Occupy combat or complete Ecaz mode support. Rules authority is being independently reviewed; existing provenance is in [Ambassadors](ECAZ_AMBASSADORS_RULES.md) and [Duke Vidal](DUKE_VIDAL_RULES.md).
## Source-confirmed branch and existing entry
The source reviewer verified E3 p.7: both Ecaz and the entrant must be unallied, and the entrant must consent. Direct Duke acquisition and alliance formation are different alternatives. Duke availability is not a prerequisite for forming an alliance without a loan. BG prediction remains private and unchanged; advisor entry cannot trigger the token. The reusable Ecaz token returns to supply when triggered and never joins or completes the five-token random cohort.
The existing producer near `engine.ts:6534` already establishes the owner, entrant, physical placed token, territory/sector, turn/phase and event, and pauses remaining actions. `finishAmbassador` near 6602 clears that receipt and resumes a saved worm ride exactly once. A Guild Ambassador's final BG accompaniment can transfer its outer continuation to a new Ambassador entry near 7280; preserve its `wormRider` and `guildAdvisorOrigin`, rather than replaying the completed Guild shipment.
Current `decideAmbassador` near 7708 only accepts `choice:'duke'` for the Ecaz token. More importantly, `ambassadorEffectBlock('ecaz')` near 6501 applies the direct Duke gate before choice dispatch. That must be separated: a dead/captured/ghola Duke, same-controller direct-acquisition boundary, or Advanced Harkonnen must not disable an otherwise supported no-loan alliance.
## Reuse alliance mechanics without importing Moritani's rule
`formTerrorAlliance` near `engine.ts:8060` breaks old alliances, refunds touched aid, removes obsolete alliance offers, links the pair, stamps `allySinceTurn` and clears Ready. Its consent stage is useful precedent, but its permission to break existing pairs and refusal-triggered Terror effect are specific to Moritani. The Ecaz branch requires two currently unallied players and must reject before spending the token if either is already allied.
The ordinary Nexus action near 15960 also links reciprocal IDs, stamps the current turn and clears Ready. Its phase restriction must remain intact; the Ambassador is a separate authorized source, not a general relaxation of Nexus timing. A small shared reciprocal-link transaction can serve both special sources after each source validates its own prerequisites. Clear offers involving either new member so an older offer cannot later create a conflicting pair. Validate rather than silently redirect stale escrow. Any actual refund must use the existing safe resource quote and pay its original donor once.
Allied movement, shared collection, victory and faction benefits mostly derive from current reciprocal IDs. Preserve those dynamic consumers. Stamp both `allySinceTurn` fields so existing departure deadlines remain consistent; Ecaz Occupy then permits supported territorial coexistence. Do not clear private hands, BG prediction, paid shipments, movement counters, battle history, traitors or source-bound card reservations as an alliance side effect. Existing promise reconciliation should run after the accepted action; do not manufacture new answers or expose a partner's private commitments.
## Agreed finite API
At the existing owned offer, `{type:'decision', event, trigger:true, choice:'alliance', beneficiary:owner}` validates the actual entry and both unallied identities before calling `triggerAmbassador`. It returns the token to supply immediately and records `effect:'ecaz'`, `stage:'allianceReply'`, `beneficiary:entrant`; the new `ecazAmbassador` decision belongs to the entrant.
The entrant sends `{type:'decision', event, accept:boolean}`. Require the exact boolean and original event. Acceptance revalidates the two unallied identities, forms the pair, clears obsolete offers/Ready, then finishes the Ambassador continuation. Refusal finishes without an alliance, Duke acquisition, fallback effect or token restoration. The latter is the coordinator's composition of committed trigger plus refusal; it is not a retrieved publisher rollback sentence. Declining the original **trigger** still leaves the placed token intact.
The existing generic decision-owner check must explicitly handle `allianceReply`; do not accidentally authorize every later Ecaz stage by the direct-acquisition beneficiary rule. On a saved reply the physical token is now in supply, so validation must distinguish the committed token from the still-placed offer. Bind owner/faction, entrant, effect, stage, source event, turn/phase and continuation. Reject orphaned live or suspended controls as well as mismatched events. No new generic Ambassador Karama response is introduced by this contract; Moritani's alliance cancellation is not authority to add one here.
Nullentropy Box and other supported decision suspensions should retain the complete reply and restore it after their own event finishes. Use the existing saved-control pattern and normalizer/CAS, not another entry event or rollback copy of the game. Test the ordinary phase-five continuation and actual phase-one worm suffix separately.
## Duke loan remains a separate material boundary
`game/duke-vidal.ts` has `source:'ally'`, but that tag is not an implemented loan lifecycle. `expireDuke` releases only unused Moritani tenure; its existing test explicitly preserves unresolved allied tenure. `consumeDuke` always clears controller/source, and actual battle resolution near `engine.ts:11063` calls it when Duke appeared in either plan. Residual Poison also releases his control after death near 9451.
`controlledLeaders` near 9510 and the player projection near 17816 already make the same physical disc available to its controller, subject to exceptional capture/ghola/Advanced-Harkonnen gates. Reusing those consumers is appropriate only after loan expiry, unused return destination and battle-use return are source-resolved. Preserve disc identity, death history and `usedAt`; neither a loan nor a return should grant a second battle use automatically. Ordinary Ecaz tenure persists, Moritani can supersede it, and revival/capture rules retain their separate gates.
The current agreed alliance branch changes **no Duke state**. Optional loan controls remain explicitly unfinished until authoritative return behavior is settled. This still delivers a complete consent-based alliance alternative, including its entry, token, aftermath, UI, AI and recovery behavior.
## Public controls, AI and evidence
Project owner-offer `allianceOffer:{blocked:string|null}` independently from `dukeAcquisition`. Eligibility depends on public identities and entry facts, not hidden Duke custody. Show a distinct alliance action, the existing direct-acquisition action and leave-in-place action. The entrant sees accept/refuse with the actual inviter and territory; everyone else sees who must respond. No confirmation is needed after an accepted automatic link or token return.
All four AI profiles can propose when the authoritative descriptor permits it, otherwise retain direct-Duke/decline behavior, and accept a valid owned reply. They receive no rival prediction, hand or balance through this path. Later negotiation strategy can differ without changing legality or inventing a Duke loan.
Focused evidence should use actual shipment and worm entry; assert both decision owners, immutable rejection of stale/malformed/foreign actions, both existing-alliance exclusions, exact token/cohort conservation, no Duke changes even when Duke is unavailable, accepted/refused continuation, private prediction invariance, actual Box suspension and JSON recovery, and all four AI policies. Production room CAS races belong to the coordinator's separate recovery tests. Keep unrelated expansion release gates in place.
+95
View File
@@ -0,0 +1,95 @@
# Ecaz shared spice collection
Verified development checkpoint, 9 September 2026. This completes the bounded
shared-collection flow; complete Ecaz, Advanced and expansion starts remain gated.
The [source contract](ECAZ_COLLECTION_RULES.md) records publisher precedence and
sector-capacity interpretation. The earlier
[runtime readiness review](ECAZ_COLLECTION_RUNTIME_READINESS.md) is a design
proposal; the implemented commitment order below supersedes its deferred-payment
proposal.
## Implemented behavior
The engine computes each collecting faction’s eligible sector capacity before
extracting spice. When both Ecaz and its reciprocal ally collect from the same
desert territory, their combined extraction becomes one shared pool. The board
loses that spice once. Ordinary collection and bank income settle automatically;
shared spice is held outside both players’ balances until allocated.
Ecaz proposes first as an interface convention. The other ally can accept or
counter. Either current decision owner can use the equal split, with odd spice
going to the ally. Each settled territory has one persisted receipt. Unaccepted
proposals are visible only to the pair; the chronicle records final allocations
and their reason. Empty pools create no confirmation.
Advanced co-occupied Arrakeen, Carthag and Tuek’s Sietch pay both allies their
normal bank income. A meaningful Karama window precedes that commitment.
Cancellation removes only Ecaz’s income from those shared strongholds. Printed
Karama and Bene Gesserit Worthless conversion preserve the same source and effect.
No available blocker means automatic continuation.
Pending events bind their turn, public collecting forces, original deposits,
allocation index and settled receipts. Actions, player views and automatic
recovery reject missing or falsely completed collection parents, including
controls suspended by Nullentropy Box and Karama conversion. Legitimate card
income during allocation is retained: settlement adds to the current balance.
Room version checks prevent simultaneous or stale acceptance from paying twice.
## Coverage checklist
| Area | Verified boundary | Evidence |
| --- | --- | --- |
| Implementation | Sector capacities, one pool per desert, ordinary/bank commitment, bilateral allocation, scoped cancellation, recovery integrity | `game/board-resolution-quote.ts`, `game/ecaz-spice-allocation.ts`, `game/engine.ts` |
| Player controls | Private proposal/counteroffer/acceptance, equal fallback, decision ownership, mobile controls, keyboard completion, refresh | `components/ecaz-spice.tsx`, `components/game-table.tsx` |
| AI | All four profiles use the equal fallback or accept a fair offer without consulting rival balances | `game/bots.ts`, `tests/ecaz-collection-engine.test.ts` |
| Documentation | Internal phase and faction guidance, source precedence, commitment order and explicit release limits | `game/reference.ts`, this document and the linked source contract |
| Verification | Pure, engine, interruption, privacy and SQLite concurrency/recovery cases; real browser allocation | Four collection test files listed below |
## Verification
`npm run check` passed typecheck, lint and **3,028 offline tests**, including the
user’s test-discovery and failure-propagation self-tests. `npm run build` passed.
`npm run test:integration` passed **40 tests** against the local development
server. These suites have different scopes; historical counts used the previous
manual test registration and are not directly comparable.
The focused collection coverage is **60 tests**:
- `tests/ecaz-collection-quote.test.ts`: 20 capacity and income cases.
- `tests/ecaz-spice-allocation.test.ts`: 11 protocol cases.
- `tests/ecaz-collection-engine.test.ts`: 26 actual transition, privacy, AI,
cancellation and suspended-parent recovery cases.
- `tests/ecaz-collection-recovery.test.ts`: 3 SQLite scenarios, including racing
proposals/acceptance, printed and converted cancellation, reconnect and secrecy.
The browser resumed the isolated three-seat QA room `8S3MRDEK`. Actual last
movement entered Advanced collection, paid bank income automatically and opened
the five-spice Hagga Basin allocation. The Medium AI ally accepted the 2/3 split.
Refresh restored the six-spice Wind Pass choice; keyboard navigation and Enter
selected its 3/3 equal split. At a 390×844 viewport, controls were readable,
44 pixels tall, visibly focused and free of horizontal overflow. The normal
viewport was restored afterward. Room version 126 retained two receipts, one
spice on Wind Pass and total balance changes of +7 Ecaz, +8 ally and zero rival.
All **2,556** pre-existing non-QA room versions and state hashes were unchanged.
This staged position verifies the interaction, not a complete expansion game.
Twenty ordinary production-AI Basic games, spanning two through six players and
all four levels, completed **10,206 accepted actions** and **465 JSON round trips**
with zero rejected candidates, stalls or invariant failures. Seed: `20261024`.
Source fingerprints stayed unchanged during the run. These games cannot exercise
Ecaz because expansion starts remain gated, and homogeneous-level games do not
measure the relative strength of the levels.
Local logs: `/tmp/dune-collection-sep09-check-verified.log`,
`/tmp/dune-collection-sep09-build-final.log`,
`/tmp/dune-collection-sep09-http.log`,
`/tmp/dune-collection-sep09-fullgames.json`, and
`/tmp/dune-collection-sep09-browser-evidence.json`.
## Remaining release gates
Combined Occupy combat and its source discrepancy, Fremen’s Ecaz endgame
exception, Tleilaxu Ambassador runtime, remaining Duke interactions, complete
Advanced/expansion/module games and broader presentation acceptance remain
unfinished. This checkpoint enables none of those modes. The maintenance
automation remains removed.
+169
View File
@@ -0,0 +1,169 @@
# Ecaz poison-discard income
Audit: 9 September 2026. This covers high Ecaz's card-discard income, not its
Homeworld victory condition or a complete Ecaz release.
## Source contract
The original Ecaz high face was visually rechecked in
[BGG component photograph 7767034](https://boardgamegeek.com/image/7767034/dune-ecaz-and-moritani)
(`/tmp/dune-card-economy-homeworlds.jpg`). At native population 7–20, it awards
three bank spice for each discarded poison weapon. It does not restrict the
discarding faction, phase, location, reason or number of awards. Consequently,
Ecaz's own discards qualify too; a two-card qualifying batch pays six. The
wording makes collection automatic, with no separate optional claim.
[GF9 E3, pp.9–10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=9)
makes high eligibility depend on current native reserves and protects Homeworld
advantages and penalties from Karama. Check Ecaz's own Homeworld at the actual
discard event. An ally's reserves or foreign visitors do not supply its native
threshold. Neither merely playing Ecaz nor selecting Advanced rules activates
the Homeworld module. Occupation lifecycle questions remain documented in
[Homeworld rules](HOMEWORLD_RULES.md).
The [November GF9 FAQ, pp.3–5,8](https://www.gf9games.com/dune/wp-content/uploads/2020/11/Dune-FAQ-Nov-2020.pdf)
clarifies generic weapon categories for special cards, Chemistry's conditional
role, and unused Poison Tooth disposal. The
[E2 rulebook, p.9](https://www.gf9games.com/dune/wp-content/uploads/2021/11/CHOAM-Rulebook-low-res.pdf#page=9)
independently requires Chemistry to be played as a weapon for the poison-weapon
Leader Skill bonus. These indexed publisher passages were freshly retrieved;
direct PDF endpoints remain unavailable. No specific Ecaz/Chemistry worked
example was retrieved, so composing the actual played role with the discard
trigger is an explicit interpretation from those category rules.
## Classification
| Physical card / runtime kind | Qualifies when actually discarded? |
| --- | --- |
| Chaumas, Chaumurky, Gom Jabbar, Ellaca Drug; Basilia Weapon (`poison`) | Yes, including unused hand disposal or a cost. |
| Poison Blade (`poisonBlade`) | Yes: its generic attack categories include poison and projectile. One card still produces one award. |
| Poison Tooth (`poisonTooth`) | Yes: poison weapon, including an unused Tooth that must nevertheless be discarded. Activation changes its attack, not its category. A retained Tooth produces no discard award. |
| Chemistry (`chemistry`) | Yes when discarded from its actual weapon slot, with the already validated complementary defense. No when used as defense or discarded directly from hand. Potential weapon use is insufficient. |
| Shield Snooper, Snooper, Portable Snooper | No: poison defenses are not poison weapons. |
| Artillery Strike, Lasgun, Stone Burner, projectile weapons, Weirding Way | No: killing a leader does not make a card a poison weapon. |
| Residual Poison | No: its verified physical card is Special, with a pre-leader effect, not a poison battle weapon. The name alone supplies no category. See [Richese component audit](RICHESE_COMPONENTS.md). |
| Worthless, Cheap Hero, ordinary special cards | No, even if occupying a weapon slot. |
| Mirror Weapon | Direct hand disposal: no. A played copy uses its retained actual copied weapon category, including poison, Blade, Tooth or weapon Chemistry. No opposing weapon gives no poison category. Existing Mirror activation/retention work remains separate. |
The Chemistry distinction must use the plan slot at disposal, before battle
cleanup loses that information. In particular, winner optional disposal and
Moritani retention occur after the engine clears `g.battle`; they need an
event-bound retained role receipt rather than consulting a missing plan. Do not call `weaponTypes(card)` on every card:
that helper assumes a weapon role and would incorrectly classify hand or
defense Chemistry. Do not rewrite a physical card's stored kind to its battle
role. Generic printed poison/Blade/Tooth discards do not require a battle.
These classifications apply equally to mandatory cleanup, voluntary winning
card disposal, hand reduction, exchange costs, CHOAM cash-in or Ambassador
effects, and paid Kaitain disposal. Merely returning an unsold lot to the deck,
transferring a card between hands, recovering a discard, reshuffling the old
discard pile or removing a card from the game is not a new discard.
## Battle cleanup timing
The [GF9 base rulebook, p.11](https://www.gf9games.com/dunegame/wp-content/uploads/Dune-Rulebook.pdf#page=11)
describes losing cleanup (all losing forces and played cards) before winning
cleanup (dialed force losses, then card retention/disposal). The
[official Quick Start, p.11](https://www.gf9games.com/dunegame/wp-content/uploads/Quick-start-Guide.pdf#page=11)
uses the same order in its worked battle. These publisher-indexed passages
support the existing losing-discard-before-winner-casualties sequence; they do
not number smaller simultaneous timing steps. Accordingly, native Ecaz winning
with seven reserves can receive losing-poison income while still high, then
fall to six when its own dialed losses are removed. Its subsequent winning-card
discards use that new low population. E3's continuous threshold rule supplies
the immediate change; no contrary E3 cleanup rule was retrieved.
The original E1 Poison Tooth face was freshly inspected in
[component photograph 5495302](https://boardgamegeek.com/image/5495302/dune-ixians-and-tleilaxu)
(`/tmp/dune-ix-cards.jpg`). It permits declining the weapon after seeing battle
results and contains no physical-discard instruction. The November FAQ, p.8,
requires a used winning Tooth to be discarded, through its winner/loser
retention answer; it does not instruct discarding upon activation. E2, p.4,
replaces this original face. Retrieval of the revised physical face remains
incomplete, so it cannot be cited as granting an earlier disposal event.
The source-based implementation recommendation is therefore to retain losing
card disposal in losing cleanup, and apply a winning used Tooth's mandatory
disposal after winner casualties, alongside winning-card cleanup. This is a
composition of the published cleanup order and the FAQ retention exception,
not an explicit Ecaz/Tooth worked ruling. Selecting Tooth activation alone is
not a physical discard: a subsequent successful traitor declaration still
overrides ordinary weapon resolution. Do not manufacture a new activation-time
discard or snapshot the battle's starting population for later disposal.
## Pure API and engine responsibilities
`game/ecaz-poison-income.ts` exports:
```ts
type EcazPoisonDiscard = {
card: Card;
battleSlot?: 'weapon' | 'defense' | 'leader';
effectiveWeapon?: EffectiveWeapon; // retained validated Mirror copy
};
quoteEcazPoisonIncome(context, discarded)
// => { player, amount, count } | null
```
The context is the Game subset `advanced`, `players`, `homeworlds`. The quote
uses public native custody and discarded physical descriptors; it does not read
hands, spice balances, opponents' plans or discarded-by identity. It validates
unique physical IDs and supplied slot values. For a played Mirror, the caller supplies its retained
`resolveBattleWeapons` descriptor. A missing or conflicting descriptor raises
`EcazPoisonIncomeError` as an integrity failure. The
[Mirror source audit](MIRROR_WEAPON_ENGINE_AUDIT.md) establishes actual-role
copying; applying that role to this discard trigger is source composition,
not a separate new ruling. The earlier unanswered question about mandatory
physical disposal after copying Tooth/Artillery concerns whether a discard
occurs, not what category its already established copy has. A recovered poison may later be
discarded again and earn again: deduplication belongs to the particular event,
not a permanent set of rewarded card IDs.
The engine must prove the cards genuinely cross into discard custody, obtain
the actual prior battle slots, pay exactly once, and preserve that payment
through JSON/CAS and any fresh-discard continuation. Quote before mutation;
commit the physical transition and its income in the same transaction. Do not
pay again when merely resuming `pendingTreacheryDiscard`. The quote's current
population must correspond to that actual event; neither a phase-start snapshot
nor a later reconstruction after unrelated force changes is equivalent.
Use the existing visibility of each source discard. A private discard remains
private; do not expose card IDs/names or change `publicFace: false` to publish the
income. Current game logs are globally projected. Any added public income
message must be reviewed for revealing a private discarded card's category;
private account evidence is preferable where the source keeps its face secret.
## Physical mutation audit
At this audit, `rg` found these direct engine mutations:
| Location | Meaning / integration requirement |
| --- | --- |
| `discard(g,p,id)` | Central hand-to-pile transition; covers battle cleanup, gifts' disposal costs, sales, cash-in, Ambassador/terror discards and ordinary card play. Preserve plan slot before cleanup. |
| `finishNullentropy`: `g.discard = result.discard` | Removes the recovered target, shuffles old cards and appends the used Box. Only the Box is freshly discarded; recovering a poison or moving old poison within the pile earns nothing. |
| `finishOrnithopter`: `g.discard.push(flight.card)` | Played-card-to-pile transition; Ornithopter itself does not qualify. |
| Distrans action: `g.discard.push(result.discarded)` | Only played Distrans is discarded; the transferred card is not. |
| `draw`: `g.discard = []` | Reshuffle into the deck, not fresh disposal. |
| `newGame`: `discard: []` | Initialization, not disposal. |
| Guild cancellation: `g.discard.splice(...)` | Retrieves a previously spent rate card; no new discard or refund of prior Ecaz income. |
`stageTreacheryDiscard` and `finishTreacheryDiscard` preserve receipts and resume
effects; they are not additional physical transfers. Existing `discard()` had
no Ecaz income hook when this audit began. No other direct `.discard.push` or
`.discard =` mutation was found in `game/`. The battle-resolution quote returns
card-ID disposal instructions; its engine adapter executes them through
`discard()`. Winner cleanup and Moritani retention also use that helper.
`resolveNullentropyBox` and inactive `resolveSemuta` construct detached discard
arrays; Box is accounted for above, while future Semuta integration must not
re-award a recovered poison. Generic hand-transfer helpers move cards without
discarding the transferred identity.
## Verification
Eight focused tests in `tests/ecaz-poison-income.test.ts` pass. They cover all
seven qualifying physical cards in the currently assembled base+Ix inventory,
both game modes, conditional Chemistry, all remaining current card kinds,
exact threshold and module-off behavior, foreign visitors, private-access
traps, JSON stability, malformed/duplicate receipts and actual Mirror-copy descriptors.
Run `npm test -- ecaz-poison-income`. These are pure-quote tests; engine timing,
income visibility and multiplayer recovery need separate integration evidence.
+27
View File
@@ -0,0 +1,27 @@
# Guild transport from Arrakis to Homeworlds
9 September 2026. Fresh primary-source audit for the next transport integration. This supplements [the transport source update](HOMEWORLD_TRANSPORT_SOURCE_UPDATE.md); it does not resolve the already recorded Junction payment, foreign-garrison departure, or ordinary Karama timing questions.
## Route and custody contract
E3 permits Guild shipment from Arrakis to a Homeworld and classifies it as cross-shipment. Guild can return to its own Junction or invade another native faction's world; an allied destination is forbidden. Guild's ordinary alliance grant does not supply this new route to its ally. Junction's separate high-face permission has its own provenance. [GF9 E3, p.10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=10), [component audit](HOMEWORLD_COMPONENT_AUDIT.md#verified-high-side-effects).
The implementable tariff is `ceil(physicalCounters / 2)` for Guild. This composes E3's one-spice-per-force Homeworld tariff with its Guild half-price clause; the paragraph does not give a separate Arrakis-origin worked example. For return to Junction, the base reserve-return price independently produces the same result. Do not use the two-spice non-stronghold territory tariff for a Homeworld. [GF9 E3, p.10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=10), [GF9 base, pp.19,23](https://www.gf9games.com/dunegame/wp-content/uploads/Dune-Rulebook.pdf#page=19).
The base Guild alternatives use the faction's single shipment and start in one territory. Its Q&A expressly allows counters distributed among sectors of that territory to ship together. Preserve exact typed source groups; reject combining different territories. The Storm Obstruction rule prevents departure of counters under storm. It supplies no exception for Guild cross-shipping; do not reject an entire partly covered territory when the selected counters are outside storm. [GF9 base, pp.7,19,22](https://www.qugs.org/rules/r283355.pdf#page=7).
The Hidden Mobile Stronghold is independently protected from storms. Its interior is the source when shipping out; its pointer locates its ordinary-board entrance. Do not substitute the pointer's storm-covered sector for the protected interior. This follows the printed protection, rather than a dedicated Guild-departure FAQ example. [GF9 E1, p.9](https://www.gf9games.com/dunegame/wp-content/uploads/2020/09/IxianAndTleilaxuRulebook.pdf#page=9).
## Distinct card interactions
Guild's special Karama names an off-planet shipment of any player. It does not say that the origin must be off Arrakis, or prohibit choosing Guild itself. A physical Arrakis-to-another-world shipment fits the interplanetary predicate used in the preceding audit; this is source composition, not a new explicit FAQ example. Preserve the existing optional owned response when Guild holds the card, including its own shipment. Never use an Arrakis-origin flag as blanket special-interception immunity. [GF9 base, p.14](https://www.gf9games.com/dunegame/wp-content/uploads/Dune-Rulebook.pdf#page=14).
Ordinary Karama has separate targets for Guild transport permission, its half-price benefit, and payment income. E1's reference prohibits cross/return transport when the Three Types advantage is canceled; it separately removes the discount. E3's immunity protects Homeworld face effects, including Junction's granted permission, without turning Guild's ordinary transport advantage into a face effect. Keep those sources separate. This audit does not choose a new announcement, repricing, or affordability policy for [the pending timing questions](GUILD_RATE_KARAMA_RULES.md#material-unresolved-timing). [GF9 E1, p.12](https://www.gf9games.com/dunegame/wp-content/uploads/2020/09/IxianAndTleilaxuRulebook.pdf#page=12), [GF9 E3, p.10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=10).
## Technology and payment
E3's FAQ confirms Heighliner activation for shipment **to** a Homeworld, without restricting the origin or requiring a foreign destination. Preserve E1's exception when Guild is the only qualifying shipper. Thus Guild's own Junction return or invasion alone earns no Heighliner income; a future non-Guild Junction-sponsored shipment to a Homeworld qualifies. Settlement activates the token once for the phase, rather than awarding spice per transported counter. [GF9 E3, p.15](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=15), [GF9 E1, p.5](https://www.gf9games.com/dunegame/wp-content/uploads/2020/09/IxianAndTleilaxuRulebook.pdf#page=5).
Retain the [contributor-specific payment contract](GUILD_SHIPMENT_PAYMENTS.md#publisher-contract-and-precedence). The shipper's personal fee for this route goes to the bank; any non-Guild ally contribution follows the independently recorded November funding rule. Funds, custody, typed totals, shipment usage, and technology remain unchanged until a valid settlement. No sector, territorial entry effect, or stronghold occupancy cap applies to the Homeworld destination.
Validation: freshly retrieved publisher-indexed E3 pp.10/15 and E1 pp.5/9/12, plus base pp.14/19/22. Direct publisher PDF requests failed; the accessible base mirror contains the publisher-authored 24-page rulebook. Fan compilations and tournament rules were excluded. Local document links reviewed; no runtime, saved game, or automation changed by this audit.
+25
View File
@@ -0,0 +1,25 @@
# Guild transport from Arrakis to Homeworlds
9 September 2026. [Source contract](GUILD_HOMEWORLD_TRANSPORT_RULES.md). This extends the existing [world-to-world shipment runtime](HOMEWORLD_SHIPMENT_RUNTIME.md); Homeworld starts remain disabled pending the complete module.
## Implemented behavior
Guild can ship physical forces from one Arrakis territory to a foreign Homeworld or return them to Junction. Several sectors of that same territory may contribute. The quote rejects mixed territories, invented sector spellings, unavailable counters, storm-covered source sectors, non-Guild users and allied Homeworld destinations. The Hidden Mobile Stronghold has its existing protected interior; its ordinary board pointer does not turn its forces into an exposed storm sector.
The tariff is one spice per two physical counters, rounded up. Native returns credit Junction's reserves; invasions create an explicit foreign pool. Both remove exactly the selected Arrakis counters and preserve the other groups, Tanks and physical special-force inventory. No Homeworld receives a fake sector, board geometry or territorial arrival effect.
The route consumes shipment and retains movement. Guild's printed Heighliner exception remains in force. A non-Guild ally's pledged contribution follows the existing November funding rule, separately from the Guild shipper's bank payment; no receipt can fund its own shipment.
The same event-bound declaration and Guild special-interception machinery serves both interplanetary routes. The new route explicitly freezes the shipper's board pools, storm and active mobile pointer as well as world custody, alliances, turn, cost and funding. The optional self-interception follows the source's unrestricted player predicate. With no legal stop it continues automatically. A real choice remains actionable, including after a paid Box interruption. The previously documented provisional stopped-shipment settlement and ordinary cancellation questions remain unresolved.
The existing `guildShip` return-to-reserves API and its Homeworld destination form now pass through this same declaration when Homeworlds are active. They cannot bypass the new custody, funding, interception or source validation. Other modes retain their prior route handling.
## Controls, AI and verification
The Guild's table has a separate Arrakis-source transport panel with explicit accessible names, sector quantities, storm guidance, Junction/foreign destinations and a shared payment quote. All four AI profiles use that quote through their own public view, consider native defense and existing invasions, retain useful defenders/collectors and preserve normal movement alternatives. Rival private resources and concealed counters do not enter this adapter.
Pure, actual-engine, all-profile, rendering and production SQLite tests cover route legality, costs, source custody, genuine setup, old API parity, interruptions, competing requests, corrupt saved receipts and private projection. Source staging used by special tests is identified in the tests; it does not substitute for complete module games.
Final `npm run check` passes types, lint and all **3,340 offline cases**, including 36 new Guild transport regressions; the production build and **40 HTTP cases** also pass. Independent review found no further defects. An isolated browser QA room used genuine Advanced setup with a staged shipment opportunity: desktop controls rejected six forces from a five-force source, quoted five forces at three spice, and submitted the declaration by keyboard. At 390×844, both owned Guild interception choices remained actionable after refresh; keyboard allowance and another refresh preserved five Guild invaders on Caladan, fifteen native reserves, two spice, zero Tanks, the unspent Karama and the remaining movement. No page errors or horizontal page overflow occurred. The completed phone table was visually inspected. All **2,771** pre-existing rooms retain their exact versions and state hashes, with none missing; the existing server was reused.
Junction-sponsored transport, other factions' Arrakis permissions, unsponsored foreign departures to Arrakis, concealed No-Field transport, ordinary Guild rate/permission cancellation timing, the generic purchased Karama destination scope, occupation, remaining faces and complete Homeworld games remain unfinished. No game-start or publication gate is opened, saved games are preserved, and maintenance automation remains removed.
+137
View File
@@ -0,0 +1,137 @@
{
"generationMode": "built-in image_gen",
"assetType": "Original artistic interpretation; standalone Homeworld planet illustration",
"generatedDate": "2026-09-09",
"assets": [
{
"id": "caladan",
"source": "/home/quintine/.codex/generated_images/01a0851a-ce33-7341-852b-02100539fded/exec-c303d3d4-6ed8-4a86-87fa-dbb944a438e2.png",
"prompt": "Use case: stylized-concept. Asset type: original standalone planet illustration for a board-game Homeworld card. Style: sophisticated original hand-painted science fiction concept art, tangible fine brush texture, restrained cinematic color, richly textured curved planetary limb and luminous thin atmosphere against deep near-black space with very sparse stars. Composition: wide horizontal 2:1 image, one large planet spans most of the frame, fully atmospheric planet from orbit, strongest identifying surface features through the central horizontal region so this works as a 2:1 card-art crop. No typography, labels, logos, card frames, UI, people, watermark, or reproduction of official Dune card art. Subject: Caladan, an ocean world: immense deep cobalt seas, scattered lush island chains and sweeping white weather systems; blue and jade.",
"inspection": "Visually inspected: correct thematic subject, wide planetary limb composition, no text, frame, logo or people.",
"workspacePath": "public/art/homeworlds/caladan-v1.png",
"sha256": "ff8a7c967856fb56e73f7e1e03cf6e90828f47f7c7e63c56cd9f4186e69b583b",
"width": 1774,
"height": 887
},
{
"id": "ix",
"source": "/home/quintine/.codex/generated_images/01a0851a-ce33-7341-852b-02100539fded/exec-30201195-892d-465b-88b5-e0a8f192b9ed.png",
"prompt": "Use case: stylized-concept. Asset type: original standalone planet illustration for a board-game Homeworld card. Style: sophisticated original hand-painted science fiction concept art, tangible fine brush texture, restrained cinematic color, richly textured curved planetary limb and luminous thin atmosphere against deep near-black space with very sparse stars. Composition: wide horizontal 2:1 image, one large planet spans most of the frame, fully atmospheric planet from orbit, strongest identifying surface features through the central horizontal region so this works as a 2:1 card-art crop. No typography, labels, logos, card frames, UI, people, watermark, or reproduction of official Dune card art. Subject: Ix, a shadowed technological world: graphite terrain with dense subtle geometric machinery and a few amber lights glowing through atmospheric haze; charcoal and subdued bronze.",
"inspection": "Visually inspected: correct thematic subject, wide planetary limb composition, no text, frame, logo or people.",
"workspacePath": "public/art/homeworlds/ix-v1.png",
"sha256": "1af35b06cd9bc27c5fee54a8319059c3b0e46fd55a4613291f2d498d0bbc85b0",
"width": 1774,
"height": 887
},
{
"id": "ecaz",
"source": "/home/quintine/.codex/generated_images/01a0851a-ce33-7341-852b-02100539fded/exec-051e0958-886c-4623-bf6f-51c4aa0158fc.png",
"prompt": "Use case: stylized-concept. Asset type: original standalone planet illustration for a board-game Homeworld card. Style: sophisticated original hand-painted science fiction concept art, tangible fine brush texture, restrained cinematic color, richly textured curved planetary limb and luminous thin atmosphere against deep near-black space with very sparse stars. Composition: wide horizontal 2:1 image, one large planet spans most of the frame, fully atmospheric planet from orbit, strongest identifying surface features through the central horizontal region so this works as a 2:1 card-art crop. No typography, labels, logos, card frames, UI, people, watermark, or reproduction of official Dune card art. Subject: Ecaz, a lush forest world: vast emerald forests, curving green continents, delicate rivers and white cloud banks; rich green and turquoise.",
"inspection": "Visually inspected: correct thematic subject, wide planetary limb composition, no text, frame, logo or people.",
"workspacePath": "public/art/homeworlds/ecaz-v1.png",
"sha256": "ce4bedf884da51b6945cf5258a2afd00bd5805ad7274e2d22756865e8e203014",
"width": 1774,
"height": 887
},
{
"id": "southern_hemisphere",
"source": "/home/quintine/.codex/generated_images/01a0851a-ce33-7341-852b-02100539fded/exec-d43b00db-c8f2-49d7-8a56-9df9515e7fca.png",
"prompt": "Use case: stylized-concept. Asset type: original standalone planet illustration for a board-game Homeworld card. Style: sophisticated original hand-painted science fiction concept art, tangible fine brush texture, restrained cinematic color, richly textured curved planetary limb and luminous thin atmosphere against deep near-black space with very sparse stars. Composition: wide horizontal 2:1 image, one large planet spans most of the frame, fully atmospheric planet from orbit, strongest identifying surface features through the central horizontal region so this works as a 2:1 card-art crop. No typography, labels, logos, card frames, UI, people, watermark, or reproduction of official Dune card art. Subject: Southern Hemisphere of Arrakis, an entirely amber desert planet: enormous golden dune fields, burnt umber rock basins, tawny dust storms and dry ochre ridges; no oceans or vegetation.",
"inspection": "Visually inspected: correct thematic subject, wide planetary limb composition, no text, frame, logo or people.",
"workspacePath": "public/art/homeworlds/southern_hemisphere-v1.png",
"sha256": "3cbad2cf8dbdd364a81867e80ddf5cd3d1700c6dd2dd7729d4f5df4b9b9cec47",
"width": 1774,
"height": 887
},
{
"id": "richese",
"source": "/home/quintine/.codex/generated_images/01a0851a-ce33-7341-852b-02100539fded/exec-6c35cad1-8960-416f-9046-0b14f6bf672d.png",
"prompt": "Use case: stylized-concept. Asset type: original standalone planet illustration for a board-game Homeworld card. Style: sophisticated original hand-painted science fiction concept art, tangible fine brush texture, restrained cinematic color, richly textured curved planetary limb and luminous thin atmosphere against deep near-black space with very sparse stars. Composition: wide horizontal 2:1 image, one large planet spans most of the frame, fully atmospheric planet from orbit, strongest identifying surface features through the central horizontal region so this works as a 2:1 card-art crop. No typography, labels, logos, card frames, UI, people, watermark, or reproduction of official Dune card art. Subject: Richese, a silvery industrial world: pale silver-grey terrain and dense refined industrial lattices, metallic valleys, cool white haze; soft silver, steel blue and graphite.",
"inspection": "Visually inspected: correct thematic subject, wide planetary limb composition, no text, frame, logo or people.",
"workspacePath": "public/art/homeworlds/richese-v1.png",
"sha256": "4cb685455459a00351f0b971e630a2a382f3a20e50a15bf140887e6447a9be06",
"width": 1774,
"height": 887
},
{
"id": "tupile",
"source": "/home/quintine/.codex/generated_images/01a0851a-ce33-7341-852b-02100539fded/exec-61923313-474f-4af2-93d3-e521831211ff.png",
"prompt": "Use case: stylized-concept. Asset type: original standalone planet illustration for a board-game Homeworld card. Style: sophisticated original hand-painted science fiction concept art, tangible fine brush texture, restrained cinematic color, richly textured curved planetary limb and luminous thin atmosphere against deep near-black space with very sparse stars. Composition: wide horizontal 2:1 image, one large planet spans most of the frame, fully atmospheric planet from orbit, strongest identifying surface features through the central horizontal region so this works as a 2:1 card-art crop. No typography, labels, logos, card frames, UI, people, watermark, or reproduction of official Dune card art. Subject: Tupile, a hidden green sanctuary world: muted green forested land and secluded mountain basins partly veiled by cloud cover; atmospheric and mysterious, moss greens and pale jade.",
"inspection": "Visually inspected: correct thematic subject, wide planetary limb composition, no text, frame, logo or people.",
"workspacePath": "public/art/homeworlds/tupile-v1.png",
"sha256": "ad221709d732e8d7d14456fdaeb8621e215e04979dbe3d89b414d715c2641d7d",
"width": 1774,
"height": 887
},
{
"id": "wallach_ix",
"source": "/home/quintine/.codex/generated_images/01a0851a-ce33-7341-852b-02100539fded/exec-eaa552d7-44bf-498a-8103-f8796d343d20.png",
"prompt": "Use case: stylized-concept. Asset type: original standalone planet illustration for a board-game Homeworld card. Style: sophisticated original hand-painted science fiction concept art, tangible fine brush texture, restrained cinematic color, richly textured curved planetary limb and luminous thin atmosphere against deep near-black space with very sparse stars. Composition: wide horizontal 2:1 image, one large planet spans most of the frame, fully atmospheric planet from orbit, strongest identifying surface features through the central horizontal region so this works as a 2:1 card-art crop. No typography, labels, logos, card frames, UI, people, watermark, or reproduction of official Dune card art. Subject: Wallach IX, a misty rocky world: slate-grey mountain ranges, long pale valleys and dense pearly fog layers, hints of muted lavender in the thin atmosphere; cool stone and silver.",
"inspection": "Visually inspected: correct thematic subject, wide planetary limb composition, no text, frame, logo or people.",
"workspacePath": "public/art/homeworlds/wallach_ix-v1.png",
"sha256": "4b5870238e9b710a5a7e9fdcf566d3ea7bb69394e64028085b17996d30bcd1cd",
"width": 1774,
"height": 887
},
{
"id": "junction",
"source": "/home/quintine/.codex/generated_images/01a0851a-ce33-7341-852b-02100539fded/exec-e5459584-6807-4d7a-800f-135f375da491.png",
"prompt": "Use case: stylized-concept. Asset type: original standalone planet illustration for a board-game Homeworld card. Style: sophisticated original hand-painted science fiction concept art, tangible fine brush texture, restrained cinematic color, richly textured curved planetary limb and luminous thin atmosphere against deep near-black space with very sparse stars. Composition: wide horizontal 2:1 image, one large planet spans most of the frame, fully atmospheric planet from orbit, strongest identifying surface features through the central horizontal region so this works as a 2:1 card-art crop. No typography, labels, logos, card frames, UI, people, watermark, or reproduction of official Dune card art. Subject: Junction, the navigators' orbital domain: a large muted blue-grey planetary limb with a majestic delicate orbital ring and several tiny distant immense cylindrical navigational stations silhouetted above it. Emphasize the planet and sparse orbital infrastructure, no close spacecraft. Blue-black space, silver and faint amber.",
"inspection": "Visually inspected: correct thematic subject, wide planetary limb composition, no text, frame, logo or people.",
"workspacePath": "public/art/homeworlds/junction-v1.png",
"sha256": "3a103dc55d45fbc06cf79689ed33ae1668efacc66b7bd66d9bcc79a0d17a26e2",
"width": 1774,
"height": 887
},
{
"id": "kaitain",
"source": "/home/quintine/.codex/generated_images/01a0851a-ce33-7341-852b-02100539fded/exec-c87699f9-808a-4518-886a-2fe471242e75.png",
"prompt": "Use case: stylized-concept. Asset type: original standalone planet illustration for a board-game Homeworld card. Style: sophisticated original hand-painted science fiction concept art, tangible fine brush texture, restrained cinematic color, richly textured curved planetary limb and luminous thin atmosphere against deep near-black space with very sparse stars. Composition: wide horizontal 2:1 image, one large planet spans most of the frame, fully atmospheric planet from orbit, strongest identifying surface features through the central horizontal region so this works as a 2:1 card-art crop. No typography, labels, logos, card frames, UI, people, watermark, or reproduction of official Dune card art. Subject: Kaitain, a verdant imperial world: rich cultivated green continents with orderly gardenlike patterns, gentle rivers, luminous oceans and a subtle small golden city network; elegant serene green and warm gold.",
"inspection": "Visually inspected: correct thematic subject, wide planetary limb composition, no text, frame, logo or people.",
"workspacePath": "public/art/homeworlds/kaitain-v1.png",
"sha256": "16a8f30bd1557fbdf630232d8c013ec102e45aa9a4690ecc57f8ae8958735088",
"width": 1774,
"height": 887
},
{
"id": "salusa_secundus",
"source": "/home/quintine/.codex/generated_images/01a0851a-ce33-7341-852b-02100539fded/exec-e0c7e1ee-97af-4541-8a8e-e7439cc16d00.png",
"prompt": "Use case: stylized-concept. Asset type: original standalone planet illustration for a board-game Homeworld card. Style: sophisticated original hand-painted science fiction concept art, tangible fine brush texture, restrained cinematic color, richly textured curved planetary limb and luminous thin atmosphere against deep near-black space with very sparse stars. Composition: wide horizontal 2:1 image, one large planet spans most of the frame, fully atmospheric planet from orbit, strongest identifying surface features through the central horizontal region so this works as a 2:1 card-art crop. No typography, labels, logos, card frames, UI, people, watermark, or reproduction of official Dune card art. Subject: Salusa Secundus, a barren storm world: scarred rust-grey land, jagged rocky highlands and enormous violent slate storm bands with a few faint lightning glows; desolate slate, umber and pale storm light.",
"inspection": "Visually inspected: correct thematic subject, wide planetary limb composition, no text, frame, logo or people.",
"workspacePath": "public/art/homeworlds/salusa_secundus-v1.png",
"sha256": "f8a08fbb9648860c800ce2fc42d103e95b311eb79cdabb610210c5b524bdfb82",
"width": 1774,
"height": 887
},
{
"id": "giedi_prime",
"source": "/home/quintine/.codex/generated_images/01a0851a-ce33-7341-852b-02100539fded/exec-b37c0d4b-5d9b-4f3d-bba1-ffb238c1d80a.png",
"prompt": "Use case: stylized-concept. Asset type: original standalone planet illustration for a board-game Homeworld card. Style: sophisticated original hand-painted science fiction concept art, tangible fine brush texture, restrained cinematic color, richly textured curved planetary limb and luminous thin atmosphere against deep near-black space with very sparse stars. Composition: wide horizontal 2:1 image, one large planet spans most of the frame, fully atmospheric planet from orbit, strongest identifying surface features through the central horizontal region so this works as a 2:1 card-art crop. No typography, labels, logos, card frames, UI, people, watermark, or reproduction of official Dune card art. Subject: Giedi Prime, a dark industrial world: polluted near-black continents scored with vast brutal industrial complexes, ember-orange furnace lights and smoky ochre atmospheric bands, oppressive charcoal and rust.",
"inspection": "Visually inspected: correct thematic subject, wide planetary limb composition, no text, frame, logo or people.",
"workspacePath": "public/art/homeworlds/giedi_prime-v1.png",
"sha256": "209a4014aa153a67d4a7357b2f6c8aa7e62188e17bfa25738c6a70a69c571b56",
"width": 1774,
"height": 887
},
{
"id": "grumman",
"source": "/home/quintine/.codex/generated_images/01a0851a-ce33-7341-852b-02100539fded/exec-e4831381-8b4e-4e0a-a73f-3ecc180fca9d.png",
"prompt": "Use case: stylized-concept. Asset type: original standalone planet illustration for a board-game Homeworld card. Style: sophisticated original hand-painted science fiction concept art, tangible fine brush texture, restrained cinematic color, richly textured curved planetary limb and luminous thin atmosphere against deep near-black space with very sparse stars. Composition: wide horizontal 2:1 image, one large planet spans most of the frame, fully atmospheric planet from orbit, strongest identifying surface features through the central horizontal region so this works as a 2:1 card-art crop. No typography, labels, logos, card frames, UI, people, watermark, or reproduction of official Dune card art. Subject: Grumman, a severe fortress world: austere iron-grey mountains, broad dry stone plateaus and small angular fortress grids under thin clouds; martial, cold stone with restrained rusty accents.",
"inspection": "Visually inspected: correct thematic subject, wide planetary limb composition, no text, frame, logo or people.",
"workspacePath": "public/art/homeworlds/grumman-v1.png",
"sha256": "d671f929938ca2134c30a0af7f40f87ade2eea6e114e00410a8b750658ee2a9e",
"width": 1774,
"height": 887
},
{
"id": "tleilax",
"source": "/home/quintine/.codex/generated_images/01a0851a-ce33-7341-852b-02100539fded/exec-2d75af27-6693-4d74-88b4-179fd02a33cd.png",
"prompt": "Use case: stylized-concept. Asset type: original standalone planet illustration for a board-game Homeworld card. Style: sophisticated original hand-painted science fiction concept art, tangible fine brush texture, restrained cinematic color, richly textured curved planetary limb and luminous thin atmosphere against deep near-black space with very sparse stars. Composition: wide horizontal 2:1 image, one large planet spans most of the frame, fully atmospheric planet from orbit, strongest identifying surface features through the central horizontal region so this works as a 2:1 card-art crop. No typography, labels, logos, card frames, UI, people, watermark, or reproduction of official Dune card art. Subject: Tleilax, a biological-industrial world: strange muted olive land patterns, organic-looking industrial districts with branching conduits and clustered domes, misty green-grey haze, unsettling but non-graphic; moss green, antique brass and charcoal.",
"inspection": "Visually inspected: correct thematic subject, wide planetary limb composition, no text, frame, logo or people.",
"workspacePath": "public/art/homeworlds/tleilax-v1.png",
"sha256": "0cc5e2c9b065b775931ba37656618637d56630ffe439802d8ea7f10622df2f79",
"width": 1774,
"height": 887
}
]
}
+31
View File
@@ -0,0 +1,31 @@
# Homeworld battle runtime
9 September 2026. This connects the [combat foundation](HOMEWORLD_COMBAT_IMPLEMENTATION.md) to real engine actions and recovery. Homeworld starts remain disabled: invasion transport, occupation, remaining face effects and complete module games are unfinished.
## Connected behavior
One combat-location adapter supplies public names, exact native/visiting armies and the combined ordered battle frontier. Arrakis geometry remains unchanged. Phase continuations see remaining Homeworld conflicts before advancing to Collection. Native reserves and foreign garrisons retain separate physical custody; no fake sector keys enter the board.
Live battle preparation, sealed plans, resolution, mandatory card disposal and winner cleanup now use that location. Printed native strength affects the score, not dial losses. Only a native combatant can call a Traitor. Battles between visitors have no traitor voters and continue automatically, preserving Poison Tooth, Stone Burner and eligible late Portable Snooper decisions. An invading owner with a legal late defense gets an event-bound use/decline choice rather than a fictional traitor vote.
Lasgun/Shield destroys visiting armies but removes only the printed number of native physical counters, capped by actual population. Multiple typed allocations belong to the native player, even when two visitors fought and the native was not a combatant. A sole allocation resolves automatically. Native leaders outside the two plans remain unaffected.
Pending typed casualties bind the exact native/visitor pool, resolved event and committed arithmetic. Mandatory disposal, JSON restoration and later owned choices do not replay payment, leader death or prior losses. Same-total reallocations between Kaitain and Salusa cannot redirect a saved choice.
Ixian winners may exchange surviving Suboids for Cyborgs lost at that same Homeworld. The saved declaration binds survivors, typed Tanks and battle-loss history; Karama cancellation leaves the original losses unchanged. Native Tleilaxu Face Dance returns the foreign winner’s army and relocates selected own Arrakis forces into native custody. Existing native reserves remain physically in place, including a redundant same-source selection; zero external replacements are allowed. All four AI profiles and controls use the public location and exact quantities.
## Explicit unfinished interactions
The [replacement source audit](HOMEWORLD_REPLACEMENT_RULES.md) does not resolve the Advanced Emperor’s returned-army allocation between Kaitain and Salusa. That Face Dance return is gated with the same server, AI and interface reason; declining remains available. The existing Salusa Ghola support-timing question also remains gated. These restrictions are development boundaries, not official prohibitions. Other Homeworld face effects, occupation rights and full interaction coverage are still required.
## Evidence
Focused engine cases cover native and visitor combat, zero-voter restoration, native and noncombatant-native explosions, late defense, mandatory disposal, physical conservation and all four AI profiles. Replacement regressions cover Basic/Advanced native/visitor Ixian wins, declared Karama cancellation, corrupt receipts, native noncombatant Face Dance and unchanged private projections.
Production SQLite tests verify competing native casualty submissions, duplicate rejection, exact-pool corruption without writes and concurrent automatic recovery. They exposed a missing room recovery scheduling hint; the engine’s actual continuation remains authoritative. Static rendering tests check world labels, sector-free replacement controls and accessible restricted choices.
Final `npm run check` passes typechecking, lint and **3,264 offline cases** across 314 files (84.55 seconds for the tests); production build passes. The HTTP suite passed **40 cases** before the final saved-decision validation and board-selection fixes. Four additional recovery regressions cover live and Box-suspended late defense, stale event ownership, missing casualty receipts and altered loss options; rejected reads, actions and normalization preserve state.
Actual desktop and 390×844 browser checks in an isolated QA room exercised sealed native plans, the native-only traitor decision, Lasgun/Shield disposal and the three legal native casualty allocations. The pending choice survived refresh. Keyboard selection of one normal counter and one Sardaukar advanced to Collection; refresh restored 18 native reserves (14 normal, four Sardaukar), two native Tanks (one Sardaukar), five invader Tanks and exactly one discarded Lasgun and Shield. No page errors or horizontal page overflow were observed. Visual inspection covered the phone casualty controls and settled desktop result. This used genuine audit setup followed by conserved staged invaders; it does not demonstrate invasion transport or a complete Homeworld game. Browser testing exposed and fixed a world ID incorrectly passed to the Arrakis territory selector.
The controlled 10:30 UTC restart preserved all 2,709 saved room versions and state hashes; the authenticated earlier QA room restored through its invitation. A final read-only comparison after browser settlement found all 2,709 baseline rooms unchanged, with 2,740 rooms now stored including new test rooms. The recurring automation remains removed and user workflow optimizations remain in use.
+32
View File
@@ -0,0 +1,32 @@
# Homeworld charity and revival benefits
9 September 2026. This checkpoint extends the native-reserve runtime; it does not certify a complete Homeworld game or enable any unfinished start mode. The [source contract](HOMEWORLD_BENEFITS_RULES.md) distinguishes publisher rules, implementation inferences and unresolved combinations.
## Implemented behavior
- Primary native low population adds one to a qualifying charity claim and to the current free-revival rate. Salusa contributes neither addition. The shared quote supplies engine validation, player amounts and AI quantities.
- Charity keeps ordinary payment and the extra bank spice separate. CHOAM funds only the ordinary portion. Inflation doubles both portions or prevents collection. Canceling a Bene Gesserit claim pays neither portion. The production token triggers once on successful payment.
- A declared revival group uses the rate before that group returns. Later groups use the resulting population. The normal capacity is the greater of the ordinary limit and the current free rate, making the FAQ's four-free Fremen entitlement usable without granting a general fourth paid return. This formula and grouped timing are documented source compositions, not quoted errata.
- Fremen's alliance grant supplies three; the recipient's own low population adds its separate fourth. La La La suppresses the whole free rate. Existing paid discounts, typed allocation, special-counter limits and physical native return destinations remain separate.
- The actual entry to Revival records whether Tleilax starts low, before phase-opening controls. Later population changes preserve that turn-bound observation. The penalty suppresses other factions' ordinary free-revival bank income, while retaining paid receipts, its own free-revival income and separately named Ghola income.
- Table controls explain payment sources, current low benefits and the phase-start income condition. The reference contains the same timing guidance. All four AI policies use the shared current allowance; they withhold the special-Karama action that awaits the unresolved overlap ruling.
## Interrupted decisions and saved games
Charity response totals and bank portions are validated in live controls and explicit saved parents, including Nullentropy Box, Richese gift, exchange and discard continuations. Payment independently checks the eligible quote. This closes a reproduced corrupt-save path in which a Box-suspended claim could pay nine instead of three spice after automatic response allowance.
Normal Homeworld revival settlement validates its saved free allocation against the shared allowance before forces return. Current legal interruptions cannot change native population or ordinary usage while that request is pending; La La La success abandons the request. This rejects invented free counters even when a forged paid price is arithmetically consistent. A future force-changing interrupt will require an explicit timing/provenance extension, rather than blindly recomputing an earlier accepted quote.
Missing, stale or malformed Tleilax opening receipts reject; recovery never invents phase-start population from current reserves. The receipt is included in ordinary-card discard signatures. In-memory production D1 tests cover competing allowances/cancellations, restarts, private projections, rejected writes and preservation of another room.
## Evidence and limits
The complete offline check passed **3,190 tests**, including typecheck and lint. The final focused Homeworld/reference run passed **144 cases**. The production build and **40 live HTTP tests** passed. Seven new Homeworld benefit recovery cases cover production SQL and optimistic concurrency. The charity interruption regression uses genuine base setup with an explicitly labeled canonical Richese component seam; CHOAM payer cases similarly identify their unsupported-faction seam. They do not establish complete expansion setup.
Independent review found and integration fixed the AI/server mismatch, invented-free allocation and Box-suspended payout defects. A separate review fixed a shuffle-dependent Hajr fixture by locating genuine cards in either deck or dealt hands; a deterministic opponent-held-card regression preserves inventory.
An isolated Chrome QA room, `4K3HXJ6D`, passed desktop (1440×1000) and phone (390×844) inspection. A keyboard charity claim paid three spice, refresh retained it, an invalid four-force selection was disabled, and the accepted three-force return cost zero and raised Caladan from five to eight reserves. Refresh preserved the result and the opponent’s hand remained private. The inspected controls had no horizontal overflow or page errors. This is bounded feature acceptance, not complete module gameplay. Screenshots are `/tmp/dune-benefits-charity-desktop.png`, `/tmp/dune-benefits-charity-phone.png`, `/tmp/dune-benefits-revival-desktop.png` and `/tmp/dune-benefits-revival-phone.png`.
The prior development server was absent. A fresh read-only snapshot and SQLite backup preserved **2,648 existing rooms** before localhost startup; all versions and state hashes were unchanged afterward. The server returned HTTP 200. No database reset or recurring automation was used.
Pending material interpretations remain CHOAM's own low-population opening income, the Tleilaxu special-Karama/Homeworld overlap, and Ix high-population Suboid bonus quota/shortage behavior. Invasions, Homeworld battles, occupation, remaining card effects, full module combinations and complete games are unfinished. Keep public Homeworld/Advanced/unfinished expansion starts disabled.
@@ -0,0 +1,69 @@
# Homeworld charity and revival integration audit
Read-only inspection, 9 September 2026. This document describes the source at inspection, not a completed implementation or a full Homeworld rules claim. Parent integration may supersede individual line numbers. No runtime or test files were changed for this audit.
## Verified scope and existing foundation
[HOMEWORLD_RULES.md](HOMEWORLD_RULES.md), based on the GF9 Ecaz/Moritani rulebook pp.9–10 and FAQ p.16, records a low native Homeworld's +1 free-revival rate and +1 **bank-paid** spice when collecting CHOAM Charity. Salusa supplies neither bonus. Karama cannot cancel Homeworld advantages or penalties. Tleilax's low face specifically conditions its loss of **other factions' free-revival income** on starting Revival at low population. These are different timing contracts.
`homeworld-population.ts:23–59` already derives public native population and potential bonuses from validated physical custody. It excludes visitors and Salusa's bonus, counts Salusa Sardaukar separately, and performs no payment. `homeworld-game.ts` validates physical inventory before public action, normalization and projection. Native reserve deposits now route revived Emperor normal forces to Kaitain and Sardaukar to Salusa. This physical foundation does not yet apply the economic benefits inspected below.
Population currently reflects physical counters, not the future occupation rule that can retain a low penalty. Reuse it for the released native population domain; do not claim that this completes occupied Homeworld effects.
## Charity: split the actual receipt
| Current producer/consumer | Required integration |
| ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `charity.ts:17 charityAmount` | Currently returns one ordinary amount, including BG's advanced allowance and Inflation. Keep ordinary eligibility separate from a module bonus: adding one before the wealth threshold would create charity for ordinarily ineligible wealthy players. |
| `charity.ts:29 charityPayer` | Determines the ordinary CHOAM payer only. Low-population bonus is from the bank even when CHOAM funds ordinary charity. |
| `engine.ts:16345` charity action | Claims once via `charityTurn`, then either pays directly or opens wealthy BG's `bgCharity`. Produce explicit ordinary and bank portions; commit each exactly once. Do not open a new Karama response for the Homeworld portion. |
| `engine.ts:9251 payCharity` | Currently charges its entire argument to CHOAM. Passing a combined total would overcharge CHOAM and incorrectly require it to fund the bank bonus. Check CHOAM solvency against only its ordinary portion, and check recipient total safely before mutation. Preserve one Production-token trigger per actual collection. |
| `engine.ts:12782` BG response completion | Currently canceled means no payment. Retain the ordinary response and an explicit pending funding split. E1's BG cancellation says no Charity: the conditional bank bonus then has no qualifying claim. Pay both portions only on the supported completion, with no replay on cancellation, counter-canceled BG conversion, refresh or nested restoration. This is not a separately cancelable Homeworld power. |
| `terminal-cancellation.ts:172`, `karama-context.ts:150` | Existing BG terminal quote validates current Advanced claim, owner and safe amount; the source signature contains ordinary response data but no standalone charity receipt. If a new receipt is retained, validate its owner/turn/source and source-bound amount before both initial card cost and paid conversion allowance. Avoid freezing unrelated balances or response-pass lists. |
| `engine.ts:18144` view; `game-table.tsx:3083–3107`; `bots.ts:2466` | Project ordinary/bank/total amounts from the same quote. Current UI says all charity comes from one payer; it must describe the bank portion. Bots already use projected positive amount/claim status, so keep that shared surface authoritative. |
The existing CHOAM phase-opening collection (`engine.ts:9162`) is `2 × seated factions × Inflation multiplier`. Do not increase this allocation merely because a claimant's bank bonus exists.
The independent source reviewer confirmed E1's BG Karama row says no Charity, so its conditional Homeworld addition has no qualifying claim. E2 p.8 changes CHOAM Charity itself: the supported composition applies Inflation to the eligible total, including the bank addition, while retaining separate funding sources. No explicit Homeworld/Inflation cross-example was located; label this composition accordingly. Preserve the once-per-turn claim semantics and encode this ordering explicitly rather than letting a single-amount representation decide it.
## Normal free revival: shared rate, frozen request, ordinary limits
`revival.ts:42–91` provides the shared free remaining, force price and maximum request functions. Their present contexts do not include Homeworld custody. Introduce a public native-rate input or widen their declared context to include validated Homeworld state and public typed reserves. Preserve source provenance: native base/Fremen-alliance free rate, Homeworld addition, ordinary usage and any named restriction.
A low Homeworld increases the free **rate**, not a general paid-revival limit, global elite limit or available Tanks. The subsequent [source audit](HOMEWORLD_BENEFITS_RULES.md) confirmed E3's explicit four-free Fremen entitlement; the implementation uses the greater of ordinary capacity and current free rate to make that entitlement usable. `forceRevivalRemaining` also uses free remaining to enforce Fremen's no-paid-revival rule when no Tleilaxu is seated; it must receive the same new rate. Keep Emperor-funded extra returns, Ghola and leader revival separate.
**Named prohibition:** `revivalRules.freeBlocked` is CHOAM's **La La La**, set at `engine.ts:12476`, not a Karama cancellation flag. The independent source reviewer confirmed E2 p.7 prevents taking Free Revival; direct composition blocks the whole free rate, including the Homeworld addition. Homeworld Karama immunity provides no exception. Likewise, prevention of the entire normal revival is distinct from cancellation of an ordinary price advantage.
| Consumer | Exact concern |
| ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `engine.ts:16704` revive declaration | Use the revised free quote for affordability, chosen free cyborg allocation and frozen `PendingRevival.free/normalCost/cost`. Sample one batch before depositing forces: that batch can itself raise the Homeworld to high population. |
| `revival-resume.ts:17` context and `:105–136` frozen-price validation | Add the public state needed for current allowance checks, while preserving a valid frozen request's free/paid split. Existing arithmetic verifies paid physical counts and Ix free cyborg attribution. A new provenance field, if used, requires runtime validation; arbitrary extra free units must not pass by supplying a self-consistent lower price. |
| `revival-cancellation.ts:22`, `:280–307` | CHOAM benefit denial and discount cancellation reprice through `forceRevivalQuote`. Pass the Homeworld context to these calls, and preserve the noncancelable module source while removing only the named faction price benefit. Do not add module cancellation to their check queue. |
| `engine.ts:11942 beginRevival` and reactive La La La | A request with any applicable free component still enters the existing CHOAM decision. Denial of La La La resumes the unchanged request through `quoteRevivalResume`; successful La La La retains its named prohibition. |
| `engine.ts:11879 finishRevival` | Retain existing native typed deposit, Tanks reduction, ordinary/free usage, elite-per-turn usage and Axlotl quote. Avoid applying the bonus again at settlement or after a frame drain. |
| `engine.ts:18205` view; `game-table.tsx:3230–3378`; `bots.ts:2644–2665` | All consume free remaining and pricing. Use the shared quote, explain the module addition, and keep `freeBlocked` text accurate. No UI-only discount. |
The current usage calculation subtracts total ordinary `p.revived`, while `freeForcesRevived` separately records known actual free usage. Do not change this legacy accounting incidentally. Test repeated partial revivals around a population threshold and record the selected timing contract. Recruits' verified doubling of the current rate must use the same source when that card's broader integration is addressed; this audit does not activate it.
## Tleilax: persist the phase-start condition
`beginPhase` at `engine.ts:9176` initializes Revival rules and usage. Add one public, turn-bound phase-start receipt identifying the Tleilaxu seat and whether its native Tleilax was low then. A later ordinary revival or Ghola can increase population; neither refresh nor subsequent income may recompute the original starting condition. Reject malformed/stale new receipts and define a deliberate legacy policy rather than inventing historical population from the current board.
`openPhase` creates an Ix/Amal opening before `beginPhase`; the current ordinary opening permits Amal/pass, plus explicitly earlier card-transfer overlays. Those do not directly change reserves. Still bind the latch to the actual phase initialization once, preserve it through nested opening parents, and do not overwrite it during JSON recovery. Add it to any saved continuation signature whose next income depends on it.
There are **two income producers**, both needing one shared eligibility predicate:
- `revival-resume.ts:338–365` quotes normal settlement's paid transfer plus the first free-revival reward, and emits a per-payer `freeIncome` receipt.
- `engine.ts:11821 collectRevivalIncome` handles card/special routes including Ghola, with separate `free` and `ghola` flags.
Existing `revivalFreeIncome[player] = turn` only tracks whether a reward opportunity was consumed. It cannot encode Tleilax's starting population. Suppress only the source-supported other-faction free-revival reward. Preserve paid fees; do not blanket-disable `revivalIncome`, the Tleilaxu seat, or Ghola rewards because the current population is low. The source reviewer confirmed paid fees and the separate Ghola reward remain distinct from the specifically named other-faction Free Revival penalty; retain those routes rather than infer suppression from a boolean's name.
`terminal-cancellation.ts:163` deliberately permits Ghola's revival-income response outside phase4. Keep that domain. `viewGame` hides income amounts from seats other than owner/recipient (`engine.ts:18170`); the new public phase-start condition does not authorize exposing private payment totals. The `ordinaryCardDiscard` signature already includes Homeworld custody; any additional phase-start receipt used by its detached income suffix must also be bound.
## Bounded verification before release
Test base/ix genuine setup with conserved low/high custody; Basic and Advanced Emperor with Salusa excluded; ordinary wealthy/poor eligibility; CHOAM-funded versus bank portions; BG printed/converted cancellation with duplicate final allowance; Inflation boundary selected from source; and JSON recovery preserving one claim and one token trigger.
For revival, test a free batch crossing high threshold, later partial request, paid/free mixed Ix typing, Fremen cap, La La La allowed/canceled, discount cancellation, physical deposit, and no duplicate usage/fee/income. Test Tleilax low-at-start then raised versus high-at-start then lowered, paid fees preserved, other-faction reward suppressed exactly as sourced, Ghola distinguished, nested saved parents, and private amount projection.
No broad test suite was run for this read-only document. These are required integration checks, not reported passing coverage.
+45
View File
@@ -0,0 +1,45 @@
# Homeworld charity and revival benefits: source contract
Source audit, 9 September 2026. This separates publisher wording, rule composition, and remaining decisions. It does not enable Homeworld games or replace the outstanding Ambassador/Duke revival rulings.
## Publisher facts and provenance
| Source | Verified material |
| -------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [GF9 E3, pp.9–10,16](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf) | Thresholds follow current native reserves. Low adds one free revival and one bank spice **when collecting** charity; Salusa supplies neither. Karama cannot affect Homeworld advantages or penalties. The FAQ explicitly gives low Fremen four free revivals; Recruits doubles the current rate, capped at seven. Local publisher extract: `/tmp/dune-rules/ecaz-audit.txt`, lines375–445 and745–750. |
| [GF9 base, pp.8–9,16–17](https://www.gf9games.com/dunegame/wp-content/uploads/Dune-Rulebook.pdf) | Ordinary charity raises zero/one spice to two. Normal force revival has a three-counter limit. Fremen normally get three free, cannot buy additional normal revivals, and may grant their ally three free. Advanced BG always gets two charity. Local `base.txt`, lines472–504,929 and1068. |
| [GF9 E1, pp.6–9,12](https://www.gf9games.com/dunegame/wp-content/uploads/2020/09/IxianAndTleilaxuRulebook.pdf) | Tleilaxu may raise another faction's limit to five; its own normal limit is unrestricted. Revival payments and bank income for other factions' free revival/Ghola are separate. Cyborgs cost three to revive; ordinary free revival may select either type. Special Tleilaxu Karama prevents revival. The Karama table denies BG charity entirely. Local `ix-official-mirror.txt`, lines197–198,250–255,335 and535–537. |
| [GF9 November FAQ, p.3](https://www.gf9games.com/dune/wp-content/uploads/2020/11/Dune-FAQ-Nov-2020.pdf) | The explicit Advanced Karama timing table restricts Tleilaxu's special effect to Revival. This is not inferred from Guild timing. |
| [GF9 E2, pp.7–8,14](https://www.gf9games.com/dune/wp-content/uploads/2021/11/CHOAM-Rulebook-low-res.pdf) | La La La prevents Free Revival during Revival. Inflation doubles or cancels charity, expressly including BG and CHOAM's income. Cancellation of CHOAM's income changes ordinary charity's payer to the bank. Local `choam-lelekan-mirror.txt`, lines279–318 and545 onward. |
Actual Ix HIGH and Tleilax LOW cards were visually rechecked in the [four-sheet component photographs](https://www.reddit.com/r/DuneBoardGame/comments/16w27x0/every_homeworld_cards/), locally `homeworld-reddit-face2.png` and `homeworld-reddit-face3.png`. These are photographs of publisher components, not authority derived from commenters. Ix grants two free Suboids when paying to revive a Cyborg. Tleilax specifically tests whether it **starts** Revival low and then denies income from other factions' Free Revival. The card catalog and broader source inventory are in [Homeworld component audit](HOMEWORLD_COMPONENT_AUDIT.md).
## Supported composition for implementation
- **Current eligibility:** use the native population before the claimed event. Do not globally freeze low benefits at phase start. Tleilax's specifically worded income penalty is the exception and requires a durable phase-start observation.
- **A grouped revival:** quote the current rate before moving that group, preserve the accepted quote through interruptions, then derive the new population for the next independent request. Neither a mid-group per-counter repricing loop nor a whole-phase entitlement lock appears in the sources. This transaction boundary is an implementation inference consistent with the current-rate language, not a separately printed timing rule.
- **Free rate versus capacity:** adding one free revival does not generally add one paid revival. A useful formula is `max(ordinaryLimit, currentFreeRate)` for total normal capacity, followed by physical Tanks and already-used allowance checks. This makes the FAQ's four-free Fremen entitlement usable without granting everyone a fourth paid revival. The exact formula is an inference; the FAQ does not separately state the no-Recruits total-limit calculation. Do not describe it as a quoted erratum.
- **Fremen alliance:** apply the granted rate of three, then the recipient's own low bonus. The donor's low population does not turn its printed alliance grant into four. Canceling the alliance benefit removes that source, not the recipient's independent Homeworld increment. This follows the distinct grant and native modifier; it does not add an ordinary Karama cancellation of every faction's printed free rate.
- **Charity:** establish a valid collection first. Multiply ordinary charity and the conditional low bonus by Inflation, while keeping the bonus bank-paid. At zero spice, ordinary low charity is two from its ordinary payer plus one bank; Double makes four plus two. At one spice it is one plus one, or two plus two. Cancel produces no collection and no bonus. Advanced BG's ordinary amount is two regardless of wealth; a canceled BG charity claim similarly has no qualifying collection. These are cross-source compositions, not located worked examples.
**CHOAM's own income needs an explicit integration decision.** Its initial two-per-faction payment is named the Charity advantage, and E2 expressly includes it in Inflation. This supports treating it as a qualifying collection for Tupile's low bank increment, but that parenthetical does not explicitly adjudicate other modifiers. Conversely, limiting the Homeworld bonus to ordinary poverty claims would give low CHOAM no increment on its usual initial income. No retrieved primary passage resolves that distinction. Preserve the ordinary claim and faction-income sources rather than accidentally awarding twice or silently excluding CHOAM.
## Keep cancellation sources distinct
`revivalRules.freeBlocked` currently represents **La La La**, not Karama. Its prohibition covers taking the current Free Revival, including the Homeworld increment. Homeworld Karama immunity does not provide immunity to this independent Worthless power. Likewise, Inflation is a charity modifier, not a direct Karama against a Homeworld. There should be no response aimed solely at turning off the low increment.
The Tleilaxu special Karama has a different unresolved overlap: it prevents revival itself, while E3 protects Homeworld advantages. The natural event-based reading prevents the ordinary request without erasing its rate, just as denying a qualifying charity event prevents its conditional bonus. However, no retrieved primary text specifically settles whether the low extra counter survives that special prohibition as an independently executable return. Do not silently turn this into La La La's known non-Karama rule, or claim that only the bonus survives without an explicit interpretation.
## Tleilax and Ix finite effect boundaries
**Tleilax:** snapshot native low status on entry to Revival; crossing high later does not erase the printed start-condition. Suppress only the bank income for another faction's Free Revival. Do not suppress paid receipts, its own revival, or Ghola income merely because they share a helper. E1 names Ghola separately; the low card does not name it. Preserve existing once-per-faction ordinary-free-income accounting independently of this condition. High Tleilax's optional shipment of the returned group is a separate destination continuation, not an automatic consequence of this low-income work.
**Ix:** the trigger requires an actually paid Cyborg return while the relevant high advantage applies. A free Cyborg, Ghola, or a paid Suboid supplies no such trigger. The grant remains two physical Suboids per qualifying Cyborg, never two newly created pieces or a Cyborg substitution. A discounted but positive Cyborg payment is still payment. Keep paid/free typed allocations in the quote so total transaction cost is not mistaken for proof that every selected Cyborg was paid.
The retrieved card and publisher FAQ do **not** settle whether those Suboids consume normal revival allowance or are additional to it; this changes legal quantities after one or more earlier revivals. Nor do they explicitly choose between partial fulfillment from an insufficient Suboid Tanks pool and requiring both. Both issues materially affect a complete automatic purchase/bonus implementation. Do not add an arbitrary optional decline to hide that uncertainty. Recruits explicitly doubles free **rates**, so it does not by itself establish four bonus Suboids per paid Cyborg. Its interaction with any exceptional total must follow the resolved quota policy.
## Release boundary
Implementable together: current low benefit projection, source-separated ordinary charity payments, current normal revival quotation, retained accepted-request pricing, and the explicit Tleilax phase-start income condition. Add tests at the exact threshold, during a suspended request, after crossing it, with a Fremen ally, and with Inflation/La La La/BG cancellation. Keep CHOAM's own-income classification, special-Karama overlap and Ix bonus quota/shortage behavior visible until interpreted. These are the remaining material combinations from this audit, not reasons to postpone the independently established mechanics.
Fresh searches of publisher rulebooks/November FAQ and targeted designer clarification queries found no additional primary ruling for the unresolved cases. Tournament compilations, wishlists, and movie-game rules were not used as authority. In particular, a third-party compilation's added “breaking current revival limits” language is not a GF9 quotation. No runtime, tests, saved rooms, or automation were changed.
+123
View File
@@ -0,0 +1,123 @@
# Homeworld card economy: source contract
Audit: 9 September 2026. Scope: high Kaitain's paid disposal and high Tupile's
Worthless-sale restriction. This document does not certify runtime integration.
## Authority and access
- The original high faces were freshly retrieved and visually inspected in
[BGG photograph 7767034](https://boardgamegeek.com/image/7767034/dune-ecaz-and-moritani).
Public metadata identifies a 3024×4032 photograph posted on 2 October 2023;
the local inspection copy is `/tmp/dune-card-economy-homeworlds.jpg`.
Its Kaitain and Tupile text agrees with the prior
[component audit](HOMEWORLD_COMPONENT_AUDIT.md). The photograph depicts
publisher components; uploader commentary supplies no rules authority.
- [GF9 E3, pp.9–10,15](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf)
was rechecked through publisher-indexed text. Population changes continuously;
Homeworld advantages and penalties are immune to Karama. The book expressly
identifies Tupile's high side as a penalty and its low side as an advantage.
- [GF9 E2, pp.4,7–8](https://www.gf9games.com/dune/wp-content/uploads/2021/11/CHOAM-Rulebook-low-res.pdf)
was likewise checked through publisher-indexed text. Ordinary CHOAM sales
occur at phase end: exact duplicate surplus pays three spice, Worthless cards
two. Its reciprocal allied card trade is once per game turn at phase end.
Special CHOAM Karama pays three per selected Treachery card at any time,
including Worthless cards. Special Worthless effects retain their own timing;
Gamont belongs to Mentat Pause. The discard pile is not freely searchable.
Direct GF9 PDF requests currently redirect or return 403; the former
`/tmp/dune-rules` cache is absent. This audit does not claim a fresh full-PDF
download. No retrieved official amendment changes either inspected high face.
Tournament compilations surfaced in search but were excluded.
## Kaitain implementation contract
At Bidding's end, an Emperor with high Kaitain may choose held Treachery cards
and pay two spice per card to discard them. The face gives neither a one-card
limit nor a forced discard. Declining is legal. Weapons, defenses, Worthless
cards and Karama are all Treachery cards. Paying to discard a Karama does not
activate its printed effect or spend the once-per-game special power.
Treat the selected group atomically: unique currently held physical IDs, enough
available spice for the whole group, exact cost, and exactly one discard per
selected card. A stale or invalid selection must spend nothing. The batch is an
implementation transaction, not a new printed once-only restriction. No extra
auction begins because disposal opened a hand slot after auctions ended.
The payment is disposal expenditure, not a card purchase, shipment or battle
support payment. No retrieved rule names a faction recipient: bank payment with
no commercial-income response is the implementation inference. Separate
discard-triggered effects still apply: the inspected high Ecaz face rewards
poison-weapon discards. Reuse physical discard handling and preserve private
selection information until the normal discard visibility rules permit it.
Do not offer a Karama response against Kaitain itself. Recheck current native
population at execution, including after a legally played Ghola; do not freeze
high eligibility at the beginning of Bidding. Foreign visitors do not supply
native population.
## Shared end-of-Bidding timing
Kaitain and CHOAM's market share a phase-end boundary. No retrieved primary rule
orders one before the other. The
[November FAQ, p.8](https://www.gf9games.com/dune/wp-content/uploads/2020/11/Dune-FAQ-Nov-2020.pdf#page=8)
uses storm order for simultaneous Truthtrance plays; it does not explicitly
establish a universal order for these later expansion abilities.
Consequently, do not describe a fixed CHOAM-before-Kaitain sequence, its reverse,
or a storm-order queue as a verified official requirement. Keep both legal
opportunities available until the shared boundary closes. In particular, do not
discard an Emperor's opportunity merely because its original hand was empty
before a legal allied trade or another permitted card acquisition. New cards
and current funds must be considered when quoting a later disposal. Preserve
any pending trade, response or post-auction continuation; disposal does not
authorize resolving another player's decision.
## Tupile implementation contract
While Tupile is high, CHOAM cannot discard Worthless cards for spice except
through Advanced Karama. The prohibition names the card and outcome, so both a
two-spice Worthless sale and a three-spice duplicate-Worthless sale are blocked.
An exact-name witness does not change the sold card's kind. Non-Worthless
duplicate sales, reciprocal trades, battle discards and special Worthless
effects are outside this prohibition. This is direct application of the face's
scope, not a new restriction on all CHOAM card handling.
The same block applies when native CHOAM benefits from the CHOAM Ambassador:
that effect exchanges selected cards for bank spice, and Ecaz may designate
its ally as beneficiary. Neither changes the card into Advanced Karama. Check
the actual beneficiary's Tupile, not the token name or Ecaz's population.
The Ixian Ambassador's discard-and-draw exchange remains outside this block.
[E3, p.8](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=8)
This composition follows the named outcome and sole printed exception; no
dedicated worked Ambassador/Tupile example was retrieved.
The Advanced Karama exception is specific to CHOAM's cash-in power. It neither
removes the high penalty generally nor creates a Basic-game exception. Preserve
the existing separate activating-Karama cost, once-per-game use, eligible
uncommitted card selection and three-spice return. Ordinary Karama cannot
cancel Tupile's restriction. At low population, this particular sale block is
absent; do not accidentally suppress the low-side information ability or
redefine its occupied-face interaction here.
Revalidate high/low status when an interrupted sale actually settles. Test a
real Ghola transition from low to high while a Worthless sale is pending:
stale permission must not remove the card or pay income. Keep the market and
its parent continuation recoverable. This requirement is independent of the
older unresolved Kull and Worthless-cancellation interpretation questions.
## Deferred payment splitting
E3 p.15 explicitly splits a five-spice Treachery payment into three for Emperor
and two for Kaitain's occupier, even if that occupier bought the card. It does
not give an allied-contribution example. The inspected reverse-face record
assigns rounded-up half of shipment receipts to low Junction. Neither evidence
establishes separate rounding per contributor versus once per purchase or
shipment. Preserve payment identity, actual payer contributions and income
source separately before integrating those effects; do not infer an answer
from existing integer arithmetic. Occupation lifecycle questions remain in
[Homeworld rules](HOMEWORLD_RULES.md).
Runtime verification should cover Basic/Advanced and module-off parity,
threshold transitions, exact card custody, private view/AI boundaries,
rejected-action immutability and saved parent recovery. Those are engineering
requirements for these rules, not evidence that the entire module is complete.
+133
View File
@@ -0,0 +1,133 @@
# Homeworld card economy runtime
9 September 2026. This records the integrated Tupile sale restriction, shared
Kaitain closing opportunity and Ecaz poison income. Source authority is in
[the card economy contract](HOMEWORLD_CARD_ECONOMY_RULES.md) and
[the Ecaz poison audit](ECAZ_POISON_INCOME_RULES.md). Complete Homeworld and expansion starts remain disabled; verification is
scoped to the integrated paths below.
## Implemented paths
- After the last auction and its income/bonus continuations finish, Homeworld
tables with Emperor open one shared end-of-Bidding opportunity. Emperor can
pay two spice per selected held Treachery Card while Kaitain is high. Payment
precedes disposal; it creates no auction income and does not activate card
effects. Any number of eligible cards can be selected, subject to current
hand custody and funds.
- CHOAM's closing sales and allied trade share that opportunity. Neither faction
has an imposed priority, so a traded card can subsequently be discarded through
Kaitain. Ghola and incoming transfers use current population and hands. The
saved event binds both owners, the turn and completed-auction state.
- Owners finish independently; another accepted card action clears readiness.
Automatic closure uses only public hand counts and possible incoming
exchanges, never private spice or card identities. Nested choices complete
before another closing action. The table advances when all owners finish.
- `game/bidding-end-options.ts` supplies private controls and all four AI profiles
with the same current opportunity. The bots preserve a spending reserve and
prefer disposing of unwanted Worthless cards. Existing CHOAM market policy
supplies their sale/trade choices.
- At eleven native forces, Tupile blocks Worthless cards from ordinary CHOAM
two-spice sales and three-spice duplicate sales. The authoritative action,
current private sale choices and final settlement use the same population
predicate. Foreign visitors do not raise native population.
- The same restriction applies when native CHOAM receives the CHOAM Ambassador's
three-spice-per-card effect. Each selected card is validated before any
discard or payment. A choice with only unavailable cards completes
automatically. Other beneficiaries and the Ixian discard-and-draw effect
retain their separate rules.
- Non-Worthless duplicates, reciprocal allied trades and CHOAM's Advanced
special Karama cash-in remain available under their existing prerequisites.
The market explains the high-Tupile restriction and shows eligible sales.
Other seats receive no private sale list or held-card information.
- Ghola can interrupt a declared CHOAM sale. The ordinary revival and physical
discard complete before the original sale resumes. A Tleilaxu income response
has its own allowance or cancellation, including saved-state restoration.
If revival raises Tupile from ten to eleven, the original Worthless sale
subsequently keeps its card and pays no spice. Canceling that original sale
is still a valid separate action.
- The suspended sale stores its exact market, response, original actor/card,
discard sequence and event. Explicit discard, income and completion stages
bind the receipt to the actual live or suspended income response. Incoming
state is checked before actions, normalization and private views. Completion
restores the original response without replaying the declaration or revival.
- All four AI profiles use the filtered market choices. Their existing Ghola
recovery policies can also use this sale interruption through the shared
timing quote. Other ordinary-card response windows remain under their
existing coverage limits.
## Ecaz income and battle cleanup
The central physical hand-to-discard operation quotes `game/ecaz-poison-income.ts`
and pays three bank spice per poison weapon while native Ecaz is at seven or
more reserves. It applies to any owner's qualifying discard, including Ecaz's
own cards, paid Kaitain disposal, battle cleanup and legal hand cash-in. Current
population is checked at disposal. Neither returning cards to the deck nor
resuming an already committed discard pays again.
Printed poison weapons, Poison Blade and Poison Tooth qualify. Chemistry
qualifies only from its actual weapon slot. Residual Poison and poison defenses
do not qualify. A conditional battle role is retained in a signature-bound
resolved-battle receipt, preserving delayed cleanup through JSON restoration.
The pure quote understands validated Mirror copy descriptors; this does not
enable currently guarded Mirror battle plans or settle its separate retention
question.
Losing cards are discarded before winner casualties. Mandatory winning cards,
including an activated winning Tooth, remain reserved until winner casualties
and any Ixian substitution finish. `pendingWinnerDiscards` binds the original
battle, owner, physical cards and optional cleanup suffix. An independent
resolved-battle obligation requires that queue until its physical disposal is
complete; missing queues and missing obligations reject on restoration. Both
mandatory and optional played cards remain reserved through the casualty pause.
`finishWinner` then
performs the actual compulsory disposal and stages its discard continuation
before offering optional winning-card cleanup. Thus a native Ecaz winner that
falls from seven reserves to six can receive losing-card income while still
high, but receives no income for its later winning-card disposals. The source
composition and revised-Tooth-face retrieval limit are recorded in the Ecaz audit.
Income is committed with the physical discard. An Ecaz-only ledger projects
amount, count, turn and phase to the owner's Homeworld panel; no public log or
event-sequence entry discloses a private discard's poison category. Other seats
receive no ledger or private spice balance.
## Verification scope
Final `npm run check` passes types, lint and **3,515 offline cases**. The
production build and **40 HTTP integration cases** also pass. Desktop and
390×844 browser seats completed paid poison disposal, private Ecaz income, an
allied CHOAM trade, a Worthless sale with a human Karama allowance, and independent
closing readiness. All three seats restored Revival and their exact private
balances after refresh. Screenshots were visually inspected; no page overflow or
browser errors occurred. QA setup uses the documented expansion faction seam.
All **2,894** pre-existing room versions and state hashes remain unchanged.
Three isolated browser rooms and thirty HTTP test rooms were added; no game was
reset. The earlier controlled server restart restored the existing private seat.
Focused entry points are `npm test -- bidding-end ecaz-poison-income`
and `npm test -- battle-discard`. The five new suites add 47 cases: twelve
Bidding engine cases, ten controls/AI cases, five production SQLite cases, eight
pure Ecaz quotes and twelve Ecaz engine cases. Existing battle-discard and SQL
recovery regressions now verify separate losing/winning batches, exactly-once
casualties, played-card reservations and missing-queue rejection.
The new pure, engine and in-memory production-room suites cover exact thresholds,
typed custody, opponent-secret getter traps, malformed selections, unchanged
rejections, both sale prices, separate legal exceptions, Ambassador selection,
Ghola revival, nested income cancellation, all four AI profiles, private JSON
restoration, corrupt receipts and competing duplicate settlements.
Fixtures explicitly isolate CHOAM's unavailable complete expansion setup.
Production recovery uses real supported setup before the documented CHOAM
faction seam. The currently implemented decks contain no duplicate Worthless
printed names, so duplicate-Worthless validation uses two real physical IDs with
a documented same-name fixture seam. Neither seam certifies the expansion deck.
No live saved game is modified by the in-memory suites.
## Remaining work
Occupation retention, Tupile's low/occupied powers, remaining Homeworld economy,
broader Ghola interruptions, complete module games and expansion setup remain
unfinished. The outstanding Mirror retention and other previously recorded
source questions are unchanged. No start or publication gate changes.
+186
View File
@@ -0,0 +1,186 @@
# Homeworld Collection and Terror integration audit
This is a read-only code audit and proposed integration boundary. The current
source audit determines the precise Grumman and Giedi Prime wording, action
ordering and unresolved combinations. Existing source contracts are in
[Homeworld rules](HOMEWORLD_RULES.md),
[Moritani Terror rules](MORITANI_TERROR_RULES.md) and
[Ecaz Collection implementation](ECAZ_COLLECTION_IMPLEMENTATION.md).
No faction or expansion completion is implied.
## Concrete hazards in the current implementation
1. `engine.ts::openTerrorEntry` uses `.find` for the first placed token at the
destination and saves that single identity. Permitting Grumman stacks without
changing entry selection silently chooses a secret effect by array order.
The present view, `decideTerror`, bots and Terror reaction component all
operate on one token. Source verification must settle whether one or several
tokens may resolve for an entry and who chooses their order.
2. `moritani-terror.ts::placeTerror` rejects a destination already containing a
token and consumes `placementTurn`. That is the ordinary Mentat opportunity,
not a reusable Grumman Collection action. Reusing it either prevents stacking
or consumes the wrong phase's allowance. Its engine action also opens an
ordinary Karama response; Homeworld effects must not inherit that response.
3. A removed token's destination matters. `revealTerror` exposes its face and
removes it from play; `returnTerror` returns it to supply and rotates available
identities using private randomness. Neither is an automatic interpretation
of Grumman's removal wording. Reusing the wrong function can reveal a hidden
face, create a replacement token or permanently lose a recoverable token.
4. `CollectionQuote.receipts[].collected` omits Ecaz shared desert escrow until
allocation. Harkonnen may be the ally. Awarding Giedi only from the initial
receipt misses later qualifying income; awarding it just because a shared
lot exists may pay even when Harkonnen eventually receives zero.
5. `collect` only gets an `ecazCollection` completion marker when an Ecaz bonus,
shared allocation or same-turn frame exists. A Homeworld once-per-Collection
award needs its own durable receipt even in a game with no Ecaz. Reads and
normalization must not infer a fresh award from current board presence.
6. Low Grumman must feed both actual entry/reveal legality and earlier competing
reaction checks. Adding only a guard to `openTerrorEntry` leaves less-than-three
entries incorrectly rejected by preflight checks that see any placed Terror.
7. Existing Terror guidance permits even zero No-Field placement to trigger.
The subsequent source audit confirms the public marker counts as one force:
low Grumman therefore suppresses a marker-only entry, independently of its
hidden value; a marker plus two admitted physical forces reaches three.
A public window must never depend on the concealed denomination.
## Arrival contract and consumers
`openTerrorEntry` is called only after entry is committed. It stores entrant,
destination, sector, `amount`, `elite`, cause, turn, phase and a continuation
for worm rides or Ambassadors. Existing callers pass total physical arrivals as
`amount`; `elite` is a subset, not an additional count. Existing forces already
at the destination must not contribute to the entering threshold. BG advisors
are physical arrivals and already qualify under ordinary Terror guidance;
ordinary one-advisor and Wallach two-advisor batches remain below three.
The smallest shared public eligibility quote should consume native Grumman
effect state, owner/entrant/ally identities, original entry cause and a verified
entering count. It should return an explicit trigger/reveal block without
reading token kinds, hands or private resources. Keep physical population and
retained occupation effects separated as described in the
[occupation integration audit](HOMEWORLD_OCCUPATION_INTEGRATION.md).
Use the same quote in these adapters:
- `openTerritoryEntry`, `openTerrorEntry` and `terrorRevealBlocked`.
- The competing-reaction checks in `guildAdvisorAmbassador` and the Ambassador
relocation path, plus the engine's movement board supplied Terror list.
- Guild Ambassador shipment and advisor continuations, Fremen Ambassador
relocation, normal/Guild shipment, ordinary movement and worm-ride entry.
- Saved Terror alliance and discard continuations, including `terrorAllianceBlocked`:
refusal requires revelation, so an unavailable revelation cannot be bypassed
by offering Enemy of My Enemy first.
A quote for stacked entries must return owner-selectable physical token IDs;
public observers should learn only the same entry/location/stage information
they already receive. Preserve a chosen token's identity through alliance reply,
discard continuation and random resolution. Never reroll or reselect on reload.
Keep unresolved token effects gated even when another token in the stack is
implemented. Exact multiple-token sequencing awaits source confirmation.
## Collection pipeline and source provenance
`board-resolution-quote.ts::quoteSpiceCollection` settles advisor stances,
calculates collection capacity, removes map deposits and returns independent
stronghold income, ordinary collected amounts and Ecaz shared lots.
`engine.ts::collect` may first open the Ecaz ordinary-advantage Karama window;
`commitCollection` then applies receipts and starts shared allocation.
`decideSharedSpice` credits each resolved lot and marks that frame complete.
`nextPhase` invokes collection on entering phase 7 and opens ordinary Terror
placement separately on entering Mentat phase 8.
Keep Homeworld additions out of `quoteSpiceCollection`'s resource mutation until
its existing result has been committed. Otherwise `commitCollection` assigning
each `receipt.balance` can overwrite a Homeworld credit made earlier. A helper
that awards during view or re-quote also duplicates payment when Ecaz's canceled
quote is recomputed. Existing `collectionBoardSignature` intentionally excludes
private balances and native reserve counts; it is not an original Homeworld
eligibility receipt.
Giedi needs qualifying collection provenance, not a balance difference. Ordinary
stronghold bank income, poison/technology payments, bribe returns and unrelated
Collection effects must not qualify by accident. Current `collected` merges all
map deposits without a terrain tag. A minimal extension is committed source
receipts of the form `{player, source, amount}`, with `source` distinguishing
desert collection, Homeworld collection and other income. Shared allocation
must add receipts for its actual recipients, including zero where needed for
auditing, rather than redistributing the original bank or ordinary income.
Homeworld occupation Collection itself remains separate unfinished work.
A pure Giedi quote can take public native-effect context plus a validated
qualifying amount and an existing event receipt, and return either zero or the
printed bank bonus. A general resource quote must not inspect another player's
private balance to decide eligibility. Current-versus-captured native eligibility
and whether qualifying shared participation requires a positive allocation must
follow the source audit rather than an incidental hook position.
## Smallest coherent Grumman contract
Use a separate `HomeworldCollection` event with turn, owner, stage and completed
receipt; do not overload `TerrorState.placementTurn` or `ecazCollection`. It must
coordinate with the existing Ecaz decision so neither overwrites the other.
The source audit determines the permitted phase ordering; a continuation can
open the next authorized opportunity only after the active one settles.
A focused pure quote should validate a discriminated action: decline, add an
owned eligible physical token to a qualifying already-marked stronghold, or
remove a selected placed token. It should return the precise custody change and
bank payment without mutating state. Validate native high eligibility, original
event, legal destination, unique token identity and prior completion. The
source must determine whether payment requires completing one operation and
where a removed token goes; the contract must represent those decisions
explicitly. Preserve Mentat placement independently.
Project own choices from the same quote for a new Collection component and bot
decision branch. The existing `MoritaniPlacementDecision` component and
`bots.ts` placement branch intentionally seek empty strongholds, so they are
inappropriate for stack destinations. All four bot levels need a legal action
or decline path. Observers see public stack count/location and completed bank
income, while available hidden token faces stay owner-only. If a hidden token
returns to supply, preserve the identity-rotation protection before reuse.
## Focused verification before enabling the paths
- Entry batches of two and three, elites counted once, existing destination
forces excluded, advisors included, module off and native high/low crossings.
- Low eligibility in both preflight and actual continuation; immutable rejected
actions and no paid entry replay through Ambassador, alliance or discard.
- Stack selection with two different physical token IDs; concealed observer
equivalence; chosen identity retained through JSON and SQL recovery.
- Collection add/remove/decline preserves six-token custody, independently of
the same turn's Mentat placement; no duplicate bank payment on retry/read.
- Giedi: zero collection, stronghold-only income, positive desert income, several
qualifying locations, and shared Ecaz allocation of zero versus positive
spice under the verified qualification rule; award at most once per event.
- Ecaz ordinary Collection cancellation does not cancel a Homeworld effect;
pending allocation and Grumman choice preserve their own original receipts.
- Source-confirmed No-Field and occupation cases, with explicit release gates
where those compositions remain unresolved.
The audit itself makes no engine changes. A subsequent isolated implementation
adds `game/homeworld-collection.ts::quoteGiediCollectionBonus` and
`lowGrummanRevealBlock`, with eight passing pure regressions in
`tests/homeworld-collection.test.ts`. They use current physical population and
validated actual source/count inputs; event timing, No-Field composition,
occupation and high Grumman token operations remain outside those helpers.
Focused lint, code references and local documentation links were checked.
The low Grumman engine integration now shares that block across movement and
Ambassador preflight, entry opening, reveal and alliance availability. Narrow
Ambassador destinations where one or two forces avoid a currently unsupported
simultaneous Intrusion/Terror reaction expose a maximum of two, used by the UI
and all four bot levels. High and module-off paths retain their prior behavior.
New entries carry `entrySignature`, a consistency receipt binding the original
public count, token, entrant, location, cause, turn and continuation identity.
View, action and normalization validate both live entries and suspended Terror
discard entries. Alliance cancellation preserves the receipt. Older saved
entries without a signature remain an explicit compatibility boundary; nothing
reconstructs their original count from present forces. Current Grumman population
is still rechecked independently of the immutable arrival.
Twelve new engine regressions cover typed counts, advisor arrivals, identical
observer views for concealed zero/three/five markers, marker-plus-two movement,
count-dependent Ambassador legality, all four bots, actual Karama cancellation,
and corrupt live/suspended receipts. The related 19-file run passed 281 tests.
These results do not implement high Grumman stacking/removal or occupation.
+63
View File
@@ -0,0 +1,63 @@
# Grumman and Giedi Prime: collection and Terror restrictions
Primary-source audit, 9 September 2026. This document supplies a bounded implementation contract, not a runtime checkpoint. Occupation lifecycle and the separate low-Guild contributor-rounding questions remain pending; do not duplicate them.
## Evidence inspected
The original high faces were visually read again from `/tmp/dune-card-economy-homeworlds.jpg`, the 3024×4032 original photograph associated with [BGG image 7767034](https://boardgamegeek.com/image/7767034/dune-ecaz-and-moritani), posted by Jaakko/zaksalo on 2 October 2023. Grumman and Giedi Prime are both legible in its bottom row. The photograph is primary component evidence; the photographer's opinions are not rules authority. The [component audit](HOMEWORLD_COMPONENT_AUDIT.md) records all face provenance.
The low-Grumman face wording comes from the earlier complete reverse-face inspection recorded in that audit. The old reverse-image cache is absent. A fresh attempt to retrieve the original gallery's public RSS returned 403, so no new reverse-image inspection is claimed. Fresh publisher-indexed E3 pages 5, 15 and 16 and E2 page 6 were retrieved successfully; direct opening of the E3 PDF failed. No additional authenticated designer ruling was located in bounded searches.
## Giedi Prime high collection income
The high face requires at least seven native Harkonnen reserves and awards two bank spice when Harkonnen collects spice from desert territories or Homeworlds during that turn's Spice Collection. The E3 FAQ explicitly limits this to **two total**, even when several qualifying collections occur. Ordinary stronghold income is not one of its listed reasons. Homeworld effects resist Karama. [GF9 E3, pp.10,15](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=15).
Executable contract:
- Preserve each actual collection receipt's player, turn, phase, source kind and positive amount. A positive desert receipt qualifies; presence in an empty desert or an uncredited collection quote does not.
- For Ecaz/Harkonnen shared desert collection, use Harkonnen's **settled allocation**. A reserved joint pool is not yet its income; a zero share does not qualify. A positive agreed or fallback share retains its desert origin. This composes the card trigger with [Ecaz's allocation rules](ECAZ_COLLECTION_RULES.md), not a dedicated Giedi/Ecaz FAQ example.
- Once the condition is met while the high advantage is available, credit two and retain a once-only turn receipt. Later desert or Homeworld receipts, repeated phase normalization and restored allocation continuations do not pay again.
- Exclude ordinary stronghold bank income, the extra Ecaz stronghold award, technology receipts, sales, charity, revival income, payment income, Grumman's four-spice award, unrelated ally gifts and collection outside the named phase. Having all Tech Tokens count toward victory does not turn their income into desert or Homeworld collection.
- Future occupied-Homeworld bank income needs its actual authorized recipient and original source. Immediate sharing of another occupier's income is not explicitly classified by this card or the retrieved FAQ; preserve provenance and resolve that interaction with occupation rather than silently counting every ally transfer.
Population at an actual qualifying receipt is the continuous-threshold composition used elsewhere in this module. The printed text does not freeze the population at phase start. An eventual low-to-high change after an earlier collection but before the phase ends needs deliberate timing composition; this document does not claim a dedicated retroactive-trigger ruling. Ordinary phase-end settlement can retain qualifying-source evidence without paying twice.
The existing `quoteSpiceCollection` totals map deposits into `receipt.collected`; it does not guarantee every deposited location is a desert. A Giedi consumer must retain/filter each source territory's actual `sand` type, rather than equating the aggregate field with desert income. Commit normal and shared receipts separately, preserving current balances and their existing durable continuations.
## Grumman high Collection opportunity
The inspected high face requires at least eight native Moritani reserves. It offers adding a Terror token to a stronghold already containing one, **or** removing a Terror token from the board during Spice Collection, followed by four bank spice. The payment is tied to the completed token change: declining or having no legal token change supplies no independent four-spice claim.
The singular phase-scoped opportunity supports one selected operation and one award per Collection, using the same ordinary phase grammar as Terrorize's place-or-move opportunity. The card does not contain an explicit repeat count or the word “once”; this is a grammar composition, not a Grumman-specific FAQ quotation. It does not authorize an add/remove loop generating repeated income. Retain a turn/phase completion receipt independent of the ordinary Mentat `placementTurn`.
For addition, select one available physical Terror token and a permitted stronghold already holding a placed token. The card supplies an exception to ordinary Terrorize's empty-destination requirement; it does not authorize a new token, a second ordinary Mentat placement, relocation from another stronghold, Homeworld placement or use of the Hidden Mobile Stronghold. Storm alone does not prevent ordinary Terror placement. [GF9 E3, pp.5,16](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=5).
For removal, select one actual placed token. A spent token, the separate Atomics Aftermath marker, an available supply token or a revealed Extortion record is not a Terror token on the board. The face says removal from the board; it does not expressly name its next custody zone. Returning it to hidden supply is a plausible composition, while ordinary **revelation** expressly removes tokens from the game. Do not claim the latter as authority to permanently spend an unrevealed removal, or call `revealTerror` merely to clear its location. The removal destination remains a source boundary for the coordinator; no new question was sent by this audit.
Token change and four-spice credit must be one accepted transaction after checking current high population, valid custody, phase and unused opportunity. Reject before mutation or randomness if any check fails. Preserve the six physical identities and every other placed token. If returning a token to hidden supply is adopted from sufficient authority, use the established identity-rotation contract so a previously known face cannot be followed through a persistent public ID.
Stacking is a genuine new registry condition. Remove only the global one-token-per-location assumption; retain unique physical identity, exactly one location/status per token and valid stronghold locations. Ordinary Mentat placement still requires an empty destination. Never overwrite an existing token merely because both share a location.
## Grumman low entry restriction
The recorded low face, zero through seven native forces, permits Terror revelation only when at least three forces enter its territory. The base Terror rule includes entering advisors and excludes Moritani and its ally. Existing presence is not an arrival. The threshold does not force revelation. [GF9 E3, p.5](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=5).
Count the current completed entry group, not the territory's population after arrival. Regular and special counters each count one physical force; do not double Sardaukar, Fedaykin or Cyborg battle strength. Count entering advisors as the ordinary Terror rule explicitly includes them. A legal move combining several sectors into one entering group uses that combined entry count. Separate shipment, movement and accompanying-advisor events do not accumulate toward three; stationary allied forces do not enlarge another faction's incoming group.
A concealed No-Field counts as one force regardless of its private 0/3/5 value. The ordinary Terror FAQ identifies its placement as an entry, including zero; it does not waive Grumman's additional low restriction. Thus a lone concealed marker fails three, while a legally admitted single move of two physical newcomers plus that marker reaches three. Do not read its secret value or force a reveal to compute eligibility. Revealing an already-present No-Field and Face Dancer replacement are not new Terror entries. This combines the ordinary marker-presence rule with the Homeworld restriction. [GF9 E2, p.6](https://www.gf9games.com/dune/wp-content/uploads/2021/11/CHOAM-Rulebook-low-res.pdf#page=6), [GF9 E3, p.14](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=14).
Keep the original public entry count through a pending decision; later group changes must not rewrite which event happened. Current native population controls whether the low penalty currently applies. A mid-response population change and Enemy of My Enemy's compulsory-refusal revelation need their existing continuation checks; a disallowed low entry must not be used to manufacture an alliance offer whose refused outcome cannot legally reveal. Retained occupied penalties remain subject to the existing occupation boundary.
## Multiple placed tokens and private choices
The ordinary rule permits Moritani to choose a Terror token to reveal. With a stack, a first-array-element lookup cannot stand in for the owner's choice. Present the owner the actual eligible placed identities, preserve their secret faces for every other seat and keep decline available. The singular entry opportunity supports selecting one token; no retrieved Grumman FAQ expressly discusses activating several stacked tokens from the same entry. Treat one-choice handling as ordinary trigger composition, not as an invented automatic all-token resolution or a claim of a dedicated stacking clarification.
Bind the selected token and immutable original entry to the saved continuation. Validate all current candidates remain at that location, and ensure relocation/removal cannot consume a reserved token during its pending trigger. Place/remove operations do not themselves activate Terror or reveal a hidden face. A successful Grumman Collection operation should not expose the removed token's type through logs, errors, public IDs or arbitrary supply ordering.
## Verification handoff
Test Giedi's first positive desert receipt, multiple pools still totaling two, desert-versus-stronghold deposits, shared zero/positive allocations, high/low boundaries, unrelated Collection-phase income and no replay across JSON restoration. Homeworld income and indirect sharing require the separate occupation source decisions.
Test Grumman addition and removal with exact custody and four-spice conservation, decline and unavailable operations, separate Collection/Mentat usage, storm and location rules, stacked owner selection, three physical elites versus two, advisors, combined and separate entry groups, stationary forces, concealed marker getter traps, original entry binding and low-state rejection without token disclosure. Extend SQLite continuation tests once runtime producers exist.
Only this document was written. Local links and whitespace were reviewed; no runtime, database, reference or implementation-status change and no gameplay verification claim follows from this audit.
+96
View File
@@ -0,0 +1,96 @@
# Giedi collection and low Grumman entry
This checkpoint connects two population effects. The complete Homeworld module,
Moritani faction and expansion starts remain gated. Printed component evidence,
the No-Field composition and Grumman's unresolved removal destination are in
[the source audit](HOMEWORLD_COLLECTION_RULES.md). The broader integration map is
in [the collection audit](HOMEWORLD_COLLECTION_INTEGRATION.md).
## Automatic Giedi Prime income
`board-resolution-quote.ts` separates actual desert collection from other map
deposits and stronghold income. The engine first commits ordinary balances,
then quotes Giedi's two bank spice using current physical native population.
Seven native reserves qualify in both Basic and Advanced. Multiple deposits
earn two total; technology and stronghold income do not qualify.
Ecaz joint desert lots remain escrow until their allocation settles. A positive
Harkonnen allocation can earn the first Giedi bonus; a zero allocation cannot.
An earlier ordinary desert bonus prevents another payment after shared income.
Canceling Ecaz's ordinary stronghold Collection advantage does not cancel Giedi.
Homeworld occupation income remains unfinished and has no new producer here.
`giedi-collection.ts` records turn, owner, cumulative actual qualifying income
and whether the bank bonus was paid. A canonical signature detects inconsistent
saved receipt fields at action, view and normalization boundaries. The receipt
is completed evidence, never a command to pay on read. Older saves without the
whole receipt remain compatible: they receive no reconstructed or retrospective
award. A newly settled positive share can still qualify. Whole-receipt absence
cannot be distinguished from legacy state and is not a claimed corruption check.
The public chronicle explains the automatic two-spice payment and supplies the
existing optional faction animation event. There is no new confirmation or AI
decision. Private balance and hand visibility remain unchanged.
## Low Grumman
The shared entry restriction checks fewer than eight native reserves and an
original entering group smaller than three. Physical special counters count
once; entering advisors count; existing destination forces do not. A concealed
No-Field counts as one independently of its private value. Two physical forces
and that marker in the same admitted movement form a group of three.
The restriction applies before competing reactions are declared and again at
actual entry, revelation and an alliance offer whose refusal requires Terror.
Ordinary movement, shipments, advisor arrivals and Ambassador continuations use
the same predicate. Guild and Fremen Ambassador choices project a maximum of
two where larger groups would require unresolved simultaneous Intrusion/Terror
ordering. Their controls and all four bot policies honor that limit.
The original public entry facts are bound to a canonical saved signature;
mutable resolution stages do not change the original count. The binding also
covers suspended Terror discard continuations. Current population can change
the low restriction, while the saved entering group cannot be rewritten.
Missing signatures remain legacy-compatible; present inconsistent signatures
must reject rather than repair the entry from current board forces.
High Grumman's optional Collection token change and four-spice payment remain
unfinished. No stacked-token or removal-destination interpretation is enabled
by these changes. The question about unrevealed removal custody is pending,
alongside the earlier occupation and low-Junction rounding questions.
## Verification scope
Final `npm run check` passes types, lint and **3,575 offline cases**. The final
production build and **40 HTTP cases** pass. There are 34 new cases: eight pure
quotes, seven Giedi engine cases, four Giedi SQLite cases, twelve Grumman engine
cases and three Grumman SQLite cases. The existing stale-Terror regression now
checks both signed receipts and legacy unsigned saves. Final check evidence is
in `/tmp/dune-collection-verified-check.log`, with build and HTTP evidence in
`/tmp/dune-collection-final-build.log` and `/tmp/dune-collection-final-http.log`.
The pure, engine and production SQLite suites cover population thresholds,
actual receipt provenance, shared allocations, rejection immutability,
simultaneous submissions, private projection and JSON/database restoration.
Grumman regression cases cover original entry counts, concealed marker equality,
advisors, elite counters, competing reactions and all four Ambassador bot levels.
These subsystem checks do not certify complete games with the module.
A three-seat browser table collected seven desert spice and automatically added
two bank spice, reaching Harkonnen's balance of 29 from 20. Keyboard completion,
three-seat refresh, private balances and desktop/390-pixel phone layouts passed.
Both chronicle screenshots were visually inspected. The initial capture waited
for chronicle text while the hand tab was selected; opening the chronicle fixed
the test harness, with no repeated gameplay action or application change.
The controlled development-server restart preserved all 2,958 existing room
versions and state hashes. Three saved payment-test seats reconnected at their
original version and balances without browser errors. The new collection QA
room and HTTP test rooms are additive. No saved game was reset, and no recurring
automation was installed.
At the end of verification, the database contains 3,019 rooms: the 2,958 unchanged
baseline rooms, one new collection browser table and 60 rooms from the two HTTP
runs. The collection table remains at version four with one completed bonus
record. Private saved-seat files and the database backup remain local temporary
artifacts and are not included in version control.
+23
View File
@@ -0,0 +1,23 @@
# Homeworld combat foundation and Salusa support
9 September 2026. This extends the native-reserve runtime. Homeworld invasion and live off-planet battle actions remain unavailable; no start gate is opened.
## Connected Salusa behavior
In Advanced Homeworld development games, maintaining at least two Sardaukar on Salusa grants free support to the Emperor’s Sardaukar wherever they fight. Normal forces retain their ordinary support costs. The shared combat calculation uses a separate optional elite-support flag, so ordinary Sardaukar Karama can reduce their strength without canceling the Homeworld benefit. Shipping a fourth Sardaukar away from the initial five leaves Salusa low and removes free elite support. Normal reserves transferred there do not replace the named population threshold.
Server plans, typed casualty options, Stone Burner comparisons, the private player view, all four AI policies and the table’s support maximum share this calculation. Saved casualty decisions preserve the relevant force snapshot. Legacy snapshots without the optional flag retain their existing behavior. Salusa’s low free-revival prohibition and occupation penalty remain unfinished.
## Off-planet foundation
`game/homeworld-combat.ts` reads exact native and visiting typed custody into detached public armies and non-allied battle pairs. It validates player order and reciprocal alliances without adding fictional sectors or strongholds to Arrakis.
The pure battle-resolution quote accepts an explicit native card, face and physical army. It adds the printed native strength without increasing dial casualties, restricts traitor callers to the native combatant, and quotes native Lasgun/Shield losses separately from invading army destruction. Two visitors can fight with no traitor voters; a noncombatant native still retains the explosion protection. Basic Homeworld outcomes preserve typed physical losses.
These quotes are not yet wired into live off-planet battle discovery, aftermath, force removal, Face Dancers or occupation. The engine must consume the separate native explosion choice before transport opens. See the [integration audit](HOMEWORLD_COMBAT_INTEGRATION_AUDIT.md) and [invasion source audit](HOMEWORLD_INVASION_RULES.md). Current invasion/occupation interpretation questions remain pending.
## Verification
Focused checks pass 62 combat/Stone Burner cases, 29 battle-resolution cases, nine Homeworld army/discovery cases and eight Salusa engine cases. These groups overlap existing regression coverage and are not a combined full-suite count. The Salusa cases use genuine Advanced setup, typed shipments and actual battle preparation, sealed plans, traitor actions and casualty settlement. They cover high/low transitions, normal support costs, ordinary Karama, JSON restoration, opponent privacy, physical conservation and legal decisions from every AI level.
The first integrated pass passed **3,218 offline cases**, typecheck, lint, production build and **40 HTTP cases**. Independent review then reproduced a Ghola deadlock: raising Salusa from one to two Sardaukar during combat could invalidate an already sealed paid-support plan. A temporary explicit release boundary now blocks only that population-changing Sardaukar Ghola return during the Emperor’s battle, before any card or force moves. Regressions cover both a sealed plan and a binding prescience dial before either full plan, JSON rejection without mutation, subsequent battle completion and the later legal Sardaukar return. The player view, AI allowance and controls expose the same restriction; ordinary force and leader targets remain available. This is an unfinished interaction, not an official prohibition. The final check after the guard passes **3,221 offline cases**, typecheck and lint; the final production build passes. The 40 HTTP cases passed before the guard; the guard’s new coverage executes production engine actions with JSON restoration. All **2,648** earlier baseline rooms retain their versions and state hashes. No new browser acceptance was performed for this slice. No live Homeworld invasion, complete Homeworld game, full module combination or browser acceptance is claimed by this checkpoint. The recurring automation remains removed.
@@ -0,0 +1,81 @@
# Homeworld combat integration audit
Read-only architecture audit, 9 September 2026. The contract is [Homeworld rules](HOMEWORLD_RULES.md), with transport/occupation boundaries in [invasion rules](HOMEWORLD_INVASION_RULES.md). This document identifies adapters required for actual combat; it does not enable Homeworlds or certify complete games. Line numbers below identify the inspected worktree and may shift during concurrent implementation; function names are the durable anchors.
## Current boundary
Native and visitor inventory already has an independent representation: `homeworldForceGroups` and `quoteHomeworldCustody` in [homeworld-custody.ts](../game/homeworld-custody.ts) return exact `{normal, elite}` groups and detached transactions. Native primary counts derive from player reserve totals; Salusa is an allocation inside Emperor's total. Visitor groups are separate and never belong in `Player.forces`. `homeworldPopulations` supplies the printed card, native owner, current side and bonus, but deliberately does not resolve occupation entitlements.
The concurrently added [homeworld-battle-rules.ts](../game/homeworld-battle-rules.ts) and Homeworld branch of [battle-resolution-quote.ts](../game/battle-resolution-quote.ts) already accept an explicit native/card/side/army contract. At inspection, the pure result can add native strength, restrict traitor callers and return typed native explosion losses. **The live engine does not yet supply this contract or consume the explosion result.** A calculator result is not evidence of live battle support.
Keep `gameTerritories`, `validLocation`, `splitLocation`, storm geometry, territory occupancy and stronghold control restricted to their existing Arrakis/HMS domain. Do not add a fabricated `homeworld:…:0` force key or append Homeworld cards to `TERRITORIES` to make existing validators pass.
## Minimum adapter contracts
Introduce one explicit combat-location resolver used by discovery, plans, resolution, aftermath, bots and controls. A discriminated location `{kind:'territory', id}` or `{kind:'homeworld', id}` can coexist with legacy saved `Battle.territory` strings through a strict decoder. The resolver must reject unseated worlds and Basic Salusa. It should supply:
- A stable canonical identity and display name; territory geometry only for the territory variant.
- Current physical armies by seated player, with native versus visitor provenance on Homeworlds. Public presence must not inspect concealed No-Field values.
- For a Homeworld, its native owner, card, applicable side and printed native bonus; use this only for that native faction's score. Preserve occupation as a separate input once its lifecycle is settled.
- Legal combatant pairs, current attacker order, entitled traitor callers, and eligible Face Dancer owner.
- A detached casualty transaction and receipt that binds exact source pool, normal/elite losses, Tanks deltas and resulting custody. This must also serve replacement/return effects without conflating them with deaths.
Do not require the native to be one of the two combatants: multiple visitors can fight each other. There is no Homeworld stronghold-capacity rule. Use the ordinary opposing-faction and turn-order rules for discovery without inventing native-first ordering. Allied noncombatants remain relevant to an explosion even when they do not fight each other.
## Live function map
| Boundary | Inspected code | Required adaptation |
| --- | --- | --- |
| Battle frontier | `quoteBattleBoard`, [board-resolution-quote.ts](../game/board-resolution-quote.ts):93; `battles`, [engine.ts](../game/engine.ts):8650 | Retain the planet quote, then compose a separate Homeworld conflict quote from custody and current order. No `gameDistance`, storm sector, advisor merge, Polar Sink exclusion or stronghold capacity applies to a world. Preserve the original advisor-release operations for planet battles. |
| Phase progress | `quoteBattleBoardContinuation`:364; `currentBattleAftermathQuote`, `finishBattle`; phase-6 initialization and automatic response normalization | Every test for “no remaining battles” must use the same combined frontier. Updating only `chooseBattle` would allow automatic advance to Collection while a Homeworld conflict remains. Preserve aid refunds and the existing CHOAM/Ix opening boundaries. |
| Choice and opening | `chooseBattle` action, `engine.ts`:17398; `Battle` type:480; `beginStrongholdBattle`, `beginBattlePowers` | Validate the selected canonical location/pair against that frontier; persist its identity in the battle event. Use normal sealed preparation. Stronghold copy/effects remain unavailable on Homeworlds; ordinary Voice, Prescience and other faction powers retain their independent scope. Do not add Homeworld bonus cancellation windows. |
| Force commitment | `combatForces`:3453; `validatePlan`:9972; `feasiblePrescience`:10912; `prescienceAnswer`; plan completion/truth helpers | Replace the board-force reduction with the exact location army. Continue to reuse `CombatForces`, `casualtyOptions`, leader/card legality and aid pricing. Basic dial parsing in `prescienceAnswer` currently caps against `at(p,b.territory)` and also needs this adapter. Audit plan-completion simulations, not just final plan submission. |
| Final pure input | `currentBattleResolutionQuote`:11160 | Supply `homeworld` from authoritative custody and current applicable face. Keep stronghold benefits null. Bind the actual native army, including when it is a noncombatant; do not infer it from a visitor's counters. Keep private hands and traitor identities server-only. |
| Removal preflight | [force-loss-preflight.ts](../game/force-loss-preflight.ts) `validateBattleForceLoss`; `currentBattleResolutionQuote` | The existing validator checks canonical sector keys only. Add Homeworld pool preflight through the custody quote, including aggregate reserve and Tanks consistency. Do not relax board-key checks. |
| Removal commit | `kill`:3402; `killTerritory`:3431; `takeBattleLosses`:3490; `resolveBattle`:11228; `settleWinnerCasualties`:11460 | Dispatch by location. Native deaths withdraw from the exact primary/Salusa pool and increment Tanks; visitor deaths withdraw from visitors and increment that faction's Tanks. Update elite Tanks and battle-loss counts exactly once. Ordinary deaths must not become reserve returns. |
| Delayed choices | `continueResolvedBattle`, `battleLosses`, `settleWinnerCasualties`, `pendingIxSubstitution`, `ixSubstitution` decision/response | Reuse owned casualty choices and automatic singleton handling, but bind them to a typed Homeworld pool. Ix substitution currently stores sector-key loss/source/recovery maps and directly reads board forces: it needs location-aware records and a real survivor/cyborg exchange. |
| Aftermath | `currentBattleAftermathQuote`:11500; [battle-aftermath-quote.ts](../game/battle-aftermath-quote.ts); `battleCleanupInput`:11762; [karama-battle-preflight.ts](../game/karama-battle-preflight.ts) | Replace the `territoryIds = gameTerritories(...)` validation boundary with explicit valid combat locations. Carry identical location identity through capture, Auditor, card retention, tech transfer and Face Dance. Keep their established sequencing and ownership; accepting a Homeworld identity must not grant territory-specific effects. |
`offerMoritaniDuke` is another consumer of `battles(g)`: it currently calls `territory(battle.territory).type`. Once the combined frontier is returned, filter the territory variant before the stronghold predicate. Homeworld combat does not qualify as a stronghold battle for this power.
## Strength and casualty details that need explicit handling
`CombatForces.freeSupport` is currently one boolean for the entire army. The Salusa high face gives **Sardaukar** free support, including when normal forces have been transferred there. Setting the existing boolean would accidentally make normal forces free too. Extend the shared arithmetic to represent per-type free support, then use it in `casualtyOptions`, plan validation, pure support payment, saved casualty validation, bots and the plan wheel. Preserve Basic strength-one starred counters, Ix fixed-half Suboids and the independent Emperor-versus-Fremen exception. Salusa occupation's loss of Sardaukar advantage is a separate printed modifier; it cannot be implemented as ordinary Karama cancellation.
The native printed bonus is a score addition, not additional physical counters, a larger dial, a spice-support charge or ordinary winner casualties. The source's “current” bonus should be supplied by the authoritative resolution adapter. Do not silently lock a high face for the whole battle merely because its opening was saved; conversely, once a resolution is committed, its receipt must retain the accepted effective facts while delayed casualties change population.
For Lasgun/Shield, `resolveBattle` currently loops through all players and calls `killTerritory(...,Infinity,true)`; it ignores the new pure `homeworldExplosion` result. The Homeworld branch must destroy actual foreign armies and commit only the native printed casualty count, capped by available natives. When multiple normal/elite allocations exist, create a native-owned casualty choice with a saved event; when only one exists, apply it automatically. Both combatants still lose and leaders die according to the explosion result. Preserve surviving natives and recalculate population after actual losses. Do not carry this named exception into Stone Burner, mutual Traitors, ordinary losses or arbitrary board destruction.
The exploding native may be a noncombatant. Test this explicitly: using the winner's ordinary casualty continuation alone cannot represent the choice because an explosion has no winner. An empty native army must not create a meaningless confirmation. Resolve the native choice before any successor consumes the final custody/occupation state.
## Traitors and Face Dancers
`traitorVoters` currently returns both combatants and sometimes a remote Harkonnen ally. On a Homeworld return only the native if it is a combatant. A native who is not fighting cannot become a remote traitor beneficiary; two visitors fighting therefore have no traitor voters. The same helper feeds `traitorCall`, automatic decline/resolution, cancellation preflight and projected `traitorVoters`; change them together to avoid an invisible waiting decision. Preserve revealed-card reactions, including Stone Burner and Poison Tooth, before automatic zero-voter resolution.
`resolveBattle` currently creates `pendingFaceDance` for any Tleilaxu seat when somebody else wins. On a Homeworld, only native Tleilaxu may receive that opportunity. A remote Tleilaxu cannot call on another faction's world, even for an ally. The occupied Tleilax immunity for an occupier/ally is a separate condition to compose when the occupation contract is available.
The `faceDance` decision (`engine.ts`:15526) currently requires a sector and uses `at(winner, territory)`, board source keys, direct reserve decrements, direct winner reserve returns and `place`. The Homeworld branch must instead quote the remaining winning foreign army, selected permitted Tleilaxu replacement sources, and a destination deposit into native Tleilax custody. Return the actual winner's normal/elite pieces through the native-return adapter, preserving Emperor's distinct pools and any unresolved return-routing interpretation. Preserve leader death, shared Cheap Hero identity, revealed-dancer custody and deck refresh. Source scope of replacement sources must be audited explicitly; the old `reserves`/sector parser does not authorize arbitrary foreign garrisons.
## Recovery boundaries
The mandatory battle-discard validator (`engine.ts`:3080–3252) both requires `gameTerritories(...).some(...)` and rechecks winner casualties by reducing `winner.forces`. It will reject an otherwise valid Homeworld battle even after the live resolver is adapted. Carry explicit combat identity and exact pool snapshots into `battleResolved`, `battleCleanup`, `lastBattleContext`, casualty choices and any new explosion continuation. Revalidate nested saved parents before read/action/normalization effects, including Nullentropy or other interruptions of those decisions.
Receipts must distinguish “resolution committed, typed losses pending” from “losses already committed, cleanup pending.” Do not rederive a completed native bonus after casualties flip its card or rerun support payment, bounty, leader death, card discard, tech transfer or capture on refresh. Same-total Salusa/native/visitor reallocations must invalidate a receipt bound to a different pool. Existing territory-only saves should continue through their current decoder and checks.
Atreides high reinforcement belongs after the appropriate completed winner/casualty sequence and requires a surviving own force at that combat location. It needs an owned optional reserve-transfer action, not a new ordinary shipment. Do not fold occupation rewards into generic battle victory: presence changes and qualification events need their own event-bound settlement, and the unresolved occupation cases remain documented in the source contract.
## Bots and controls
`viewGame` already projects owner-only `battle.ownForces`, sealed own plans, revealed plans and entitled prescience separately. Reuse that privacy boundary and add public combat location/name, native bonus and public opponent army counts. Do not expose a server-side `ResolutionCombatant` object; it contains private cards.
[bot-battle-choices.ts](../game/bot-battle-choices.ts) independently reconstructs only planetary battles. Replace that duplication with shared legal combat choices. In [bots.ts](../game/bots.ts), `plans` already prefers `b.ownForces`, but its opponent estimate uses `presenceAt(other,b.territory)` and would see zero defenders on a Homeworld. Update both legal candidates and strength estimates with the public adapter; add native bonus to evaluation, not dial. Face Dance strategy currently selects board sectors; Ix substitution and explosion choices also need exact legal descriptors for all four difficulty levels.
[game-table.tsx](../components/game-table.tsx) prefers `ownForces` but still uses `territory(g.battle.territory).name` in the battle heading and multiple cleanup/replacement labels. Use the combat display adapter; no sector selector should appear for a Homeworld-only target. Show the native bonus separately from the dial, per-type support costs, exact casualty pools and clear decision ownership. Mandatory single-option effects remain automatic with existing animation notices; optional replacement/casualty choices stay actionable after reload.
## Evidence required before enabling
Use actual dispatcher paths from a conserved invasion fixture through battle choice, sealed plans, reveal, owned casualties, card disposal and aftermath. Cover native/visitor and visitor/visitor pairs, ordinary turn order, allied third-party explosion losses, zero-voter automatic progress, remote Harkonnen/Tleilaxu rejection, Basic starred identity, mixed Salusa forces, population crossings, ordinary traitor losses and the explosion exception. Check typed Ix substitution and native Tleilax Face Dance without creating counters.
Test JSON and in-memory D1 recovery before/after each committed stage, concurrent final plans, duplicate casualty submissions and corrupted exact-pool receipts. Demonstrate all four bots can finish these paths without secret information. Browser-check Homeworld battle selection, sealed plan controls, native bonus, typed support/casualty choices, Face Dance, labels and refresh on desktop/mobile. Broader setup-to-endgame and every-faction/module evidence remains necessary for the full release gate.
This audit changed only this document and ran no game, test suite, server or saved-room operation. Current pure-calculator edits were observed, not independently certified. Occupation lifecycle and other existing source ambiguities remain unresolved here.
+116
View File
@@ -0,0 +1,116 @@
# Homeworld component audit
Verified 9 September 2026. All 13 physical cards, both faces, have now been visually inspected. The tables below preserve the gameplay facts in original wording; they are not a transcription or a claim that the Homeworld module is implemented. Global module rules and unresolved compositions belong to [HOMEWORLD_RULES.md](HOMEWORLD_RULES.md).
## Sources and completeness
- **Publisher inventory:** [GF9 E3 rulebook](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf), printed p.4, lists **13 Homeworld cards and 13 matching tokens**. There are 12 factions: Emperor has Kaitain and the Advanced-only Salusa Secundus. Local page `/tmp/dune-rules/ecaz-p4.png` was visually checked; the count is not on printed p.3.
- **Independent physical photograph:** [Jaakko/zaksalo, BGG image 7767034](https://boardgamegeek.com/image/7767034/dune-ecaz-and-moritani), posted 2 October 2023, shows all 13 high faces and matching tokens. Public metadata API `/api/images/7767034` supplied the original 3024×4032 photograph. Local inspection file: `/tmp/dune-rules/homeworld-bgg-high.jpg`.
- **Complete front/back face sheets:** [C4ESIUM, “Every Homeworld cards”](https://www.reddit.com/r/DuneBoardGame/comments/16w27x0/every_homeworld_cards/), 30 September 2023. Its public RSS feed supplied four direct physical-face images; all were visually read. These are third-party-hosted depictions of the original components, not authority from comment replies. Their production provenance cannot be established from the post alone. The independent BGG photograph corroborates every high face. No fan interpretations are adopted.
- **Designer corroboration:** [Jack Reda, Homeworlds Revealed](https://www.youtube.com/watch?v=4KZKz13wf9c), linked by [Future Pastimes](https://futurepastimes.com/dune-ecaz-moritani). Public preview sheets `/tmp/dune-rules/homeworld-story-0.jpg` through `-14.jpg` show selected enlarged original faces. Particularly useful: Caladan high around 8:55; Kaitain low around 1:50 and 3:00; Tupile low around 2:15; Junction occupied around 4:00; Tupile occupied around 4:35. Only visible text was used; the captions request returned empty and no unverified spoken statement is credited.
The complete sheets are `/tmp/dune-rules/homeworld-reddit-face0.png` (seven base high faces), `face1.png` (their reverses), `face2.png` (six expansion high faces), and `face3.png` (their reverses). These research images are not application assets or redistribution permission.
## Canonical physical manifest
Each row is **one two-sided card plus one matching world token**. High and low ranges are printed inclusive ranges, not an inferred universal flip algorithm. Battle numbers are native faction additions to its dial in battles on that world. The card prints the same number as its native losses from a Lasgun/Shield explosion. Occupied icons are counted separately from the occupied text.
| Proposed card ID | Printed name | Runtime faction | High reserves | Low reserves | High battle / explosion losses | Low battle / explosion losses | Occupied spice icons |
|---|---|---|---|---|---|---|---|
| `caladan` | Caladan | `atreides` | 6–20 | 0–5 | 2 | 2 | 2 |
| `giedi_prime` | Giedi Prime | `harkonnen` | 7–20 | 0–6 | 2 | 2 | 2 |
| `southern_hemisphere` | Southern Hemisphere | `fremen` | 3–20 | 0–2 | 2 | 2 | 2 |
| `junction` | Junction | `guild` | 5–20 | 0–4 | 2 | 2 | 2 |
| `wallach_ix` | Wallach IX | `beneGesserit` | 11–20 | 0–10 | 3 | 2 | 1 |
| `kaitain` | Kaitain | `emperor` | 5–20 | 0–4 | 2 | 3 | 2 |
| `salusa_secundus` | Salusa Secundus | `emperor` | **2–5 Sardaukar** | **0–2 Sardaukar** | 3 | 2 | 0 |
| `ix` | Ix | `ixians` | 5–20 | 0–4 | 2 | 2 | 2 |
| `tleilax` | Tleilax | `tleilaxu` | 9–20 | 0–8 | 2 | 2 | 2 |
| `tupile` | Tupile | `choam` | 11–20 | 0–10 | 2 | 2 | 2 |
| `richese` | Richese | `richese` | 10–20 | 0–9 | 2 | 2 | 1 |
| `ecaz` | Ecaz | `ecaz` | 7–20 | 0–6 | 2 | 2 | 2 |
| `grumman` | Grumman | `moritani` | 8–20 | 0–7 | 2 | 2 | 2 |
All ranges except Salusa name the faction's reserves, not a special force type. Do not substitute Arrakis for the Fremen card's printed name, Junction for CHOAM, or the Tleilaxu faction name for the world Tleilax. Card IDs above are implementation proposals, not printed identifiers; engine custody zones can have distinct stable IDs.
## Verified high-side effects
| Card | Gameplay facts |
|---|---|
| Caladan | After winning a battle, Atreides may add one reserve force to its battle territory or homeworld, provided Atreides already has a force there. |
| Giedi Prime | Harkonnen receives 2 bank spice when it collects spice from any desert territories or homeworlds during that turn's Spice Collection. |
| Southern Hemisphere | A revived starred Fedaykin force may immediately be placed in any territory already containing Fremen forces. |
| Junction | Guild may offer another faction cross-planet shipment, at half or full price, as part of that faction's Shipping action. This includes travel to or from homeworlds, including the shipper's own. |
| Wallach IX | When accompaniment to another faction's shipment sends spiritual advisors to Polar Sink, BG may send two. |
| Kaitain | At the end of Bidding, Emperor may pay 2 spice for each Treachery Card it chooses to discard from its hand. |
| Salusa Secundus | Sardaukar do not require spice support to count at full strength. |
| Ix | Paying to revive a Cyborg also grants two free Suboid revivals. |
| Tleilax | On taking Free Revival, Tleilaxu may send those forces from reserves, without shipping cost, to one territory or homeworld; storm and occupancy restrictions still apply. |
| Tupile | CHOAM cannot exchange Worthless Cards for spice, except through its Advanced Karama. This high side is a penalty. |
| Richese | Reserve forces may accompany a No-Field token shipment. |
| Ecaz | Each poison-weapon discard yields 3 bank spice. Its alliance also has a victory route: jointly occupy at least one stronghold and occupy two other factions' homeworlds. |
| Grumman | During Spice Collection, Moritani may either add a Terror token to a stronghold already holding one, or remove a Terror token from the board; it then receives 4 bank spice. |
These are source scopes, not completed adapters. For example, Giedi Prime's collection award is not automatically repeated for every pool; Kaitain's discard is a paid choice, and Tupile's exception does not erase its high-side restriction.
## Verified low-side effects
Every low face **except Salusa Secundus** also explicitly grants **one extra Free Revival and one extra CHOAM Charity spice from the bank**. The extra Charity is not a payment from the CHOAM player. Salusa prints neither bonus, corroborated by E3 p.10.
| Card | Additional low-side gameplay |
|---|---|
| Caladan | Atreides cannot use its Movement advantage to inspect the next Spice Blow. |
| Giedi Prime | No additional penalty. |
| Southern Hemisphere | No additional penalty. |
| Junction | Guild receives only the rounded-up half of shipping payments. |
| Wallach IX | BG cannot send spiritual advisors. |
| Kaitain | Emperor receives only the rounded-up half of Treachery Card payments. |
| Salusa Secundus | Sardaukar cannot be revived for free. |
| Ix | The Hidden Mobile Stronghold cannot be moved. |
| Tleilax | If Tleilaxu starts the Revival phase low, it receives no spice for other factions' Free Revival that phase. The start-of-phase condition is printed and requires a timing snapshot. |
| Tupile | Once per faction, when CHOAM is on another homeworld or another faction is on Tupile, CHOAM can require that faction to disclose its spice and the number of weapons or defenses it holds. |
| Richese | A No-Field token cannot be moved. |
| Ecaz | When Ecaz and its ally are both present for a battle against another faction, the opponent chooses which allied faction fights. |
| Grumman | A Terror token can be revealed only if at least three forces enter its territory. |
## Verified occupied-side effects
The occupied block is on the reverse alongside the low block; it does not replace the still-active low penalty. Printed yellow spice symbols are distinct from the income/payment-sharing instructions below. E3 p.10 assigns occupied Homeworld income to Spice Collection and the bank, and the source reviewer independently confirms each symbol represents one additional bank spice, separate from the text-dependent payment splits.
| Card | Occupied text gameplay |
|---|---|
| Caladan | The occupier shares Atreides' Bidding advantage. |
| Giedi Prime | When Harkonnen buys Treachery Cards, the occupier or its ally receives Harkonnen's extra free card if the recipient has hand room. |
| Southern Hemisphere | The occupier receives the rounded-down half of all spice collected by Fremen during Spice Collection. |
| Junction | The occupier receives the rounded-down other half of shipping payments made by other players. |
| Wallach IX | The occupier and its ally are immune to Voice. |
| Kaitain | The occupier receives the rounded-down other half of Treachery Card payments received by Emperor. |
| Salusa Secundus | Sardaukar lose their Sardaukar advantage. |
| Ix | The occupier controls the Ixian Bidding advantage. |
| Tleilax | Tleilaxu cannot reveal Face Dancers against the occupier or the occupier's ally. |
| Tupile | The occupier and its ally each gain one hand slot; they discard to their ordinary limits once they cease occupying Tupile. CHOAM loses its low-side advantage. |
| Richese | The occupier chooses the Richese Treachery Card offered during bidding and receives the rounded-down half of the payment received by Richese. |
| Ecaz | The occupier or its ally gains Duke Vidal and may revive him from the Tanks; this overrides the Ecaz/Moritani Duke advantage. |
| Grumman | Terror cannot be revealed when the occupier or its ally enters a territory holding a Terror token. |
## Source discrepancies and catalog boundary
1. **Caladan:** both independent physical-image sets and the designer's visible close-up print battle bonus 2 and explosion losses 2. The E3 p.10 example says high Caladan loses 3, while the actual rule delegates the value to the card. The coordinator/source reviewer therefore adopts the explicit face value **2** and records the inconsistent example; no missing card fact remains here.
2. **Salusa ranges overlap:** high 2–5 and low 0–2 are verified on the actual faces. Do not encode one threshold number or silently change low to 0–1. A stateful return-to-high interpretation is discussed by third-party commenters but was not independently verified from designer speech in this audit. The coordinator adopts the rulebook’s operative minimum-high rule: **2 is high**, treating the overlapping low endpoint as inconsistent printed data. Both ranges remain in the catalog; it does not implement this transition itself.
3. **Salusa counted reserves:** both faces name Sardaukar. The rules also permit Emperor movement between its two worlds. A future threshold evaluator must resolve what happens to normal forces transferred to Salusa without pretending the printed label is generic.
4. **Tupile information scope:** the designer close-up confirms CHOAM must be **on another homeworld**, or another faction must be on Tupile. An initial audit reading omitted the small word “on”; this was corrected through independent visual review. No planet-moving effect is printed.
5. **Occupier timing/custody:** a catalog cannot decide when a persistent occupier's power ends, competing occupiers, Duke return, private answers, paid-card redirection, or interrupted discard/refill timing. These remain runtime work and any independently identified rulings in the global audit.
Proposed catalog contract: one immutable definition per row; faction and name; `reserveType: 'faction' | 'sardaukar'`; `high` and `low` each containing their own inclusive reserve range, native battle strength and readable gameplay; `occupied` containing readable gameplay and the verified icon count. The catalog is inspectable reference data, not permission to enable module starts or an executable payout/threshold engine.
## Research file checksums
| File | SHA-256 |
|---|---|
| BGG high photograph | `1200b1f3a12c963dc5e58d06fc19de879f5f9d2768557c178ce37237c8046295` |
| Base high sheet | `d3fbf506c2bb697d0f6b4c497c731d5e3138bb3be60d2363607b54ebab7c2c54` |
| Base reverse sheet | `10a2e53c5d6ee8e7ae67f9761a0c64d0f6d36abfec40d863b6b1119af0ad048d` |
| Expansion high sheet | `dfbbb9bb3776899633617a351c7921ed3d64bf25b6780d0722484afca9d1ebaf` |
| Expansion reverse sheet | `950e39c320b66b12749d1fc971489482b0053766358b9ac558c93333977e9523` |
No production files, game states, application artwork or databases were changed by this audit. No individual face remains missing.
+108
View File
@@ -0,0 +1,108 @@
# Homeworld component and custody foundation
Historical component checkpoint. Subsequent setup, native shipment/revival,
Emperor movement, controls, AI and recovery work is recorded in
[HOMEWORLD_RUNTIME_IMPLEMENTATION.md](HOMEWORLD_RUNTIME_IMPLEMENTATION.md).
9 September 2026. This checkpoint adds the complete public Homeworld card
collection and isolated physical-state helpers. **Homeworld gameplay is not
enabled.** It does not certify the complete module, any expansion or Advanced
play.
## Implemented boundary
- `game/homeworld-cards.ts` contains 13 immutable two-sided definitions, one
per physical card/token pair, covering all twelve factions. Both faces include
original gameplay prose, population ranges, native battle/explosion values
and occupied Collection symbols. No source photographs are bundled.
- `components/homeworld-cards.tsx` renders original local art with selectable
text, high/reverse tabs and a scrollable enlarged inspector. The reverse
correctly contains both low and occupied panels. Salusa is marked Advanced
only. The internal reference searches the complete card text as well as names.
- `game/homeworld-custody.ts` keeps native primary reserves authoritative in
each player's existing typed totals. It stores only foreign visitors and
Salusa's allocation within Emperor totals. Explicit withdrawals/deposits
return detached before/after receipts; a transfer cannot spend forces newly
deposited during the same transaction. Native and foreign physical totals,
special-counter caps, active worlds and seated identities are validated.
- `game/homeworld-population.ts` joins the card manifest to those separate
world locations. It counts native forces only, uses Sardaukar alone on
Salusa, selects the face at the verified minimum-high boundary, and exposes
printed native battle values and conditional low-population bonuses.
Printed occupied income is explicitly potential, never a payment.
The helpers never read private hands or leaders. Homeworld IDs do not enter
the Arrakis territory/sector registry. Both Emperor force types can be
transferred between Kaitain and Salusa without duplicating reserves or
mistaking normal Salusa defenders for Sardaukar population. Starred Fremen
identity can be retained in Basic without granting Advanced strength.
## Source decisions
See [component audit](HOMEWORLD_COMPONENT_AUDIT.md) and
[global rules contract](HOMEWORLD_RULES.md). All 26 physical faces were inspected
and independently reviewed. Caladan's printed native value is 2; the rulebook
delegates to the card despite an inconsistent example saying 3. Salusa's
printed high 2–5 and low 0–2 ranges are both retained; the global minimum-high
instruction selects high at 2. Tupile's reverse says CHOAM on another
Homeworld **or** another faction on Tupile; an initial missing-word reading was
corrected before release.
## Verification
Focused tests cover all 13 card boundaries, inventory and immutable data;
57 base rosters in both modes and every expansion faction; native/foreign
custody and both-type Emperor transfers; death/revival custody deltas; duplicate
change aggregation; malformed state; prototype-like player IDs; private getter
guards; and JSON round trips. The focused Homeworld/reference run passes 39
cases. The runner's five-case subprocess self-check also passes.
Full typecheck, lint and **3,085 offline tests** pass; the final production
build also passes. The final text-size-only adjustment was followed by named
lint, a rebuild and browser verification. Logs:
`/tmp/dune-homeworld-check-final.log`,
`/tmp/dune-homeworld-build-final.log`, and
`/tmp/dune-homeworld-focused-second.log`.
Browser checks exercised both enlarged faces of all 13 cards on desktop and
at 390×844, all normal reverse controls, loaded original artwork, full-text
search, refresh, keyboard face selection/activation and Escape dismissal.
No inspector or visible text overflows horizontally. Normal gameplay text is
16px; enlarged text is 20px with 32px line height. Screenshot review covered
Caladan high/reverse on desktop, Ecaz high on desktop, Tupile high/reverse on
phone, Salusa reverse on phone and the normal Caladan phone card. This is
bounded visual sampling, not a claim that screenshots of every possible face
and viewport have been inspected.
All thirteen 1774×887 original illustrations were individually inspected by
the asset agent. Final files are `public/art/homeworlds/<card-id>-v1.png`;
[the exact prompt manifest](HOMEWORLD_ART_PROMPTS.json) records the built-in
image-generation mode, selected sources, workspace paths and SHA-256 hashes.
The controlled 07:53 UTC development-server restart preserved all **2,617**
saved room versions and state hashes. The human setup room stayed at version
14 and the QA room at version 132. No HTTP/persistence implementation changed,
so unrelated complete-game simulations and HTTP suites were not repeated.
## Remaining runtime work
The custody quote is physical bookkeeping, not action authorization. Callers
must validate the matching Arrakis/Tanks change, turn ownership, destination,
cost, ally restrictions and special permissions before accepting a transfer.
No saved `Game` schema or existing game's reserves were migrated here.
The module still needs setup/migration and complete typed arrival routing;
ordinary and Guild-sponsored shipments; Emperor movement; revival and
post-battle arrivals; occupation entitlements and turnover; battles and native
explosion casualties; all high/low/occupied card effects at their real timing
windows; income sharing, private knowledge, Duke and hand-limit custody;
alliance restrictions and Ecaz victory; authoritative player views, controls,
all four AI profiles, persistence races and complete-game verification.
Population, current foreign forces and a turn-qualified Occupier are separate
concepts. Do not replace them with one high/low/occupied enum or let this
projection decide occupation duration. Homeworld advantage/penalty immunity
must also remain distinct from ordinary cancelable faction powers.
No release gate or maintenance automation was changed. User development
workflow optimizations and all existing saved games are preserved.
+62
View File
@@ -0,0 +1,62 @@
# Homeworld invasion transport and occupation audit
Source audit, 9 September 2026. This document refines the existing [Homeworld contract](HOMEWORLD_RULES.md#transport-and-arrival); it does not activate transport, occupation, battles, or faction effects. Implementation evidence remains separate.
## Authority and fresh verification
The [GF9 E3 rulebook](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf) remains the module authority. Its indexed printed pages 9, 10 and 15 were freshly retrieved. Direct PDF access returned HTTP 403; the earlier `/tmp/dune-rules/ecaz-audit.txt` is no longer present. No claim here relies on that missing file. The [designer expansion page](https://futurepastimes.com/dune-ecaz-moritani) was accessible and links the rules and Homeworld explanation; the video could not be retrieved, so no new spoken ruling is attributed to Jack Reda.
**Fresh E3 checkpoint:** another Homeworld can be invaded; its native reserves defend it. Homeworld-to-Homeworld shipment costs one spice per counter, halved for Guild. Arrakis-to-Homeworld travel requires Guild cross-shipment or the explicit Junction permission. Allied destinations and alliances with an occupier of one's own world are forbidden. Emperor can combine both native origins and has a separate inter-world movement. Homeworlds are not territories. BG advisors cannot arrive there or replace invading fighters. Homeworld effects resist Karama. The FAQ confirms Heighliner activation. Occupier qualification occurs with foreign presence at turn start/end, or immediately upon being alone there; the latter qualification names the current turn. Occupied income is collected during Collection and can immediately be shared with an ally. Native low penalties remain active while occupied. [E3, pp.9–10,15](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=9)
The detailed route and component mappings already in [transport and arrival](HOMEWORLD_RULES.md#transport-and-arrival), [occupation](HOMEWORLD_RULES.md#occupier-lifecycle-and-benefits), and the [physical component audit](HOMEWORLD_COMPONENT_AUDIT.md#verified-high-side-effects) remain the applicable local contract. In particular, the actual Junction, Wallach IX and Tupile faces must be used rather than replacing their text with generic transport or control rules.
## Base-rule composition
The [base rulebook, pp.17,19,23](https://www.gf9games.com/dunegame/wp-content/uploads/Dune-Rulebook.pdf#page=17) freshly confirms that both ordinary BG accompaniment and its Advanced destination alternative require another faction's off-planet shipment **to Dune**. Therefore a shipment ending on a Homeworld does not, by itself, create a Polar Sink accompaniment opportunity. The Wallach high face changes the size of an eligible accompaniment, not its trigger. This is source composition, not a separate Homeworld FAQ answer.
Guild's base transport alternatives are one shipment per turn; its cross-board or reserve-return alternatives start in one territory. Its printed alliance grant names reserve-to-Dune and territory-to-territory travel. That alliance grant does not independently authorize the new Arrakis-to-Homeworld route. Fractional shipment costs round up: five counters at the E3 half rate cost three spice, and one costs one. Do not round individual counters first or halve a rounded total again. [Base, pp.19,23](https://www.gf9games.com/dunegame/wp-content/uploads/Dune-Rulebook.pdf#page=19)
The [November 2020 FAQ, p.7](https://www.gf9games.com/dune/wp-content/uploads/2020/11/Dune-FAQ-Nov-2020.pdf#page=7) allows Karama purchase for another player at Guild rates, paid to the bank. Its cancellation list distinguishes Guild income, half-price shipment, ally rates, cross-shipment/reserve return, and Advanced timing. These are distinct sources. E3's immunity does not justify dropping every ordinary Karama response merely because a Homeworld is involved; equally, a response cannot erase a transport permission supplied by Junction's Homeworld face. The November wording and [E1 cancellation table, p.12](https://www.gf9games.com/dunegame/wp-content/uploads/2020/09/IxianAndTleilaxuRulebook.pdf#page=12) supersede the older April FAQ's contrary statement that Guild's transport types cannot be canceled.
## Route boundaries for implementation
Use an explicit source-world/source-sector and destination-world/destination-sector pair. A foreign garrison must remain physically separate from native reserves. Existing native-to-Arrakis shipment and Emperor transfer are already documented; the new interface must not turn every off-board force into an interchangeable reserve.
| Route | Required distinction |
| --- | --- |
| Native Homeworld → foreign Homeworld | New invasion route; retain ordinary shipment usage, typed counters and destination ownership. Fremen's free Southern Hemisphere reinforcement onto Arrakis is not a free invasion. |
| Foreign Homeworld → another foreign Homeworld | Covered by the general world-to-world permission; use the actual foreign source pool. |
| Any foreign source → one's native Homeworld | Apply the specific own-world restriction and its explicit exceptions, not merely the general world-to-world sentence. |
| Arrakis → Homeworld | Ordinary Guild privilege and Junction-sponsored permission need different provenance and cancellation handling. The Guild ally flag alone is insufficient. |
| Foreign Homeworld → Arrakis | Do not silently label a foreign garrison as native reserves. Junction explicitly supports transport from Homeworlds; a general unsponsored foreign-garrison departure is not expressly described in the retrieved transport paragraph. Record the selected interpretation before exposing this edge. |
| Any route → ally's Homeworld | Reject before payment or arrival; Ecaz's territorial co-occupation is not an exception. |
There is no retrieved numeric invasion-force cap or Homeworld two-faction capacity rule. Preserve the twenty physical counters, actual available group, affordability and named permissions; do not reuse a stronghold's two-faction occupancy check for a non-territory world. Combining unrelated source worlds in one shipment has no general permission. Emperor's named two-origin exception must remain explicit. These are composition boundaries, not newly printed caps.
**Payment is source composition, not a new question merely because E3 omits a recipient.** The ordinary rule pays the bank; a qualifying faction or funding rule overrides that default. This default is explicit in the [publisher quick-start payment rule, p.8](https://www.gf9games.com/dunegame/wp-content/uploads/Quick-start-Guide.pdf#page=8). A shipper's own invasion fee therefore goes to the bank unless an applicable effect supplies another recipient. Guild's base onto-Dune trigger must not be broadened solely by reusing `guildShipmentIncome`.
Preserve the already documented [November allied-payment adjudication](GUILD_SHIPMENT_PAYMENTS.md#publisher-contract-and-precedence): non-Guild ally contributions go to Guild when present, Guild contributions go to the bank, and an independent Karama rate sends the payment to the bank. This is contributor-specific even when Guild is the shipper. The [November FAQ, p.2](https://www.gf9games.com/dune/wp-content/uploads/2020/11/Dune-FAQ-Nov-2020.pdf#page=2) was freshly rechecked. A route quote must separate the shipper's eligible income from that contribution rule. `shipment-price.ts` currently has no route parameter; its arithmetic is reusable, its current caller assumptions are not a new Homeworld authority. No Homeworld-specific user ruling was located in the existing payment documents.
Generic Karama purchase must retain its actual destination scope and never grant a missing transport route. Its FAQ establishes payment/rate but supplies no Homeworld worked example; do not turn the absence of an example into a blanket blocker. An exact card/rule-scope review is still needed before extending the existing reserve-shipment purchase to a new off-board route. Existing unresolved ordinary rate-cancellation timing remains tracked in [Guild rate Karama rules](GUILD_RATE_KARAMA_RULES.md#material-unresolved-timing), without asking those questions again.
## Occupation evidence and unresolved lifecycle
Keep three independent facts: present native/foreign forces, current native population, and a recorded qualification event with its turn. A sole-controller enum loses evidence that the published timing rule explicitly creates. Do not reconstruct historical qualifications from a reloaded current board.
The following cases still require a lifecycle decision; the cited material does not supply an exclusive-controller or automatic handoff algorithm:
- A qualifies alone, then B enters before Collection. Is A's current-turn benefit retained while contested?
- A qualifies, leaves entirely, and B becomes sole occupant later that turn. Which continuing advantages and income entitlements survive?
- Two foreigners remain at a turn boundary, including allies jointly visiting a third faction's world. Does each receive the named qualification, and how are unique rewards resolved?
- Native revival restores a high population while a foreign qualifier remains. Which native high/low effects coexist with the occupied effect, and until when?
- A remembered current-turn qualification remains after departure: does it prohibit a later alliance, or does the alliance restriction use present forces? Do not resolve this merely by sharing one occupation predicate across all consumers.
Tupile's component-specific loss-of-occupation discard must be preserved even if another benefit ultimately uses a turn receipt. A unique physical reward such as Duke ownership cannot be duplicated to mask simultaneous entitlements. Occupied bank income, percentage receipts, hand limits, immunity and victory conditions each need their own consumer timing once the lifecycle is resolved.
Fresh targeted GF9, designer-name and occupation searches produced no new official resolution. A community compilation replaces the publisher's start/end-turn wording with an unopposed-only definition; it is not an erratum and was excluded. Search absence is not proof that no clarification exists.
## Verification handoff
Transport tests should cover odd/even Guild costs, funding and income separation, the ordinary shipment limit, native and foreign custody, mixed Emperor origins, own/ally rejection, Fremen invasion payment, BG non-trigger on Homeworld arrival, and one Heighliner receipt. Capture the exact permission source before each response; restore it through JSON/CAS without spending twice.
Occupation tests must use the five cases above plus loss of the last invader, surviving native defenders after an explosion, Collection exactly once, alliance formation, and unique-reward custody. A transport-only pass cannot certify occupation or a complete Homeworld game. No production, server, saved-room, Sites or automation state was changed by this audit. Existing CHOAM charity, Tleilaxu special-Karama and Ix revival questions are neither repeated nor resolved here.
+51
View File
@@ -0,0 +1,51 @@
# Homeworld mobility effects
Primary-source audit, 9 September 2026. This contract covers Caladan low, Wallach IX high/low, Ix low and Richese low. It is not an implementation checkpoint or a release certification. The [component audit](HOMEWORLD_COMPONENT_AUDIT.md) records the inspected physical faces and their provenance; its former `/tmp/dune-rules/` images are absent in this session, so this audit does not claim a new visual inspection. Fresh searches retrieved publisher-indexed rulebook and November FAQ passages; direct publisher PDF requests returned HTTP 403. No community comment or other edition supplies a rule below.
## Population and effect identity
Evaluate the native world's current population. Caladan is low at 0–5; Wallach IX at 0–10; Ix at 0–4; Richese at 0–9. Foreign visitors do not increase native population. E3's minimum-high rule is continuous, not a generic phase-start snapshot. The low penalty remains applicable while the world is occupied. Karama cannot remove a Homeworld advantage or penalty. These rules do not protect a separately sourced faction advantage merely because its faction has a Homeworld. [E3, pp.9–10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=9)
Implementation consequence: recheck current eligibility before an effect commits, including restored pending frames. A selected two-counter transfer is one batch: starting at native 11 permits both counters and leaves 9. Do not re-evaluate between the first and second counter. An interrupted declaration must retain its selected amount; never silently increase, truncate or replace it. Population-derived public controls need no opponent hand access.
## Caladan: the named Movement advantage
Low Caladan disables the Atreides Spice Deck inspection. The ordinary advantage occurs at the beginning of Movement, before anyone moves; it does **not** spend an ordinary force movement. Earlier Homeworld developer prose calling it a “movement-spent” peek is inaccurate. The penalty does not cancel battle prescience, auction inspection or a separately printed card effect. [Base, p.17](https://www.gf9games.com/dunegame/wp-content/uploads/Dune-Rulebook.pdf#page=17)
The November FAQ limits the inspection to one card even with Double Spice Blow. Ordinary Karama can prevent that inspection when otherwise available. Low Caladan supplies a direct prohibition, not an extra Karama target or an acknowledgement decision. Hajr cannot buy a second inspection or bypass the penalty: its additional movement follows normal movement rules. [November FAQ, pp.3,7–8](https://www.gf9games.com/dune/wp-content/uploads/2020/11/Dune-FAQ-Nov-2020.pdf#page=3)
Do not grant delayed inspection merely because Caladan becomes high after its printed opening opportunity has passed. Likewise, restoring high does not erase information already legally learned. Availability, historical knowledge and a continuously exposed live deck preview are separate implementation concerns.
## Wallach IX: accompaniment, amount and stance
Spiritual Advisors is the named free accompaniment power. Another faction's completed off-planet shipment **to Dune** creates the opportunity; Basic sends one reserve force to Polar Sink, and Advanced offers the arriving territory instead. BG does not accompany itself. An on-planet relocation, Fremen's ordinary reserve entry or a shipment ending at a Homeworld does not meet that trigger. [Base, p.18](https://www.gf9games.com/dunegame/wp-content/uploads/Dune-Rulebook.pdf#page=18), [Homeworld invasion audit](HOMEWORLD_INVASION_RULES.md)
Wallach low suppresses both accompaniment destinations. Wallach high permits an optional two-counter Polar Sink accompaniment. One remains available; passing remains available. The same-territory Advanced alternative stays one, and a two-counter action cannot split its destinations. With the module enabled, a native reserve pool of one is necessarily low and permits no accompaniment. With the module absent, the ordinary one-counter option remains valid. The source of these modifiers is the [physical component audit](HOMEWORLD_COMPONENT_AUDIT.md#verified-high-side-effects).
This restriction does not prohibit ordinary paid BG shipment, moving existing advisors, Intrusion or the normal stance transitions. In particular, the November FAQ permits directly shipped forces to join existing advisors and requires arrivals to match the territory's existing BG type. This supersedes the conflicting April FAQ. [November FAQ, p.4](https://www.gf9games.com/dune/wp-content/uploads/2020/11/Dune-FAQ-Nov-2020.pdf#page=4)
The Guild Ambassador's extra shipment also qualifies when it is another faction's off-planet arrival. Its special parent continuation does not remove the Wallach conditions. E3 confirms both that Ambassador shipments interrupt the triggering player's action and that allied BG may accompany Ecaz. Preserve that original entrant, independent beneficiary and BG as separate actors. [E3, p.15](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=15), [Guild Ambassador audit](GUILD_AMBASSADOR_RULES.md)
Check Wallach at every accompaniment producer and at placement. Do not freeze high merely when the original shipper starts its turn. Suppressing an unavailable accompaniment must resume the correct original action without a fake “allow” decision. The parent shipment cannot be charged or transferred again.
### Ordinary Karama and the high modifier
E1 explicitly lists Spiritual Advisors and Advanced Advisors as cancelable free shipments. E3 independently protects Homeworld effects. Neither retrieved source directly answers a two-counter Wallach accompaniment cancellation. [E1, p.12](https://www.gf9games.com/dunegame/wp-content/uploads/2020/09/IxianAndTleilaxuRulebook.pdf#page=12), [E3, p.10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=10)
The adopted composition is that the high face changes the quantity of a qualifying accompaniment; canceling the underlying Spiritual Advisors use leaves no independent bonus shipment. A second Karama aimed only at removing the extra counter is forbidden. This follows the conditional modifier and its underlying action, rather than a specific two-counter FAQ answer. No retrieved primary text contradicts that composition. A Guild Ambassador parent's resistance to ordinary cancellation does not automatically transfer to BG's distinct accompaniment advantage.
## Ix and Richese: prohibit relocation, preserve other actions
Low Ix prohibits moving the Hidden Mobile Stronghold itself. Apply it both to the ordinary pre-storm relocation and the special Ixian Karama relocation during Shipment and Movement. A Karama cannot override the protected low penalty. The special power otherwise adds a two-territory HMS move while preserving normal troop movement. Ordinary HMS movement and its travel-related collection are described separately from initial placement, protected interior and troop entry. [E1, pp.6,9](https://www.gf9games.com/dunegame/wp-content/uploads/2020/09/IxianAndTleilaxuRulebook.pdf#page=6)
Low Ix does not immobilize Cyborgs or Suboids, forbid troop entry/exit through a stationary HMS, erase its shelter, or forbid unrelated collection by troops. Initial setup placement is not a later relocation. Do not spend the special Karama or mark it used on a rejected low-population attempt.
Low Richese prohibits relocating a deployed No-Field marker, including a marker-only move, a mixed group carrying it, Hajr movement or an otherwise legal Fremen Ambassador relocation. It does not prohibit initial shipment, voluntary reveal, mandatory reveal, or moving ordinary forces while leaving the marker in place. The token moves like a force, but deployment and revelation have distinct lifecycle rules. [E2, p.6](https://www.gf9games.com/dune/wp-content/uploads/2021/11/CHOAM-Rulebook-low-res.pdf#page=6), [No-Field audit](RICHESE_NO_FIELD_RULES.md)
Hajr supplies no immunity from the prohibition. CHOAM's Baliset remains a separate movement restriction and expressly permits shipment; do not apply it to free BG accompaniment. A stopped marker move preserves its hidden denomination, physical location and last-use history. Ordinary forces materialized by a separately legal reveal can subsequently move normally. [November FAQ, p.8](https://www.gf9games.com/dune/wp-content/uploads/2020/11/Dune-FAQ-Nov-2020.pdf#page=8), [E2, p.7](https://www.gf9games.com/dune/wp-content/uploads/2021/11/CHOAM-Rulebook-low-res.pdf#page=7)
These movement conclusions do not resolve the prior No-Field return/capture or off-planet marker questions. A generic relocation adapter must not fabricate a reveal or change concealed custody to bypass those existing boundaries.
## Verification obligations
Exercise exact thresholds, Basic and Advanced accompaniment, one versus two versus pass, same-territory versus Polar Sink, native 11→9 as one batch, module-off reserve shortage, normal and Ambassador continuations, paid BG arrival joining advisors, low-population restored frames, stationary HMS troop movement, both HMS relocation sources, marker-only/mixed/Hajr moves, independent physical-force movement and legal reveal. Verify rejection immutability, no private information leakage, all four AI profiles and SQLite recovery. No tests were run or code changed by this source-only audit.
+25
View File
@@ -0,0 +1,25 @@
# Homeworld mobility and Spiritual Advisors
9 September 2026. [Source contract](HOMEWORLD_MOBILITY_RULES.md). This integrates native population effects into existing movement, knowledge and accompaniment paths. Homeworld starts remain disabled pending the whole module.
## Implemented behavior
Low Caladan suppresses the Atreides foresight opportunity at the start of Shipment and Movement, including a refill that would only serve that inspection. This advantage never spends movement. Knowledge already obtained legally remains available; raising population later does not manufacture a missed phase-opening peek.
Low Wallach IX suppresses the optional free Spiritual Advisor follow-up after another faction's qualifying shipment, including Guild Ambassador and Junction transport. It does not prevent paid Bene Gesserit shipment, joining existing advisors, or moving existing forces. High Wallach IX offers one or two normal reserve counters to Polar Sink; accompanying another destination still permits only one. A declared two-counter batch uses the high population before departure, then removes and places both counters together. Lower population afterward governs later opportunities.
The declared amount survives the existing ordinary advisor response and saved interruptions. Canceling Spiritual Advisors prevents the whole conditional arrival, including its added counter; it does not create a separate Homeworld cancellation. This source composition is identified in the rules audit. Guild Ambassador settlement preserves its already-completed primary shipment and records an exact one- or two-counter accompaniment receipt. Historical two-counter receipts require Homeworlds and Polar Sink but do not incorrectly recheck high population after that legal departure.
Low Ix prevents movement of the Hidden Mobile Stronghold, including the special Karama relocation. Its setup placement and movements by physical forces remain distinct. A low native population skips the ordinary unavailable stronghold movement opportunity. Low Richese prevents movement of the No-Field token, including Hajr, Ornithopter movement selections and Fremen Ambassador relocation; physical forces can move while leaving the token where it is. Shipment and voluntary revelation retain their own rules.
Shared public helpers supply the authoritative limits, player controls and all four AI profiles. Controls explain blocked movement, leave physical-force alternatives available, and expose both permitted Polar Sink amounts. Native counters determine these effects; visitors and another faction's Homeworld do not supply a false threshold. Saved advisor, foresight and mobile-stronghold responses are checked in the current frame and supported explicit saved parents before costs or projection.
## Verification and remaining scope
Fifty-three new regressions cover the public helper (11), mobility engine paths (14), mobility SQLite recovery (4), ordinary advisor engine paths (10), advisor SQLite recovery (6) and Guild Ambassador integration (8). They verify both native thresholds and typed custody, legitimate learned knowledge, no late foresight, ordinary and special movement, free versus paid advisor sources, pair settlement, cancellation, saved Box parents, concurrent requests, rejected writes, private projection and unchanged unrelated rooms. Richese and Ecaz audit fixtures explicitly retain supported physical decks and constructors; they do not establish full expansion setup. Independent reviews and existing related tests passed. Final broad results are recorded in the newest [implementation checkpoint](IMPLEMENTATION_STATUS.md).
In an isolated browser room using genuine Advanced Homeworld setup with a staged shipment opportunity, Emperor's actual one-force shipment opened the BG follow-up. Desktop controls exposed one/two Polar Sink choices and the separate one-force accompaniment alternative. On a 390×844 viewport, keyboard selection declared two forces; the saved response retained that amount after refresh with all nineteen reserves still present. The other human seat allowed the power by keyboard. Another refresh preserved seventeen reserves, two forces in Polar Sink, the original one elsewhere, zero Tanks and BG's unused ordinary shipment. Emperor retained its Karama, nineteen native reserves and nine spice. No page errors or horizontal phone overflow occurred. Phone choice/settlement screenshots were visually inspected. The reaction display subsequently gained explicit declared quantity and destination text; full checks/build were rerun after that display edit.
All **2,833** pre-existing room versions and state hashes remained unchanged after the isolated browser and HTTP tests, with none missing. The existing development server was reused; no maintenance restart was due during this checkpoint.
Occupation may retain low penalties independently of current native population; its existing lifecycle interpretations remain unresolved. Remaining high and occupied faces, concealed transport, full expansion setup and complete Homeworld games remain unfinished. No start or publication gate opens, saved games are preserved, and the maintenance automation stays removed.
+149
View File
@@ -0,0 +1,149 @@
# Homeworld occupation integration audit
This is a code integration map, not an occupation ruling or a claim of runtime
completion. It records the current native effect consumers and the boundaries a
future occupation implementation must preserve. Authority and unresolved cases
remain in [Homeworld rules](HOMEWORLD_RULES.md),
[invasion rules](HOMEWORLD_INVASION_RULES.md), and the current source audit.
## Separate physical population from active effects
`game/homeworld-population.ts::homeworldPopulations` is explicitly a public,
physical projection. Its `side` follows native typed counters and the printed
minimum. Visitors never raise native population; Kaitain excludes Salusa's
separate allocation, and Salusa counts Sardaukar only. Keep these calculations,
reserve custody, shipment sources, and before/after population quotes physical.
Occupation qualification is event based; present foreign forces are not a
sufficient replacement for saved qualification. Conversely, a saved reward
entitlement need not answer every present-control question. The existing source
contract leaves repopulation and some competing-occupier cases unresolved. Do
not silently impose an exclusive controller or globally replace physical
`side` with `low` when a foreign force appears.
Three distinct inputs are needed: physical native population, the native
effects currently active under the verified occupation rule, and each qualified
occupier's particular benefits. Low penalties, generic low bonuses, high effects
and native battle strength are separate consumers. Tupile makes this especially
visible: its Worthless-sale restriction is a **high** effect, while its low
disclosure ability is explicitly lost under occupation.
## Existing consumers
| Consumer | Current physical predicate | Occupation integration boundary |
| --- | --- | --- |
| `homeworld-benefits.ts::homeworldLowBonus` | Native primary world low; Salusa excluded | Generic charity/revival bonus eligibility must be resolved independently of retaining a named low penalty. Do not award bonuses merely because an occupation penalty remains. |
| `charity.ts::charityQuote`, `revival.ts::freeRevivalRate` | Shared low bonus | Preserve ordinary eligibility, bank funding, inflation, Recruits and resource caps. Changing the shared helper reaches engine/view quotes. |
| `homeworld-benefits.ts::snapshotHomeworldRevival` | Tleilax physically low at Revival opening | Snapshot the verified low-penalty condition at the original phase-opening event. `tleilaxuHomeworldFreeIncomeBlocked` must continue reading that saved receipt, not current population or occupation. |
| `homeworld-benefits.ts::homeworldSardaukarFreeSupport` | Advanced Salusa high | A native high capability. Occupied Salusa's loss of Sardaukar advantage needs its own rule composition, not a physical force conversion. |
| `homeworld-benefits.ts::homeworldSardaukarGholaBlock` | Salusa population exactly one during an Emperor battle | Existing unresolved support-transition guard. If occupation changes effective support, compare the relevant before/after capability; do not remove the guard solely because occupation exists. |
| `homeworld-mobility.ts::homeworldMovementForesightBlock` | Caladan low | Retained low penalty blocks a new Movement peek; it does not erase already acquired knowledge. |
| `homeworld-mobility.ts::homeworldMobileStrongholdMovementBlock` | Ix low | Retained low penalty blocks stronghold relocation, including its special Karama route; ordinary troop movement remains separate. |
| `homeworld-mobility.ts::homeworldNoFieldMovementBlock` | Richese low | Retained low penalty restricts existing marker movement. Shipment and reveal rules remain separate. |
| `homeworld-mobility.ts::homeworldSpiritualAdvisorAllowance` | Wallach low gives zero; high permits two at Polar Sink | Resolve low suppression and the high two-advisor benefit explicitly. Preserve physical reserve limits and accepted reaction counts. |
| `homeworld-card-economy.ts::highKaitainDiscardsAvailable` | Kaitain high | Native high capability; use the shared effective condition at quote/action time. Keep the shared end-of-Bidding event public and independent of private affordability. |
| `homeworld-card-economy.ts::homeworldWorthlessSaleBlock` | Tupile high | High-face restriction, not a retained low penalty. Both ordinary and duplicate Worthless sales and CHOAM Ambassador bank payouts consume this helper. Trades, Ixian discard/draw and special Karama retain their own rules. |
| `ecaz-poison-income.ts::quoteEcazPoisonIncome` | Ecaz high | Evaluate active high income at actual physical discard, including delayed winner cleanup. Battle roles remain captured at battle resolution; they must not freeze future population or occupation eligibility. |
| `junction-offer.ts::junctionSponsor` and `junction-transport.ts::junctionSponsorEligible` | Independently test Junction high | Replace duplicated eligibility with one shared capability predicate. Preserve public offer-event invalidation and ordinary Guild transport rights. |
| `homeworld-payment-income.ts::quoteHomeworldPaymentIncome` | Kaitain/Junction physically low | Physical low native income reduction only. Future retained low must be supplied through the common effect layer; occupier shares need separate payment provenance and settlement. |
| `homeworld-combat.ts::locations`, `homeworldBattleRules` | Physical face selects native battle strength | Resolve the applicable combat face explicitly. Native dial bonus and Lasgun/shield native casualties use this strength; neither can be inferred from a generic retained-penalty boolean. |
The payment quote is an independently scoped addition being implemented with
this audit; it does not implement occupation or create a payment event.
The engine also uses `homeworldLowBonus` when deciding whether CHOAM's opening
charity income may proceed, and when projecting the owner's revival bonus.
Keep that existing opening-income release boundary explicit: deciding retained
low penalties alone does not resolve the separately documented classification
of CHOAM's opening income. `homeworldRevivalKaramaBlock` also derives from the
generic bonus; its unresolved special-Karama overlap must remain visible.
## Engine, interruptions and projection
`homeworld-game.ts::homeworldGameIntegrity` currently accepts exactly the
`custody` key inside the module record. Any new persisted occupation field needs
an explicit schema/integrity change, a compatible initialization rule and JSON
recovery coverage. Do not reconstruct historical qualification on view/read.
`homeworldContext` deliberately strips players to public identity, faction and
typed reserve counts. Extend public context intentionally rather than passing
hands, secrets or held spice to occupation calculations.
The mobility helpers already feed `movement-phase-quote.ts`,
`terminal-cancellation.ts`, `karama-movement-cancellation.ts`,
`guild-ambassador.ts`, `fremen-ambassador.ts` and engine action/view guards.
Update their narrowed context types consistently. Accepted declarations and
durable continuations require a source-specific choice between current
eligibility and captured eligibility; never rewrite their counts on reload.
Card income and sale settlement already have live rechecks. Preserve the CHOAM
sale parent through Ghola/Tleilaxu income and the battle winner discard queue
through casualties/Ixian substitution. Ecaz income must observe the effect
state at each disposal, so losing-card income before winner casualties can
differ from mandatory and optional winner disposal afterward. Occupied Ecaz's
Duke authority belongs in the unique Duke custody/alliance lifecycle, not in
the poison quote.
`combat-location.ts::homeworldBattleLocation` is the common engine adapter for
Homeworld combat; use it to carry an explicit effective battle projection into
the existing pure combat rules. Physical battle presence, reciprocal-alliance
restrictions, typed loss pools and substitution remain independent.
`components/homeworld-table.tsx` labels `world.side` as population. Keep that
truthful when adding occupied status and active effects. The shipment option
modules and bots also use physical side and native strength for scores; expose
separate values if their strategic evaluation needs effective effects. Bot
heuristics must not become authority for occupation qualification or legality.
## Suggested shared interface
Keep `homeworldPopulations` unchanged. Add one public projection module around
validated occupation receipts, with a Game adapter providing only public
physical context, current turn and explicit occupation state. A suitable shape
is:
```ts
type HomeworldEffectState = {
physical: HomeworldPopulation;
occupation: { qualified: readonly string[]; active: boolean };
highEffectsActive: boolean;
lowPenaltiesActive: boolean;
lowBonusActive: boolean;
battleSide: 'high' | 'low';
};
```
This is a proposed interface, not a decision that the four effect fields follow
one rule. Their construction must follow the completed source audit. Card
exceptions such as occupied Tupile's disclosure loss and occupied Salusa's
Sardaukar restriction should have named quotes consuming this projection; do
not represent every native faction ability with a blanket disabled flag.
Beneficiary selection, allied sharing and expiry obligations require their own
quotes over the receipts; `qualified` alone is not permission to pay every
listed faction.
Migrate existing capability helpers to this projection rather than inserting
occupation conditionals independently into engine, view and bots. The same
projection can supply public explanatory status. Keep actual payment splits,
card selection and physical mutation in their existing focused quotes and
settlement functions.
## Verification targets
- Native low to high while a qualified invader remains, with independent
assertions for retained low penalties, generic bonuses, high effects and
battle strength under the finalized ruling.
- Present visitors versus qualified occupiers; departure, return, competing
qualifiers, turn boundaries and no duplicate awards after JSON restoration.
- Revival phase-start receipt retained across later population/occupation
changes; ordinary paid income and Ghola remain distinct.
- Sale/Ghola, winner casualties/Ixian substitution, advisor and canceled
shipment continuations preserve exact original events and resource custody.
- Junction/Kaitain rounding per verified payment unit; retain eligible source
contributions and explicitly guard cases where transaction and contributor
rounding disagree until that rule is resolved. No native/occupier income is
minted on read.
- Opponent private getters are never read; observed public state does not
disclose hidden discarded card kinds or private balances.
This documentation audit changes no runtime rules. Links and code symbols were
reviewed; it does not certify occupation, any full faction or expansion.
@@ -0,0 +1,71 @@
# Homeworld occupation lifecycle integration audit
Read-only code audit, 9 September 2026. This document maps implementation boundaries; it does not settle the occupation interpretations still identified in [the invasion source audit](HOMEWORLD_INVASION_RULES.md#verification-handoff). Root source work must define retention after departure, contested qualification, native high/low coexistence and unique rewards before those consumers are implemented. No runtime, database or deployment changes were made by this audit.
## Observe semantic force changes, not just actions
The engine can perform several ordered physical changes inside one accepted action or one automatic recovery. An observation only at the end of `applyAction` or `finishActionContinuations` misses a foreign winner becoming alone after native loser removal, then losing its final force to its own dial before the wrapper returns. Losing-card disposal can also occur during that interval, so occupation-dependent card effects must see the correctly observed state before the discard is processed.
Conversely, observing every counter assignment or every `killTerritory` call can invent intermediate occupation. `resolveBattle` implements double-traitor destruction with two sequential army removals, and explosions iterate `quote.destroyedArmies`. Those loops are implementation details of one destruction result. Subject to the source ruling about simultaneous losses, observe the completed destruction group, rather than granting the second army an entitlement merely because its array entry was processed last.
Use a focused, pure occupation reducer over public typed force groups, with an explicit observation cause and event identity. The engine should call it at **completed semantic mutation boundaries**. Preserve already recorded qualification separately from the current occupants; the eventual rules may give these different consumers. Source-dependent rewards should run only after this observation and through their own durable continuation if a player choice is required. A final wrapper check is useful as an invariant, but does not replace the intermediate observations.
## Mutation sites
All engine names below refer to [game/engine.ts](../game/engine.ts). Homeworld groups come from [homeworld-custody.ts](../game/homeworld-custody.ts), where primary native counts derive from player reserve totals, foreign visitors are explicit, and Salusa is a separate allocation within the Emperor's totals. Consequently, changing native reserves can change occupation without changing `custody.visitors`.
| Boundary | Existing code path | Observation placement and constraint |
| --- | --- | --- |
| Ordinary reserve departure | `withdrawNativeReserves`, called by ordinary shipment and Spiritual Advisor arrivals | Observe after the matching board placement and complete typed reserve update, before arrival/income consequences that consume occupation. Do not invoke full force-conservation validation halfway between withdrawal and placement. |
| Revival or Ghola return | `addRevivedReserves`, called by normal revival, Ghola and revival effects | Observe after reserve deposit and the caller's Tanks/elite updates. Native revival can end present sole foreign occupancy and change population while a remembered entitlement remains a separate question. |
| Homeworld shipment | `commitHomeworldShipment` | Observe after `quote.state`, every quoted player reserve total, and any Arrakis source map are installed; before shipment income or subsequent powers. A declaration or a Guild stop does not move forces and must not qualify anyone. |
| Junction transport | `performJunctionTransport` | Observe once after all source withdrawals, destination deposits and any Arrakis placement. Include every affected origin and destination, including both Emperor native origins. The pure quote's internal withdrawal/deposit order is not a sequence of independent events. |
| Emperor inter-world movement | `emperorHomeworldMove` action branch | The quote replaces the Salusa allocation while aggregate reserves stay unchanged. Observe both native worlds after the complete quote is installed. A reserve-total-only watcher misses this path. |
| Homeworld combat loss | `commitHomeworldLoss` → `commitHomeworldResources`, reached by `killTerritory` and `takeBattleLosses` | The resource helper applies custody and all reserve/Tanks counts atomically. The caller must distinguish an independently ordered loser or winner loss from one member of a simultaneous destruction group. |
| Native explosion allocation | `settleHomeworldExplosion` | Observe after the exact selected native casualty group is committed, before `finishBattle`. Earlier invading-army destruction and later native allocation have distinct saved stages; preserve the source-defined ordering. |
| Homeworld Ix substitution | `finishResponse` branch `ixSubstitution` → `commitHomeworldResources` | Observe after the whole substitution quote, before `finishWinner` processes mandatory winner discards. Exchanging Suboids and Cyborgs is one operation; do not manufacture a temporary empty army between its component writes. A canceled substitution has no physical transition. |
| Homeworld Face Dancer replacement | `decision.kind === 'faceDance'` replacement code using `quoteHomeworldCustody` | Observe after winner return, selected external-source removal and replacement deposit are all committed. Include the returned winner's native world as well as the battle world. Do not observe the pure quote's component changes separately. |
| Setup | `initializeStartingForces`, later faction placements and `finishSetup` | Initialize the new-game tracking baseline after physical custody exists, with setup provenance. Setup allocation is not a retrospective invasion history. |
Several active paths still change reserves directly. A hook only inside the two native-reserve helpers will miss them: `revealPlayerNoField`, `commitAmbassadorShipment`, Moritani Sneak Attack, Trip to Gamont, board Face Dancer replacement, and the legacy `guildShip` branch. Some combinations have their own gates or are redirected to existing Homeworld transport, but each admitted path needs either an explicit observation after its completed transfer or a proved no-Homeworld precondition. Audit source guards before claiming complete coverage. Initial Moritani, Bene Gesserit and Fremen placement also use direct reserve writes and belong to the setup baseline, not occupation rewards.
## Battle order that must survive recovery
The current normal Homeworld battle flow is:
1. `resolveBattle` removes the loser army. Record any source-authorized new sole-foreign qualification here before processing the losing cards.
2. Losing cards enter the `battle:mandatory` discard batch; `battleResolved` retains winner casualty commitments. Winner mandatory cards remain physically held in `pendingWinnerDiscards`, independently backed by `lastBattleContext.winnerDiscards`.
3. `continueResolvedBattle` commits the winner's automatic casualties or offers the owned allocation. Observe the completed group even if it removes the final winning force.
4. Ix substitution, when applicable, runs before `finishWinner`. Its allowed physical change receives its own observation; cancellation does not replay casualties.
5. `finishWinner` commits the separate `battle:winnerMandatory` card batch. Optional winner card disposal and later cleanup follow.
`finishActionContinuations` can drain multiple discard batches in a loop, and `settleAutomaticContinuations` can allow responses without a new human action. Every one of these paths must use the same physical observation hooks. Recording only the final board cannot reconstruct stage 1 after stage 3 removed the last foreign force. An occupation receipt associated with the battle must remain independent of nullable pending queues, following the existing mandatory-winner obligation safeguard.
## Turn and income boundaries
`completePhase` is the explicit turn rollover: after phase 8 work, it increments phase, expires Duke state, increments `g.turn`, assigns phase 0 and calls `openPhase`. Place the end-turn occupation observation before changing the turn number; then apply the defined expiry and start-turn observation with the new turn, before `openPhase` exposes any new phase powers. Use separate identities for the old turn's end and the new turn's start, even if the physical board is unchanged.
Do not put turn-boundary logic in `beginStormTurn` alone: Ix phase opening and mobile-stronghold opportunities can intervene before that function. `beginPhase` invokes `collect` in phase 7; occupation income needs a once-per-applicable-turn/recipient receipt at its authoritative payment point. Do not infer that ordinary occupation observation itself pays Collection income. The source audit must define which start/end qualifiers and retained receipts are eligible for each payment or unique advantage.
## Durable state and legacy saves
[homeworldGameIntegrity](../game/homeworld-game.ts) currently accepts exactly `{ custody }` for the Homeworld module. Adding a sibling ledger inside that object requires updating the explicit shape contract and its malformed-save tests; silently adding a field currently rejects existing code paths. A separately versioned top-level ledger is another implementation option. In either design, distinguish an absent legacy field from an explicitly malformed, deleted or inconsistent initialized record.
[db/rooms.ts](../db/rooms.ts) parses saved JSON in `readRoom` and `readSeatView`; it does not migrate or persist reads. Accepted actions and `continueRoomAutomatic` persist complete JSON with SQL version comparison. A ledger stored in the JSON does not inherently require a D1 table migration, but its initialization and every qualification/reward must use this existing compare-and-swap boundary. Reconnects, duplicate workers and repeated normalization must not create extra awards or change source state during a private view.
For new games, initialize a versioned ledger from the genuine setup baseline and observe all subsequent semantic transitions. For old games, present force locations do **not** prove earlier sole occupation, a completed boundary check, Collection payment, discarded cards or prior unique-reward ownership. Do not reconstruct these from aggregate reserves, the public chronicle or a default empty receipt list interpreted as complete history.
A compatible adoption design should explicitly mark the first supported observation and incomplete earlier coverage, persist that adoption once, and record only facts actually established from then onward. Present sole occupancy can be observed at adoption if the approved rule grants an immediate current qualification; that still does not prove a past payment or departed occupier. An older save already inside a battle/discard continuation especially cannot recover a sole-presence interval that ended before the saved snapshot. Leave that limitation explicit instead of inventing entitlement. Whether adoption can grant current benefits or must wait for a specified boundary is a rules/product decision, not a database default.
If adoption is an automatic continuation, extend the scheduler hint deliberately: `needsAutomaticRoomRecovery` currently wakes known pending interactions, not an otherwise idle game merely missing a new ledger. Preserve original phase, pending event IDs, credentials, force/card custody and all other saved rooms. Do not reset or bulk rewrite the live database to install this feature.
## Required regressions
- Loser elimination creates an observed sole foreign interval; winner dial then empties it within one public action and within one resumed SQL continuation.
- Losing poison disposal and later mandatory winner disposal consume the occupation state appropriate to their actual stage; Ix allowance/cancellation and casualty choices restore without repeating qualification.
- Simultaneous double-traitor/explosion groups do not gain array-order-dependent qualifiers; native explosion survivors and multi-invader cases follow the approved source rule.
- Multi-origin transport, Salusa movement, native revival and Face Dancing observe complete transfers without temporary invalid custody or artificial empty intervals.
- End/start boundaries and Collection receipts remain exactly once under two SQL workers, with private views unchanged and malformed/deleted initialized obligations rejected.
- A legacy mid-turn and a legacy mid-battle save preserve all physical state and explicitly incomplete history; adoption never fabricates earlier rewards or departed occupiers.
This is an integration map, not evidence that occupation or any occupied-card benefit is implemented. The retained-low, contested entitlement and unique-reward source questions remain prerequisites for their respective consumers.
+56
View File
@@ -0,0 +1,56 @@
# Homeworld occupation: qualification and unresolved entitlement
Source audit, 9 September 2026. This supplements [Homeworld rules](HOMEWORLD_RULES.md#occupier-lifecycle-and-benefits) and the [invasion audit](HOMEWORLD_INVASION_RULES.md#occupation-evidence-and-unresolved-lifecycle). It defines the evidence that can safely be recorded; it does **not** settle every occupied benefit or authorize a complete occupation release. The [integration audit](HOMEWORLD_OCCUPATION_LIFECYCLE_AUDIT.md) maps the physical mutation and recovery boundaries.
## Confirmed publisher contract
The E3 rulebook establishes these distinct rules:
- Foreign forces at the start or end of a game turn qualify their faction as an Occupier. Sole foreign occupation at any instant qualifies immediately for that turn.
- High advantages follow the native reserve threshold. Occupation retains the native low penalty; no global sentence explicitly suppresses a restored high advantage or replaces its battle value.
- The printed occupied bank award occurs during Spice Collection, including Basic. Occupation income may immediately be shared with the occupier's ally.
- Homeworld effects cannot be canceled with Karama.
These are separate conditions, rather than three mutually exclusive card states. [GF9 E3, pp.9–10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=9).
The Kaitain FAQ divides a five-spice purchase into Emperor three and occupier two, including an occupier's own purchase. It does not demonstrate multiple contributors or resolve competing recipients. [GF9 E3, p.15](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=15).
Here a game turn is the complete nine-phase sequence, Storm through Mentat Pause; an individual player's shipment/movement opportunity is not this boundary. [GF9 base rules, p.7](https://www.gf9games.com/dunegame/wp-content/uploads/Dune-Rulebook.pdf#page=7).
## Executable evidence contract
The following is an implementation design derived from those timing requirements, not an additional rule about who receives a disputed reward:
1. Keep native population, present foreign armies and historical qualification evidence separate. Include the exact Homeworld ID: Emperor's two worlds are distinct locations.
2. After a completed semantic force change, record a sole-occupation event when exactly one foreign faction has forces and no other faction has forces there. A single foreign faction sharing the world with natives is not alone. Do not require an Arrakis stronghold or treat Homeworlds as territories.
3. Observe the old turn's end before incrementing the turn; observe the new turn's start before opening Storm opportunities. At a boundary, preserve every foreign presence relevant to the printed qualification sentence. If multiple factions satisfy the sentence, storing their evidence does not authorize duplicate rewards.
4. Bind each observation to its accepted event, turn, world, qualifying faction and cause (`sole`, `turnStart`, `turnEnd`). Make observation replay idempotent. Keep historical facts after departure; a future entitlement policy can expire a benefit without erasing that the qualification happened.
5. Observe semantic casualty groups rather than intermediate array writes. A separately ordered loser removal can make a foreign winner alone before its own casualties; simultaneous destruction must not manufacture a survivor from implementation order. See the integration audit for the existing battle continuation boundaries.
6. Use a separate once-only Collection receipt for any awarded bank income and its immediate ally allocation. Qualification, refresh, view projection and JSON normalization must not themselves mint spice. A later qualification is not an instruction to replay an earlier Collection.
A public qualification record needs no hand, Traitor, Face Dancer or sealed-plan data. Malformed initialized evidence must fail validation; a legacy save lacking history cannot be claimed to prove that no earlier qualifier existed. Resolving entitlement by scanning current armies alone would discard the distinction the publisher created.
## Questions the retrieved sources do not settle
| Concrete situation | Missing decision; do not silently substitute a policy |
| --- | --- |
| A qualifies alone, then departs completely | Whether all continuing benefits expire immediately or some survive for the stated game turn. |
| A departs and B becomes alone in the same turn | Whether A retains any entitlement, and which faction controls a unique occupied power or receives the next receipt. |
| B enters while qualified A remains | Whether A's remembered qualification continues to supply each benefit while contested. |
| Multiple foreigners remain at a turn boundary | How the qualification wording composes with a unique card choice, Duke custody or a single income stream. Storm order is not an established automatic tie-break here. |
| Native revival restores the high threshold after qualification | How retained low penalties and occupied benefits expire; occupation alone supplies no explicit global high-benefit suppression. Do not infer low charity/revival bonuses or a low native battle value merely from a remembered qualifier. |
| A leaves and returns during the same turn | Whether departure interrupts a specific benefit and triggers its cleanup. Recording a second arrival must not itself create a second Collection award. |
Tupile's verified physical reverse explicitly requires hand-limit cleanup when occupation ceases and removes native CHOAM's low advantage. That specific endpoint must be implemented once its triggering occupation condition is determined; it does not establish a universal expiry policy for every card. Original component provenance and the separate occupied income symbols are recorded in the [component audit](HOMEWORLD_COMPONENT_AUDIT.md). This audit did not re-fetch the old reverse-image cache.
The sharing sentence covers occupation income broadly. A bank-only implementation should not silently exclude later occupied percentage receipts; their funding identity and legal beneficiary must first be resolved. An alliance prohibition arising from physically invading a prospective ally is separately grounded in actual presence, rather than in an invented single controller shared by every consumer.
## Fresh research and implementation boundary
The current publisher-indexed E3 Homeworld text was retrieved again. The previously examined E3 FAQ supplies the Kaitain arithmetic but no complete departure/replacement algorithm. Bounded searches of GF9, Future Pastimes and designer-name results found no authenticated further ruling. The [designer's expansion page](https://futurepastimes.com/dune-ecaz-moritani) links [Homeworlds Revealed](https://www.youtube.com/watch?v=4KZKz13wf9c); no usable spoken transcript was retrieved. Earlier component-frame inspection is not evidence for an unheard spoken clarification. A community compilation's replacement of the publisher's boundary clause with an unopposed-only definition is not an official erratum. Search absence does not prove that no clarification exists.
The existing source documents already record these unresolved cases. During this audit the coordinating agent sent the user this concrete clarification, and the answer is pending: **If Guild occupies an empty Homeworld, then withdraws its last force and another faction occupies it during the same game turn, who keeps that Homeworld's occupied ability and income—the first faction, the current occupier, or both?** None of these alternatives is presented here as the official answer. Do not send a duplicate question or treat elapsed time as an answer.
Progress can continue independently on population-only low Kaitain/Junction income reductions, retaining the [contributor routing contract](GUILD_SHIPMENT_PAYMENTS.md#publisher-contract-and-precedence). Rounding once over an eligible transaction total and evaluating a continuous threshold when income actually settles are reasoned compositions, not explicit worked publisher examples for allied funding or Ghola-interrupted receipts. Preserve those distinctions and the already documented [payment-splitting source gap](HOMEWORLD_CARD_ECONOMY_RULES.md#deferred-payment-splitting). A unique current garrison is not sufficient evidence to discard an earlier faction's same-turn qualification.
This documentation-only audit changes no runtime, stored games, mode gates or publication status. Verification is limited to source/link review and the patch whitespace check.
+66
View File
@@ -0,0 +1,66 @@
# Low Kaitain and Junction: faction payment income
Source-composition contract, 9 September 2026. This covers population-based reductions to existing Emperor and Guild payment receipts. It does not implement occupied income, decide competing Occupiers or certify a complete Homeworld module. [Occupation source boundary](HOMEWORLD_OCCUPATION_RULES.md).
## Printed effects and source precedence
The verified low faces say that native Emperor receives the rounded-up half of Treachery Card payments and native Guild receives the rounded-up half of shipping payments. Both are low at zero through four native forces. Kaitain population is its own physical native pool, excluding forces allocated to Salusa Secundus. Component provenance is recorded in the [Homeworld component audit](HOMEWORLD_COMPONENT_AUDIT.md); this pass did not re-download its historical reverse-image cache.
The E3 Kaitain FAQ's five-spice purchase produces Emperor three and occupier two, even if the occupier bought the card. This supports a division of the existing payment, not an additional buyer charge. It supplies no allied-contribution example. E3 also makes Homeworld penalties Karama-immune and describes threshold effects as continuously dependent on native population. [GF9 E3, pp.9–10,15](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=9).
Preserve the November FAQ's contribution routing before applying Junction's cut: non-Guild contributions eligible for shipment income go to Guild; Guild's own contribution goes to the bank. Preserve the existing independent-Karama bank-only route. The later funding answer replaces the earlier transfer-to-shipper instruction. This source adjudication and its Guild-as-shipper application are already documented in [Guild shipment payments](GUILD_SHIPMENT_PAYMENTS.md#publisher-contract-and-precedence), with the [November FAQ, p.2](https://www.gf9games.com/dune/wp-content/uploads/2020/11/Dune-FAQ-Nov-2020.pdf#page=2). No new contributor-rounding ruling was retrieved in this audit.
## Supported receipts and pending contributor-rounding question
The coordinating implementation keeps these operations separate:
1. Validate the transaction's actual authorized contributions. Before a low-Junction shipment declaration or cost commits, reject a split whose two positive eligible contributions are both odd: the two plausible rounding interpretations differ. This is an unsupported-case guard, not a printed prohibition. Complete admitted purchases or shipments and debit each contribution once under the transaction's own source rule.
2. Determine the amount that the existing ordinary income rule would deliver to the eligible faction. This `gross` is the faction's eligible receipt, not necessarily the total cost.
3. If ordinary faction-income cancellation succeeds, credit zero and leave that eligible amount in the bank. Homeworld immunity does not immunize the separate ordinary income advantage.
4. Otherwise evaluate the native world's current low condition at income settlement. For supported low receipts, credit `ceil(gross / 2)` and leave the remainder in the bank. This aggregate arithmetic agrees with per-contributor rounding only where the contributor guard admits the transaction; it does not establish a rule for blocked cases. Without the low condition, credit `gross`.
5. Keep the original gross transaction receipt and the original positive eligible contribution amounts immutable through responses and restore. These source amounts remain server-private. Recompute the current low-state preview; do not overwrite the original amount with an earlier preview, merge away payer evidence or halve an already reduced amount. Threshold changes must not let a previously high receipt bypass the unresolved-case check when it settles low.
**Contributor rounding remains unanswered.** The coordinating agent has sent a second user question: for low Guild income on a shipment funded by two non-Guild contributions of one spice each, is the income one spice (round the total) or two spice (round each contribution)? Neither interpretation is selected for cases where they differ. Do not duplicate the question, treat elapsed time as an answer, or present the pending aggregate hypothesis as a verified rule. Single positive eligible contributions are unaffected by this distinction; with two contributors, the alternatives coincide unless both are odd. Do not pool unrelated purchases or shipments either. The [payment source gap](HOMEWORLD_CARD_ECONOMY_RULES.md#deferred-payment-splitting) remains open. The separate occupation-lifecycle question is also pending.
**Current population at actual income settlement is also a source composition.** Continuous threshold wording supports applying the condition when the faction receives spice. The publisher supplies no worked example of Ghola changing the native population during an already-open payment response. The implementation must label this composition honestly and test it; it must not reprice the buyer's completed purchase or shipment when the recipient's population changes.
| Supported or deferred example | Low native receipt | Bank portion of the total payment |
| --- | --- | --- |
| Five-spice auction payment eligible for Emperor | 3 | 2 |
| One shipment funded by two non-Guild payers, 1 + 1 | **Pending ruling: 1 or 2; blocked before commitment** | **Pending: 1 or 0** |
| One shipment funded by two non-Guild payers, 2 + 1 | 2 under either interpretation | 1 |
| Shipment cost 5, with Guild contributing 2 | 2 from eligible gross 3 | 3: the Guild-funded 2 plus the cut 1 |
| Guild's own shipment, personal 2 plus non-Guild ally 3 | 2 from eligible gross 3 | 3 |
| Independent Karama bank-only payment | 0 | Entire actual payment |
| Zero-price/free acquisition or shipment | 0 | 0 |
The supported multi-payer arithmetic examples deliberately use splits on which both interpretations agree; the five-spice Kaitain split has the cited E3 worked example. The blocked 1 + 1 case is recorded to make the unanswered choice concrete. A paid tariff discount and a reduced income receipt are separate calculations. A recipient cannot spend its future income to fund the same transaction.
## Income-source adapters
| Source | Existing destination/classification to preserve before applying the cut |
| --- | --- |
| Normal paid Treachery auction | Emperor income from another faction's payment; the Emperor's own purchase gives no self-income. Free Karama acquisition supplies no paid receipt. |
| Richese compulsory cache auction bought by Richese | Emperor or bank normally. This destination is explicit in E2 p.5; a positive Emperor receipt uses Kaitain's cut. |
| Richese cache auction bought by another faction | Richese receives its sale proceeds. Do not send them to Emperor merely because the physical item is a Treachery Card. |
| Richese Black Market hand-card sale | Preserve its separately specified seller-income destination and existing self-sale handling. This document does not resolve the older self-sale gap or redirect the seller's receipt. |
| Richese advanced special Karama three-spice cache purchase | Existing composition treats the purchase payment as Emperor income. Apply Kaitain's cut to that receipt; do not cancel or replay the protected special purchase when ordinary income is canceled. |
| Richese Ambassador three-spice paid draw | Existing composition treats a successful paid draw as a purchase. Another purchasing faction supplies Emperor income; Emperor as buyer supplies none. A failed conditional draw supplies no payment. Preserve its Ambassador continuation and subsequent Harkonnen bonus. |
| Ordinary reserve, Guild cross/return and admitted Homeworld shipment | Preserve each route's price, payer routing and actual eligible Guild income, then apply Junction's cut. Being a Homeworld route alone does not redefine the receipt. |
| Junction-sponsored transport | Preserve the explicit route quote and donor contributions. The high transport permission and later low income condition are different effects; do not replay the completed route if population changes before income. |
The Emperor trigger and the two special-purchase compositions are sourced in [Richese acquisition rules](RICHESE_ACQUISITION_RULES.md#1-advanced-special-karama-purchase) and [Richese Ambassador rules](RICHESE_AMBASSADOR_RULES.md). The publisher directly confirms Richese cache self-purchase routing in [GF9 E2, p.5](https://www.gf9games.com/dune/wp-content/uploads/2021/11/CHOAM-Rulebook-low-res.pdf#page=5). Black Market has its own [source contract](RICHESE_BLACK_MARKET_RULES.md#official-expansion-anchors). The special purchase and Ambassador destinations are general-rule compositions, not claims of dedicated GF9 FAQ answers.
Do not reduce unrelated Emperor/Guild bank awards, charity, revival income, ordinary Collection, sales to CHOAM, or Kaitain's paid card disposal. In particular, the Emperor Ambassador's five bank spice is not a Treachery payment; free Guild Ambassador transport does not manufacture shipping income.
## Occupied branch remains separate
The unoccupied calculation leaves the missing half in the bank. An occupied face can assign that portion to a qualifying occupier and may independently award printed bank spice during Collection. Do not convert the bank remainder into an occupier award until the lifecycle and actual recipient are resolved. Likewise, high native population alone cannot prove that a retained occupation penalty has expired. Any runtime scope guard must acknowledge this limitation rather than describing the population-only quote as complete occupation support.
Future integration must preserve the original eligible receipt, present force state and qualification history separately. Ordinary income cancellation, retained low effects, occupied percentage income and immediate ally sharing must compose from their own rules; the current unoccupied branch is not authority for a future occupied Karama outcome.
## Required verification before a runtime claim
Meaningful regressions cover odd/even and zero receipts, rejection of two eligible odd contributions before declaration or payment, coincident 2 + 1 rounding, both contributor identities, protected original contribution evidence, module-off parity, current 4-to-5 and 5-to-4 changes across legal Ghola interruptions, cancellation without refund, all listed Emperor sources, all admitted shipment adapters and exact parent restoration. Save/recovery tests should prove no repeat debit, card acquisition, force move or faction credit, and reject altered gross/source/owner binding without persistence. Public previews may show the current numeric split but must not expose the purchased card's private face.
This documentation pass reviewed source links, referenced local targets, the limited adapter wiring and whitespace only. The contributor guard and unpublished development code are not a completed runtime checkpoint. Runtime tests, full checks and release evidence belong to the coordinating implementation checkpoint; no such result is claimed here.
+48
View File
@@ -0,0 +1,48 @@
# Homeworld payment income runtime
Development checkpoint, 9 September 2026. Low Kaitain and low Junction now reduce supported native faction payment receipts while preserving the payer's original cost. Occupation and divergent allied-contributor rounding remain unfinished. The [source contract](HOMEWORLD_PAYMENT_INCOME_RULES.md) distinguishes printed rules from timing composition and records the pending user question. No Homeworld, Advanced or expansion start gate is opened by this checkpoint.
## Calculation and settlement
[homeworld-payment-income.ts](../game/homeworld-payment-income.ts) quotes the original eligible gross amount, current native low condition, faction income and bank remainder. A supported low receipt rounds its half upward. Eligibility and actual contributor routing are established before this calculation; a Guild-funded share already destined for the bank is not included in Guild's gross receipt. Kaitain counts its own native forces, excluding the Emperor's Salusa allocation.
The payer has already paid when the faction income opportunity opens. [The engine](../game/engine.ts) credits the quoted faction amount once when that opportunity settles; it does not charge again, refund the buyer or replay the shipment or acquired card. Current native population controls the reduction at receipt. This checkpoint adds no Ghola interruption window; pending income retains the existing card-timing boundaries. Rechecking population at receipt is the continuous-threshold composition documented in the source contract, not a dedicated publisher Ghola example.
Ordinary Karama can prevent the separate Emperor or Guild income advantage. The Homeworld penalty itself remains immune. Canceling an eligible native income leaves the payment in the bank and preserves the completed purchase or transport. This supported unoccupied branch does not decide future occupied-income cancellation or beneficiary rules.
Emperor adapters include ordinary paid auctions, the existing Richese cache self-purchase destination, Richese's advanced three-spice special purchase and successful Richese Ambassador paid draws. Emperor buying for itself creates no self-income. Richese's own seller receipts retain their destination. Guild adapters preserve ordinary and legacy shipment, native return, Homeworld shipment and Junction-sponsored route classifications. Free transport and unrelated bank rewards create no new payment income.
## Unanswered contributor rounding
For two eligible odd contributions, rounding the combined payment and rounding each contributor separately differ. A one-spice plus one-spice non-Guild payment would produce either one or two spice for low Guild. The user question is pending; neither result has been adopted for that case.
The engine rejects that unsupported split before a low-Junction shipment declaration or cost commits. This is a temporary scope guard, not a printed prohibition. Single positive eligible contributions and two-contributor splits on which both interpretations agree remain supported. The aggregate quote implements their common result; it must not be cited as resolving blocked cases. Original contribution evidence accompanies the receipt for later validation, including population-sensitive settlement. Player shipment controls and all four AI profiles use the same public funding guard; blocked candidates are excluded before declaration.
## Saved receipts and private information
New Homeworld Guild income responses retain positive original eligible contribution amounts and a matching proof string. The proof binds turn, phase, owner, gross and contributions. It is an internal consistency record, not a cryptographic authentication claim. Validation checks the amounts sum to gross and rejects partial deletion or mismatched initialized metadata before the relevant read or continuation can settle it.
Legacy responses missing **all** new contribution metadata remain compatible. Such a response cannot reconstruct historical payer evidence, and total metadata removal is not distinguished from a legacy shape by this compatibility rule. This limitation is explicit; the checkpoint does not claim complete tamper detection or full recovery certification.
Contribution amounts and their proof remain server-private in the response projection. The public income preview shows the already-paid eligible gross, current native receipt and bank remainder to every seat; it exposes no private acquired card or unrelated spice balance. [The table](../components/game-table.tsx) explains the low split and unchanged payer cost at the ordinary income opportunity. No additional player claim is needed for the automatic arithmetic.
## Verification at this handoff
Final `npm run check` passes types, lint and **3,541 offline cases**. The
production build passes. **40 HTTP integration cases** passed before the final
UI/AI funding-filter adjustment; that adjustment received the final offline
check and build. The three new payment suites add 26 cases: ten pure quotes,
eleven engine/control/AI scenarios and five production SQLite scenarios.
Independent review verified all four profiles and found no secret-state access
in the shared funding guard. It also identified the Ambassador preview-binding
and AI-candidate defects repaired before these final checks.
All **2,894** rooms in the saved maintenance baseline retain their exact versions
and state hashes. This checkpoint added one isolated browser QA room and thirty
HTTP test rooms. No saved game was reset.
Desktop and phone browser checks exercised a five-spice bid yielding three to low-population Emperor and two to the bank. Keyboard allowance and refresh of all three seats passed. The coordinating agent inspected the resulting views and reported no page overflow or browser errors. These are bounded payment-flow checks, not complete Homeworld-game acceptance.
Focused entry point: `npm test -- homeworld-payment-income`. The relevant suites are [pure rules](../tests/homeworld-payment-income.test.ts), [engine flows](../tests/homeworld-payment-income-engine.test.ts) and [production SQLite recovery](../tests/homeworld-payment-income-recovery.test.ts). Their coverage includes source routing, unchanged payer cost, native threshold crossings, allowed/canceled receipt recovery, divergence rejection before commitment, proof validation and private projection. The implementation-status checkpoint records the same scoped evidence; complete expansion games and occupation behavior are not certified.
This documentation/reference pass changes no database or automation. The removed automation remains removed. Occupation retention, occupied percentage recipients and Collection income, remaining Homeworld effects and complete expansion acceptance retain their existing release gates.
+79
View File
@@ -0,0 +1,79 @@
# Homeworld replacement: source audit and adapter contract
Audited 9 September 2026. Read alongside [Homeworld rules](HOMEWORLD_RULES.md).
This document authorizes no runtime activation and adds no occupation or Ghola
ruling. No production files changed in this audit.
## Sources and explicit rules
The [GF9 Ixians & Tleilaxu rulebook](https://www.gf9games.com/dunegame/wp-content/uploads/2020/09/IxianAndTleilaxuRulebook.pdf)
currently returns HTTP 403. Its publisher-authored 12-page
[retailer mirror](https://lelekan.com.ua/files/rules/2081/pravila-nastilnoyi-gri-dyuna-dim-iksianciv-ta-dim-tlejlaksu-dune-ixians-amp-amp-tleilaxu-dopovnennya-angl-anglijskoyu-movoyu.0.pdf)
was freshly read, including GF9 2020/Future Pastimes credits, pp.6, 9–10 and 12;
the official indexed p.9 and Karama table agree. This is original publisher
content, not the retailer's own rules.
- **Face Dance, p.6:** another faction's victory remains its victory. The
revealed leader dies without a new bounty. Surviving winning forces return
to their reserves. Tleilaxu replacements may come from its reserves or
Arrakis, up to the returning force count. No positive minimum is specified.
The p.10 FAQ orders traitor declaration, winner declaration, then Face Dance.
- **Ixians, pp.9–10:** after calculating casualties, surviving Suboids at that
battle's location may replace Cyborgs lost in that battle, one for one. The
example sends the substituted Suboids to the Tanks and retains the Cyborgs.
The p.12 Karama table permits canceling this ordinary substitution advantage.
The [GF9 E3 rulebook, p.10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=10)
was freshly checked through its official indexed text; direct retrieval also
returns 403. Only natives may call Homeworld Face Dancers. It does not require
the native caller to be one of the two combatants. Homeworlds hold reserves;
they are not Arrakis territories. Advanced Emperor has two homes: initial
Sardaukar and revived Sardaukar go to Salusa, revived normal forces to Kaitain.
An expressly permitted transfer can subsequently mix the types. Those placement
sentences do not expressly assign forces returned by Face Dance. The
[designer's expansion page](https://futurepastimes.com/dune-ecaz-moritani)
supplies no additional replacement ruling. No community compilation was adopted
as an erratum.
## Physical interpretation and remaining assignment boundary
**Native Tleilaxu:** composition of the ordinary caller rule permits a reveal
after two visitors fight at Tleilax, subject to the existing occupied-face
restriction. Eligibility must not require Tleilaxu to have lost that battle.
This is a composition, not a separately retrieved three-army FAQ.
Native reserve counters are already at the destination. Selecting some as
replacement sources must produce no net force change. The interface may omit
that redundant selection while allowing zero external replacements. Existing
natives remain; returning winners disappear. Only actual external arrivals
increase the native pool. Never create a Tleilaxu visitor pool on Tleilax or
withdraw the same reserves twice. The original source scope does not expressly
include Tleilaxu garrisons on other foreign Homeworlds.
**Returning winner:** preserve every normal/special identity and return only
that winning army, not third parties. A single native Homeworld has an
unambiguous destination. Advanced Emperor's allocation remains unverified:
neither arbitrary player choice, universal Salusa routing for stars, nor
restoration to a historical shipment origin is expressly prescribed for this
effect. Keep this assignment boundary visible rather than presenting a revival
helper's default as a confirmed Face Dance rule.
**Ixian adapter:** treating substitution as ordinary battle cleanup at a
Homeworld is an application of existing combat mechanics, not a new shipment
permission. Use the one actual native or visiting Ixian pool at the battle
location. Record the Cyborg casualties of that resolved battle; surviving
Suboids elsewhere cannot pay. Exchange exact types between that pool and
the Tanks. Total physical casualties and total Tanks remain unchanged by the
exchange; only their type allocation changes. No sectors, reserve shipment,
revival allowance, revival income or fresh population-arrival event is created.
Native reserves elsewhere and unrelated old Cyborg deaths are not recovery
sources. Cancellation leaves the original casualties intact.
## Verification targets
Test native and visitor Ixian pools, exact casualty receipts, cancellation and
JSON resume. For Face Dance, cover a noncombatant native, no replacement,
existing native reserves, Arrakis arrivals, untouched third-party armies,
special-counter returns, and the unresolved Emperor assignment explicitly.
Reject duplicate or nonexistent sources before changing custody. Preserve the
original winner, leader/card cleanup and any prior battle rewards.
@@ -0,0 +1,86 @@
# Homeworld reserve integration audit
Read-only engine audit, 9 September 2026. Line references identify the source examined before the coordinator's Homeworld setup/Emperor-transfer integration; function names are the durable anchors. No runtime edits or new rules are introduced here. The source contract is [HOMEWORLD_RULES.md](HOMEWORLD_RULES.md), with the broader location architecture in [HOMEWORLD_RUNTIME_READINESS.md](HOMEWORLD_RUNTIME_READINESS.md).
## Authoritative custody and an important Ix correction
`game/homeworld-custody.ts` derives native primary forces from `Player.reserves` and `elites.reserves`, subtracting the explicitly stored Salusa normal/elite allocation. Foreign garrisons are separate. `quoteHomeworldCustody` changes aggregate native totals and Salusa together and returns exact before/after receipts; it does not perform the matching board/Tanks transfer or authorize the rule action. Every native withdrawal/deposit must therefore be composed with its board/Tanks delta exactly once.
**Ix setup is already correct.** `initializeStartingForces` (`engine.ts:3473`) sets remaining Cyborg reserves to four and places three Cyborgs among six HMS forces. `place` (`3291`) only credits a location, so the resulting four reserves plus three deployed counters are the seven physical Cyborgs. Do not subtract three from the four again. `newPlayer` (`2076`) correctly has all seven before setup; `tests/ix-forces.test.ts:113–121` checks a seven-counter inventory. The new custody helper initially used an Ix maximum of four; that is the initial remaining reserve count, not the physical cap. The coordinator was notified to change that cap to seven and add a return/revival regression. Later all seven may legally be native reserves.
## Real setup hook
| Hook | Current behavior | Correct integration responsibility |
| ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `newPlayer`, `2072–2077`; lobby faction action, `15846` | Fresh reserves20; only Ix has an initial elite record, with seven. Faction changes replace the elite record. | Store the module option separately. Do not freeze native pools or Salusa against a lobby roster that can still change. |
| `start`, `3403` | Public Basic/base/no-expansion gate. | Explicitly retain the Homeworld gate while only native setup/transfer is integrated. No implicit activation from possessing a card catalog. |
| `initializeSetup`, `3420` | Sets decks/order and enters prediction stage; private traitor deal follows later. | Validate the module/configuration here, but do not prematurely install a native snapshot or expose starting cards before the established prediction/traitor order. |
| `initializeStartingForces`, `3457–3497` | Grants starting spice, creates faction pieces, deletes/rebuilds elite state, and applies fixed board placements. | Install initial custody after these operations. Advanced Emperor's five initial Sardaukar then populate Salusa. Other native groups derive from the final remaining totals. |
| `advanceSetup`, `3566–3574` | Runs the force initializer once, then waits for Fremen/BG placement before dealing Treachery. | Never re-run `createHomeworldCustody` on every normalization or force choice: that would overwrite later saved allocations. |
| Fremen setup, `15907–15959` | Places ten with explicit `elitePlacements`, subtracts selected elites, sets reserves10. | Preserve the selected physical starred counters; derived native custody shrinks accordingly. Creation of the identity record must precede this choice. |
| BG setup, `15870–15892` | Advanced starting advisor removes one native reserve. | Debit its sole native pool; preserve setup order/stance. |
| Moritani setup, `14715–14736` | Places six after the other setup conditions complete. | The existing setup sentinel is reserves20. Do not alter that count merely to represent the Homeworld. Its native pool then becomes fourteen. |
| `initializeBaseGameForAudit`, `3579–3638` | Strict cloned fresh base lobby without optional modules. | Add the Homeworld exclusion to this existing contract. A new explicitly named fresh all-faction audit seam can exercise the shared initializer without changing public start authorization. |
An installation after fixed placements is safe while the later choices remain genuine setup actions: native counts are derived, so their subsequent single-world debits need no recreation of custody. Initializing at `finishSetup` instead is too late for a source-correct setup view and risks treating all later reserve mutations as unobserved initialization. Do not retrofit a Salusa allocation into an arbitrary already-playing save by guessing where its Emperor forces were located.
## Every existing engine reserve mutation category
The following are actual mutation sites, not every occurrence of the word reserves. Pure prerequisite helpers and projections must receive the matching source data, but must not commit these deltas themselves.
| Route / exact source anchor | Present mutation | Required native allocation and failure example |
| ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `revealPlayerNoField`, `1329` | Materializes Richese forces from reserves. | Debit Richese's native pool only when physical forces are revealed; deploying the marker alone does not debit its hidden denomination. Never count marker plus still-native physical forces as two inventories. All reveal callers inherit this path. |
| `commitShipment`, `13107–13109` | Debits selected total and elite reserves, then places physical forces; allied No-Field physical shipment shares this branch. | Advanced Emperor needs exact Kaitain/Salusa source quantities, potentially combined in one shipment. An aggregate subtraction can leave `salusa.elite > eliteReserves`, or silently withdraw regulars from Kaitain when those regulars are actually on Salusa. Preserve source allocation through pending Guild/Karama declarations. |
| `commitAmbassadorShipment`, `7074–7076` | Free Guild Ambassador selected native forces to Arrakis. | Same physical source requirement even though payment and ordinary counters are absent. Emperor beneficiary may need both native pools; do not infer location from `elite` alone after interworld transfers. |
| `finishGuildAmbassadorAdvisor`, `7265`; `finishResponse` BG advisor branch, `12872` | Removes one BG reserve for free accompaniment. | Debit BG's single native pool; source-specific destination restrictions remain separate. No new Homeworld advisor permission follows from the custody helper. |
| `decideTerror` Sneak Attack, `8347` | Moritani reserve reinforcement. | Debit the native pool, preserving its independent arrival continuation and zero-choice behavior. |
| `applyGholaEffect`, `10123–10128` | Tanks→reserves and elite Tanks→elite reserves; increments elite usage. | Deposit revived Emperor normal forces on Kaitain and Sardaukar on Salusa through the prescribed revival routing, while preserving Ghola's own quota/income semantics. Do not merely increase aggregate elite reserves and thereby derive the new Sardaukar on Kaitain. |
| `finishRevival`, `11688–11704` | All ordinary force and Emperor-funded-extra revival recipients share this commit. | Same typed return routing; preserve payer versus recipient, frozen price, ordinary/free counters and exact quoted Axlotl/Tleilaxu income. Leader, Auditor, KH and buyback branches do not themselves move force reserves. |
| `executeSpecialKaramaIntent`, Emperor forces, `13944–13951` | Free Tanks→reserves with typed counter usage. | Must use the same typed native revival deposit. The card's cost/once-per-game flag remains owned by the surrounding effect. |
| `finishResponse` CHOAM Trip to Gamont, `12269–12273` | One selected board force returns to its owner's reserves, preserving elite identity. | Non-revival native return needs an explicit destination contract for two-world Emperor; do not automatically classify every return as revival or increment revival counters. Keep the unresolved destination policy separate from the otherwise definite physical return. |
| `applyActionInner`, Face Dancer replacement, `15278–15294` | Tleilaxu may withdraw own reserves as replacement; every defeated winner force returns from the territory to its native reserves, including its elites. | Debit Tleilaxu native reserves. For an Emperor winner, the returning normal/elite group needs a source-appropriate **non-revival** deposit decision/contract. Normal board replacement is not shipment and must not add fees or movement counters. |
| `applyActionInner`, `guildShip`, `16811–16817` | Paid Fremen ally reserve route debits reserves; Guild board return credits reserves; board cross-shipment uses `removeGroup`. | Current genuine native actors have one native Homeworld, but future Junction sponsorship exposes arbitrary recipients. Retain explicit return destination and typed custody rather than treating every `to:'reserves'` as a universal primary-pool return. |
| New Emperor internal transfer | Not present in the audited snapshot. | One atomic withdrawal+deposit between Kaitain and Salusa; aggregate reserves and total elite reserves remain unchanged. Validate both source physical types before debit, then update movement consumption once. No shipment fee, no Heighliner grant, and no piece multiplication. |
Setup writes described above are the remaining direct reserve mutations in the audited engine. Outside it, `homeworld-custody.ts` mutates only its detached quote results; the search found no other production module directly changing a player's reserve count. Pure helpers that return transformed custody, disaster calculations or views are not additional live commits.
`game/tleilaxu-ambassador-forces.ts` is a pure prospective quote, not an additional integrated Ambassador commit. Likewise the Ecaz Reinforcements/Harass & Withdraw definitions and the new Homeworld free-revival/reinforcement faces must eventually use the same native transfer boundary, but this inventory does not invent live handlers for them. Tleilaxu Ambassador entitlement questions remain separate from routing its eventual actual returns.
## Basic physical identity is not an Advanced power switch
E3 explicitly uses starred Fremen identity in Basic Homeworlds. Current code normally has no Basic Fremen/Emperor elite record, so several consumers implicitly use record presence as a feature flag. Preserve physical identity without accidentally introducing Advanced benefits or restrictions.
| Consumer | Existing behavior / required separation |
| ---------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `combatForces`, `engine.ts:3347–3381`; bot fallback `bots.ts:535` | The descriptor sets elite strength2 without a Basic-Fremen guard. Gate benefit strength by rules mode while preserving physical counts. Ordinary Basic scoring is **not universally doubled today**: the separate plan gates below already keep normal Basic dial limits. The descriptor still feeds public `ownForces`, Stone Burner and direct casualty calculations. |
| `validatePlan`, `9766`; `findLegalBattlePlan`, `10161`; bot plans, `545`; Prescience answer, `17124` | Already use `advanced | | ixians`to choose strength-valued/half-step dialing. Do not replace this with`!!p.elites`, which would introduce Advanced dialing merely because Basic starred counters are tracked. |
| Combat power queue, `9953–9959` | Already offers Emperor/Fremen elite and Fremen support responses only in Advanced. Preserve that guard. |
| `eliteRevivalRemaining`, `revival.ts:182` | Has no game-mode argument: non-Ix tracked elites are capped at one per turn. Mode-aware eligibility is necessary before Basic physical tracking is made playable. Do not silently adopt an Advanced restriction from existence of the counter record. |
| Its engine callers | `gholaOptions:10054`, `applyGholaEffect:10120`, Ghola/card prerequisite `10240`, special Karama validation `13687`, extra revival `16259`, ordinary revival declaration `16466`, projected revival choices `17890`. All must agree with the actual commit. |
| Its other callers | `revival-cancellation.ts:101` saved/canceled revival validation; `bots.ts:1250,2616,2626,2636`; `components/game-table.tsx:3262`. Updating only the live declaration leaves restored receipts, bots or UI contradictory. |
| `battle-resolution-quote.ts:456`; `kill:3296` | Basic normal winners take immediate untyped dial losses, and default `kill` selects normal counters first. Once starred identity has future Homeworld value, this is a separate typed-casualty selection audit: do not claim identity-aware combat complete merely because the counters survive setup. Total losses and ordinary strength must remain Basic. |
| Fremen setup bot, `bots.ts:1067` | Currently omits `elitePlacements` and therefore leaves all stars in reserves. This is legal, though a meaningful future Homeworld policy should reason from the actual card. The human action already accepts explicit setup allocation. |
| `place`, `3291`; `kill`, `3296`; `removeGroup` | Preserve typed location/Tanks quantities mechanically. Their physical accounting does not itself require Advanced strength. Retain it rather than discarding Basic special identity after movement or death. |
Basic Emperor uses only Kaitain. Preserving its five printed counter identities is compatible with the location model but has the same mode-aware combat/revival obligations; it is not necessary to create Salusa in Basic. Ix always retains its own printed typed mechanics in both modes.
## Saved commitments and speculative preparation
Pending shipments currently bind aggregate `amount`/`elite`, not a split native source. New source selections must be part of the original intent and revalidated at final allowance. Equal aggregate totals do not prove the same Homeworld still contains a promised group. This applies to ordinary shipment, Guild Ambassador shipment and any future Junction-sponsored shipment.
`ordinaryDiscardSignature` (`engine.ts:2238`) captures completed reserve/elite outcomes for Ghola, but a new Salusa allocation is not represented by old aggregate fields. Extend appropriate completed-effect/signature receipts when Homeworlds are active; a wrong secondary allocation with unchanged totals must not pass recovery. Revival cancellation and terminal preflight must quote the real typed destination without performing effects or payments twice.
`findShipmentCompletion` uses internal `shipmentPreparation` execution to simulate real Ghola preparation while suppressing only the ordinary discard frame. Its cloned native custody must change through the same helper as live execution. Otherwise an apparently legal Ghola→shipment witness can fail after the actual Ghola restores Sardaukar to a different pool. Projections may inspect public native counts and owner-controlled source options, but cannot mutate a live Homeworld or emit income while constructing a witness.
## Required concrete checks for this integration
1. Actual prediction→traitors→fixed forces→Fremen/BG/Moritani choices→starting cards preserves existing order. No custody recreation after JSON reload; no duplicate native pieces. Every seated faction receives exactly its active Homeworld locations.
2. Ix setup retains three Cyborgs on HMS and four native; later a legal return can yield seven native Cyborgs. Full physical totals include visitors and Tanks, not just the helper's local native-plus-visitor bound.
3. Advanced Emperor starts Kaitain15normal/Salusa5Sardaukar. Transfer normal forces to Salusa, then reject an attempted withdrawal from empty Kaitain even when aggregate reserves suffice. A reverse transfer restores the original allocation and consumes only the appropriate movement once.
4. A mixed outbound Emperor shipment can use both locations once; pending/reloaded/canceled declarations preserve the selected source quantities. A source corruption with unchanged total reserves rejects atomically.
5. Normal and Ghola revival credit the correct typed native pool and preserve unrelated counters/income. Non-revival card returns must not be silently forced through a revival helper with new quota or placement semantics.
6. Basic Fremen retains all three stars across setup, movement, Tanks and revival without double strength. Check authoritative action, public descriptor, all bot levels and resumed prerequisite against the same mode-aware eligibility.
7. Existing games with the option disabled retain their behavior and saved state. The new fresh audit seam rejects reused/dirty state; public starts remain gated until complete Homeworld gameplay is implemented.
The audit found the concrete Ix custody-cap error described above and the Basic-record/mode coupling. It does not claim that the Homeworld module is playable, choose an unresolved Emperor non-revival return destination, or infer any other new rules from an implementation convenience.
@@ -0,0 +1,239 @@
# Revival deployment integration audit
Historical integration audit, retained as the pre-implementation hazard map.
Statements below describing proposed hooks or missing controls reflect that
earlier audit, not the current runtime. As of 10 September 2026, source-specific
normal, Emperor-extra and Ghola settlement hooks create `homeworldRevivalReturn`;
the engine connects its owned placement decision, typed custody transfer,
Ambassador continuation and held revival-income response. Dedicated destination,
return-receipt and projected-choice modules now exist, with focused engine and
production SQLite coverage.
Use [the runtime checkpoint](HOMEWORLD_REVIVAL_DEPLOYMENT_RUNTIME.md) for current
behavior and verification limits, and [the source contract](HOMEWORLD_REVIVAL_DEPLOYMENT_RULES.md)
for the unresolved threshold, quantity and arrival classifications. This
historical document does not select those interpretations or lift the full
Homeworld/expansion release gates.
Related contracts are [Homeworld benefits](HOMEWORLD_BENEFITS_RULES.md),
[Homeworld replacement](HOMEWORLD_REPLACEMENT_RULES.md),
[occupation integration](HOMEWORLD_OCCUPATION_INTEGRATION.md), and
[Collection/Terror integration](HOMEWORLD_COLLECTION_INTEGRATION.md).
## Concrete integration hazards
1. `engine.ts::addRevivedReserves` is a physical destination adapter shared by
normal revival, Ghola and Emperor special Karama. Adding the ability there
would lose the distinction between ordinary Free Revival, a free card effect
and a paid return. The effect needs a producer-supplied source receipt.
2. `PendingRevival` saves total `amount`, total `elite`, scalar `free`, price and
ordered checks. It does not save a generally usable typed free group.
`action.freeElite` is currently meaningful only for Ixian pricing; that split
is recoverable from the frozen normal price. Do not infer every free elite
allocation from cost zero, or deploy all revived forces when only some were
Free-Revived. Native Tleilaxu has no special counters, simplifying its own
group, but the shared contract still needs explicit types.
3. Once returned counters merge into reserves, counts alone cannot distinguish
the new eligible batch from previously held reserves. A bounded, protected
typed group must survive until placement or decline; a second independent
revival must not append to the earlier permission or substitute its pieces.
4. Normal revival and Ghola both create income continuations. Installing a new
`decision` before those existing controls are saved can overwrite the income
response or let the original parent continue before the placement finishes.
5. Ghola's `ordinaryCardDiscard` integrity explicitly rejects a suspended
decision. Simply opening a placement inside `applyGholaEffect` makes its
normal card-disposal continuation invalid. Any supported Ghola trigger needs
a deliberately extended continuation, including market-sale Ghola's parent.
6. Ordinary Homeworld shipment has phase, cost, source and own-world permission
rules. Reusing `quoteHomeworldShipment` or its engine dispatcher directly
would consume a shipment, apply a price, or reject a separately authorized
native destination. Reuse custody and destination validation, not that action.
7. Arrival may trigger Intrusion, Terror or an Ambassador only if the verified
rule classifies this deployment as a qualifying entry. A new phase-four
placement is not automatically an ordinary phase-five shipment. Conversely,
skipping the existing arrival pipeline without checking that classification
could omit a required reaction.
## Actual force-return producers
| Producer | Original source evidence | Current settlement |
| --- | --- | --- |
| Normal `revive` action | `forceRevivalQuote`, selected total/elite, scalar free, costs and ordered checks | `beginRevival` → CHOAM free-revival opportunity → Tleilaxu stop/checks → `finishRevival` |
| Emperor-funded extra ally revival | `PendingRevival.emperorExtra`, distinct payer, free zero and full frozen price | Same `finishRevival`; increments `emperorExtra` rather than normal revival usage |
| Ghola force branch | Physical owned card, selected total/elite, separate card timing and per-turn special-counter limit | `applyGholaEffect` returns forces, then Axlotl/Tleilaxu income and physical card disposal |
| Emperor special Karama force branch | Prepared `emperorForces` intent, original turn/phase/card, total/elite | `executeSpecialKaramaIntent` returns forces, marks special usage and consumes the card |
| Leader/Kwisatz/foreign-ghola/Duke revival | Explicit leader identity and its own cycle/custody authority | Does not produce a force group; must not create a deployment receipt |
| Ixian substitution or Face Dancer replacement | Their own already-committed battle/replacement receipt | Not a generic revival event merely because counters leave Tanks or reserves |
`addRevivedReserves` calls `quoteNativeRevivalDeposit` when Homeworlds are active.
This deposits normal Emperor counters on Kaitain and Sardaukar on Salusa;
other factions deposit on their native primary world. It does not authorize
revival, price it or inspect Tanks. Retain that separation. Existing withdrawal
uses `quoteNativeReserveWithdrawal`, which enforces exact normal/elite sources
and cannot consume visitor forces or guess an ambiguous Emperor allocation.
Do not silently broaden Southern Hemisphere to every listed return producer.
The source audit must decide normal paid revival, Ghola, Basic starred counters,
and any exceptional replacement cases from the actual wording. High Tleilax
specifically requires identifying the qualifying Free-Revived group; paying
zero for some other effect is not adequate source evidence.
## Normal revival sequencing
The declaration quotes the current free rate and selected group before changing
population. `beginRevival` allows CHOAM's reactive La La La before offering
Tleilaxu's special stop and ordinary advantage checks. A successful La La La
clears the request without payment or force movement; its cancellation resumes
the same original request. `quoteRevivalCancellation` and `quoteRevivalResume`
preserve the frozen request rather than silently reprice an accepted batch.
`finishRevival` is the first normal producer hook that proves the force return
actually succeeded. Unfunded and Fremen-limit outcomes must produce no deployment
permission. Successful settlement debits the correct payer, deposits the exact
typed group, removes it from Tanks, updates normal or Emperor-extra allowances,
and handles Axlotl income. It then clears `pendingRevival`, records ordinary free
income use and installs the quoted `revivalIncome` response.
Capture a completed return receipt at that settlement boundary. Do not leave
`pendingRevival` live after counters have moved: its resume validation expects
the original unreturned group and accepted free allocation. Preserve the native
eligibility observation required by the source audit separately from the
resulting population. In particular, a return can cross Southern Hemisphere's
three-counter or Tleilax's nine-counter minimum, and a later deployment can
cross back. These are distinct observations, not a reason to recalculate the
accepted price or grant another bonus.
Keep Tleilax's existing low-income observation at the start of Revival separate
from its high deployment eligibility. `homeworldRevival` owns that phase-start
condition; ordinary free-income once-per-player history uses
`revivalFreeIncome`. Neither is a record of which returned counters can deploy.
The deployment must not create another Axlotl or Tleilaxu revival payment.
## Ghola and nested controls
`applyGholaEffect` has explicit leader and force branches. Its force branch
returns at most five physical counters, updates elite usage, and leaves normal
revival allowance untouched. `collectRevivalIncome(..., ghola=true)` creates the
separate Ghola bank reward; it is not ordinary Free Revival income.
`stageOrdinaryCardDiscard` captures the current controls, clears them and binds
the completed effect through `ordinaryDiscardSignature`. That signature includes
Homeworld custody, revival income history, force/Tanks/resource totals and the
saved response. The current validator admits only the expected Tleilaxu income
response after Ghola and no suspended decision. `finishTreacheryDiscard` restores
those controls after the physical card retires.
The scoped `pendingChoamMarketGhola` additionally preserves the original CHOAM
sale through discard → income → complete, then `resumeMarketGhola` restores the
sale. If Southern Hemisphere also applies to a Ghola return, its deployment
must remain inside this original parent, without replaying the card, revival,
income or sale. Add an explicit source-linked child stage; never mark the market
interruption complete merely because no income response exists while a placement
still waits. Ghola played in battle also needs the original battle controls and
population-sensitive support limits preserved.
Richese gifts/purchases, Nullentropy, Truthtrance, Worthless-as-Karama and generic
response suspensions retain their original controls while source state remains
live. Include a new placement obligation in their integrity fences where it can
legally coexist. Do not restore a whole old Game snapshot over newly settled
resources. Existing Duke revival remains leader-only with its own source/custody
gates; no force-deployment decision should change Duke controller or cycle.
## Proposed shared contract
Use a focused pure module with a public physical context and an explicit
completed-return receipt. A possible receipt shape is:
```ts
type RevivalReturnReceipt = {
event: string;
turn: number;
phase: number;
owner: string;
source: 'normal' | 'emperorExtra' | 'ghola' | 'emperorKarama';
returned: { normal: number; elite: number };
free: { normal: number; elite: number };
paid: { normal: number; elite: number };
card?: string;
nativeSources: Record<string, { normal: number; elite: number }>;
// Exact eligible subset and eligibility observation are fixed by source rules.
};
```
This is a proposed shape, not a decision that every source activates either
Homeworld. Require `free + paid = returned` for normal classified groups; a
card-effect source must retain its own classification rather than automatically
calling all zero-cost pieces Free-Revived. If card effects need a third category,
model it explicitly. Bind the original eligible subset and producing event in
an immutable consistency receipt, with an independent outstanding obligation so
deleting the pending choice cannot silently erase or duplicate it.
A pure destination quote should accept that receipt, actor and a discriminated
choice (`decline` or one explicit destination). Return exact custody transfers
and arrival facts; do not mutate counters, spend another allowance, mint income
or select opponent secrets. Source verification decides whether a subset may
deploy or the entire eligible group must move together. Never offer more than
the receipt's eligible types, even if reserves contain many other counters.
The optional decision needs an independent event and stage, with the original
income/card/outer continuation retained. Serialize stages such as awaiting
selection, committed arrival and completed; exact order follows the source
audit. Once physical departure and arrival commit, resume only the reaction
suffix. Decline consumes the optional placement opportunity while keeping the
already revived counters at their recorded native location.
## Destination validation and entry
For an Arrakis destination, reuse `allowedEntry`'s sector/storm/occupancy checks
where the printed route requires them, but do not automatically grant Fremen's
ordinary storm-shipment exception or enforce its Great Flat reinforcement range.
Those belong to the ordinary shipment source. Southern Hemisphere's destination
presence prerequisite should read the verified native physical presence, not a
foreign player's forces or hypothetical future placement. Exact advisor, mobile
stronghold and Homeworld scope remains a source question.
For a Homeworld, use explicit `homeworld:*` identity and
`quoteHomeworldCustody` transfers, respecting the verified ally/native destination
rules. Homeworld locations are not Arrakis sectors and must not pass through
`place`, `territory` or a fabricated sector zero. Do not turn free deployment
into a Guild tariff, paid shipment, ordinary shipment promise or Heighliner event
without a rule establishing that trigger.
If this arrival qualifies for reactions, extend `openTerritoryEntry`, Intrusion,
Terror/Ambassador continuation identity and `terror-entry-receipt.ts` with the
new explicit cause and resume contract. Terror's original count must be exactly
the deployed batch, not all destination occupants. Low Grumman's three-force
rule and all preflight checks must use that same count. Existing simultaneous
arrival ordering gates remain until the new composition is verified. Off-planet
deployment must likewise call the eventual occupation lifecycle at its actual
physical event, without inventing an Arrakis reaction.
## UI, bots and recovery hooks
`GameView.revival.pending` currently means only `pendingRevival`; it cannot stand
in for the new optional decision. Add a source-labelled owner-only descriptor
with event, exact eligible types, currently legal destinations and decline.
Observers need the public pending owner and committed result, not the owner's
card or undisclosed choices. Reuse the destination quote for UI and bots.
Normal revival controls in `components/game-table.tsx` select total, elites and
Ixian free elites. Ghola controls use `GameView.ghola`; neither currently selects
a later deployment. Add a separate decision component rather than reusing the
ordinary shipment form. All four bot levels need a legal destination or explicit
decline. `standaloneGholaAction` already avoids pending decisions; preserve that
behavior and prevent a new revival from replacing an outstanding group.
Integrate obligation validation with pre-action/view/normalization integrity and
`finishActionContinuations`. Automatic progression must wait for a real choice;
`automaticContinuationPending` should represent only an automatic stage. Test
JSON plus SQL competing workers so an accepted uncertain response cannot repeat
the revival, deployment, income or optional decline.
Minimum regression matrix: pre/post threshold crossing; mixed free/paid return;
new versus previously held reserves; exact Fedaykin identity; module off and
Basic/Advanced physical counters; La La La allowed/canceled and revival denied;
Tleilax income allowed/canceled; Ghola card disposal and market/battle parents if
supported; destination storm/occupancy and actual arrival reactions; deleted or
altered original receipt; all four bots; private getter and observer equivalence.
Only this document changed in the audit. Local links and current code symbols
were reviewed; no tests or runtime behavior were changed.
@@ -0,0 +1,63 @@
# Southern Hemisphere and Tleilax revival deployment
Primary-source audit, 10 September 2026. This is a source and implementation-boundary contract, not a runtime completion claim. The coordinator has already asked about threshold restoration and splitting several revived Fedaykin; those answers remain pending.
## Printed effects and provenance
The high faces were visually reread in the original 3024×4032 component photograph, locally `/tmp/dune-card-economy-homeworlds.jpg`, associated with [BGG image 7767034](https://boardgamegeek.com/image/7767034/dune-ecaz-and-moritani). See the [component audit](HOMEWORLD_COMPONENT_AUDIT.md) for provenance. The photographed publisher components are evidence; community explanations are not substituted for rules.
| Homeworld | Native high threshold | Printed scope, paraphrased |
| --- | --- | --- |
| Southern Hemisphere | 3 | Newly revived starred Fedaykin may immediately join a territory already containing Fremen forces. |
| Tleilax | 9 | On taking Free Revival, its returned forces may go from reserves, without cost, to one territory or Homeworld, observing storm and occupancy restrictions. |
Southern uses plural forces and does not name Free Revival or a phase. Tleilax uses the verb **send**, not **ship**. Earlier local documents calling the latter a shipment use a classification inference; the face alone does not establish that inference.
## Exact returning group
Southern applies to actual starred counters revived by an otherwise supported producer: ordinary revival, Ghola, or an eligible Ambassador effect. It excludes ordinary counters, leaders, preexisting reserves, Face Dancer replacement and returning surviving forces. Preserve the physical starred identity in Basic too. Advanced permits only one Fedaykin revival per turn across producers; Basic does not acquire that Advanced limit. [GF9 E3, p.16](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=16), [November FAQ, p.2](https://www.gf9games.com/dune/wp-content/uploads/2020/11/Dune-FAQ-Nov-2020.pdf#page=2).
Tleilax names the ordinary Free Revival source. A paid counter in the same request is excluded. Modifiers to that ordinary free allowance retain its source. E1 distinguishes free revival from Ghola; zero spice alone therefore cannot classify a Ghola or Ambassador return as Free Revival for deployment. This distinction composes the printed sources; no retrieved FAQ directly answers this Homeworld/Ghola interaction. [GF9 E1, p.7](https://www.gf9games.com/dunegame/wp-content/uploads/2020/09/IxianAndTleilaxuRulebook.pdf#page=7). Keep any unresolved Ambassador quota restrictions from its [existing audit](TLEILAXU_AMBASSADOR_RULES.md).
## Population and immediate timing
The base return goes into reserves. E3 maintains high benefits while the minimum native population is present and inactivates them below it. Its nearby immediate-qualification language concerns occupation, not an explicit revival-trigger ordering. [Base, p.9](https://www.gf9games.com/dunegame/wp-content/uploads/Dune-Rulebook.pdf#page=9), [E3, p.9](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=9).
Ordinary free-rate pricing remains the pre-return quotation described in [benefit rules](HOMEWORLD_BENEFITS_RULES.md). Eligibility for a newly triggered deployment is a separate question. Depositing the complete revived group and then testing high is a plausible composition, but no inspected source settles the low-to-high boundary. Do not present it as a verified timing rule. Preserve both populations and block the divergent case pending the existing question.
If the player starts high and only the newly returned subset leaves, its native population cannot fall below its pre-return count unless another intervening action changes custody. This supplies an independently usable timing subset. Do not substitute old reserves for the returned group. A pending decision must reserve its exact eligible counters and revalidate intervening custody changes.
Tleilax specifies one destination. Southern does not explicitly settle whether a Basic group containing several stars can split among territories, nor whether repeated placements re-evaluate an entitlement earned by the group. The already-pending question covers that case. Do not resolve it through array iteration order or silently assert that plural wording mandates either one destination or several.
Sending the complete eligible group to one legal destination works under both candidate destination interpretations, so the splitting question does not require declining that common case. Neither face expressly permits an arbitrary strict subset through an up-to quantity. A complete eligible group or decline is the strongest directly supported quantity subset; do not present arbitrary partial deployment as separately verified. For Southern the eligible group means only its newly revived stars; for Tleilax it means only the ordinary free counters, excluding any paid counters returned alongside them. Finish that disposition once instead of repeatedly offering the remainder and thereby silently allowing splitting.
## Destinations and arrival effects
Homeworlds are not territories, and allied Homeworld destinations are forbidden. Southern's territory permission therefore excludes Homeworlds; Tleilax expressly includes them. Neither effect authorizes ignoring other occupancy restrictions. [E3, p.10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=10).
Southern's existing-force requirement is territorial, not a Great Flat distance limit. Its face supplies no express storm permission. The Fremen half-loss permission in the November FAQ is explicitly about Shipment; applying it to revival placement would be an additional interpretation. Fremen reserves are on-planet. Strongholds containing two other factions cannot be entered for any reason. [November FAQ, pp.2,5](https://www.gf9games.com/dune/wp-content/uploads/2020/11/Dune-FAQ-Nov-2020.pdf#page=5).
Use legal out-of-storm sectors for the independently supported Southern subset. Do not label storm placement definitely forbidden or definitely half-loss solely from that subset. Preserve ordinary alliance and protected-location rules; the word territory is not authority to bypass the Hidden Mobile Stronghold's source-specific restrictions.
| Interaction | Source-grounded treatment or remaining boundary |
| --- | --- |
| Guild payment income | The deployment costs zero, so it generates no paid-spice receipt regardless of shipment classification. |
| Ordinary turn usage | This immediate revival consequence does not use or reset the later ordinary shipment/movement allowance. This is timing composition, not a separate FAQ example. |
| Heighliner | The Tech Token operates in Shipment & Movement. Ordinary Revival-phase deployment therefore does not pay it. Do not generalize this conclusion to a future out-of-phase producer without inspecting its source. [E1, p.5](https://www.gf9games.com/dunegame/wp-content/uploads/2020/09/IxianAndTleilaxuRulebook.pdf#page=5). |
| BG accompaniment | Requires an off-planet shipment onto Dune. Southern's on-planet origin does not satisfy it. A Tleilax destination on another Homeworld also does not satisfy onto-Dune. Tleilax deployment onto Arrakis still needs its send/shipment classification settled. [Base, pp.17–18](https://www.gf9games.com/dunegame/wp-content/uploads/Dune-Rulebook.pdf#page=17). |
| BG Intrusion | Its condition names shipping or moving into a territory with fighters. Neither face explicitly classifies its arrival using those terms. Do not automatically force or suppress an Intrusion response at an affected destination. [Base, p.18](https://www.gf9games.com/dunegame/wp-content/uploads/Dune-Rulebook.pdf#page=18). |
| Moritani Terror | The general trigger names movement or shipment. These deployment classifications are not settled by the retrieved sources. No-Field placement's explicit FAQ treatment does not prove all placements trigger Terror. [E3, pp.5,14](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=5). |
| Ecaz Ambassador | The printed trigger more broadly names entry into a stronghold. Actual deployment can compose with this entry condition and its ordinary faction, ally and advisor exclusions; this is not a specific revival FAQ answer. [E3, p.7](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=7). |
| Karama | The Homeworld effect itself is immune. Independent ordinary advantages retain their own cancellation rules. Do not duplicate the existing unresolved special-Tleilaxu-Karama versus underlying revival question. [E3, p.10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=10). |
Until arrival classification is settled, a legal destination with no relevant unresolved reaction permits useful independent work. At a destination where classification changes a reaction, preserve an explicit gate instead of choosing a reaction policy silently. An off-planet BG accompaniment opportunity can make classification relevant even when BG is absent from the selected territory.
## Implementation handoff and existing questions
Retain a server-owned event receipt containing source kind, player, turn/phase, revived physical normal/starred counts, the actual ordinary free subset, pre/post native counts, remaining eligible counters and the suspended phase continuation. Bind its immutable event fields. A deployment must consume those reserved counters exactly once, and decline must leave them in reserves. Restore cannot recreate an offer from current reserves, current Tanks or a recalculated free rate. Keep projected choices, bots and server validation on the same quote; expose no private card identity merely to identify a Ghola source.
Meaningful regressions include paid/free mixed revival, old reserves excluded, Basic stars versus Advanced shared revival cap, low-to-high refusal pending its ruling, no Homeworld option for Southern, one Tleilax destination, legal storm sectors, current alliance occupancy, reaction-specific gates, unchanged phase usage, decline, JSON continuation and rejected-action immutability. Additional complete-module verification remains required.
Ix's paid-Cyborg bonus still lacks authoritative quota and insufficient-Suboid rulings. Those questions were already asked; see [benefits](HOMEWORLD_BENEFITS_RULES.md) and [invasion audit](HOMEWORLD_INVASION_RULES.md). No new authority found here resolves them. Occupation lifecycle, low-Junction contributor rounding and unrevealed Grumman token removal are separate pending questions and were not repeated.
Only this source document was edited. Fresh publisher-indexed extracts and the physical high faces were inspected; direct E3 PDF opening remained unavailable. No runtime behavior, saved game, reference or implementation checkpoint is certified by this audit.
@@ -0,0 +1,157 @@
# Homeworld revival deployment runtime
Development checkpoint, 10 September 2026. High Southern Hemisphere and high
Tleilax have bounded runtime support. Full Homeworld, Advanced and unfinished
expansion starts remain gated. See the [source contract](HOMEWORLD_REVIVAL_DEPLOYMENT_RULES.md)
for printed evidence and unresolved interpretations; the [integration audit](HOMEWORLD_REVIVAL_DEPLOYMENT_INTEGRATION.md)
is the historical implementation hazard map.
Subsequent Caladan integration adds a shared Ambassador arrival validator and a
separate stage record for newly created revival returns. New original signatures
include a version field and require matching independent progress through
waiting, choice, arrival and completion. Removing that record or editing an
arrival back into a choice rejects even when older reserve forces remain
available. Removing the version field does not preserve the original signature.
Unversioned legacy records retain their previous signature format and explicit
compatibility; this does not retroactively prove their stage history. No stored
room migration is needed. The subsequent
[Caladan checkpoint](HOMEWORLD_VICTORY_REINFORCEMENT_RUNTIME.md) and implementation
status record the combined verification.
## Supported return and placement
Southern selects only the newly revived physical Fedaykin from a successful
ordinary revival, Emperor-funded extra revival or Ghola force return. Basic
preserves starred identity; Advanced retains its shared one-star-per-turn
revival limit. Tleilax selects only the actual ordinary Free Revival portion,
excluding paid counters returned beside it and separately sourced Ghola returns.
Leaders, substitutions and surviving forces returned to reserves create no
deployment permission.
The supported threshold case begins high: at least three native Fremen or nine
native Tleilaxu forces before the return. The original price remains the normal
revival quote. A return that first restores high population is blocked before
cost or force movement while its timing ruling is pending.
The owner may place the whole eligible group in one permitted destination or
leave it in reserves. Southern requires existing Fremen territorial presence;
Homeworlds are excluded. Tleilax permits a territory or Homeworld, including its
own world as a custody-preserving choice, but excludes an allied Homeworld.
There is no second revival, fee, income trigger or ordinary shipment/movement
allowance use. Old reserves cannot enlarge the eligible group. Partial
deployment and splitting among destinations are not enabled.
`homeworld-revival-deployment.ts` validates the source and completed typed
deposit. `homeworld-revival-destinations.ts` supplies current destination and
custody quotes. `homeworld-revival-return.ts` binds the original event, group,
population observations, source/card and retained response. The engine opens an
owned `homeworldRevivalDeployment` decision only after the original return and
required card disposal finish. A new revival cannot replace that outstanding
group.
## Reactions and retained continuations
Ordinary occupancy and sector restrictions remain active. Tleilax cannot enter
storm. Southern storm placement and Hidden Mobile Stronghold entry remain
explicit ruling boundaries; the mobile stronghold uses its actual pointer
sector for storm checks.
An otherwise relevant BG Intrusion or Terror reaction blocks that destination
pending deployment classification. Terror relevance uses the exact arriving
physical count, current low Grumman restriction and public token placement;
it does not read a secret token face. Tleilax arrival onto Arrakis also remains
blocked if BG has reserves and a currently permitted Spiritual Advisor. That
gate does not apply to Homeworld destinations or Southern's on-planet origin.
Concealed No-Field occupancy uses the public marker without its denomination.
Supported Ambassador entry passes through the existing arrival pipeline with a
bound revival event and recorded secondary-entry ancestry. The revival-income
response stays inside the frame until placement and its Ambassador children
finish. The original response then resumes once. Ghola's card disposal and any
CHOAM-market parent remain separate obligations; an unfinished placement cannot
be treated as a completed market interruption.
Independent review found two saved-arrival defects: edited offer identities
could bypass the later effect-specific checks, and deleting a live Ambassador
could prematurely restore income. Offer validation now checks the original
arrival, and each recorded child has a signed completion flag set by the actual
Ambassador settlement. Missing unfinished children reject during reads, actions
and automatic normalization. An actual phase-four Guild shipment, BG
accompaniment and secondary Fremen relocation completes across JSON restores
before the original Tleilax income resumes. The CHOAM-sale regression separately
proves Ghola disposal, placement, income and original sale restoration in order.
Direct cancellation of the Homeworld deployment is not offered. Independently
cancelable revival income and underlying ordinary powers keep their own source
rules. The existing special-Tleilaxu-Karama overlap remains a separate gate.
## Persistence and presentation
Waiting, choice, arrival and complete stages distinguish actual physical work
from an outstanding decision. Independent signatures bind the original return,
saved income response and arrival ancestry. View, action and automatic
normalization reject inconsistent present records. Completion is evidence,
never a command to revive, discard or pay again. No recovery reconstructs a
missing original grant from current reserves.
The projected offer exposes its public owner and eligible count; destinations
belong to the acting seat, and the private Ghola card identity is omitted.
`homeworld-revival-deployment-options.ts` and the dedicated component consume
that offer. All four bot profiles use the same destination and source-specific
threshold guards as the player controls. Group quantities cannot enlarge the
original permission or select previously held reserves.
Browser QA room `463GUCY3` completed normal revival of two counters, placed its
single newly revived Fedaykin in Arrakeen, then played Ghola for another Fedaykin
and left that group in reserves. Both owned choices survived refresh; actual
keyboard submission, three saved seats and private-hand boundaries passed.
Desktop 1440×1000 and phone 390×844 screenshots were inspected, with readable
controls, no horizontal overflow and no page errors. Evidence is retained in
`/tmp/dune-revival-desktop.png`, `/tmp/dune-revival-phone.png` and the isolated QA
scripts. This does not certify complete Homeworld games.
The controlled hourly restart at 14:39 UTC preserved all 3,050 saved room
versions and state hashes. The three QA seats reconnected to version 7 with
the same forces, Tanks, private hands and completed Ghola disposal. The backup
and exact baseline are in `/tmp/dune-maintenance-20260909T1439/`. The removed
recurring automation remains absent.
## Verified scope and remaining gates
Nine destination regressions and seven production SQLite cases pass through the
standard focused runner. Focused lint passes for those test files. Destination
coverage includes exact typed withdrawal, own/foreign Homeworld custody, allied
exclusion, storm and mobile-sector checks, relevant reactions, and throwing
private-field getters.
SQLite tests run the production room module, authentication and SQL. They cover
competing placement requests with one successful CAS, uncertain responses,
module reload and seat refresh, Ghola decline, one-time held income, corrupted
original/resume/completed-arrival records, unchanged unrelated rooms and private
hand boundaries. Two additional cases restore the actual live BG Ambassador
child, race the final Fremen relocation with one successful write, and verify
that held income settles once. Missing children, changed ancestry/completion
flags and premature parent completion reject without changing persisted state.
The shared engine suites cover ordinary and Emperor-extra returns, physical
Ghola disposal, the suspended CHOAM sale, Advanced limits, typed free subsets,
all-profile legal choices and public/private projection.
Final `npm run check` passes types, lint and all **3,634 offline cases** with no
failures or skips (88.4 seconds for the offline suite). Production build, all
**40 HTTP checks** and the browser acceptance above pass. Logs are
`/tmp/dune-revival-complete-check.log`, `/tmp/dune-revival-final-build.log` and
`/tmp/dune-revival-final-http.log`.
The full suite also exposed an intermittent older auction-test assumption:
buying a Karama creates a second eligible Emperor-income responder. The fixture
now deliberately buys that card, verifies the continued response, and counts
the retained current-lot reference separately from physical card custody. The
production auction behavior was unchanged. Earlier Tleilax income tests now
exercise a non-crossing return and explicitly stage their later high-population
position, while verifying that unsupported crossing requests make no writes.
Threshold restoration, arbitrary partial
groups, multiple Southern destinations, storm permission, reaction/Hidden
Mobile Stronghold classification, occupation lifecycle and the earlier Ix bonus
questions remain explicit boundaries. Passing these subsystem tests does not
certify complete games or release any expansion.
+122
View File
@@ -0,0 +1,122 @@
# Homeworlds: publisher rules and implementation contract
Source audit, 9 September 2026. No runtime activation. The primary module source is the [GF9 Ecaz & Moritani rulebook](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf), especially printed pp.4, 9–10 and the Homeworld FAQ on pp.15–16. The local publisher-text transcription is `/tmp/dune-rules/ecaz-audit.txt`; fresh official indexed pp.9, 10 and 15 were checked against it. Direct PDF retrieval currently returns HTTP 403. Physical card faces are separately audited in [Homeworld component audit](HOMEWORLD_COMPONENT_AUDIT.md); a rulebook statement and a card-face statement are not interchangeable evidence.
## Module scope and component inventory
There are **13 double-sided Homeworld cards and 13 corresponding planet discs for twelve factions**, not twelve of each. Emperor uses Kaitain and, in Advanced, Salusa Secundus. Only the seated factions' components enter the game. E3 permits the module independently of the selected factions and independently of Nexus cards, Discovery tokens and new Treachery cards. It does not require either Ecaz or Moritani to be seated, or all expansion factions to be present. [E3 pp.4, 9–10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=9)
Both Basic and Advanced are supported by the printed module. In particular, the FAQ explicitly permits the Fremen Homeworld in Basic, using its physical starred tokens without granting Advanced double battle strength. The module does not grant extra player seats: retain the underlying two-to-six-player game and its low-player-count rules. Twelve selectable factions does not mean twelve simultaneous players. [Base setup, p.6](https://www.gf9games.com/dunegame/wp-content/uploads/Dune-Rulebook.pdf#page=6), [designer expansion page](https://futurepastimes.com/dune-ecaz-moritani)
### Verified high faces
The photographed physical components in [BGG image 7767034](https://boardgamegeek.com/image/7767034) were inspected directly, independently of the rulebook prose (`/tmp/dune-rules/homeworld-bgg-high.jpg`). These are primary component artifacts hosted by a community site, not a publisher errata page. Full image provenance belongs to the component audit. The bonus column is both native battle addition and the printed native Lasgun/Shield casualty count.
| Faction / Homeworld | High population | Bonus | Verified high effect and real integration point |
| ---------------------------- | -------------------------- | ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Atreides / Caladan | 6–20 reserves | 2 | Optional one-force reserve reinforcement after winning a battle, to that battle's territory or Homeworld, provided an own force survives there. Post-battle transfer, not an extra ordinary shipment. |
| Bene Gesserit / Wallach IX | 11–20 reserves | 3 | May send two spiritual advisors instead of one when accompanying another faction's shipment **to Polar Sink**. This does not allow advisors on Homeworlds. |
| Emperor / Kaitain | 5–20 reserves | 2 | At Bidding end, may pay two spice per discarded hand Treachery card. Explicit optional paid discard window. |
| Emperor / Salusa Secundus | 2–5 **Sardaukar** reserves | 3 | Sardaukar need no spice support for full battle strength. Count the named type, not normal forces transferred to Salusa. |
| Fremen / Southern Hemisphere | 3–20 reserves | 2 | Revived starred forces may be placed directly in a territory already containing own forces. Preserve actual starred identity in Basic too. |
| Harkonnen / Giedi Prime | 7–20 reserves | 2 | Two bank spice when qualifying desert or Homeworld spice is collected that Collection phase. FAQ caps this at one two-spice award per phase. |
| Guild / Junction | 5–20 reserves | 2 | May offer other factions cross-shipping at half or full price during their shipping action, including to/from Homeworlds and to their own. Sponsor consent, payment and source pools must be explicit. |
| Ixians / Ix | 5–20 reserves | 2 | Paying to revive a Cyborg also grants two free Suboids. This is a typed revival modifier, not two manufactured counters. |
| Tleilaxu / Tleilax | 9–20 reserves | 2 | Free-revived forces may immediately ship free to one territory or Homeworld, subject to storm and occupancy. The revived group must remain identifiable through its owned destination choice. |
| CHOAM / Tupile | 11–20 reserves | 2 | Cannot discard Worthless for spice except through Advanced Karama. This is not a prohibition on every Worthless special effect. |
| Richese / Richese | 10–20 reserves | 2 | May ship physical reserve forces together with a No-Field. This is an explicit mixed-shipment modifier and needs concealed/physical custody handling. |
| Ecaz / Ecaz | 7–20 reserves | 2 | Three bank spice per discarded poison weapon; also an alliance victory combining at least one jointly occupied stronghold with occupation of two other factions' Homeworlds. |
| Moritani / Grumman | 8–20 reserves | 2 | During Collection, may add Terror to a stronghold already containing Terror or remove a board Terror token, then gain four bank spice. This is a Collection decision, not an unrestricted placement change. |
**Caladan numeric precedence:** E3 p.10 directs the native battle addition to the value on the Homeworld card, then gives a parenthetical Caladan example using three. The inspected card prints two for both relevant numbers. Use the card's two because the operative rule explicitly delegates that value to the component; annotate the inconsistent example. This is not an invented balance ruling or a reason to block every Homeworld pending clarification. No verified subsequent erratum overriding the face was retrieved.
### Verified low and occupied faces
The reverse galleries were also inspected directly (`/tmp/dune-rules/homeworld-reddit-face1.png` and `homeworld-reddit-face3.png`; from [Every Homeworld cards](https://www.reddit.com/r/DuneBoardGame/comments/16w27x0/every_homeworld_cards/), 30 September 2023; detailed provenance is retained in the component audit). These are photographs of the actual components, not rulings by the uploader. Except Salusa, every reverse prints the global +1 free revival and +1 bank charity. The bank column below counts the gold spice symbols in the Occupied panel: E3 p.10 identifies that panel's indicated income as bank-paid during Collection, even in Basic. It is additional to the panel's separately described conditional payments.
| Homeworld | Low population / native battle bonus | Low effect | Occupied effect / occupier bank income |
| ------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| Caladan | 0–5 / 2 | No movement-spent peek at the next Spice Blow. | Occupier shares Atreides' Bidding advantage. **2 bank.** |
| Wallach IX | 0–10 / 2 | No spiritual-advisor shipment. | Occupier and its ally are immune to Voice. **1 bank.** |
| Kaitain | 0–4 / 3 | Emperor receives only the rounded-up half of Treachery payments. | Occupier receives the rounded-down remainder, as clarified by the five-spice FAQ example. **2 bank.** |
| Salusa Secundus | Printed 0–2 / 2 | No free Sardaukar revival. Neither generic low bonus is printed/granted. | Sardaukar lose their Sardaukar advantage. **0 bank.** |
| Southern Hemisphere | 0–2 / 2 | No additional penalty. | Occupier receives the rounded-down half of all spice the native Fremen collect during Collection. **2 bank.** |
| Giedi Prime | 0–6 / 2 | No additional penalty. | When Harkonnen buys a Treachery card, occupier or its ally gains the extra free card if its receiving hand has room. **2 bank.** |
| Junction | 0–4 / 2 | Guild receives only the rounded-up half of shipping payments. | Occupier receives the rounded-down half of other players' shipping payments. **2 bank.** |
| Ix | 0–4 / 2 | Cannot move the Hidden Mobile Stronghold. | Occupier takes control of Ixian Bidding, rather than merely observing a copy of the private selection. **2 bank.** |
| Tleilax | 0–8 / 2 | Starting Revival low prevents income when another faction takes free revival. This condition is phase-start-specific. | No Face Dancer reveal against occupier or its ally. **2 bank.** |
| Tupile | 0–10 / 2 | Once per faction, CHOAM can force disclosure of spice and either weapon or defense count when it is on that faction's Homeworld or that faction is on Tupile. | Occupier and ally gain one hand slot; discard to normal limit when no longer occupying. CHOAM loses its low advantage. **2 bank.** |
| Richese | 0–9 / 2 | Cannot move a No-Field. | Occupier selects the Richese Treachery card sold during bidding and receives the rounded-down half of the payment Richese receives. **1 bank.** |
| Ecaz | 0–6 / 2 | With Ecaz and ally both in a battle, their opponent selects the participating allied faction. | Occupier or its ally gains Duke, including permission to revive him, overriding the two native Duke advantages. **2 bank.** |
| Grumman | 0–7 / 2 | Revealing Terror requires entry by at least three forces. | Terror cannot be revealed against occupier or its ally entering its location. **2 bank.** |
**Salusa endpoint discrepancy:** high prints 2–5 Sardaukar while low prints 0–2. E3's operative rule keeps a card high while its minimum is maintained and flips it only below that minimum. That supports high at two and low below two; annotate the conflicting reverse endpoint instead of inventing a player-chosen side or hysteresis. The population domain remains Sardaukar regardless of regular troops transferred there.
These faces require actual rule integrations, not a generic faction-disabled flag. Tleilax's phase-start condition, Tupile's once-per-faction private question and hand-limit cleanup, Grumman's reveal immunity, split income and displaced Bidding/bonus ownership have different lifecycles. Occupied Ecaz is an explicit additional Duke authority and revival permission; it does not by itself answer every existing loan-expiry, revival-custody or death-cycle question.
## Native custody and population
The planet disc holds that faction's native reserve forces. A Homeworld is a distinct off-planet location, not an Arrakis territory, additional stronghold, private hand zone or a new supply of pieces. Invaders retain their own faction and physical force types; native reserves and foreign garrisons must be distinguishable. Total faction inventory continues to include forces on Arrakis, on every Homeworld, and in the Tanks.
Start with the illustrated high-threshold face. Each card supplies its own population boundary. While native reserves meet that boundary, apply its high effect; falling below it switches to the low effect. Recompute after actual custody changes, not merely at phase boundaries. Restoring sufficient population restores the corresponding high condition. The rulebook names reserves as the population measure; an invader cannot inflate the native population or count as an extra native reserve. These are direct compositions of the continuously conditional threshold rule. [E3 p.9](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=9)
Low population adds one to the native faction's free-revival rate and adds one bank-paid spice when that faction collects CHOAM Charity. The extra charity is not charged to CHOAM. Salusa supplies neither bonus. Tupile reverses the usual desirable-high/undesirable-low card effects; do not implement that reversal by globally exchanging all high/low mechanics. Recruits doubles the **current** free-revival rate, subject to its printed limit: the FAQ's low-population Fremen example is four doubled but capped at seven. This does not settle unrelated existing Recruits/unlimited-revival questions. [E3 pp.9–10, 16](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=10)
Advanced Emperor starts with Sardaukar on Salusa and normal reserves on Kaitain. Revival returns these types to their respective native locations. During Shipment and Movement, Emperor can spend its movement transferring forces between the two. One outbound shipment can combine forces from both Homeworlds. The initial/revival placement restriction is not a permanent ban on the other type arriving through that expressly permitted transfer. Salusa's printed threshold nevertheless counts Sardaukar, so transferred normal defenders do not substitute for them. Basic uses only Kaitain and treats Sardaukar as ordinary battle forces. [E3 p.10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=10)
## Transport and arrival
| Route or effect | Source contract |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Native reserves to Arrakis | Existing faction shipment rules apply unless the actual Homeworld face modifies them. Keep free Fremen placement, Guild rates and ordinary restrictions distinct. |
| Homeworld to another Homeworld | Permitted; printed price is one spice per physical force, half price for Guild. Check owner/ally restrictions and the particular card's transport advantage. |
| Arrakis to a Homeworld | Guild cross-shipment only, except a permission actually conferred by the Guild Homeworld face. Do not infer permission from ordinary allied discounts. |
| Adding forces to one's own Homeworld | Revival is the general route; Guild/cross-shipping exceptions are explicit. No generic free board-to-reserve return follows merely from introducing the module. Specific existing card returns require their own composition. |
| Emperor inter-Homeworld transfer | Uses movement, not another ordinary shipment. Preserve typed quantities and the combined-shipment exception. |
| Allied Homeworld | Shipping there and occupying it are forbidden, including for the Ecaz pair. |
| BG | No spiritual advisors may be sent to Homeworlds. BG fighters on a foreign Homeworld cannot flip to advisors. |
Homeworld shipment triggers the Heighliner Tech Token, explicitly confirmed by the E3 FAQ. Price payment, ordinary shipment allowance and token ownership remain separate effects; an incoming shipment is not an Arrakis movement and has no sector, storm path, ornithopter access or sandworm route. No Ambassador or Terror placement follows: Homeworlds are not territories, and the FAQ expressly forbids Terror there. [E3 pp.10, 15–16](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=15)
The new route must preserve the actual source location. Do not let a foreign garrison become an indistinguishable part of the owner's native `reserves`, or silently ship pieces out of an occupied native location twice. No-Field transport, concealed population and reveal causes need explicit integration with their physical marker rules; the module text alone does not establish those combinations.
## Occupier lifecycle and benefits
The rulebook defines an **Occupier** by events: foreign forces present at the start or end of a turn qualify; a faction alone on the foreign Homeworld at any instant qualifies immediately for that turn. Thus a simple current sole-controller lookup is insufficient. Save which faction qualified, on which Homeworld and turn, separately from the present native/foreign armies. Native low penalties remain in force while occupied. [E3 pp.9–10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=9)
An Occupied face can grant an ability and/or bank income during Spice Collection, including in Basic. The occupier may immediately share that income with its ally; this is a specific immediate-sharing permission, not ordinary deferred bribery or Ecaz desert-allocation negotiation. The face determines the amount and any event-specific restrictions. Do not mint the income when occupation first occurs or again when refreshing a saved state.
Kaitain's FAQ supplies a concrete payment split: a five-spice Treachery payment yields three to Emperor and two to the occupier, even when that occupier bought the card. The payment is not charged again. Giedi Prime's high benefit is a total two-spice award per Collection phase if either listed reason occurs, not two per individual collection. These FAQ facts constrain the corresponding card implementations but are not substitutes for the full faces. [E3 p.15](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=15)
Do not form an alliance if either prospective partner occupies the other's Homeworld. Apply this to Nexus, Ecaz Ambassador consent and Moritani alliance formation, not only to ordinary alliance buttons. An alliance cannot legalize an already forbidden allied garrison. This restriction uses actual force occupation; do not substitute a private card condition or an unrelated remembered payment benefit. [E3 p.10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=10)
## Combat and victory
Homeworld invasion attacks the actual native reserve army, with normal battle sequencing unless a face says otherwise. Add the native Homeworld's current printed battle-strength bonus to its dialed result. Do not transfer that native bonus to an invader. The module gives no permission to merge Ecaz/ally armies there. It also does not define a two-faction stronghold capacity for these non-territory locations. Preserve the ordinary combat rules rather than silently applying every Arrakis stronghold predicate. [E3 p.10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=10)
Only the native faction may call Traitors or Face Dancers in a Homeworld battle. This restriction is on the caller, so an otherwise valid remote Harkonnen ally is not exempt merely because the beneficiary is defending its native Homeworld. For Lasgun/Shield explosion, native casualties are limited to the printed Homeworld battle strength, regardless of dial; surviving natives stay there. Both sides still lose and leaders die normally. The ordinary explosion removes the invading army. This named exception is not evidence for changing Stone Burner or other destruction effects. Physical type allocation, revived arrivals and threshold changes must be evaluated against the actual battle snapshot, without replaying outcomes on restore.
**There is no blanket Homeworld stronghold or victory point in the global rules.** Any occupied card face that explicitly counts as a stronghold must be represented as its own source-specific victory contribution. It must not become an Arrakis territory, a six-card Stronghold Card control site, a location for Ecaz joint-three occupation, or a location satisfying Moritani's battle-in-strongholds Duke condition by accidental shared IDs. Actual card wording must decide its limited contribution and any occupied-native victory restriction. Ordinary and special wins, alliances and BG prediction retain their existing priority unless a verified face expressly changes them.
Ecaz's verified high face supplies a separate actual win predicate: its alliance jointly occupies at least one stronghold and occupies Homeworlds belonging to two **other factions**. Two Emperor Homeworlds do not supply two different native factions. Implement this as a Homeworld-card condition while Ecaz's high advantage applies; do not add all foreign Homeworlds to ordinary stronghold progress. The sentence's alliance subject supports combining the two members' qualifying foreign occupations, while its explicit co-occupation requirement applies to the stronghold. Exact interaction with a transient turn-bound Occupier receipt must use the finalized occupation semantics rather than silently replacing actual occupation with an income entitlement.
## Karama and other optional systems
Karama cannot cancel Homeworld advantages **or** penalties. This includes a BG Worthless card converted into Karama. Do not generate response windows for threshold flips, Homeworld strength or occupied-face awards. However, this immunity is not a blanket ban on playing Karama during a Homeworld shipment/battle: an independently cancelable ordinary faction advantage still has its own source and timing. Distinguish printed Homeworld transport permission from a faction ability and from the generic paid card effect. [E3 p.10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=10)
Homeworlds do not enable the other optional modules. Leader Skills, Stronghold Cards, Discovery sites and Nexus cards retain their existing activation boundaries. E3 Harass & Withdraw specifically excludes one's own Homeworld; foreign Homeworld use follows the card's actual return rule. New off-planet locations must be audited at every effect currently phrased as territory, Arrakis, reserves, own Homeworld or any forces; these are different predicates.
## Evidence gaps and implementation sequence
The component audit retains provenance for the thirteen names, thresholds, battle bonuses and high/low/occupied face effects summarized above. All thirteen front and reverse faces have now been visually inspected; there is no remaining absent-face placeholder in this contract. The [designer's expansion page](https://futurepastimes.com/dune-ecaz-moritani) embeds [Homeworlds Revealed](https://www.youtube.com/watch?v=4KZKz13wf9c); its presence is verified, but no spoken ruling is attributed here without an inspected passage. Community-hosted component photographs establish their visible printed text, not any additional explanation by the uploader.
Global text leaves a material occupation-lifecycle edge: it awards status for a turn but does not fully specify simultaneous qualifying foreigners, expiry after leaving, or replacement if multiple factions qualify successively. Native repopulation may also restore a high threshold while a prior invader has a turn-qualified entitlement. The state model should retain population, actual presence and event evidence separately rather than pick an arbitrary exclusive controller or three-state enum; resolve an actual conflicting benefit case against the card face and any verified designer clarification. Tupile's explicit loss-of-occupation discard is a concrete expiry obligation even though not every other reward names the same endpoint. Other potential interactions—No-Field hidden population, card returns to an occupied native location, and threshold-sensitive mid-revival entitlements—require targeted source composition before those paths are enabled. Missing implementation is not itself an ambiguous rule; neither is a missing scan evidence for a house rule.
Recommended full-module implementation order:
1. Install verified immutable face data and an explicit module setting; create native Homeworld locations during real setup with conserved typed forces, including Basic Fremen and Advanced Emperor's second disc.
2. Introduce a shared location/custody model, dynamic population quote and event-bound occupation state. Make UI, bots, battle eligibility, reserve selection and persistence use those same public or owner-private descriptors.
3. Implement actual shipment, Emperor transfer and revival routes, including payment/income/Heighliner transitions and alliance restrictions. Every action must reject atomically and survive JSON/CAS continuation.
4. Extend actual combat and aftermath to off-planet locations, native strength, Traitor/Face Dancer restrictions and explosion casualties; preserve physical force and leader custody.
5. Integrate every verified face into its real phase/card/faction effect, bank/occupier income and source-specific victory contribution. Add occupation turnover, threshold-crossing and canceled ordinary-advantage tests.
6. Exercise all twelve faction profiles in complete games with this module, plus real multiplayer recovery and UI inspection. Until those contracts and material source cases are resolved, retaining the module gate is accurate; a pure population helper alone does not constitute Homeworld support.
+129
View File
@@ -0,0 +1,129 @@
# Homeworld setup and native reserve runtime
9 September 2026. This checkpoint connects the physical Homeworld model to
the authoritative game, player table and AI. **Public Homeworld starts remain
disabled.** It does not certify Homeworld battles, occupation, card effects or
complete Advanced/expansion games. The earlier component checkpoint remains
in [HOMEWORLD_IMPLEMENTATION.md](HOMEWORLD_IMPLEMENTATION.md).
## Implemented behavior
`Game.homeworlds` is optional for existing saves. An enabled fresh lobby stores
`{custody:null}` until the genuine setup pipeline places forces, after prediction
and traitor choices. Setup then records typed native reserves and Advanced
Emperor's separate Salusa allocation. The offline-only initializer does not
replace the public start gates or dispatch through the room API. It supports
the currently implemented base/Ix deck sets; CHOAM/Richese and Ecaz/Moritani
deck construction still rejects instead of substituting a different deck.
Native primary counts derive from the player's aggregate reserves; Salusa is
an allocation within those totals. Foreign garrisons remain separate physical
pools. Reads, actions and automatic normalization validate custody and all
twenty physical counters, including special-counter identities across board,
Tanks, native worlds and foreign worlds. Missing Salusa allocation is rejected,
not reconstructed. Ixians have seven Cyborgs total, initially four in reserves
and three in the mobile stronghold. The earlier custody limit of four is fixed.
Basic Homeworld setup retains Emperor's five Sardaukar and Fremen's three
starred counters. They count as strength one in ordinary Basic combat and do
not activate Advanced faction responses. Basic winner casualties preserve the
owner's physical normal/special selection. Basic revival and Ghola preserve
identity without imposing the Advanced one-special-counter-per-turn limit.
Ixian special-counter rules retain their separate behavior.
The Advanced Emperor's `emperorHomeworldMove` action transfers an explicit
normal/Sardaukar group between Kaitain and Salusa. The server checks current
owner, phase, movement budget, pending controls and a public-state event. It
spends one movement, charges no spice and conserves aggregate reserves.
Starting with movement passes an unused shipment. A real Hajr supplies the
second movement; active Ornithopter composition remains explicitly blocked.
Homeworld permission is independent of ordinary faction Karama cancellation.
Ordinary native-to-Arrakis shipments now withdraw exact typed Homeworld sources.
An omitted selection is inferred only when the allocation is unique; ambiguous
partial draws from both Imperial worlds require explicit choices. The same
transaction places the matching Arrakis counters once. The chronicle records
the Homeworld sources and cost. No-Fields retain their separate source contract.
Normal force revival, Emperor special-Karama force revival and Ghola deposit
Advanced Emperor's normal forces on Kaitain and Sardaukar on Salusa, even when
those counters previously moved between worlds. Other factions return to their
one native reserve pool. Completed Ghola discard receipts bind the full
Homeworld custody as well as aggregate counters.
The public table displays each native world's physical counts and population,
with the full local-art card inspector. Emperor controls select a movement's
origin and force types and the Salusa contribution to a combined shipment.
Kaitain's complementary contribution is displayed and submitted explicitly.
Invalid source counts disable submission; stale choices are revalidated by the
server. Shared public helpers give all four AI levels legal typed shipment
sources and a bounded transfer policy to restore Imperial population. They
do not read opponent hands, decks, predictions or spice.
The server's shipment-completion search uses the same source helper. Its
mixed-Imperial proof is tested as an internal future integration seam: actual
Advanced Truthtrance shipment questions still remain Basic-gated.
## Verification scope
- Genuine setup: sixteen six-seat setups span the eight supported factions,
Basic/Advanced and all four profiles; another eight mixed-Ix setups cover
two through five seats. Unsupported deck combinations reject unchanged.
Prediction/traitor privacy, physical card uniqueness and JSON recovery pass.
- Actual actions: transfer, Hajr, wrong-owner/stale/blocked rejections, mixed
native shipment and a Sardaukar's shipment → Storm death → revival on Salusa.
Ghola's saved completed-effect frame drains once; changing only its Salusa
allocation rejects despite unchanged aggregate counters.
- Basic counters: both Emperor and Fremen retain strength-one stars, legal
casualty choices, repeated typed revival and Ghola. Ordinary Basic behavior
without the module remains unchanged.
- AI: every offered movement/shipment candidate is individually accepted by
the real dispatcher across all four levels. Explicit sources, unavoidable
elite draws, hidden-information independence, Basic exclusions and no
oscillating population repair are verified.
- In-memory production SQL: duplicate and competing transfer requests commit
one version; fresh module instances and authentication restore the same
physical state/private hand. Corrupt missing Salusa state rejects without
writes. Unrelated rooms remain unchanged.
`npm run check` passes typecheck, lint and **3,152 offline tests**. The final
production build passes; `npm test -- homeworld reference` passes **106**
focused cases. Logs: `/tmp/dune-homeworld-runtime-check-final.log`,
`/tmp/dune-homeworld-runtime-build-final.log`,
`/tmp/dune-homeworld-runtime-focused-final.log`, and
`/tmp/dune-homeworld-actions-engine-final.log`.
The live browser used a new named QA room, `VQ6ALGRE`. Genuine setup preceded
a documented conserved dual-source phase position. UI actions shipped three
forces (one normal from Kaitain; one normal and one Sardaukar from Salusa),
then moved three normal forces from Kaitain to Salusa. The final position has
Kaitain 7 normal + 2 Sardaukar; Salusa 6 normal + 2 Sardaukar; Arrakeen three
forces including one Sardaukar; seventeen reserves and seven spice. Refresh
preserved it. Invalid source input disabled shipment, enlarged Kaitain opened
from the table, and 390×844 inspection found no horizontal overflow in the
world panels or inspector. Desktop card and phone movement screenshots were
visually reviewed; this is bounded sampling, not full module acceptance.
Forty live HTTP tests pass. Twenty ordinary **two-player Basic** games finish
3,079 accepted actions with no rejected candidates or stalls, using seed
20261026 and unchanged source fingerprints. This small regression sample is
not new strength calibration or Homeworld/full-player-count verification.
All 2,617 pre-existing room versions and hashes remain unchanged. The separate
QA room and thirty HTTP-test rooms were added. The development server remains
running from the 07:53 UTC controlled restart; no hourly restart was yet due
during this checkpoint. The removed automation stays removed.
## Remaining integration
Homeworld population values currently describe physical state; they do not yet
apply high/low advantages, charity/free-revival bonuses or occupation penalties.
Foreign Homeworld shipment permissions, Guild sponsorship, alliance rules,
occupation qualification/turnover, Homeworld combat and aftermath, explosions,
all card effects, occupation Collection, Ecaz victory and full AI policies
remain unfinished. Ordinary special arrival/return routes still need the
reserve integration audit, including Ambassador, Face Dance, No-Field and
card-specific destinations. Emperor transfer with Ornithopter is also pending.
Occupation history must remain distinct from population and current foreign
forces. Some turnover/expiry interpretations still need source resolution.
Do not infer a complete mode from a valid physical state or successful native
transfer. No release gate, saved-game migration or hosting access was changed.
+77
View File
@@ -0,0 +1,77 @@
# Homeworld runtime readiness
This is the pre-integration architecture audit. For the later implemented
boundary and remaining work, see
[HOMEWORLD_RUNTIME_IMPLEMENTATION.md](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)` and `quoteForceTransfer(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 blanket `factionDisabled` flag: 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, then `quoteHomeworldAftermath` determines 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
1. **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.
2. **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.
3. **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. `finishMovementTurn` currently grants Ecaz permanent cooccupation only over `gameTerritories`; do not extend that benefit to Homeworlds. Ally shipment funding permission is distinct from permission to land on an ally's Homeworld.
4. **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.
5. **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.
6. **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.
7. **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.
8. **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.
1. **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.
2. **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.
3. **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.
4. **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.
+35
View File
@@ -0,0 +1,35 @@
# Homeworld shipment runtime
9 September 2026. The [transport source update](HOMEWORLD_TRANSPORT_SOURCE_UPDATE.md) and [invasion audit](HOMEWORLD_INVASION_RULES.md) supply the source contract. Homeworld starts remain disabled pending complete transport, occupation, face effects and full-game acceptance.
## Connected behavior
World-to-world shipment now uses an actual engine action with explicit source pools and destination. Each ordinary faction pays one spice per physical counter, including Fremen; Guild pays half, rounding up. A shipment uses one source world, except Advanced Emperor may combine its native Kaitain and Salusa pools. Foreign garrisons stay separate from native reserves. Guild may return a foreign garrison to its own Homeworld through its explicit exception. Other ordinary own-world returns and allied destinations are rejected.
The action consumes ordinary shipment, preserves movement and checks Heighliners once, retaining the printed Guild exception. Homeworld arrivals have no planet sector, storm traversal, stronghold capacity, advisor accompaniment, Terror or Ambassador entry. Native and visiting armies feed the existing [Homeworld battle runtime](HOMEWORLD_BATTLE_RUNTIME.md), so actual invasion reaches battle discovery without staging foreign forces.
The shipper's invasion payment goes to the bank. November FAQ ally-contribution routing is separate: a non-Guild donor's share goes to Guild when present; Guild contributions go to the bank. Pledged and own funding are reserved during a pending declaration. Income is awarded only after payment and arrival, through the existing income response; it cannot fund the same shipment.
Advanced Guild special Karama can stop this interplanetary declaration, including a Fremen invasion. This is the documented source composition, not a new publisher worked example. No forces, payment or technology income move before resolution. The owned choice survives refresh and Box interruption. When Guild has no legal stop, allowance is automatic. The current stopped-shipment settlement retains the existing provisional no-payment interpretation; the previously recorded cancellation/refund questions remain unresolved.
Pending declarations bind the turn, actor, unused shipment, public custody, alliances, exact typed source receipts, price and pledge. Live and saved decision parents must match the event and destination. Rejected reads, actions and normalization preserve the input. Production room writes retain their existing compare-and-swap fence.
The prohibition on alliances with a faction occupying one's own Homeworld uses present foreign forces, independently of unresolved turn-benefit entitlements. Nexus, Ecaz Ambassador and Moritani alliance paths enforce it, and existing allied garrisons are rejected as invalid saved states. Controls and AI receive the same public restriction.
## Controls and AI
The table has typed native/foreign source selectors, combined Emperor selection, explicit costs, pledged contributions and a destination list. Guild gets actual allow/stop controls. All four AI profiles use the public quote, retain native defense, budget shipment and battle spice, select typed forces and consider reinforcement or native returns. They do not receive opponent hands or spice. These tactical policies do not certify relative AI strength or complete module games.
## Verification and limits
Forty new tests cover pure transport, actual engine actions, all-profile public policy, controls and production SQLite recovery. They include competing declarations, duplicate allowances, allowance versus special Karama, Box-suspended ownership, stale events, typed source corruption, conservation, all donor directions and actual invasion followed by battle discovery. Heighliner testing uses canonical staged token ownership after genuine faction setup because combined module setup remains gated.
Independent review found that a public automatic-continuation flag incorrectly disabled human controls while Guild could stop a shipment. A shared predicate now distinguishes that real choice from automatic allowance; three regressions cover it and detached recovery.
Final `npm run check` passes types, lint and **3,304 offline cases** (79.92 seconds for tests). Final production build passes. **40 HTTP cases** passed after engine/persistence integration and before the final UI label, heading and reference edits. `git diff --check` passes.
An isolated three-seat QA room used genuine Advanced Homeworld setup with a staged Shipment phase and a physically held Guild Karama. Actual desktop controls selected three normal forces from Kaitain plus two Sardaukar from Salusa for Caladan, quoting five spice. Before allowance, all forces and spice stayed at their original sources. An independent authenticated Guild seat on 390×844 phone had enabled Allow and Stop controls, survived refresh and allowed using the keyboard. The Emperor then had 12 normal counters on Kaitain, three Sardaukar on Salusa, the exact five-counter foreign army on Caladan and five spice remaining. Shipment was used, movement remained available, Guild retained its card and received no shipper income. Refresh preserved that result. No page errors or horizontal page overflow were observed. Visual inspection covered desktop source selection, phone Guild controls and the settled phone table; it exposed a generic battle heading on the shipment decision, now corrected. Explicit accessible select names were also added.
Read-only comparison after the browser and HTTP tests found all **2,740** pre-existing room versions/hashes unchanged; 2,771 rooms are stored including the new test rooms. The existing server was reused. This browser check verifies declaration/allowance and restoration, not a complete Homeworld game or every interception branch; those other focused branches have engine/SQLite evidence.
Remaining transport includes Arrakis-to-Homeworld routes, Junction offers and their payment composition, generic purchased Karama destination scope, unsponsored foreign departures to Arrakis, concealed No-Fields and ordinary Guild rate-cancellation timing. Occupation qualification/rewards, remaining Homeworld faces, victory and complete module games remain unfinished. This checkpoint does not open a start gate, publish the site or reinstall maintenance automation.
+49
View File
@@ -0,0 +1,49 @@
# Homeworld transport source update
9 September 2026. Targeted source review for invasion integration. This supplements [the invasion audit](HOMEWORLD_INVASION_RULES.md), preserves its occupation questions, and changes no runtime behavior or release gate.
Subsequent source adjudication: [Junction transport rules](JUNCTION_TRANSPORT_RULES.md) resolves the sponsored-route payment recipient using the bank default, the native off-planet reserve income trigger and the independent contributor rule. It separately documents Junction's Karama immunity. The earlier open Junction recipient item below is retained as this audit's historical evidence boundary.
## Newly checked authority
Fresh indexed publisher passages were retrieved from E3 printed p.10, the base rulebook p.14, and the November 2020 FAQ pp.2 and 7. The publisher base PDF returned HTTP 403 on direct access. An accessible [mirror of the publisher-authored 24-page base rulebook](https://www.qugs.org/rules/r283355.pdf) independently supplied the same special-Karama wording and the payment/shipment paragraphs on pp.9 and 19. Its content is the GF9 rulebook, not the mirror host's interpretation. Search results for fan compilations and tournament rules were excluded, including a compilation that narrows the Guild special power to arrivals on Arrakis.
The [publisher E2 rulebook, p.4](https://www.gf9games.com/dune/wp-content/uploads/2021/11/CHOAM-Rulebook-low-res.pdf#page=4) confirms that its two updated Karama cards replace the base copies. A readable original replacement card face was not retrieved during this review; a search result quoting a community revision is not a substitute for that component.
## Route contracts
The explicit own-world restriction takes precedence over the general world-to-world permission. Ordinary factions cannot ship back to their native world; Guild and Junction-sponsored cross-shipping are named exceptions. Emperor's inter-world movement remains separate. World-to-world shipment costs one spice per physical counter, halved for Guild, and Emperor may combine its two native origins. Arrakis-to-world shipment requires Guild or the named Junction exception. Allied destinations remain prohibited. [GF9 E3, p.10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=10)
The previously inspected Junction high face authorizes offers to other factions, at half or full price, during the recipient's Shipping action. Its scope includes travel to or from Homeworlds, including the shipper's own. Retain the actual offered tariff and permission source. Guild alliance status alone is not a Junction offer. [Physical component audit](HOMEWORLD_COMPONENT_AUDIT.md#verified-high-side-effects)
**Unresolved departure edge:** neither the freshly retrieved E3 transport paragraph nor ordinary reserve shipment expressly authorizes an unsponsored foreign garrison to ship to Arrakis. Junction supplies a supported path. Do not silently reclassify foreign forces as reserves to manufacture the other path. This remains a targeted source gap, not a reason to block explicit world-to-world invasion.
## Karama: distinguish three effects
**Special Guild interception.** The publisher's operative phrase is “stop one off-planet shipment of any one player.” It does not name Arrakis as the destination. [GF9 base, p.14](https://www.gf9games.com/dunegame/wp-content/uploads/Dune-Rulebook.pdf#page=14)
Recommended source composition: an actual interplanetary invasion is an eligible shipment, including a Fremen invasion. Fremen's ordinary Southern Hemisphere reinforcement is on Arrakis; the faction's identity does not turn every future shipment into that reinforcement. The module's generic invasion route is distinct from a Homeworld card advantage. This is a composition of the published predicates, not an explicit Homeworld example in the FAQ. Stamp route provenance in the pending intent instead of testing only `faction !== 'fremen'`. A Fremen garrison leaving Caladan provides a particularly clear regression against a faction-wide exemption.
**Ordinary cancellation.** The November FAQ distinguishes Guild payment, its personal discount, allied rates, and cross/return transport. Canceling one does not cancel the others. Fremen's protected reinforcement is its movement from reserves during shipping. [November FAQ, p.7](https://www.gf9games.com/dune/wp-content/uploads/2020/11/Dune-FAQ-Nov-2020.pdf#page=7)
E3 immunity covers Homeworld advantages and penalties. Junction's granted route/rate therefore needs a different cancellation source from Guild's ordinary discount. Printing the standard Guild half rate in the module's general tariff paragraph does not convert it into Junction's high-face advantage. [GF9 E3, p.10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=10)
**Generic purchased rate.** November confirms that Karama may benefit another player, at Guild rates, paid to the bank. It provides no Homeworld example. [November FAQ, p.7](https://www.gf9games.com/dune/wp-content/uploads/2020/11/Dune-FAQ-Nov-2020.pdf#page=7) The replacement physical card's exact destination scope is still an evidence gap. Do not grant a missing route through the rate card. Do not present either universal Homeworld eligibility or a publisher-confirmed prohibition as established by this review. Existing [ordinary rate-cancellation timing questions](GUILD_RATE_KARAMA_RULES.md#material-unresolved-timing) remain unchanged.
## Contributor routing and Junction
Ordinary shipment payments go to the bank. Guild's base personal income override names other factions shipping from their off-planet reserves onto Dune. That does not independently collect a shipper's world-to-world invasion fee. [GF9 base, pp.9 and 19](https://www.qugs.org/rules/r283355.pdf#page=9)
The November funding rule separately sends a non-Guild ally's contribution directly to Guild when present; Guild's contributions go to the bank. The FAQ sets no destination restriction on this funding paragraph. Preserve the existing [contributor-specific adjudication](GUILD_SHIPMENT_PAYMENTS.md#publisher-contract-and-precedence), including when Guild is the shipper. An independently purchased Karama rate sends the payment to the bank. [November FAQ, pp.2 and 7](https://www.gf9games.com/dune/wp-content/uploads/2020/11/Dune-FAQ-Nov-2020.pdf)
Consequently, `guildShipmentIncome` cannot receive an invasion's full fee unchanged: its shipper contribution currently assumes an eligible ordinary route. Example under this composition: a five-spice invasion funded by shipper three plus a non-Guild ally two routes three to the bank and two to Guild before applicable Junction effects. Preserve the two debits and their provenance; the incoming receipt cannot fund the same shipment.
Junction low retains the rounded-up half of eligible shipping payments. Its occupied face awards the rounded-down other half paid by other players to the occupier. These face effects modify an eligible payment; they do not manufacture another full fee or broaden every bank payment into Guild income. [Physical component audit](HOMEWORLD_COMPONENT_AUDIT.md#verified-low-side-effects) This review does not resolve existing occupation lifecycle questions or a new multiple-beneficiary rounding policy. Store an original payment identity and contributor ledger so a later consumer can apply the finalized split once. The exact payment recipient for a Junction-sponsored route whose shipper contribution misses the base income trigger should be resolved explicitly before that distinct sponsored route is exposed.
## Integration checks
Keep route legality, tariff provenance, funding, income entitlement, and interception separate in a detached quote. Revalidation must use the actual typed source pools and authorized escrow without replacing the original offer after a pause. Validate ownership and ally restrictions before card disposal, payment, force arrival, or technology income. No sector, stronghold-capacity, advisor accompaniment, or territorial arrival effect should be inferred merely from an off-board location ID.
Required focused cases for this contract: own-world rejection despite general invasion permission; explicit Guild/Junction exceptions; Emperor combined origins; odd Guild force count; paid Fremen invasion versus free reinforcement; a Fremen foreign-garrison interception; shipper/donor routing in both Guild directions; independent card-rate provenance; unchanged funds and forces on rejection; and exactly one final settlement after JSON recovery and duplicate requests.
Validation of this document: local links and referenced function were inspected; primary passages were freshly browsed. No executable tests, databases, saved games, server processes, or automation settings were changed.
@@ -0,0 +1,40 @@
# Tupile low-population intelligence source contract
Audited 10 September 2026. This checkpoint implements a public eligibility quote only. It does not activate an intelligence action, disclose private information, establish occupation lifecycle rules, or certify Homeworld play. Existing release gates remain.
## Primary evidence
The [Future Pastimes designer page](https://futurepastimes.com/dune-ecaz-moritani) links [Jack Reda’s component presentation](https://www.youtube.com/watch?v=4KZKz13wf9c). Fresh inspection of its public storyboard images showed the readable Tupile low face around 2:15 and occupied instructions around 4:20. This audit reads the printed component; no spoken clarification was obtained. The low face specifies 0–10 native CHOAM reserves and begins “Once per faction”. It permits CHOAM to obtain that faction’s spice balance and its weapon **or** defense count when CHOAM is on the faction’s Homeworld or that faction is on Tupile. The occupied instructions explicitly remove CHOAM’s low-threshold advantage.
The [official Ecaz & Moritani rulebook](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf), printed pp9–10, supplies continuous population thresholds and the Homeworld occupation framework. Page10 distinguishes the usual low-population penalties from CHOAM’s low-population advantage, establishes the Emperor’s two native Homeworlds in Advanced play, and exempts Homeworld advantages and penalties from Karama cancellation. The general retention of low **penalties** under occupation does not override Tupile’s explicit loss of its low **advantage**.
The [official November 2020 FAQ](https://www.gf9games.com/dune/wp-content/uploads/2020/11/Dune-FAQ-Nov-2020.pdf), printed p8, permits a Truthtrance question asking whether someone holds a weapon and a defense. It does not provide a held-card category-count algorithm. Its p3 Weirding Way/Chemistry answers describe their conditional roles in a committed battle plan. Those battle roles should not be mistaken for evidence that every card playable in a slot counts in that held-card category.
## Executable public eligibility
- The native CHOAM player has 0–10 native reserves at the request. Foreign visitors do not contribute to this threshold.
- Tupile’s advantage is available only with an authoritative **unoccupied** status. An unresolved occupation status blocks the request. The helper does not infer an occupation’s qualification or expiry from current visitors; those unresolved lifecycle questions are tracked in [HOMEWORLD_OCCUPATION_RULES.md](HOMEWORLD_OCCUPATION_RULES.md).
- Positive physical CHOAM forces on any Homeworld native to the target establish outbound contact. Positive physical target forces on Tupile establish inbound contact. Contact does not require sole presence, occupation, an alliance, or CHOAM forces beside an inbound visitor. Two visitors sharing a third faction’s Homeworld do not establish contact with each other.
- Either Kaitain or Salusa Secundus supplies contact with the Emperor in Advanced play. The entitlement belongs to the faction, so contact with both worlds still supplies only one use against the Emperor.
- The printed frequency has no turn, phase, visit, world or category reset. Its direct reading is one successful request per opposing faction for the game. Leaving, returning, changing the contact direction or choosing the other category cannot restore that use.
- The card describes current presence rather than an arrival-only trigger and prints no phase restriction. A future engine action must fit its existing legal action/continuation boundaries without silently limiting the ability to Shipment and Movement. This audit does not establish special priority over an already unresolved action.
Usage is consumed by a successful disclosure, not by opening controls, asking for a quote or rejecting a stale request. The pure helper accepts externally supplied game-long usage and never mutates it.
## Private answer and held-card classification
The answer consists of the target’s current spice and **one** selected count: weapons or defenses. The recipient named by the component is CHOAM. A server can calculate this truthful snapshot without requiring a redundant opponent confirmation. Future integration must atomically validate contact, population, occupation and unused entitlement, calculate the answer, record use and store one private CHOAM receipt. Other players must not receive the balance, category count, hand identities or a private receipt through logs, controls, exports or recovery views. A saved answer is a historical observation, not a live view of subsequent changes.
Eligibility is independent of the answer. An empty hand, zero spice, a hybrid card, a skill or an unfinished card effect must not change the public action’s availability and thereby reveal hidden information.
The appropriate classification composition is physical held cards by their printed primary category, with conditional battle roles applied only when resolving a battle. Each qualifying physical card counts once; an attack effective against two defense types is still one card. Worthless cards and leader-replacement cards are not weapons or defenses merely because battle slots accept them. Leader skills are not additional held Treachery cards. The E3 rulebook, printed p11, explicitly treats Reinforcements and Harass & Withdraw as neither weapons nor defenses despite allowing their use in those slots.
Canonical printed identity matters for Richese cards: Stone Burner and Mirror Weapon are printed weapons, Portable Snooper a defense, and Residual Poison a Special card. A transport value such as `kind: special` is insufficient to determine this count. Physical component evidence is recorded in [RICHESE_COMPONENTS.md](RICHESE_COMPONENTS.md).
For Weirding Way and Chemistry, the existing canonical presentation/default battle-role convention is respectively weapon and defense. The official FAQ supports distinguishing the default role from a conditional alternate battle role, but does not expressly answer Tupile held-card counting. This is a documented source composition, not a claimed Tupile-specific FAQ ruling. No category-count function is introduced by this checkpoint. Before a disclosure handler is activated, its canonical category table must be checked against the printed component inventory, including expansion cards; reusing the permissive `isWeaponCard`/`isDefenseCard` slot predicates would incorrectly include Worthless cards and alternate roles. The existing [Truthtrance card-count implementation](TRUTHTRANCE_CARD_COUNT.md) counts named physical identities rather than these categories and is not a substitute.
## Current code boundary and verification
[tupile-intelligence.ts](../game/tupile-intelligence.ts) exports `tupileIntelligenceTargets(context, custody, owner, usedFactions, occupation)` and `quoteTupileIntelligenceRequest(context, custody, owner, usedFactions, occupation, target, category)`. Occupation is explicitly `unoccupied`, `occupied` or `unknown`. The first returns public target/contact/blocking information; the second returns a validated request without an answer or a usage mutation. Neither accepts private hand or balance fields as part of its contract.
[tupile-intelligence.test.ts](../tests/tupile-intelligence.test.ts) covers both contact directions, irrelevant co-visitors, zero forces, both Emperor worlds sharing one lifetime use, threshold boundaries, occupation blocks, malformed inputs, immutable queries, saved usage and getter traps proving that private hands, balances, plans and other hidden fields are not read. Engine actions, signed receipts, player projection, bots, UI and production SQLite disclosure recovery remain future integration work.
@@ -0,0 +1,158 @@
# Caladan victory reinforcement: integration audit
Historical pre-integration audit. The subsequent
[runtime checkpoint](HOMEWORLD_VICTORY_REINFORCEMENT_RUNTIME.md) records the
implemented hook and evidence. Face Dancer overlap remains guarded pending a
ruling; the structural recommendation below does not establish its rules order.
10 September 2026. Read-only, bounded runtime audit. This identifies integration
points for the high-Caladan optional reserve force; it does not establish new
rules, certify the feature, or change existing saves. The source/quote owner must
settle the timing and destination boundaries called out below.
The current [Caladan component](../game/homeworld-cards.ts) requires a battle win
and an existing own force at that battle's territory or Homeworld. Its high
threshold is six native forces. The [Homeworld rule inventory](HOMEWORLD_RULES.md)
identifies this as a post-battle transfer, separate from ordinary shipment.
## Actual battle completion order
The following functions are in [engine.ts](../game/engine.ts). The ordering is
observable across saved discard batches, decisions, and responses; the initial
winner announcement is not the end of cleanup.
| Stage | Existing behavior | Reinforcement implication |
| --- | --- | --- |
| `chooseBattle` | Creates a fresh `Battle.event`; validates the selected unresolved board/Homeworld battle. Voice, prescience, Stronghold powers, and later revealed-plan responses belong to this battle. | Bind a new entitlement to this event, not territory plus turn. Multiple battles can occur in the same territory and turn. |
| `resolveBattle` | Uses the committed resolution quote; pays support/bounties, kills losers, and applies immediate Basic winner losses where the quote supplies them. Traitor wins preserve their winner; mutual traitors/explosions do not declare a winner. | A winner can have no surviving force. Never add a force before final winner casualties to make an otherwise eliminated winner survive. A native explosion survivor is not a battle winner. |
| Resolved context | Sets `lastBattleContext` with event, turn, territory, combatants, winner and result. Stages winner mandatory-discard commitments separately. Saves Homeworld casualty commitments, clears `g.battle`, and stages the losing/mandatory discard batch. | This is a place to record new-event provenance, but not yet to expose an actionable reinforcement. Keep a pending marker even when cleanup suspends. |
| `continueResolvedBattle` | Runs after the first discard continuation. Applies the sole casualty option, exposes `battleLosses`, or routes a native explosion through `homeworldExplosion`. | The reserve force cannot enter the committed casualty pool or change the number/type of losses. |
| `settleWinnerCasualties` | Applies real normal/starred casualties; clears the Homeworld loss record. A surviving Ixian Suboid and a lost Cyborg can produce `ixSubstitution`. | Do not bypass the casualty or substitution continuation. Atreides cannot itself be the Ixian substitution winner, but a generic cleanup hook must retain this ordering. |
| `finishWinner` | Retires mandatory winner cards through `winnerMandatoryDiscard`, then exposes optional `battleCards`, or calls `finishBattle`. | The new choice must not replace a mandatory discard or reuse its optional-card list. Winning Cheap Heroes/Poison Tooth can have a separate physical retirement batch. |
| Optional winning discards | The current `battleCards` decision handler stages `battleCleanup`; `finishTreacheryDiscard` resumes `finishBattle` only after retirement. | A zero-card choice and a nonempty discard batch must reach the same reinforcement stage once. |
| `finishBattle` aftermath | Uses [battle-aftermath-quote.ts](../game/battle-aftermath-quote.ts): Moritani retention, CHOAM battle income, technology transfer, Harkonnen capture, CHOAM Auditor, Face Dance, then board continuation. | `finishBattle` is called repeatedly. An unchecked hook here would grant several forces for one battle. |
| Board continuation | Once the quote returns `board`, computes remaining battles and activates the next attacker; otherwise calls `nextPhase`. | This is the narrow final interception point before another battle or Collection. Do not advance the phase while an owned choice/arrival remains. |
`g.battle = null` retires the old Voice, prescience, revealed plans and battle
power checks. Their completed context is historical evidence; reinforcement
must not recreate `g.battle`, restart `beginBattlePowers`, call
`finishBattlePreparation`, or revive a spent Voice response. Captured leaders are
returned/marked during resolution and the capture aftermath; reinforcement does
not reopen their battle eligibility.
## Recommended hook and the timing boundary
The smallest structural hook is immediately before the final `board` branch of
`finishBattle`, after `currentBattleAftermathQuote` and its existing deterministic
steps have committed. It opens an optional owned decision or records a terminal
skip, then eventually resumes that same board suffix. This preserves every
existing casualty, discard, capture and resource response.
**This placement is a recommendation about code structure, not a source ruling
that Caladan follows Face Dance.** Face Dance removes the original winner's
entire remaining army and returns it to native reserves; the Tleilaxu replacement
can even be zero. If reinforcement occurs after it, the original winner has no
survivor and cannot reinforce. If sources require reinforcement before it, add a
distinct aftermath stage immediately before Face Dance, and let its completion
resume Face Dance. Do not choose between these outcomes accidentally by placing
a generic end-action observer. The winner in `lastBattleContext` does not change
when a Face Dancer replaces it.
The same source decision must identify when to evaluate native high population:
at the original win, after casualty cleanup, or when the choice is used. Native
Caladan casualties can change that side. Record the rule-defined eligibility
facts; recheck current physical availability and destinations before mutation.
Do not infer a new entitlement simply because a subsequent return raises Caladan.
## Minimal durable contract
Use a feature-specific optional Game record; keep it outside the exact-shape
`homeworlds.custody` object. A practical record contains:
- Original battle event, turn, player, target combat-location ID, result and
rule-defined qualifying facts. Bind these immutable fields in a canonical
signature.
- A stage such as `waiting`, `choice`, `arrival`, `complete`; a fixed grant of one
ordinary force; and a signed completion/decline outcome. A completed marker
must survive every repeated `finishBattle` call for that event.
- An owned decision carrying the same event. Accept only the current event and
a currently offered sector/destination, or explicit decline. Do not accept a
posted winner, battle result, source balance, or additional amount.
- If a transfer can cause an arrival reaction, a saved parent describing the
exact board/aftermath suffix, plus original arrival provenance and completion
evidence. Retire the reinforcement transfer before executing a child.
Validate the record and owned decision together in the common integrity path
used by `viewGame`, `applyAction`, and `normalizeAutomaticGame`. A signed record
does not by itself detect deletion: a new battle's independently committed
context needs an obligation/completion marker if deleting the pending record
must be rejected. The existing `lastBattleContext.winnerDiscards` versus
`pendingWinnerDiscards` pair illustrates why this matters.
Reject malformed original fields, contradictory stages, missing required owned
choices, stale battle events, and replayed completion before any custody, log,
resource, phase or response mutation. A skip because there is no surviving force
must also become terminal for the event; repeated normalization cannot wait for
some later action to manufacture a survivor.
## Physical destinations and reactions
Use [combat-location.ts](../game/combat-location.ts) and
[homeworld-custody.ts](../game/homeworld-custody.ts), rather than an Arrakis-only
`at()`/`p.forces` test. Homeworld defenders/visitors have physical forces outside
ordinary board keys. For Atreides' source, withdraw one ordinary counter from the
actual native pool through [homeworld-native-reserves.ts](../game/homeworld-native-reserves.ts).
An aggregate reserve count or foreign visitor does not prove native availability.
For an Arrakis target, require the original battle territory and a legal offered
sector, then withdraw and place the one counter atomically. For a foreign
Homeworld target, withdraw native custody and deposit explicit visitor custody.
Retain allied-Homeworld and applicable occupancy restrictions; do not silently
route to a different territory. The native-Caladan target needs an explicit
source/quote decision: native reserves are already the native battle army, so
withdrawing and depositing into the same pool cannot create an additional
physical counter. Do not increase native population as though a force came from
outside custody.
Do not reuse `ship` or `guildShip`: those actions consume phase-five usage and
can assess Guild income/technology and response windows. This grant must not
change `shipped`, `moved`, spice, revival allowances, Tanks, or the already paid
battle support merely to add a reserve force.
`openTerritoryEntry` composes Ecaz Ambassador and Moritani Terror and expects a
supported cause plus a clear decision/response parent. It is not a generic safe
callback: it can open multiple saved children or reject competing entry effects.
The new reinforcement's shipment/movement classification, storm permission,
Spiritual Advisors, Intrusion, and Terror need the source owner's explicit
contract. Gate any unresolved affected destination before transfer. The recently
added [revival return](../game/homeworld-revival-return.ts) shows a durable
Ambassador chain but is a different entitlement and must not be reused by
pretending victory reinforcement was revival.
## Persistence and verification seams
[rooms.ts](../db/rooms.ts) persists automatic normalization with a version CAS.
Its `needsAutomaticRoomRecovery` predicate must recognize any new `waiting` or
`arrival` stage that needs to advance without a user action. A deliberate human
`choice` should remain pending; bots use its projected legal options. Never mutate
on read or write an unfenced completion from a projection helper.
Older saves can contain an already completed `lastBattleContext` or a legacy
cleanup context constructed by `cleanupBattleContext`. Neither proves that a
new Caladan offer is owed or was previously consumed. Missing new-feature
provenance must remain legacy-compatible without granting a retrospective force.
Newly resolved battles can opt into the signed record at their real commit.
No database migration needs to rewrite old room JSON or fabricate battle history.
Focused regressions should use genuine battle resolution: ordinary and traitor
wins; zero survivors; mutual traitors/native explosions; losing and winner
discard retirement; before/after final casualty population; same-location second
battle; Homeworld visitor custody; chosen-versus-declined single grant; stale
events/corrupt or deleted queues; Face Dance ordering; and any supported arrival
child. Production in-memory SQLite should race two identical decisions and two
automatic workers across reload, asserting one transfer and one suffix, exact
twenty-counter custody, unchanged battle losses/usage, private observer views,
and zero writes for rejected corruption.
Only this document was created. No production engine, persistence code, stored
room, test fixture, or release gate was changed by this audit.
@@ -0,0 +1,55 @@
# Caladan victory reinforcement contract
Source review, 10 September 2026. The original high Caladan face grants an
optional transfer of one reserve force to the location of a victorious battle,
provided Atreides still has a force there. The printed high range is six through
twenty native forces. Territory and Homeworld destinations are both named.
The [component audit](HOMEWORLD_COMPONENT_AUDIT.md) records the original physical
face; its text was visually checked again using the retained component image.
The linked [designer presentation](https://www.youtube.com/watch?v=4KZKz13wf9c)
corroborates the visible component. No unheard narration supplies a ruling.
[E3 pp.9–10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=9)
make native population thresholds continuous and Homeworld effects immune to
Karama. The implementation checks the current threshold after winner casualties
and again when the optional transfer is selected. A legal transfer from six
reserves to five is not retroactively invalidated. Foreign visitors do not raise
native population. Basic and Advanced use the same optional physical transfer;
it does not revive a counter, charge spice or spend ordinary shipment/movement.
The original winner is the beneficiary, including a traitor victory. Loss,
mutual-traitor destruction and explosion do not create a winning Atreides
beneficiary. No surviving Atreides force means no destination. Fighting on
native Caladan cannot create an additional counter: those reserve forces are
already present in the native battle pool. That source/destination coincidence
has zero net transfer, consistent with the physical-custody treatment in the
[replacement contract](HOMEWORLD_REPLACEMENT_RULES.md).
The transfer must stay at the original battle location. A foreign Homeworld
receives one actual ordinary counter withdrawn from Caladan. Arrakis uses an
explicit sector choice within the battle territory. Occupancy constraints and
the allied-Homeworld prohibition remain in force. Arrival at an Ambassador
stronghold uses the existing entry predicate and a source-bound continuation;
it does not create a second battle victory.
## Unresolved ordering and entry combinations
The E1 Face Dancer sequence preserves the original winner and its ordinary
battle consequences before replacing surviving forces. No retrieved official
example orders that replacement against the later Caladan Homeworld card.
The coordinator asked the user whether reinforcement precedes or follows Face
Dance; the answer remains pending. The engine displays that boundary when the
two opportunities overlap. It supports an explicit decline without choosing
the disputed placement order; this does not certify the combined interaction.
Storm-sector placement, Hidden Mobile Stronghold classification, and otherwise
relevant Intrusion/Terror reactions remain explicit source boundaries.
Destination guards use public physical presence and token placement, never a
secret Terror identity. Low Grumman's entering-force minimum still determines
whether its Terror reaction would be relevant to the one arriving counter.
The [integration audit](HOMEWORLD_VICTORY_REINFORCEMENT_INTEGRATION.md) maps
battle cleanup and persistence. The
[runtime checkpoint](HOMEWORLD_VICTORY_REINFORCEMENT_RUNTIME.md) records the
implemented flow and verification. No complete Homeworld, Advanced or expansion
release is claimed.
@@ -0,0 +1,83 @@
# Caladan victory reinforcement runtime
Development checkpoint, 10 September 2026. This implements the bounded behavior
in the [source contract](HOMEWORLD_VICTORY_REINFORCEMENT_RULES.md), not complete
Homeworld or expansion support. Advanced and unfinished module starts remain
disabled.
## Actual battle and player flow
An actual normal or traitor victory by Atreides records its original battle
event. After casualty and card cleanup, high Caladan may transfer exactly one
ordinary native reserve force to the victorious army's location while an
Atreides force survives there. Current native population must be at least six;
transferring from six to five is legal. Foreign visitors do not raise that
threshold. Loss, mutual destruction and explosion create no entitlement.
The player selects an eligible sector of the original territory or the original
foreign Homeworld, or leaves the force in reserves. Native Caladan is already
the source pool, so it cannot create another counter there. The transfer spends
no spice, revival allowance or shipment/movement use. All four AI profiles use
the same projected legal choices. Controls show ownership, the fixed amount
and unavailable-destination reasons.
The unresolved Face Dancer ordering overlap permits decline only. Storm,
mobile-stronghold and relevant Intrusion/Terror combinations retain explicit
destination guards. These are incomplete interactions, not optional house rules.
An admitted Ambassador arrival can interrupt reinforcement and return through
its saved child sequence before the next battle or phase begins.
## Saved state and custody
[homeworld-victory-return.ts](../game/homeworld-victory-return.ts) binds the
original event, turn, winner, location and result to the offer. A separate battle
obligation records the actual waiting, choice, arrival or completed stage. This
prevents editing an arrival back into a choice while another reserve force is
still available. Deleted choices, mismatched markers and changed original facts
reject before resource or persistence changes.
An unfinished waiting stage also requires its preceding cleanup control or
interrupt; deleting an optional winning-card decision cannot leave a silent
waiting record. Production actions settle automatic reinforcement work before
their database write, while legitimate human choices remain pending.
[homeworld-arrival.ts](../game/homeworld-arrival.ts) shares Ambassador ancestry
and child completion validation with revival deployment. Each child remains
bound to its source event, entrant, location and parent. A removed unfinished
child cannot release the battle suffix. The original victory remains distinct
from any later Ambassador movement or shipment.
Older completed Caladan development saves without the separate stage field
remain readable. A stage-less unfinished obligation is rejected. Older battles
without this feature's records do not receive retrospective reinforcements.
These canonical records validate consistency; they are not cryptographic
authentication of arbitrary edited database contents.
## Verification evidence
Focused cases cover pure thresholds and physical transfers, owned controls,
actual normal/traitor outcomes, mandatory and optional cleanup, all four AI
profiles, and actual nested Ambassador arrivals. Production in-memory SQLite
cases exercise authenticated competing actions, lost-response reloads, private
seat projections, unrelated rooms and corrupt continuations with zero writes.
The stage-rewind regression starts with seven reserves and leaves six after the
first placement, proving rejection does not depend on running out of forces.
The isolated browser game completed a real battle, restored the pending choice,
selected Hagga Basin by keyboard and added one reserve force. Desktop and
390-pixel phone views were inspected without overflow. After another refresh,
the army had three forces, Caladan had five and the Tanks had one. All three
private seats restored with no page errors. Its completed legacy record also
restored after the subsequent server restart.
Whole-project verification results belong in the dated
[implementation status](IMPLEMENTATION_STATUS.md) checkpoint. Passing this slice
does not certify complete Homeworld games, occupation, all arrival reactions,
Face Dancer ordering or the full requested expansions.
## Related public-only work
[tupile-intelligence.ts](../game/tupile-intelligence.ts) now quotes public contact,
low population, occupation suppression and lifetime once-per-faction eligibility.
It reads no opposing hand. It does not yet disclose spice or card counts, consume
a use, or provide a playable engine action. See the
[Tupile source contract](HOMEWORLD_TUPILE_INTELLIGENCE_RULES.md) for that boundary.
+34
View File
@@ -1,5 +1,39 @@
# Dune implementation status
**Caladan victory reinforcement checkpoint, 10 September 2026:** [HOMEWORLD_VICTORY_REINFORCEMENT_RUNTIME.md](HOMEWORLD_VICTORY_REINFORCEMENT_RUNTIME.md) records the actual high-Caladan post-victory one-force transfer, current population and survivors, original battle location, exact native/visitor custody, owned controls and all-profile AI. Shared Ambassador arrivals preserve the original reinforcement and its nested children. Independent review reproduced and fixed arrival-to-choice rewinds and a deleted preceding cleanup choice; new revival returns also carry version-bound independent progress, while legacy completed QA saves remain readable. Final types, lint, **3,682 offline cases** (89.9 seconds), production build and **40 HTTP cases** pass. Eight Caladan production SQLite cases cover competing writes, reloads, private projections, nested arrivals and corruption. Two older Face Dance fixtures now explicitly decline the preceding guarded Caladan option, without choosing the unresolved placement order. Desktop and phone keyboard placement and three-seat refresh passed; final restart restoration passed for both Caladan and revival QA games. All **3,051** pre-existing room versions/hashes remain unchanged after restart and additive HTTP work. Low-Tupile public contact/once-per-faction quoting has seven cases but no playable disclosure action. Face Dancer ordering, guarded entry combinations, occupation, other missing effects and complete expansion games remain unfinished; no release gate opened. User workflow optimizations remain in use and automation stays removed.
**Homeworld revival deployment checkpoint, 10 September 2026:** [HOMEWORLD_REVIVAL_DEPLOYMENT_RUNTIME.md](HOMEWORLD_REVIVAL_DEPLOYMENT_RUNTIME.md) records newly revived Fedaykin placement and Tleilax ordinary Free Revival deployment, exact typed groups, normal/Emperor-extra/Ghola source distinctions, owned controls and all-profile AI. Signed return, income and Ambassador completion records preserve nested arrivals and CHOAM sale restoration. Independent review found and fixed altered-offer acceptance and deleted-child premature completion. Final types, lint, **3,634 offline cases**, production build and **40 HTTP cases** pass; seven new production SQLite cases cover competing writes, lost responses, nested Ambassador restoration and corruption. The final suite also made an older auction test deterministic when the purchased Karama creates a second income responder. Desktop and phone keyboard placement, Ghola decline, refresh and three private seats passed without overflow or page errors. The hourly restart preserved all **3,050** saved room versions/hashes and restored the QA seats. First-reaching-high timing, partial/split groups, storm/arrival classification, occupation and complete expansion games remain unfinished; no release gate opened. User workflow optimizations remain in use and the automation stays removed.
**Homeworld collection and Terror checkpoint, 9 September 2026:** [HOMEWORLD_COLLECTION_RUNTIME.md](HOMEWORLD_COLLECTION_RUNTIME.md) records automatic high-Giedi income on actual positive desert receipts, once-per-phase recovery across Ecaz allocations, and low-Grumman original entering-force restrictions. Concealed No-Fields count as one; Ambassador choices and all four bot levels honor count-dependent arrival limits. Independent review found and verified a repair for altered saved arrival counts: original facts are now bound through live Terror, alliance cancellation and forced-discard continuations. Final types, lint, **3,575 offline cases**, production build and **40 HTTP cases** pass. Thirty-four new cases include seven production SQLite recovery scenarios; the older stale-entry regression now covers both signed and legacy saves. Desktop/390-pixel phone keyboard collection and three-seat refresh preserve seven collected spice plus the automatic two-spice bonus, with readable history and no overflow or browser errors. All **2,958** pre-existing room versions/hashes remain unchanged after the controlled restart and additive QA/HTTP work. Missing whole new receipts/signatures retain explicit legacy compatibility. High Grumman removal custody, occupation and low-Junction rounding questions remain pending; high Grumman operations, other faction effects and complete expansion games remain unfinished. No release gate opened, workflow optimizations remain in use, and automation stays removed.
**Homeworld payment income checkpoint, 9 September 2026:** [HOMEWORLD_PAYMENT_INCOME_RUNTIME.md](HOMEWORLD_PAYMENT_INCOME_RUNTIME.md) records low Kaitain and Junction reductions, original payer costs, separate ordinary-income cancellation, public split previews and private Guild contributor receipts. Final types, lint, **3,541 offline cases** and production build pass; **40 HTTP cases** passed before the final UI/AI funding guard. Twenty-six new cases cover actual auctions, shipment funding, native departure thresholds, Richese special/Ambassador purchases, all four profiles and five production SQLite recovery scenarios. Independent review found and verified repairs for mismatched Ambassador previews and invalid AI funding candidates. Desktop/390×844 phone keyboard allowance and three-seat refresh preserve the 5-spice purchase, 3-spice Emperor receipt and 2-spice bank remainder; screenshots were inspected without page overflow. All **2,894** baseline room versions/hashes remain unchanged. [Occupation](HOMEWORLD_OCCUPATION_RULES.md) and [contributor rounding](HOMEWORLD_PAYMENT_INCOME_RULES.md) questions are pending; divergent low-Junction odd/odd splits reject before declaration/payment rather than adopting an unverified rule. Legacy receipts without all new metadata retain the documented evidence limitation. Occupation, remaining card effects and full expansion games remain unfinished; no release gate opened and automation stays removed.
**Kaitain and Ecaz card economy checkpoint, 9 September 2026:** [HOMEWORLD_CARD_ECONOMY_RUNTIME.md](HOMEWORLD_CARD_ECONOMY_RUNTIME.md) records shared end-of-Bidding paid Kaitain discards and CHOAM sales/trades, current-population Ecaz poison income, private receipts and all-profile controls. Winning mandatory cards now discard after winner casualties and Ixian substitution, with reserved physical custody and independent saved battle obligations. Final types, lint, **3,515 offline cases**, production build and **40 HTTP cases** pass. Forty-seven new cases and updated battle/SQL regressions cover timing, privacy, corruption and races. Independent review found and verified fixes for conditional battle-role corruption, played-card diversion and deleted winner-discard queues. Desktop keyboard and 390×844 phone play completed disposal, private income, trade, sale, closing readiness and all-seat refresh; screenshots were inspected without page overflow. All **2,894** pre-existing room versions/hashes remain unchanged. Occupation, remaining Homeworld effects, complete expansion setup and full module games remain unfinished; no release gate opened. Workflow optimizations remain in use and automation stays removed.
**Tupile card economy checkpoint, 9 September 2026:** [HOMEWORLD_CARD_ECONOMY_RUNTIME.md](HOMEWORLD_CARD_ECONOMY_RUNTIME.md) records high-Tupile restrictions on both Worthless sale prices and CHOAM Ambassador payouts, private legal choices, and Ghola interruption with durable sale restoration and nested Tleilaxu income. Types, lint, **3,468 offline cases**, production build and **40 HTTP cases** pass. Thirty-one new regressions include all four AI profiles, five production SQLite scenarios and the repaired receipt-binding issue found by independent review. All **2,864** pre-existing room versions/hashes remain unchanged. Kaitain has source and pure-quote coverage only; its shared phase-end window, Ecaz poison-discard income, occupation and complete expansion games remain unfinished. No release gate opened. The optimized workflow remains in use; automation stays removed.
**Homeworld mobility and advisor checkpoint, 9 September 2026:** [HOMEWORLD_MOBILITY_RUNTIME.md](HOMEWORLD_MOBILITY_RUNTIME.md) records low-Caladan phase-opening foresight restrictions, low-Wallach free-advisor suppression and high-Wallach two-force Polar Sink batches, low-Ix mobile-stronghold restrictions, and low-Richese token movement restrictions. Paid arrivals, physical troop movement and legitimate previously learned knowledge remain available under their separate rules. Final types, lint, **3,437 offline cases** and production build pass; **40 HTTP cases** passed before the final declared-advisor-count display text. Fifty-three new cases cover pure thresholds, actual actions, all-profile choices, Guild Ambassador continuations, and ten production SQLite recovery scenarios including paid Box interruption. Desktop choices, phone keyboard declaration, another human seat's allowance, saved reaction and settled refresh passed; phone screenshots were visually inspected without overflow. All **2,833** pre-existing room versions/hashes remain unchanged. Occupation-retained penalties, remaining high/occupied effects, full expansion setup and complete Homeworld games remain unfinished; no start or publication gate opened. Workflow optimizations remain in use and automation stays removed.
**Junction sponsored transport checkpoint, 9 September 2026:** [JUNCTION_TRANSPORT_RUNTIME.md](JUNCTION_TRANSPORT_RUNTIME.md) records optional Guild half/full offers, replacement and expiry, exact Arrakis/Homeworld source groups, native returns, foreign departures, payment provenance, Karama immunity, arrival continuations and all-profile controls/AI. Final types, lint, **3,384 offline cases** and production build pass; **40 HTTP cases** passed before the final sponsor-panel identity and AI-priority guard adjustments. Forty-four new regressions include production SQLite concurrency/recovery and independent review. Actual desktop keyboard offers/replacements and phone typed shipment/refresh passed; visual inspection found readable layouts without phone overflow. Browser testing prompted preserving the sponsor panel across offer replacement. A controlled restart restored the private QA seat and preserved all **2,802** saved rooms; all **2,802** pre-existing room versions/hashes also remain unchanged after isolated QA/API tests. Occupation, remaining faces, concealed transport, unresolved generic/ordinary Karama interactions and complete module games remain unfinished; no start or publication gate opened. Workflow optimizations remain in use and automation stays removed.
**Guild Arrakis-to-Homeworld transport checkpoint, 9 September 2026:** [GUILD_HOMEWORLD_TRANSPORT_RUNTIME.md](GUILD_HOMEWORLD_TRANSPORT_RUNTIME.md) records actual Guild invasions and Junction returns from exact Arrakis sector pools, protected mobile-stronghold departures, shared interception, legacy API parity, accessible controls and all-profile AI. Final types, lint, **3,340 offline cases**, production build and **40 HTTP cases** pass. Thirty-six new regressions cover legality, physical custody, competing requests, interrupted recovery and private projection; independent review found no further defects. Desktop validation and keyboard declaration, phone interception, refresh and visual inspection passed in an isolated QA room. All **2,771** pre-existing room versions/hashes remain unchanged, with none missing. Junction-sponsored routes, occupation, remaining faces, unresolved Karama interpretations and complete module games remain unfinished; no start or publication gate opened. User workflow optimizations remain in use and automation stays removed.
**Homeworld invasion shipment checkpoint, 9 September 2026:** [HOMEWORLD_SHIPMENT_RUNTIME.md](HOMEWORLD_SHIPMENT_RUNTIME.md) records actual world-to-world invasions, explicit native/foreign pools, mixed Emperor origins, Guild native returns, separate shipper/donor payments, Guild interception and present-force alliance restrictions. Final types, lint, **3,304 offline cases** and production build pass; **40 HTTP cases** passed before final UI/reference edits. Forty new regressions include actual invasion-to-battle discovery, all-profile policies, competing declarations, allowance-versus-stop races and Box-suspended recovery. Independent review fixed a public automatic-work flag that disabled genuine human Guild choices. Desktop mixed-source shipment, phone keyboard allowance and both-seat refresh preserve exact forces/payment; all **2,740** pre-existing room versions/hashes remain unchanged. Arrakis/Junction routes, occupation, remaining faces, unresolved Karama interpretations and complete module games remain unfinished; no start gate opened. User workflow optimizations remain in use and automation stays removed.
**Homeworld battle runtime checkpoint, 9 September 2026:** [HOMEWORLD_BATTLE_RUNTIME.md](HOMEWORLD_BATTLE_RUNTIME.md) records live Homeworld battle discovery, native strength, sealed plans, native-only Traitor calls, typed explosion losses, late Portable Snooper decisions, Ixian replacement and native Tleilaxu Face Dance. Final typecheck, lint, **3,264 offline cases** and production build pass; **40 HTTP cases** passed before the final saved-decision and board-selection fixes. Independent review and browser testing fixed paused-decision validation gaps and an off-planet territory-selector crash. Desktop/390×844 keyboard battle settlement and refresh preserved exact typed forces and card disposal in a conserved staged invasion. All **2,709** baseline room versions/hashes remain unchanged. Actual invasion transport, occupation, remaining face effects, unresolved return/support interpretations and complete module games remain unfinished; no start gate opened. User workflow optimizations remain in use and automation stays removed.
**Homeworld combat foundation and Salusa checkpoint, 9 September 2026:** [HOMEWORLD_COMBAT_IMPLEMENTATION.md](HOMEWORLD_COMBAT_IMPLEMENTATION.md) records public typed off-planet armies, pure native battle/explosion rules and connected high-Salusa free Sardaukar support. Final typecheck, lint, **3,221 offline cases** and production build pass; **40 HTTP cases** passed before the final Ghola guard. Independent review reproduced a population-changing Ghola deadlock after a sealed plan or prescience answer; execution, UI and AI now gate that specific unresolved interaction, with eight Salusa engine regressions covering rejection, privacy, JSON restoration and subsequent completion. All **2,648** baseline room versions/hashes are unchanged. Live Homeworld invasion/battle/occupation, remaining face effects, full module games and new browser acceptance remain unfinished; no start gate opened. User workflow optimizations remain in use and automation stays removed.
**Homeworld charity and revival checkpoint, 9 September 2026:** [HOMEWORLD_BENEFITS_IMPLEMENTATION.md](HOMEWORLD_BENEFITS_IMPLEMENTATION.md) records source-separated charity payments, dynamic low free-revival rates, four-free Fremen capacity, and Tleilax’s durable phase-start income condition. **3,190 offline tests**, typecheck, lint, final production build, **40 HTTP tests** and **144 focused Homeworld/reference cases** pass. Independent review reproduced and integration fixed Box-suspended charity overpayment, invented saved free revivals and an AI/server special-Karama mismatch. Seven production SQLite recovery cases cover races, interrupted choices, privacy and rejected writes. Desktop/390×844 keyboard claims, invalid revival prevention, threshold crossing and refresh pass in an isolated QA room. All **2,648** pre-existing room versions/hashes are preserved. CHOAM opening-income and special-Karama interpretations remain pending; Homeworld battles, invasion, occupation and full module games are unfinished. No start gate opened; automation remains removed.
**Homeworld native-reserve runtime checkpoint, 9 September 2026:** [HOMEWORLD_RUNTIME_IMPLEMENTATION.md](HOMEWORLD_RUNTIME_IMPLEMENTATION.md) records genuine supported-deck setup, saved typed custody, Basic strength-one special counters, exact native shipment sources, Emperor transfers and revival destinations, public controls and all-profile AI. **3,152 offline tests**, typecheck, lint, production build and **40 live HTTP tests** pass; the final focused Homeworld/reference run passes **106** cases. Actual transfer → shipment → Storm death → revival, Hajr, Ghola receipt integrity and competing SQLite requests are covered. Desktop/390×844 controls, card inspection, invalid-source prevention and refresh pass in a new isolated QA room. Twenty **two-player Basic** games complete 3,079 accepted actions without rejects/stalls or changed source fingerprints; this is a bounded regression sample. All **2,617** older saved rooms are unchanged. Invasions, Homeworld battles, occupation, card effects, remaining arrival routes and full module games are unfinished; public starts remain disabled. Workflow optimizations are preserved and the automation stays removed.
**Homeworld component and custody checkpoint, 9 September 2026:** [HOMEWORLD_IMPLEMENTATION.md](HOMEWORLD_IMPLEMENTATION.md) records all 13 cards and 26 verified faces, original bundled planetary art, searchable high/reverse inspectors, typed native/foreign custody and a separate population projection. **3,085 offline tests**, typecheck, lint and the final production build pass. Both enlarged faces of every card were exercised on desktop and 390×844 phone; normal reverse controls, artwork loading, full-text search, keyboard activation, scrolling and refresh pass. Screenshot sampling and remaining complete visual acceptance are explicitly bounded in the feature document. The 07:53 UTC controlled restart preserved all **2,617** saved room versions/hashes and restored the authenticated QA seat. Actual Homeworld shipment, battles, occupation, card effects, AI and complete games remain unfinished; no mode gate opened. User workflow optimizations are in use and the automation remains removed.
**Ecaz Ambassador alliance checkpoint, 9 September 2026:** [ECAZ_ALLIANCE_IMPLEMENTATION.md](ECAZ_ALLIANCE_IMPLEMENTATION.md) records the reusable token’s owner offer, entrant consent/refusal, immediate reciprocal alliance and original movement/worm continuation. Duke availability is independent; optional loans await a custody ruling. **3,058 offline tests**, typecheck, lint, production build and **40 HTTP-suite tests** pass. Thirty new alliance tests include public-identity quotes, all four AI levels, actual Box suspension, corrupt-save rejection and competing SQLite replies. Browser mobile keyboard proposal, AI acceptance, chronicle and refresh passed; all 2,586 older non-QA room versions/hashes are unchanged. Twenty Basic games completed 12,186 accepted actions and 545 JSON round trips with zero rejects/stalls and unchanged source fingerprints. Full faction/mode/module completion remains gated, user workflow changes are preserved, and the automation stays removed.
**Ecaz shared collection checkpoint, 9 September 2026:** [ECAZ_COLLECTION_IMPLEMENTATION.md](ECAZ_COLLECTION_IMPLEMENTATION.md) records bilateral desert allocation, private proposals/counteroffers, the odd-to-ally default, automatic bank income and scoped Karama cancellation. All **3,028 offline tests**, typecheck, lint, production build and **40 HTTP-suite tests** pass under the new automatic test-discovery workflow. Sixty collection tests include actual engine transitions, all four AI levels, suspended Box/Karama recovery and SQLite races; review fixed orphaned collection controls. Twenty Basic games completed 10,206 accepted actions and 465 JSON round trips without rejects/stalls or changed source fingerprints. Real browser proposal/AI acceptance, phone keyboard completion and refresh passed; all 2,556 older non-QA room versions/hashes remain unchanged. Full Ecaz combat, its Fremen endgame exception, Tleilaxu Ambassador, remaining Duke interactions and complete Advanced/expansion/module acceptance stay unfinished and gated. User workflow optimizations are preserved; the automation stays removed.
**Ecaz joint stronghold victory checkpoint, 7 September 2026:** [ECAZ_VICTORY_IMPLEMENTATION.md](ECAZ_VICTORY_IMPLEMENTATION.md) records the three co-occupied stronghold win, shared public server/UI/AI progress, prediction privacy and final Stronghold Card recovery. **2,758 rules/client/component +245 multiplayer tests (3,003 total)** pass with TypeScript, lint and production build clean. Twenty Basic games completed 12,818 accepted actions and 568 JSON round trips with zero rejects/stalls and unchanged source fingerprints. Actual browser Mentat victory, verbose chronicle, phone/keyboard and refresh passed; all 2,526 pre-existing non-QA room versions/hashes remain unchanged. Fremen’s Ecaz endgame exception, combined Occupy combat, shared collection, Tleilaxu Ambassador runtime and full Advanced/expansion/module acceptance remain unfinished. The automation stays removed.
**Ecaz territorial occupancy checkpoint, 7 September 2026:** [ECAZ_OCCUPANCY_IMPLEMENTATION.md](ECAZ_OCCUPANCY_IMPLEMENTATION.md) records shared server/AI entry and path checks, permanent Ecaz allied co-occupation, advisor exceptions, physical/hidden-marker conservation and the automatic turn-end notice. **2,730 rules/client/component +242 multiplayer tests (2,972 total)** pass, with TypeScript, lint and production build clean. Twenty Basic games completed 11,446 accepted actions and 515 JSON round trips with zero rejects/stalls and unchanged source fingerprints. Desktop/phone, keyboard completion, notices and refresh passed; all 2,496 older non-QA room versions/hashes are unchanged. Combined Occupy combat, shared desert collection, special victory, Tleilaxu Ambassador runtime and complete Advanced/expansion/module acceptance remain unfinished. The automation stays removed.
+49
View File
@@ -0,0 +1,49 @@
# Junction transport offers
9 September 2026. Implementation contract for Junction's high-face transport advantage. This is a source audit, not certification of a completed transport module. It supplements [the component audit](HOMEWORLD_COMPONENT_AUDIT.md), [invasion rules](HOMEWORLD_INVASION_RULES.md), and [transport source update](HOMEWORLD_TRANSPORT_SOURCE_UPDATE.md).
## Evidence and precedence
Fresh publisher-indexed passages were retrieved from the [GF9 E3 rulebook, pp.10 and 15](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=10), [base rulebook, pp.9 and 19](https://www.gf9games.com/dunegame/wp-content/uploads/Dune-Rulebook.pdf#page=19), [November 2020 FAQ, pp.2 and 5](https://www.gf9games.com/dune/wp-content/uploads/2020/11/Dune-FAQ-Nov-2020.pdf#page=2), and [E1 cancellation table, p.12](https://www.gf9games.com/dunegame/wp-content/uploads/2020/09/IxianAndTleilaxuRulebook.pdf#page=12). Direct publisher PDF opens returned HTTP 403. This review does not claim a new binary download or new visual inspection of the physical card: the previously inspected research images under `/tmp/dune-rules` are absent in the current environment.
Junction's physical face was previously checked through the sources recorded in the [component audit](HOMEWORLD_COMPONENT_AUDIT.md#sources-and-completeness). Its operative facts are: while high, Guild may offer other factions cross-planet shipment at half or full price, as part of their Shipping action, including travel to/from Homeworlds and their own world. Its printed high range is 5–20 native reserves. Guild is the offer owner; alliance status does not imply consent. The [designer's E3 page](https://futurepastimes.com/dune-ecaz-moritani) still links its Homeworld explanatory material, but no fresh authenticated explanation of payment or special interception was obtained here. Player discussions and fan compilations were not adopted as rules authority.
## Routes and counter custody
E3 permits own-world return through the Junction exception, retains the ban on allied-world destinations, and allows Emperor to combine both native origins for a shipment. Homeworlds have no territory geometry. Bene Gesserit cannot send advisors there. A paid Fremen invasion remains distinct from ordinary free southern reinforcement. Homeworld arrival activates Heighliner; retain E1's Guild exception. [E3, pp.10 and 15](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=10), [E1, p.5](https://www.gf9games.com/dunegame/wp-content/uploads/2020/09/IxianAndTleilaxuRulebook.pdf#page=5).
The following route matrix composes that exception with the face's express scope and the base meaning of cross-planet shipment:
| Origin | Destination | Contract |
|---|---|---|
| One Arrakis territory | Another Arrakis territory | Cross-planet shipment; exact destination sector and ordinary entry rules. |
| One Arrakis territory | Native or foreign Homeworld | Explicit sponsored route, including a return to the shipper's own world. |
| One Homeworld | Another Homeworld | Exact current native/foreign custody; own-world return permitted by sponsor. |
| Foreign Homeworld | Arrakis | Explicit departure permission from Junction; visitors never become native reserves. |
| Native Homeworld | Arrakis | Ordinary reserve shipping already supplies permission. A sponsored route must keep its Junction provenance separate from ordinary personal/allied rates. |
Do not use a synthetic Homeworld sector. Do not combine unrelated Arrakis territories or arbitrary foreign worlds into one origin. Multiple sectors of one territory remain one source; the Emperor's two-native-world exception is explicit. Board sources and destinations must obey storm and entry restrictions. Protected Hidden Mobile Stronghold interior custody does not inherit the pointer sector's storm exposure. [Guild transport source contract](GUILD_HOMEWORLD_TRANSPORT_RULES.md#route-and-custody-contract).
For BG, source selection must distinguish actual fighters and advisors. An advisor cannot be silently converted into an invading fighter as a side effect of shipment. Any separately legal flip requires its own valid timing. The Fremen native Homeworld is **Southern Hemisphere**, not Sietch Tabr; a sponsored paid route does not become free merely because the owner is Fremen.
## Tariff and payment
Treat the accepted offer as either `half` or `full`, never a general arbitrary discount. Use the ordinary destination tariff before the offer multiplier: Homeworld destination costs one spice per physical counter; Arrakis stronghold costs one, other territory two, with independently applicable special-location prices. Half-price totals round upward once. Five counters to a world therefore cost five at full or three at half. Elite counters are physical counters for shipment price. Do not stack an allied Guild discount onto a half-price Junction offer. [E3, p.10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=10), [base, p.9](https://www.gf9games.com/dunegame/wp-content/uploads/Dune-Rulebook.pdf#page=9), [November FAQ, p.5](https://www.gf9games.com/dune/wp-content/uploads/2020/11/Dune-FAQ-Nov-2020.pdf#page=5).
**Coordinating source composition:** Junction supplies permission and tariff, but its inspected face supplies no separate payment-recipient instruction. Apply the base bank default. Guild's ordinary income exception covers another faction's off-planet native reserves arriving on Dune. It does not automatically collect fees for sponsored world destinations, foreign-garrison departures, or board-to-board cross-shipment. Sponsorship alone is not an income trigger. This resolves the previously recorded recipient gap by composing the existing general and specific rules; there is no official Junction worked example. [Base, pp.9 and 19](https://www.gf9games.com/dunegame/wp-content/uploads/Dune-Rulebook.pdf#page=19), [quick-start payment rule, p.8](https://www.gf9games.com/dunegame/wp-content/uploads/Quick-start-Guide.pdf#page=8).
The November FAQ independently sends a non-Guild ally's contribution directly to Guild when present and sends Guild-funded contributions to the bank. Preserve this [previously adjudicated contributor contract](GUILD_SHIPMENT_PAYMENTS.md#publisher-contract-and-precedence), rather than routing every spice through one shipper-income rule. Incoming receipts cannot finance the same transaction. A five-spice world shipment funded by shipper three and non-Guild ally two thus sends three to bank and two to Guild before independently applicable Homeworld splits. The offer is not a direct spice gift or a bribe. [November FAQ, p.2](https://www.gf9games.com/dune/wp-content/uploads/2020/11/Dune-FAQ-Nov-2020.pdf#page=2).
## Karama and offer lifetime
E3 states: “Karama cards have no effect on Homeworld advantages or penalties.” The grant and offered rate therefore resist ordinary cancellation. **Coordinating inference:** Guild's special stop must also not prevent a shipment whose permission/rate comes from Junction; doing so would negate this Homeworld advantage. Do not create a special-stop choice for that declared route. This differs from a shipment using Guild's ordinary faction privilege. It does not make all unrelated faction powers during a sponsored arrival immune. [E3, p.10](https://www.gf9games.com/dune/wp-content/uploads/EcazMoritani-Rulebook-LOWRES.pdf#page=10), [ordinary cancellation distinction](GUILD_HOMEWORLD_TRANSPORT_RULES.md#distinct-card-interactions).
The card authorizes use during the recipient's Shipping action; it grants no extra shipment and no extra movement. It prints no once-per-turn cap on Guild offers. An offer's UI storage and replacement policy are implementation mechanics, not additional faction powers. Bind any executable offer to the current recipient and unused shipping opportunity, revalidate Guild's high benefit and selected tariff before declaration, and expire stale grants when that opportunity ends. Do not preserve a reusable permission into later turns merely because a proposal was once accepted. Once shipment settlement has validly committed, a later threshold change must not reverse it.
## Remaining evidence boundaries and verification obligations
No publisher example was found for a threshold change between an earlier conversational offer and its execution. Current-state revalidation avoids inventing a permanent grant; a future binding-deal implementation must preserve the documented ordinary deal rules. The existing broader occupation-lifecycle and ordinary Karama repricing questions remain open and are not resolved by this audit. The exact generic purchased-Karama card scope likewise remains in [the source update](HOMEWORLD_TRANSPORT_SOURCE_UPDATE.md#karama-distinguish-three-effects).
Implementation evidence must cover sponsor ownership and consent; high/low revalidation; half/full odd totals; current-shipping expiry; board/world/native/foreign origins; own/ally destination rules; exact normal/elite/advisor custody; paid Fremen routes; source and destination storms; both donor identities; no circular funding; immunity without a spurious human stop; one arrival/technology receipt; unchanged rejected state; JSON restoration; and duplicate/concurrent acceptance. These are engineering acceptance requirements, not claims that the corresponding code currently passes.
Validation for this document: relevant local references reviewed, primary indexed passages compared against earlier source audits, and no runtime, database, server, or automation modified.
+27
View File
@@ -0,0 +1,27 @@
# Junction transport runtime
9 September 2026. [Source contract and adjudicated compositions](JUNCTION_TRANSPORT_RULES.md). This extends [Guild transport](GUILD_HOMEWORLD_TRANSPORT_RUNTIME.md) with Junction's distinct high-population grant. Homeworld game starts remain disabled pending completion of the entire module.
## Offers and routes
Guild can offer half or full price to the faction currently taking its unused shipment. Offers are optional: the recipient can use one or continue ordinary actions. A replacement has a new identity; the old proposal cannot authorize a shipment. Current actor, turn, unused shipment, native high population, typed source custody, funding and destination legality are revalidated before acceptance. Expired offers cannot be reused in a later opportunity. The grant gives no extra shipment or movement.
The shared quote supports one Arrakis territory to another territory or Homeworld, and one native or foreign Homeworld to Arrakis or another Homeworld. Advanced Emperor can combine both native worlds. Native returns are allowed; allied-world destinations remain prohibited. Normal and elite counters retain physical identity and exact source custody. Multiple sectors from the same territory can contribute. Protected mobile-stronghold interiors, source/destination storms, advisor stance and locked advisors, native reserves, and foreign garrisons remain distinct. Concealed No-Fields are not silently converted to physical counters.
Homeworld destinations cost one spice per counter; ordinary Arrakis destination tariffs apply before the offered multiplier. Half price rounds upward once and does not stack with an ordinary allied discount. Junction's route and rate resist Karama, so settlement has no special Guild interception choice. Unrelated arrival responses retain their own cancellation rules.
Settlement validates before changing payment or forces, consumes the shipment once, and retains movement. Native off-planet reserve shipments onto Arrakis produce ordinary Guild income; other personal route fees use the bank default. The November contributor-specific ally routing remains independent. Incoming income cannot finance the transaction that creates it. Actual Homeworld arrivals and eligible off-planet arrivals on Arrakis activate Heighliner; native Fremen southern departure retains its on-planet distinction. Eligible off-planet arrivals offer the ordinary Bene Gesserit follow-up, and Arrakis entry resumes territory effects.
## Controls, AI and verification
The table exposes half/full offer buttons to Guild and a typed source/destination/payment panel to the recipient. The same pure quote supplies authoritative calculations, controls and all four AI profiles. AI offers use public state; recipients retain defenders and collecting forces while considering native defense, invasions and Arrakis objectives. Automated Guild receives an opportunity to offer before an earlier-seated automated recipient spends its shipment. No human action is delayed to force an optional offer.
Forty-four new regressions cover pure transport (14), actual engine actions (11), controls and all four AI profiles (9), independent integration review (6), and production SQLite recovery (4). They include duplicate acceptance, offer replacement versus acceptance races, exact typed settlement, no repeat execution on reads, malformed saved offers, private event invariance, advisory locks, and native versus foreign Fremen arrival effects. Independent review found no further core defect. Final broad check evidence is recorded in the newest [implementation checkpoint](IMPLEMENTATION_STATUS.md).
Desktop browser testing exercised real keyboard offer creation and replacement, rejected eleven counters from a ten-counter source, and quoted five counters at three spice. The initial replacement collapsed the sponsor panel; retaining its opportunity identity fixed that, and subsequent keyboard replacements remained visible. At 390×844, the recipient restored the offer after refresh and used keyboard shipment to return five actual starting Atreides counters from Arrakeen to Caladan. Another refresh preserved fifteen native reserves, five counters in Arrakeen, seven spice, zero used movement and the consumed offer. Guild's held Karama remained unspent, with no spurious stop prompt or fee receipt. Desktop selection and phone selection/settlement screenshots were visually inspected; no page errors or horizontal phone overflow occurred. This used genuine setup with only the shipment opportunity staged, not a complete Homeworld game.
The hourly controlled server restart backed up and preserved all **2,802** then-existing room versions/state hashes and restored the prior private QA seat. After the new browser/API checks, all **2,802** pre-existing rooms still matched their baseline with none missing. Four additional in-memory probes verified that every automated difficulty lets a later-seated Guild offer before an earlier-seated recipient spends shipment. The live QA room was never modified by those probes.
## Remaining scope
Occupation lifecycle and its retained low penalties, remaining Homeworld faces, concealed transport, unsponsored foreign departures, generic purchased-Karama scope, ordinary Guild cancellation timing, and complete module games remain unfinished. The high-population predicate does not claim to settle the existing occupation interpretation. Public starts and publication remain gated. Saved games and the removed-automation preference are preserved.