#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>
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>
- 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>
The PR delivers four coherent feature tickets with good structural decisions — D-069 dip values are correct, recognition chime architecture matches D-067, indicator z-ordering is correctly above fog. One warning-level issue requires a fix before merge.
#
File
Severity
Issue
1
audio_manager.gd ~line 149
warning
SOUND_EVENT_ASSETS key mismatch: maps "Footstep" / "FootstepWalk" etc. to "sfx_footstep_metal", but the actual audio file is sfx_footstep_metal_walk.ogg. Registry scan uses file_name.get_basename() producing key "sfx_footstep_metal_walk". Lookup in play_sound_event will always miss. The _run variant (sfx_footstep_metal_run) is correct. Fix: update walk-speed keys to "sfx_footstep_metal_walk".
2
sound_indicator_renderer.gd ~line 74
suggestion
get_camera_2d() null fallback uses magic Vector2(2.0, 2.0). Works correctly now but not sourced from any constant. Consider adding a Constants.CAMERA_DEFAULT_ZOOM or documenting the assumption.
3
audio_manager.gd ~line 149
suggestion
SOUND_EVENT_ASSETS maps all walk/careful/crouch stances to the same asset key. D-053 implies distinct sound profiles per stance. Worth tracking as a future audio differentiation ticket.
4
main.gd ~line 212
suggestion
_play_close_sound_events() clears GameState.close_sound_events = [] after consuming. Consistent with existing consume-once patterns (current_monologue, current_dialogue). A brief comment noting consume-once semantics would help future readers.
Tyre (Architecture): APPROVE
Well-structured sprint landing four tickets cleanly. Audio pipeline (D-068/D-069), close-range positional audio (#125), and medium-range indicators (#126) all conform to their respective decisions. D-076 dialogue width fix is correctly derived and properly documented as a decision amendment. Test coverage is substantive.
#
File
Severity
Issue
1
sound_indicator_renderer.gd:30-32
suggestion
Color constants COLOR_NEUTRAL, COLOR_VOICE, COLOR_DANGER duplicate values from Constants.INSERT_COLOR_TEXT, Constants.ENTITY_COLOR_POI, Constants.ENTITY_COLOR_HOSTILE. Source from Constants to prevent palette drift on future adjustments.
2
audio_manager.gd:139-150
suggestion
play_loop() casts stream.duplicate() as AudioStream — if duplicate fails, null propagates silently to a mute player. Add null guard: if loop_stream == null: return null.
3
main.gd:212
suggestion
GameState.close_sound_events = [] is consume-once by design. Consistent with existing pattern, but worth a comment noting D-009 multiplayer implications if a second observer reads the same state.
Deduplicated action items
WARNING — SOUND_EVENT_ASSETS walk-speed key mismatch: "sfx_footstep_metal" should be "sfx_footstep_metal_walk" to match the actual audio filename.
Suggestion — Indicator colors should reference Constants instead of duplicating hex literals.
Suggestion — play_loop() null guard on stream.duplicate().
Suggestion — Camera zoom fallback magic number.
Suggestion — Document consume-once semantics on close_sound_events.
Suggestion — Track stance-differentiated audio as future work.
## Review: client -> main (type: code) — PR #43
**Verdict: CHANGES REQUESTED**
---
### Hoshe (Code Quality): REQUEST_CHANGES
The PR delivers four coherent feature tickets with good structural decisions — D-069 dip values are correct, recognition chime architecture matches D-067, indicator z-ordering is correctly above fog. One warning-level issue requires a fix before merge.
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | `audio_manager.gd` ~line 149 | warning | `SOUND_EVENT_ASSETS` key mismatch: maps `"Footstep"` / `"FootstepWalk"` etc. to `"sfx_footstep_metal"`, but the actual audio file is `sfx_footstep_metal_walk.ogg`. Registry scan uses `file_name.get_basename()` producing key `"sfx_footstep_metal_walk"`. Lookup in `play_sound_event` will always miss. The `_run` variant (`sfx_footstep_metal_run`) is correct. Fix: update walk-speed keys to `"sfx_footstep_metal_walk"`. |
| 2 | `sound_indicator_renderer.gd` ~line 74 | suggestion | `get_camera_2d()` null fallback uses magic `Vector2(2.0, 2.0)`. Works correctly now but not sourced from any constant. Consider adding a `Constants.CAMERA_DEFAULT_ZOOM` or documenting the assumption. |
| 3 | `audio_manager.gd` ~line 149 | suggestion | `SOUND_EVENT_ASSETS` maps all walk/careful/crouch stances to the same asset key. D-053 implies distinct sound profiles per stance. Worth tracking as a future audio differentiation ticket. |
| 4 | `main.gd` ~line 212 | suggestion | `_play_close_sound_events()` clears `GameState.close_sound_events = []` after consuming. Consistent with existing consume-once patterns (`current_monologue`, `current_dialogue`). A brief comment noting consume-once semantics would help future readers. |
### Tyre (Architecture): APPROVE
Well-structured sprint landing four tickets cleanly. Audio pipeline (D-068/D-069), close-range positional audio (#125), and medium-range indicators (#126) all conform to their respective decisions. D-076 dialogue width fix is correctly derived and properly documented as a decision amendment. Test coverage is substantive.
| # | File | Severity | Issue |
|---|------|----------|-------|
| 1 | `sound_indicator_renderer.gd:30-32` | suggestion | Color constants `COLOR_NEUTRAL`, `COLOR_VOICE`, `COLOR_DANGER` duplicate values from `Constants.INSERT_COLOR_TEXT`, `Constants.ENTITY_COLOR_POI`, `Constants.ENTITY_COLOR_HOSTILE`. Source from Constants to prevent palette drift on future adjustments. |
| 2 | `audio_manager.gd:139-150` | suggestion | `play_loop()` casts `stream.duplicate() as AudioStream` — if duplicate fails, null propagates silently to a mute player. Add null guard: `if loop_stream == null: return null`. |
| 3 | `main.gd:212` | suggestion | `GameState.close_sound_events = []` is consume-once by design. Consistent with existing pattern, but worth a comment noting D-009 multiplayer implications if a second observer reads the same state. |
### Deduplicated action items
1. **WARNING** — `SOUND_EVENT_ASSETS` walk-speed key mismatch: `"sfx_footstep_metal"` should be `"sfx_footstep_metal_walk"` to match the actual audio filename.
2. Suggestion — Indicator colors should reference `Constants` instead of duplicating hex literals.
3. Suggestion — `play_loop()` null guard on `stream.duplicate()`.
4. Suggestion — Camera zoom fallback magic number.
5. Suggestion — Document consume-once semantics on `close_sound_events`.
6. Suggestion — Track stance-differentiated audio as future work.
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>
All 6 items from the previous review are verified fixed. No new critical or warning issues introduced.
Hoshe (Code Quality): APPROVE
All 6 items properly addressed. Walk key mismatch corrected, indicator colors sourced from Constants, play_loop() null guard added, camera zoom fallback uses Constants.CAMERA_DEFAULT_ZOOM, consume-once documented, stance audio gap flagged with D-053 inline comments.
#
File
Severity
Issue
1
audio_manager.gd SOUND_EVENT_ASSETS
suggestion
FootstepCareful and FootstepCrouch keys are defensive additions — confirm server actually emits these event type strings. If not, they are harmless dead entries.
Tyre (Architecture): APPROVE
Pipeline is D-018/D-038/D-067/D-068/D-069/D-076 compliant. 5-bus architecture correct, recognition chime fires at onset per D-067, dip profiles match spec mid-range values, consume-once pattern documented with D-009 rationale.
#
File
Severity
Issue
1
audio_manager.gd:180
suggestion
D-038 lists asset as sfx_footstep_metal.ogg but code maps to sfx_footstep_metal_walk. Confirm audio branch filename matches. Safe either way (no-op fallback).
2
constants.gd
suggestion
D-076 referenced in code but not yet recorded in decisions/ domain files. Process gap, not a code defect.
3
audio_manager.gd:26
suggestion
listening_focus tick gate is caller's responsibility per comment. No runtime enforcement — consider push_warning() in debug builds.
Previous review items — all verified
WARNING — Walk key mismatch: FIXED. "sfx_footstep_metal" → "sfx_footstep_metal_walk".
Suggestion — Indicator colors: FIXED. Now references Constants.INSERT_COLOR_TEXT, ENTITY_COLOR_POI, ENTITY_COLOR_HOSTILE.
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.
Summary
Sprint 12 client delivery — sound event pipeline, medium-range indicators, renderer fix, and dialogue width resolution.
id→entity_id) with 5 regression testsBug fixes found in pre-PR review
draw_colored_polygon→draw_polygon(runtime crash in indicator renderer)_indicators.clear()on every tick killed indicators after ~100ms — changed to append+dedup so 3.5s lifetime actually worksdialogue_box.gdhardcodedMAX_WIDTH_PX = 832instead of referencingConstants.DIALOGUE_MAX_WIDTHhas("entity_id")guard in_play_recognition_chimes()_color_for_typerenamed to publiccolor_for_type(testable API)Test coverage
test_audio_bus_routing.gd(293 lines): D-068 bus constants, D-069 dip profiles, D-067 chime, snapshot integrationtest_rendering.gd(+199 lines): #345 regression suite, #126 indicator data layer, GameState sound event partitioningtest_sound_indicators.gd(236 lines): D-018 color spec, range routing, direction geometry, indicator script APIReview
- 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>Review: client -> main (type: code) — PR #43
Verdict: CHANGES REQUESTED
Hoshe (Code Quality): REQUEST_CHANGES
The PR delivers four coherent feature tickets with good structural decisions — D-069 dip values are correct, recognition chime architecture matches D-067, indicator z-ordering is correctly above fog. One warning-level issue requires a fix before merge.
audio_manager.gd~line 149SOUND_EVENT_ASSETSkey mismatch: maps"Footstep"/"FootstepWalk"etc. to"sfx_footstep_metal", but the actual audio file issfx_footstep_metal_walk.ogg. Registry scan usesfile_name.get_basename()producing key"sfx_footstep_metal_walk". Lookup inplay_sound_eventwill always miss. The_runvariant (sfx_footstep_metal_run) is correct. Fix: update walk-speed keys to"sfx_footstep_metal_walk".sound_indicator_renderer.gd~line 74get_camera_2d()null fallback uses magicVector2(2.0, 2.0). Works correctly now but not sourced from any constant. Consider adding aConstants.CAMERA_DEFAULT_ZOOMor documenting the assumption.audio_manager.gd~line 149SOUND_EVENT_ASSETSmaps all walk/careful/crouch stances to the same asset key. D-053 implies distinct sound profiles per stance. Worth tracking as a future audio differentiation ticket.main.gd~line 212_play_close_sound_events()clearsGameState.close_sound_events = []after consuming. Consistent with existing consume-once patterns (current_monologue,current_dialogue). A brief comment noting consume-once semantics would help future readers.Tyre (Architecture): APPROVE
Well-structured sprint landing four tickets cleanly. Audio pipeline (D-068/D-069), close-range positional audio (#125), and medium-range indicators (#126) all conform to their respective decisions. D-076 dialogue width fix is correctly derived and properly documented as a decision amendment. Test coverage is substantive.
sound_indicator_renderer.gd:30-32COLOR_NEUTRAL,COLOR_VOICE,COLOR_DANGERduplicate values fromConstants.INSERT_COLOR_TEXT,Constants.ENTITY_COLOR_POI,Constants.ENTITY_COLOR_HOSTILE. Source from Constants to prevent palette drift on future adjustments.audio_manager.gd:139-150play_loop()castsstream.duplicate() as AudioStream— if duplicate fails, null propagates silently to a mute player. Add null guard:if loop_stream == null: return null.main.gd:212GameState.close_sound_events = []is consume-once by design. Consistent with existing pattern, but worth a comment noting D-009 multiplayer implications if a second observer reads the same state.Deduplicated action items
SOUND_EVENT_ASSETSwalk-speed key mismatch:"sfx_footstep_metal"should be"sfx_footstep_metal_walk"to match the actual audio filename.Constantsinstead of duplicating hex literals.play_loop()null guard onstream.duplicate().close_sound_events.Re-Review: client -> main (type: code) — PR #43
Verdict: APPROVED
All 6 items from the previous review are verified fixed. No new critical or warning issues introduced.
Hoshe (Code Quality): APPROVE
All 6 items properly addressed. Walk key mismatch corrected, indicator colors sourced from Constants, play_loop() null guard added, camera zoom fallback uses Constants.CAMERA_DEFAULT_ZOOM, consume-once documented, stance audio gap flagged with D-053 inline comments.
audio_manager.gdSOUND_EVENT_ASSETSFootstepCarefulandFootstepCrouchkeys are defensive additions — confirm server actually emits these event type strings. If not, they are harmless dead entries.Tyre (Architecture): APPROVE
Pipeline is D-018/D-038/D-067/D-068/D-069/D-076 compliant. 5-bus architecture correct, recognition chime fires at onset per D-067, dip profiles match spec mid-range values, consume-once pattern documented with D-009 rationale.
audio_manager.gd:180sfx_footstep_metal.oggbut code maps tosfx_footstep_metal_walk. Confirm audio branch filename matches. Safe either way (no-op fallback).constants.gddecisions/domain files. Process gap, not a code defect.audio_manager.gd:26listening_focustick gate is caller's responsibility per comment. No runtime enforcement — considerpush_warning()in debug builds.Previous review items — all verified
"sfx_footstep_metal"→"sfx_footstep_metal_walk".Constants.INSERT_COLOR_TEXT,ENTITY_COLOR_POI,ENTITY_COLOR_HOSTILE.nullifstream.duplicate()fails.Constants.CAMERA_DEFAULT_ZOOM._play_close_sound_events().Pull request closed