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.
This commit is contained in:
@@ -5,6 +5,15 @@ REWORK_PLAN.md.
|
|||||||
|
|
||||||
## Feature backlog
|
## Feature backlog
|
||||||
|
|
||||||
|
### FEAT-M6: Transactional undo (moved from REWORK_PLAN)
|
||||||
|
- Every mutating action writes event: `(type, payload, undo_payload, undone, ts)`.
|
||||||
|
- Undo = apply `undo_payload` in same SQLite tx, flip `undone`. Transactional,
|
||||||
|
no stale clobber.
|
||||||
|
- Replaces fragile `/logs` snapshot-write undo.
|
||||||
|
- Migration: keep old undo working for existing entries until cleared; new
|
||||||
|
format for new entries.
|
||||||
|
- Related: BUG-7 (reorder no undo).
|
||||||
|
|
||||||
### FEAT-1: Dead participants stay in turn order — DONE
|
### FEAT-1: Dead participants stay in turn order — DONE
|
||||||
- Fixed: `applyHpChange` no longer flips `isActive` or touches `turnOrderIds`
|
- Fixed: `applyHpChange` no longer flips `isActive` or touches `turnOrderIds`
|
||||||
on death/revive. Dead stay in rotation, `nextTurn` visits them, PCs get
|
on death/revive. Dead stay in rotation, `nextTurn` visits them, PCs get
|
||||||
@@ -78,18 +87,10 @@ REWORK_PLAN.md.
|
|||||||
- Test: render App + DisplayView, toggle hide-HP, assert display still shows
|
- Test: render App + DisplayView, toggle hide-HP, assert display still shows
|
||||||
encounter (not paused).
|
encounter (not paused).
|
||||||
|
|
||||||
### BUG-5: mid-round addParticipant/revive corrupts rotation
|
### BUG-5: mid-round addParticipant/revive corrupts rotation — FIXED
|
||||||
- Test: `shared/tests/turn.combat.test.js` (jest, seeded RNG, RED).
|
- Fixed (commit `494327f`). Slot-array turn order + DRY advance core
|
||||||
- 13 rotation-dupes / 100 rounds. First at round 4 (Cleric twice).
|
`nextActiveAfter`. Both nextTurn + computeTurnOrderAfterRemoval delegate.
|
||||||
- Pattern: Reinforce/Summon added mid-round → appears in rotation same round
|
- 500-round replay: 0 skips, 0 double-acts.
|
||||||
→ round wrap re-sorts by initiative → currentTurnParticipantId pointer
|
|
||||||
stale → nextTurn revisits.
|
|
||||||
- Root cause: `computeTurnOrderAfterAddition` appends id to turnOrderIds
|
|
||||||
end. Round wrap re-sorts by initiative. currentTurn pointer stale after
|
|
||||||
sort → drifts → nextTurn revisits.
|
|
||||||
- This is the test audit should have been. Mirrors replay-combat.js op
|
|
||||||
sequence exactly (damage, heal, conditions, toggleActive, deathSave,
|
|
||||||
remove, add, edit, pause/resume, reorder, revive-between-rounds).
|
|
||||||
|
|
||||||
### BUG-6: reorderParticipants doesn't update turnOrderIds
|
### BUG-6: reorderParticipants doesn't update turnOrderIds
|
||||||
- Test: `shared/tests/turn.reorder.test.js` 'reorder updates turnOrderIds' (RED).
|
- Test: `shared/tests/turn.reorder.test.js` 'reorder updates turnOrderIds' (RED).
|
||||||
@@ -114,8 +115,27 @@ REWORK_PLAN.md.
|
|||||||
- Display frozen until full reload.
|
- Display frozen until full reload.
|
||||||
- Fix: `onclose` → reconnect + re-subscribe existing paths.
|
- Fix: `onclose` → reconnect + re-subscribe existing paths.
|
||||||
|
|
||||||
|
### BUG-10: deact+reactivate same round double-acts participant
|
||||||
|
- Discovered in 500-round replay (3 occurrences). DISTINCT from BUG-5.
|
||||||
|
- Pattern: participant acts → DM deactivates them → DM reactivates them
|
||||||
|
same round → `computeTurnOrderAfterAddition` re-inserts by initiative
|
||||||
|
(front) → acts AGAIN before round ends.
|
||||||
|
- No "acted-this-round" guard. Slot-array model has no per-round-acted set.
|
||||||
|
- Edge case (DM deact+reactivate same participant same round).
|
||||||
|
- Fix candidate: track actedThisRound set, skip re-acted; OR insertion
|
||||||
|
places reactivate AFTER current position (not by initiative).
|
||||||
|
- Parser now discounts deact-current advances, so this surfaced real.
|
||||||
|
|
||||||
|
### BUG-11: FE Combat.scenario test crashes (pre-existing)
|
||||||
|
- `src/tests/Combat.scenario.test.js:254` deathSave query helper throws
|
||||||
|
(button not found).
|
||||||
|
- Baseline (my changes removed) also exit=1. Pre-existing, not regression.
|
||||||
|
- Crashes whole FE test run (process dies).
|
||||||
|
|
||||||
## Pipeline (bugs only --- milestones live in REWORK_PLAN.md)
|
## Pipeline (bugs only --- milestones live in REWORK_PLAN.md)
|
||||||
- [ ] BUG-4: fix setDoc→updateDoc for all 5 activeDisplay sites
|
- [ ] BUG-4: fix setDoc→updateDoc for all 5 activeDisplay sites
|
||||||
- [ ] BUG-5: fix computeTurnOrderAfterAddition currentTurn re-anchor
|
- [x] BUG-5: fixed (commit 494327f)
|
||||||
- [ ] BUG-6: reorderParticipants update turnOrderIds
|
- [ ] BUG-6: reorderParticipants update turnOrderIds
|
||||||
- [ ] BUG-8: ws adapter reconnect
|
- [ ] BUG-8: ws adapter reconnect
|
||||||
|
- [ ] BUG-10: deact+reactivate double-act
|
||||||
|
- [ ] BUG-11: FE Combat.scenario crash
|
||||||
|
|||||||
+18
-21
@@ -121,8 +121,9 @@ Each milestone = independently mergeable PR upstream (unless marked ❌).
|
|||||||
| 3 | characterization tests lock current behavior | yes |
|
| 3 | characterization tests lock current behavior | yes |
|
||||||
| 4 | resolve initiative rotation corruption (BUG-5) | yes |
|
| 4 | resolve initiative rotation corruption (BUG-5) | yes |
|
||||||
| 5 | docker compose in-house | smoke |
|
| 5 | docker compose in-house | smoke |
|
||||||
| 6 | undo rework (tx events) | unit |
|
| 6 | _moved to TODO backlog (feature work)_ | - |
|
||||||
| 7 | playwright multi-window e2e (deferred) | e2e |
|
| 7 | playwright multi-window e2e (deferred) | e2e |
|
||||||
|
| 8 | (future) public exposure | - |
|
||||||
|
|
||||||
### Milestone 0 — Repo + branch setup ✅
|
### Milestone 0 — Repo + branch setup ✅
|
||||||
- Fresh branch off `main` (not `dsr-rework`). Name: `rework-backend`.
|
- Fresh branch off `main` (not `dsr-rework`). Name: `rework-backend`.
|
||||||
@@ -159,33 +160,29 @@ Each milestone = independently mergeable PR upstream (unless marked ❌).
|
|||||||
- **Exit criteria:** characterization suite green. Baseline locked. ✅ DONE.
|
- **Exit criteria:** characterization suite green. Baseline locked. ✅ DONE.
|
||||||
- **Upstream-PRable:** ✅ if kept storage-agnostic (tests target turn logic shape).
|
- **Upstream-PRable:** ✅ if kept storage-agnostic (tests target turn logic shape).
|
||||||
|
|
||||||
### Milestone 4 — Resolve initiative rotation corruption (BUG-5)
|
### Milestone 4 — Resolve initiative rotation corruption (BUG-5) ✅
|
||||||
- **Real bug.** Mid-round add/revive corrupts rotation.
|
- **Fixed** (commit `494327f`).
|
||||||
- 13 dupes / 100 rounds (deterministic seeded test).
|
- Slot-array turn order model + DRY advance core (`nextActiveAfter`).
|
||||||
- Root cause: `computeTurnOrderAfterAddition` appends id to turnOrderIds
|
Both `nextTurn` + `computeTurnOrderAfterRemoval` delegate → one advance
|
||||||
end. Round wrap re-sorts by initiative. `currentTurnParticipantId`
|
path, no drift.
|
||||||
pointer stale → nextTurn revisits.
|
- 500-round replay: 0 skips, 0 double-acts.
|
||||||
- RED test locked: `shared/tests/turn.combat.test.js`.
|
- Tests: `turn.skip.test.js`, `turn.dry.test.js` (advance parity lock).
|
||||||
- Detail in `TODO.md` BUG-5.
|
|
||||||
- **Exit criteria:** RED green. Rotation invariant holds across
|
|
||||||
add/remove/revive.
|
|
||||||
- **Upstream-PRable:** ✅ bug fix.
|
- **Upstream-PRable:** ✅ bug fix.
|
||||||
|
|
||||||
### Milestone 5 — Docker compose
|
### Milestone 5 — Docker compose
|
||||||
- `docker-compose.yml`:
|
- `docker-compose.yml`:
|
||||||
- `backend` service (Node + sqlite volume)
|
- `backend` service (Node + sqlite volume)
|
||||||
- `nginx` service (static frontend + reverse proxy + http basic auth)
|
- `frontend` service (static build served via **Caddy**)
|
||||||
|
- Caddy reverse-proxies `/api` + `/ws` → backend, auto WS upgrade, HTTP basic auth
|
||||||
|
- Caddy chosen over nginx: simpler config, native WS, one file `Caddyfile`.
|
||||||
- Profiles: `firebase` (frontend only, current behavior) vs `backend` (full stack).
|
- Profiles: `firebase` (frontend only, current behavior) vs `backend` (full stack).
|
||||||
|
- Run: OrbStack local now; remote docker context later.
|
||||||
- **Exit criteria:** `docker compose up` runs full stack in-house.
|
- **Exit criteria:** `docker compose up` runs full stack in-house.
|
||||||
- **Upstream-PRable:** ❌ divergence.
|
- **Upstream-PRable:** ❌ divergence.
|
||||||
|
|
||||||
### Milestone 6 — Undo rework
|
### Milestone 6 — Undo rework — _MOVED to TODO backlog_
|
||||||
- Events table: every mutating action writes `(type, payload, undo_payload, undone, ts)`.
|
- Moved: feature work (transactional undo), not infra. Lives in `TODO.md` now.
|
||||||
- Undo = apply `undo_payload` in same SQLite tx, flip `undone`. Transactional, no stale clobber.
|
- Scope: events table `(type, payload, undo_payload, undone, ts)`; undo = apply undo_payload in tx.
|
||||||
- Replaces current fragile `/logs` snapshot-write undo.
|
|
||||||
- Migration: keep old undo working for existing entries until cleared; new format for new entries.
|
|
||||||
- **Exit criteria:** undo works transactionally; interleaved undos don't corrupt.
|
|
||||||
- **Upstream-PRable:** ⚠️ partial. Turn-logic-level undo = ✅. Backend events table = ❌.
|
|
||||||
|
|
||||||
### Milestone 7 — Playwright E2E (deferred)
|
### Milestone 7 — Playwright E2E (deferred)
|
||||||
- Multi-window E2E: DM view + display + player view in separate browser contexts against running backend.
|
- Multi-window E2E: DM view + display + player view in separate browser contexts against running backend.
|
||||||
@@ -234,7 +231,7 @@ Each milestone = independently mergeable PR upstream (unless marked ❌).
|
|||||||
| 3 characterization tests | ✅ | if storage-agnostic |
|
| 3 characterization tests | ✅ | if storage-agnostic |
|
||||||
| 4 BUG-5 rotation fix | ✅ | bug fix |
|
| 4 BUG-5 rotation fix | ✅ | bug fix |
|
||||||
| 5 docker compose | ❌ | divergence |
|
| 5 docker compose | ❌ | divergence |
|
||||||
| 6 undo rework | ⚠️ partial | turn-logic-level ✅, events table ❌ |
|
| 6 undo (moved to TODO) | - | - |
|
||||||
| 7 playwright | ✅ | if test infra shared |
|
| 7 playwright | ✅ | if test infra shared |
|
||||||
|
|
||||||
Default `STORAGE=firebase` + `AUTH_MODE=none` (unset) = upstream sees literally zero change.
|
Default `STORAGE=firebase` + `AUTH_MODE=none` (unset) = upstream sees literally zero change.
|
||||||
@@ -264,4 +261,4 @@ Default `STORAGE=firebase` + `AUTH_MODE=none` (unset) = upstream sees literally
|
|||||||
- Backend live: port 4001, db `./data/tracker.sqlite`
|
- Backend live: port 4001, db `./data/tracker.sqlite`
|
||||||
- Frontend: port 3999 with `REACT_APP_STORAGE=ws`
|
- Frontend: port 3999 with `REACT_APP_STORAGE=ws`
|
||||||
- Test suite: ~160 tests (shared + server + FE). Bugs tracked in `TODO.md`.
|
- Test suite: ~160 tests (shared + server + FE). Bugs tracked in `TODO.md`.
|
||||||
- Next milestones: M5 docker-compose, M6 undo rework.
|
- Next milestones: M5 docker-compose. Undo moved to TODO backlog.
|
||||||
|
|||||||
Reference in New Issue
Block a user