GauntletHUD in UILayer shows TIMER: MM:SS (PB: MM:SS). Timer starts on
room entry, resets on room change, records personal bests to
user://gauntlet-stats.json. Session summary printed on disconnect.
Hidden in non-gauntlet mode (anti-tedium guard).
Adds room_id and gauntlet_mode fields to GameState, parsed from
ObserverSnapshot. Main.gd wires update_from_state() and finalize().
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
F12 pauses simulation, shows modal LineEdit prompt, saves three files
to user://bug-reports/gauntlet-t{tick}-{timestamp}/: snapshot.json
(full ObserverSnapshot), render.txt (simplified client-side text
render), description.txt (tester notes + tick/room/stance metadata).
Esc cancels without saving. Double-activation guard prevents stacking.
BUG_REPORT action added to InputMapper with wire guard in SimBridge
(client-only, never sent to server). Dialog on ModalLayer (CL 30).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Cast Variant to String via str() before passing to _on_room_change
- Clear _current_room_id on null room transition (fixes re-entry skip)
- Add push_error for failed dir creation and file writes in _save_report
- Fix docstring: tests/gauntlet-stats.json → user://dev/gauntlet-stats.json
- Namespace stats path to user://dev/ to avoid save data collision
- Replace print() with push_warning in _save_report (codebase consistency)
- Downgrade client-only wire guard from push_warning to silent return
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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 9 client remaining deliverables: both blocked tickets now complete.
TIMER: MM:SS (PB: MM:SS). Timer starts on room entry, resets on room change, persists stats touser://gauntlet-stats.json. Session summary on disconnect. Hidden in non-gauntlet mode (anti-tedium guard).snapshot.json+render.txt+description.txttouser://bug-reports/gauntlet-t{tick}-{timestamp}/. Esc cancels. Double-activation guard.Tickets
Test plan
make test-clientpasses headless (all new + existing tests green)🤖 Generated with Claude Code
F12 pauses simulation, shows modal LineEdit prompt, saves three files to user://bug-reports/gauntlet-t{tick}-{timestamp}/: snapshot.json (full ObserverSnapshot), render.txt (simplified client-side text render), description.txt (tester notes + tick/room/stance metadata). Esc cancels without saving. Double-activation guard prevents stacking. BUG_REPORT action added to InputMapper with wire guard in SimBridge (client-only, never sent to server). Dialog on ModalLayer (CL 30). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>Review: client -> main (PR #34, type: code)
Hoshe (Code Quality): REQUEST_CHANGES
Two features well-structured with 24 tests. Three warnings need fixing.
Variantpassed toString-typed parameter — runtime type error in strict mode_current_room_idnot cleared on null transition — re-entry to same room skips timer restarttests/gauntlet-stats.json, actual path isuser://gauntlet-stats.json_save_reportTyre (Architecture): APPROVE
Correct D-020 client-server separation, proper CanvasLayer 30 placement, BUG_REPORT correctly excluded from wire protocol.
user://root will collide with future save data — namespace touser://dev/print()inconsistent with codebase style (push_warning/push_error)_action_enum_to_wireemits false-alarmpush_warningfor known client-only actionsVerdict: CHANGES REQUESTED
Re-Review: client -> main (PR #34, type: code) — Post-Fix
Hoshe (Code Quality): APPROVE
All 3 warnings FIXED. Suggestions addressed.
str(new_room_id)cast_current_room_idnot cleared on nullpush_erroron all failure pathsTyre (Architecture): APPROVE
All 4 items FIXED. Surgical fixes, no regressions.
str()castuser://dev/print()stylepush_warning/push_errorpush_warningVerdict: APPROVED
Pull request closed