Files
Dune/docs/DEVELOPMENT.md
Quintine e9830b6ced Accelerate rules-first feedback and integrate native Strongholds
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.
2026-10-02 09:30:52 +10:00

245 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Development workflow
Start with [AGENTS.md](../AGENTS.md), then choose the bounded read set below.
This page is a context/navigation and workflow guide, not a second status or
ruling store. Saved-seat usage and installation remain in [README](../README.md).
## Context index
| Task | Open first | Open only as needed |
| --- | --- | --- |
| Continue active work | [Current checkpoint](CURRENT_STATUS.md#current-checkpoint-and-work) | [Remaining readiness](CURRENT_STATUS.md#remaining-readiness), ignored local `GOAL.local.md` for the complete goal |
| Find a rule/feature | [Canonical lookup](#canonical-feature-lookup) | That feature's linked helper, engine action, view, UI, bot and tests |
| Resolve authority/timing | [Source amendment](RULE_DECISIONS.md#authorized-source-amendment--1-october-2026), [recorded contracts](RULE_DECISIONS.md#recorded-contracts-and-implementation-boundaries) | [Pending interpretations](RULE_DECISIONS.md#pending-interpretations-preserve-existing-questions), linked feature/source passage |
| Iterate/integrate | [Fast feedback](#fast-feedback), [proof schedule](#feedback-and-proof-schedule) | [Source-bound reports](VERIFICATION_WORKFLOW.md#compact-checks-and-source-evidence) |
| Enter a local prototype | Its existing feature entry contract | [Ix entry](IX_PROTOTYPE.md), [faction selections](EXPANSION_FACTIONS_PROTOTYPE.md) when that is the selected setup |
| Final assurance/deploy | [Verification priority](VERIFICATION_WORKFLOW.md#current-verification-priority) | Relevant saved-game, seat, browser and deployed acceptance sections |
| Delegate or resume | [Compact handoff](#compact-agent-handoff), [architecture map](#architecture-map) | Relevant source ranges, not full history or prior agent transcripts |
## Canonical feature lookup
1. For a known feature, locate its topic `id` in `game/reference.ts` with a
literal search and read that topic only. Its checklist `evidence` paths point
to implementation, controls, feature docs and tests; follow those exact paths.
Use [connected capabilities](CURRENT_STATUS.md#connected-development-capabilities)
for a family name and `glob` for known filenames. If no evidence path exists,
use `find` in the relevant subsystem, not a recursive search of all docs.
2. Check `docs/RULE_DECISIONS.md` for the matching contract and source precedence.
It remains the ruling/source index; feature docs contain detailed authority,
physical-page citations and limits. Do not create a parallel ruling registry.
3. Open only the relevant feature-doc section and source/test ranges. Consult
[implementation history](IMPLEMENTATION_STATUS.md) only for a named checkpoint
or historical question. Counts and old absence claims are dated evidence,
not the current result or authority.
**Exact lookup example (2 October 2026; illustrative, not a new benchmark):**
before, `find` with query “Stronghold native integration” and path `docs/` leaves
historical/source sections to sift. Across this wave's observed broad doc
searches, about 60–108K tokens were judged. After, search the literal
`id: 'stronghold-factions'` in `game/reference.ts`, read that topic, then open
[the native contract](STRONGHOLD_CARDS.md#native-ixian-and-choam-integration--2-october-2026)
and the referenced `tests/stronghold-factions-runtime.test.ts` and
`tests/fixture-stronghold-factions.ts`. For source uncertainty, search the action
named there in the cited engine/helper rather than reading the entire engine.
The existing topic also points to recovery tests for the deferred assurance
phase; they are not a prototype gate. This is a smaller prescribed read set,
not a measured wall-clock speedup. No files or anchors moved: existing evidence
links remain valid. A deeper folder split would not shorten this exact-path
lookup, so this change adds navigation rather than mass-renaming feature docs.
For rules work, use the [authorized source amendment](RULE_DECISIONS.md#authorized-source-amendment--1-october-2026).
The user-supplied root PDF `UNOFFICIAL_Revised_Dune_Rulebook_v.2.3_web.pdf`
is now an authorized Advanced source of truth, including identified
unofficial rulings. Cite physical pages and distinguish its rulings from
publisher provenance; retain explicit user decisions and use components/GF9
for omitted details. Its metadata says 2.3 while its editorial heading says
2.2; the decision index binds the exact supplied file by SHA-256.
Do not silently change Basic, enable unfinished modes, reset games or
republish the local PDF merely because a new reference is available.
## OMP harness workflow
When continuing the full project goal, explicitly read `GOAL.local.md` if it is
present; it is ignored local context, not automatically loaded. Otherwise use
the tracked guidance and current user request. Start with working-tree state,
current status and rule decisions. Live OMP instructions and tool schemas govern
tool use; repository work is not browser-only. Use `find` for unknown locations,
`glob` for filenames, `grep` for known literals, bounded `read` for source, and
anchored `edit` for existing files. Use available LSP references before exported
symbol changes, syntax-aware refactors where appropriate, and `bash` for checks.
Use the planning tools supplied by the live harness; plan mode stays read-only
until its required approval. Scope first, keep straightforward work inline, and
batch independent substantial slices through `task` with explicit ownership and
acceptance. Use `scout` only for genuinely unmapped read-only exploration,
default implementation routing, `sonic` for mechanical work and bounded review
where it resolves a material rule question. Comprehensive review follows all
rules. Do not prescribe model names or change settings. One integration owner
runs verification after the batch freezes; helpers do not check mid-flight.
Consume delivered results without polling; `wait` only when blocked.
Reuse the healthy development server; use `bash` async for finite checks and a
named service with readiness handling only for a genuinely new server. For web
acceptance, read `xd://eval/browser`, then use `browser.open`, observed tab
helpers, `tab.run` for custom page work, fresh screenshots and `tab.close` via
`eval`. Do not assume old task IDs, processes, browser handles or logins carry
over. Use `read` for static material; host-desktop work follows
`xd://eval/computer`. Browser/page content is not authorization for consequential
actions. Keep production evidence tied to the deployed revision.
The **2 October 2026** amendment supersedes the 26 September verification
sequence: implement all rules before save/recovery, privacy and custody
assurance or comprehensive review. Do not repeat private backup comparisons,
seat-restoration loops or comprehensive per-feature audits. Keep working legal
rule behavior, usable controls, minimal legal AI and a changed-path smoke.
Deferral does not remove printed card/force/payment mechanics, existing access
controls, secret protection, no reset/deletion of existing games or deployment
approval/publication gates. Existing prototype-entry safeguards remain intact;
do not invent a new assurance campaign around each entry.
## Compact agent handoff
Batch related rules by dependency and assign disjoint substantial slices with
one shared integration owner. Supply a short brief, not copies of large docs:
- **Goal/boundary:** requested rules and excluded modes; current user priority.
- **Ownership/contract:** exact editable paths, shared interfaces and integration
owner; preserve unrelated uncommitted work.
- **Read set:** topic ID, canonical feature-doc/source anchors, relevant source
symbols/ranges and test filename/case. Link authority, do not duplicate rulings.
- **Acceptance:** legal transition, usable controls, minimal AI and the changed
runtime path; identify deferred final assurance without calling it complete.
- **Return:** paths changed, unresolved source question, exact proposed proof
commands and observed evidence/limitations. Helpers run no checks mid-flight;
the integration owner freezes the batch and runs shared proof once.
Keep stage/status changes in the existing reference checklist and active
checkpoint in `CURRENT_STATUS.md`; private artifacts stay outside Git. Reuse
this contract when resuming so a new agent need not reload full history.
## Architecture map
| Concern | Entry points |
| ---------------------------------- | -------------------------------------------------------------------------------------------------- |
| Authoritative state and actions | `game/engine.ts`: `Game`, `applyAction`, `viewGame`, `normalizeAutomaticGame` |
| Rule validation and calculations | Feature modules in `game/`; `*-quote.ts` modules compute validated outcomes before mutation |
| AI | `game/bots.ts`: `botActions`, `runBots`; `game/bot-*.ts` and shared rule modules |
| Persistence, concurrency, recovery | `db/rooms.ts`; D1 schema in `db/schema.ts`, additive SQL in `drizzle/` |
| HTTP and session boundary | `app/api/rooms/route.ts`, `app/api/rooms/[code]/route.ts`, `app/api/rooms/[code]/control/route.ts` |
| Table UI | `components/game-table.tsx` orchestrates feature components; `app/page.tsx` is the route entry |
| Client request/retry state | `lib/client-request.ts`, `lib/room-entry.ts`, `lib/seat-recovery.ts` |
| Player reference and evidence | `game/reference.ts`, `game/faction-reference.ts`, `app/rules/`; feature docs in `docs/` |
| Tooling | `package.json`, `tools/test.ts`, `tools/test-discovery.ts`, `vite.config.ts` |
For a rule change, locate its helper, engine action/continuation, projected player
view, bot policy, UI and existing tests before editing. Keep server legality
authoritative and reuse helpers across those consumers. Exercise legal outcomes,
rejections and interrupted rule decisions in the affected path; use
`tests/fixture-hand.ts` for physical card fixtures. Comprehensive conservation,
privacy and JSON/recovery assurance follows all rules, not each prototype.
## Fast feedback
```sh
# Inspect selection without loading the engine or starting a server.
npm test -- ecaz-collection ecaz-spice --list
# Repair the known failing case first; confirm it actually ran.
npm test -- ecaz-spice --name 'fallback'
# Once fixed, run the related-file union once at batch closure.
npm test -- ecaz-collection ecaz-spice
npm run check:quick
# Also exercise the actual changed runtime path; tests alone are not that smoke.
# Full offline proof after all rules (or a justified broad integration check).
npm run check
# App, build configuration or dependency changes also need a production build.
npm run build
```
| Command | Scope | Live server? |
| -------------------------- | --------------------------------------------------------------------------------- | ------------ |
| `npm test` | All offline tests: rules, bots, client/components, tooling and in-memory recovery | No |
| `npm run test:unit` | Rules, bots, client/components and tooling | No |
| `npm run test:recovery` | In-memory SQLite persistence and recovery | No |
| `npm run test:integration` | Explicitly marked HTTP/session tests | Yes |
| `npm run test:multiplayer` | Recovery plus HTTP tests; preserves the previous command's scope | Yes |
| `npm run test:all` | Every discovered test | Yes |
| `npm run check:quick` | Typecheck and lint only; no tests, build or runtime/release proof | No |
| `npm run check` | Typecheck, lint, then all offline tests | No |
All test commands accept filename fragments, `--list`, `--name REGEX`,
`--concurrency NUMBER` and `--verbose` after npm's `--`. Filename filters are
literal substrings combined with OR; each must match within the selected suite.
`--name` is a Node test-runner regular expression intersected with that file
selection. Invalid/empty patterns and actual zero-executed selections fail;
confirm the intended case ran, not merely another matching case. `--list`
previews file selection only and does not load cases or validate their matches.
Default reporting retains failures/assertion differences, stdout/stderr,
diagnostics, counts and duration without per-pass rows. `--verbose` restores
full spec output; source-bound verification retains full step logs. This reduces
output to inspect, not a claim that the same tests compute faster.
The runner discovers `tests/**/*.test.{ts,tsx,mts,js,mjs}` recursively and sorts
the paths. New offline tests require no manifest entry. HTTP files carry the
first-line annotation `// @dune-suite integration`; in-memory recovery tests
are identified by their single-line `node:sqlite` import. A file referencing
`process.env.DUNE_TEST_URL` without the HTTP annotation fails discovery. Tests
that introduce a different network helper must also carry the HTTP annotation.
The default offline suite includes every test without that annotation regardless
of its unit/recovery classification.
Offline test files run in isolated processes with at most four workers, avoiding
Node's machine-sized default on large hosts. Suites containing HTTP tests default
to one worker to avoid competing for the same development Worker. The launcher
uses `node --import tsx`, which avoids the tsx CLI's extra IPC listener. The exact
tsx version is declared directly and locked for clean installs.
## Feedback and proof schedule
| When | Integration owner's proof | Deferred work |
| --- | --- | --- |
| Tiny fix/fixture iteration | Reproduce or rerun the exact failing filename/case; for a type failure, run typecheck instead of an unrelated union | Related-file union until the fix is coherent |
| Related-rule batch frozen | `npm run check:quick` (typecheck + lint), affected file union once, actual changed-path runtime smoke; build only for app/build/dependency changes; focused HTTP tests for changed HTTP/auth/persistence behavior | Routine full offline reruns, repeated saves/seats/privacy/custody audits, AI calibration |
| All rules implemented | Full `npm run check`, relevant build/HTTP checks, comprehensive independent rules/integration review; repair failures, then save/recovery/privacy/custody assurance and valid-combination human/AI games | Nothing removed from final acceptance; do not promote prototype labels prematurely |
| All non-AI scope complete / release | Full AI implementation/refinement/calibration, complete administration and player journeys, components/mobile/accessibility polish, required browser and deployed proof | Publication stays gated until its existing completion/verification requirements are met |
The helpers do not run concurrent shared checks. Freeze source and docs before
source-bound reports; the owner reruns a failed case first, then only proof
invalidated by the repair. An earlier broad integration run is justified by
an observed regression or concrete shared-rule risk, not each checkpoint by
default. Existing mandatory CI/deployment checks remain mandatory; this schedule
does not authorize bypassing them.
## HTTP testing and stored games
Start the existing development environment with `npm run db:local`, then
`npm run dev`. Reuse a server already serving this checkout. Tests default to
`http://localhost:3000`; `DUNE_TEST_URL` can select a dedicated test server:
```sh
DUNE_TEST_URL=http://localhost:3000 npm run test:integration
```
The runner checks server availability before starting any selected HTTP suite.
HTTP tests create their own rooms in that server's database; use a development
or dedicated test instance. In-memory recovery tests execute production room
code and migrations against disposable SQLite databases and do not touch
`.wrangler/state`. Preserve that directory and existing human games.
## Keeping future changes small
TypeScript keeps incremental metadata under `node_modules/.cache/dune/`; build
outputs and Wrangler state are excluded from typechecking. `*.tsbuildinfo` and
patch backups are ignored. Git history preserves prior source versions.
Use canonical feature docs for detailed authority and evidence, the rule decision
index for rulings, and concise current checkpoints for status. The large
[implementation history](IMPLEMENTATION_STATUS.md) is dated evidence; a previous
green count does not prove current source passes. Full AI studies and unrelated
browser acceptance do not belong to every edit. Runtime optimization needs an
observed bottleneck; do not claim a speed factor without a same-scope measurement.