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:
1 parent
3be49512f7
commit
28ba1618ba
266 files changed
+47680
-16851
No files matched your search
@@ -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.
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
Reference in new issue
Block a user