--- title: "Sprint 23 — Client Briefing" description: "Dialogue speaker colors fix, test failures fix, debug console UI, wall LOS rendering" type: sprint status: archived sprint: 23 team: "client" --- # Sprint 23: Terrain — Client Tasks **Goal:** Build the walkable Sova world under the authored content, complete the storyteller engagement layer, and add the debug console — clearing the path to v0.1 integration in Sprint 24. **Branch:** `client` **Agents:** Stig (UI/rendering), Hoshe (QA) --- ## New Tickets | # | Title | Blocked by | |---|-------|------------| | #573 | Dialogue speaker colors are position-based instead of speaker-bound | — | | #574 | Pre-existing test failures in test_entity_renderer (test_rendering.gd) | — | | #581 | Debug console client: tilde console UI, settings toggle, command dispatch | #580 (server) | | #585 | Walls at LOS boundary: client — render margin tiles correctly through fog | #584 (server) | Use `tooling/db/ticket show ` for full descriptions. --- ## Key Decisions - `decisions/architecture.md` — D-020 (ObserverSnapshot is the only data crossing IPC boundary), D-088 (3-state pause — Normal/Overlay/Paused) - `decisions/content.md` — D-033 (entity color = relationship to player; player color set at character creation), D-076 (dialogue box max-width 1200px) - `decisions/perception.md` — D-059 (fog system — 3-state: visible, explored, never-seen) --- ## Notes ### #573 — Dialogue speaker colors **What exists:** `client/ui/dialogue_box.gd` renders the dialogue box (D-028, D-076). Speaker colors are currently assigned by position (left speaker = color A, right speaker = color B), which means all left-side speakers share one color and all right-side speakers share another regardless of identity. **What to deliver:** Bind speaker color to entity identity, not screen position. The `ObserverSnapshot` carries entity IDs on dialogue lines (check `client/scripts/protocol/protocol.gd` `_decode_nearby_interaction` for the entity_id field on dialogue events). Maintain a `Dict[entity_id -> Color]` in `dialogue_box.gd`. On first encounter with an entity ID, assign a color from a palette and store it. Subsequent lines from the same entity reuse the stored color. The palette should be distinct from D-033 relationship colors (those are world-layer entity colors; dialogue colors are UI-layer only). **Non-obvious gotcha:** The player character is always one speaker. Assign the player a fixed color (e.g. the character's D-033 color, or a designated white/near-white). NPCs get assigned from the palette on first appearance in the conversation. ### #574 — Entity renderer test failures **What exists:** `client/tests/test_rendering.gd` contains `test_entity_renderer_*` tests that fail on clean main (5aea6e2). Affected: positions_centered, player_color_differs_from_npc, player_uses_d033_color, npc_uses_unknown_teal, object_uses_grey, facing_indicator_rotation_accuracy, regression_345_entity_position_set_from_entity_id_entity. **What to deliver:** Fix the failing tests. `client/scripts/rendering/entity_renderer.gd` likely changed without the tests being updated. Read the renderer to understand the current implementation, then update tests to match (or fix the renderer if it regressed from D-033 spec). Do not change the passing visual golden tests — only fix the unit tests in `test_rendering.gd`. Run `make test-client` to verify. **Gotcha:** D-033 specifies entity color = relationship to player. If entity_renderer.gd was updated correctly but tests use stale expected values, update the test assertions. If entity_renderer.gd was updated incorrectly and broke D-033 compliance, fix the renderer. ### #581 — Debug console client **What exists:** `client/ui/settings_dialog.gd` — existing settings panel with 5-bus audio volume sliders. `client/ui/debug_overlay.gd` — existing debug overlay tied to `OS.is_debug_build()` and a `debug_overlay` input action. `client/scripts/main.gd` — input routing. `client/scripts/protocol/protocol.gd` — `encode_player_input(tick, action_name, action_data)` and `decode_snapshot()`. **What to deliver:** 1. `client/ui/debug_console.gd` + `debug_console.tscn` — semi-transparent panel (40% screen height, anchored bottom). Input line at bottom, scrollable output log above (50-line buffer). Tilde key (`KEY_QUOTELEFT`) toggles open/closed. When open, swallows all keyboard input except tilde (no movement commands leak). 2. Settings integration — add a "Debug Console" checkbox to `settings_dialog.gd`. Persisted in `user://settings.cfg` alongside audio volumes. Default: enabled. When disabled, tilde key is inert. 3. Command parsing and dispatch — parse input as ` [args...]`. Map to `DebugCommandKind` variants. Serialize via `Protocol.encode_player_input('debug_command', { kind: ..., args: ... })`. Commands: `ticks `, `contaminate`, `tp [z]`, `tp `, `activate`, `triangle `, `npc `, `triangles`, `pop`, `status`, `help`. 4. Response display — read `debug_response` from the decoded snapshot dict (new optional field from server #580). Format and append to output log. Complex payloads (NPC state, triangle list) displayed as formatted key-value blocks. 5. Protocol extension — update `protocol.gd` to encode `debug_command` action and decode `debug_response` from snapshot. Bump `Protocol.PROTOCOL_VERSION` to 18 to match server. **Coordination required:** Stig must coordinate with Dudley on the PROTOCOL_VERSION bump (#580 server) before either PR is merged. Client and server PRs must land together or within the same merge window — a version mismatch will crash the connection. **Blocked by:** #580 (server must define `DebugCommandKind` wire format before client serialization is finalized). ### #585 — LOS boundary wall rendering **What exists:** `client/scripts/rendering/tile_renderer.gd` — `update_tiles()` processes `VisibleTile` entries from the snapshot. The tile accumulation fix (removed `clear()` from `update_tiles()`) means explored tiles stay rendered. `client/scripts/autoloads/fog_state.gd` — manages exploration state per tile. **What to deliver:** Handle the new `VisibilitySector::BoundaryWall` tiles from server #584. In `update_tiles()`, detect boundary wall sector tiles and: - Render them to the TileMapLayer as wall tiles (so fog has content to composite over) - Do NOT record them as explored in `fog_state.gd` — they are "seen right now" only, not explored - Do NOT update the fog exploration texture for these tiles The visual result: walls at the LOS edge are distinct from fog (they render as wall tiles) but disappear from the map when not in the current LOS cone (they don't leave a memory trace). **Blocked by:** #584 (server must send the boundary tiles before client can render them). --- ## Dependency Chain ``` #573 (speaker color fix) — standalone #574 (renderer test fix) — standalone #580 (server debug) → #581 (debug console) #584 (server wall margin) → #585 (client wall margin) ``` #573 and #574 are fully independent — start immediately. #581 is blocked on server work landing first. #585 is blocked on server #584 landing first. --- ## PR Workflow ```bash tea pr create --repo jpmschweitzer/settled-reach --login schweitz \ --title "fix(client): bind dialogue speaker colors to entity identity" \ --description "body" --base main --head client ``` --- ## Sprint Completion (Client Criteria) 1. Dialogue conversations show consistent per-speaker colors regardless of screen position. 2. All `test_entity_renderer_*` tests pass in `test_rendering.gd`. 3. Tilde key opens debug console in-game; `status` command returns contamination state; `triangles` lists all active triangles. 4. Debug console toggle visible in Settings menu; persists across restarts. 5. Walls at LOS edge render as distinct tile content rather than blending into fog. 6. `make test-client` green on client branch.