Rework backend #1

Merged
robert merged 86 commits from rework-backend into main 2026-07-01 19:29:34 -04:00
5 changed files with 41 additions and 54 deletions
Showing only changes of commit c314d1975e - Show all commits
+1
View File
@@ -12,3 +12,4 @@ data/*.sqlite-*
server/data/*.sqlite server/data/*.sqlite
server/data/*.sqlite-* server/data/*.sqlite-*
/data /data
/scratch
+31 -18
View File
@@ -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) shared/ # Pure logic, no I/O (client + server + tests import)
turn.js # turn-order state machine turn.js # turn-order state machine
tests/ # turn logic tests tests/ # turn logic tests
scripts/ # manual demo/audit tools (NOT unit tests) scripts/ # manual demo tool (NOT test)
replay-combat.js # live backend demo replay-combat.js # live backend demo
audit-rotation.js # exploratory rotation bug-finder tests/
audit-state.js # exploratory invariant bug-finder (9 classes) audit/ # exploratory bug-finders (manual, Math.random)
audit-rotation.js # rotation invariant
audit-state.js # 9 invariant classes
scratch/ # gitignored: throwaway repro/exploration
docs/ docs/
REWORK_PLAN.md REWORK_PLAN.md
DEVELOPMENT.md # this file 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" 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. `scripts/replay-combat.js` = live backend demo. Watch UI react to state changes.
### replay-combat.js — live demo
Drives full combat through real backend via ws adapter (same contract as App). Player display live-updates.
```bash ```bash
# start backend + frontend first (see Run) # start backend + frontend first
node scripts/replay-combat.js [rounds] [delayMs] node scripts/replay-combat.js [rounds] [delayMs]
# defaults: 100 rounds, 200ms/step # 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 ```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: 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 9. undo support
```bash ```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. See `TODO.md` for known bugs.
## Scratch
`scratch/` = gitignored throwaway. Repro scripts, exploration, debug.
Not committed. Use freely, delete anytime.
## Build ## Build
```bash ```bash
+7 -34
View File
@@ -1,13 +1,11 @@
# scripts/ # scripts/
Manual tools. NOT unit tests. Math.random, non-deterministic. Manual demo tool. NOT test.
Used to FIND bugs. Unit tests (in `*/tests/`) LOCK them.
## replay-combat.js ## replay-combat.js
Drives full combat through live backend via ws adapter (same contract as App). Live backend demo. Drives full combat via ws adapter (same contract as App).
Player display live-updates. Use to watch UI react to state changes. Player display live-updates. Watch UI react to state changes.
```bash ```bash
# start backend + frontend first (see docs/DEVELOPMENT.md) # start backend + frontend first (see docs/DEVELOPMENT.md)
@@ -20,33 +18,8 @@ removeParticipant, addParticipant (reinforcements), updateParticipant,
pause/resume, reorderParticipants, endEncounter. Revives dead each round pause/resume, reorderParticipants, endEncounter. Revives dead each round
to sustain full round count. to sustain full round count.
## audit-rotation.js ## See also
Pure turn.js simulation of replay op sequence. Detects rotation violations - `tests/audit/` — exploratory bug-finders (manual run, non-deterministic)
(skip/dupe per round). Pinpointed BUG-1 (addParticipant + pause corrupts). - `{shared,server,src}/tests/` — jest unit/integration/characterization
- `scratch/` — gitignored throwaway
```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.
@@ -3,7 +3,7 @@
// rotation breaks (skip or dupe). Prints minimal repro + preceding ops. // rotation breaks (skip or dupe). Prints minimal repro + preceding ops.
// No backend, no WS, no sleep. Fast. // No backend, no WS, no sleep. Fast.
const shared = require('../shared'); const shared = require('../../shared');
const { const {
buildCharacterParticipant, buildMonsterParticipant, buildCharacterParticipant, buildMonsterParticipant,
startEncounter, nextTurn, togglePause, startEncounter, nextTurn, togglePause,
@@ -17,7 +17,7 @@
// Run: node scripts/audit-state.js [rounds] // Run: node scripts/audit-state.js [rounds]
'use strict'; 'use strict';
const shared = require('../shared'); const shared = require('../../shared');
const { const {
makeParticipant, startEncounter, nextTurn, togglePause, makeParticipant, startEncounter, nextTurn, togglePause,
addParticipant, updateParticipant, removeParticipant, addParticipant, updateParticipant, removeParticipant,