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>
Replaced /var/home/jeroenschweitzer/Projects/ with /var/mnt/data/projects/
across 13 files (skills, docs, workshops, discussions).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Hoshe #3: replace O(n²) Vec scan in fallback NPC assignment with
BTreeSet; prevent same NPC assigned to two roles in one triangle
- Hoshe #4: add From impls for RoleId, TriangleId, StableId, and
TriangleCrisisEventWire — eliminate fragile .0 access on newtypes
- Hoshe #5: consolidate near-identical unit tests with integration
counterparts — keep only unique tests in #[cfg(test)] module
- Tyre #3: replace O(N*M) scan in apply_resolve_triangle with
BTreeMap<TriangleId, Entity> index for O(1) per-command lookup
- Tyre #4: document &mut World on generate_intra_template_triangles
- Observer snapshot uses TriangleCrisisEventWire::from instead of
manual field mapping
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TriangleDef.validate() now rejects relationship constraints where
with_role references a role not in the triangle's three roles.
Catches authoring errors at load time instead of silently producing
broken constraint data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Triangle phase and tension were silently lost on save/load. Now
serialized as triangle_states vec in SaveStateV1, sorted by
triangle_id for determinism (D-010). Dedicated triangle entities
are respawned on load.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The TriangleCrisisEventQueue was populated by tick_triangle_escalation
but never drained into ObserverSnapshot — clients always saw an empty
vec despite protocol v16 advertising the field. Now drains the queue
each tick and converts to TriangleCrisisEventWire.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Updates all client-side msgpack test fixtures and server test
harnesses to include the new triangle_crisis_events field added
in protocol v16.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Registers tick_triangle_escalation and apply_resolve_triangle systems
in SimulationPlugin. Adds TriangleCrisisEventWire to ObserverSnapshot
(protocol v16) for future client rendering of triangle crises (#250,
D-087). Observer emits empty vec by default; escalation system will
populate when triangles reach Active phase.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds TemplateOwnership to NpcSaveState and TemplateReferenceMap to
SaveStateV1 so cross-template links survive save/load and tier
eviction (D-025, D-026). Both fields use serde(default) for backward
compatibility with existing saves.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements #163 (RoleSchema), #164 (SpaceSpec), #165 (TemplateOwnership
+ TemplateReferenceMap), #106 (TriangleDef), #107 (intra-template
triangle generation), and #250 (triangle escalation system) as the
foundational Tier 2 template system per D-025.
New content/template module with YAML-deserializable schema types,
ECS components for ownership/triangle state, escalation system
running on game-minute boundaries, and TriangleCrisisEvent emission.
Sample YAML templates at server/data/templates/.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract shared YamlParser utility (client/scripts/util/yaml_parser.gd)
with parse() for nested typed dicts and parse_flat() for dotted-key
string format. UIStrings._parse_yaml() and ChecklistEvaluator's inline
parser both delegate to YamlParser, removing ~140 lines of duplication.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New SnapshotEventRouter class (46 lines) provides callable-based
snapshot dispatch via register(), register_always(), and dispatch().
main.gd _process() now calls _router.dispatch(snapshot) instead of
15+ inline if-has blocks. Handlers registered in _ready().
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace 3 direct GameState.dialogue_active mutations and all
AudioManager.apply_dip/clear_dip calls with signals:
dialogue_state_changed, audio_dip_requested, audio_dip_cleared.
dialogue_box.gd now has zero references to GameState or AudioManager.
main.gd wires coordinator handlers in _ready() (D-020).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
apply_snapshot() now reads stationary_ticks and zone_id directly from
the server snapshot when present (D-020 compliance). Client-side
accumulation and tile lookup retained as deprecated fallbacks until
the server populates these fields. Protocol.gd extended with decode
paths and TODO markers for the server team.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
D2 source + PNG render showing all zone connections, access tiers,
z-levels, maintenance corridor routing, and dual entry vectors.
Vertical layout with color-coded access tiers per D-093.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full tile-level layout doc matching Terminal and Bar format. 7 zones
across z=1 and z=2, sightline matrix, access tier map, NPC traffic
density, Triangle 5 narrative notes. Per D-093 gate cluster spec.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Workshop brief for ticket #562 covering the top-down district
generator pipeline (Cities Skylines model). Builds on D-094
chunk/block/district hierarchy. Targets Q-036 and Q-037 resolution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Corrects horizon gate description per D-095: gates are at the Krenn
Ring (800 AU orbital installation), not on Station Sova. Admin Hub
houses transit processing facility, not gate apertures.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Supports design discussion tickets that run on the planning branch
with a purpose-assembled agent panel. Includes Qatux (documenter)
and SI (project manager) for bookkeeping alongside domain agents.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Server (6 tickets): template role/spatial/ownership schemas, triangle
definition, generation, and escalation. Client (4 tickets): code quality
refactors from review pass. Planning (1 ticket): #153 station district
layout design discussion with purpose-assembled agent panel.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- input_mapper.gd: call set_input_as_handled() before early return on
empty game_id so F5/F6 events don't propagate to other handlers
- session_manager.gd: defer scene change by one frame after buffering
quit-save so SimBridge._process() flushes the outbound buffer
- monologue_display.gd: tag queued notifications with is_notification
flag so drain path routes to _show_notification_line (correct color)
instead of _show_line (lattice-profile fallback color)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wire SaveGame/LoadGame player actions through the full client stack:
protocol v15 decode, InputMapper F5/F6 bindings, SimBridge wire mapping
with one-shot carry-forward, GameState save_result field, and HUD
notification via monologue display. Quit-to-menu triggers quicksave
before scene change.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- gen_fixtures.rs: version comments now say PROTOCOL_VERSION instead
of hardcoded 14, so they stay correct across bumps
- run-ipc-benchmark: remove --iterations flag that was parsed but
never forwarded to the Rust test (compile-time constant governs)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Server bumped to v15 in Sprint 19 (save_result field) but client
constant was never updated. Fixes cross-language fixture test failures.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
#556: HANDSHAKING state in sim_bridge.gd — decodes first framed message
as HandshakeMessage, validates vs Protocol.PROTOCOL_VERSION, 5s timeout,
handshake_complete/handshake_failed signals.
#342: IPC benchmark now reads and validates HandshakeMessage before
starting the timing loop.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
protocol.gd decoded server's poi_category as "category", minimap.gd
read "category" — both now use "poi_category" matching the wire format.
Protocol falls back to "category" for older server snapshots.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 5 new rules to the agent spawn prompt: read-before-write,
verify-after-write, no-partial-work, message-when-blocked, and
backward-compatibility. Adds verification checklist before marking
tasks done. Addresses recurring issues with agents skipping call
site updates, leaving partial implementations, and not escalating
blockers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add missing _test_input_queue proxy to SimBridge (26 call sites across
6 test files broken by TestHarness extraction)
- Parent quit dialog to SceneTree root instead of caller node to prevent
orphaned reference if caller freed before user responds
- Remove deprecated rng.randomize() call (Godot 4 auto-seeds)
- Clear debug overlay state (_npc_paths, tick timing) on session change
via new GameState.game_id_changed signal to prevent entity ID collisions
- Update settings_dialog quit_to_menu() call site (no-arg signature)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Removed duplicate examine_result from ObserverSnapshot (old ExamineResultEvent
superseded by ExamineResultWire). Fixed serde_default test version assertion.
Regenerated golden file and all fixture .msgpack files. 1070 Rust tests passing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Five new .msgpack fixtures: snapshot_minimal, snapshot_full,
player_input_move, player_input_interact, malformed. Rust generator in
gen_fixtures.rs, 7 Rust validation tests in serialization.rs, GDScript
cross-language test in test_ipc_fixtures.gd (22 assertions).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Six test runner scripts at tests/: run-rust, run-godot, run-ipc-fixtures,
run-ipc-protocol, run-ipc-integration, run-all. Plus run-ipc-benchmark
for Layer 3 timing. All produce structured JSON stdout, support --filter,
and exit 0/non-zero. Makefile targets updated to delegate to scripts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Closes content-gap-analysis, KG-information-boundaries,
v01-content-scoping, v01-gap-analysis, and wiki-review workshops
with formal outcomes recording decisions produced, tickets created,
and open questions carried forward.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Moves ~300 lines of test simulation logic (Bresenham LOS, collision,
procedural room generation, movement physics, dialogue triggers) from
the production sim_bridge.gd autoload into a dedicated TestHarness
class at scripts/protocol/test_harness.gd. Enforces D-020 information
boundary — no game logic in the production client.
SimBridge retains thin proxy properties and methods for backward
compatibility with 13+ test files (zero test changes needed).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
D-087 through D-092: v0.1 triangle config, 3-state pause, self-contained
forks, PC voice registers, complicity as theme, anchor line requirement.
Q-030 through Q-039: long-term strategy questions from wiki-review R4
(seed schema, generator pipeline, Sacred/Profane, 300-world estimates).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
SessionManager.new_game() now returns "" on dir creation failure
instead of proceeding with a broken game-id. Main menu guards
against empty return. Test suite tracks and cleans up created
save directories in after_test().
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
F3-toggled dev overlay: LOS rays, vision cone arcs, NPC path trails,
knowledge confidence tags, tick timing sparkline. Guarded by
OS.is_debug_build() for export builds.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Per-game save directories under user://saves/<timestamp>-<seed>/.
SessionManager autoload handles new_game(), resume_game(), quit flow.
Main menu scene with New Game / Continue / Quit buttons. Game-id
passed to server subprocess via --game-id flag.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SceneHelper class for gdUnit4: load scenes into test tree with
assert_node_exists, assert_signal_emitted, get_node_at helpers.
14 tests for GameState.apply_snapshot() covering v2+ fields.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Headless test runner that delegates to GdUnitTestCIRunner for CI
integration. Exit code 0 = all pass, non-zero = failures per D-030.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Server (7), client (5), CI (4) briefings plus joint integration plan.
Save/load with D-085 per-game dirs, tier eviction/scope, test infra.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Session-specific working notes that are context-brittle and would
create noise across branches.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
LOAD tab now shows games grouped by directory with expand/collapse.
QUICKSAVE slot distinct from AUTOSAVE. F5/F6 keybind hints in footer.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- `db/connectors/decision next [D|Q|R]` — show next available ID
- `db/connectors/decision claim <prefix> <domain> [title]` — reserve ID in DB
- `db/connectors/decision check-dupes` — detect duplicate IDs in markdown
- `tooling/check-decision-ids` — pre-commit hook for dupe detection
- D-035 added as known exception (139 files, too embedded to renumber)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolves ID collision: D-084 was used independently by both the copy
branch (line ID scheme, content.md) and the visual branch (insert icon
system, perception.md). Content's D-084 keeps the number; visual's is
renumbered to D-086.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
D-085: per-game save directory structure with F5/F6 quicksave/quickload.
Q-029: open question tracking long-term save file format design.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Re-rendered all 19 wireframe PNGs via Frame0 paid license,
removing trial watermarks. JSON sources unchanged.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Regenerated MsgPack fixtures for protocol v14 (examine_result and
character_pressure fields). Updated golden test, serialization
assertions, and cross-language fixture generator.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Background tier state machines (#95), NPC vision (#115), player-
awareness behavior (#244), skill system & combat flag (#91), social
propagation (#249), examine mechanic (#242), character pressure
framework (#248), save state data model (#256), tell state wiring
(#337). Protocol version bumped 13→14 for examine_result and
character_pressure snapshot fields.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix npc:nils → npc:nils-davan canonical ID mismatch. Replace
auto-flag gates on ring_completes/ring_splinters with player-
action-gated fact conditions (unreachable outcomes). Add
ring_stalemate terminal exit for non-terminal ring_splinters.
Create ring.yaml with 10 fact stubs for content/global/knowledge/.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- test_journal_sprint18.gd: replace references to removed
CONFIDENCE_LABELS/SOURCE_LABELS with UIStrings key tests and
regression guards
- dialogue_box.gd: escape ] as [rb] in _escape_bbcode for complete
BBCode injection protection
- dialogue_box.gd: fix _expire_entries to skip pinned entries with
continue instead of break, cleaning expired entries behind pins
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix events_fired referencing flag names instead of event IDs (two
outcomes unreachable). Wire 4 orphaned flags into narratively
coupled outcome conditions. Fix typo and stale question count.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- minimap.gd: fix "poi_category" → "category" key mismatch so POI
colors and shapes render correctly
- journal_panel.gd: parse ToldBy(N) source format, resolve entity
names from player_knowledge; move confidence/source labels to
UIStrings per D-042
- observer/mod.rs: add Changed<KnowledgeGraph> dirty flag to skip
per-tick KG serialization when unchanged
- types.rs: fix stale version doc comment (13 → 14)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
50 tests across two files: 30 dialogue tests (D-062 compliance,
D-063 confrontation beat, D-064 walk-away, BBCode guard, size
constraints) and 20 journal tests (KG parsing, confidence/source/
state enums, scene structure, UIStrings keys, POI list). Test plan
document with manual procedures and sprint completion checklist.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Right-side insert panel toggled with J key. Facts grouped by entity
with confidence, source, and state metadata. Contradicted entries
in amber with strikethrough (THE FRIEND arc surface). Stale entries
dimmed. Mutual exclusion with dialogue box. All labels via UIStrings.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Confrontation options use RichTextLabel with italic tags for
first-person voice (D-063). Examine result overlay auto-dismisses
after 5s with confidence-based color tinting. Dismisses when
dialogue opens. D-062 invisible locked options confirmed correct.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Circular 160px diegetic insert overlay on CanvasLayer 10. Nearby
POIs as colored dots (diamond=danger, square=evidence, circle=default),
distant POIs as directional border arrows. Player centered, fixed-north.
Moved from UILayer to InsertOverlay per D-013/D-049.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Decode poi_list, examine_result, and player_knowledge from
ObserverSnapshot. Add GameState.discovered_pois,
current_examine_result, and player_knowledge fields populated
from snapshot apply handlers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add three new ObserverSnapshot fields for client Sprint 18 tickets:
poi_list (Vec<PoiWire>) for minimap #151, examine_result
(Option<ExamineResultWire>) for #174, player_knowledge
(Option<PlayerKnowledgeWire>) for journal #264. POI list populated
live from KG-discovered PointOfInterest components. KG dump
serializes entity/fact knowledge with confidence, source, and state.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
JSON Schema for drama modules covering entry conditions, NPC
requirements, event sequences, and outcomes. Includes v0.1
vertical slice stub module and authoring guide with review
feedback from Mellanie (pattern/motivation reference, terminal
outcome semantics, fact ID conventions, trigger type bridge).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Role namespace (shared pool) stays unchanged; instance namespace
(role-slug + seeded counter) added as opt-in for per-instance
authored content on auto-generated NPCs. No schema migration needed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
14 tickets across server (9), client (3), copy (2). Examine mechanic,
NPC awareness, social propagation, minimap, dialogue UI, save state
data model, and blocker-clearing work for Sprint 19.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- monologue.rs: tracing::warn on unrecognized trigger in fallback arm
- disclosure.rs: borrow-sequencing comment, first() simplification note
- trait_modifiers.rs: delegate parse_confidence to KnowledgeConfidence::try_from
- npc_knowledge_transfer.rs: fix misleading "draw randomly" comment,
document one-directional transfer behavior
- graph.rs: document intentional no-retrigger after contradiction
- dialogue.rs: explain entity grant guardrail asymmetry (D-079)
- knowledge/mod.rs: document one-tick monologue lag from system ordering
- poi_discovery.rs: document D-079 carve-out for direct KG write
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pass PR description inline instead of writing to /tmp/pr-body.md
and cat-ing it back — matches the tea-comment wrapper approach.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
record_incomplete_interaction now uses Heard/Close source instead of
DirectObservation, preventing false inoculation against contradiction
detection. Wired exclude_high_trust_entities (Loyal trait) filter into
derive_disclosure_candidates — facts from Friendly-relationship source
entities are excluded from disclosure pool.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move CLI reference material, endpoint configs, and orchestration
patterns to .claude/rules/ (auto-loaded). CLAUDE.md now focuses on
project identity, safety rules, and workflow conventions.
Update cross-references in ticket, docs-search, and git-commit
skills to point to new rules/ locations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduces 5 rules files following Anthropic's recommended pattern
for splitting large CLAUDE.md files. Rules auto-load every session
and separate CLI reference material from core project identity.
- tea-cli.md: Gitea CLI reference, PR creation, protected branches
- git-safety.md: staging rules, commit conventions (from git-commit skill)
- project-structure.md: full annotated directory tree
- team-patterns.md: model selection, large content push pattern
- local-services.md: Gitea/Qdrant/Ollama endpoints
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reviews must run from main. Added step 0 hard stop if current branch
is not main, preventing repeated misuse from team branches.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Heartbeat rule for agent spawn prompts (15-min progress check) and
team lead proactive checks (bottleneck detection pattern).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Version field round-trip, mismatch detection, serde_default migration
pattern, all TellCategory and VerbKind variant coverage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
tell_state reads KG for other-entity relationship state (MVP boundary
per D-082). Contradiction monologue fires with pre-resolved entity names,
shifts ToldBy source to PersonOfInterest. Full THE FRIEND arc event chain.
Implements D-082 step 1, D-083 event chain.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
transfer_npc_knowledge system runs after conversations with trust-gated
fact exchange, confidence capping at KnowsOf, ToldBy source construction.
POI data model with PointOfInterest component and proximity-based discovery
via KnowledgeGranted events. Implements D-080. Closes Q-024.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Contradiction files:
- Add role/access/trust back to all lines (schema-required)
- prerequisite: → prerequisites: (plural, matching schema)
- Remove cooldown entirely — fire-once enforced by trigger semantics
(contradiction_detected fires once per KG state change), not magic numbers
Tutorial files:
- Remove cooldown: -1 — same reasoning, first_* triggers are one-time
Server:
- Document cooldown: Option<i32> on MonologueLine — None means no
per-line cooldown, fire-once relies on trigger design
CHANGELOG:
- Move displaced entries from ### Fixed back to ### Changed
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Single-command wrapper that handles temp file creation and cleanup
so tea comment works reliably with multi-line strings. Pre-approved
in settings.json, referenced in CLAUDE.md and pr-review skill.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Insert overlay uses custom SVG icons instead of an icon font. No
available font matches the neural lattice visual language. Custom
SVGs respond to lattice_profile weight parameter and maintain visual
coherence with existing geometric primitives.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds explicit exception to worktree boundary rules: agents may
remove their own worktree's stale index.lock file from the shared
.git directory, but never another worktree's lock.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- interaction_list.gd: skip queue_redraw() when position unchanged (Tyre #4)
- time_display.tscn: widen bounding rect 154x44→184x54, add clip note
for #314 wireframe (Tyre #3)
- test_time_display_sprint17.gd: document private state access pattern
in header (Tyre #5), add upper bound assertion for D-031 1439 max (Hoshe #6)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- constants.gd: clamp format_game_time input to 0..1439 (Hoshe #2)
- interaction_list.gd: add public hide_list() wrapper (Hoshe #3, Tyre #1)
- main.gd: call hide_list() instead of private _hide()
- time_display.gd: cache font geometry in update_from_state(), use boolean
_has_data flag instead of string guard (Tyre #2)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix test API mismatches: time display tests target InsertOverlay/
TimeDisplay and time_display.gd; E-Talk tests rewritten to target
interaction_list.gd _cache_entity_relationship() and _relationship_color
state. Phase 2 tests (name, tier hint) marked as skip placeholders.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 1: interaction_list.gd shows a 3px left-edge accent bar in
D-033 relationship color (teal/green/amber/red) at 85% alpha.
Cross-references entity_id against visible_entities via
_cache_entity_relationship(). NPC name and tier hint deferred to
Phase 2 (requires server protocol extension).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Time display on InsertOverlay (CanvasLayer 10) shows station local
time (HH:MM), day phase with cycle-tinted color, and day number.
Reads SimulationTime from GameState.game_time via update_from_state().
Adds Constants.format_game_time() helper for testability.
Placeholder layout — position refines when #314 wireframe lands.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add model selection section to CLAUDE.md covering /model sonnet[1m]
and opus[1m] for extended context sessions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Delegate sprint-status to a haiku subagent (sprint-plan pattern) so
intermediate artifacts (sweep JSON, template read, PR list) stay out
of the main context window. Trim sweep JSON output by removing unused
fields (ok, sprint.status, priority, ticket_id) and shortening issue
detail strings. Condense output template by moving rendering rules
into SKILL.md and simplifying the bookkeeping table to two columns.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
10 lines per character teaching 5 core mechanics diegetically:
movement/exploration, fog of perception, sound model, NPC interaction,
insert/HUD. Detective lines in analytical register, smuggler lines in
street-smart fragments. Fires on first-time events (first_move,
first_fog_encounter, first_sound_heard, first_npc_proximity,
first_insert_open, etc.). _tut_ ID discriminator, cooldown -1.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Source-named contradiction monologue for both detective and smuggler.
Detective: Sera/Kael location contradiction (Phase 2 blindsiding +
Phase 3 pattern recognition with Torek avoidance). Smuggler: Kael in
B-7 with unrecognized contact (Phase 2 gut reaction + Phase 3
behavioral pattern accumulation). Cognitive-dissonance-not-accusation
tone per D-083. 16 hand-authored lines total (8 per character).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pixel-precise wireframe and visual specification for the neural lattice
overlay HUD (#314). Covers smuggler (social network view) and detective
(investigation overlay) variants via lattice_profile parameter.
Specifies: time display, entity markers, location labels, border arrows,
commission grid, inventory icons, stance indicator, and all interaction
states. Includes implementation notes for Stig (#263 time display).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Orchestrates sprint sweep + tea pr list to produce a consistent
health report: tickets by status, PR cross-reference, bookkeeping
issues, and open work by team summary.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Structured JSON output with tickets grouped by status, per-team
summary counts, and bookkeeping issue detection (unassigned
in_progress, stale backlog, assigned but done).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reconcile sprint planning after Knowledge Flow workshop:
- Server briefing: add #545-#551 workshop tickets, correct dependency
chain, reference D-079–D-083, remove stale "blocked by workshop"
- Joint briefing: mark workshop complete, add completion proofs #9
(contradiction) and #10 (NPC-to-NPC transfer), update teams table
- Copy briefing: add #552 contradiction monologue ticket with full
Mellanie authoring spec per D-083 and Paula Round 2 output
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
NPC-scoped line ID scheme (D-035) works for hand-authored content but
will produce slug collisions with auto-generated populations (D-029).
Tracked as open question with ticket #544.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Address review comments from Hoshe, Paula, and Miri:
- Update mood vocabulary in 3 docs (line-pool-format.md §6.5,
style-guide §11, content-directory-structure.md Appendix B) from
pre-Sprint 14 values to current D-035 enum
- Fix worked example IDs in line-pool-format.md §3.5 to match
actual the-last-shift kael-davan sequence (_015, _024, _026)
- Fix Section 5.1 restart note to describe multi-location continuity
- Fix style-guide §16 worked example: dock-worker_d_071 → kael-davan_d_076
- Fix stale mood reference in style-guide §16 Step 3
- Fix orphaned the-terminal_d_040 in maintenance-tech.yaml comment
- Fix orphaned the-terminal_d_008/018 in smuggler-inventory.yaml
- Fix Lera tenure: twelve → eighteen years (bar-owner_d_018)
- Fix fact_id: location.surveillance_gaps → investigation.surveillance_gaps
in ring-operative.yaml (2 occurrences)
- Fix NPC name: Lera Osk → Lera Sessik in bar-owner.yaml comment
- Fix mood line format example in style-guide §5
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
14 tests covering _octant_to_direction (all 8 octants + 2 fallbacks)
and _entity_direction (NPC default south, player facing 3 cases).
Closes review warning on zero test coverage for direction system.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add push_error on null texture at create time, keep previous texture
on null at update time (entity stays visible mid-game). Add push_warning
on unrecognised octant in _octant_to_direction fallback.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Line IDs in all dialogue and monologue pool files renamed from the
old location-scoped format (e.g. the-terminal_d_039) to the new
NPC-scoped format (e.g. kael-davan_d_001) per the D-035 Sprint 15
amendment.
Changes:
- 20 dialogue pool files across 3 locations renamed
- 14 monologue pool files (detective + smuggler) renamed
- Schema descriptions updated in dialogue/monologue schema files
- Authoring style guide and design docs updated with new examples
- Multi-location NPCs (kael-davan, pc-detective, pc-smuggler) given
globally unique cross-file sequences to satisfy XREF uniqueness check
The location-scoped scheme already caused a collision (the-terminal_d_039
appearing in multiple NPC files) and would not scale to procedurally
generated NPC populations (D-029). Zero content changes — pure ID
substitution.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Migrate entity rendering from ColorRect placeholders to Sprite2D with
rendered PNGs at -72.5° from horizontal. Key changes:
- Sprite2D.centered=false, scale=0.5 for 64px source → 32px runtime
- self_modulate for D-033 relationship tinting (modulate.a reserved
for D-015 peripheral dimming)
- 8-octant to 4-cardinal direction mapping for sprite selection
- Feet-anchored ENTITY_OFFSET_Y for correct y-sort with tilted sprites
- Facing indicator repositioned to sprite local center (32,32)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Build _tile_by_coord dictionary from member visible_tiles (covers both
test-mode "tiles" key and live-server "visible_tiles" key), then replace
the linear scan with a single dict lookup. Net-zero complexity: adds one
dict-set per tile in an existing iteration, removes the separate scan loop.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
sprint-start: add step 9 (post-work lifecycle) — commit, push, review,
fix-comments loop, approve, then shutdown. Team stays alive until PR is
accepted. Step 8e updated to reference the new lifecycle.
pr-push: add step 9 (team awareness) — don't shut down agents after
pushing, suggest /pr-review next.
pr-review: add step 8 (post-review team actions) — cross-references
sprint-start step 9c for dispatching review comments to agents on
CHANGES_REQUESTED and shutdown on APPROVED.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tyre #1: Extract run_dialogue_pipeline() shared helper — eliminates ~60
lines of duplication between process_talk_interaction and
process_dialogue_response (L1-L4 pipeline).
Hoshe #1: process_dialogue_response now updates ActiveDialogue with
current tick on follow-up selection — prevents stale started_tick.
Tyre #4: process_dialogue_response now updates InteractionMemory on
follow-up — multi-turn conversations are visible in history.
Hoshe #6 / Tyre #6: handle_dialogue_response adds server-side range
check (CLOSE_RANGE), matching Talk/Confront pattern (D-010 info
boundary).
Hoshe #2: Weighted selection fallback replaced with unreachable!() —
score_line always returns >= 1, so the fallback was dead code.
Hoshe #3: assert!(false, ...) → panic!() in serialization.rs (clippy).
Hoshe #4: SetFacing and TeleportToHub added to roundtrip test.
Hoshe #5: setup_dialogue_response_world inlined (trivial pass-through).
Tyre #2: Doc comment on DialogueCooldownTracker explains per-player-global
design choice (line IDs are NPC-scoped per D-035, no collision risk).
Tyre #3: CONFRONTATION_LINES comment updated with TODO for D-028/D-035
migration.
Tyre #5: DialogueResponse fixture added for cross-language GDScript
testing (input_dialogue_response.msgpack).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix client sprite naming in README (files are _64.png, not .png)
- Clarify --path working directory (renderer/ from repo root)
- Remove /sprite-gen reference (skill not in branch yet)
- Add D-043 citation on outline color in render_export.gd
- Add uid to wall_bar_green.tscn for reproducible imports
- Note wall_bar_green has no rendered sprites yet
- Note npc_generic capsule symmetry is by design (D-044)
- Add outline + D-033 tint compatibility guidance
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Runtime 64px sprites rendered through the new pipeline: generic NPC
(4 directions) and structural wall (4 directions). These unblock
client ticket #540 for sprite camera angle integration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update Camera3D to exact D-019 angle (-72.5° from horizontal).
Replace single DirectionalLight with three-point studio rig
(key 1.0, fill 0.4, rim 0.3) for clean silhouettes without
baked shadows. Add generic NPC capsule model (24×32px footprint
per D-044). Document full pipeline spec in renderer/README.md.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move dialogue system registrations from BridgePlugin to NpcPlugin (#538):
game logic that depends on NPC-layer resources now registers where it
belongs. BridgePlugin retains only wire protocol concerns.
Implement DialogueResponse verb handler (#539): new process_dialogue_response
system runs the full D-028 four-layer pipeline to select follow-up lines
when the player picks a dialogue option. Clears ActiveDialogue when no
candidates remain. Fix latent schedule ambiguity — emit_observation_events
now has explicit .before(advance_tick) constraint.
Verify trust-gated gossip pipeline (#171): confirmed process_talk_interaction
correctly passes KnowledgeConfidence through relationship_to_trust() per
D-075. Added integration tests for Secret-tier access (Friendly+KnowsDetails)
and Surface-only fallback (Friendly+Suspects).
Wire DialogueCooldownTracker into selection (#338): added regression test
confirming no line_id repeats within the 600-tick cooldown window across
10 consecutive Talk interactions.
Closes#538, #539, #171, #338
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Plan 8 tickets across server (4), client (2), copy (1), visual (1).
Focus: two-way dialogue exchange, trust-gated gossip, sprite pipeline,
and housekeeping fixes. No carry-overs from sprint 15.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sprint 15 amendment: line ID namespace changed from location-scoped
to NPC-scoped. Each NPC's IDs are independent, eliminating cross-file
coordination and collision risk at scale.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All reviewer agents now read source files from worktree paths using
the Read tool instead of git show. Removes Bash dependency for
non-code reviewers and ensures files are always the actual branch
checkout.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- dialogue_box.gd: panel is always visible as permanent insert UI
element per D-061 — content fades but frame stays on screen
- protocol.gd: bump PROTOCOL_VERSION to 13
- Makefile: add check-protocol target that verifies server/client
protocol versions match, runs automatically before build
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
First wireframe set covering all major UI surfaces:
- HUD: basic insert (v0.1), full insert with perception modes (v1.0)
- Dialogue: speaking, choosing, overheard states (v0.1), full with
relationship indicators (v1.0)
- Monologue: idle, reaction (v0.1), thought threading (v1.0)
- Popups: modal, tooltip, interaction list (v0.1), context menu,
notification stack (v1.0)
- Menus: main, pause, save/load (v0.1), main menu, options (v1.0)
README.md cross-references each wireframe to governing D-records.
JSON source + PNG exports tracked in git.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace individual API call workflow with JSON-as-truth architecture.
Local wireframe JSON files are the source of truth; Frame0 is treated
purely as a renderer. New frame0-sync.py handles push/pull/export with
stable local ID <-> ephemeral Frame0 ID mapping via .idmap.json files.
Key changes:
- frame0-sync.py: push/pull/export with topo-sorted shape creation
- frame0-export-batch.sh: batch export with staleness check
- frame0-cmd.sh: fixed command names, list-pages JSON bug, added commands
- Removed frame0-wireframe.sh (superseded by JSON workflow)
- SKILL.md: renderer-only guidance, simplified workflow
- api-reference.md: corrected commands, type/color token mapping
- component-library.md: all 6 patterns rewritten as JSON templates
- .gitignore: added *.idmap.json
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
16 d2 diagrams covering architecture (IPC bridge, system tiers,
testability, audio bus), data flow (perception, dialogue, eavesdrop
pipelines), entity (knowledge graph, NPC generation, dialogue tags),
state (simulation tiers, movement stances, knowledge confidence), and
UI (HUD layout, interaction flow, fog layers). PNG output for universal
viewer compatibility. Removes test SVG from font debugging.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces Frame0 MCP server with portable bash+curl scripts that call
Frame0's local HTTP API directly. Includes low-level API wrapper,
high-level composition helpers with project styling, component library
patterns, and setup guide. Requires Frame0 desktop app running locally.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix protocol version comment (12 → 13) in ObserverSnapshot doc
- Widen Want intensity range from 3..=9 to 1..=10 to match spec and test
- Replace duplicated pool selection in trigger_recognition_monologue with
call to select_pool_line helper (~50 lines removed)
- Document NaiveSpatialIndex migration cost for grid/quadtree swap
- Remove misleading Default derive from TellCategory (Nervous is not a
sensible default for neutral NPCs)
- Add caller invariant doc on generate_npc (no TilePosition spawned)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reflects the intentional override — 1200px chosen for readability
after playtest feedback. Updates decision text, derivation, and
amendment history.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The 1200px value was a deliberate readability decision, not a spec
violation. Reverts the incorrect 640px change from round 1. Updates
comment and regression test to match.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove stale smoothing re-enable comments from main.gd (Hoshe #1).
Add DIALOGUE_MAX_WIDTH=640 regression test (Hoshe #2).
Extract GROUND_FLOOR const in tile_renderer (Tyre #3).
Clean up entity_renderer migration comment (Hoshe #3).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Regenerate all msgpack test fixtures with tell_state and follow_state
fields. Update golden proof_room snapshot. Adjust serialization and
bridge tests for new ObserverSnapshot fields.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Register all new systems in NpcPlugin and SimulationPlugin with correct
ordering constraints. Protocol bumped to v13: tell_state on VisibleEntity,
follow_state and PostConversationQueue on ObserverSnapshot, Follow verb
on VerbKind. Observer snapshot populates tell state from DerivedTellState
and follow state from FollowTarget. System ordering: tolerance after
mood, deviation after activity, tell after mood+deviation, follow after
visibility geometry, event monologue after conversations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add observe_npc, hear_sound, observe_anomaly, witness_interaction, and
post_conversation triggers to monologue system. trigger_event_monologue
system fires after sound collection, NPC conversations, and walk-away.
Context tags (location, situation, character_state) populated for D-035
content pool matching. COOLDOWN_TICKS=300 anti-spam guard respected.
witness_interaction fires after overheard NPC-to-NPC conversation per
D-078. Voice sounds and ambient sounds correctly excluded from
hear_sound trigger.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Follow verb on interaction dispatcher. FollowTarget component tracks
target entity, proximity ticks, and LOS-lost ticks. update_follow_state
system: observation events fire at double frequency while following,
NPC suspicion increases via stress when player within 2 tiles for 60+
ticks (configurable). Follow ends on LOS lost timeout, suspicion
threshold crossed, or player issues different action. FollowStateWire
emitted in ObserverSnapshot for client HUD.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
RoutineDeviationEvent emitted when NPC breaks daily routine: wrong
location for day phase or wrong activity at correct location.
CurrentlyDeviating marker prevents duplicate events per episode.
Respects pathfinding-in-progress (no false positives). Feeds
observation event generator for observe_anomaly monologue triggers.
Primary detective mechanic per D-027 criterion 4.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TellCategory enum (Nervous, Angry, Friendly, Guarded, RoutineDeviation)
with DerivedTellState component. derive_tell_state system runs after
update_mood and detect_routine_deviation. Tell state derived from NPC
axis values per D-024: Secret+low Tolerance→Nervous, low Contentment+
Hostile→Angry, high Contentment+Friendly→Friendly, high Secret→Guarded.
v0.1 renderer is monologue text, not visual animation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
RoleDefinition struct + generate_npc() seeds all 10 D-024 axes via
SimRng for deterministic generation. Constraint validation: no duplicate
relationship targets, stress < threshold, one routine entry per phase,
no contradictory personality trait pairs. Spawns fully-populated NPC
entity with 2-3 personality traits for tell system (#90).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ToleranceBreachEvent emitted when NPC stress exceeds per-seed threshold.
ToleranceBreached marker prevents duplicate events per episode, cleared
on recovery. check_tolerance_threshold system runs after update_mood,
integrates with mood FSM to push toward Hostile/Anxious. Background-tier
NPCs excluded. Unblocks #250 (triangle escalation).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Define SpatialIndex trait with entities_in_range, entities_at, and
update methods. NaiveSpatialIndex uses Vec backend with Manhattan
distance. sync_spatial_index system auto-updates from Changed<TilePosition>.
Registered as Bevy resource. Trait abstraction allows grid/quadtree
replacement later without touching callers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Critical: DIALOGUE_MAX_WIDTH 1200 → 640 to match D-076 spec.
tile_renderer: clarify z = server floor level, not scene z_index.
Add z-filter unit test (tiles at z!=0 must be skipped).
Camera test: is_equal → distance check for float safety, convergence
test frames 40 → 120 for robustness at lower smoothing speeds.
Teleport: remove redundant first snap in _teleport_transition (the
camera block in _process handles it via _teleport_in_progress flag).
entity_renderer: document y-sort bottom-anchor migration path.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace Godot built-in Camera2D smoothing with manual lerp using
CAMERA_SMOOTHING_SPEED (8.0) in constants.gd — same exponential
smoothing pattern as entity_renderer.gd. Teleport snap preserved
via _teleport_in_progress flag. D-015 fixed-north camera lock intact.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
tile_renderer: only render z=0 tiles on FloorTiles layer (D-049 z-stack).
entity_renderer: fix footprint from 24x24 to 24x32 per D-044, split
ENTITY_SIZE into ENTITY_WIDTH/ENTITY_HEIGHT with separate offsets.
game_state: add follow_target_id stub for server ticket #241.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New: docs/design/layer2-situation-mapping.md — full InteractionMemory→Layer 2
pipeline documentation, 5 relationship history states, authoring checklist.
Greeting variants added:
- Kael Davan: 12 lines (4 per location × 3 locations)
- Sera Venn: 4 lines at The Last Shift
All use situation: [greeting], correct Sprint 14 mood vocabulary.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Part A: Sprint 14 mood vocabulary applied across 20 dialogue files (334 fixes):
fond→warm, comfortable→content, worried→anxious, concerned→frustrated,
analytical→focused, conflicted→anxious/suspicious per context.
Part B: All 12 monologue pool files now carry required D-035 structural tags
(role, access, trust, situation) — 223 lines fixed.
Part C: Full access tag audit passed — all dialogue lines have valid tags.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Server (7), client (5), copy (2) tickets. Goal: player acts and
world reacts — follow/examine, dialogue access layers, server-side
monologue events, personality and tell system.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New .uid files from Godot 4 and updated .import metadata for
audio assets and fonts added during Sprint 14.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Skill for triaging in-game bug reports from the Godot client's
user://bug-reports/ directory. Reads snapshot, render, inputs,
and description files; presents summaries; offers investigate,
create ticket, or dismiss actions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Regenerated all cross-language test fixtures to include new
conversation_events wire fields (speaker/target name, color index).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- bug_report_dialog: release_focus() before queue_free() prevents
stale focus on ModalLayer blocking input to lower layers
- dialogue_box: clear dialogue_active immediately on conversation
end instead of holding for entry_lifetime
- main.gd: permanent entity ID tracking per room stops recognition
chime re-triggering when NPCs oscillate in/out of fog queue
- audio_manager: correct path res://audio/ to res://assets/audio/
- world_radial.tscn: anchors_preset 15 to 0 (script sets size)
- bug_report_dialog: push_warning to print (informational)
- debug_overlay: max() to maxi() for integer line count
- monologue_display: remove unnecessary Tween cast
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Log entries store entity IDs and resolve display names at render
time from _entity_display lookup — enables retroactive name update
when player learns an NPC's real name. Color index from server
replaces name-hash coloring for stable NPC colors.
Dialogue options: switched RichTextLabel to Label (fixes stacking
bug), added 1/2/3 number key selection, numbered option labels.
Interaction list: added background panel, mouse hover highlighting,
click-to-interact, pointing hand cursor.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
Hard cap at 256 with soft guidance to aim for ≤160 to avoid line wrap.
Allows longer lines for urgent monologue and confrontation beats that
need more space without schema validation failures.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sprint 14 #535 redesigned the dialogue box into a single chronological
log for both player-NPC and overheard NPC-NPC conversations. Updates
D-061 in perception.md to document the unified log pattern, entry
lifecycle, passive line treatment, and cross-references to D-076/D-078.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Critical: bump PROTOCOL_VERSION 8→9 for conversation_events/ended fields.
Hoshe review:
- Dirty flag (_log_dirty) prevents per-frame O(n) BBCode rebuild
- BBCode injection: _escape_bbcode() replaces [ with [lb] on server text
- D-064 regression: dialogue_active cleared in fade callback, not before
- YAML quoting: remove unnecessary quotes from numeric values
Tyre review:
- Carry-forward for dialogue_response, conversation_events, conversation_ended
in receive_bytes() — arrays merge, scalar falls through
- pause_requested/unpause_requested signals route through main.gd input
recording (_pending_record_inputs) for #507 replay determinism
- Fix version comments: dialogue_response is v8 (#305), not v9
- Remove dead _active_overheard dictionary
Araminta review:
- Passive lines: ┃ glyph prefix + _desaturate() for name colours
- Active conversation entries pinned (no timeout), unpinned with timestamp
reset on conversation end
- _enforce_contrast(): minimum luminance floor for name colour readability
- Simplified 1-on-1 attribution: "Speaker:" instead of "Speaker → You:"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Refactors dialogue box into a scrolling conversation log. All dialogue
(player-NPC and overheard NPC-NPC) flows chronologically, oldest at top.
Player response options at the bottom during active conversations.
- Entries expire after configurable timeout (equal for all message types)
- Walk-away clears options but preserves log entries (fair information)
- Per-character name colors from dialogue-theme.yaml (hash-indexed palette)
- Overheard lines render at 90% opacity (D-078)
- Protocol decode for conversation_events + conversation_ended
- GameState fields for conversation_events, conversation_ended, dialogue_response
- Mock Mira/Soren NPC-NPC conversation in test snapshot
- Also wires #511 debug overlay into main.gd and main.tscn
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Critical: bump PROTOCOL_VERSION 8→9 for conversation_events/ended fields.
Hoshe review:
- Dirty flag (_log_dirty) prevents per-frame O(n) BBCode rebuild
- BBCode injection: _escape_bbcode() replaces [ with [lb] on server text
- D-064 regression: dialogue_active cleared in fade callback, not before
- YAML quoting: remove unnecessary quotes from numeric values
Tyre review:
- Carry-forward for dialogue_response, conversation_events, conversation_ended
in receive_bytes() — arrays merge, scalar falls through
- pause_requested/unpause_requested signals route through main.gd input
recording (_pending_record_inputs) for #507 replay determinism
- Fix version comments: dialogue_response is v8 (#305), not v9
- Remove dead _active_overheard dictionary
Araminta review:
- Passive lines: ┃ glyph prefix + _desaturate() for name colours
- Active conversation entries pinned (no timeout), unpinned with timestamp
reset on conversation end
- _enforce_contrast(): minimum luminance floor for name colour readability
- Simplified 1-on-1 attribution: "Speaker:" instead of "Speaker → You:"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Refactors dialogue box into a scrolling conversation log. All dialogue
(player-NPC and overheard NPC-NPC) flows chronologically, oldest at top.
Player response options at the bottom during active conversations.
- Entries expire after configurable timeout (equal for all message types)
- Walk-away clears options but preserves log entries (fair information)
- Per-character name colors from dialogue-theme.yaml (hash-indexed palette)
- Overheard lines render at 90% opacity (D-078)
- Protocol decode for conversation_events + conversation_ended
- GameState fields for conversation_events, conversation_ended, dialogue_response
- Mock Mira/Soren NPC-NPC conversation in test snapshot
- Also wires #511 debug overlay into main.gd and main.tscn
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Keep all new variants from both branches: Greeting (copy), FirstMeeting
and RepeatedVisit (server). Combine Mood doc comments.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Warnings fixed:
- BBCode injection (line 153): escape [ → [lb] in server text before interpolation
- sort_custom on silent-drop (line 125): sort now only runs on actual insertion/replacement
- clip_contents: add clip_contents=true to MonologueDisplay Control (overflow guard)
- confrontation tick guard (main.gd): _last_confrontation_tick deduplicates same-tick signals
- GameState decoupling: show_monologue() reads lattice_profile once and passes it through
_show_line() → _build_line_node(); renderer no longer reaches into autoload (D-020)
- Equal-priority eviction: >= tiebreak (was >); FIFO for equal-priority queue overflow
Suggestions fixed:
- Minimum duration clamp: maxf(duration, FADE_IN_SEC + 0.1) — line survives own fade-in
- _label_text bounds check: guard against empty _visible before indexing [0]
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three NPC profiles added by copy team content expansion. Updates
content_loading test expectations to match actual content directory.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Additional integration tests for conversation cooldown application, distance
termination with both NPCs receiving cooldown, and edge cases in the NPC-to-NPC
conversation pipeline.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
update_relationship_dynamics runs once per game-minute (10 ticks). Edges
inactive for 1+ game-hours (600 ticks) decay trust 1 point toward 0 per
minute. Creates social texture: NPCs who haven't interacted drift to neutral
without active maintenance. Blocks #249 (social propagation, Sprint 15).
Constants: DECAY_INTERVAL_TICKS=10, DECAY_INACTIVITY_THRESHOLD_TICKS=600,
DECAY_DELTA=1. Integer arithmetic only (D-010 determinism).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ActivityState component tracks the activity an NPC is currently performing
at their routine destination (activity name, phase, started_tick). The
enter_activity system runs after movement validation and sets ActivityState
when an NPC has arrived with no active path. Cleared on phase transitions.
Feeds TellTrigger::DuringActivity and D-028 Layer 2 situation matching.
Unit tests verified via shift_change room integration.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
InteractionMemory component tracks interaction_count, last_interaction_tick,
and notable_events per NPC. Drives D-028 Layer 2 situation activation:
first_meeting (count==0) and repeated_visit (count>=3). warm_active in mood
system now derives from InteractionMemory within a 300-tick window.
Trust progression wired into dialogue systems: talk completion (+1),
walk-away (-1), confrontation (-2) emit TrustEvents consumed by update_trust.
InteractionEvent (WalkAway, Confrontation) recorded in notable_events for
fast per-pair access.
Adds FirstMeeting and RepeatedVisit Situation variants. 18 unit tests in
interaction.rs. All arithmetic integer-only (D-010 determinism). No HashMap.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
#253 monologue-content-architecture.md:
- All prerequisite fact_ids validated against knowledge vocabulary — APPROVED
- Flag: behavioral.sera_avoidance should be behavioral.sera_avoidance_pattern
- Flag: investigation.drin_inspection_pattern duplicated in investigation.yaml
- Confirm: cooldown is content-layer (schema field) — OQ item 3 resolved
- Pending: witness_interaction trigger payload (OQ item 4) — Dudley to confirm
before named-pair witness_interaction lines can be authored
#121 monologue-voice-guide.md:
- BLOCKING: mood vocabulary mismatch — voice guide uses neutral/anxious/frustrated/
content/warm/hostile but schema enum uses fond/comfortable/worried/analytical/
conflicted/concerned/relieved; hostile not in schema at all
- Provide interim mapping table so Mellanie can use correct schema names
- Flag schema gaps: analytical and relieved have no voice guide coverage
- Recommend schema rename to voice guide names (Lead decision required)
- Mood-as-selection-weight model is mechanically coherent — APPROVED
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds test_world::invariants with 29 world-query invariants (structural,
perception, population, simulation) and 7 system-execution tests. All
invariants are gated behind the gauntlet feature and run against the
fully-initialized gauntlet world. Documents StableId ranges through
Sprint 14 rooms.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
8-state NPC mood FSM driven by stress, time of day, and interaction events.
Adds MoodState component, derive_mood() pure function, and update_mood() Bevy
system wired into NpcPlugin. Adds Focused as 9th Mood content tag (D-035
Sprint 8 amendment). Syncs CurrentMood for Layer 4 dialogue selection.
31 unit tests covering priority ordering, boundary conditions, and system
integration. All random values route through SimRng (D-010 determinism).
No floats. No HashMap.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements server-authoritative per-word occlusion for NPC conversations.
ConversationEventBuffer drains into ObserverSnapshot each tick so the client
receives only words audible from the player's position. Updates test fixtures
to include the new conversation_events and conversation_ended fields.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
show_monologue() now returns early when text.is_empty(), preventing:
- ghost visible slots with blank labels
- stagger timer advancing on empty calls
- empty strings queuing when slots are full
Tests: add test_show_monologue_with_empty_text_does_not_set_displaying and
two companion cases (stagger timer unchanged, no enqueue when full) anticipating
Hoshe's QA additions to the test suite.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add content/_schema/dialogue-line.schema.json — canonical standalone line schema
with all 6 structural + 3 selection + 2 authoring-only tags and $defs for
monologue extension (character, trigger, prerequisite)
- Update dialogue-pool.schema.json: add dual_lens and notes authoring-only tags,
add additionalProperties: false to knowledge_grant
- Update monologue-pool.schema.json: add all 6 structural tags as required fields
for schema compliance (role=player_character, access=[public], trust=surface are
constrained constants); add topic, mood, dual_lens, notes
- Enumerate all 14 v0.1 situations and 9 v0.1 topics as allowed enum values per D-035
- Fix Rust sync gap: add Situation::Greeting and Mood::Focused to line_pool.rs
(D-035 Sprint 8 amendments — were in schema but missing from Rust enums, causing
content with these values to be silently dropped at runtime)
- Update line_preview.rs situation_str, mood_str match arms and help text for
new variants; all 25 line_pool tests pass
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Godot requires .import files for stable uid:// references across
editor sessions. All other audio assets have one — this was missed
in the audio branch PR.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove premature Voice/VoiceConversation from SOUND_EVENT_ASSETS (D-072
defers murmur to end-to-end sprint). Extract current_zone_id in
GameState.apply_snapshot() as first-class field, eliminating O(N) tile
scan in main.gd (D-020 server-authoritative). Add dir.list_dir_end()
after registry scan. Add rapid zone-crossing + _load_prefs() roundtrip
tests. Enhance comments on hub/workplace same-asset pattern, station
base hum, and confrontation dip replacement semantics.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
tea comment hangs with inline heredocs and multi-line strings.
Document the two-step pattern: write to .tmp/ first, then pass
via $(cat).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 3 zone enrichment tests to observer pipeline (tile inside zone,
tile outside zone, absent ZoneMap resource). Fix misleading Decay
Observatory doc comment that claimed Direct start when test starts at
KnowsDetails. Add production population TBD note on ZoneMap.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
57 new tests in test_audio_sprint13.gd covering bus setup, dip profiles,
zone crossfade, recognition chime, and murmur wiring. Fix lambda capture
bug in 3 signal tests (String → Array wrapper for reliable closure
capture in Godot 4). Add bus volume reset to before_test() for test
isolation against prefs-loaded state.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
AudioManager: volume slider persistence (ConfigFile), settings UI with
5 teal-bordered sliders, default_bus_layout.tres for editor. Zone
crossfade: defensive zone_id read from snapshot tiles, 1.5-2s ambient
tween, auto-activates when server ships OQ-09. Dip profiles: dialogue
dip in show/hide_dialogue, ListeningFocus 30-tick gate via
stationary_ticks in game_state.gd. NPC murmur: client plumbing for
event-driven World SFX playback, no-ops until audio asset arrives.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Spawned agents are told not to run git commands (team lead handles those)
and to call db/connectors scripts with bare commands only — no python3
prefix or command chaining — so they match the permission whitelist.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Server-tracked zone_id on VisibleTile for D-073 zone crossfade and
D-059 deep fog temperature tint. ZoneMap resource backed by BTreeMap,
observer enrichment in snapshot assembly. Backwards-compatible: v10
payloads deserialize with zone_id: None.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three new gauntlet test rooms for Sprint 13, each targeting a specific
system under test. StableIds are additive-only (66–74).
Sound Lab (66-68): Three NPCs at calibrated tile distances (2, 6, 12
tiles) verify D-018 three-range sound model. Tests confirm Close ≤3,
Medium ≤8, Long ≤20 tile thresholds via SoundEvent::audible_at().
Decay Observatory (69): Single NPC observed in LOS then broken. Tests
confirm D-041 confidence decay: KnowsDetails → KnowsOf → Suspects
(floor), and Stale state when stale_after threshold is exceeded.
Shift Change (70-71): Two NPCs with DailyRoutine components. Test
confirms D-031 phase-boundary check_phase_transition issues PathRequest
only to NPCs not already at their target location.
Sprint 13 reset plates (72-74) wired per existing pattern.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Produces sfx_npc_murmur.ogg via Stable Audio Open for D-072 universal
event-driven NPC proximity murmur. Organic sonic family (D-074): warm
mid-freq 200-800Hz vocal texture, human voices in adjacent room with
direction and cadence distinguishable, words not. World SFX bus.
Generated 3 candidates (5s/CFG8, 6s/CFG7, 4s/CFG9), selected candidate
1 for richest texture and clearest spatial framing. Unblocks client #533.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Typography, positioning, stacking rules (max 3 lines), priority
system (observation > atmosphere > tutorial), fade animation,
character-differentiated color (detective cool, smuggler warm),
and 80-character line length constraint for copy team.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add sprint-plan, pr-push, pr-review, ticket, docs-search, and
workshop-start to shared permission settings.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Case A on main previously closed the active sprint immediately without
checking ticket completion or open PR status. Now checks both and asks
the user before proceeding.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sprint 12 copy team output: 26 tickets covering foundation docs,
character builds, design documents, content packs, and ambient
expansion.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
D-075 dissent was pending Gestalt and Nigel input on the no-archetype-tag
decision. Gestalt endorses: access tier tags in content handle archetype
distinction emergently; starting knowledge differentials produce per-character
gate timing without hardcoded archetype filters; maintenance cost of archetype
tags would undermine the "two keyholes on the same world" experience (D-027).
Nigel's input still pending.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Ten coverage zones from Gate Terminal Approach (comprehensive) through
Corridor 7B (dead air, Severance-enhanced). Maps detective investigative
progression, smuggler operational geography, NPC behavioral modulation by
zone, and coverage-transition monologue triggers.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Cultural generation guide (#189), Sova Texture Appendix (#302),
Contraband specification (#321), Sova Station Profile (#320), and
Span Gate Transit Schedule (#336). These are the blocking foundation
docs for all three content packs (#190/#191/#192) and the Meridian
Coverage Map (#335).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix SOUND_EVENT_ASSETS walk-speed keys to match actual filename
(sfx_footstep_metal_walk), add play_loop null guard, source indicator
colors from Constants, extract CAMERA_DEFAULT_ZOOM, document
consume-once semantics on close_sound_events.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
validate_movement now inserts SoundEventEmitter with Footstep events on
every successful move. Intensity scales by stance: Sprint 0.8, Walk 0.5,
Careful 0.3, Crouch 0.15. Range is Close (3 tiles) for all stances.
This completes the sound event pipeline end-to-end: movement produces
events → collect_sound_events drains to queue → observer snapshot
includes audible events → client bridge receives them.
Addresses Tyre critical review item #1 on PR #42.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1. Sound producers: document empty v0.1 pipeline explicitly (critical)
2. Routine tests: add ActiveSim to 3 tests that passed trivially
3. Rename _observer_pos → observer_pos (used at line 191)
4. Add FactionOnly positive test case (matching faction_id)
5. Fix stale doc comment "Current: 9" → 10 in ObserverSnapshot
6. Remove orphaned SimulationTier/LastInteraction/ScopeTag types
7. Add tracing::warn on FactionOnly non-numeric parse failure
8. Document Medium-range occlusion gap as TODO in audible_at
9. Insert SoundEventQueue in observer test setup_world
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tile-level floor plans with sightline analysis for all three Sova Transit
District locations. Unblocks copy team content packs #190, #191, #192.
- spatial-layout-terminal-v01.md: The Terminal (44×28m), scanner bays,
main corridor chokepoint, manifest processing, cargo floor, supervisor
office with window, restricted storage. Sightline table, access tiers,
NPC traffic density, Triangle 1 + 2 service notes.
- spatial-layout-bar-v01.md: The Last Shift (28×22m + eastern extension).
Corner booth sightline analysis (sees entrance, bar, card table, back
room door simultaneously). Bathroom corridor as private exchange zone.
Triangle 3 + 4 service notes.
- spatial-layout-smuggling-corridors-v01.md: Ring infrastructure overlay
— restricted storage staging, maintenance corridor network, three
dead-drop locations with discovery vectors, transition corridor (40m)
with camera constraint and traffic density. Full operation flow diagram.
Also carries forward minor visual-grammar and placeholder-spec corrections
from earlier in the sprint (wall_top tile spec, cursor D-056 attribution,
transition strip procedural generation clarification).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
- main.gd: add has("entity_id") guard to _play_recognition_chimes()
(matches defensive pattern in _play_close_sound_events and update_sound_events)
- sound_indicator_renderer.gd: rename _color_for_type → color_for_type
(public testable API, not an internal-only method)
- test_rendering.gd: update test calls to match rename
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
Adds rng_seed: Option<u64> to ObserverSnapshot. The WRONG button (#507) captures
inputs.jsonl and seed.txt for replay, but seed.txt was writing "unavailable"
because the server did not include the RNG seed in ObserverSnapshot.
Changes:
- bridge/types.rs: PROTOCOL_VERSION 9→10, rng_seed field with serde(default,
skip_serializing_if = "Option::is_none") for backward compatibility
- perception/observer/mod.rs: inject Res<SimRng> into compute_observer_snapshot,
populate rng_seed: Some(rng.seed()) each tick
- All test files: add rng_seed: None to ObserverSnapshot constructors
- tests/serialization.rs: bump protocol_version_constant assertion 9→10
- Regenerate msgpack fixtures and golden file for protocol v10
Completes the WRONG button capture loop: replays can now fully reproduce
observed bugs with the exact RNG seed from the capture.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
#94 — Active tier simulation (complete):
- Add ActiveSim marker to all 9 test world room NPC spawns
- Fix test entities in routine.rs and path_follow.rs to include ActiveSim
so With<ActiveSim> queries match correctly in unit tests
#99 — Tier transition logic (complete):
- Implement update_tier_markers system in tier.rs
- Promotes/demotes tier markers by manhattan distance from PlayerCharacter:
≤40 tiles → ActiveSim, ≤120 → BackgroundSim, beyond → StateSaved
- Handles cross-z-level as u32::MAX (effectively unreachable)
- No-op when no PlayerCharacter entity present (headless tests safe)
- 11 new unit tests covering all distance bands and boundary cases
- TierPlugin now registers the system after movement::validate_movement
Also picks up extended test coverage added by hoshe:
- observer/tests.rs — 230 lines of perception observer tests
- sound.rs — additional sound event integration tests
All 548 tests pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
DIALOGUE_MAX_WIDTH: correct to 640px (20 × TILE_SIZE) per Tyre architecture
review. D-076 updated in decisions/perception.md with amendment note.
Initial 1920px was D-061 "max-width" but readability wins at 640px.
D-067 recognition chime: wire sfx_monologue_chime to fog entity recognition
onset. AudioManager.CHIME_RECOGNITION constant added. main.gd tracks seen
entity IDs in _known_recognition_ids; fires chime on first appearance in
pending_recognitions, expires when entity leaves the queue. UISounds bus
(not WorldSFX) per D-038 "monologue chime is a UI sound." Tests added
to test_audio_bus_routing.gd (Layer 2b).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add rng_seed: Option<u64> to ObserverSnapshot (protocol v10). Populated
from SimRng state each tick. Completes the WRONG button capture loop —
seed.txt now writes a valid u64 instead of "unavailable", enabling
deterministic replay from bug reports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add clippy::disallowed_types for std::collections::HashMap scoped to
the simulation crate. Replace HashMap with BTreeMap in movement.rs for
deterministic iteration order. Allow exception in perception/query.rs
where iteration order is irrelevant (per-frame scratch buffer).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements 4 completed tickets + partial progress on 2 more:
- #93 Tier marker components (ActiveSim, BackgroundSim, StateSaved + TierPlugin)
- #138 Information tag schema (ObserverAccess enum in knowledge/types.rs)
- #124 Sound event system (SoundEventEmitter, SoundEventQueue, bridge wiring)
- #193 Line previewer CLI (line_preview binary with filter/explain/sequence modes)
- #94 Active tier simulation (in progress — With<ActiveSim> filters)
- #139 Component-level access control (in progress — filter_by_access)
Updates snapshot fixtures and test golden files for new sound_events field.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
#345: entity_renderer.gd already used entity_id; added regression tests
confirming old "id" field is rejected and "entity_id" is accepted.
#447 (OQ-29): DIALOGUE_MAX_WIDTH = 1920 added to constants.gd. Full
viewport width at target resolution (60 × TILE_SIZE), per D-061 Lead
directive "max-width". Recorded as D-076 in decisions/perception.md.
#126: SoundIndicatorRenderer — fog-edge directional arrows for medium-range
sound events (D-018). Node2D at z:951 in World scene. Color-coded per
D-018/D-069 (neutral/voice/danger). GameState.medium_sound_events
partitions Medium events from snapshot sound_events field. Tests added
to test_rendering.gd; Hoshe's test_sound_indicators.gd stubs updated.
#125: Close-range stereo audio pipeline wired. AudioManager.play_sound_event()
maps event_type to D-038 asset key (Footstep/FootstepSprint → sfx_footstep_*).
GameState.close_sound_events partitions Close events. main.gd calls
_play_close_sound_events() each snapshot tick. test_audio_bus_routing.gd
Layer 4 stubs upgraded to real tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adopts the whatsinagame naming pattern where the domain comes
first and the action second (e.g. pr-review, sprint-start,
audio-gen). Updated all cross-references in settings, agents,
docs, and inter-skill references.
12 renames: commit→git-commit, create-skill→skill-create,
gen-audio→audio-gen, gen-image→image-gen, plan-sprint→sprint-plan,
push-pr→pr-push, render-sprite→sprite-gen, review-pr→pr-review,
search-docs→docs-search, start-sprint→sprint-start,
start-workshop→workshop-start.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Warnings fixed:
- contraband.rs: scan event now always emits even when NPC already
knows (was skipped by early `continue`). Contract matches doc.
- test_world/mod.rs: ScanEventBuffer added to player spawn bundle
so check_contraband_scan doesn't silently no-op in gauntlet mode.
- npc/mod.rs → simulation/mod.rs: moved check_contraband_scan
registration to SimulationPlugin (operates on player inventory and
snapshot pipeline, consistent with process_talk_interaction).
Suggestions addressed:
- cross_room_transitions.rs T1: clarified standalone position vs
constants.rs observer position in comment.
- dialogue.rs: Vec<&str> dedup replaced with BTreeSet<&str> for
deterministic iteration (project convention).
- contraband.rs: added test for multiple simultaneous ScanAuthority
NPCs in range (564 tests total).
- dialogue.rs: doc-comment on relationship_to_trust explaining
KnowledgeConfidence ordering and Suspects default.
- cross_room_transitions.rs T5: noted direct KG API usage vs full
perception system.
- sprint_gauntlet.rs: documented intentional Contentment { level: 0 }.
- content_scaling.rs: noted GAUNTLET_NPC_COUNT is manually maintained.
- contraband.rs: doc-comment on cross-plugin registration rationale.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Gitignored .tmp/ avoids Bash permission prompts when writing
temp files for tea comment posting. Added sed -n blanket
permission. Updated review-pr skill to use Write tool into
.tmp/ instead of Bash heredocs to /tmp/.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Test plan for #507/#522, preliminary review of #522, and final
combine test report. All tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
33 tests: 17 for ring buffer (capacity, overwrite, JSONL format, seed),
16 for insert-off behavior (diegetic test, cursor transitions, cross-system).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Upgrades bug_report_dialog.gd from single-tick MVP to 60-tick rolling
history. Pre-allocated ring buffers for inputs and snapshots. Outputs
inputs.jsonl (replay-compatible), snapshots.jsonl, and seed.txt on F12.
Inter-frame input accumulation ensures no inputs lost between server ticks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Option (a): cursor shape still changes (body orients to targets), but
verb labels and interaction prompts are suppressed when insert_active
is false. Amends D-056 and D-057 with resolution note.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cross-room transition tests (server/tests/cross_room_transitions.rs):
- T1: sprint suppresses interaction buffer, restores on Walk (D-055)
- T2: CarriedBy survives room transition — no TilePosition leak (D-065)
- T3: pause mid-corridor discards movement, Unpause resumes (D-031)
- T4: KnowledgeGraph persists across player position change (D-041)
- T5: entity knowledge downgrades Direct→KnowsDetails on LOS exit (D-060)
- T6: eavesdrop cut immediately on first movement out of corner (D-071)
- T7: confrontation verb disappears on retreat beyond MID_RANGE=5 (D-057/D-070)
- T8: Sprint blocks eavesdrop accumulation, Careful enables it (D-055+D-071)
All 8 tests pass. Test suite grows from 545 → 563 (18 tests added across sprint).
Tests use direct ECS World + Schedule pattern; T3 uses full App + SimulationPlugin.
Test suite expansion:
- content_scaling.rs: max_npc_pack_behavioral_regression + stress tests (#513)
- golden/proof_room_tick_10.json: updated golden file for gauntlet world changes
- golden_suite.rs, serialization.rs, bridge_ipc.rs, bridge_tcp.rs: adapted to
new world entity count and wire types
- gen_fixtures.rs, perf_bench.rs, content_runtime.rs: minor test adaptations
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds three new test rooms to the gauntlet layout at coordinates that tile
correctly with the existing Sprint 11 world. All rooms follow the canonical
entity-registration pattern (StableId 55-62 assigned in spawn order).
- sprint_gauntlet.rs: 32×22 room (StableId 55-57) — Npc_pacing, Npc_guard,
Readable sign. Validates sprint suppression (D-055) at close range.
- eavesdrop_alcove.rs: 24×16 room (StableId 58-60) — two NPC speakers,
corner Readable marker. Validates eavesdrop positioning (D-071).
- confrontation_stage.rs: 32×24 room (StableId 61-62) — Npc_target and
peripheral passer-by NPC. Validates confrontation verb range (D-070).
Updated test_world: mod.rs registers all new rooms, constants.rs adds GAUNTLET
region constant and room spawn points, reset.rs clears all gauntlet rooms.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Server (5 tickets), client (2 tickets), and joint coordination
briefings for the Gauntlet completion sprint.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Documents audio-batch manifest format, synth parameters, and the
--post flag as the preferred workflows. Batch reduces approval
count from ~30 to 2 for multi-asset generation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reduces prompt approvals from ~30 per batch to 2 (one manifest write,
one batch run). audio-generate --post chains trim+normalize+convert
after generation. audio-batch processes a JSON manifest of multiple
assets sequentially, supporting both SAO generation and harmonic
synthesis methods. Includes --dry-run, --only, and --skip-existing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Updated ambient.md, sfx.md, and ui.md with generation parameters,
frequency specs, and integration notes for all 8 new assets.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@@ -28,7 +28,7 @@ Named after Qatux, the Raiel with perfect memory who helped Paula Myo by recalli
- Provide "state of the project" summaries when asked
### Knowledge management
- Maintain the Qdrant document index via /search-docs skill
- Maintain the Qdrant document index via /docs-search skill
- Update briefing files when decisions change
- Answer retrieval questions: "did we discuss X?", "what did we decide about Y?"
- Catch staleness in briefings and flag for update
@@ -44,7 +44,7 @@ Named after Qatux, the Raiel with perfect memory who helped Paula Myo by recalli
- **Work in dedicated round files:** All new rounds happen in `docs/discussions/round-NN-topic.md` from the start. DISCUSSION.md is retired for new content.
- **Update the discussion index ONLY when closing:** After a round is formally closed, update `docs/discussions/README.md` with the round entry (number, topic, decisions produced, file link).
- **Update briefings:** After a round produces new decisions, update the relevant agent briefing files in `docs/briefings/`.
- **Re-index documents:** After archiving or updating documents, re-index them in Qdrant via `db/connectors/qdrant-index <path>`.
- **Re-index documents:** After archiving or updating documents, re-index them in Qdrant via `tooling/db/qdrant-index <path>`.
tea issue list --login schweitz --repo jpmschweitzer/settled-reach --state open --output simple
```
## Key rules
- **All flags must be explicit** — omitting `--login` or `--repo` triggers interactive prompts that crash in Claude Code (no TTY)
- **Use `--output simple`** for machine-readable output (no table borders)
- **For comments, use `tooling/tea-comment <number> "body"`** — handles temp files and cleanup automatically. Works with multi-line strings.
- **`tea pr reject` does not work on your own PRs** — use `tea comment` instead
- **Never delete protected branches:** `main`, `maintenance`, `server`, `client`, `copy`, `audio`, `visual`, `ci` are protected on Gitea. Do not use `tea pr clean`, `git push --delete`, or `git branch -D` on these branches.
## Pull requests
**Use `tea` (Gitea CLI), not `gh` (GitHub CLI).** The remote is Gitea at `git.schweitz.internal`.
Always provide all required flags to ensure non-interactive execution:
When producing many files (wiki pages, content batches, bulk docs):
1.**Lore librarian** agent (read-only): ingests all source material, answers focused context queries from writers, tracks cross-file consistency
2.**Multiple writer** agents (parallel, by domain): each gets a task slice, writes directly to disk using the Write tool — one file at a time, write often, no text accumulation
Key: writers use Write tool directly (no transcription bottleneck), librarian catches contradictions early, split work by domain not volume.
## Team monitoring (stuck agent detection)
When leading a team (sprint, workshop, or any multi-agent session):
**Agent heartbeat rule** — include in every agent spawn prompt:
> If you have been working on a single task for more than 15 minutes
> without making progress, message the team lead with what is blocking
> you. Do not keep retrying the same approach silently.
**Team lead proactive checks:**
- If an agent has not sent a message in ~20 minutes, ping them for a status update.
- **Bottleneck detection:** if other agents are idle and waiting on one agent's output, that agent's silence is a red flag — check on them immediately, do not wait for the next natural message.
- When checking on a stuck agent, offer to reassign the task or pull in another agent to help.
@@ -6,6 +6,376 @@ Format based on [Keep a Changelog](https://keepachangelog.com/).
## [Unreleased]
## [v0.1.23] — 2026-03-04
### Added
- TileKind enum (Floor/Wall/Void/Restricted) on WalkabilityMap with per-tile type data alongside walkability (#576, D-094)
- Location YAML tile format — hand-author tiles as string arrays (F/W/V/R characters), loaded into WalkabilityMap on production startup (#577)
- Chunk streaming system — ChunkLoadRadius and cadence-gated load/unload around player position, v0.1 covers full district (#578, D-012)
- EngagementRecord component — per-NPC observation time, conversation count, and monologue trigger count tracked by perception/dialogue/monologue systems (#570)
- MovementHistoryBuffer resource — 3000-tick ring buffer of player positions with co-presence proximity query (#571)
- Storyteller lifecycle rules — single activation per session, no concurrency, terminal resolution constants (#572)
- Debug console server — 10 DebugCommandKind variants (AdvanceTicks, SkipToContamination, TeleportToPosition, InspectNpc, ListTriangles, etc.) with DebugResponsePayload on ObserverSnapshot (#580)
- Debug console client — tilde-toggle UI panel with command input, output log, settings toggle, and full DebugCommandKind dispatch via protocol v18 (#581)
- Entity-bound dialogue speaker colors — NPC colors assigned by entity ID (not screen position) with per-conversation lifecycle and round-robin palette (#573)
- Sova Transit District tile maps — 5 locations authored: The Terminal (44×28), The Last Shift (34×22), Maintenance Corridors (58×6), Gate Ground (40×34), Gate Gallery (32×10) (#582, #583)
### Fixed
- LOS boundary walls — 1-tile wall margin beyond vision cone included in visible_tiles as BoundaryWall sector, walls at fog edge now render instead of bleeding into fog (#584)
- LOS boundary walls client — BoundaryWall tiles render through fog without marking explored, 4 new fog tests verify lifecycle (#585)
- Entity renderer test failures — updated 7 stale ColorRect/position assertions for Sprite2D migration, fixed SoundIndicatorRenderer class cache (#574)
- Dialogue speaker color contrast — re-enforce contrast floor after desaturation for passive (overheard) lines
- PROTOCOL_VERSION 17 → 18 mismatch — client rejected every server snapshot
- Debug console D-088 pause — sim now pauses while console is open, matching dialogue/settings overlay behavior
- Debug console settings toggle reads live state instead of ConfigFile, preventing checkbox divergence
### Changed
- PROTOCOL_VERSION bumped 17 → 18 (debug_response field on ObserverSnapshot, DebugCommand PlayerAction variant)
## [v0.1.22] — 2026-03-03
### Added
- Visual test harness — `make screenshot`, `make test-visual`, `make visual-update` for automated visual regression testing with golden PNGs across 11 scenarios (fog, HUD, dialogue, minimap)
- Visual movie mode — `make visual-movie` captures interaction flows as frame sequences with contact sheet generation
- World seed protocol — StartupMessage carries world_seed from client to server after handshake, enabling deterministic NPC population seeding (D-010, D-029)
- EntanglementConfig — per-seed NPC population ratios (flat/mundane/intrigue) sampled from seeded RNG with D-029 bounds, ensuring same seed = same world (#175, #178)
- Fog debug mode — toggle FogState.debug_exploration to render raw exploration texture as colored overlay for diagnostic use
- D-110 through D-112: z-level addressing, subterranean architecture, no instancing decisions
- Q-051: speech bubble indicator over speaking NPCs
- Production NPC pool generation — 23 authored Sova NPCs spawn with EntanglementTag (Flat/Intrigue) based on triangle membership (#176, D-029)
- Authored triangle instantiation — 5 Sova triangles (3 active forks, 2 passive tensions) loaded from content YAML with deterministic IDs (#188, D-087)
- Contamination activation mechanic — timer-based storyteller fires after 30 game-minutes, pressures active triangles, emits ContaminationEvent (#254)
- Modifications data model stub — Vec<Modification> on chunk entities, round-trips through save/load for future construction DLC (#567, D-112)
- Zone Gate gauntlet room — two-zone test room with door boundary, zone crossing detection system (#512)
- Fuzzy map tests — 50-seed randomized testing of procedural maps against 4 structural invariants (#509)
### Fixed
- Fog shader: silent compilation failure in OpenGL3 compat mode — removed `return` statements from fragment() which are not supported, causing fog overlay to render as no-op (root cause of Sprint 22 fog regression)
- Fog system: blocky stair-stepped edges at vision cone boundary — doubled Gaussian blur step size for D-066 compliant 6-8 tile smooth gradient (#569)
- Fog system: zero visibility in explored areas — switched bounds calculation from visible_tiles (empty in live server mode) to visible_positions, and removed shader guard that cut off gradient bleed into unexplored tiles (#569)
- Fog shader alpha tuned to D-059 spec: light fog 0.25-0.35 (was 0.25-0.55), deep fog 0.55-0.70 (was 0.78-0.90) — world content now visible through fog instead of hidden behind it (#563)
### Changed
- Fog shader now distinguishes light fog (near cone, neutral dark) from deep fog (far from cone, zone temperature tint) with separate Perlin noise breathing cycles (8-10s / 15-20s)
- Zone temperature tint populated per-tile from server zone_id: bar=warm amber-dark, hub=cool blue-dark, corridor=neutral dark (D-059/D-046/D-077)
- Simplified vision cone from 3-sector (forward/peripheral/blind) to forward-only 120° arc — server sends only forward-cone tiles, client renders explored tiles behind the player with light fog overlay
- Simplified fog shader from 5-layer to 3-layer model (clear, explored, unexplored)
- Fog texture resize now preserves exploration data — tiles behind the player stay as light fog instead of reverting to unexplored black
- Updated D-015/D-017 perception decisions to reflect simplified cone model
- Moved connector scripts from db/connectors/ to tooling/db/ (#274) — backwards-compat symlink removed in #568
### Removed
- db/connectors symlink — all references now use tooling/db/ directly (#568)
## [v0.1.20] — 2026-02-25
### Added
- Social site template schema — RoleSchema (#163), SpaceSpec (#164), TriangleDef (#106) with YAML deserialization, sample templates at server/data/templates/
- Single-ownership model — TemplateOwnership component, TemplateReferenceMap resource, cross-template reference links preserved across save/load and tier eviction (#165, D-025)
- Triangle generation — intra-template constraint satisfaction assigns NPCs to triangle roles, minimum 2 triangles per template with fallback on imperfect seeds (#107)
- Triangle escalation system — tick_triangle_escalation runs per game-minute, tension increments toward ToleranceThreshold, TriangleCrisisEvent emitted on Active phase entry, ResolveTriangle stub command (#250, D-087)
- Protocol v16 — TriangleCrisisEventWire on ObserverSnapshot for future client rendering of triangle crises
- D-093: Sova Transit District spatial layout — 4 social sites (Terminal, Bar, Gate Cluster, Sector 3), 2 encounter nodes, zone palette, gate cluster 7-zone spec, z-level scheme (z=0 maintenance, z=1 main, z=2 observation gallery), 3 investigation paths, corridor widths
- YamlParser shared utility — unified YAML parsing for UI strings and checklist conditions (#560)
### Fixed
- Wire triangle crisis event queue into observer snapshot — clients now receive TriangleCrisisEventWire via protocol v16 (was always empty)
- Persist TriangleState in SaveStateV1 — triangle phase and tension survive save/load cycles
- Validate dangling with_role references in TriangleDef constraint validation
- Replace O(n²) fallback NPC assignment with BTreeSet; prevent same NPC assigned to two roles in one triangle
- Replace O(N*M) scan in apply_resolve_triangle with BTreeMap index for O(1) per-command lookup
- Add From impls for RoleId, TriangleId, StableId, TriangleCrisisEventWire — eliminate fragile .0 newtype access
- Consolidate near-identical unit tests with integration counterparts
### Changed
- Sova station profile updated — horizon gates located at The Krenn Ring (800 AU), not on Station Sova; Admin Hub houses transit processing facility only
- game_state.gd: stationary_ticks and zone_id now read from server snapshot with deprecated client-side fallbacks (#557, D-020)
- dialogue_box.gd: decoupled from GameState and AudioManager via signals — zero direct autoload references (#558, D-020)
- main.gd: snapshot dispatch via SnapshotEventRouter, dialogue signal coordinator handlers (#559, #558)
- ui_strings.gd and checklist_evaluator.gd: delegate to YamlParser, ~140 lines of duplication removed (#560)
- Protocol version handshake — `HandshakeMessage` as first IPC frame before tick loop, forward-compatible input handling (#555, D-020)
- Protocol v15 — `save_result` field on ObserverSnapshot for client save/load confirmation
- State serialization primitives — `serialize_npc_to_frozen`/`deserialize_npc_from_frozen` with full D-024 10-axis coverage for tier eviction freeze/thaw (#96, D-026)
- Scope tag system — `ScopeTagKind` (Neighborhood, ActiveQuest, Colleague, KnownContact), `ScopePinned` marker, automatic assignment from KnowledgeGraph and RelationshipGraph (#98, D-026)
- Timestamp-based eviction — `LastInteractionTick` LRU tracking, `SimSpacePressure` resource, BinaryHeap eviction respecting scope-pinned entities, Active cap 80 (#97, D-026)
- Save/load ECS extraction — `save_to_file`/`load_from_file` via MessagePack, `SaveGame`/`LoadGame` IPC commands, `SaveLoadResultWire` on ObserverSnapshot (#553, D-085)
- ScopePinned eviction regression test — adversarial at-scale test proving pinned NPCs survive eviction even with oldest ticks
- Test infrastructure — Layer 3 integration test entry point, three-layer architecture per D-030 (#200)
- Information boundary negative tests — 4 tests proving no passive KG leakage, LOS fog holds, tier boundary holds, per-NPC save isolation (#272, D-010)
- gdUnit4 CI runner script — headless test execution via `run_gdunit4.gd` with exit code for CI (#205)
- Scene testing utilities — SceneHelper class with node existence, signal, and path helpers for gdUnit4 (#206)
- Game session management — per-game save directories under `user://saves/<timestamp>-<seed>/` per D-085, SessionManager autoload, main menu scene (#258)
- Debug visualization overlay — F3-toggled dev overlay with LOS rays, vision cone arcs, NPC path trails, knowledge confidence tags, tick timing sparkline (#348)
- SimBridge→TestHarness extraction — test simulation logic separated into dedicated RefCounted class with backward-compat proxy API
- D-087 through D-092 — recovered decisions from v01-content-scoping and wiki-review workshops (triangle config, pause system, content scope, voice registers, anchor lines, complicity theme)
- Q-030 through Q-039 — open questions from workshop backlog (seed schema, style guide, cultural ingredients, NPC architecture, PC archetypes, sacred/profane framework, district skeleton, generator pipeline, authored content estimate, gate topology)
- Decision ID claim system — `db/connectors/decision` CLI with `next`, `claim`, `check-dupes` commands to prevent cross-worktree D/Q/R ID collisions, pre-commit duplicate check
- D-085: Per-game save directory structure — every new game creates `user://saves/<game-id>/`, F5 quicksave, F6 quickload
- Q-029: Save file format design — long-term considerations for versioning, compression, integrity, metadata headers
- D-086: Renumbered insert icon system (was D-084 on visual branch) to resolve cross-worktree ID collision
- Save/load wireframe updated for D-085 — LOAD tab shows games grouped by directory with expand/collapse, QUICKSAVE slot, F5/F6 hints
- Sprint 19: Persist planned — 16 tickets (server 7, client 5, CI 4) covering save/load, tier eviction/scope, test infrastructure
- Character creation & game setup workshop brief — covers creation model, seed boundary, gate activation, quest seeding, game toggles (resolves Q-011)
- Protocol v14 — `poi_list`, `examine_result`, `player_knowledge` ObserverSnapshot wire types with live KG serialization (#151, #174, #264)
- Minimap rendering — circular 160px diegetic insert overlay with POI dots (colored by category), border arrows for distant POIs, player-centered fixed-north (#151)
- Dialogue UI hardening — confrontation italic voice (D-063), examine result overlay with 5s auto-dismiss and confidence coloring (#174)
- Knowledge/journal panel — right-side insert panel (J key), facts grouped by entity, contradicted entries in amber with strikethrough, stale entries dimmed, mutual exclusion with dialogue (#264)
- Sprint 18 client test suite — 50 gdUnit4 tests for dialogue (D-062, D-063, D-064) and journal (KG parsing, scene structure, UIStrings), plus test plan document
- D-084: dual-namespace line ID scheme for auto-generated NPCs — role pool (shared, unchanged) + instance override (opt-in, seeded counter). Resolves Q-028 (#544)
- Tier 1 drama module schema (`content/schemas/drama_module.schema.yaml`) — entry conditions, NPC requirements, event sequences, outcomes, pool format (#158)
- Trait modifier system — Cautious/Gossipy/Loyal/Talkative filter predicates via content-authorable config (D-081, #173)
- POI data model and proximity-based discovery system via KnowledgeGranted events (#148, #149)
- Protocol versioning tests — version round-trip, mismatch detection, serde_default migration pattern, full variant coverage (#232)
- Team monitoring rules — heartbeat rule for stuck agent detection, bottleneck detection pattern
-`tooling/tea-comment` — single-command wrapper for posting Gitea PR/issue comments with multi-line bodies
- D-086: Insert icon system — custom SVG icons over icon fonts, authored to insert geometric constraints with lattice_profile weight scaling
- Insert/HUD wireframe and visual spec (#314) — dual character variants (smuggler social network view, detective investigation overlay) with pixel-precise layout, entity markers, time display, border arrows, commission grid, and all interaction states
- Contradiction monologue lines — 16 hand-authored lines (8 detective, 8 smuggler) for Sera/Kael FRIEND arc, Phase 2 blindsiding + Phase 3 pattern recognition, cognitive-dissonance-not-accusation tone per D-083 (#552)
- Diegetic tutorial monologue — 20 lines (10 per character) teaching movement, fog, sound, NPC interaction, and insert/HUD through character voice, fire-once on first-time events (#330)
- Diegetic time display on insert HUD — station local time (HH:MM), day phase with cycle-tinted color, day number on InsertOverlay (#263)
- Relationship color accent on E-Talk overlay — 3px left-edge bar using D-033 palette signals NPC relationship at a glance (#537)
-`Constants.format_game_time()` helper for converting game-minutes to HH:MM station time
-`/sprint-status` cleanup sweep skill — consistent health report with tickets by status, PR cross-reference, bookkeeping issue detection, and open work by team
-`sprint sweep` CLI subcommand — structured JSON output for sprint health checks (grouped tickets, per-team summary, issue detection)
- Entity renderer migrated from ColorRect placeholders to Sprite2D with D-019 angle sprites — self_modulate for D-033 tinting, 8→4 octant direction mapping, feet-anchored y-sort (#540)
### Fixed
- Client protocol version bumped to 15 to match server (was still at 14 after server PR #68 added save_result field)
- gen_fixtures.rs version comments changed from hardcoded 14 to PROTOCOL_VERSION constant
- run-ipc-benchmark dead --iterations flag removed (Rust compile-time constant governs rounds)
### Changed
- Team boundary framing — replaced worktree-centric language with `$WORKTREE_TEAM` env var identity across CLAUDE.md and skills (sprint-start, sprint-plan, pr-review) to prevent agents from following `.git` pointers across boundaries
- CLAUDE.md compacted from 188 to 67 lines — CLI references, endpoints, and patterns moved to `.claude/rules/`
-`/sprint-status` delegates to haiku subagent — keeps sweep JSON, template read, and PR list out of main context window
- Line variety tracker wiring — DialogueCooldownTracker prevents repeat lines within 600-tick window (#338)
- DialogueResponse cross-language fixture for GDScript testing
- Sprint team lifecycle through PR review — teams stay alive for commit → push → review → fix loop → approve → shutdown
- Zone_id extraction in game_state.gd optimized from O(N) tile scan to O(1) dictionary lookup — builds _tile_by_coord from member visible_tiles covering both test and live paths (#543)
- Shared run_dialogue_pipeline() helper eliminates ~60 lines of duplication between Talk and DialogueResponse systems
- Dialogue and monologue line IDs migrated from location-scoped (the-terminal_d_039) to NPC-scoped (kael-davan_d_001) namespace — each NPC has an independent sequence per D-035 (#542)
- DialogueCooldownTracker documented as per-player-global by design (NPC-scoped line IDs per D-035 prevent collision)
- CONFRONTATION_LINES marked TODO for migration to D-028/D-035 content pipeline
- pr-push and pr-review skills updated with team lifecycle awareness
### Fixed
- PR #59 review: stale mood vocabulary updated in line-pool-format.md, style-guide, and content-directory-structure.md to post-Sprint 14 values
- PR #59 review: orphaned location-scoped IDs in maintenance-tech.yaml comments and smuggler-inventory.yaml cross-references updated to NPC-scoped
- PR #59 review: Lera Sessik tenure corrected from "twelve years" to "eighteen years", NPC header fixed
- PR #59 review: ring-operative.yaml fact_id corrected from `location.surveillance_gaps` to `investigation.surveillance_gaps`
- Dialogue systems moved from BridgePlugin to NpcPlugin — game logic registers where it belongs (#538)
- Schedule ambiguity: emit_observation_events now has explicit .before(advance_tick) constraint
- process_dialogue_response updates ActiveDialogue tick and InteractionMemory on follow-up
- DialogueResponse range check added (CLOSE_RANGE, matching Talk/Confront pattern)
- Weighted selection fallback replaced with unreachable!() — dead code removed
- assert!(false) → panic!() in serialization tests (clippy)
- SetFacing and TeleportToHub added to roundtrip test coverage
## [v0.1.15] — 2026-02-23
### Added
- Sprint 16 "Converse" briefings — 8 tickets across server/client/copy/visual teams
- 19 UI wireframes — HUD, dialogue, monologue, popups, menus in v0.1 and v1.0 variants with D-record cross-references
- Dialogue theme system — configurable NPC name colour palette, entry timing, passive opacity via dialogue-theme.yaml
- Monologue display system visual spec — typography, positioning, stacking, priority, fade animation, character color differentiation, 80-char line constraint (#315)
- Entity color system spec — D-033 relationship-to-player mapping, transition animations, color blindness assessment (#304)
- Text display hierarchy spec — 4 content pipelines (dialogue, monologue, observation, environmental) with z-layers and positioning (#316)
- Sound indicator visual design — fog-edge pulse for D-018 three-range sound model with direction encoding and range differentiation (#317)
- THE FRIEND visual treatment spec — 3-phase earned visual detail for Kael Davan and Sera Venn (#318)
- Environmental text visual standards — signage, terminal, and news ticker rendering with bilingual Concordat/Krenn treatment (#334)
- Monologue line pool maxLength raised from 160 to 256 chars (soft guidance ≤160)
- NPC name masking infrastructure — entity-anchored dialogue log with server-side role labels, retroactive name update on learning, NpcColorIndex for stable color assignment
- Dialogue option keyboard selection (1/2/3 number keys) and numbered option labels
- Interaction list chrome — background panel, mouse hover highlighting, click-to-interact, pointing hand cursor
### Changed
- D-061 updated to document unified conversation log architecture from Sprint 14
- Dialogue options switched from RichTextLabel to Label for reliable VBoxContainer sizing
### Fixed
- Visual grammar dialogue max-width corrected from "~70% screen width" to 640px per D-076
- BBCode injection in dialogue log formatting — server-sourced strings now escaped with [lb]
- Per-frame dialogue log rebuild replaced with dirty flag (performance)
- dialogue_active lifecycle — now cleared after panel fade completes per D-064
- PAUSE/UNPAUSE routed through main.gd input recording for bug report replay (#507)
- WASD input freeze after filing bug report — LineEdit focus not released before queue_free() across CanvasLayers
- WASD not reactivating after Talk — dialogue_active held for entry_lifetime instead of cleared immediately
- Recognition chime spam — entity IDs now tracked permanently per room instead of expiring
- Audio path warning — res://audio/ corrected to res://assets/audio/ in AudioManager
- world_radial.tscn anchors_preset warning — changed from 15 to 0
- bug_report_dialog.gd push_warning changed to print for informational message
## [v0.1.13] — 2026-02-20
### Added
- D-078: Overheard NPC conversation — passive dialogue panel with server-authoritative stochastic word occlusion
- Sprint 14 "Live" briefings — 22 tickets across server (7), client (3), copy (6), visual (6)
- Auto-checklist progress tracking (#503) — ChecklistEvaluator parses room YAML and evaluates 7 condition types against GameState with latching, ChecklistOverlay renders progress in gauntlet mode only, 48 new tests
- 4 ambient zone loops: station base, workplace, bar, corridor — SAO-generated organic soundscape with crossfade loop points (#327)
- 2 footstep SFX: metal walk and run — SAO hybrid with best-transient extraction (#327)
-`audio-batch` command — batch audio generation from JSON manifests, supports SAO and harmonic synthesis, with `--dry-run`, `--only`, and `--skip-existing` flags
-`--post` and `--output-ogg` flags on `audio-generate` — chain post-processing (trim, normalize, convert) into a single command
### Changed
-`push-pr` skill now runs `/commit` first when uncommitted changes are detected
- Insert open/close now sends explicit PauseSimulation/ResumeSimulation (#518, D-058) — replaces toggle-style pause with idempotent pair
- Interaction list colors reference Constants.IMPLANT_TEXT_COLOR instead of hardcoded values
- World radial menu uses theme font instead of ThemeDB.fallback_font
- Monologue chimes replaced with production-quality manual synthesis — insert-tech aesthetic per D-074, pure sine harmonics with mathematical envelopes (#327)
### Fixed
- Bidirectional relationship check (#515) — Check 9 tested `target in npc_rels` which missed NPCs with no relationship entries; changed to `target in self.npcs`
A top-down immersive sim — occlusion-based detective game with combat elements, set in an original science fiction universe. Single-character perspective, asymmetric information as core mechanic, Rimworld-style storyteller. Godot 4 client + Rust/bevy_ecs simulation server via subprocess/IPC (D-020).
A top-down immersive sim — occlusion-based detective game with combat elements, set in an original science fiction universe. Single-character perspective, asymmetric information as core mechanic, Rimworld-style storyteller. Godot 4 client + Rust/bevy_ecs simulation server via subprocess/IPC.
**Official Title:** The Settled Reach (D-021)
**Repository name:** settled-reach (formerly commonwealth, renamed for clarity)
**Official Title:** The Settled Reach
**Repository name:** settled-reach
**Version source of truth:** `project.yaml` (root `version` field, scheme: `0.1.{sprint_number}`)
Full annotated tree: `.claude/rules/project-structure.md`
## DevOps
See [docs/DEVOPS.md](docs/DEVOPS.md) for build, test, lint, and CI procedures. All development operations go through the top-level `Makefile` — run `make` for a summary of targets.
## Agent Instructions
### Worktree boundaries
### Team boundaries
This project uses **git worktrees** in a shared parent directory (`settled-reach/`). Each team branch (`server`, `client`, `copy`, `audio`, `visual`, `ci`) is checked out in its own worktree under that parent. The parent directory also contains shared resources like the ticketing database.
**Your team identity is `$WORKTREE_TEAM`.** All work must stay within the current working directory.
Each worktree contains the full repository: `server/` (Rust backend), `client/` (Godot client), `docs/`, `decisions/`, etc. The worktree root IS the git root — use `git rev-parse --show-toplevel` if in doubt.
Unless there is a direct instruction or a functional need (e.g. accessing the shared database in the parent directory), **all work must remain within the scope of the git root Claude is running in.**
- All file paths are relative to the worktree/git root (e.g. `server/src/bridge/types.rs`, `client/scripts/rendering/fog.gd`).
- Do not navigate to or access sibling worktrees in the parent directory (`../client/`, `../copy/`, etc.) unless explicitly instructed.
- Do not navigate above the git root unless explicitly instructed.
- All file paths are relative to the current working directory (e.g. `server/src/bridge/types.rs`).
- **Do NOT navigate to parent or sibling directories** (`../`, `../client/`, etc.) unless explicitly instructed. Do NOT use absolute paths to reach other team directories.
- **Do NOT write auto-memory files for other teams.** If `$WORKTREE_TEAM` is `server`, do not write to memory paths containing `client`, `main`, etc.
- For context: each team has its own directory via git worktrees, sharing a parent directory (`settled-reach/`). The `.git` file points to a shared git directory — do not follow it to determine your working root.
- **Exception — stale git lock files:** If a `git` command fails with `index.lock: File exists`, you may remove the lock file for **your own team only** (e.g. `main/.git/worktrees/$WORKTREE_TEAM/index.lock`). Never touch lock files belonging to other teams.
### Database
@@ -69,107 +43,36 @@ The ticketing database (`settledreach.db`) lives in the **parent directory** sha
### Before starting work
1. Read your sprint briefing at `docs/sprints/sprint-N/{team}.md` for current tasks
2. Use `db/connectors/ticket show <id>` for full ticket details
2. Use `tooling/db/ticket show <id>` for full ticket details
3. Read the relevant `decisions/*.md` domain file(s) referenced in the briefing
**Prefer the ticket CLI over raw SQL.** The CLI handles column names, joins, and output formatting correctly:
```bash
db/connectors/ticket list --sprint 2 --team server
db/connectors/ticket show 78
db/connectors/ticket sprint --active
```
### CLI tools
### Sprint CLI
**Use the sprint CLI for sprint-scoped operations.** It batches ticket queries and formats output for agent consumption:
```bash
db/connectors/sprint status # Current sprint progress
db/connectors/sprint status --team server # Team-scoped view
db/connectors/sprint start-work --team client # Full context dump for starting work
db/connectors/sprint prepare # Prepare next sprint (candidates + gaps)
db/connectors/sprint start # Activate a planned sprint
db/connectors/sprint stop # Complete an active sprint
```
Team is auto-detected from the current git branch (if not `main`). Sprint is auto-detected from DB state.
**Prefer CLI wrappers over raw SQL.** Never use the `sqlite3` CLI — it crashes in Claude Code (std::bad_alloc). Use the wrapper scripts instead.
Only fall back to raw SQL for queries the CLI doesn't support. **Never use the `sqlite3` CLI** — it crashes in Claude Code due to a known std::bad_alloc bug. Use the wrapper scripts instead:
```bash
db/connectors/sqlite-query "SELECT * FROM tickets WHERE status='in_progress'"
db/connectors/sqlite-exec "UPDATE tickets SET status='done' WHERE id=1"
tea issue list --login schweitz --repo jpmschweitzer/settled-reach --state open --output simple
```
Key rules:
- **All flags must be explicit** — omitting `--login` or `--repo` triggers interactive prompts that crash in Claude Code (no TTY)
- **Use `--output simple`** for machine-readable output (no table borders)
- **`tea pr reject` does not work on your own PRs** — use `tea comment` instead
- **Never delete protected branches:**`main`, `maintenance`, `server`, `client`, `copy`, `audio`, `visual`, `ci` are protected on Gitea. Do not use `tea pr clean`, `git push --delete`, or `git branch -D` on these branches.
- **Prefer live Gauntlet testing over mocks.** For visual tests and rendering verification, use the full client/server pipeline (`--test-mode` + `SR_LIVE=1`) instead of TestHarness mocks. The Gauntlet test world produces production-identical data. Mocks can mask rendering bugs by taking different code paths.
- **Gauntlet rooms are immutable.** Never modify existing rooms — new systems get new rooms. This ensures StableId determinism and fixture stability.
- Three test tiers: (1) Live server — highest fidelity, (2) MessagePack replay via `Protocol.decode_snapshot()` — for unreachable rooms, (3) TestHarness mock — for UI-only tests where fog data doesn't matter.
- `make fixtures-gauntlet` regenerates real server snapshot fixtures from the Gauntlet world.
### File conventions
- Decisions: domain files in `decisions/` (see `decisions/README.md` for index)
- **Claim IDs before writing:**`tooling/db/decision claim D <domain> "title"` — prevents ID collisions across worktrees
- Diagrams: `.d2` source + `.png` renders in `docs/diagrams/{category}/`. Create or update diagrams via `/d2-diagram` when D-records are added or modified.
- Discussion rounds: numbered sequentially, archived to `docs/discussions/` when complete
- Briefings: one per agent, updated after decision-producing rounds
- Tickets: managed via `db/connectors/ticket` CLI or `/ticket` skill
### Commit conventions
Use conventional commits with project-specific scopes:
**Use `tea` (Gitea CLI), not `gh` (GitHub CLI).** The remote is Gitea at `git.schweitz.internal`.
Always provide all required flags to ensure non-interactive execution:
```bash
tea pr create \
--repo jpmschweitzer/settled-reach \
--login schweitz \
--title "feat(scope): short description" \
--description "PR body here" \
--base main \
--head branch-name
```
### Large content pushes (team pattern)
When producing many files (wiki pages, content batches, bulk docs):
1. **Lore librarian** agent (read-only): ingests all source material, answers focused context queries from writers, tracks cross-file consistency
2. **Multiple writer** agents (parallel, by domain): each gets a task slice, writes directly to disk using the Write tool — one file at a time, write often, no text accumulation
@test -n "$(GODOT)"||{echo"Godot not found. Run 'make setup' first.";exit 1;}
$(GODOT) --headless --path client -s res://addons/gdUnit4/bin/GdUnitCmdTool.gd --ignoreHeadlessMode -a res://tests/
tests/run-godot
test-ipc-fixtures:
tests/run-ipc-fixtures
test-ipc-protocol:
tests/run-ipc-protocol
test-ipc-integration:
tests/run-ipc-integration
test-ipc-benchmark:
tests/run-ipc-benchmark
# --- Lint ---
@@ -257,16 +290,16 @@ db-install:
# --- Decisions ---
decisions-sync:
@db/connectors/decisions-sync
@tooling/db/decisions-sync
decisions-coverage:
@db/connectors/sqlite-query "SELECT d.domain, COUNT(DISTINCT d.id) as decisions, COUNT(DISTINCT t.decision_ref) as with_tickets FROM decisions d LEFT JOIN tickets t ON d.id = t.decision_ref WHERE d.status='active' AND d.type='confirmed' GROUP BY d.domain"
@tooling/db/sqlite-query "SELECT d.domain, COUNT(DISTINCT d.id) as decisions, COUNT(DISTINCT t.decision_ref) as with_tickets FROM decisions d LEFT JOIN tickets t ON d.id = t.decision_ref WHERE d.status='active' AND d.type='confirmed' GROUP BY d.domain"
decisions-active:
@db/connectors/sqlite-query "SELECT id, domain, title FROM decisions WHERE status='active' AND type='confirmed' ORDER BY domain, id"
@tooling/db/sqlite-query "SELECT id, domain, title FROM decisions WHERE status='active' AND type='confirmed' ORDER BY domain, id"
decisions-orphan:
@db/connectors/sqlite-query "SELECT id, title FROM decisions WHERE type='confirmed' AND status='active' AND id NOT IN (SELECT DISTINCT decision_ref FROM tickets WHERE decision_ref IS NOT NULL)"
@tooling/db/sqlite-query "SELECT id, title FROM decisions WHERE type='confirmed' AND status='active' AND id NOT IN (SELECT DISTINCT decision_ref FROM tickets WHERE decision_ref IS NOT NULL)"
# --- Content Validation ---
@@ -285,6 +318,26 @@ checklist-generate:
perf-baseline:
@tooling/perf-baseline
# --- Schedule debug (#346) ---
debug-schedule:
@echo "Dumping bevy_ecs schedule graph..."
@cd server && cargo run --bin settled-reach-server -- --dump-schedule
# --- Visual test harness ---
screenshot:
@tests/run-visual --screenshot $(SCENARIO)
visual-movie:
@tests/run-visual --movie $(FLOW)
test-visual:
@tests/run-visual
visual-update:
@tests/run-visual --update
content-ron:
cd tooling/content-converter && cargo build --release
# Back to top level — shouldn't happen in valid checklist YAML
in_conditions=false
ifnotcurrent_item.is_empty():
conditions.append(current_item)
current_item={}
varcolon:=content.find(":")
ifcolon>=0:
varkey:=content.substr(0,colon).strip_edges()
varval_str:=content.substr(colon+1).strip_edges()
result[key]=_parse_value(val_str)
# Flush last item
ifnotcurrent_item.is_empty():
conditions.append(current_item)
ifnotconditions.is_empty():
result["conditions"]=conditions
returnresult
staticfunc_parse_value(val:String)->Variant:
ifval.is_empty():
return""
# Strip inline comments (not inside quotes)
ifnotval.begins_with("\""):
varcomment_pos:=val.find(" #")
ifcomment_pos>=0:
val=val.substr(0,comment_pos).strip_edges()
# Quoted string
ifval.begins_with("\""):
varend_quote:=val.find("\"",1)
ifend_quote>0:
returnval.substr(1,end_quote-1)
returnval.substr(1)
# Boolean
ifval=="true":
returntrue
ifval=="false":
returnfalse
# Float (contains decimal point)
ifval.contains(".")andval.is_valid_float():
returnval.to_float()
# Integer
ifval.is_valid_int():
returnval.to_int()
# Plain string
returnval
returnYamlParser.parse(text)
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.