6 Commits
Author SHA1 Message Date
John SmithandClaude a6af1c91e0 feat(gateway): Foundry module zip upload with hardening (iteration 40)
Replaces the multipart-transport 501: gm/admin-gated upload, zip-slip/
absolute-path/symlink rejection, double-enforced size+expansion caps
(413), manifest-root discovery delegating to the fail-loud importer.
501 reasons list updated to only still-true limitations. 10 tests
red-first; pytest 806 passed / 27 skipped.

Co-Authored-By: Claude <[email protected]>
2026-08-25 09:32:35 -04:00
John SmithandClaude 5f47c5a8dc feat(gateway): real hybrid dense+sparse RAG via fastembed (iteration 18)
Replaces hash pseudo-embeddings with BAAI/bge-small-en-v1.5 dense +
Qdrant/bm25 sparse legs fused by reciprocal-rank fusion over Qdrant
named vectors. Opt-in via QDRANT_EMBEDDINGS=1; offline fallback keeps
hash embedder relabeled qdrant-hash-fallback with an honest warning.
Live-verified semantically on a compendium subset. 27 new offline-safe
tests; pytest 713 passed / 25 skipped.

Co-Authored-By: Claude <[email protected]>
2026-08-25 00:24:15 -04:00
John SmithandClaude 30850a5e59 test(llm): opt-in live-LLM suite that never runs in CI (iteration 55)
pytest 'live' marker + conftest auto-skip unless LLM_KEY is set AND
RUN_LIVE_LLM=1 — structurally CI-proof. Six tests exercise the REAL
endpoint: mechanical/safety classification provenance, Concordia
generator-marker-vs-reality (a template marker while the endpoint is
alive FAILS), strict-JSON parsing, soft 60s latency budget, and a gate
proving non-mock configuration. Connection failures degrade to SKIP.

First live run surfaced two real integration bugs, reported honestly
as skips rather than fabricated passes: .env named a nonexistent model
that hangs instead of 404ing (fixed in .env), and the endpoint returns
text/event-stream even for non-streaming calls which breaks resp.json()
(fix iteration pending). Default suite unchanged: 406 passed / 8 skips.

Co-Authored-By: Claude <[email protected]>
2026-08-24 06:24:12 -04:00
John SmithandClaude 013677eb4d feat(wave13): UI/UX hardening — code splitting, dice history, a11y & honest ambience
Perf:
- Route-level code splitting (React.lazy + Suspense): entry chunk 1.9 MB → 241 kB,
  30 on-demand view/modal chunks, Vite chunk-size warning gone

Features:
- DiceHistoryPanel: session audit log of every engine-resolved roll with
  crit/fumble highlighting, 50-entry cap, localStorage persistence
- ShortcutsModal + global keys: `?` cheat-sheet, Escape closes top-most modal,
  typing guard; "Keyboard Shortcuts" entry in Cmd+K palette
- Real WebAudio ambience engine (startAmbience/stopAmbience/setAmbienceVolume):
  jukebox presets synthesize per-track noise+drone loops; play state is now
  honest (opens paused) and master slider is live

Bug fixes:
- pyproject: declare reportlab (6 test modules failed collection on fresh envs)
- Navbar clipped X-CARD at 1366×768: responsive collapse, 0 overflow 900→1920px
- Canvas tool rail clipped under character dock: flex-wrap + max-width
- Macro quickbar occluded ~80% of chat console: collapsed by default
- Alarm-fatigue sounds removed from pagination/mic-toggle/seat-pick

A11y:
- Global :focus-visible rings, prefers-reduced-motion, .selectable-text
- aria-labels on icon-only controls; all modal close buttons labeled + autoFocus
  so focus enters dialogs on open; unlabeled form fields fixed (0 remaining)

SEO: meta description, <main> landmark, robots.txt, spec-compliant llms.txt

Verified: cargo ✅, pytest 57/1 ✅, MCR 100% / HCI 1.0 ✅, build ~1s ✅,
Lighthouse 100/100/100, Chrome DevTools sweeps 900→1920px with 0 visible
overflows. Details in docs/improvement-log.md.

Co-Authored-By: Claude <[email protected]>
2026-08-23 15:16:15 -04:00
John SmithandClaude 6aef9e73b8 feat(wave12): Postgres persistence & campaign save/load
- storage.py: dual-mode store — PostgresStore (asyncpg pool) when
  DATABASE_URL is reachable, MemoryStore fallback otherwise; idempotent
  _ensure_tables() DDL at startup; PBKDF2 credential helpers centralized
- 03_campaign_persistence.sql: narrative_state.users, campaigns (anchors
  the previously free-floating campaign_id), campaign_saves (JSONB
  snapshots) + owner/updated index — also auto-run by compose init
- auth routes now persist users across restarts (verified live: seeded GM
  account survives process restarts via Postgres)
- new token-guarded API: POST /api/v1/campaign/save (upsert by owner+name),
  GET /campaign/saves, GET /campaign/save/{id}, DELETE /campaign/save/{id}
- client: CampaignSaveModal (save/list/load/delete with round + timestamp),
  Campaign Saves entry in Table Tools dropdown, snapshot build/apply in App
- fix compose postgres crash-loop on SELinux systems (:ro,z relabel flag)
- tests: memory-mode API CRUD always runs; PG end-to-end incl. cross-owner
  denial and durability-across-reinit skips without DATABASE_URL
  (58 pytest pass with Postgres up, cargo clean, MCR 100%)

Co-Authored-By: Claude <[email protected]>
2026-08-23 10:53:40 -04:00
John Smith 25a3301480 feat: complete Phases 1-7 enterprise autonomous AI-native virtual tabletop engine 2026-08-22 17:34:37 -04:00