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 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>
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>
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>
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>
- 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>
- 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>
- 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>
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>
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>
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>
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>
- 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>
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>
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 .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>
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>