david raistrick
ed67535b1f
Reapply "M2: fix ws adapter for browser WebSocket + firebase path prefix"
...
This reverts commit 74b4c2c42d .
2026-06-29 12:36:16 -04:00
david raistrick
17245dfa1b
Reapply "M2: gate storage init on STORAGE mode (firebase vs ws/memory)"
...
This reverts commit e843acdf8a .
2026-06-29 12:36:16 -04:00
david raistrick
e843acdf8a
Revert "M2: gate storage init on STORAGE mode (firebase vs ws/memory)"
...
This reverts commit 3e84f28325 .
2026-06-29 12:03:57 -04:00
david raistrick
74b4c2c42d
Revert "M2: fix ws adapter for browser WebSocket + firebase path prefix"
...
This reverts commit e743d40e8d .
2026-06-29 12:03:57 -04:00
david raistrick
d1ee69a70a
Revert "M3: stub db sentinel in ws/memory mode so legacy guards pass"
...
This reverts commit a5a4df78f0 .
2026-06-29 12:03:57 -04:00
david raistrick
a5a4df78f0
M3: stub db sentinel in ws/memory mode so legacy guards pass
...
ws/memory storage mode never set the module-level `db` variable. 24 handlers
guarded with `if (!db) return` early-exited, silently dropping all writes
(create campaign, add encounter, participant CRUD, combat, logs).
db stays a truthy sentinel object { __localStub: true } in non-firebase mode.
All real reads/writes route through storage.*; db only used by guards.
56 frontend tests green. Verified via headed browser: create campaign flow
works end-to-end (modal closes, campaign appears via WS realtime push).
2026-06-29 11:30:08 -04:00
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