Skip to content

feat(m1): TUI load-on-mount state persistence from SaveExchange#21

Merged
SolshineCode merged 1 commit into
mainfrom
feat/m1-tui-load-on-mount
May 8, 2026
Merged

feat(m1): TUI load-on-mount state persistence from SaveExchange#21
SolshineCode merged 1 commit into
mainfrom
feat/m1-tui-load-on-mount

Conversation

@SolshineCode
Copy link
Copy Markdown
Owner

Summary

Closes the last M1 deliverable: "Close/reopen preserves all state."

Previously MainApp.on_mount called refresh_panels() but never loaded from the save exchange — every reopen started from scratch. Save-on-exit was already wired in action_quit.

Implementation (tui/app.py)

  • MainApp._load_from_save_exchange() — if bridge_loop.save_exchange exists and has a file, reads the payload and replaces:
    • self.session_state (TUI state)
    • self.bridge_loop.state (loop's state reference)
    • self.bridge_loop.hook_listener.state (so post-mount injections land on the loaded session)
  • Called at the top of on_mount() before refresh_panels()

Tests (+9 tests)

Pilot tests (test_app_pilot.py):

Test What it covers
test_app_loads_kingdom_name_from_save_on_mount Kingdom name survives close/reopen
test_app_restores_session_count_and_attributes_from_save Sessions, turn, momentum, goals, tokens all restored
test_app_with_no_save_file_starts_fresh No crash when save file absent
test_save_on_quit_then_reload_round_trip Full cycle: save via s → new app → loads state
test_hook_listener_uses_loaded_state_after_mount Post-load g key increments loaded session, not stale state

Unit tests (test_app.pyTestLoadFromSaveExchange):

  • Returns False when no bridge loop / no exchange / no file
  • Returns True and updates state, bridge_loop.state, and hook_listener.state when save exists

Toward kanban

Toward kanban: t_cefabee5 (M1 Vertical Slice) — all M1 deliverables now complete including close/reopen

Test plan

  • pytest tui/tests/ -q → 48 passed
  • pytest -q → 149 passed

https://claude.ai/code/session_01NpeAv65eF3PeVd91JoTNJs


Generated by Claude Code

PRD M1 deliverable: "Close/reopen preserves all state."

Previously MainApp.on_mount called refresh_panels() but never loaded from
the save exchange, so every reopen started from scratch. Save-on-exit was
already implemented in action_quit (via bridge_loop.save_exchange).

Implementation:
- Add MainApp._load_from_save_exchange() — checks bridge_loop.save_exchange,
  reads the payload, and replaces self.session_state, bridge_loop.state, and
  hook_listener.state with the loaded state so all three references are
  consistent after the swap.
- Call _load_from_save_exchange() at the top of on_mount() before refresh.

Tests (5 Pilot + 4 unit = 9 new tests):

Pilot (test_app_pilot.py):
- test_app_loads_kingdom_name_from_save_on_mount
- test_app_restores_session_count_and_attributes_from_save
- test_app_with_no_save_file_starts_fresh
- test_save_on_quit_then_reload_round_trip
- test_hook_listener_uses_loaded_state_after_mount

Unit (test_app.py — TestLoadFromSaveExchange):
- test_returns_false_when_no_bridge_loop
- test_returns_false_when_no_save_exchange_on_loop
- test_returns_false_when_save_file_does_not_exist
- test_returns_true_and_replaces_state_when_save_exists (also verifies
  bridge_loop.state and hook_listener.state are updated)

+9 tests, 149 total passing.

https://claude.ai/code/session_01NpeAv65eF3PeVd91JoTNJs
@gemini-code-assist
Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@SolshineCode SolshineCode merged commit 4b4b119 into main May 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants