Review fixes:
- Terminal: fix sightlines comment col 22 → col 28 (actual window position)
- Last Shift: fix door comment col 21 → col 22, add spatial features
(bar counter W-stubs cols 1-2, table clusters, card table, ticker mount)
- Maintenance corridors: extend transition corridor from 26 to 40 tiles
per D-093 spec (grid now 58x6)
- Gate ground: expand customs zone from 8 to 10 rows per D-093 spec,
correct freight (20 tiles west) / ped (10 tiles east) layout with
6-tile corridor between (grid now 40x34)
- Gate gallery: add staircase entrance tile (col 1 row 0 = R)
- District description: update from "Three social sites" to five locations
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace worktree-centric language with team-centric framing across
CLAUDE.md and skills. Agents now identify by $WORKTREE_TEAM env var
instead of resolving git internals. This prevents agents from
following .git pointers back to the main repo and crossing boundaries.
- CLAUDE.md: rename section to "Team boundaries", reference $WORKTREE_TEAM
- sprint-start: add TEAM BOUNDARY rule to agent spawn prompt
- sprint-plan: replace "worktree-relative paths" with "relative paths only"
- pr-review: replace "worktree" with "team directory", note cross-dir
reading is a main-team privilege only
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Complete tile data for all five locations in the transit district:
- The Terminal (44x28, z=1): logistics hub with supervisor office LOS window
- The Last Shift (34x22, z=1): bar with corner booth and back room alley exit
- Maintenance Corridors (44x6, z=0): restricted storage, hatch room, transition corridor
- Gate Ground (40x32, z=1): aperture chamber, staging, customs lanes, concourse
- Gate Gallery (32x10, z=2): Commission-only observation gallery
Gate corridor split into two files (gate-ground, gate-gallery) because
the Location struct supports only one tile_bounds per file.
Updated district.yaml locations list with gate-ground and gate-gallery.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add D-088 Overlay pause/unpause signals to DebugConsole, wire in main.gd
so sim does not advance while typing debug commands
- Settings dialog reads live DebugConsole.is_enabled() instead of ConfigFile
directly, preventing checkbox/state divergence
- append_response respects disabled state — no auto-open when user disabled
console via settings
- tp command warns on invalid z value instead of silently defaulting to 0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Server #580 bumped to 18 for debug_response field. Client was still
at 17, causing every snapshot to be rejected — game unplayable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4 new tests in test_fog_sprint22.gd verify BoundaryWall tiles populate
boundary_positions (not visible_positions), get VIS_FORWARD without
EXP_VISIBLE, stay EXP_UNEXPLORED after leaving LOS, and clear on new
snapshot. Comment in tile_renderer.gd documents implicit rendering path.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- game_state.gd: add boundary_positions Dictionary field; BoundaryWall tiles from
visible_tiles go to boundary_positions instead of visible_positions — rendered by
tile_renderer but not tracked as explored fog memory
- fog_state.gd: update_from_state() writes VIS_FORWARD for boundary_positions so fog
lifts over margin wall content; boundary tiles excluded from exploration step so they
don't persist as EXP_EXPLORED when player turns away
- tile_renderer.gd: no changes needed — renders all visible_tiles by type, sector-agnostic
- test_fog_shader.gd: 4 new tests — boundary excluded from visible_positions, tracked in
boundary_positions, cleared each snapshot, fog lifts to VIS_FORWARD
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Same Sprite2D correction applied to test_client_p2.gd entity color tests
(Terrain, Player) — ColorRect was replaced with Sprite2D in entity_renderer.gd.
Minor comment clarification in test_rendering.gd rotation test.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Reset _npc_entity_colors/_npc_entity_id/_next_npc_color in _end_player_conversation()
to prevent palette exhaustion across long sessions with many unique NPCs
- Re-enforce contrast floor after passive desaturation (_enforce_contrast after _desaturate)
- Add TestDialogueSpeakerColors suite: palette allocation, entity reuse, reset, fallback
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Maintains Dict[entity_id → Color] in dialogue_box for player conversations.
On first encounter, assigns a round-robin palette color; reuses on subsequent lines.
Eliminates position-based name-hash coloring for player dialogue.
Changes:
- Add _npc_entity_colors dict, _npc_entity_id, _next_npc_color fields
- Add _assign_npc_color(entity_id) — registers palette color on first encounter
- show_dialogue: accept npc_entity_id param, register entity color
- append_line: optional speaker_entity_id/target_entity_id stored in log entries
- append_player_line: pass _npc_entity_id as target_entity_id
- append_dialogue_response: accept entity_id, register, pass to append_line
- _format_entry else branch: look up _npc_entity_colors before name-hash fallback
- main.gd: pass _last_dialogue_npc_id to show_dialogue, speaker_entity_id to append_dialogue_response
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fixes 7 pre-existing failures in test_entity_renderer tests:
- ColorRect → Sprite2D cast; .color → .self_modulate for D-033 color checks
- Position offset: (TILE_SIZE-24)/2 → EntityRenderer.ENTITY_OFFSET_{X,Y} (0.0)
- Rotation accuracy: expected values updated for raw un-normalised Godot rotation
Also adds SoundIndicatorRenderer to global_script_class_cache.cfg so test_rendering.gd parses.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
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>
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>
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>
Godot 4.6 OpenGL3 compatibility mode does not support 'return' in
fragment(). The early returns on lines 68 and 82 caused silent shader
compilation failure, making the fog overlay render as a no-op — the
root cause of the Sprint 22 fog regression.
Restructured to if/else-if/else chain preserving identical logic.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The 5-layer fog model's deep fog sub-zone (alpha 0.55-0.70) was designed
for the old peripheral sector. After #569 removed peripheral, tiles behind
the player dropped straight to deep fog — indistinguishable from unexplored
black over dark scene tiles.
D-015 is explicit: behind = light fog overlay, art preserved, just "not
fresh." There is no deep fog sub-zone.
Changes:
- Remove dual light/deep fog alpha — all explored tiles use alpha 0.25-0.35
- Add 5x5 Gaussian blur on exploration texture to soften staircase boundary
- Use blurred exploration value for the visual transition (raw for anti-bleed)
- Remove DARK_OVERLAY constant (zone_tint handles all explored color)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The merge of visual and client branches dropped the `tiles` variable
declaration. The client branch refactored bounds calculation to use
`visible_positions`, but the visual branch's zone tint loop still
iterates over `visible_tiles` for zone_id data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 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>
Round 4 review: mark VIS_PERIPHERAL as deprecated (peripheral sector
removed in #569, constant retained for test compatibility). Fix spec
status table row from "peripheral sector" to "cone gradient".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Round 3 review fixes — thorough spec cleanup:
- Remove visibility_sectors from data flow (peripheral removed in #569)
- Remove player_pos uniform (cone center implicit in visibility_tex)
- Update FogState pseudocode: remove sector step, add zone tint step
- Update lifecycle diagram to match single update_from_state() call
- Fix "5-layer fog" → "3-state fog" in Files to Create and impl notes
- Mark zone tint open question as resolved (Sprint 22, D-077)
- Document filter_nearest rationale on zone_tint_tex (D-073 hard zones)
- Note low-saturation tint is intentional per D-046 Hopper test
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
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>
GDScript int is i64 — when randi() returns a value with bit 31 set,
left-shifting by 32 sets bit 63, producing a negative i64. MessagePack
encodes this as a negative integer, which Rust rmp_serde rejects when
deserializing as u64, causing ~50% startup failure rate.
Fix: mask bit 31 before shifting in new_game() to cap entropy at 63
bits. Also mask the sign bit in _read_seed_file() to handle save files
written before this fix.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GLSL sample comments now say ±0.05 / ±0.075 matching the code and
spec table. Implementation notes gradient radius updated from 6-8
to 3-4 tiles.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove the db/connectors → tooling/db/ symlink added in Sprint 21
(#274) and migrate all references to use tooling/db/ directly.
- Delete tracked symlink from db/connectors
- Remove duplicate db/connectors/* permission patterns from settings
- Update project-structure.md to reflect removal
- Move whatsinagame/static/db/connectors/ to whatsinagame/static/tooling/db/
- Update 20 whatsinagame template, skill, and test files
- Update comment references in client/tests/test_anti_tedium.gd
- Historical docs (old sprint briefings, changelog, discussions) left as-is
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The 7x7 Gaussian kernel (sigma 2.0) produces a 3-4 tile radius
gradient, not 6-8 tiles. Header comment now matches the function
comment and actual math.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 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>
Sync fog-shader-spec.md with actual shader values after #563 tuning:
light fog 0.25-0.35 (was 0.26-0.34), deep fog 0.55-0.70 (was 0.54-0.70).
Pseudocode now uses symmetric noise remapping (noise*2-1)*amp to match
the shader. Added first-call guard comment on _tint_bytes in fog_state.gd.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
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>
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>
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>
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>
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>
Root cause: update_from_state() used visible_tiles (always empty in live
server mode) instead of visible_positions for bounds calculation. Bounds
never grew beyond 64x64, so tiles outside that area rendered as solid
unexplored black.
Fix: new _grow_bounds_from_positions() method reads visible_positions
(always populated from server snapshots). Shader fix: removed the
(explored < 0.01 && vis_raw < 0.01) guard that cut off the Gaussian
gradient at unexplored tile boundaries. Doubled blur step size for
D-066 compliant 6-8 tile soft gradient. Added debug_exploration mode
for diagnostic rendering of the exploration texture.
19 acceptance tests covering exploration persistence, bounds grow-only
invariant, gradient margin, Forward-only visibility writes, and
exploration data surviving texture resize.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ticket #563. Light fog alpha tuned to 0.25-0.35 range (was 0.25-0.55),
deep fog alpha set to 0.55-0.70 with zone temperature tint from
zone_tint_tex (bar=warm #2a1f15, hub=cool #1a1f2e, corridor=neutral
#1a1a1a). Two Perlin noise cycles: 8-10s light, 15-20s deep.
Zone tint texture now populated per-tile from server zone_id in
fog_state.gd with preservation across texture resizes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sprint 22 "Wire" briefings for server, client, visual, CI, and
planning teams. Also track Godot .import and .uid files that were
previously untracked.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update perception decisions to reflect the forward-only 120° cone
(no peripheral sector). Add Q-051: speech bubble indicator over
speaking NPCs for dialogue attribution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reduce from 5-layer to 3-layer fog: clear (forward cone), explored
(light overlay preserving art), and unexplored (solid near-black).
Remove peripheral sector handling from fog_state.gd.
Also preserve exploration data across texture resizes — previously,
resizing the fog texture lost all explored-tile state, causing tiles
behind the player to render as unexplored black instead of light fog.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
- 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>
Deep fog noise scroll speed 0.045/0.03 → 0.06/0.045 to match D-059
15-20s breathing cycle spec. Clamp sample_visibility() UV coordinates
to [0,1] to prevent sticky gradient at map edges.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The visibility texture has binary per-tile values (0/180/255) — bilinear
filtering alone only smooths ~1 tile, producing hard stair-stepped edges
at the LOS boundary instead of the 6-8 sim tile gradient D-059 specifies.
Add sample_visibility() with 7x7 Gaussian kernel (sigma 2.0) that
spreads the LOS boundary into a 3-4 tile radius gradient. Lower
PERIPHERAL_LOW from 0.55 to 0.08 so gradient tiles enter the peripheral
fog branch. Fix Layer 1/2 alpha discontinuity at CLEAR_THRESHOLD.
Guard against gradient bleed into unexplored tiles.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Layer 2 (peripheral): reduce peak alpha 0.55→0.38, noise 0.1→0.05,
taper noise to zero near clear boundary for a clean gradient edge.
Layer 3 (deep fog): reduce alpha range 0.78-0.90→0.62-0.76 so zone
temperature tint breathes through. Layer 5 unchanged (alpha 1.0).
Ticket: #564
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
Parity fix from PR #74 re-review round 2: legacy permission block
was missing audio-batch entry that exists in the tooling/db/ block.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Defer LOAD_GAME dispatch until SimBridge reaches CONNECTED (critical)
- Guard _build_saves_list() against queue_free() race on rapid reopen
- Disable save entries with empty newest_save, guard in _on_save_selected
- Send before show_loading on F6 quickload, skip overlay on send failure
- Clear pending_load_path in _on_new_game()/_on_continue() (stale path)
- Add hide_loading(success: bool) API for future failure-state UI
- Add test_save_load_flow_sprint21.gd covering LoadingScreen + GameState
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove duplicate #[test] attribute, unused TemplateId import, and dead
spawn_escalation_npc helper function (no longer referenced after #250
refactor).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add missing db/connectors/decision permission in settings.json and
update DEVOPS.md layout table to reflect connector move. Filed #568
for Sprint 22 symlink removal.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add spawn_template_npcs: three-phase template instantiation (spawn NPCs
per role slot, wire intra-template relationships, record cross-template
references in TemplateReferenceMap). Partially complete — needs
validation pass, error handling, and integration with content loading
pipeline.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add FullTemplateDef integration tests: round-trip YAML serialization,
space spec validation, routine schedule, sightline zones, dialogue pool
refs, cross-template link specs, and logistics-hub template fixture.
Tests cover the full social site template document structure per D-023,
D-024, D-025, D-028.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
Follow-up to b6a9b78: register TerminalInteractedQueue resource and
door/terminal interaction systems in SimulationPlugin; add door state
save/load in save_io (open doors round-trip through SaveStateV1);
make WalkabilityMap param optional in process_door_interaction so
plugin-only tests work without a loaded map; fix information_boundaries
test missing open_doors field.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add DoorState component tracking is_open and blocking_tile; add
DoorInteractRequest per-player component consumed by new
process_door_interaction system (toggles walkability each use)
- Add TerminalInteracted event, TerminalInteractedQueue resource,
TerminalInteractRequest component, and process_terminal_interaction
system (emits event on Use verb)
- Add ExamineText(String) component for authored object examine text;
extend process_examine_interaction with object examine path:
uses ExamineText if present, falls back to generic string if absent
- Fix: add Without<ObjectType> filter to npc_query in
process_examine_interaction — previously any entity with TilePosition
was mis-routed through the NPC text generator
- Add SaveStateV1.open_doors: Vec<StableId> with #[serde(default)]
for backward-compatible serialization
- Add "Open"/"Close" → DoorInteractRequest and "Use" →
TerminalInteractRequest dispatch in process_player_input
- 10 integration tests in tests/environmental_interaction.rs covering
all acceptance criteria: door toggle (both directions), open-to-close,
invalid target, readable examine (with/without ExamineText), out-of-range,
terminal event emission, request cleanup, and save state round-trip
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add ValidationError enum with three failure modes: ConflictViability
(missing Want axis), RelationshipCoherence (empty constraints),
InterestDivergence (duplicate interest axes)
- Add validate_triangle_def() pure function enforcing all three checks
in priority order (per D-087)
- Add generate_cross_template_triangles() function that combines NPC
pools from two templates, validates each TriangleDef before processing,
and assigns ownership to template_a
- 10 integration tests in tests/triangle_validation.rs covering all
validation failure modes, ordering guarantees, cross-template span,
invalid def skipping, determinism, and intra-template isolation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Consolidates all connector scripts under tooling/ per project
structure conventions. Symlink at db/connectors → tooling/db/
preserves backwards compatibility (remove after Sprint 22).
Updated references in CLAUDE.md, Makefile, DEVOPS.md, all skill
files, agent files, rules, schema comments, and Sprint 21
briefings. Python scripts updated with correct SCHEMA_PATH
(now relative to WORKTREE_ROOT/db/schema.sql).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed z-level fix (base_z u8→i8), MobileChunk Idle as stationary
installation primitive, and rejection of separate location instancing.
LocalOverlay confirmed as canonical DLC/mod content injection point.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
#257: Add Load Game screen to main menu with sorted save list, loading
overlay during quickload round-trip, and pending_load_path cross-scene
flow. F5/F6 quicksave/quickload were already wired.
#561: Move debug_overlay.gd from scripts/ui/ to ui/ for consistency
with all other UI components. Update scene and test references.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>