Files
Dune/docs/AUTOMATIC_ACTIONS_AUDIT.md
T
2026-09-08 07:37:52 +10:00

15 KiB
Raw Blame History

Automatic actions and player decisions

Read-only engine/UI/API audit, 2026-09-06, against the updated goal's requirement: automatic effects should not require confirmation; optional 1–2-second house-colored action notifications must not block play. Only this audit document was written. No rule or timing interpretation was changed.

Safest concrete removals

Current behavior Why it is redundant Safe implementation boundary
resolveBattle creates battleLosses even when casualtyOptions contains exactly one result (game/engine.ts, approximately 3753 and 3873). There is no choice of unit mix. Even a zero-loss result can require a click. This differs from storm casualties, which already resolve a forced mix automatically. Extract the existing settlement of the selected option from the battleLosses handler. Invoke it directly for one option. Preserve the following Ixian substitution decision, winner card-retention choice, and postbattle continuation. Do not bypass them by merely calling finishBattle.
Every power owner must submit passResponse for its own power; completion currently counts every player (game/engine.ts, approximately 5695–5715; components/game-table.tsx, approximately 1495). The same dispatcher explicitly forbids the owner from canceling its own power. This pass is not an ordinary Karama cancellation choice. Count the owner as satisfied using public response.owner, while requiring all other participants' passes. Use one shared responder predicate for engine, bots and UI; normalize persisted windows and nested Worthless-Karama windows. Keep permitted Truthtrance/CHOAM overlays available while the actual responders decide. Do not globally auto-pass other players based on their hands.
fullPlanRead only accepts {continue:true} (game/engine.ts, approximately 6291); UI requires “Finish inspection.” Opponent's plan is already committed, and the Atreides player's next meaningful action is preparing their own plan. The acknowledgement does not choose an effect. Remove the extra blocking decision only with persistent private inspection in the ordinary plan editor. Preserve fullPlan target-first submission and authorized insight, including Truthtrance promises. A 1–2-second animation must not be the sole way to inspect a tactical plan. Legacy saved fullPlanRead can normalize to the plan editor without submitting a plan.

These findings are based on actual code branches, not a count of buttons labelled “Confirm.” No runtime reproductions were needed to establish the singleton branch or all-player response predicate; new integration tests remain necessary before modifying them.

The owner-pass reduction does not establish a new automatic deadline for other players. A player who has already passed can currently still use permitted overlays/cancel before the last responder passes; preserve those existing rights unless a separate authoritative timing change is made.

Additional candidate requiring a narrower integration check

beginPhase(7) calls collect(g) immediately. The UI then presents “Ready for next phase” to every player even though collection has already happened. Current collect contains automatic stronghold/desert awards; no collection allocation choice is exposed in this baseline. A collection-result notification followed by the existing phase-end continuation would remove a likely acknowledgement-only pause.

Do not implement this by removing all phase readiness or skipping nextPhase: CHOAM phase-end market, technology settlement, future Ecaz co-collection choices, and any applicable phase-specific reactions must remain. Complete the current phase's real decisions first. Special CHOAM and Truthtrance currently have broad timing, so verify their existing before/after boundary semantics when advancing automatically. This candidate is less isolated than singleton casualties and is not certified as a universal all-expansions rule.

Prompts that protect real choices

Prompt/window Actual choice or reaction protected
Storm movement confirmation Weather Control and Family Atomics before movement. Do not move storm on a display timeout.
Accept spice blow Harvester timing; other current Spice Blow continuations also include Thumper, Nexus, Fremen special Karama and worm choices. A publicly Harvester-closed blow can be examined separately, not used to remove all spice windows.
Phase opening Amal, including an opportunity after a prior Amal. The engine deliberately offers the same window regardless of hidden ownership.
Opponents allowing powers Ordinary Karama; Advanced BG Worthless conversion and nested cancellation. Income that looks automatic still has a cancellation window before settlement.
Guild shipment, full-plan offer, revival stop Spending an optional special Karama versus preserving it; hand-independent offers prevent information leaks.
Charity/Revival ready Remaining claims, revival resources, leader/force choices and other phase powers. Zero current payable revivals is not proof of no actions when special cards or resources can change.
Winner card cleanup, Moritani retention, Poison Tooth Keep/discard/activate choices remain even if one card is involved. One eligible card still offers keep versus discard.
Advisor arrival/intrusion, Face Dancer, captured leader, Moritani/Ecaz placement Optional effects, destinations, ownership or spending choices. Their availability is not equivalent to mandatory use.
Mentat readiness Negotiation, later turn-end effects, Face Dancer replacement, Gamont and other faction choices; do not globally skip because victory has already been checked once.
Lobby readiness, battle-plan lock, storm dial Consent or sealed strategic decisions, never automatic acknowledgements.

choamTradeConfirm is a genuine final assent after the ally specifies the returned card. auctionPayment can choose Karama versus spice. Do not remove either simply because it contains a confirmation label.

Existing automatic behavior to preserve

  • stormCasualties calls kill directly when the allowable elite-loss interval is a singleton; only a real mix choice creates stormLosses.
  • finishBattle transfers a single available technology token directly; multiple tokens produce techToken.
  • Empty winner-card cleanup proceeds immediately; combat with no remaining battles advances through its existing phase-end continuation.
  • Force transfers, payments, resource awards, setup completion, predetermined casualties and battle results already commit on the server; they need presentation, not new acknowledgements.

Do not replace these with client confirmation steps merely to make animations visible.

Privacy and multiplayer requirements

Do not auto-pass based on a player's hidden hand. A faster or absent Karama/Amal/Guild-special window would disclose that a player lacks a relevant card. A private local checkbox which emits an immediate pass only when a card is absent can leak through visible timing too. Removing a responder because they publicly own the power is different: that condition is already public and the rules branch prohibits self-cancellation.

Automatic rules resolution belongs in the authoritative engine on the disposable action clone, before the database compare-and-swap commits. db/rooms.ts act currently applies one action, runs AI, increments version and writes under room-version plus current-token authority. A deterministic normalization chain can share that transaction. It must stop at the first meaningful choice/reaction and use a bound that reports a real loop rather than silently dropping work. Do not imitate human confirmations from the browser or add client timer POSTs.

continueRoomBots already persists bounded AI batches with version fencing. It is not permission to advance human choices, and an animation completing must not call advanceBots, ready, or passResponse. Read-only GET/reconnect should project state; any migration that resolves a legacy redundant decision must happen at an explicit authoritative write, or a separately designed fenced continuation, never a mutating view.

Nonblocking notification contract

The UI currently has ordinary game logs and reduced-motion CSS, but no audited structured automatic-action notification stream. Game.log contains {seq,text} and retains 250 entries; one persisted bot batch can produce many events and skip intermediate phase snapshots. A phase-name comparison alone cannot reliably report every action.

Prefer small server-authored public event metadata such as {seq,kind,actorFaction,label} alongside the settled result. Private effects need viewer-authorized metadata; do not infer secrets from full game state or put inspected cards into public events. Keep action names separate from player-generated names and arbitrary log parsing.

Display each notification for approximately 1–2 seconds, with faction colors and a readable action name. It must use no modal backdrop, focus trap, pointer interception or disabled gameplay state. Provide a local toggle, honor reduced motion, and keep a durable readable history. Turning it off must change only presentation. Keep a per-room processed sequence so refresh or stale poll cannot replay old notifications; initialize a newly joined/restored view at its current sequence. Coalesce excessive AI-batch notices rather than queueing minutes of stale animation. Avoid announcing the entire historical log through a live region on every update.

Meaningful validation before changes land

  1. Single-option Advanced casualties settle exactly once, including JSON legacy state; multiple options still ask. Ixian cyborg losses still offer legal substitution. Winner cleanup, Moritani retention, technology/capture/Face Dancer continuations remain intact.
  2. Power owner is never a required pass; every other player remains eligible, including an ally. Windows remain identical for hidden-card variants. Nested BG conversion/counter and Truthtrance overlays restore the correct responders.
  3. Special prescience proceeds to Atreides planning with persistent private opponent-plan visibility; the opponent cannot change it and other seats cannot inspect it. Refresh preserves the insight; no automatic battle plan is submitted.
  4. Automatic settlement survives duplicate requests/concurrent CAS without duplicate payment, RNG, casualties or events. A disconnected owner's redundant acknowledgement cannot stall an otherwise settled window.
  5. Notices remain nonblocking on desktop/mobile and keyboard; toggle/reduced-motion behavior does not affect room state. Reconnect and multi-event bot batches do not replay history or expose hidden identities.

Full scope remains gated. This is an implementation audit of the present runtime, not a claim that every future expansion effect is automatic or already covered.

Implemented checkpoint (2026-09-06)

The candidate audit above describes the earlier baseline. Singleton auction payment and full-plan acknowledgement removal are now implemented. Exact funded split plus no usable Karama permits automatic payment; a real Karama choice remains explicit. Atreides retains private plan inspection until reveal, including when helping an ally. Legacy saved decisions recover via authenticated CAS continuation. Tests: automatic-decisions, full-plan, automatic-response-recovery, and the full 1,029 rules / 74 persistence checkpoint. Other candidate pauses still require their own timing audit.