Commit Graph
31 Commits
Author SHA1 Message Date
jpmschweitzerandClaude Opus 4.6 aa79dd97e7 fix(simulation): Clippy cleanup and CI enforcement (#635)
Fix all Clippy warnings across the server codebase (2411 insertions, 1341
deletions). Raise type-complexity-threshold to 750 and too-many-arguments
to 12 in .clippy.toml for idiomatic Bevy ECS system signatures. The server
now passes `cargo clippy -- --deny warnings` cleanly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 10:33:15 +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 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 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 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
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 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 d31ac1cc70 feat(simulation): error handling and recovery — panic supervision, state hash, structured errors (#85)
Protocol v17: add state_hash (desync detection) and sim_errors
(structured error reporting) to ObserverSnapshot. Add SimError,
SimErrorKind, SimErrorBuffer types. Wrap main loop app.update() in
catch_unwind — on panic, send a final SimError snapshot before exit.
Report recoverable deserialization errors to client via SimErrorBuffer.
Compute per-tick state hash from player position + NPC count + tick.
Update all test fixtures and golden files for protocol v17.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 17:46:27 +01:00
jpmschweitzerandClaude Opus 4.6 6ed8d11502 feat(simulation): Sprint 19 — 7 server systems
Protocol handshake (#555): HandshakeMessage as first IPC frame,
HandshakeState resource, forward-compatible input handling.

State serialization (#96): serialize_npc_to_frozen/deserialize with
full D-024 axis coverage (10 new optional fields on NpcSaveState).

Scope tags (#98): ScopeTagKind enum, ScopePinned marker, automatic
assignment from KnowledgeGraph and RelationshipGraph.

Timestamp eviction (#97): LastInteractionTick, SimSpacePressure,
BinaryHeap LRU eviction respecting ScopePinned entities.

Save/load (#553): save_to_file/load_from_file via MessagePack,
SaveGame/LoadGame IPC commands, SaveLoadResultWire on snapshot.

Test infrastructure (#200): Layer 3 integration test entry point,
three-layer architecture documented per D-030.

Information boundary tests (#272): 4 negative tests proving no
passive KG leakage, LOS fog holds, tier boundary holds, save
isolation per NPC.

1063 tests passing, 0 failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 12:13:03 +01:00
jpmschweitzerandClaude Opus 4.6 28e7e6d9ad feat(simulation): add NPC name masking with role labels and color index
Server-side infrastructure for information asymmetry in dialogue.
NPCs display role labels (Worker, Supervisor, Patron) instead of
real names until the player explicitly learns them via KG lookup.
NpcColorIndex (stable_id % 8) persists across name reveal.

ConversationEvent and DialogueResponseEvent carry display names +
color indices on the wire with serde(default) for compat.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 13:42:59 +01:00
jpmschweitzerandClaude Opus 4.6 e047218ad2 fix(ci): remove duplicate doc comment, add rng_seed serialization tests (#344, #527)
Review fixes: deduplicate dump_schedule_graph doc comment,
add rng_seed round-trip test and v9→v10 backward compat test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 15:05:56 +01:00
jpmschweitzerandClaude Sonnet 4.6 a71218f6bc feat(ci): tracing JSON format in CI, tick duration logging, schedule dump (#344, #346)
Tracing (#344):
- Add 'json' feature to tracing-subscriber dependency
- Emit JSON log format when CI=true or RUST_LOG_FORMAT=json is set
  (structured log ingestion in CI pipelines)
- Add tracing::debug! with tick_ms/budget_ms/over_budget fields on each
  tick for performance profiling and tier system debugging prerequisite

Schedule dump (#346):
- Add --dump-schedule CLI flag that prints bevy_ecs schedule graph and exits
  without requiring TCP bridge or world setup
- Add make debug-schedule target for CI artifact generation and diff-based
  regression detection of unintended system reordering

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 14:15:46 +01:00
jpmschweitzerandClaude Opus 4.6 09eb6d7582 refactor(simulation): address PR #32 review — 14 items from Hoshe + Tyre
Hoshe (code quality):
- Remove dead RoomMember component from reset.rs
- Remove execute_reset (dual API trap); plan_reset is sole production path
- .unwrap() → .expect() on reset_plate in setup_gauntlet boot path
- Add 10s read timeout to TCP runtime test (prevents hangs)
- Register player in EntityRegistry in runtime boot test
- Document room_at z-range and corridor overlap assumptions
- Derive entity count from EXPECTED_ENTITY_COUNT constant (was hardcoded 24)
- Add reset plate (49-51) verification to stable_id_ranges_match_spec
- Add debounce exact boundary test (tick 9 rejected, tick 10 accepted)

Tyre (architecture):
- Gate test_world rooms/constants/setup behind "gauntlet" feature (default-on);
  reset module stays always-compiled (production dependency via input system)
- Document setup_gauntlet scheduler bypass for future tracking
- Extract runtime TCP test to content_runtime.rs (separate failure modes)

507 tests passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 09:45:17 +01:00
jpmschweitzerandClaude Opus 4.6 e66352e0ea feat(simulation): sprint 9 gauntlet — test infrastructure and first 3 rooms
Add Gauntlet test world with 3 rooms (Inventory Warehouse, Occlusion
Corridor, Pause Chamber) + Central Hub, room constants module, room
reset trigger mechanism, Layer 3 subprocess integration test, golden
file comparison engine and test suite, and content runtime validation.

Tickets: #482, #484, #485, #487, #488, #489, #490

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 02:25:57 +01:00
jpmschweitzerandClaude Opus 4.6 d5a1f6dadb refactor(simulation): apply rustfmt formatting
Formatting-only changes across server source and test files.
No logic changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 01:39:44 +01:00
jpmschweitzerandClaude Opus 4.6 12d1fd505e fix(simulation): address PR #26 review comments (13 items)
Warnings fixed:
- Add WalkAway to all_player_action_variants_roundtrip test
- Warn and skip on unresolvable speaker_entity_id (was silent 0)
- Change MonologueState.shown_ids from Vec to HashSet (O(1) lookup)
- Add cross-plugin ordering: trigger_recognition_monologue after
  detect_anomalies (latent determinism bug)
- Add TODO for unreachable Secret trust tier

Suggestions addressed:
- Server-side range check for Talk verb in handle_talk (CLOSE_RANGE)
- Emit IncompleteInteraction before overwriting ActiveDialogue
- Add different_seed_produces_different_replay determinism test
- Replace panic with assert for unknown fixture naming convention
- Fix duplicate "Observe" label: ExamineNpc now uses "Examine NPC"
- Change DialogueCooldownTracker.used from Vec to BTreeMap (D-041)
- Add .after(process_talk_interaction) to process_walk_away ordering
- Collapse dead conditional in main.rs (both branches identical)

468 tests pass, 0 failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 18:12:45 +01:00
jpmschweitzerandClaude Opus 4.6 ed7498cb24 feat(simulation): add --test-mode, --port, --seed CLI flags
Add CLI argument parsing for test infrastructure: --test-mode enables
deterministic seed (42) and warn-level tracing to stderr, --port allows
OS-assigned ports (--port 0), --seed overrides RNG seed. Prints
LISTENING:{port} to stdout after bind for test harness discovery.
Extracts setup_proof_room() for reuse. Fixes #459.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:41:05 +01:00
jpmschweitzerandClaude Opus 4.6 d1aba3d554 fix(simulation): use non-blocking TCP to prevent game loop stall
read_framed() called read_exact() which blocked the entire bevy Update
schedule waiting for client input — no systems ran until a keystroke
arrived. Switch TcpStream to non-blocking mode so receive_inputs()
returns Ok(vec![]) on WouldBlock instead of blocking. Toggle to
blocking for snapshot writes (reliable delivery). Add 50ms frame
throttle (~20 ticks/sec) since the non-blocking loop would otherwise
spin. Downgrade input receive logging to trace, add error logging for
missing bridge resource and failed observer queries.

Fixes bug #1 (server never sends snapshots) and #2 (camera doesn't
center until first keystroke).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 23:25:45 +01:00
jpmschweitzerandClaude Opus 4.6 4d8fe996fc feat(perception): add cognitive delay system for fog recognition (#423)
New CognitiveDelay component buffers perception events before emitting
KnowledgeEvents. Normal delay: 6 ticks (0.6s), urgent: 3 ticks (0.3s).
Drain system runs after emit_observation_events, before process_knowledge_events.

Adds pending_recognitions to ObserverSnapshot (protocol v7) for client
fog entity visualization. Includes cancellation when entity leaves LOS.

Monologue fires during delay (not after) per D-060 — cross-system
wiring deferred to follow-up ticket #451.

Ref: D-060 (cognitive delay), D-031 (10 tps), D-059 (fog layers)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 00:41:08 +01:00
jpmschweitzerandClaude Opus 4.6 df81b24cd1 feat(simulation): sprint anomaly double-take monologue (#428, D-055)
When sprinting past a Contradicted entity, queue a delayed retroactive
monologue that fires after ~1.5s: "Wait — something wasn't right back
there." SprintAnomalyQueue component with first-in-wins semantics.
Detection in observer pipeline, processing in monologue system.
Wire MovementProfile, Stance, and SprintAnomalyQueue into player spawn.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 16:00:20 +01:00
jpmschweitzerandClaude Opus 4.6 3c106aa2d0 feat(simulation): complete interaction and monologue pipelines (#413, #414, #415)
Three fixes to make the gameplay loop functional end-to-end:

- Add Interactable component to NPC spawn so E-prompt detection works
- Build monologue trigger system (enter_location + time_idle) with
  MonologueBuffer/MonologueState components, wire through ObserverSnapshot
  as current_monologue field, decode on client and display via HUD
- Change PlayerAction::Interact from unit to struct variant carrying
  optional target_entity_id and verb fields

Bumps protocol version from 4 to 5. Regenerates MessagePack fixtures.
All 200 tests pass (170 unit + 30 integration).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 19:23:47 +01:00
jpmschweitzerandClaude Opus 4.6 6f9537fff3 refactor(server): NearbyInteractionBuffer from Resource to Component
Per-entity Component attached to PlayerCharacter instead of global
Resource. Makes the interaction buffer multiplayer-ready (D-009) —
each observer gets their own buffer without pipeline refactoring.

Updated all 8 files touching the buffer: system signatures, player
spawn bundles, and ~30 test spawn sites.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 22:52:47 +01:00
jpmschweitzerandClaude Opus 4.6 0b599ed662 feat(simulation): spawn 3 NPCs with full component bundles
Implements ticket #84 for Sprint 3:
- Replace single bare NPC with 3 distinct NPCs: dock worker (16,13)
  with full 4-phase routine and MovementSpeed(2), field tech (14,18)
  with partial routine, stationary guard (18,14) with no routine
- Register all entities (player + 3 NPCs) in EntityRegistry
- Populate RelationshipGraph with colleague and rival edges
- Add NpcPlugin to app for routine system registration
- Add multi-entity visibility tests: 3 NPCs in LOS all visible,
  NPC behind wall excluded from snapshot

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 17:51:50 +01:00
jpmschweitzerandClaude Opus 4.6 a7e2c8fbf4 feat(simulation): add proof room with wall and NPC (#357)
Wall at (16,14) and NPC at (16,13) for Sprint 2 fog-of-perception
proof. Player starts at (16,16) — NPC hidden behind wall until
player moves around it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 01:45:47 +01:00
jpmschweitzerandClaude Opus 4.6 3115c7a84c fix(simulation): address PR #10 review — plugin wiring, stale reset, warnings
- Register KnowledgePlugin in main.rs and game_loop test (Tyre critical)
- Add KnowledgeGraph component to player spawn (Tyre critical)
- Reset Stale -> Active on fresh direct observation (Hoshe warning)
- Make registry/queue non-optional in emit_observation_events (Tyre/Hoshe)
- Add tracing::warn for missing EntityRegistry entries (Hoshe warning)
- Replace HashSet with Vec for small entity ID lookups (Hoshe suggestion)
- Add const static assertion for KnowledgeConfidence ordering (Hoshe)
- Add is_empty() and known_facts_iter() to KnowledgeGraph (Tyre)
- Add decay_skips_non_minute_ticks and observe_resets_stale tests (Hoshe)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 01:06:33 +01:00
jpmschweitzerandClaude Opus 4.6 f760624967 feat(simulation): add vision cone with forward/peripheral/blind sectors (#111)
Implement direction-dependent visibility modulation per D-015.
Forward cone (~120 deg) at full range, peripheral (~180 deg each side)
at reduced range, blind spot (~60 deg behind) excluded. Facing component
updated on player movement via facing_from_delta.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 00:21:01 +01:00
jpmschweitzerandClaude Opus 4.6 3f4c663242 fix(bridge): improve accept error reporting with address context
Replace expect() with unwrap_or_else that logs the bind address
and error via tracing before exiting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 21:16:08 +01:00
jpmschweitzerandClaude Opus 4.6 7864bfdf7d feat(simulation): add input processing, snapshot gen, and game loop
Implements the full server-side tick pipeline:
- process_player_input drains InputQueue, converts PlayerActions to
  MoveIntent components or pause/unpause toggles
- generate_snapshot builds ObserverSnapshot from ECS state with
  render coordinate conversion
- receive_bridge_inputs/send_bridge_snapshot handle bridge I/O with
  graceful disconnect detection via ServerRunning resource
- main.rs now accepts TCP connections and runs a proper game loop
- PlayerCharacter marker, Player EntityKind, SnapshotBuffer resource

Closes server side of #81, #82, #83.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 21:01:28 +01:00
jpmschweitzerandClaude Opus 4.6 6bda4a7620 fix(simulation): address PR #2 review findings
- Fix Cargo.toml edition 2024 → 2021 (Hoshe #1)
- Switch test runner to cargo-nextest in Makefile (Hoshe #2, D-030)
- Add debug_assert tick ordering enforcement in InputQueue::push (Hoshe #4)
- Add DayPhase Serialize/Deserialize derives (Tyre #6)
- Add day phase boundary comments clarifying half-open ranges (Hoshe #3)
- Add phase duration adjustability comment (Tyre #5)
- Document ObserverSnapshot planned fields as TODO (Tyre #1)
- Document entity_id as wire-format ID, not ECS Entity (Tyre #2)
- Change Relationship.target_name to target_id: u64 (Tyre #3)
- Clarify single app.update() is intentional boilerplate (Hoshe #8, Tyre #7)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 17:53:01 +01:00
jpmschweitzerandClaude Opus 4.6 f67caf1986 feat(server): initialize Rust/bevy_ecs simulation server
Server boilerplate epic (276) complete. Establishes the Rust simulation
server foundation per D-020 (subprocess/IPC architecture).

Structure:
- bevy_ecs 0.18 + bevy_app 0.18, MessagePack serialization (rmp-serde)
- SimulationPlugin with deterministic resources: SimulationTime (D-031),
  SimRng (D-030), InputQueue (D-010)
- Core IPC types: ObserverSnapshot, PlayerInput, SimBridge trait (D-020)
- CauseChain production component for provenance tracking (D-030)
- SimulationTier types with LRU eviction support (D-026)
- NPC 10-axis model components (D-024)
- 15 tests: inline unit tests + integration smoke/serialization tests
- make ci-server passes (clippy, fmt, build, test)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 16:54:40 +01:00