Files
Dune/docs/VERIFICATION_WORKFLOW.md
T
Quintine 903d861170 Prevent saved CHOAM movement arrival deadlocks
Preflight ordinary movement through the existing arrival quote before creating new Ornithopter escrow or opening Ixian, Fremen and CHOAM prevention windows. An explicit legacy CHOAM decline can return an uncommitted unsupported arrival for another choice without consuming movement or touching forces, spice, cards or tokens. Preserve an existing Ornithopter and retire it exactly once on a legal replacement move. Keep dedicated Ambassador relocation handling and Karama cancellation validation before cost; unrelated exceptions remain atomic. Simultaneous Ambassador/Terror priority still awaits the recorded material interpretation, with no invented ordering.

Add reusable offline faction-game samples with genuine Basic/Advanced setup, all four AI profiles, physical custody checks, JSON restorations, private traces and failed snapshots. Source-bound reports and input snapshot hashes make fresh and resumed samples repeatable; document that a resumed continuation starts a new seeded stream and does not prove input setup provenance.

Validation: independently reviewed fresh declaration, native cancellation, supported single arrivals, legacy retry and card custody tests. Two production SQLite tests cover authenticated private restoration, stale/duplicate/wrong-owner rejection, resource conservation and concurrent version races. Typecheck, lint, 4583 offline tests, production build and 43 HTTP tests passed. Retain the initial failed check log for the corrected numeric-sort lint issue.

All six fresh samples complete. CHOAM Basic 1054 actions/28 JSON restores, CHOAM Advanced 225/6, Ecaz Basic 91/2, Ecaz Advanced 523/14, all-three Basic 476/12, all-three Advanced 1303/35 with a turn-six CHOAM win. Combined Advanced has 46 guarded arrival candidates with legal alternatives. The exact prior 614-action failed snapshot separately finishes after 691 additional actions/18 restores and 39 guarded candidates. These are bounded paths, not complete faction or combination certification. Gameplay source hashes match the final checkpoint; later evidence-only documentation and recovery-test lint edits are explicit.

After the reported outage, all 632 opening games and original seat/recovery records were preserved (665 after HTTP tests); integrity and foreign keys passed. Existing Ecaz and Ixian browser seats restored their same private hands, resources and pending choices after reload. This is browser restoration evidence, not a staged arrival-return claim. The healthy server was reused; no restart, database reset, recurring automation or publication.

Verified source tree: 550221850f4802c41155f7bbc35d623965bc7db3330825636d50f26bb42868f8
2026-09-13 23:15:00 +10:00

6.1 KiB

Repeatable verification

Use the development guide to choose checks appropriate to the change. These wrappers retain the existing test runner and simulation harness; they do not replace rules, browser or release acceptance.

Compact checks and source evidence

node --import tsx tools/verify.ts --out /tmp/dune-new-focused focused --focus guild-payment
node --import tsx tools/verify.ts --out /tmp/dune-new-check check
# Add build for app/build/dependency changes, integration for HTTP/auth/persistence.
node --import tsx tools/verify.ts --out /tmp/dune-new-release check build integration
# Only for relevant AI/gameplay work; the existing study covers Basic base factions.
node --import tsx tools/verify.ts --out /tmp/dune-new-study base-games --games 20 --seed 20260913

Each output must be a new directory outside the checkout, with an existing parent. It is created with private permissions. Full command output stays in step logs; report.json records commands, exit codes, timings, HEAD and a content fingerprint of tracked and nonignored untracked files before and after the run. Ignored local credentials, saved games and build caches are excluded. Do not supply secrets in command arguments. A failed child stops subsequent steps. Changed source or HEAD invalidates a successful run; finish all source/doc edits before broad checks. This checks the two observed snapshots, not changes made and reverted between them, nor the contents of dependencies, ignored files or an external HTTP server. An interrupted or incomplete report is never evidence of success.

Saved games and online backups

Reusable faction sample games

node --import tsx tools/faction-games.ts --out /tmp/dune-new-faction-games
node --import tsx tools/faction-games.ts --out /tmp/dune-new-combined --profile combined --rules advanced --seed 20260926
node --import tsx tools/faction-games.ts --out /tmp/dune-new-resume --resume /private/failed-combined-advanced.json

This offline tool runs six fixed CHOAM/Richese, Ecaz/Moritani and combined Basic/Advanced samples from genuine setup, using all four AI profiles. Filters retain each scenario's seed offset. --seed defaults to 20260926; --max-actions defaults to 3500 accepted actions per game. Every action checks physical card and force custody; every 37 actions checks all private views after JSON restoration. Rejected candidates remain visible in private traces even when a later candidate succeeds. Samples are development evidence, not calibration or complete rules certification.

The output is a new private directory outside the checkout. It contains private traces, incomplete-game snapshots, results.json and a source-bound report.json. An incomplete game or changed source exits nonzero. Resume requires a matching fixed-scenario snapshot with saved AI profiles and records its SHA-256; it cannot be combined with profile/rules filters. Its action budget starts at the snapshot, and its random stream restarts from the supplied seed plus scenario offset. Check setup provenance against the original report: accepting a supplied snapshot does not prove it came from genuine setup. No live room or database is accessed.

Preservation commands

node --import tsx tools/saved-games.ts snapshot --db /absolute/games.sqlite --out /private/new-baseline --backup
node --import tsx tools/saved-games.ts compare --db /absolute/games.sqlite --baseline /private/new-baseline/snapshot.json

The source database is opened read-only. Snapshots store room versions and state hashes, not private game state. New rooms are allowed; every changed or missing original room fails comparison. Legitimate human play can change a room: investigate and document it, never overwrite progress to make a comparison pass. Snapshot the current set before each maintenance operation so newly created rooms are protected. Online backup includes WAL contents and requires Node 22.16 or newer; snapshot and comparison retain the project's Node 22.13 minimum. Backup files contain private state and session records, remain outside Git, and never overwrite an earlier run. This tool does not delete, reset or restore the live database.

Authorized reset, 13 September 2026

The user requested clearing all old local games and starting a new checkpoint. With no development server running, a verified online backup preceded a single transaction deleting 3,644 rooms and cascading their seat/recovery/entry records. Schema, migrations and Wrangler state files were preserved. All five application tables were empty afterward; foreign-key validation passed.

Private archive: /home/quintine/.local/share/dune/checkpoints/20260913-before-reset/. Fresh empty database backup and snapshot: /home/quintine/.local/share/dune/checkpoints/20260913-fresh-baseline/. These machine-local paths are operational records, not portable repo artifacts. Old room IDs in historical browser evidence no longer identify active local games. Future games must be preserved. This was a one-time user-authorized reset, not a maintenance strategy or permission to clear future games.

Private-seat restoration

Create a private JSON file (mode 0600) outside the checkout with this structure; substitute credentials only in that private file, never in a command or tracked doc:

{"baseUrl":"http://127.0.0.1:3000","isolatedQa":true,"seats":[{"code":"ABCDEFGH","playerId":"fixture-seat-id","version":4,"token":"fixture_session_token"}]}
node --import tsx tools/restore-seats.ts --config /private/qa-seats.json

Use deliberately isolated, stable human QA rooms. The server's GET route can resume bots or automatic work, so this is not a generally side-effect-free read and must not probe arbitrary human games. Requests use loopback origins only, reject redirects and time out. Checks require the expected room, seat and version, the owning seat's private fields, and absence of selected rival private fields. No session tokens, response bodies or hands are printed. This is HTTP seat restoration, not recovery-key rotation, exact hand-content proof, a complete privacy audit or browser rendering. Pair it with saved-game comparison and feature-specific browser acceptance.