Skip to main content

Module session_restore

Module session_restore 

Source
Expand description

Restore-on-relaunch (Feature 1 of docs/specs/SPEC_SESSION_RESTORE_AND_SAVED_LAYOUTS_2026_08_13.md).

A graceful window close today deliberately cascades a full delete of the workspace/tabs/blocks (e3a6f85c2, wired to the last-window “main” case by 4cbf856b7 — see docs/retro/retro-pane-layout-restore-was-a-leak-not-a-feature-2026-08-13.md), so the next cold launch always finds Client.windowids empty and reseeds the hardcoded default 3-pane layout (window_create::default_three_pane_tree).

This module adds an independent, durable “what was open last” record — written just before that destroy cascade runs (window_close::handle_close_window) and consulted by the cold-launch path (window_create::handle_create_window) before it falls back to the hardcoded seed. It deliberately does NOT touch the destroy cascade itself (that fix is correct and must stay — orphaned shell processes were the original bug) and does NOT reuse Pillar 1’s crash-reproject machinery (that’s scoped to crash-only recovery from rows a graceful close is specifically supposed to remove — see docs/specs/SPEC_PILLAR1_HOST_REPROJECT_DESIGN_2026_06_30.md §3).

Stored as a JSON blob under Client.meta["session:last_topology"] — Client is already a durable singleton row with a generic meta sidecar (the same “per-entity loosely-typed sidecar” pattern Pillar 1 Step 2 used for floating-pane placement on Block.meta), so this needs no new StoreObj type, table, or migration.

Structs§

ReplayTab 🔒
One tab to rebuild: its blocks’ meta, and a split tree whose leaves name those blocks by position (placeholder(i) ↔ blocks[i]).
ReplayedTab 🔒
A tab that replay_tabs actually rebuilt, with its blocks’ new ids in the order they were created.

Constants§

SNAPSHOT_META_KEY 🔒

Functions§

apply_and_publish 🔒
clear_last_session_snapshot 🔒
Consume the durable “last session” record after a fully successful restore (called only once window_create::handle_create_window’s final window read-back succeeds — see that call site’s comment for why not any earlier). Best-effort, same as save_last_session_snapshot: a failure to clear just means a future stray/misused restore call could replay this snapshot again, which client_windowids_empty’s server-side check (handle_create_window) already independently guards against — this is defense in depth, not the only thing preventing duplicates.
current_workspace_id 🔒
The workspace backing one of this client’s windows, if any.
find_error 🔒
handle_save_session_snapshot 🔒
Attempt to replay the durable “last session” snapshot (if any) into a fresh workspace: CreateWorkspace → per-tab CreateTab + per-block CreateBlock (reusing each block’s saved meta, so a restored agent pane relaunches the same way opening a fresh one does) → LayoutSetTree with the saved split tree (block ids remapped from placeholders to the newly created ones).
load_last_session_snapshot 🔒
placeholder 🔒
placeholder_idx 🔒
placeholderize 🔒
Replace every leaf’s real block id (in data.block_id, block_stack, active_block_id) with a positional placeholder, in place.
replay_tabs 🔒
Rebuild tabs inside an existing workspace: per tab CreateTab, each block CreateBlock (its saved meta), then LayoutSetTree with the tree’s placeholders resolved to the new block ids. Shared by restore-on-relaunch (into a fresh workspace) and Layouts → Open layout… (into the current window’s) — SPEC_LAYOUT_FILES_2026_09_25.md §1.1.
resolve_placeholders 🔒
Replace every leaf’s positional placeholder with the corresponding freshly created block id, in place. A placeholder with no matching entry (should not happen — new_ids is built 1:1 from the same snapshot’s blocks array — but tolerated defensively) is left as-is; such a leaf simply won’t resolve to a real block and the frontend already handles unknown block ids in a layout leaf as an empty pane, matching how a manually-crafted or corrupted layout degrades today.
restore_last_session 🔒
save_last_session_snapshot 🔒
Persist a snapshot as the durable “last session” record, overwriting whatever was there before. Best-effort: a write failure is logged, never propagated — this must never block the close it rides alongside.
snapshot_workspace 🔒
Read the given workspace’s tabs/blocks/layout directly from the store and build a durable, block-id-independent snapshot (real block ids are replaced with positional placeholders — CreateBlock always assigns a fresh id, so the snapshot can never reference one that will exist again). Returns None for an empty/unknown workspace (nothing worth persisting).