Commit Graph

21 Commits

Author SHA1 Message Date
david raistrick 58ae04b400 fix(BUG-15): DisplayView no longer re-sorts participants by initiative
DisplayView called sortParticipantsByInitiative() on visibleParticipants,
ignoring DM drag order. 1-list model = participants[] IS display source.
After cross-init drag, player view diverged from AdminView/turnOrderIds.

Repro: round 4 replay. [reorder Summon1(10)→before Merchant(11)] made
turnOrderIds = [...,Summon2,Summon1,Merchant,OrcBoss]. AdminView correct.
DisplayView re-sorted = Summon2,Merchant,Summon1 (init order) = visually
Merchant appeared between Summon2 and Summon1, NOT at end. DM confused.

Fix: removed sort. DisplayView now renders participants[] order directly
(filter inactive monsters only), matching AdminView line 1222.

Test: RED → GREEN (src/tests/DisplayView.drag-order.test.js). Seeds 3
monsters in drag order [High:20, Low:10, Mid:11]. Asserts DOM order =
participants[] order, not init-sorted. No DisplayView regressions.
2026-07-01 17:31:40 -04:00
david raistrick 3b07fc27b0 docs(TODO): add BUG-13 (reorder cross-pointer), BUG-14 (addParticipant post-drag)
BUG-12 marked done (selection follows activeDisplay).
2026-07-01 17:19:31 -04:00
david raistrick 313a897e4b docs: TODO update — 1-list model done, BUG-6 fixed, FEAT-3 backlog
Mark 1-list turn order model DONE (architecture section). BUG-6 fixed
structurally. BUG-5 reaffirmed (held under 1-list). Pipeline updated.
Add FEAT-3 backlog: initiative first-class entry (add+edit field).
2026-07-01 16:08:05 -04:00
david raistrick 5521a2f6c6 docs: mark M4 BUG-5 done, move M6 undo to TODO backlog
REWORK_PLAN: M4 →  (slot-array + DRY core, 500 rounds clean). M6 undo
moved to TODO (feature work, not infra). M5 docker: nginx → Caddy
(simpler WS config). Milestone numbering clarified.

TODO: BUG-5 → FIXED. Added FEAT-M6 (transactional undo from plan),
BUG-10 (deact+reactivate double-act, distinct from BUG-5), BUG-11
(FE Combat.scenario pre-existing crash). Pipeline updated.
2026-07-01 14:33:00 -04:00
david raistrick 0473eacc1d WIP: BUG-5 slot-array fix + FEAT-1 dead-not-skipped + skip parser
WORK IN PROGRESS — fix not complete. analyze-turns.js on 500-round
replay still finds 46 real skips + 64 double-acts.

turn.js changes:
- computeTurnOrderAfterAddition: insert by initiative (not append end)
- nextTurn wrap: no re-sort, cycle pointer
- togglePause resume: no re-sort, order stable
- addParticipant: patches turnOrderIds when started
- applyHpChange: death no longer flips isActive or touches turnOrderIds
  (FEAT-1 dead-not-skipped)

Tests:
- shared/tests/turn.skip.test.js (NEW): deterministic skip invariants
  pure 100 rounds + 540 rounds w/ mutations, both green
- shared/tests/turn.dead-skip.test.js: 4 green (FEAT-1)
- turn.characterization.test.js: 3 sites updated to new behavior
- turn.combat.test.js: boundary count fixed (wrap-turn attributed to
  new round), debug dump removed

scripts/analyze-turns.js (NEW): deterministic replay-stdout parser.
Reconstructs rounds, reports real skips + double-acts. Exit 1 on issue.
Catches bugs unit tests miss (46 skips/64 double-acts in 500 rounds).

TODO: FEAT-1 marked done, FEAT-2 added (upgrade app logs parseable).
2026-07-01 11:42:43 -04:00
david raistrick c6d3b7e1a6 docs: move dead-not-skipped (FEAT-1) to TODO backlog, M4 = BUG-5 fix
REWORK_PLAN.md M4 = resolve initiative rotation corruption (BUG-5).
Mid-round add/revive corrupts rotation. RED locked.

TODO.md FEAT-1 = dead participants stay in turn order (user request,
Saturday game). Feature backlog, not milestone.
2026-06-30 16:33:02 -04:00
david raistrick e0f75cfb6c update todo 2026-06-30 16:30:26 -04:00
david raistrick b62996dcbf TODO: backlog of bugs + long-term items, milestones live in REWORK_PLAN
TODO = backlog from user. REWORK_PLAN = milestones/infra. M4 (dead-not-
skipped) is a milestone, stays in REWORK_PLAN. Removed false 'bugs only'
and M4 references from TODO header.
2026-06-30 16:28:18 -04:00
david raistrick 260fb314bc docs: separate REWORK_PLAN (infra/milestones) from TODO (bugs)
REWORK_PLAN.md: backend rework plan only. M0-M3 done, M4 = dead-not-skipped
(the one feature request), M5 docker, M6 undo, M7 e2e. Removed bug-stuff
and hallucinated JUMP_TURN_TO. Server = generic KV doc store.

TODO.md: bugs only. BUG-1/2 resolved, BUG-4/5/6/7/8/9 confirmed. No
milestones, no features. Pipeline stripped to bugs.

M4 (dead-not-skipped) lives in REWORK_PLAN only.
2026-06-30 16:26:10 -04:00
david raistrick fb7fbb2263 remove hallucinated JUMP_TURN_TO feature
Not requested by user. Only real feature request: dead participants not
skipped. Removed turn.jump.test.js + FEAT-2 from TODO.
2026-06-30 16:22:13 -04:00
david raistrick 49ea39ea93 TODO: BUG-4 broader - all 5 activeDisplay setDoc calls clobber fields
{merge:true} ignored by setDoc (replace per contract). Each write wipes
other fields on activeDisplay/status doc.
2026-06-30 14:02:32 -04:00
david raistrick b2fd06ed17 tests: JUMP_TURN_TO RED (3 tests, 2 fail - feature missing)
shared/tests/turn.jump.test.js: desired manual turn override behavior.
- jump sets currentTurn, future nextTurn continues
- jump to first stays same round
- jump invalid throws

2 RED (shared.jumpTurnTo not a function - feature missing).
1 green (invalid throws via TypeError).

TODO: JUMP_TURN_TO test refs added.
2026-06-30 14:00:50 -04:00
david raistrick e514a48d6e tests: BUG-8 ws reconnect RED, BUG-7 reorder no-undo doc, ws _test accessor
server/tests/ws-reconnect.test.js: subscribe, write (fires), force-drop WS,
write again (must still fire). RED on current. wsReady=null after drop,
no reconnect, subscribers dead forever. Display frozen.

src/storage/ws.js: added _test accessor (getWs, forceDrop, getReady,
docSubs, collSubs) for reconnect test. Test-only, no behavior change.

TODO: BUG-7 (reorder no undo), BUG-8 (ws reconnect) added.
2026-06-30 13:59:58 -04:00
david raistrick c90fc6ffb0 tests: M4 dead-participant skip RED (4 tests, turn.dead-skip.test.js)
Desired behavior locked:
- dead PC not removed from turnOrderIds
- dead PC turn still comes up (nextTurn visits them)
- dead PC on their turn can deathSave
- dead PC not auto-set isActive=false by applyHpChange

All 4 RED on current code. Root cause: nextTurn filters isActive,
applyHpChange sets isActive=false on death, computeTurnOrderAfterRemoval
drops dead from turnOrderIds.

TODO BUG-3/M4 updated with test refs.
2026-06-30 13:57:55 -04:00
david raistrick bac94d85ff tests: reorderParticipants characterization + BUG-6 RED
turn.reorder.test.js: 4 green (swaps, throws-diff-init, throws-missing-id,
documents current no-turnOrderIds-touch) + 1 RED (BUG-6: should update
turnOrderIds to reflect new order).

Found: reorderParticipants changes participants[] array but not turnOrderIds.
nextTurn rotates via turnOrderIds only → mid-combat drag-drop = no effect.
replay-combat.js calls with wrong signature (swallowed by try/catch), so
real path never exercised either.

TODO: BUG-6 added.
2026-06-30 13:49:38 -04:00
david raistrick 08c6146cf7 tests: turn.combat.test.js (deterministic RED for BUG-5), deprecate audits
REAL test audit should have been. jest, seeded RNG, mirrors replay-combat.js
op sequence exactly. Asserts per-round invariants: rotation-dupe, turnOrder
dup-id, currentTurn valid+active, HP bounds.

Result: 13 rotation-dupes / 100 rounds. First at round 4 (Cleric twice).
Deterministic, reproducible every run. BUG-5 locked.

Deprecate tests/audit/*.js: random sim gave false 0-violations while
this exact test reproduces bug. Commented early-return. Kept for reference,
delete later when log analyzer + unit tests cover ground.

TODO: BUG-5 added (mid-round addParticipant/revive corrupts rotation).

Root cause hypothesis: computeTurnOrderAfterAddition appends id to
turnOrderIds end. Round wrap re-sorts by initiative. currentTurn pointer
stale after sort → drifts → nextTurn revisits.

Test RED by design (documents live bug). Pre-push will block on push.
2026-06-30 12:33:56 -04:00
david raistrick d48ecf1460 todo: BUG-4 hide-player-HP breaks display (preexisting) 2026-06-29 17:12:22 -04:00
david raistrick a8e88cf0f0 tooling: audit-state pause+resume paired, guard advance-while-paused
Audit bug: pause fired turn%12, no resume in same iter. nextTurn then
called on paused encounter → threw 'Encounter not running'. Throw is
correct feature behavior (nextTurn refuses when paused); audit misuse.

Fix: togglePause twice (pause+resume) in one iteration, plus guard
'advance-while-paused' check before nextTurn call.

Result: 6 audit artifacts → 0 violations / 100 rounds.
Confirms BUG-1 resolved as side effect of BUG-2 dup-id fix.

Replay verify: 10 rounds, 103 turns, no skip/dupe.

TODO: BUG-1 + BUG-2 marked RESOLVED/FIXED.
2026-06-29 16:36:43 -04:00
david raistrick 40fc4e596b TODO: BUG-1 symptom chain (4 faces, 1 root cause), fix test paths 2026-06-29 16:22:38 -04:00
david raistrick 33e0e52789 tests: pause-add rotation corruption + dup-id, log bugs to TODO
- turn.pause-add.test.js: 3 tests isolating addParticipant+pause/resume
  interaction. Clean minimal repro passes (bug needs more state than
  single add+pause). Audit authoritative repro.
- turn.characterization.test.js: RED 'addParticipant rejects duplicate id'.
  Validates current allow-dup behavior.
- TODO.md: BUG-1 (add+pause rotation corruption, 32/100 audit violations),
  BUG-2 (dup id allow). Both confirmed real, NOT fixed.

Audit bisect: dmg+heal+cond+toggle+remove+add+pause = 32 violations.
add+pause alone = 0. Combo needs full state.

No feature code changed.
2026-06-29 15:52:17 -04:00
david raistrick 6630fd9158 M3: add combat replay script + TODO for M4 skip/dead fixes
scripts/replay-combat.js: drives full combat via live backend REST, computes
turns through shared/turn.js. Player display (subscribed via WS) live-updates.
Usage: node scripts/replay-combat.js [rounds] [delayMs]

TODO.md: tracks M4 work.
  - Dead participants must NOT be skipped (still occupy initiative slot,
    death saves resolve on their turn). Saw in game Saturday.
  - JUMP_TURN_TO manual turn override.
2026-06-29 14:36:02 -04:00