Addresses Tyre's 9 architecture items from the sprint-36 client review.
- decisions/architecture.md (Tyre #1): D-192 now says "deprecate; removal
tracked in #868" instead of "remove". The branch does not remove the
version field or guard — that belongs in the coordinated server+client
PR. The decision text now matches the code on this branch.
- meta_stack.gd (#2): handle_escape() on a screen with
closable_by_escape=false now consumes the event unconditionally. Was
returning whatever on_escape() returned, which default-returned false
and leaked ESC into main.gd's implant/settings chain — opening the
settings dialog behind the loading screen.
- debug_console.gd (#4): drop the direct KEY_ESCAPE branch in
_unhandled_input. ESC now falls through to main.gd → MetaStack, which
finds the console on top of the stack and closes it via the normal
path. Other keys are still consumed so movement/action can't leak.
- main.gd (#6, #10): extract the ESC priority chain into
_handle_menu_key() so "MetaStack → implant → settings" is a named
thing. Add a comment near connect_to_sim explaining that
GameState.bookmark_catalog survives the Option A scene transition via
the autoload.
- main_menu.gd (#7): header comment documenting the double LoadingScreen
lifecycle — safe today because main_menu.tscn and main.tscn never
co-exist, noted for future promotion to autoload if that changes.
- meta_screen.gd (#8): apply captures_input symmetrically in open()/
close() — was set in open() only, so a screen changing the flag
between open+close kept the opened value forever.
- meta_screen.gd (#9): on_escape() docstring clarifies the tri-state
(consume-and-hold / consume-and-close / ignore) — and that
closable_by_escape=false is the screen-wide way to say
"consume-and-hold".
- bug_report_dialog.gd (#11): capture_cancelled now emits from
on_close() (covers any close path — ESC, MetaStack pop, programmatic
close) rather than only on_escape(). A new _completed flag
distinguishes completion from cancel so the two signals stay
mutually exclusive.
Relocates main_menu, character_creation, settings_dialog, debug_console,
bug_report_dialog, loading_screen from flat client/ui/ into structured
client/ui/meta/screens/<name>/. All six now extend MetaScreen instead
of Control; the base handles open/close lifecycle, visibility,
captures_input, and — for overlays — the sim-pause contract.
Screen policies set per Tyre's proposal:
- settings_dialog: pauses_sim=false, PUSHES onto MetaStack
- debug_console: pauses_sim=true, PUSHES (D-088 routing via base)
- bug_report_dialog: pauses_sim=true, PUSHES
- loading_screen: closable_by_escape=false, PUSHES
- main_menu, character_creation: scene-roots, extend MetaScreen for
the lifecycle contract only, do NOT push onto the stack
character_creation stays at its current surface (tabs, descriptor,
creation_confirmed signal unchanged). Tab consolidation and
CharacterProfile migration happen in Workstreams 5 and 6.
Knock-on changes:
- main.tscn ModalLayer CanvasLayer renamed to MetaLayer; main.gd
@onready refs updated; constants.gd comment updated; test_client_p3
and test_ui_framework_sprint15 assertions updated; test_monologue_display
and .tscn header comments updated.
- OPEN_MENU handler now pushes settings_dialog onto MetaStack before
calling open(). Full ESC priority chain lands in Workstream 4.
- atlas_app.gd: _unhandled_key_input signature widened from
InputEventKey to InputEvent with an is-check, per Godot 4 API. Pre-
existing narrowing was silently tolerated until main.tscn started
fully instantiating under the new pattern.
- test_client_p3: entity_renderer type annotations corrected from
ColorRect to Sprite2D (stale since a prior refactor); facing
indicator rotation assertion switched to angle_difference() for
modular-safe comparison.
Verification:
- gdlint client/scripts/ client/ui/ — zero problems
- godot --headless --path client --quit — no SCRIPT ERROR
- test_client_p3: 24/24 pass
- test_ui_framework_sprint15: 54/54 pass
- test_implant_nav_stack: 52/52 pass
- test_implant_registry: 42/42 pass
- test_implant_app_lifecycle: 36/36 pass
Workstream 1 foundation (84105916) remains unchanged. Workstreams 3-8
follow: protocol layer, Option A sequencing, 3-tab restructure,
Bookmark tab, location picker, Skills stub.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>