diff --git a/docs/superpowers/specs/2026-06-05-live-gui-state-sync-design.md b/docs/superpowers/specs/2026-06-05-live-gui-state-sync-design.md index d2f22ba7..5482329e 100644 --- a/docs/superpowers/specs/2026-06-05-live-gui-state-sync-design.md +++ b/docs/superpowers/specs/2026-06-05-live-gui-state-sync-design.md @@ -16,7 +16,35 @@ 3. **`test_undo_redo_lifecycle::test_undo_redo_lifecycle`** (NEW regression) — sets `ai_input="Initial Input"`, modifies to `"Modified Input"`, clicks `btn_undo`. Expects `ai_input="Initial Input"`. **Fails: snapshot reads `app.ui_ai_input` but `set_value` writes to `controller.ui_ai_input`.** -### Audit of duplicated fields +### Discovery (2026-06-05 execution): State sync is NOT the root cause + +Initial hypothesis: App and Controller maintain parallel state for settable fields. Verified during execution: **the App class already has `__getattr__` (line 478) and `__setattr__` (line 483) that auto-delegate to the controller.** Writes go through `__setattr__` → controller. Reads go through `__getattr__` → controller. The state is correctly synced at the descriptor level. The original spec assumption was wrong. + +## REAL root cause: `_capture_workspace_profile` is not a class method + +During execution, AST analysis of `src/gui_2.py` reveals the actual bug: + +``` +$ uv run python -c "import ast; ..." +App methods (count): 59 + WORKSPACE METHOD: _apply_workspace_profile # ← exists + # ← _capture_workspace_profile MISSING +``` + +`_capture_workspace_profile` is defined at line 607 of `src/gui_2.py` with 2-space indent (intended as a class method), but the AST walks it as **nested inside `_apply_snapshot`** (line 572). The body of `_apply_snapshot` (lines 573-635) absorbs the next `def` as a nested function. + +This means when the live_gui calls `self._app._capture_workspace_profile(name)`, Python's normal class lookup fails to find `_capture_workspace_profile` on the App class. `__getattr__('_capture_workspace_profile')` is triggered, which delegates to `self.controller._capture_workspace_profile`. The controller does NOT have this method. `AttributeError` is raised. The save callback fails silently. The test's `load_workspace_profile` finds no profile to load (because save failed). The test fails. + +### Why AST sees it as nested + +The likely cause is the user's recent cleanup commit `873edf42` ("began to go through the files and organize imports and gui_2.py's new context defs") which touched `src/gui_2.py:261` lines. The cleanup reorganized method placement. Either: +- Indentation was accidentally off by 1 space on some lines. +- A blank line or comment that closed a function body was removed. +- Method definitions were moved but their indentation wasn't updated. + +Specific to the bug: `_apply_snapshot` has a `try:` (line 574) without an `except` (only a `finally:` at line 604). This is valid Python syntax, but the indentation of subsequent lines may have been off, causing the AST to consume the next `def` into the `try` block. + +## Audit of duplicated fields (retained from original spec, for context) Static analysis of the 71 settable fields in `AppController._settable_fields` vs the 12 `panel_states` keys captured in `App._capture_workspace_profile`, plus the `show_windows` dict and snapshot fields: