Files
Dune/docs/JUICE_OF_SAPHO_RUNTIME.md
T
Quintine 9b67a780eb Connect early Juice of Sapho battle aggressor
During the existing public pre-plan opportunity, the holder can discard canonical unreserved Sapho to become aggressor before their readiness or any binding plan/Voice/inspection/Truthtrance commitment. Unchosen preparation prompts remain available. No new confirmation-only or holder-dependent response window is introduced. Later intervention and its allocation/privacy protocol remain unfinished.

A battle/turn/revision-bound history and independent event list preserve accepted priority while keeping attacker, defender and chooser stable. Legitimately recovered cards can change priority again at a fresh event. Reads, actions and normalization reject corrupt histories/custody. Shared tie priority respects Habbanya in either physical slot and reaches pre-commit Stone/Voice checks, public views, bot calculations and actual ordinary/Stone resolution. The final quote previously assumed original attacker priority and now consumes the validated aggressor. Harkonnen capture still follows actual winner/loser.

Owner controls, public aggressor/tie text, automatic notices and internal guidance are connected. Focused tests exercise actual tied results in Basic/Advanced, both Habbanya sides, mixed-force Stone finishability before opposing commitments, a real allied Prescience boundary, stale/late/cross-owner rejection, private rival noninterference, receipt corruption, saved recovered-card revision, actual policies at all four AI levels and authenticated SQLite races/seat restoration. Independent review found no material defect. A prior scheduling test now explicitly readies its human holder to save the card instead of allowing the new legal AI play.

Types, lint and 4866 offline tests, production build and 43 HTTP/session tests pass on the unchanged source fingerprint below. Two genuine CHOAM/Richese samples completed with 1279 accepted actions, 34 periodic JSON restores and no rejected candidates. One movement Sapho play occurred; neither sample used aggressor. Targeted tests and browser evidence, not those samples, establish the new effect. Full expansion and module acceptance remain incomplete.

In a new isolated browser room, genuine Advanced faction setup was followed by conserved battle staging. The human Guild used the actual aggressor button, restored the spent card and priority after refresh, readied, selected Master Bewt with zero dial/support, and declined a Traitor call. The staged Emperor opponent used real engine ready/plan/vote actions with Caid and zero dial/support. Guild won the 3-3 tie, retained four forces and 30 spice, and Emperor lost four forces. Final refresh and private JSON views restored the same outcome; the original seat row is unchanged. Screenshot capture timed out, so visual screenshot acceptance is not claimed.

All 1072 original games and original seat/recovery/entry/handover records are unchanged; 1106 rooms remain including isolated QA and HTTP fixtures. SQLite quick-check and foreign keys pass. The healthy server was reused without reset/restart or automation.

The Mirror audit now records why every genuine CHOAM/Richese setup includes unresolved copy candidates: an ordinary-copy-only gate would need hidden eligibility or altered inventory. Mirror stays gated pending the existing disposal ruling and copied-choice work. No mode/publication gate is opened.

Verified source tree: 2fb3160efd713a3f7068aedb474868ba6863bccc420848a56e69e1df1d84441b
2026-09-20 11:45:47 +10:00

9.7 KiB
Raw Blame History

Juice of Sapho: finite ordering implementation

Updated 14 September 2026. Partial card implementation; complete Richese/Advanced starts remain disabled. This document distinguishes implemented boundaries from printed rules. Sources and unresolved questions remain in the source audit. The publisher CHOAM/Richese rulebook p11 confirms Once Around last; the physical face describes first, last (including after Guild), and battle aggressor. No newly discovered official ruling resolves normal cyclic auction duration, partly completed combined turns, or first versus Guild. These three material questions have been sent to the user; no answer has been assumed.

The Battle-phase ordering prototype adds first/last remaining battle choices. Its separate chooser, phase priority and saved-boundary contract supersede the earlier absence of that mode below. The early aggressor prototype now uses the existing shared pre-plan opportunity; later aggressor intervention remains unfinished.

Implemented contract

{type:'card',card:'richese-juice-of-sapho',scope,event,mode} accepts one of these current opportunities and discards the actual held card once:

  • scope:'onceAround': first before any bidder acts; last while the holder has not acted. The intervention applies to this lot only. Prior bids, funding, completed participants, physical lot, event and storm tie order remain intact. Richese is not restored to last after Sapho. A holder excluded initially by a full hand gains a slot and eligibility by discarding Sapho, provided this lot is still open. Completed passes never reopen. Every purchase still requires a strict outbid.
  • scope:'movement': reorder entire remaining combined shipment/movement turns at a clean boundary. First requires every remaining turn to be unstarted; previously completed turns may retain their spent shipment/movement counters. In Advanced, Guild must be absent or have fully completed its turn and left the remaining queue. Last remains after Guild, including later Guild deferrals. No movement counters, Hajr, transport pricing, concealed tokens, resources or completed turns reset. Existing shipment/movement/preparation, reaction, Truthtrance, paid Box and gift commitments block the intervention. The next actor retains an already settled Guild timing choice when their identity is unchanged. An already granted, unstarted early Guild turn is lifted to the front of the local remaining queue before applying last, without changing physical order; this also permits Guild itself to declare last. A player now actually last cannot spend the card on a no-op.

The reusable immutable ordered-opportunity helper checks unique IDs, exact remaining/completed partition, stable event and locked current/protected-last positions. It never defines card scope or cyclic timing. Movement protection persists as saphoMovementLast:{event,turn,player}, checked on action, normalization and projection, and cleared when its owner finishes. Normal storm order is never rewritten. Invalid records are rejected, not repaired by replaying turns.

Owner-only saphoOptions supplies permitted actions to the hand panel and every AI level. It inspects only that owner's custody and public scope/timing. Other player views contain no possession-derived reaction flag. Played protection is public. A no-op does not consume the card. Unreserved canonical custody and exact allowed fields are checked server-side, and room version CAS prevents duplicate play and stale continuation.

All four AI levels consume the same legal owner projection. They prefer last in Once Around; movement first is preferred with own shipment resources and a visible spice opportunity, otherwise last. This is a bounded legal timing policy, not evidence of relative strength calibration.

Remaining scope

The battle-order follow-up connects first/last at a clean boundary between actual battles. It does not implement the separate aggressor mode discussed below.

Later battle aggressor intervention, normal/Black Market cyclic bidding, other ordered actions and partly completed movement remain unfinished. Once Around first after an already completed bid and first/Guild competing priority are guarded. Reacquiring and replaying Sapho while an existing movement protection remains is also guarded. Silent submission is simultaneous and receives no fabricated order or tie change.

The battle audit in the battle review found a real Stone Burner counterexample: a plan admitted with original aggressor tie priority can become allocation-ambiguous after late Sapho. A complete implementation needs the actual allocation continuation (and a usable, possession-independent late intervention boundary), not rejection based on an opponent's hidden plan. No aggressor handler has been enabled around that defect.

Verification

New source contribution review covers the pure helper and all four new rules test files (33 test cases including 960 helper reorder cases), plus four real room/SQLite recovery cases. Recovery exercises simultaneous duplicate Sapho requests with one successful CAS and one failed CAS, old/new-version replay, strict outbid sale, exact physical inventory, private projections, actual phase entry and Guild deferral through phase completion.

Browser and final regression outcomes from 7 September are recorded in the historical checkpoint below. The hourly maintenance automation remains removed. Reuse the server; restart only when an observed condition or change requires it, preserving saved games and verifying restoration.

13 September: first at a later clean movement boundary

The existing source contract already permits reordering the remaining unstarted participants between complete combined turns. The old global completed/shipped guard was narrower than that contract. The engine now checks only remaining participants and only retains the Advanced Guild-first guard while Guild is among them. No new timing ruling, saved field, player action shape or separate AI legality calculation is added.

Four new engine tests cover a real completed shipment before first, a genuine Advanced Guild turn that fully finishes, rejected partly started/queued turns, and all four private AI profiles. The existing Advanced engine fixtures now use the shared Advanced initializer instead of flipping a Basic game. A separate production-room SQLite test races duplicate first requests after a real completed shipment and proves one discard, private projections and intact completed-player custody. Focused checks pass; broad results are recorded in the checkpoint commit and private source-bound report. This is a bounded connected prototype.

Final checkpoint

1,631 rules/client/component tests and 152 multiplayer tests pass (1,783 total). Final rules run: /tmp/dune-sapho-full-tests3.log (59.50 s). Multiplayer run: /tmp/dune-sapho-multiplayer.log (18.70 s), with /tmp/dune-sapho-final-recovery2.log rechecking all four Sapho recovery cases after the early-Guild adapter correction. Typecheck, lint and production build pass in /tmp/dune-sapho-final-type2.log, /tmp/dune-sapho-final-lint2.log and /tmp/dune-sapho-final-build2.log. Earlier runs identified stale documentation assertions; those assertions and the generated guides now identify eight bounded handlers and two inactive faces. All five new test files and both fresh source/architecture reviews were read by the coordinating agent.

Twenty Basic games using ordinary production AI completed across 2–6 players and all four homogeneous profiles: 12,052 accepted actions, zero rejected candidates/stalls/exceptions/invariant failures, 94 setup actions and 537 actual JSON continuations. No test card-use policy or inventory/resource injection was used. Public Basic starts contain no Sapho, so this is a regression sample, not full-game Sapho or expansion verification or relative difficulty calibration. The runner /tmp/dune-sapho-base-fullgames.ts and its complete result, summary, diff and source fingerprints were reviewed; all 58 source/runner fingerprints were independently unchanged at completion. Combined hash b83fb0197e9f3fb0b0fab31cc360d88a9562459e97a0fd9bac7911ebd13cb141; result hash 06b9fdf1cedfb4341cb0868432946618b813602f842f603981458d51b8cdbea3. Later changes were the explicit Advanced Guild queue correction (covered by full regression and new direct tests), reference text and presentation. These games predate that final correction.

Desktop and 390×844 phone inspection verified the new panel, full readable Sapho inspector and last-bid action. In isolated room 8S3MRDEK, the human used Sapho-last, Hard Richese bid 1, and the human won Ornithopter for 2; version 38 had 18 human spice, one acquired card, one Sapho discard and one play log. A separate staged movement test used Sapho-last, the Hard opponent shipped four and finished, then the human completed its unchanged full turn; version 47 reached Spice Collection with an empty remaining queue, cleared protection and exactly one discard/play log. Both are staged component tests, not full expansion games. Before each staging the prior room JSON was backed up. Refresh restored the saved seat and state; the viewport was reset. The phone inspection also exposed a pre-existing masthead overflow: wrapping its controls removed document horizontal overflow (375 px viewport / 375 px content).

At 02:46 UTC, all 1,746 existing rooms were backed up, the idle human room checked, and the server restarted. Every saved version and SHA-256 state hash restored unchanged; HTTP health was 200 and the browser resumed the same room. The restart backup is /tmp/dune-maintenance-20260907T0246. This is manual authorized maintenance; no automation was recreated.