Admit the genuine private setup profile for Basic Moritani with base opponents, exactly the Ecaz expansion and no other optional modules. Keep all14 physical skills, private two-card offers, starting-card/Traitor order and Moritani's final six-force placement. Public starts and complete-mode/publication gates remain. Share public profile eligibility across Banker, Diplomat, Sandmaster movement and worm riding, Smuggler shipping/collection, Bureaucrat payments, Planetologist controls/bots and Suk/Rihani/Sandmaster battle settlement. Admission reads no hidden cards or random deal. Preserve base/CHOAM boundaries and existing source questions; no full AI implementation, strategy or calibration changes. Genuine setup regressions cover all14 assignments, legal profiles and guards, Terror Assassination death and exact skill return, optional own revival draw/privacy, Sabotage, movement controls/bots, Smuggler shipment and Bureaucrat paid bribes. Battle actions cover Rihani exchange, Sandmaster spice, Banker funds, Suk casualties and Smuggler collection. Actual enemy alliances prove losing-ally retention excludes mandatory Planetologist Special and Diplomat-copy disposal. A real worm/Nexus ride collects Sandmaster spice once. Authenticated in-memory SQLite restarts and concurrent skill choices preserve one assignment, private offers, saved seats and final Moritani placement. Conserved staged positions are explicitly distinct from played phase histories. Add a reproducible moritani-skills profile to the existing faction-game runner, including fixed2-6-player Basic rosters, seed offsets16-20 and saved resume. Verify expected module presence, all14 physical skills and ordinary Traitor custody alongside existing card/force/private-view checks. Default six expansion samples and base samples retain their rosters/ordinals. No live DB is used by these complete-game samples. CLI regressions check interrupted continuation and Advanced refusal; corruption tests catch lost cards and entire module loss. Independent review caught an old all-base worm guard and a sample checker that missed whole-module deletion; both fixed with meaningful regressions and reviewed. Initial edits had a stale helper reference and final lint found an unused import; these were corrected. Types, lint, all 5034 offline tests and build pass on stable final source. Five genuine complete-game samples passed with no rejected actions:2 players189 actions/5 restores,3 players53/1,4 players862/23, 5 players116/3 and6 players1338/36. These are legality samples, not calibration or exhaustive faction/card acceptance. No endpoint/auth/storage changes; existing HTTP suite not repeated, while new authenticated storage and live browser actions exercise the newly admitted profile through production boundaries. Browser created a fresh Basic human Moritani/Easy Emperor lobby, then the existing backed-up local initializer started that named ready room without replacing seats. Human inspected both Killer Medic bands, assigned Lupino Ord, chose a private Traitor and placed six in Polar Sink after all other setup. Refresh preserved the two public skills, own hand/Traitor and6 deployed/14 reserves at pending Storm. Mobile skill panel339px, client/scroll337; viewport restored afterward. Screenshot capture timed out, so full visual/screen-reader acceptance stays open. All 1580 opening games, 3348 saved seats and auxiliary rows remain identical. One isolated QA game adds one human seat and entry receipt; its row is unchanged after setup through refresh, with all seats unchanged. SQLite integrity and foreign keys pass. No server restart, migration, reset or recurring automation. Existing unfinished Leader Skill bands and material rulings remain explicit in the new integration guide and internal checklist. Private evidence: 20260921-moritani-skills. Verified source tree: d5078661ecc2199b2bbfebd18034b16585d06410a697a78dc514bfa5b3b77a1c
8.3 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 base and faction sample games
node --import tsx tools/faction-games.ts --out /tmp/dune-new-faction-games
# Ten genuine base samples: Basic and Advanced at each player count.
node --import tsx tools/faction-games.ts --out /tmp/dune-new-base-games --profile base
# Basic Moritani with the full Leader Skills deck, two through six seats.
node --import tsx tools/faction-games.ts --out /tmp/dune-new-moritani-skills --profile moritani-skills
node --import tsx tools/faction-games.ts --out /tmp/dune-new-base-three --profile base --players 3 --rules advanced
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
Default and --profile all retain the original six fixed CHOAM/Richese,
Ecaz/Moritani and combined Basic/Advanced samples. --profile base selects ten
additional samples: Basic and Advanced with two through six players.
--players 2..6 narrows only that base profile; omission or all retains all
five counts. The fixed base roster adds Atreides, Harkonnen, Fremen, Emperor,
Guild and Bene Gesserit in that order. These are sample rosters, not an assertion
that these are the only rules-permitted player-count configurations.
--profile moritani-skills adds five Basic samples with Moritani, then Emperor,
Guild, Harkonnen, Fremen and Bene Gesserit. --players also narrows this profile;
Advanced requests fail before running. Its seed offsets are 16–20, leaving
existing samples unchanged. The full fourteen-card skill census and ordinary
Moritani/base Traitor census are checked throughout. --resume preserves this
explicit profile; other optional modules still fail its admission checks.
All samples use genuine setup and saved AI profiles, cycling Easy, Medium,
Hard and Brutal by seat. Smaller games necessarily contain fewer profiles;
the matrix collectively exercises all four. Filters retain each scenario's
seed offset: the original six use 0–5; base uses
6 + 2 × (players − 2) + Advanced, where Advanced is 0 or 1. --seed defaults to 20260926;
--max-actions defaults to 3500 accepted actions per game. Every action checks
physical card custody (including unsold auction cards), nonnegative integer
forces/spice, twenty-force totals and the distinct Fremen/Emperor/Ixian elite totals
and subsets. Base samples also check the exact Traitor inventory after dealing
has finished; expansion Traitor/Face Dancer zones are not certified by this
check. Every rejected candidate must leave its input unchanged. Every 37 actions
checks all private views after JSON restoration and absence of rival hand,
spice, Traitor and Face Dancer fields. Rejected candidates remain visible in private traces even when
a later candidate succeeds. The ordinary AI arrival adapter
filters known supported-scope reaction conflicts before attempting an action;
remaining rejections are still reported, never hidden by the runner. 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 base or expansion scenario snapshot with saved AI profiles and records its
SHA-256; it cannot be combined with profile/rules/player-count 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.