Commit Graph
104 Commits
Author SHA1 Message Date
jpmschweitzerandClaude Opus 4.6 31ae462cb2 test(simulation): update protocol fixtures and golden for Sprint 18
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>
2026-02-25 09:50:48 +01:00
jpmschweitzerandClaude Opus 4.6 821d716509 fix(client): address PR #62 review suggestions — polish pass
- 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>
2026-02-24 11:30:24 +01:00
jpmschweitzerandClaude Opus 4.6 d8eb256dad test(client): align sprint 17 tests with implementation (#263, #537)
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>
2026-02-24 11:22:39 +01:00
jpmschweitzerandClaude Opus 4.6 6c3a30a4bc feat(ui): add relationship color accent to E-Talk overlay (#537)
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>
2026-02-24 11:16:33 +01:00
jpmschweitzerandClaude Opus 4.6 66a435e201 feat(ui): add diegetic time display on insert HUD (#263)
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>
2026-02-24 11:16:23 +01:00
jpmschweitzerandClaude Opus 4.6 0ebd417a1f test(client): add direction mapping tests for octant and entity facing (#540 review)
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>
2026-02-23 21:06:35 +01:00
jpmschweitzerandClaude Opus 4.6 a0260176b4 feat(client): integrate D-019 angle sprites into entity renderer (#540)
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>
2026-02-23 21:01:30 +01:00
jpmschweitzerandClaude Opus 4.6 ebc973b558 refactor(client): optimize zone_id extraction from O(N) to O(1) lookup (#543)
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>
2026-02-23 21:01:22 +01:00
jpmschweitzerandClaude Opus 4.6 2189a9addd fix(simulation): address PR #56 review — pipeline extraction, ActiveDialogue, range check
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>
2026-02-23 20:20:00 +01:00
jpmschweitzer 4d7d77dc3a merge: resolve CHANGELOG.md conflict from server branch 2026-02-21 15:13:29 +01:00
jpmschweitzerandClaude Opus 4.6 062ae88803 fix(client): revert DIALOGUE_MAX_WIDTH to 1200px (intentional override of D-076)
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>
2026-02-21 14:44:34 +01:00
jpmschweitzerandClaude Opus 4.6 78c8bb97de fix(client): address PR #54 round 2 — stale comments, D-076 test, GROUND_FLOOR const
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>
2026-02-21 14:42:25 +01:00
jpmschweitzerandClaude Opus 4.6 46cf744e6a data(client): update msgpack fixtures and golden files for protocol v13
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>
2026-02-21 14:40:18 +01:00
jpmschweitzerandClaude Opus 4.6 c347f28cbd fix(client): address PR #54 review — 7 items across Hoshe and Tyre
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>
2026-02-21 14:20:27 +01:00
jpmschweitzerandClaude Opus 4.6 e616af6eca test(client): sprint 15 validation tests — camera, UI framework, entities
Add test_smooth_camera_sprint15.gd (11 tests): lerp convergence,
teleport snap, D-015 fixed-north, constant range validation.
Add test_ui_framework_sprint15.gd (20 tests): D-049 z-layer hierarchy,
OQ-07 insert_active, #241 follow stub, Sprint 14 regression checks.
Update test_camera_anchor.gd and test_client_p3.gd for ENTITY_OFFSET_X/Y
split and manual lerp camera behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 14:10:06 +01:00
jpmschweitzerandClaude Opus 4.6 aa97ef988a chore(client): track Godot-generated uid and import files
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>
2026-02-21 13:43:43 +01:00
jpmschweitzerandClaude Opus 4.6 038f97f07b data(client): update msgpack fixtures for protocol v12
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>
2026-02-21 13:43:24 +01:00
jpmschweitzerandClaude Sonnet 4.6 677ca9b59d fix(ui): address PR #49 review — 6 warnings + 2 suggestions (#122)
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>
2026-02-20 19:06:26 +01:00
jpmschweitzerandClaude Opus 4.6 c71ba8ebb3 test(ui): GameState integration + D-049 compliance tests for monologue display (#122)
7 tests: snapshot round-trip, null/stale clearing, non-dict rejection,
duration/id preservation, canvas layer constant. before_test/after_test
lifecycle hooks prevent state bleed between test cases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 18:43:41 +01:00
jpmschweitzerandClaude Sonnet 4.6 b49d78ef6a fix(ui): guard empty text in show_monologue — no ghost slots or queue entries (#122)
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>
2026-02-20 18:41:22 +01:00
jpmschweitzerandClaude Sonnet 4.6 1765e2922f refactor(ui): monologue display — multi-line architecture per Tyre review (#122)
Rewrites the monologue display system per Tyre architecture review (Sprint 14):

Rendering:
- Up to 3 simultaneous visible lines (VBoxContainer, dynamic node creation)
- Lines created programmatically as MarginContainer > RichTextLabel per slot
- Percentage-based anchors: 5% left, 75–98% vertical (25% area from bottom), 50% max width
- Z-layer 7 in UILayer (CanvasLayer 20, D-049)

Queue:
- 5-entry priority queue; highest priority drains first
- On overflow: incoming line replaces lowest-priority queued entry if it outranks it
- Lower/equal priority incoming lines silently dropped when queue full

API:
  show_monologue(text, duration, priority=2, is_urgent=false)
- Replaces old (text, duration, character_type) signature
- main.gd passes priority and is_urgent from MonologueEvent fields
- Confrontation monologue: priority=3, is_urgent=true (D-063)

Colour:
- Reads GameState.lattice_profile at render time (D-032)
- lattice_augmented (detective): standard #d0d4e0 / urgent #e0e8f8
- lattice_baseline (smuggler): standard #d8d0c4 / urgent #f0e4d4
- Fallback for unknown profiles; no crash

Stagger: 0.15s between consecutive fade-ins (spec §5.4)
Opacity: standard 0.85, urgent 1.0; bloom deferred

GameState: adds lattice_profile field, parsed from snapshot

Tests: 27 gdUnit4 test cases — queue order, priority drop, overflow, stagger,
no-overwrite (P0 #477), BBCode output, palette selection, slot lifecycle

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 18:39:49 +01:00
jpmschweitzerandClaude Sonnet 4.6 4365871846 feat(ui): monologue display — queue, character colours, italic BBCode (#122)
- Queue management: enqueue on mid-display arrival, drain in order, MAX_QUEUE_DEPTH=8 cap, no-overwrite contract (P0 #477)
- Character colours: detective=#c8e0ff (cool blue), smuggler=#f0c870 (warm amber), fallback to neutral insert text
- Typography: italic via BBCode [i] tags; font size 13px (smaller than dialogue)
- Positioning: bottom-left of viewport, 420×120px, 80px bottom margin above verb list
- main.gd: _get_active_character_type() reads player entity kind.data.character_type; passed to show_monologue() and _on_confrontation_monologue()
- gdUnit4 tests: queue order, depth cap, no-overwrite, BBCode output, colour mapping, fade timer integration

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 18:31:13 +01:00
jpmschweitzer bc1cfabb68 Merge remote-tracking branch 'origin/client' 2026-02-19 18:45:54 +01:00
jpmschweitzerandClaude Opus 4.6 8985340bdd fix(client): address PR #47 review — murmur deferral, zone extraction, 6 tests
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>
2026-02-19 18:37:23 +01:00
jpmschweitzerandClaude Opus 4.6 513682522f test(audio): Sprint 13 test suite + lambda capture fix (#528-#533)
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>
2026-02-19 18:19:32 +01:00
jpmschweitzerandClaude Opus 4.6 51abc3e3c1 feat(simulation): #523 add zone_id to ObserverSnapshot (D-077, protocol v11)
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>
2026-02-19 18:10:06 +01:00
jpmschweitzer 7874493d2a Merge remote-tracking branch 'origin/client' 2026-02-19 15:56:57 +01:00
jpmschweitzerandClaude Opus 4.6 f42c3209d8 chore(db): backup database after worktree merge
Regenerate msgpack fixtures for combined sound_events + rng_seed struct.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 15:37:28 +01:00
jpmschweitzerandClaude Opus 4.6 dfcafee3ee fix(client): address PR #43 review — walk key mismatch + 5 suggestions
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>
2026-02-19 15:37:20 +01:00
jpmschweitzerandClaude Opus 4.6 e1a1a9cfc2 fix(client): address PR review warnings — field guard + public API rename
- 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>
2026-02-19 15:03:10 +01:00
jpmschweitzerandClaude Opus 4.6 f337bb3ca8 fix(client): correct 5 bugs found in pre-PR review
- sound_indicator_renderer: draw_colored_polygon → draw_polygon (runtime crash)
- sound_indicator_renderer: append+dedup instead of clear — indicators now
  survive 3.5s instead of dying after one server tick
- dialogue_box: wire Constants.DIALOGUE_MAX_WIDTH (640px) instead of
  hardcoded 832px MAX_WIDTH_PX
- dialogue_box.tscn: update default offsets to ±320 (was ±416)
- decisions/perception.md: fix footer typo (1920px → 640px)
- tests updated for new append/dedup indicator behavior

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 14:59:50 +01:00
jpmschweitzerandClaude Sonnet 4.6 6a7dc915de feat(bridge): add rng_seed to ObserverSnapshot for deterministic replay (#527)
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>
2026-02-19 14:15:34 +01:00
jpmschweitzerandClaude Sonnet 4.6 719721cd4c fix(client): apply arch review corrections — 640px dialogue width, D-067 chime
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>
2026-02-19 13:35:27 +01:00
jpmschweitzerandClaude Sonnet 4.6 c6bd7c2db2 feat(client): Sprint 12 — renderer fix, sound pipeline, medium-range indicators
#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>
2026-02-19 13:33:05 +01:00
jpmschweitzerandClaude Opus 4.6 44d9941f04 fix(client): address PR #40 review — 13 suggestions
- Rename _insert to insert_state in main.gd (Hoshe #1)
- Add after_each() to test_bug_report_ring_buffer.gd for GameState
  cleanup on assertion failure (Hoshe #2)
- Add after_each() to test_insert_off_behavior.gd for stance/interaction
  restore on assertion failure (Hoshe #3)
- Fix assertion message: "unknown" → "unavailable" (Hoshe #4)
- Document memory ceiling of 60 JSON snapshots in ring buffer (Hoshe #5)
- Add precision warning for u64 rng_seed via JSON float (Hoshe #6)
- Promote _action_enum_to_wire to public action_enum_to_wire (Tyre #1)
- Add @warning_ignore for unused _tick parameter (Tyre #5)
- Document insert_active assumption for future no-insert characters (Tyre #4)
- Restructure OQ-07 decision amendments as bullet points (Tyre #7)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 12:19:41 +01:00
jpmschweitzerandClaude Opus 4.6 2d9bc33760 test(client): add tests for ring buffer and insert-off behavior (#507, #522)
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>
2026-02-19 12:05:47 +01:00
jpmschweitzerandClaude Opus 4.6 931399f248 feat(client): resolve OQ-07 — insert-off suppresses verb labels (#522)
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>
2026-02-19 12:05:36 +01:00
jpmschweitzerandClaude Opus 4.6 7640a9ab87 fix(client): address PR #38 review — 6 warnings + 4 suggestions
Hoshe:
- COLOR_FADE_DURATION 0.7 → 0.5 to match D-033 spec ("0.5s fade")
- Gauntlet guard tests now exercise InputMapper._unhandled_input()
  with synthesized InputEventKey instead of asserting a bool
- Buffer clearing tests use SimBridge pipeline instead of manual nulls
- Add mid-transition re-trigger test (rapid relationship changes)
- Add relationship field to test snapshot NPC

Tyre:
- Add _teleport_in_progress flag to defer smoothing re-enable by one
  frame after teleport (prevents same-_process() re-enable race)
- Add _test_gauntlet_mode to SimBridge test snapshot
- Extract TELEPORT_DISTANCE_THRESHOLD constant, mirror in tests
- Add comments: flash preemption, modulate/color independence
- Rename "hub teleport" → "Gauntlet dev teleport" in code comments
  to clarify this is not production fast-travel

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 09:06:42 +01:00
jpmschweitzerandClaude Opus 4.6 58e592fd5e feat(client): confrontation D-033 color shift (#521, D-063)
Entity renderer now tracks relationship per entity and tweens D-033
tint color over 0.7s when relationship changes (e.g. on confrontation
delivery). Uses manual lerp in _process() for testability instead of
SceneTree tweens. Cursor hover tint cascades automatically via
Constants.color_for_entity_kind().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 08:46:12 +01:00
jpmschweitzerandClaude Opus 4.6 7274151671 feat(client): hub teleport UX — Home key, fade transition (#501)
Home key sends TeleportToHub in Gauntlet mode. Camera snaps to hub
spawn with 0.3s fade-from-black. Clears dialogue/monologue buffers
on teleport. Teleport detection uses distance threshold (>5 tiles)
so future teleport types get the transition for free.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 08:46:02 +01:00
jpmschweitzer fd2101368e Merge remote-tracking branch 'origin/client'
# Conflicts:
#	CHANGELOG.md
2026-02-18 18:35:15 +01:00
jpmschweitzerandClaude Opus 4.6 503644beb1 fix(client): address PR #36 re-review — 7 items from Hoshe + Tyre
Warnings: facing indicator tests use Godot-normalized rotation range
(-PI, PI] instead of raw addition (SW/W/NW in test_rendering,
West in test_client_p3). Suggestions: cache font in world_radial
_draw(), fix docstring on deactivate_insert() trigger, document
tile-coordinate system on _eval_player_near (D-066), add public
reset_facing_state() to InputMapper (D-030 testability).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 18:28:37 +01:00
jpmschweitzerandClaude Opus 4.6 919ef39cbd fix(client): address PR #36 review — 10 items from Hoshe + Tyre
Critical:
- deactivate_insert() now called when selecting non-Insert spoke,
  cancelling with no selection, or pressing Escape while insert is
  active. Fixes simulation staying paused permanently after Insert.

Warnings:
- Checklist conditions with empty id excluded from get_results() and
  get_total_count() — prevents impossible-to-complete checklists.
  Warns at load time when empty-id conditions are found.
- _content_base now checks res://content/ first (exported builds),
  falls back to ../content for editor/dev mode.
- 26 new tests for D-054 functions: _angle_to_octant (8 octants),
  _snap_to_octant_dir (9 cases incl. zero/tiny), _wasd_to_world_dir
  (8 facing/movement combos). New test file: test_input_mapper_facing.gd.

Suggestions:
- Cached get_theme_default_font() in checklist overlay _ready().
- Documented InputMapper → GameState coupling as intentional.
- Documented YAML parser # truncation limitation.
- _insert_active reset on Escape dismiss (Tyre #3).
- SimBridge test mode SetFacing reads action_data.facing instead of
  InputMapper global (Tyre #4).
- Removed dead _facing_to_rotation() from entity_renderer.gd (Tyre #5).
- Fixed 2 failing facing indicator tests to use InputMapper.facing_angle
  instead of GameState.player_facing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 13:09:38 +01:00
jpmschweitzerandClaude Opus 4.6 6c62e2228f test(simulation): sprint 10 — replay loading, content scaling, serialization v9, observer tests
#483: Replay loading in test-client — JSONL file loading, tick-scheduled
PlayerInput sending, 13 unit tests, 3 sample replay files.
#500: Content scaling test — baseline + extra NPC comparative, tick budget
assertion (D-026), determinism check across content packs.
#514: Serialization tests for protocol v9 — blocked_entities roundtrip,
backward compat (v5→v9, v8→v9), regenerated msgpack fixtures.
Observer perception tests for confrontation + walk-away mechanics.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 12:58:27 +01:00
jpmschweitzerandClaude Opus 4.6 eb1d89ea86 feat(client): room reset UX, insert pause wiring, auto-checklist (#502, #518, #503)
Room reset (#502): amber reset_plate tile type in TileRenderer, 0.15s
screen flash on room_reset monologue, 'Reset Room' verb via existing
nearby_interactions.

Insert pause (#518, D-058): explicit PauseSimulation on insert open,
ResumeSimulation on close. Replaces toggle-style pause with idempotent
pair per D-058.

Auto-checklist (#503): ChecklistEvaluator parses room YAML, evaluates
7 condition types against GameState with latching. ChecklistOverlay
renders progress in gauntlet mode only. 48 tests covering parser,
evaluation, latching, visibility, and integration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 12:53:35 +01:00
jpmschweitzerandClaude Opus 4.6 d627c2bc0a chore(client): add missing .uid and .import files from Godot 4.6
Generated by headless --import after audio merge. These are needed
for stable UID references across editor sessions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 11:51:41 +01:00
jpmschweitzerandClaude Opus 4.6 a292674342 feat(client): add 24 gauntlet + bug report tests (#495, #496)
Replace stub F12 tests with BugReportDialog integration tests (dialog
exists, activates on action, pause/unpause, wire guard, text render
with entities/monologue/dialogue, empty snapshot edge case). Add 16
GauntletHUD tests (format_time, visibility toggle, timer lifecycle,
room change reset, personal bests record/overwrite/preserve, null room,
timer paused when hidden, finalize, session attempts, snapshot
roundtrip). Anti-tedium assertions now falsifiable against real
GameState.room_id and gauntlet_mode properties.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 10:53:26 +01:00
jpmschweitzer bb94a6581c Merge remote-tracking branch 'origin/ci' 2026-02-18 10:24:13 +01:00
jpmschweitzerandClaude Opus 4.6 4f20a996aa fix(client): address PR #30 review — 9 items from Hoshe and Tyre
- Add SimBridge._last_snapshot = null to P3 before_test() (contamination risk)
- Clarify mono.is_visible is custom property, not CanvasItem builtin
- Camera smoothing test uses approximate equality instead of exact
- Propagate inner _encode_message errors in array/dict encoding
- Add explanatory comment on int_64 encoder branch
- Document unfalsifiable gauntlet guard as intentional future-proof
- Remove loose D-053 citation from LERP_SPEED pin
- Assert FogOverlay is sibling of FogGroup under World
- Add CANVAS_MODAL=30 (ModalLayer) assertion in P3-Z04

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 09:46:08 +01:00
jpmschweitzerandClaude Opus 4.6 3ccac5432b fix(ci): address PR #31 review — harden cross-encoder fixture pipeline
- Fail on encode errors instead of silently writing empty .msgpack files
- Fail test on missing/empty fixture dir instead of silent skip
- Add all missing action variants (MoveSouth, MoveEast, MoveWest,
  Unpause, ToggleStanceDown, WalkAway) to GDScript fixture generator
- Add GDScript fixture staleness check to make pre-pr
- Validate repo root detection before writing outside client/
- Add file.flush() before close in headless mode
- Document fixture failure recovery in DEVOPS.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 09:45:13 +01:00