232 Commits
Author SHA1 Message Date
jpmschweitzerandClaude Opus 4.6 abb509eb00 chore(meta): release v0.1.26
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:38:13 +01:00
jpmschweitzerandClaude Opus 4.6 51414b0b63 fix(simulation): address PR #89 review — version comment, settings contract, docs, dead process recovery
Must-fix: protocol version comment now references PROTOCOL_VERSION
(no hardcoded number), settings delete is idempotent no-op.

Suggestions addressed: BehaviorModifier dedup claim dropped, hash
collision safety documented, FK pragma in test store, columns_to_value
consolidated, modifier_hint mismatch logging, OffDuty test coverage,
batching tradeoff documented, unknown value_type warning, occluded
text risk documented, dead child respawn in voice worker, INJECT
block ambiguity documented.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:34:33 +01:00
jpmschweitzerandClaude Sonnet 4.6 b37583ddfc fix(simulation): address PR review items for #655 content removal
- line_pool.rs: add trace! when active_situations is empty (Layer 2
  will silently filter all lines — important for content debugging)
- knowledge_grant.rs: document serde(untagged) ambiguity hazard; add
  KnowledgeGrant::validate() for load-time field validation
- monologue.rs: annotate trigger_monologue as schedule ordering anchor;
  fix stale "periodic trigger cooldown tracking" doc reference in
  trigger_event_monologue (COOLDOWN_TICKS removed in #655)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 09:32:48 +01:00
jpmschweitzerandClaude Opus 4.6 50800cbf81 feat(simulation): composable behavior engine — action+modifier+context primitives (#633)
Replaces flat culture×zone×role behavior strings with three-layer
composition: BehaviorAction (role-generic), BehaviorModifier (culture
coloring), BehaviorContext (situation gating). Assembly at NpcBlueprint
instantiation. Backward compatible — falls back to legacy behaviors
when primitives are empty. D-139 filed, Q-057 resolved.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:12:07 +01:00
jpmschweitzerandClaude Opus 4.6 accbe579c9 feat(simulation): SQLite settings storage with IPC protocol v20 (#627)
Per-player settings via rusqlite (bundled, zero runtime dep). Server
owns the settings DB; client sends ChangeSettings commands over IPC.
Extensible key-value with typed columns (String/Int/Float/Bool).
Protocol bumped to v20 with settings_response in ObserverSnapshot.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:11:53 +01:00
jpmschweitzerandClaude Opus 4.6 1a4fd578cc feat(simulation): voice pipeline integration — Factual bypass, observer wiring, tell iteration (#650 #652 #651)
ContentType::Factual bypasses LLM for fact-bearing lines (numbers,
denials). Observer enrichment systems rewrite dialogue/conversation
text with voiced versions before snapshot assembly. Friendly and
RoutineDeviation tells get concrete surface-pattern examples.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:11:44 +01:00
jpmschweitzerandClaude Sonnet 4.6 ce0df2f320 refactor(simulation): remove v0.1 content loading system (#655)
Delete the hand-authored YAML content pipeline (server/src/content/) superseded
by the v0.2 generator-first approach (D-122, D-128). Runtime ECS types that were
co-located with content loading have been extracted to dedicated simulation modules:

- simulation/triangle.rs: TriangleState, TriangleCrisisEventQueue, tick/resolve systems
- simulation/line_pool.rs: LinePoolIndex, AccessTier, TrustTier, Mood, LinePoolIndexResource
- simulation/knowledge_grant.rs: KnowledgeGrant, Prerequisites

Monologue systems (trigger_monologue, trigger_recognition_monologue,
trigger_event_monologue) now use hardcoded fallback lines only; the
ContentStoreResource branch and select_pool_line function are removed.

Deleted: content/{loader,types,line_pool,hot_reload,spawn,instantiation,entanglement,mod}.rs
Deleted: tests/{content_loading,content_runtime,content_scaling,template_instantiation,template_schema}.rs
Deleted: bin/line_preview.rs (v0.1 tool)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 09:07:57 +01:00
jpmschweitzerandClaude Opus 4.6 441164fe23 chore(meta): release v0.1.25
Sprint 25: Emerge — generator extrapolation from minimal input,
voice pipeline spikes (D-138), behavior dedup, Want/State layer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 19:53:10 +01:00
jpmschweitzer ecbe905071 Merge remote-tracking branch 'origin/server'
# Conflicts:
#	CHANGELOG.md
2026-03-07 19:52:08 +01:00
jpmschweitzerandClaude Opus 4.6 9f34d030d7 feat(voice): complete Spike 2 voice pipeline with quality-tested prompt engine
Spike 2 delivers the full voice pipeline: queue → worker pool → sr-voice
child process (stdio JSONL) → cache → disk. Three rounds of quality testing
with Paula, Mellanie, and Gestalt produced iterative prompt improvements.

Prompt engine (prompt_builder.rs):
- Example-based epistemic marker integration (not keyword lists)
- Length-aware Angry tell variant (preserves facts on long content)
- Double-prompt technique: REMEMBER block repeats constraints near OUTPUT:
- Imperative injection framing (composition engine controls frequency)
- Anti-invention constraint ("do not add information not in the input")
- Universal RULES cleaned: worldbuilding moved to culture personas

Worker pool (worker.rs):
- Output post-processor strips after first newline (prevents prompt leakage)
- Watchdog poll loop (1s ticks) replaces blocking sleep for cancel
- Child health check before writing (try_wait)

Test infrastructure:
- voice_pipeline.rs: end-to-end test, auto-detects real sr-voice or mock
- voice_quality_batch.rs: 39 edge-case prompts for quality review
- mock-stdio.sh: Python JSONL mock for CI (no model needed)
- Makefile targets: test-voice-mock, test-voice-real

Quality results (Gemma 2B Q4_K_M, CPU ~13 t/s):
- Epistemic markers: naturally integrated (round 1 comma-lists fixed)
- Tell differentiation: 3/5 working (Nervous, Guarded, Angry)
- Information preservation: ~90% (up from ~70%)
- Prompt leakage: eliminated
- Open: Friendly/RoutineDeviation tells inert (#651), Factual bypass (#650)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 19:20:06 +01:00
jpmschweitzerandClaude Opus 4.6 e93a9e8b70 fix(voice): address PR review findings — 3 critical, 5 warning, 4 suggestion
Critical fixes:
- Pause mechanism: workers now hold requests during pause instead of
  dropping them. Queue and worker pool share the same AtomicBool flag
  via VoiceQueue::paused_flag(). Submit() rejects while paused.
- Seed type: sr-voice accepts u64 seeds over IPC (explicit u32 truncation
  for llama.cpp sampler, documented).

Warning fixes:
- HashMap → BTreeMap in cache.rs and worker.rs (D-010 determinism mandate).
  Added Ord derives to CacheKey, ContentType, TellCategory.
- VoicePipe::generate() watchdog kills child after 120s timeout to prevent
  indefinite blocking on read_line.
- VoiceCacheStore Drop impl calls save_all() on shutdown.
- trait-modifiers.ron: fixed 3 wrong trait names (Impulsive→Compassionate,
  Methodical→Incurious, Stubborn→Ruthless) to match PersonalityTrait enum.

Suggestion fixes:
- Worker spawn: log error + reduce pool instead of panic on thread failure.
- on_battery(): added macOS detection via pmset.
- Epistemic markers: lowercased constants, removed redundant to_lowercase().
- cache.rs: documented non-atomic write tradeoff.
- queue.rs: reprioritize() bypasses pause check (it runs during pause).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:11:46 +01:00
jpmschweitzerandClaude Opus 4.6 0b0fa8c04e refactor(voice): replace HTTP with stdin/stdout IPC for sr-voice workers
Gemma 2 T&C compliance: exposed HTTP ports allow mods or external code
to reach the model, complicating license enforcement. Switch to piped
stdin/stdout (JSONL protocol) so the model is only reachable through
the game server's internal queue.

- worker.rs: VoicePipe owns Child + piped stdin/stdout, VoiceProcessConfig
  replaces port-based config, workers spawn their own sr-voice child
- hardware.rs: remove VoiceInstanceManager (port/process lifecycle),
  replace with evaluate_scaling() free function + HardwareProbe::voice_config()
- sr-voice: add --stdio flag to serve command, new stdio.rs JSONL mode
- Remove ureq dependency from server crate (no longer needed)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 17:57:32 +01:00
jpmschweitzerandClaude Opus 4.6 be6f2a3db9 feat(voice): add hardware detection + dynamic sr-voice instance management (Phase 4)
GPU-aware scaling: NVIDIA (nvidia-smi), AMD (sysfs VRAM), Apple Silicon
(unified memory). GPU mode detected at install, persisted to settings.
Scaling ceiling: (free_resource - existing_llm_usage) / 2 / per_instance_cost.
VoiceInstanceManager spawns/stops sr-voice processes on unique ports.
Battery detection scales to 1 worker.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 17:32:20 +01:00
jpmschweitzerandClaude Opus 4.6 fafa1c49b8 feat(voice): stub voice cache lookup for behavior text (Phase 3)
Add lookup.rs with voiced_behavior() — ready to wire into a behavior-serving
system once one exists (Q-058). Tell behaviors always passthrough (never
re-voiced). Cache miss returns base text (graceful degradation).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 17:13:15 +01:00
jpmschweitzerandClaude Opus 4.6 82a911f3aa feat(voice): add cache, queue, and worker modules (D-138, Spike 2 Phase 2)
MessagePack voice cache with per-zone persistence and version invalidation.
Priority work queue with crossbeam bounded channel, backpressure, pause/resume,
and zone-change reprioritization. Inference worker pool with empty output guard
and graceful degradation to base text.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 17:09:24 +01:00
jpmschweitzerandClaude Opus 4.6 33030fcc58 feat(engine): voice pipeline Phase 1 — composition engine and data model
Add the voice pipeline composition engine (D-138 Spike 2, Phase 1):

- voice/prompt_builder.rs: full prompt assembly from culture profile,
  tell state, and base text. Handles occasional injection gating,
  epistemic marker extraction, content-length-gated tell injection.
  16 unit tests.

- blueprint.rs: CultureProfile gains voice_persona, voice_examples,
  occasional_injections fields. NpcBlueprint gains tell_behaviors.
  OccasionalInjection struct with kind discriminator (oath/faith/
  hesitancy/etc), frequency, and tell-suppression gating.

- culture-krenn.ron: v2 voice injector from Spike 1 — persona block,
  3 examples, oath injection at 0.25 frequency.

- D-138 amended: Phi-3 dropped entirely, exact Gemma 2B provenance
  documented. Model file renamed to gemma2.gguf.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 16:35:39 +01:00
jpmschweitzerandClaude Opus 4.6 1b58d8f949 feat(engine): add sr-voice LLM inference service for NPC voice pipeline
Standalone Rust crate wrapping llama-cpp-2 for GGUF model inference.
Persistent HTTP server architecture — model loaded once, requests
processed sequentially, zero CPU contention by construction.

Subcommands: serve (load model, listen), generate (single prompt),
batch (JSONL), benchmark (5-run average). Makefile targets for
build/serve/run/stop workflow.

Spike 1 validated: Gemma 2B Q4_K_M at ~16 t/s CPU, 4 cultures
tested (Krenn, Ireland, Shek'na, Aranthi), composition-engine
oath injection mechanism proven. GO for Spike 2.

Refs: D-138, #639

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 15:44:37 +01:00
jpmschweitzerandClaude Opus 4.6 c3a8dcc481 feat(simulation): name dedup, behavior dedup, relationship pipeline, Want/State layer (#628 #629 #631 #632)
Four generator spike improvements in one pass:

- #628: Fix name pool first-pick bias. build_name_pool now derives a
  zone+culture-specific ChaCha20 RNG via FNV-1a mixing of (seed,
  zone_type, culture_id), isolating name ordering from main RNG
  consumption. Different zone types with the same seed now produce
  different first names.

- #629: Behavior dedup within a zone run. build_behavior_pools
  pre-shuffles each role's behavior list; gen_behaviors draws without
  replacement. Falls back to random repeat with warning when pool
  exhausts.

- #631: Relationship-to-behavior pipeline. Third generation pass
  (~50% chance) replaces primary behavior with relationship-revealing
  action — rivals talk past each other, friends drift together,
  subordinates defer.

- #632: Want/State layer. NpcWant enum (Neutral/Bored/Alert/Suspicious/
  AvoidingSomeone/LookingForInfo) biased by traits and role. Fourth
  generation pass produces observable tells that leak internal state
  through behavior. AvoidingSomeone resolves against negative-valence
  relationships for named targets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 11:26:48 +01:00
jpmschweitzerandClaude Opus 4.6 4b57006a5c chore(simulation): remove duplicate TODO and dead binding in generator spike
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 08:48:20 +01:00
jpmschweitzerandClaude Opus 4.6 a54b9d24e0 fix(simulation): address PR #87 review — name collision, validation, and polish
- Fix critical name collision: shuffle+pop for unique NPC names (#3)
- Validate population_density >= 1 in generator and validator (#4)
- Guard against empty given_names/roles with validator warnings (#5)
- Extract filler word cap to MAX_FILLER_WORDS constant (#6)
- Fix cultural behavior gate checking wrong field (#7)
- Document intentional one-directional relationships (#8)
- Validate min_npcs <= max_npcs in validator (#9)
- Fix validate-ron script realpath error handling (#10)
- Add TODO comments for spike-specific code duplication (#11, #12, #13)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:50:33 +01:00
jpmschweitzerandClaude Opus 4.6 0f83c64e8f feat(simulation): generator spike binary — template assembly Phase 1 (#612)
Add generator-spike binary producing NPC rosters from hardcoded zone and
culture stubs. Deterministic via SimRng, supports rural and industrial
zone types with Krenn culture. Phase 2 (RON file loading) wired via
--from-files flag, awaiting copy team deliverables (#609, #610).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:39:36 +01:00
jpmschweitzerandClaude Opus 4.6 fb3ebf4313 feat(simulation): NpcBlueprint struct design, RON schema, and validator CLI (#611)
Define ZoneSpec, CultureProfile, and NpcBlueprint structs with serde/RON
deserialization. Ship example RON files as schema contract for the copy
team (#609, #610). Add validate-ron CLI for copy team to lint their files
without compiling the server.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:39:27 +01:00
jpmschweitzerandClaude Opus 4.6 5f6a42000b chore(meta): release v0.1.24
Sprint 24: Signal — 10/10 tickets done.
Character archetype selection, triangle activation consumer,
news ticker HUD, proximity monologue lines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:00:08 +01:00
jpmschweitzerandClaude Opus 4.6 63bb6ff7c7 chore(db): replace Commonwealth with Settled Reach in tooling and server
Updated docstrings in sqlite_connector, qdrant_connector,
decisions_sync, schema.sql, and two doc comments in generator.rs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 11:26:59 +01:00
jpmschweitzerandClaude Opus 4.6 9ed6094d69 fix(simulation): address PR #85 review — warnings and polish items
- Ticker rotation: document sliding-window semantics (vs modulus-aligned)
- Ticker zone ID: add warning about Gauntlet vs production zone ID mismatch
- Proof-room movement profile: respect archetype instead of hardcoding smuggler
- Storyteller tie-break: use exact f32 equality (inputs are discrete integers)
- Observer: .map().flatten() → .and_then() (clippy strict)
- Content loader: remove dangling doc comment before section header
- Tests: replace assert!(false, ...) with TODO comments in ignored tests
- Tests: add frame limiter note on 302-update loop in tell expiry test

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 10:59:38 +01:00
jpmschweitzerandClaude Opus 4.6 fd824a1028 test(simulation): Sprint 24 tests — archetype, tell escalation, ticker, v0.1 playthrough (#593, #595)
- 7 archetype→monologue regression tests (smuggler/detective pool partitioning)
- 3 tell escalation unit tests (RoutineDeviation insertion + expiry)
- 6 news ticker tests (pool loading, SimRng rotation, zone gating)
- 3 live integration tests against real server binary (Layer 3)
- Update existing tests for current_ticker field and protocol v19

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 09:13:24 +01:00
jpmschweitzerandClaude Opus 4.6 3194a6e491 feat(simulation): character archetype, tell escalation, and news ticker (#587, #589, #591)
- Add character_archetype to StartupMessage with serde default (Detective)
- Bump PROTOCOL_VERSION to 19
- Add escalate_tells_on_activation() and expire_routine_deviations() systems
- RoutineDeviation inserted on triangle NPCs with 300-tick TTL
- Add TickerPool resource with deterministic SimRng rotation (200 ticks)
- Emit current_ticker in ObserverSnapshot when player is in bar zone
- Load ticker YAML from district content directories

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 09:13:03 +01:00
jpmschweitzerandClaude Opus 4.6 ac763fef97 feat(engine): live server visual tests and gauntlet snapshot replay
Add live server lifecycle to tests/run-visual (start/stop server per
scenario, parse LISTENING:{port}). Add MessagePack snapshot replay to
visual_capture.gd via Protocol.decode_snapshot() — exercises the full
client pipeline from wire bytes to rendered fog. Three replay scenarios
(hub_spawn, fog_theater, hub_after_movement) plus one live scenario
(fog_live_hub). Add gen_gauntlet_fixtures.rs to produce .msgpack fixtures
from the Gauntlet test world. Add max_diff_pct threshold to visual-diff.
Makefile: add fixtures-gauntlet target, fix build-client double-import,
preserve .godot cache in clean.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 08:41:09 +01:00
jpmschweitzerandClaude Opus 4.6 f7852b93ac chore(meta): release v0.1.23
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 23:27:06 +01:00
jpmschweitzerandClaude Opus 4.6 ac68ec6eef fix(simulation): address PR #81 review — critical and high-priority issues
Critical fixes:
- storyteller: replace .expect() with guard + log in activation_pass (Hoshe #1)
- content/loader: validate inverted tile_bounds before iteration (Hoshe #C)
- save_io: persist ActivationState on save/load (Tyre #7)

High-priority fixes:
- storyteller: f64 intermediate for observation_time_ticks scoring (Hoshe #A)
- storyteller: deduplicate copresent entities before scoring (Hoshe #B)
- storyteller: skip activation_pass at tick 0 (Hoshe #G)
- storyteller: explicit .before(advance_tick) ordering (Tyre #9)
- save_state: insert EngagementRecord on NPC deserialize (Tyre #10)
- save_io: reset TriangleActivatedQueue + MovementHistoryBuffer on load (Tyre #8)
- debug: validate teleport target walkability (Hoshe #E)
- debug: reject SkipToContamination when tick past delay (Hoshe #F)
- debug: DebugEnabled defaults to cfg!(debug_assertions) (Hoshe #3)
- debug: log when response overwritten (Hoshe #2)
- content/loader: error on tile dimension mismatch (Hoshe #5)
- content/types: DistrictMeta.description optional (Hoshe #D)
- types: version docs updated to v18 (Tyre #1, #2, #3)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 23:40:59 +01:00
jpmschweitzerandClaude Opus 4.6 c797a72fc2 chore(simulation): update tests and fixtures for Sprint 23
- Add debug_response: None to all ObserverSnapshot constructors in
  integration tests
- Bump PROTOCOL_VERSION assertion 17 → 18 in serialization tests
- Regenerate golden proof_room_tick_10.json (BoundaryWall tiles)
- Regenerate client msgpack fixtures for new snapshot fields
- Fix debug.rs resource optionality (Option<ResMut> for
  ContaminationActive/EventQueue)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 19:12:19 +01:00
jpmschweitzerandClaude Opus 4.6 c30197db0e feat(simulation): add debug console server and LOS boundary wall margin
Debug and LOS tracks for Sprint 23 (#580, #584):

- DebugCommandKind enum with 10 variants (AdvanceTicks,
  SkipToContamination, TeleportToPosition, ForceContaminationActivate,
  InspectNpc, ListTriangles, ListPopulation, GetContaminationStatus,
  TeleportToLocation, ForceTriangleActivation)
- DebugResponsePayload on ObserverSnapshot, handle_debug_commands
  system gated by DebugEnabled resource
- PROTOCOL_VERSION bumped 17 → 18
- VisibilitySector::BoundaryWall variant — 1-tile wall margin beyond
  LOS boundary included in visible_tiles (not exploration/memory)
- compute_boundary_walls() pass in NaturalVision after FOV+cone

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 19:12:08 +01:00
jpmschweitzerandClaude Opus 4.6 50f5d6c22e feat(simulation): add storyteller engagement tracking and activation pass
Storyteller chain for Sprint 23 (#570, #571, #572, #579):

- EngagementRecord component: per-NPC observation_time_ticks,
  conversation_count, monologue_trigger_count — incremented by
  perception, dialogue, and monologue systems
- MovementHistoryBuffer resource: ring buffer of player positions
  over last 3000 ticks with npcs_copresent_in_window() query
- Lifecycle rules: single activation per session, no concurrency,
  no cooldown, terminal resolution constants
- activation_pass() system: gate check, proximity query, engagement
  scoring, unentangled-NPC routing, module selection, emits
  TriangleActivatedEvent on 10-tick cadence after contamination

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 19:11:54 +01:00
jpmschweitzerandClaude Opus 4.6 7fbfc5ae65 feat(simulation): add tile-type layer, content loader, and chunk streaming
Spatial chain for Sprint 23 (#576, #577, #578):

- TileKind enum (Floor/Wall/Void/Restricted) on WalkabilityMap with
  set_tile_kind/tile_kind API, backward-compatible with existing
  is_walkable/set_walkable
- Location YAML tile format: tiles as string arrays (F/W/V/R chars),
  load_location_tiles() stamps tile data onto WalkabilityMap from
  ContentStore on production startup
- Chunk streaming system: ChunkLoadRadius + ChunkStreamingCadence
  resources, loads/unloads chunks around player position on cadence.
  v0.1 radius covers full district (no streaming stutter)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 19:11:42 +01:00
jpmschweitzerandClaude Opus 4.6 7231b28850 chore(meta): release v0.1.22
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 17:25:31 +01:00
jpmschweitzer 24b9a7a0cc Merge remote-tracking branch 'origin/server'
# Conflicts:
#	CHANGELOG.md
2026-02-28 23:55:42 +01:00
jpmschweitzerandClaude Opus 4.6 282dad8d50 fix(simulation): address all round 3 PR review issues
- Register StorytellerPlugin in main() and dump_schedule_graph() so
  contamination system runs in production (critical, rounds 2+3)
- Add doc comment to z_bands_connected clarifying band indices vs
  absolute z-levels (D-110)
- Add TODO on hardcoded modifications: vec![] in save_to_file
- Init ContaminationActive in minimal_world() test helper
- Replace ChaCha20Rng with SimRng in fuzzy_map tests (D-010)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:48:03 +01:00
jpmschweitzerandClaude Opus 4.6 d3217c5ae3 fix(simulation): replace f32 fields in generator with integer types
BlockPlacement.street_width_factor (f32) → street_width_bps (u16,
basis points where 10000 = 1.0×). BlockSkeleton.density (f32) →
density_pct (u8, 0–100 percentage). Eliminates latent f32
non-determinism per D-010 principle 1.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:25:02 +01:00
jpmschweitzerandClaude Opus 4.6 339f112c8f fix(simulation): fix triangle state save/load and persist contamination
Three save/load bugs fixed:
- ContaminationActive not persisted in SaveStateV1 — caused double-fire
  of contamination pressure on reload after tick 300.
- Loaded triangle entities missing ActiveSim marker — made them
  invisible to escalation and contamination systems after any load.
- Existing triangle entities not despawned before load — created
  duplicates, doubling tension escalation per tick.

Also: HashSet → BTreeSet for D-010 compliance, defensive event queue
reset on load, and three regression tests for triangle roundtrip.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:24:56 +01:00
jpmschweitzerandClaude Opus 4.6 70de959ac3 fix(simulation): correct CONTAMINATION_DELAY_TICKS from 1800 to 300
The constant was supposed to represent 30 game-minutes but the formula
was wrong (30 × 10 tps × 60s = 1800). Correct derivation: 30 minutes ×
TICKS_PER_GAME_MINUTE (10) = 300. Now uses the canonical constant
directly. Also fixes stale assertion message in integration test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:24:47 +01:00
jpmschweitzerandClaude Opus 4.6 50aba3adf6 fix(client): address PR #78 review comments
- Widen world_seed entropy from u32 to full u64 by combining two randi()
  calls (Hoshe warning #1)
- Persist world_seed to save directory and restore on resume_game() so
  loaded sessions maintain D-010 deterministic replay (Tyre warning #2)
- Constrain EntanglementConfig intrigue range based on flat value so
  mundane_ratio stays within D-029 spec [45,55]% (both reviewers)
- Remove dead VIS_PERIPHERAL constant and _grow_bounds() method
- Update test_client_p1 peripheral test for forward-only simplification
- Fix misleading exp_fade shader comment (filter_nearest = hard step)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:11:17 +01:00
jpmschweitzerandClaude Opus 4.6 3cd3a998c0 test(simulation): add fuzzy tests for procedural map generation (#509)
50-seed randomized testing against 4 structural invariants:
walkable connectivity (BFS), entity bounds, door adjacency,
and minimum tile count floor. Includes generator module for
test-scoped procedural map creation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 16:34:58 +01:00
jpmschweitzerandClaude Opus 4.6 b126e1830d feat(simulation): add contamination activation mechanic (#254)
Timer-based storyteller system fires after 1800 ticks (30 game-min).
Sets ContaminationActive resource, applies tension delta to all
ActiveFork triangles, and emits ContaminationEvent for downstream
monologue/behavioral hooks. Q-017 fallback constants in place.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 16:34:47 +01:00
jpmschweitzerandClaude Opus 4.6 42febf4059 feat(simulation): wire NPC pool generation and authored triangle instantiation (#176, #188)
Production startup now spawns 23 Sova NPCs with EntanglementTag
(Flat/Intrigue) based on triangle_membership. Three-phase spawn:
entity creation, cross-reference resolution, and authored triangle
instantiation. Five triangles (3 ActiveFork, 2 PassiveTension per
D-087) with deterministic IDs via FNV-1a hashing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 16:34:36 +01:00
jpmschweitzerandClaude Opus 4.6 daae3dd6ab feat(simulation): add Zone Gate gauntlet room and zone crossing detection (#512)
New test_world room with two zones (Terminal/Corridor) separated by
a door. Adds ZoneCrossEventQueue resource and detect_zone_crossings
system to fire events when the player crosses zone boundaries.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 16:34:21 +01:00
jpmschweitzerandClaude Opus 4.6 61eb40fcab feat(simulation): add modifications data model stub (#567, D-112)
DLC entry point for future player construction system. Adds
Modification struct, ModificationType enum, and Modifications
component. Wired into SaveStateV1 with #[serde(default)] for
forward-compatible save format.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 16:34:08 +01:00
jpmschweitzerandClaude Opus 4.6 d591f44b35 feat(simulation): add world_seed IPC and EntanglementConfig (#175, #178)
Implements the StartupMessage protocol: client generates world_seed in
SessionManager.new_game(), sends it after handshake, server uses it to
seed SimRng and sample EntanglementConfig.

EntanglementConfig samples flat ∈ [25,35]%, intrigue ∈ [15,25]%, mundane
as remainder (D-029). Same seed produces identical config (D-010
determinism). Different seeds produce distinct configs in ≥90% of pairs.

Protocol flow: HandshakeMessage (server→client) → StartupMessage with
world_seed (client→server) → SimRng initialization → tick loop.

10 Rust tests (determinism, variation, bounds, sum invariant).
9 GDScript test stubs + 2 encode tests for client-side pipeline.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 14:26:31 +01:00
jpmschweitzerandClaude Opus 4.6 2016e9a725 refactor(simulation): simplify vision cone to forward-only 120° arc
Remove the peripheral sector (100° half-angle, reduced range) and blind
spot classification. The server now sends only tiles within the 120°
forward cone; the client renders previously-explored tiles behind the
player with a light fog overlay instead.

This eliminates complexity in both the cone classifier and the snapshot
protocol while preserving the core information asymmetry — you still
can't see behind you, and the monologue system (D-016) still bridges
the perceptual gap.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 12:19:38 +01:00
jpmschweitzerandClaude Opus 4.6 a69e69e663 feat(perception): ground vision cone in human sensory physiology
- Visible half-angle 150° → 100° (200° arc), matching average human
  binocular field. Blind spot widens from 60° to 160° — genuine
  vulnerability behind the character.
- Forward half-angle stays at 60° (120° arc) — binocular overlap zone.
- Peripheral zone represents combined sensory awareness: visual
  periphery + subconscious sound/motion tracking, not just eyes.
- Per-character VisionConeConfig allows implants and perception modes
  (D-017) to widen beyond the unaugmented baseline.
- Fog shader: smooth back-edge gradient via smoothstep blend between
  Layer 2 (peripheral) and Layer 3 (deep fog), eliminating blocky
  stair-stepped tiles at the rear of the vision cone.
- D-015 updated with physiological basis and per-character config.
- D-017 updated with vision cone modification by perception modes.
- D-020 updated with protocol versioning policy: PROTOCOL_VERSION
  gates wire format, not gameplay parameters.
- DB backup after sprint 21 close.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 22:31:29 +01:00
jpmschweitzerandClaude Opus 4.6 dd00a9cd9e fix(simulation): address PR #75 review — vision components, triangle validation, FNV-1a, KG gating
1. CRITICAL: spawn_template_npcs now inserts NpcVisionState, NpcMemory,
   PlayerAwareness on template-spawned NPCs — matches spawn_npc() pattern
   from PR #66. Without these, template NPCs were invisible to vision and
   awareness systems.

2. WARNING: generate_intra_template_triangles now calls validate_triangle_def
   before generating TriangleState — mirrors cross-template path. Updates
   test TriangleDefs and logistics-hub.yaml to pass all three quality checks
   (conflict viability, relationship coherence, interest divergence).

3. WARNING: state_hash in compute_observer_snapshot now uses FNV-1a instead
   of DefaultHasher — consistent with D-010 principle 4 and the pattern in
   TemplateId/TriangleId. Updates golden file for new hash value.

4. WARNING: TriangleCrisisEventWire.role_assignments now filtered against
   observer KnowledgeGraph — unknown NPCs redacted from wire event per
   D-010 principle 2 (information boundaries).

5. WARNING: ActiveTemplateInstances::insert now despawns previous instance
   entities before overwriting — prevents orphaned ECS entities.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 19:02:43 +01:00