25 KiB
Fremen Ambassador runtime readiness
Historical design review. The implemented contract and final validation supersede the proposals below: FREMEN_AMBASSADOR_IMPLEMENTATION.md.
Read-only implementation audit, 7 September 2026. The smallest useful addition is a beneficiary-owned remote board-group selection under the existing Ambassador event, followed by a bounded arrival continuation. Existing typed force and marker operations are reusable. Ordinary movement completion is not: it spends a movement and shipment opportunity. A general recursive Ambassador stack or a new durable discard framework is unnecessary for this effect.
This is a design review of the current source, not a released implementation or full expansion certification. Runtime line pointers below describe the reviewed snapshot and may move during integration. Source interpretation is coordinated with the independent publisher-source reviewer; the earlier remaining-effects readiness is historical where it leaves remote relocation and recursive Ambassador entry unresolved.
Rules composition and current gates
The GF9 Ecaz & Moritani rulebook, pp.7–8 assigns the effect to Ecaz or its ally and relocates one group already on the board to a territory, retaining storm and occupancy restrictions. The source reviewer establishes a direct remote relocation, parallel to ordinary worm transportation: no ordinary adjacency, distance allowance, or clear path through intermediate territories. Neither reserves nor Homeworlds are source/destination territories; the latter exclusion is explicit in E3 p.10. Discovery locations that are territories require board support currently absent from this implementation.
One group may select partial counts from several sectors of one territory. Selected source sectors and the destination must be clear of storm. Elites remain typed forces. A concealed No-Field moves under its existing movement rules, counts as one effective presence even when its hidden value is zero, and does not reveal merely by relocating. The Hidden Mobile Stronghold is a separate destination: the Ixians & Tleilaxu rules, p.9 restrict non-Ixian entry to its pointing territory. Relocating forces never moves the stronghold itself or collects spice along its route.
Same-territory movement to a different sector remains possible under the November FAQ movement clarification; require actual relocation and do not manufacture another territory-entry reaction. In phase5, existing Baliset restrictions apply because this is movement into CHOAM occupation, not shipment; phase1 relocation does not meet Baliset’s phase condition. Reuse balisetPrevents for the existing restriction. Opening a new reactive CHOAM movement decision requires this effect’s own return link rather than pendingChoamMove, whose validator and completion spend ordinary movement.
If no legal relocation exists after commitment, follow an explicitly documented unavailable-effect interpretation: token committed, no group moved, finish once. Do not add an arbitrary beneficiary decline to an otherwise mandatory effect. Recompute current legal availability without leaking hidden No-Field values.
Two useful consequences bound the implementation:
- The original entrant cannot be Ecaz or its ally. Therefore a legal beneficiary is not that entrant, and their relocation cannot trigger a second Ecaz Ambassador while the same alliance remains in force.
canTriggerAmbassadoralready expresses this exclusion. BG copying the Fremen effect changes neither beneficiary entitlement nor the original physical-token provenance. - An active phase-5 Ornithopter belongs to the original entrant. It cannot belong to this effect's beneficiary. Preserve the original flight, its original-unmoved cohort, counters, card custody and remaining selection unchanged; do not create another flight or subtract the relocated beneficiary's forces from that cohort.
allowedEntry currently bans allied co-occupation outside Polar Sink. That is not complete Ecaz legality: E3 p.8 Occupy permits Ecaz and its ally to co-occupy and treats them as one faction. Its downstream combat/collection/victory implementation remains separately incomplete. Reusing that blanket rejection must remain an explicit development gate, not a claimed printed Fremen Ambassador restriction. The same applies to the existing simultaneous Terror/BG arrival gate and absent Discovery/Homeworld modules. Full Advanced/expansion starts are already disabled independently; those start gates do not prevent implementing and testing this bounded effect in conserved development positions.
Existing reusable operations
| Current code | Reuse and required adaptation |
|---|---|
engine.ts:5696 forceGroup, eliteChoice, removeGroup, place |
Parse positive physical counts from one source territory, preserve ordinary/elite custody, aggregate a marker as one effective unit. Revalidate the selected source before mutation. Add an explicit selected-source storm check; do not derive remote legality from gameDistance. |
engine.ts:5650 allowedEntry |
Reuse destination existence, sector, storm and ordinary stronghold-capacity checks subject to the explicit Occupy composition/gate above. It checks mobile placement but not its pointing-territory entry rule. Do not pass stormShipment:true: this is not reserve shipment. |
advisors.ts:arrivalAsAdvisor, isAdvisor, fighterCount |
Reuse territory-wide BG stance, lock and capacity semantics from the ordinary move branch, including destination merges. If optional fighter conversion is supported, its response must return to this effect's arrival continuation. Do not silently turn moving advisors into fighters or count advisors as a third fighting faction. |
richese-no-field.ts:moveRicheseNoField |
Move only the same canonical deployed marker. Preserve concealed value, last-shipped history and physical reserve/Tank counts; allocate a fresh marker event once on commit. Physical forces may accompany it. Neither marker presence nor a zero value is a physical force to pass to place. |
engine.ts:13998 worm-ride decision |
Closest actual dispatcher pattern: remote destination, multi-sector typed source counts, explicit storm-origin restriction, one place operation and arrival handling. It is source-locked to the worm's territory and Fremen player, so share its low-level operations rather than dispatching a fake worm decision. |
engine.ts:6081 validateMovementArrival / karama-movement-preflight.ts |
Existing pure arrival analysis identifies intrusion and token reactions before any mutation. It currently rejects simultaneous reactions and assumes ordinary movement/flight retirement. Extract/adapt its applicable predicates for this separate arrival; do not disable all guards merely because the Ambassador parent is intentionally retained. |
engine.ts:6130 completeMove, 6202 finishMovedGroup |
Do not invoke unchanged. They update shipped, moved, shipment promises, flight counters, karamaShipping, ordinary move logs and entry cause. Only the typed remove/place and arrival operations belong in this new effect. |
engine.ts:5839 finishOrnithopter, discard continuation at 3160 |
The original move's final-card retirement completes before its arrival opens the Ambassador. A first two-group move retains the original flight. No second Ornithopter discard/frame is needed for the Ambassador move. |
There is a concrete command-field collision: decideAmbassador binds action.event to the Ambassador event, while forceGroup reads action.event as the No-Field movement event. Use a separate marker-event field or nested selection, then adapt it explicitly when calling forceGroup. Do not weaken either stale-event check.
No general teleport function exists in the reviewed runtime. The absence of such a helper is ordinary implementation work, not a reason to route through paid transport or require a new global architecture.
Bounded state and arrival continuation
Proposed contract; names are implementation choices:
- Keep the real entry producer, owner offer and physical token commitment in
decideAmbassador. A triggered Fremen effect, including BG copying, opens an event-boundmovestage for the selected beneficiary. Keep the original entrant, original entry territory/sector, turn/phase, physical token, copy provenance andresumeuntouched. Do not open a second confirmation after the beneficiary has submitted a valid move. - A pure selection quote validates current event/beneficiary, original used/removed token provenance, one board source group, selected ordinary/elite/marker custody, storm endpoints, destination stance, mobile destination rule and applicable occupancy/Baliset restrictions. Permit a genuine different-sector move within the source territory, with no token-entry reaction. It returns the exact relocation plus arrival requirements. It must not use random values, expose marker value, spend resources, set
active, or demand the beneficiary's ordinary movement allowance. - Commit remove/place/stance/marker event and one relocation log once. Keep
shipped,moved,hajr,karamaShipping, movement queue, Guild timing, Sapho ordering and original flight unchanged. Freeze a small completed relocation receipt while child reactions remain; recovery must resume the suffix rather than select or move the group again. - A clean destination calls
finishAmbassadoronce. Reactive CHOAM Baliset, if offered for this phase5 relocation, needs a source-tagged pending order and return link that preserves this independent movement; do not reuseresumeChoamMovementunchanged. For an actual Terror or BG reaction, keep the Ambassador in a non-actionable arrival stage and attach an explicit return link to its event. A small typed child continuation is sufficient; no second Ambassador is opened for Ecaz/its ally. Only after the child finishes mayfinishAmbassadorreplenish a completed five-token cohort and restore the original entrant or worm queue. - If both BG intrusion and Terror apply, either implement a source-justified local ordering or retain a clearly named unsupported simultaneous-arrival gate before relocation. Existing code opens intrusion first and rejects a competing token; that is a gate, not an authoritative ordering. Source priority must not be invented by the new helper.
Concrete suffix consumers that need the new return link:
| Consumer | Current assumption that must change for an Ambassador child |
|---|---|
openTerrorEntry / finishTerrorEntry at 6779–6827 |
resume is only none or wormRide. Add an Ambassador return event/cause; clear Terror once and resume the completed effect, not nextWormRide directly. |
intrusion, intrusion decision, finishAdvisorReaction at 7585, 13891, 7569 |
Current controls retain only worm/declaration/followup semantics. Preserve an Ambassador return link across decline, advisorFlip allow, cancellation and BG Worthless conversion. |
treacheryDiscardIntegrity Terror branch at 2812–2877 |
Existing non-worm causes require resume:none; worm causes require a Fremen entrant in phase1. A phase1 Ambassador beneficiary may be any eligible faction. Add the exact new cause/parent binding for Sabotage and Robbery overflow frames, whose existing suffix already restores the entire Terror entry. Do not masquerade as wormRide. |
moritani-alliance-cancellation.ts:quoteMoritaniAllianceCancellation |
Same phase/cause assumptions. Accept the real new producer with its bound parent. Enemy of My Enemy can change the beneficiary's alliance after committed relocation; finish the historical effect without demanding the old alliance still exist. Ecaz itself remains excluded from that alliance offer. |
afterWorm and nextWormRide |
A summoned worm may interrupt phase1 controls. Preserve the Ambassador return chain and defer the original ride/Nexus appropriately. The present afterWorm detection explicitly recognizes Terror/advisor worm resumes but does not list pendingAmbassador.resume; exercise the actual combined path rather than assuming the new nested control is covered. |
| Saved-control and Karama source binding | New advisor/Terror return metadata must survive Box, gift, Truthtrance and BG conversion envelopes already supported at those controls. Bind event/receipt/provenance; do not hash unrelated hands, balances, response passes, or the whole mutable game. |
A nested Terror alliance can legitimately end Ecaz's alliance with the beneficiary. That does not invalidate the already committed relocation or entitle a replay. Selection entitlement is checked before moving; the completed receipt is historical. Similarly, later Terror losses can remove the relocated units. A suffix validator should not insist that all originally moved units still survive at the destination after those losses.
Concrete reactive Baliset adapter
Root's planned contract fits the existing engine without inventing an ordinary move: MovementOrder gains source?: 'ambassador' and ambassadorEvent?: string; pendingChoamMove owns that exact order only while CHOAM decides or its Worthless response is pending. The original Ambassador entry remains live and bound to the source event. Offer this reaction only in phase5, for another faction moving into a different territory currently occupied by CHOAM; neither within-territory sector transfer nor phase1 relocation opens it.
The complete source-specific branch inventory from the reviewed code is:
| Hook | Required behavior |
|---|---|
offerChoamMovement (5980) |
Keep the current declared player/destination/count decision fields. Its no-CHOAM tail must dispatch an Ambassador order to the independent commit, not completeMove; phase1 skips the reactive offer. |
validateMovementOrder (5999) |
Source branch first: validate the parent Ambassador event and pure Fremen relocation quote. Do not require active === beneficiary, phase5, remaining ordinary moves, flight event or ordinary range. Require the correct current Ambassador stage and original committed token/copy provenance. |
resumeChoamMovement (6065) |
Clear only the declared CHOAM order, revalidate source, then commit through the independent relocation. An accepted no-move/fizzle must restore the beneficiary's actionable move stage (or documented no-legal-move finish); the existing ordinary catch merely returns and would strand a non-actionable Ambassador parent. |
currentChoamWorthlessCancellationQuote (10225) |
Its existing pure declaration envelope remains valid for reactive Baliset in phase5. Branch the subsequent arrival preflight by order source: ordinary validateMovementArrival sees a live Ambassador and rejects it. The new preflight must validate the source-bound future arrival without replay, spending, RNG or clearing controls. |
quoteChoamWorthlessCancellation (game/choam-worthless-cancellation.ts:164) |
Keep target/location/sector/origin binding. An Ambassador event must also be validated by the caller's source quote. Existing checks do not require the mover be active, so no broad phase relaxation or fake ordinary ownership is needed. |
finishResponse Baliset success (10665) |
Preserve the intended restriction, discard and log. Before clearing pendingChoamMove, capture whether it is Ambassador-sourced; restore that entry's move stage with newly computed legal destinations. No force, marker, move counter, token or cohort replay. |
finishResponse canceled Baliset / vanished-card tail (10727) |
Resume the exact pending source order through the shared source-aware dispatcher. Printed Karama cancellation and an allowed BG conversion must have identical relocation consequences; counter-canceled BG conversion must still permit the original Baliset and return to reselection. |
CHOAM decision decline (13229) |
The existing call to resumeChoamMovement becomes correct once that dispatcher is source-aware. Do not add a beneficiary acknowledgement or a second payment. |
karama-context.ts choamWorthless selector |
It already serializes the actual pending movement, so the new source/event fields enter the signature. Its semantic validator must prove the parent event; no whole-game, hand or balance signature is needed. Suspended Box/gift/BG controls must retain the same order and parent link. |
Do not route this order through pendingFremenMovement, pendingIxMove, movementOrderRange, validateFlightSelection or finishOrnithopter: those are faction/ordinary-move opportunities, not a free Ambassador relocation. Existing Ornithopter-discard integrity forbids a live pending CHOAM order; the actual producer drains its original retirement before opening the Ambassador, so that exclusion remains correct.
Minimum Baliset evidence is a genuine entry followed by a remote declared move into CHOAM, then each of: decline; successful Baliset and a different legal destination; printed cancellation; BG cancellation allowed; BG cancellation itself canceled; unavailable declared card and source revalidation. Repeat final allowance through SQL CAS and check exactly one relocation, marker-event rotation and eventual cohort finish. Mutating only the saved Ambassador event or copied-source binding must reject before Karama cost and on a paid final allowance. Parent loss must never be converted into a silent ordinary movement fizzle.
Privacy, automation and focused evidence
Use the existing owner offer and beneficiary choice projections. Return available physical counts, own elite counts and the beneficiary's own marker selection only to that beneficiary. Other seats need the public effect/stage/beneficiary and committed visible board movement, never marker value, private hand/traitor identities or raw saved controls. Pure option generation must not allocate marker/event IDs or advance random state. An active entry decision must keep the original entrant from moving while the beneficiary or child owner acts.
A compact verification set should include:
- Actual enemy move or shipment into a placed Fremen token, both Ecaz-self and allied beneficiary, with remote nonadjacent multi-sector mixed ordinary/elite move. Test BG copy independently; preserve original entry costs, counts and active player.
- Storm source/destination, invalid sector, typed over-selection, malformed/stale parent and marker events, unsupported Occupy/combined-arrival boundaries, mobile pointing territory and unplaced mobile marker. Illegal actions must leave input and persisted SQL state unchanged.
- No-Field alone and accompanied physical forces, including hidden zero; only one marker-event rotation and no reveal/reserve loss. Compare non-owner projections under hidden-value perturbation.
- Clean finish, Terror decline, Sabotage/Robbery discard suffix, intrusion decline/allow/cancel and permitted BG conversion. Verify original source/counters and exactly one cohort renewal after the final child, including a fifth-token BG copy.
- Original first-two-group Ornithopter arrival resumes the unchanged second-group cohort; original last-group card is already discarded exactly once. The beneficiary's independent move never increments either flight or ordinary counters.
- Actual worm-origin entry with a non-Fremen beneficiary, child reaction and remaining worm queue; summoned-worm interruption if permitted by existing controls. Reconnect, JSON round-trip and competing final child requests must move once, finish once, and preserve private projections.
- All four AI profiles select only projected legal options, and the UI offers a readable typed group/destination editor rather than a generic card-selection tail. No unrelated full-game calibration is required to establish this bounded slice.
No production or test files were edited or tests executed for this audit. Reviewed hashes: engine.ts 0c5e1b84be33743ff5801f1486b55d187f3b017af3289b39411683b6a8225a1d; movement-arrival quote 6f9cba097393b9cb901ca92925586fae5270a17f2413191ffcf474c4be37bb26; Ambassador inventory 03aa96e3873521ff15161831b258f4903b9ec2409b8230a47b25d6ad409ae03f; Ornithopter helper afe3d78fd78b30dee960d7361ea917aa8fb327909a118995cf998c1d51f51cbb. These are review snapshots, not final integration hashes.