diff --git a/.gitignore b/.gitignore index 31a0bbd..d559aa7 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ data/*.sqlite-* server/data/*.sqlite server/data/*.sqlite-* /data +/scratch diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 2e09cd6..3042fde 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -24,10 +24,13 @@ TTRPG Initiative Tracker — fork with self-hosted backend. Monorepo via npm wor shared/ # Pure logic, no I/O (client + server + tests import) turn.js # turn-order state machine tests/ # turn logic tests - scripts/ # manual demo/audit tools (NOT unit tests) + scripts/ # manual demo tool (NOT test) replay-combat.js # live backend demo - audit-rotation.js # exploratory rotation bug-finder - audit-state.js # exploratory invariant bug-finder (9 classes) + tests/ + audit/ # exploratory bug-finders (manual, Math.random) + audit-rotation.js # rotation invariant + audit-state.js # 9 invariant classes + scratch/ # gitignored: throwaway repro/exploration docs/ REWORK_PLAN.md DEVELOPMENT.md # this file @@ -119,33 +122,38 @@ CI=true npx react-scripts test --watchAll=false src/tests/App.characterization.t CI=true npx react-scripts test --watchAll=false --testPathIgnorePatterns="Combat.scenario" ``` -## Manual tools (NOT tests) +## Demo tool (NOT test) -`scripts/` = exploratory. Math.random, non-deterministic. Used to find bugs, unit tests lock them. - -### replay-combat.js — live demo - -Drives full combat through real backend via ws adapter (same contract as App). Player display live-updates. +`scripts/replay-combat.js` = live backend demo. Watch UI react to state changes. ```bash -# start backend + frontend first (see Run) +# start backend + frontend first node scripts/replay-combat.js [rounds] [delayMs] # defaults: 100 rounds, 200ms/step ``` -Coverage per round: damage, heal, all 22 conditions, toggleActive (mark inactive/reactivate), removeParticipant, addParticipant (reinforcements), updateParticipant (edit), pause/resume, reorderParticipants, endEncounter. Revives dead each round to sustain 100 rounds. +Coverage per round: damage, heal, all 22 conditions, toggleActive, +removeParticipant, addParticipant (reinforcements), updateParticipant, +pause/resume, reorderParticipants, endEncounter. Revives dead each round +to sustain full round count. -### audit-rotation.js — rotation bug-finder +## Audit tools (NOT unit tests) -Pure turn.js simulation of replay op sequence. Detects rotation violations (skip/dupe per round). Pinpointed BUG-1 (addParticipant + pause corrupts rotation). +`tests/audit/` = exploratory, Math.random, non-deterministic. Manual run. +Unit tests (`{shared,server,src}/tests/`) lock known bugs deterministically. + +### audit-rotation.js + +Pure turn.js simulation of replay op sequence. Detects rotation violations +(skip/dupe per round). Found BUG-1 (addParticipant + pause corrupts rotation). ```bash -node scripts/audit-rotation.js +node tests/audit/audit-rotation.js ``` -Bisect mode: comment/uncomment op blocks to isolate which combo triggers. +Bisect: comment/uncomment op blocks to isolate triggering combo. -### audit-state.js — expanded invariant bug-finder +### audit-state.js Runs pure turn.js combat, audits 9 invariant classes per round: @@ -160,13 +168,18 @@ Runs pure turn.js combat, audits 9 invariant classes per round: 9. undo support ```bash -node scripts/audit-state.js [rounds] +node tests/audit/audit-state.js [rounds] # default 100 ``` -100-round run: 128 violations, all BUG-1/BUG-2 family (4 symptom faces). Clean: HP, isActive, deathSave, conditions, removal. +Current state (post BUG-1/2 fix): 0 violations / 100 rounds. See `TODO.md` for known bugs. +## Scratch + +`scratch/` = gitignored throwaway. Repro scripts, exploration, debug. +Not committed. Use freely, delete anytime. + ## Build ```bash diff --git a/scripts/README.md b/scripts/README.md index 1b54bf2..c7b0a26 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,13 +1,11 @@ # scripts/ -Manual tools. NOT unit tests. Math.random, non-deterministic. - -Used to FIND bugs. Unit tests (in `*/tests/`) LOCK them. +Manual demo tool. NOT test. ## replay-combat.js -Drives full combat through live backend via ws adapter (same contract as App). -Player display live-updates. Use to watch UI react to state changes. +Live backend demo. Drives full combat via ws adapter (same contract as App). +Player display live-updates. Watch UI react to state changes. ```bash # start backend + frontend first (see docs/DEVELOPMENT.md) @@ -20,33 +18,8 @@ removeParticipant, addParticipant (reinforcements), updateParticipant, pause/resume, reorderParticipants, endEncounter. Revives dead each round to sustain full round count. -## audit-rotation.js +## See also -Pure turn.js simulation of replay op sequence. Detects rotation violations -(skip/dupe per round). Pinpointed BUG-1 (addParticipant + pause corrupts). - -```bash -node scripts/audit-rotation.js -``` - -Bisect: comment/uncomment op blocks to isolate triggering combo. - -## audit-state.js - -Expanded invariant bug-finder. 9 check classes per round: - -1. rotation integrity -2. HP bounds -3. isActive consistency -4. turnOrder no dup ids -5. turnOrder ids all active -6. currentTurn valid + active -7. deathSave range + reset on revive -8. removeParticipant orphans -9. undo support - -```bash -node scripts/audit-state.js [rounds] # default 100 -``` - -See TODO.md for bugs found. +- `tests/audit/` — exploratory bug-finders (manual run, non-deterministic) +- `{shared,server,src}/tests/` — jest unit/integration/characterization +- `scratch/` — gitignored throwaway diff --git a/scripts/audit-rotation.js b/tests/audit/audit-rotation.js similarity index 99% rename from scripts/audit-rotation.js rename to tests/audit/audit-rotation.js index 944929b..856e4d0 100644 --- a/scripts/audit-rotation.js +++ b/tests/audit/audit-rotation.js @@ -3,7 +3,7 @@ // rotation breaks (skip or dupe). Prints minimal repro + preceding ops. // No backend, no WS, no sleep. Fast. -const shared = require('../shared'); +const shared = require('../../shared'); const { buildCharacterParticipant, buildMonsterParticipant, startEncounter, nextTurn, togglePause, diff --git a/scripts/audit-state.js b/tests/audit/audit-state.js similarity index 99% rename from scripts/audit-state.js rename to tests/audit/audit-state.js index 2abe1a2..22e33ef 100644 --- a/scripts/audit-state.js +++ b/tests/audit/audit-state.js @@ -17,7 +17,7 @@ // Run: node scripts/audit-state.js [rounds] 'use strict'; -const shared = require('../shared'); +const shared = require('../../shared'); const { makeParticipant, startEncounter, nextTurn, togglePause, addParticipant, updateParticipant, removeParticipant,