Private
Public Access
feat(gui_2): add 3 drain-plane render functions (Phase 2, tasks 2.1-2.3)
TIER-2 READ conductor/code_styleguides/error_handling.md end-to-end before Phase 2. Adds the drain plane that consumes the 8 controller error attributes (the data plane added by sub-track 3 Phase 6). Module-level functions in src/gui_2.py (lines 7293-7410): - _drain_normalize_errors (helper, lines 7295-7326): duck-typed normalizer for 3 error-container shapes (Optional[ErrorInfo], List[Tuple[str, ErrorInfo]], Dict[str, ErrorInfo]) - render_controller_error_modal (lines 7328-7368): FR-DP-1 Pattern 2 drain point; reads all 8 controller attrs, opens per-attr popups - _render_worker_error_indicator (lines 7370-7385): FR-DP-2 status-bar widget showing worker error count, clickable - _render_last_request_errors_modal (lines 7387-7409): FR-DP-3 per-request error modal opened after AI request completion App class delegation wrappers (lines 1138-1148): - App._render_controller_error_modal -> module-level - App._render_worker_error_indicator -> module-level - App._render_last_request_errors_modal -> module-level Per UI Delegation Pattern: App class has thin wrappers; logic at module level for hot-reload support. 1-space indentation, CRLF. Audit: no new violations introduced (gui_2.py still 25 V + 13 S + 2 RETHROW + 2 UNCLEAR + 12 COMPLIANT = 54). Tests: 4/4 pass.
This commit is contained in:
@@ -116,4 +116,88 @@ def test_phase_1_audit_has_42_migration_target_sites():
|
||||
f"expected {EXPECTED_SITE_COUNT}. Categories seen: "
|
||||
f"{sorted({f.get('category') for f in migration_sites})}. "
|
||||
f"This must match the 42 sites declared in PHASE1_SITE_INVENTORY.md."
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_phase_2_invariant_drain_plane_render_functions_exist():
|
||||
"""
|
||||
Verify the 3 new module-level render functions exist in src/gui_2.py:
|
||||
- render_controller_error_modal
|
||||
- _render_worker_error_indicator
|
||||
- _render_last_request_errors_modal
|
||||
|
||||
These are the drain-plane functions added in Phase 2 of the
|
||||
result_migration_gui_2_20260619 track. They read the 8 controller
|
||||
error attributes (added by sub-track 3 Phase 6) and surface them
|
||||
to the user via ImGui popups and indicators.
|
||||
|
||||
The test imports src.gui_2 and inspects the module for the function
|
||||
names. A failure here means the drain-plane wiring is incomplete.
|
||||
"""
|
||||
import inspect
|
||||
import src.gui_2 as gui2_mod
|
||||
assert hasattr(gui2_mod, "render_controller_error_modal"), (
|
||||
"src/gui_2.py is missing the module-level function "
|
||||
"'render_controller_error_modal'. This is the FR-DP-1 drain plane "
|
||||
"function; it must be added per the result_migration_gui_2_20260619 "
|
||||
"Phase 2 spec."
|
||||
)
|
||||
assert hasattr(gui2_mod, "_render_worker_error_indicator"), (
|
||||
"src/gui_2.py is missing the module-level function "
|
||||
"'_render_worker_error_indicator'. This is the FR-DP-2 drain plane "
|
||||
"function; it must be added per the result_migration_gui_2_20260619 "
|
||||
"Phase 2 spec."
|
||||
)
|
||||
assert hasattr(gui2_mod, "_render_last_request_errors_modal"), (
|
||||
"src/gui_2.py is missing the module-level function "
|
||||
"'_render_last_request_errors_modal'. This is the FR-DP-3 drain plane "
|
||||
"function; it must be added per the result_migration_gui_2_20260619 "
|
||||
"Phase 2 spec."
|
||||
)
|
||||
assert callable(getattr(gui2_mod, "render_controller_error_modal")), (
|
||||
"render_controller_error_modal exists but is not callable."
|
||||
)
|
||||
assert callable(getattr(gui2_mod, "_render_worker_error_indicator")), (
|
||||
"_render_worker_error_indicator exists but is not callable."
|
||||
)
|
||||
assert callable(getattr(gui2_mod, "_render_last_request_errors_modal")), (
|
||||
"_render_last_request_errors_modal exists but is not callable."
|
||||
)
|
||||
|
||||
|
||||
def test_phase_2_invariant_drain_plane_app_delegations_exist():
|
||||
"""
|
||||
Verify the 3 new App class delegation methods exist in src/gui_2.py:
|
||||
- App._render_controller_error_modal
|
||||
- App._render_worker_error_indicator
|
||||
- App._render_last_request_errors_modal
|
||||
|
||||
Per conductor/product-guidelines.md §"UI Delegation for Hot-Reload",
|
||||
the App class must contain only thin delegation wrappers; the actual
|
||||
logic lives in module-level functions. This test locks the
|
||||
delegation contract for Phase 2.
|
||||
|
||||
The test imports src.gui_2, gets the App class via the module
|
||||
(lazily - via the _LazyModule path or directly), and checks for
|
||||
the methods.
|
||||
"""
|
||||
import src.gui_2 as gui2_mod
|
||||
app_cls = getattr(gui2_mod, "App", None)
|
||||
assert app_cls is not None, (
|
||||
"src.gui_2 has no 'App' class attribute. Cannot verify delegations."
|
||||
)
|
||||
for method_name in (
|
||||
"_render_controller_error_modal",
|
||||
"_render_worker_error_indicator",
|
||||
"_render_last_request_errors_modal",
|
||||
):
|
||||
assert hasattr(app_cls, method_name), (
|
||||
f"App class is missing delegation method '{method_name}'. "
|
||||
f"The drain plane requires the App class to delegate to the "
|
||||
f"module-level render functions so the UI delegation pattern "
|
||||
f"supports hot-reload."
|
||||
)
|
||||
method = getattr(app_cls, method_name)
|
||||
assert callable(method), (
|
||||
f"App.{method_name} exists but is not callable."
|
||||
)
|
||||
Reference in New Issue
Block a user