18 Commits
Author SHA1 Message Date
John SmithandClaude 4c1196b17d feat(gateway): session spotlight aggregation over self-reports (loop 3, iteration 33)
POST /sessions/{id}/spotlight/report accepts participant self-reports of
local speaking (0..600000ms, member seat only, per-IP tight spotlight
bucket); GET /sessions/{id}/spotlight returns per-roster-seat rolling
scores decayed at half-life 3min with is_quiet = score < mean - sigma
and an observed_at staleness stamp; DELETE clears scores (GM/admin).

Honesty contract: survey confirmed the CRDT speech ledger is real and
remote-aware at the client layer, but python has no read-path into the
Y.Doc (Node relay), so the self-report channel is the honest seam this
iteration can implement; every route states that nonzero values
originate from spoofable client self-reports (insight tooling for the
DM, not an authentication boundary). DirectorAgent remains unwired by
design — aggregation is built so a future iteration can feed it. The
legacy VoiceSpotlightTracker hardcoded demo roster is left untouched.

Gates: pytest 1347 passed / 33 skipped (baseline 1302, +45).

Co-Authored-By: Claude <[email protected]>
2026-08-26 16:59:11 -04:00
John SmithandClaude 68a69c44c1 feat(gateway): campaign sim exercises OA + ready/release reactions (iteration 81)
Deterministic per-seed tactical layer: pending-OA disclosures queue
opponent reaction attacks (host drives ownerless attackers), 15% seeded
ready actions release only when the structured trigger observably fired.
Reaction attempts count as valid attempts, never compliance failures;
decision_seed=None preserves legacy behavior byte-identically. 20 tests
red-first; pytest 989 passed / 29 skipped.

Co-Authored-By: Claude <[email protected]>
2026-08-25 22:32:19 -04:00
John SmithandClaude 6b43e7d90c feat(gateway): persistent campaign quest + faction state across restarts (iteration 47)
Autosave snapshot carries quest-graph and faction-state slots on the
existing campaign_saves JSONB; explicit POST /campaign/restore (GM-only,
ownership-scoped) reapplies them; readonly quest reads self-heal from the
newest owned save instead of rolling new canon. Corrupt slots → honest
422 *_CORRUPT; legacy saves restore cleanly. Inventory of memory-only
singletons audited and documented durable-vs-local. 9 tests red-first;
pytest 839 passed / 27 skipped.

Co-Authored-By: Claude <[email protected]>
2026-08-25 11:03:17 -04:00
John SmithandClaude 716c80c8dc feat(gateway): lobby ready flags + character binding + launch gating (iteration 33)
Per-member ready/selected_character_id persisted in MemoryStore and
Postgres (idempotent ALTER migration); member-scoped ready/character
routes with ownership validation; host launch refuses unready members
(409 with honest roster) unless host forces. Campaign sim readies seats
before launch. 7 new tests red-first; pytest 782 passed / 27 skipped.

Co-Authored-By: Claude <[email protected]>
2026-08-25 05:17:38 -04:00
John SmithandClaude 5551a321b7 feat(gateway): DirectorAgent wired to real campaign-sim tension signals (iteration 24)
Deterministic tension tracker: weighted components (hp swing/deaths/
disposition shifts/round pressure/quest stage) fold into exponential
smoothing over the sim's round loop; recommendations (raise_stakes,
introduce_complication, spotlight_player) derive from pure thresholds.
LLM only phrases hook text with provenance labels. Sim report gains a
director telemetry block; identical runs byte-identical. 35 tests
red-first; pytest 747 passed / 26 skipped.

Co-Authored-By: Claude <[email protected]>
2026-08-25 01:13:50 -04:00
John SmithandClaude 4e8477d08b feat(gateway): admin bootstrap allowlist, fail-closed secret, lobby membership gate (iteration 12)
Signup accepts only player/spectator — staff roles come from the
VTT_ADMIN_EMAILS allowlist (rotatable without restart). Gateway aborts
startup without AUTH_SECRET/VTT_ENGINE_SECRET, mirroring engine semantics.
GET /lobbies/{id} member-or-staff only with no existence oracle; invite
codes stay visible to members. 20 tests red-first; pytest 672 passed.

Co-Authored-By: Claude <[email protected]>
2026-08-24 21:14:10 -04:00
John SmithandClaude 703f5c1e00 fix: sixth-audit remediation — gate reliability + honesty corrections (iteration 84)
- Gate reliability: autouse conftest fixture clears the shared auth
  rate-limit windows around every test; full suite now 3x-consecutive
  green (was nondeterministically red via cross-module bucket pressure).
- Test quality over claim-laundering: computedHP gains the real SRD
  hit-die table (Wizard/Sorcerer d6, Barbarian d12, per-die average
  growth) — the old flat d8 fallback had been pinned by a test falsely
  citing "hit-die max"; tests now cite SRD values explicitly.
- Scripted-mode social phase force-pins llm_gateway=None so an
  LLM-gatewayed persona can't leak upstream calls the report claims
  never happened; no-network test extended with a recording gateway.
- Dynasty test tautology replaced with real lineage assertions.
- Ambience-honesty test derives expected ids from AudioManager recipes
  (source of truth) with a drift guard, not the copied list.
- Tracker honesty note appended to iteration 79: default quest output
  changed materially; only quest_id and summary preserved.

Gates: pytest 547x3 green, vitest 69 green, build 13.3s.

Co-Authored-By: Claude <[email protected]>
2026-08-24 15:32:44 -04:00
John SmithandClaude dac7f36d77 feat(simulation): multi-generation dynasty lineages, alliances, prestige (iteration 82)
Pillar 8 depth: extend_lineage compounds trait inheritance across
generations (0.65 base + 0.08/ancestor, capped 0.95) with atavism for
ancestral traits; form_alliance marries houses with dominance-weighted
trait pools (Iron Will 0.70 → Cursed Bloodline 0.15); deterministic
house_prestige from traits, pacts, feuds, and unbroken-bloodline depth;
lore injection emits generation-appropriate canon (young bloodline as
PROPOSED_FACT vs N-generation UNBROKEN as VALIDATED_CANON). Legacy API
and seed output pinned unchanged; probabilistic gates asserted exactly
via ScriptedRandom. 12 red-first tests; suite at 539.

Co-Authored-By: Claude <[email protected]>
2026-08-24 14:18:22 -04:00
John SmithandClaude e51bb2b8c0 feat(simulation): parametrized quest generation from curated theme tables (iteration 79)
The quest engine built one hardcoded intrigue DAG regardless of theme
args — rng instantiated but never used. Now: three curated theme tables
(court/crypt/wilderness with a new TRAVEL_HAZARD node type) drive node
types, titles, prompts, skills, and factions; party level scales DCs
and rewards; length plans 8/10/12-node DAGs; seed drives all selection
deterministically. Unknown themes raise instead of silently
substituting; thin tables truncate with an explicit coverage_note
rather than padding with invented filler. Legacy call signature and
default output preserved. 20 red-first tests; suite at 527.

Co-Authored-By: Claude <[email protected]>
2026-08-24 13:59:24 -04:00
John SmithandClaude 7a104a7ebf feat(simulation): Concordia social-dialogue phase in campaign simulation (iteration 80)
Pillar 5 depth: between combat rounds, players attempt one dialogue
against a designated social NPC — LLM decisions via the same strict-
JSON gateway path with stance-branched scripted fallback, replies from
injectable ConcordiaNPC personas (registry=None skips the phase
entirely, never faked), approaches mapped onto disposition kinds so
repeated hostility visibly shifts stances across rounds. Norms are
absolute in both directions: violating utterances never reach the NPC,
violating replies degrade to template — both surfaced as norm_rejected.
Deterministic sim-clock timestamps; 11 red-first tests; suite at 526.

Co-Authored-By: Claude <[email protected]>
2026-08-24 13:58:52 -04:00
John SmithandClaude fdca883144 feat(simulation): autonomous AI companion PCs with tactical roles (iteration 54)
GOALS.md Pillar 1's drop-in AI party members: tank / skirmisher /
healer roles execute coherent turns through the same authenticated
proxy path as campaign_sim (no second HTTP stack), with optional LLM
targeting refinement validated against known entities and per-turn
provenance accounting (decision_source, fallback_reason, degraded).
Honest realizability matrix: ally-heal triage from a plain player seat
is REFUSED rather than fabricated because the role projection redacts
other PCs' HP — the companion falls back to tank behavior instead.
19 red-first tests; suite at 425.

Co-Authored-By: Claude <[email protected]>
2026-08-24 06:22:25 -04:00
John SmithandClaude b4baa54546 feat(simulation): social-state telemetry in campaign simulation (iteration 24)
NpcDispositionEngine wired into CampaignSimulation: accepted attacks
record 'attacked' on the target's disposition toward the attacker
(rejected actions and non-attacks record nothing), decision prompts and
scripted-policy inputs receive each visible target's current stance
toward the acting player, and reports carry per-player end-of-run
stances plus interaction totals. All disposition timestamps use an
explicit sim clock — deterministic across identical runs; the engine's
clock is pinned so wall-clock can never fire. 'aided' hook deliberately
absent (no heal action reachable through proxies) and documented.
8 new tests; suite at 192 passed.

Co-Authored-By: Claude <[email protected]>
2026-08-24 02:36:38 -04:00
John SmithandClaude b4913c67ac feat(simulation): agent-driven campaign simulation harness (iteration 21)
The deferred flagship: synthetic players authenticate, host/join/launch
a lobby, deploy RBAC-owned characters, and take turns through the same
authenticated engine proxies real clients use. Decisions come from the
configured custom LLM endpoint via complete_json with strict decision
validation (unknown actions / malformed JSON / bad coordinates fall
back per-turn while still counting the attempt); no key means honest
scripted mode with zero network. Every LLM call flows through the
existing gateway so logs/llm_calls.jsonl captures it. Reports carry
only counted metrics with enforced invariants (accepted+rejected ==
attempted). 13 tests, fully mocked; __main__ entry runs live from .env.

Co-Authored-By: Claude <[email protected]>
2026-08-24 02:17:38 -04:00
John SmithandClaude 50fe903023 feat(simulation): genuine GOAP planner for faction simulation (iteration 13)
Replaces greedy first-fit with STRIPS-style forward search: actions
declare preconditions and effects (thresholds + delta wrappers), the
planner runs uniform-cost A* over world-state snapshots with
deterministic tie-breaking, dominance dedup, depth/expansion caps
bounding EspionageRaid's positive resource loop. Risk folds into
planning cost; execution stays deterministic. Legacy tick behavior is
preserved verbatim when no goal is set — same three actions, same log
lines — so existing callers are untouched. New API: set_goal/clear_
goal/plan/execute_plan/goal_progress_pending. 19 new tests including
optimality-over-greedy and legacy-equivalence pins.

Co-Authored-By: Claude <[email protected]>
2026-08-24 01:42:18 -04:00
John SmithandClaude 9b6caf12a3 feat(simulation): NPC disposition scoring engine (iteration 2)
Continuous directed relationship scores per (npc, player) pair per
GOALS.md Pillar 8: trust and fear with independent exponential decay
(fear half-life ~3.5x shorter), alignment-compatibility bias, NPC-level
stress that amplifies fear, event-driven interaction recording with
strict kind validation, stance banding (hostile..allied), and lazy
decay computed at query time so scores are pure functions of recorded
events. Injectable clock keeps it deterministic for replay/testing.
Pydantic v2 record model matches project conventions. 15 new tests.

Co-Authored-By: Claude <[email protected]>
2026-08-24 01:20:54 -04:00
John Smith 3ed3815820 feat: complete Horizons 1, 2, and 3 (Docker Compose, Procedural Quest Engine & Concordia Pacts, and 3D Elevation) 2026-08-22 19:49:55 -04:00
John Smith 8ef12b5e4d feat(dynasty-empirical-playtest): implement opendnd dynasty lineages, feud matrix, and dnddata empirical party benchmarks 2026-08-22 19:27:54 -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