david raistrick
b095e37bfe
M3: remove project dev-serve skill (moving to generic global skill)
2026-06-29 11:25:13 -04:00
david raistrick
54e8df9ffa
M3: add dev-serve skill (boot stack + headed browser for human testing)
...
- pkill stale procs, boot backend + frontend in background
- STORAGE=ws default (firebase opt-in)
- agent_browser --headed fresh session for user-visible window
- troubleshooting table + teardown
Skill loads via /skill:dev-serve
2026-06-29 11:24:23 -04:00
david raistrick
e743d40e8d
M2: fix ws adapter for browser WebSocket + firebase path prefix
...
- WebSocketImpl: native browser WebSocket if present, else ws pkg (node/jest)
- ensureWs: use onopen/onmessage/onerror/onclose property handlers (browser API)
instead of ws.on('open') EventEmitter (node-only) — was silent no-op in browser
- norm(): strip 'artifacts/{APP_ID}/public/data/' prefix from all paths
App passes firebase-prefixed paths; backend uses canonical campaigns/...
- apply norm() to getDoc/getCollection/setDoc/updateDoc/deleteDoc/addDoc/
subscribeDoc/subscribeCollection/changeTypesForDocPath/changeTypesForCollPath
Verified: STORAGE=ws boots, WS subscribe fires, backend broadcast -> browser
live update (curl POST campaign -> appears without reload). Cross-device sync
confirmed end-to-end.
2026-06-28 22:43:30 -04:00
david raistrick
3e84f28325
M2: gate storage init on STORAGE mode (firebase vs ws/memory)
...
- STORAGE_MODE = getStorageMode()
- initializeStorage(): firebase = real SDK init; ws/memory = stub auth
- App auth flow: ws/memory skip signInAnonymously, unblock UI
- error screen mode-aware message
56 tests green. STORAGE=ws now boots past config error.
2026-06-28 21:11:56 -04:00
david raistrick
812298fa73
M2: refactor all firebase write sites to storage adapter
...
- 37 call sites: setDoc/updateDoc/deleteDoc/addDoc/getDocs/writeBatch -> storage.*
- adapter wraps SDK, path-string interface
- storage instance app-wide (getStorage)
- firebase.js: static imports (getDoc/getDocs alias), no dynamic import
56 frontend tests green. STORAGE=firebase = identical behavior.
2026-06-28 21:05:39 -04:00
david raistrick
5bb9e5fc19
M2: refactor hooks to storage adapter (subscribe)
...
- src/storage/index.js: getStorage() factory + SDK re-exports
- App.js: useFirestoreDocument/Collection call storage.subscribeDoc/Collection
- getStorage import added
56 frontend tests green. Hooks now impl-agnostic (firebase vs ws).
2026-06-28 19:03:44 -04:00
david raistrick
35b5a1d238
test: logs + deathSave characterization (6 tests)
...
- Logs.characterization.test.js: logAction (write + undo payload), clearLogs batch delete, undo (updateDoc encounter + mark undone), deathSave increment + isDying
- mock firestore getDocs: return .ref.path on docs (batch.delete support)
- mock addDoc: record full doc path not collection path
All write sites characterized. 56 frontend tests green.
2026-06-28 19:00:08 -04:00
david raistrick
d581e60ba3
test: combat characterization (9 tests)
...
- Combat.characterization.test.js: startEncounter (state + activeDisplay), nextTurn, round wrap, pause, resume, endEncounter (reset + clear activeDisplay), toggleHidePlayerHp
Locks combat control write paths.
2026-06-28 18:52:49 -04:00
david raistrick
4158a1634d
test: participant characterization (9 tests)
...
- Participant.characterization.test.js: addMonster (shape, initiative range, NPC), deleteParticipant, toggleActive, applyDamage, damage-to-0, heal revive, toggleCondition
- testHelpers.js: getParticipantForm (scoped), addMonsterViaUI, setupReady, startCombatViaUI
Locks participant write paths + payload shapes. Refactor guard.
2026-06-28 18:50:42 -04:00
david raistrick
0c1196aee1
test: encounter characterization (6 tests)
...
- Encounter.characterization.test.js: createEncounter, path nesting, togglePlayerDisplay on/off, deleteEncounter + clears activeDisplay
- testHelpers.js: createEncounterViaUI, selectEncounterByName
Locks encounter write paths + payload shapes.
2026-06-28 18:30:57 -04:00
david raistrick
672f042b60
chore: alphabetize package.json deps after install/uninstall churn
...
trivial reorder, no version changes
2026-06-28 18:29:09 -04:00
david raistrick
b6555648ee
test: campaign characterization (7 tests)
...
- src/testHelpers.js: renderApp, createCampaignViaUI, selectCampaignByName
- App.characterization.test.js: createCampaign, addCharacter, updateCharacter, deleteCharacter, deleteCampaign + path namespace + bg url
- mock firestore writeBatch sync (was async, app no-await)
Locks path + payload shape per action. Refactor guard.
2026-06-28 18:12:27 -04:00
david raistrick
84dd17e174
test: Firebase mock harness + createCampaign characterization
...
- src/__mocks__/firebase/*: jest manual mocks (app/auth/firestore)
- src/__mocks__/firebase/_mock-db.js: in-memory DB + call recorder
- src/setupTests.js: jest-dom, env stubs, crypto polyfill, DB reset
- src/App.characterization.test.js: createCampaign -> setDoc path/payload locked
- src/storage/contract.js (renamed from .test.js, helper not suite)
21 tests green (memory 19 + createCampaign 2).
2026-06-28 17:59:50 -04:00
david raistrick
12b24eb707
M2 (C): storage barrel re-export, App.js imports swapped
...
- src/storage/index.js: re-exports Firebase SDK
- App.js: imports from ./storage (was firebase/* direct)
- STORAGE=firebase = identical behavior
- dev server compiles clean
Safe refactor proof. Next: per-call-site path-based rewrite for ws adapter.
2026-06-28 17:51:39 -04:00
david raistrick
2ee2bba93b
M2 (TDD): storage contract test + memory impl
...
- src/storage/contract.test.js: storage interface spec (19 assertions)
- src/storage/memory.js: in-process impl (Map + EventEmitter)
- src/storage/storage.test.js: runner, memory first
TDD: contract RED first, memory built to satisfy, 19/19 green.
Next impls (ws, firebase) run same contract.
2026-06-28 17:18:14 -04:00
david raistrick
9457f48b23
ci: local pre-push hook instead of GH Actions (private repo)
...
- remove .github/workflows/ci.yml
- add .githooks/pre-push: runs npm run test:all
- git config core.hooksPath .githooks (set)
- docs/DEVELOPMENT.md: document local pipeline
Private repo = no free Actions. Revisit when public.
2026-06-28 17:16:23 -04:00
david raistrick
fa19913e23
ci: add GitHub Actions workflow + dev docs + test:all script
...
- .github/workflows/ci.yml: runs shared + server tests on push/PR
- docs/DEVELOPMENT.md: setup, run, test, architecture, status
- package.json: test:all script (shared + server suites)
2026-06-28 17:14:51 -04:00
david raistrick
0e76fb2fc7
M1: backend (Express+ws+better-sqlite3) + integration tests
...
- server/db.js: SQLite schema mirroring Firestore doc tree
- server/handlers.js: action -> shared turn fn -> tx persist -> broadcast
- server/index.js: REST endpoints + WebSocket real-time push
- server/server.test.js: 7 integration tests (REST CRUD + combat flow)
- --forceExit for jest (open WS handles)
Backend boots, serves state, persists to SQLite.
2026-06-28 17:01:53 -04:00
david raistrick
e06adaa081
M1: shared turn logic + characterization tests (39 green)
...
- npm workspaces: shared/, server/
- shared/turn.js: port turn logic verbatim from App.js (bugs preserved)
- 39 characterization tests lock current behavior
- gitignore: sqlite data, logs
2026-06-28 16:57:43 -04:00
david raistrick
d679c9d1e9
docs: restore approved milestone plan (backend=M1, drop FSM-extract milestone)
2026-06-28 16:53:18 -04:00
david raistrick
ad7979d8fd
docs: add rework plan (backend-first, test-ecosystem baseline)
2026-06-28 16:47:48 -04:00
robert
33b27775b4
Bump version to v0.3
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
v0.3
2026-06-27 20:15:20 -04:00
robert
d96d3a6cf2
Guard against undefined values in combat log undo payloads
...
Firestore rejects writes containing undefined values. The pause/resume
and end-combat undo snapshots read encounter fields that may not yet
exist in Firestore, so add ?? false / ?? null / ?? 0 fallbacks to
match the pattern already used in the start-combat undo path.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
v.03
2026-06-27 17:19:52 -04:00
robert
439f48871e
Fix mid-round activation causing participants to be skipped in round 2+
...
When a participant was activated mid-combat, computeTurnOrderAfterAddition
appended them to the end of turnOrderIds. The visual display sorted by
initiative (putting them at the top), but the turn pointer followed the
append order, making it look like the top-initiative participants were
skipped when the round wrapped.
Fix: at the round boundary in handleNextTurn, rebuild turnOrderIds from
all active participants sorted by initiative. Mid-round additions go last
in round 1 (standard D&D ruling), then slot into proper initiative order
from round 2 onwards. Also adds turnOrderIds to the next-turn undo snapshot.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-27 16:57:08 -04:00
robert
35990f588e
Add per-entry undo buttons to combat log, bump to v0.2.5
...
Each logged action now stores a Firestore snapshot of the affected
encounter state. The /logs page shows an ↩ Undo button on any entry
with undo data; clicking it restores the encounter to its pre-action
state and marks the entry as rolled back (greyed out, strikethrough).
Covered actions: damage/heal, condition toggle, activate/deactivate,
add/remove participant, next turn, start/pause/resume/end combat.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-27 16:45:07 -04:00
robert
b11fbe4715
Update README to reflect current feature set
...
Documents conditions list (now 22), combat log at /logs, hide player HP
toggle, inactive monster hiding, fullscreen button, and wake lock toggle.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-27 11:59:36 -04:00
robert
7b52480329
Add wake lock toggle to prevent screen sleep on player display
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-27 11:56:11 -04:00
robert
58cc588726
Add fullscreen button to player display view
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-27 11:53:56 -04:00
robert
e200f59b7e
Hide inactive monsters from player display view
...
Inactive monsters are now filtered out of the DisplayView so DMs can
pre-stage summoned/reserve monsters without spoiling them for players.
Inactive characters remain visible since their inactive state is
player-relevant.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-26 14:39:59 -04:00
robert
bb65709e26
Added shield to list of conditions.
2026-05-16 15:29:27 -04:00
robert
33d831af54
Fix race condition causing permissions error on /display page
...
onAuthStateChanged fires with null before signInAnonymously completes,
causing DisplayView to query Firestore unauthenticated. Now only marks
auth ready when an actual user is present; auth failures are handled in
the catch block to avoid hanging the UI.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-16 10:53:03 -04:00
robert
4150267925
Add combat action log at /logs
...
Instruments 9 handlers (combat start/end/pause/resume, next turn,
participant add/remove/toggle, HP changes, conditions) to write
timestamped entries to a Firestore logs collection. New LogsView
at /logs shows entries newest-first with encounter context, and
includes a Clear Log button. Adds a View Logs link in the header.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-16 10:25:17 -04:00
robert
e23cea205a
Add HP toggle, new conditions, fix turn order sync bug
...
- Add DM toggle (default on) to hide player HP bars on player display;
persisted in activeDisplay Firestore doc for real-time sync
- Add Alchemist Fire and Bardic Inspiration conditions; sort all
conditions alphabetically
- Fix turn order skipping when participants are deleted, deactivated,
or killed mid-combat: turnOrderIds was never updated, causing
handleNextTurn to resolve currentIndex as -1 and snap back to the
first participant. Now all mutation paths (delete, toggle active,
HP death/resurrection) keep turnOrderIds in sync and advance the
turn pointer correctly when the current participant is removed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-16 10:00:17 -04:00
robert
6cd25dadaa
Alchemist Fire and Bardic Inspiration conditions, sort alphabetically.
2026-05-16 09:37:11 -04:00
robert
90cfb36b56
Adds a 'Hide player HP' toggle in the Combat Controls panel (on by default) that suppresses health bars for player characters in the DisplayView. Setting is persisted in the activeDisplay Firestore doc so it survives page reloads and takes effect in real time on the player screen.
2026-05-16 09:30:35 -04:00
robert
7676751a5b
Added weapon conditions
2026-04-26 17:12:29 -04:00
robert
16118dd958
Updated README.md and added CLAUDE.md
2026-04-26 11:42:22 -04:00
robert
33c93ab86b
Added conditions.
2026-04-26 10:37:25 -04:00
robert
451151628c
fixing build and nginx
2026-04-25 20:35:52 -04:00
robert
1e0df31cd4
More text improvements.
2026-04-25 20:25:34 -04:00
robert
3be9b0a921
Updated look of site.
2026-04-25 18:37:55 -04:00
robert
895fa06227
updated fix for adding combatants mid fight and added some death effects.
2025-12-13 19:15:26 -05:00
robert
82f45e60f0
Updated readme, and added a license.
2025-05-28 18:58:38 -04:00
robert
ceba7632f8
Update README.md
...
Just a little clean up.
2025-05-28 15:33:44 -04:00
robert
8cf3a49a76
Added collapsible Characters.
v0.2.1
2025-05-28 14:58:54 -04:00
robert
dda3453d79
version bump.
v0.2
2025-05-28 12:23:10 -04:00
robert
d754f8657c
Added small counters in Campaign cards.
2025-05-28 12:15:01 -04:00
robert
9563ce7959
fixed player display on added participant to live encounter
2025-05-27 14:52:04 -04:00
robert
5f8602cd73
changed red color for monster display.
2025-05-27 11:15:32 -04:00
robert
788e3cd1a2
Tightened up the UI a bit.
2025-05-27 11:02:03 -04:00