Apply user priority: save/recovery/privacy/custody assurance after all rules. Add quick types/lint, concise failure-preserving reporter, verbose mode, actual empty-execution guard, signal handling and focused verify name selection; compact canonical context/handoffs without mass moves. Tooling15, six negative CLI, named/empty source-bound smokes,206 doc links; same15-case278B vs2455B,2.35s vs2.36s no compute speedclaim. Native Advanced Ix/CHOAM47-card Stronghold profile: actual firstMentat/HMS/sixeffects,18native/four legalpolicies,five genuine2..6games3129actions/no rejection, human390px LAUDR2WNv14 bank2/personal1 plan and real battle. Earlier162/6513 checks before assurance amendment; finalquick25/build/guide pass. No new preservation/privacy audit or public/deployed/full-mode claim.
347 lines
22 KiB
Markdown
347 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. This is still a gated development profile.
|
||
`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.
|