Match original Ecaz sample snapshots to their native Occupy and Advanced assassination state. Preserve older absent-power samples and resume the original scenario instead of rejecting fresh saved output. Update stale fixture reactions and module expectations while retaining meaningful Banker guidance and positive legal commitments. Correct the unsupported rules-completion claim. Validation: typecheck/lint, 173 affected tests across 16 files, bounded independent source review, and one direct Ecaz continuation completed through 178 accepted actions. Runtime fingerprint 95d009d3957650b08bb24826b70aa5f00a74cdd9992b6a6c222f0665d3e3759c; documentation-only proof update a91ab248109bee74a74373fb544027a2e7cc8f178e26d2c9dad475a9618eb64d. Full rules, comprehensive assurance and deployed acceptance remain open. No saved-room or provider changes.
353 lines
22 KiB
Markdown
353 lines
22 KiB
Markdown
# Repeatable verification
|
||
|
||
Use the [development guide](DEVELOPMENT.md) 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.
|
||
|
||
## Current verification priority
|
||
|
||
The **2 October 2026** amendment supersedes the 26 September sequence: implement
|
||
all rules first; save/recovery, privacy and custody assurance and comprehensive
|
||
review follow afterward. They are not per-prototype gates. Keep legal rule
|
||
transitions, usable controls, minimal legal AI and changed-path runtime smoke.
|
||
Printed card/force/payment mechanics, existing authorization, secret protection,
|
||
no reset/deletion of existing games and deployment safeguards remain in force.
|
||
|
||
Use the [feedback/proof schedule](DEVELOPMENT.md#feedback-and-proof-schedule):
|
||
exact failing case first, related tests once at frozen batch closure with one
|
||
integration owner, full offline/integration proof and comprehensive review after
|
||
all rules. Earlier broad checks need an observed failure or concrete integration
|
||
risk. Do not repeat HTTP/save comparisons or seat-restoration loops for routine
|
||
rule checkpoints. Helpers run no shared checks mid-flight.
|
||
|
||
The recovery/backup/seat tools below remain available for final assurance and
|
||
authorized operations, not a checklist to repeat at every feature. Final
|
||
recovery, privacy, custody, complete administration and deployed/release
|
||
acceptance are deferred, not deleted. Historical sample counts retain their
|
||
dated/source-bound scope and are not fresh evidence for a later revision.
|
||
Existing mandatory CI, prototype-entry and deployment safeguards are unchanged.
|
||
|
||
## Verify the deployed application
|
||
|
||
The user requires testing the actual application at
|
||
**https://dune.procrastination.games**, added to the goal on 22 September 2026.
|
||
Local development, a local production build and container smoke tests do not
|
||
replace testing that deployed origin.
|
||
|
||
After relevant application changes are deployed, identify the running revision
|
||
or image digest and match it to the checkpoint under test. Record when testing
|
||
occurred, what revision actually ran, the routes/actions exercised, results and
|
||
remaining limitations. If the deployed revision is older, label the results for
|
||
that older revision; do not claim that new source passed deployed acceptance.
|
||
If access or deployment is unavailable, report the gap and keep acceptance open.
|
||
A pushed image is not a deployment. Do not make a separate live rollout a
|
||
per-prototype gate; deployed acceptance remains required after all rules and for
|
||
actual deployments. Follow [the manual TrueNAS update](TRUENAS.md#applying-an-update)
|
||
only after the image passes CI, the persistent volume is backed up, human play
|
||
reaches a safe point and required interactive approval is obtained.
|
||
|
||
For an authorized deployment, use a dedicated deployment agent if useful while
|
||
the integration owner continues other work. Supply the exact successful immutable
|
||
image tag; the agent changes only the `dune` app in Apps, retains its `/data`
|
||
volume, and reports the displayed revision and deployment-required continuity
|
||
before the checkpoint is called deployed.
|
||
|
||
If access, the backup or a safe point is missing, report the push as **not
|
||
deployed** and keep its production verification open rather than claiming the
|
||
Git revision label matches the pushed commit.
|
||
|
||
Use the production browser flow to verify relevant navigation and deep links,
|
||
bundled assets and rendering, HTTPS/proxy behavior, cookies and authentication,
|
||
room creation/join, rules selection, human/AI decisions, multiplayer updates,
|
||
private views and refresh/reconnection. Exercise changed gameplay and admin
|
||
operations through the real controls and server, with desktop/mobile coverage
|
||
where relevant. Do not rely solely on HTTP status codes or local test results.
|
||
Keep checks focused on the changed behavior and its dependencies; broad final
|
||
acceptance must cover the complete game and administration scope.
|
||
|
||
Create clearly identified QA rooms/seats and track their IDs privately. Protect
|
||
human games, private information, recovery credentials and logs. Admin tests
|
||
must use explicitly authorized admin access, with destructive or restoration
|
||
checks restricted to designated test records and appropriate recovery snapshots.
|
||
Do not reset production storage, interrupt live human play, weaken permissions
|
||
or restart the server merely to run a routine smoke test.
|
||
|
||
Actual production deployments retain their existing continuity safeguards.
|
||
A routine local content checkpoint or dev-server reload is not a mandate to
|
||
reaudit every saved seat. Comprehensive save/recovery/privacy/custody assurance
|
||
waits until all rules. Use additive migrations and the hosting procedure;
|
||
sequencing changes do not bypass completion, publication or provider approval.
|
||
Documentation-only checkpoints need documentation/link review, not an unrelated
|
||
production gameplay run. Record production evidence separately from the local
|
||
source-bound checks below, and repair runtime-specific failures before treating
|
||
the affected deployed feature as verified.
|
||
|
||
## Compact checks and source evidence
|
||
|
||
```sh
|
||
# Exact failing case first (file selection plus name regex).
|
||
node --import tsx tools/verify.ts --out /tmp/dune-new-case focused --focus test-workflow --name 'each filename filter'
|
||
# Related union at frozen batch closure; repeat --focus for another fragment.
|
||
node --import tsx tools/verify.ts --out /tmp/dune-new-focused focused --focus guild-payment
|
||
# Full offline proof after all rules or a justified broad integration checkpoint.
|
||
node --import tsx tools/verify.ts --out /tmp/dune-new-check check
|
||
# Final proof: build for app/build/dependencies, integration for HTTP/auth/persistence.
|
||
node --import tsx tools/verify.ts --out /tmp/dune-new-release check build integration
|
||
# Final AI work, not per-rule iteration; this study covers Basic base factions.
|
||
node --import tsx tools/verify.ts --out /tmp/dune-new-study base-games --games 20 --seed 20260913
|
||
```
|
||
|
||
`focused` accepts repeated `--focus` filename fragments and optional `--name
|
||
REGEX`, using the test runner's union/file-plus-name semantics. Use
|
||
`npm test -- <fragment> --list` before the run to inspect file selection; it does
|
||
not preview matching cases. Invalid selectors or a name that executes no cases
|
||
fail instead of producing false-green proof. Console output is compact; full
|
||
emitted command output remains in each private step log.
|
||
|
||
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
|
||
|
||
Saved-game and private-seat assurance in this section is scheduled **after all
|
||
rules**. Do not run every sample matrix or preservation command per prototype.
|
||
Existing genuine-game harness checks stay intact when a relevant game smoke
|
||
uses them; their presence does not require a separate assurance campaign.
|
||
|
||
### Reusable base and faction sample games
|
||
|
||
```sh
|
||
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-tleilaxu-skills --profile tleilaxu-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
|
||
# Optional-module and expansion rosters, two through six seats, Basic and Advanced.
|
||
node --import tsx tools/faction-games.ts --out /tmp/dune-new-homeworld --profile homeworld
|
||
node --import tsx tools/faction-games.ts --out /tmp/dune-new-nexus --profile nexus
|
||
node --import tsx tools/faction-games.ts --out /tmp/dune-new-homeworld-nexus --profile homeworld-nexus
|
||
node --import tsx tools/faction-games.ts --out /tmp/dune-new-choam-roster --profile choam-roster
|
||
node --import tsx tools/faction-games.ts --out /tmp/dune-new-ecaz-roster --profile ecaz-roster
|
||
node --import tsx tools/faction-games.ts --out /tmp/dune-new-ix-roster --profile ix-roster
|
||
node --import tsx tools/faction-games.ts --out /tmp/dune-new-ecaz-cards --profile ecaz-treachery
|
||
node --import tsx tools/faction-games.ts --out /tmp/dune-new-moritani-assassinate --profile moritani-assassinate
|
||
node --import tsx tools/faction-games.ts --out /tmp/dune-new-choam-nexus --profile choam-nexus
|
||
node --import tsx tools/faction-games.ts --out /tmp/dune-new-ecaz-nexus --profile ecaz-nexus
|
||
node --import tsx tools/faction-games.ts --out /tmp/dune-new-ix-nexus --profile ix-nexus
|
||
node --import tsx tools/faction-games.ts --out /tmp/dune-new-combined-nexus --profile combined-nexus
|
||
node --import tsx tools/faction-games.ts --out /tmp/dune-new-combined-homeworld-nexus --profile combined-homeworld-nexus
|
||
node --import tsx tools/faction-games.ts --out /tmp/dune-new-nexus-three --profile nexus --players 3 --rules advanced
|
||
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 the base, Homeworld, Nexus, combined
|
||
`homeworld-nexus`, expansion-roster, paired-Nexus, independent Ecaz-card or
|
||
Leader Skills profiles. The `combined-nexus` and
|
||
`combined-homeworld-nexus` profiles support `--players 5`
|
||
or `6` only. Omission or `all` retains every roster in a selected profile. The fixed
|
||
base roster adds Atreides, Harkonnen, Fremen, Emperor, Guild and Bene Gesserit
|
||
in that order. These are sample rosters, not the only rules-permitted
|
||
player-count configurations. Each optional module profile runs two through
|
||
six base factions under Basic and Advanced using the actual setup seams. The
|
||
three expansion-roster profiles also run Basic and Advanced with their
|
||
respective physical expansion enabled: CHOAM/Richese start with CHOAM then
|
||
Richese, Ecaz/Moritani with Moritani then Ecaz, Ixian/Tleilaxu with Ixians
|
||
then Tleilaxu. Subsequent seats extend each to six without changing existing
|
||
fixed four-seat samples. Their seed offsets are 68–77, 78–87 and 88–97.
|
||
`ecaz-treachery` reuses the two-through-six-seat Ecaz/Moritani roster with the
|
||
independent three-card Treachery variant instead of Nexus Cards. Basic and
|
||
Advanced seed offsets are 136–145; default/all keeps its original six games.
|
||
The runner counts all three physical cards and resume requires the variant
|
||
marker and exact roster. Original `ecaz-treachery` and `ecaz-roster` snapshots
|
||
retain their native Ecaz Occupy and, in Advanced, Moritani assassination state
|
||
under their own scenario names. Older snapshots with both native powers absent
|
||
remain resumable without adding them or inventing ability history; partial native
|
||
state and unrelated module overlays are not admitted. Resume continues the saved
|
||
turn, phase and custody rather than running setup again. These are still gated
|
||
development profiles.
|
||
`moritani-assassinate` runs only Advanced with Moritani followed by Atreides,
|
||
Emperor, Fremen, Guild and Bene Gesserit as seats are added. Harkonnen and
|
||
other optional modules remain outside this explicit development preview.
|
||
Five scenario offsets 146–150 leave earlier profiles unchanged. A resumed
|
||
snapshot must retain both the preview and its authoritative ability state;
|
||
the external physical census includes each public set-aside Traitor Card after
|
||
its actual Mentat replacement.
|
||
`choam-nexus`, `ecaz-nexus` and `ix-nexus` reuse the respective expansion
|
||
rosters with Nexus Cards enabled at seed offsets 98–107, 108–117 and 118–127.
|
||
`combined-nexus` selects five or six actual expansion factions and all three
|
||
expansion decks with Nexus Cards in Basic and Advanced. Five seats leave Richese
|
||
absent so a player can remain unallied and draw; six seats contain every expansion
|
||
faction. Their seed offsets are 130–131 and 128–129 respectively.
|
||
`combined-homeworld-nexus` reuses the same four rosters with physical Homeworld
|
||
custody added, at offsets 132–135. Its public arrival-priority gate can reject a
|
||
route where Ecaz Ambassadors and Moritani Terror both react; the bot must choose
|
||
another legal route. Neither profile establishes those pending source priorities.
|
||
The original six default samples are unchanged. Output names include the player count.
|
||
Homeworld's original four-seat seed offsets remain 36–37; its other rosters
|
||
use 48–51 and 54–57. Nexus's six-seat offsets remain 38–39; its smaller
|
||
rosters use 40–47. The combined module uses offsets 58–67. These samples
|
||
do not open public module or expansion starts or assert complete interaction
|
||
coverage.
|
||
|
||
At base seed `20260929`, the Ecaz-card profile completed all ten
|
||
two-to-six-seat Basic/Advanced samples with 3,768 accepted actions, no
|
||
rejected candidates and 95 JSON continuations. The six-seat Advanced trace
|
||
includes Recruits, Reinforcements and Harass & Withdraw actual uses. The
|
||
private source-bound report is
|
||
`/tmp/dune-ecaz-treachery-matrix-final-20260929/report.json`. The first
|
||
matrix exposed a non-serializable unlocked advisor stance; its corrected
|
||
writer paths are documented in
|
||
[the implementation log](IMPLEMENTATION_STATUS.md#29-september-2026--ecaz-card-variant-full-game-integration-samples).
|
||
This is not expansion release evidence.
|
||
|
||
At the same base seed, five Advanced Moritani assassination preview games
|
||
completed with 2,511 accepted actions, zero rejected candidates and 65 JSON
|
||
continuations. The six-seat game reached two actual private
|
||
assassination opportunities, both declined; it did **not** naturally test
|
||
reveal and replacement. Focused engine/custody regressions cover that
|
||
physical path. Private report:
|
||
`/tmp/dune-moritani-assassinate-matrix-20260929/report.json`. This is
|
||
sampled continuation, not a duration ruling or public expansion readiness.
|
||
|
||
All-AI Nexus samples now make public reciprocal offers as well as accepting
|
||
them, so an actual alliance can form without a human proposer. At the
|
||
20260927 seed, each six-seat sample made six alliance actions and completed;
|
||
no Nexus Card choice occurred at those tables. The two-to-six-seat matrix
|
||
completed without rejected actions and with JSON restores throughout; the
|
||
three-seat Advanced sample and five-seat Basic sample reached actual
|
||
`nexusCardChoice` actions. The focused Nexus alliance regression exercises
|
||
the subsequent draw when a seat remains unallied. These samples do not
|
||
establish complete card-effect coverage.
|
||
|
||
At the 20260927 seed, all ten Homeworld samples completed with no rejected
|
||
actions and repeated JSON restores. The six-seat Basic game reached actual
|
||
Junction offers/shipments and a Caladan reinforcement decision; these
|
||
observations do not certify every Homeworld occupation or expansion
|
||
interaction.
|
||
|
||
At the same seed, all ten combined Homeworld/Nexus samples completed without
|
||
rejected actions and with JSON restores. The five-seat Advanced game reached
|
||
three Nexus Card choices and eight Homeworld shipments in one physical game,
|
||
including 26 restores. This does not certify every interaction between the
|
||
two independent modules or either module's unfinished card effects.
|
||
|
||
`--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.
|
||
Homeworld, Nexus, independent Ecaz-card, Advanced Moritani assassination and
|
||
combined snapshots resume only when their saved modules and fixed rosters
|
||
match a supported profile; other optional-module combinations remain
|
||
excluded. An edited snapshot with a removed module can match a different
|
||
fixed profile, so verify its original private report before relying on
|
||
resumed provenance.
|
||
|
||
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](BOT_ARRIVAL_PREFLIGHT.md)
|
||
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
|
||
|
||
```sh
|
||
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. When a
|
||
targeted authorized storage operation warrants a baseline, snapshot the current
|
||
set rather than reusing historical room counts. Routine rule checkpoints do not
|
||
require these comparisons; comprehensive assurance follows all rules.
|
||
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.
|
||
|
||
The explicit `--profile choam-skills` runs Basic CHOAM and base opponents for
|
||
two through six players (ordinals 31–35), retaining the full skill module and
|
||
native 35-card Treachery deck; see [CHOAM integration](CHOAM_LEADER_SKILLS.md).
|
||
|
||
The explicit `--profile ix-skills` runs genuine Basic Ixian full-deck setup for
|
||
two through six players, with Tleilaxu and base opponents. It preserves ordinals
|
||
26–30 and full custody/private saved continuation; see [Ix integration](IX_LEADER_SKILLS.md).
|
||
|
||
## 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:
|
||
|
||
```json
|
||
{"baseUrl":"http://127.0.0.1:3000","isolatedQa":true,"seats":[{"code":"ABCDEFGH","playerId":"fixture-seat-id","version":4,"token":"fixture_session_token"}]}
|
||
```
|
||
|
||
```sh
|
||
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.
|
||
During final assurance, pair it with saved-game comparison and relevant browser
|
||
acceptance; it is not a repeated per-prototype seat audit.
|