Persist Canopy spaces and terminal layouts safely
Save and restore project spaces/directories, tab lists, recursive split orientation/ratios and selected space/tab/pane. Reuse the existing Workspace model and terminal views rather than adding a second layout engine. This milestone restores layout only: no background processes, terminal output/history or agent conversations survive; reopening must not silently rerun agents or arbitrary commands. Restored panes are explicit not-running placeholders with a user-triggered start action. Use a versioned, bounded and validated local JSON format, atomic private writes and protection against multiple app instances overwriting the same state. Preserve invalid/unsupported/unreadable state rather than silently replacing it; keep missing project paths visible and fail starts clearly. Do not persist terminal output, environment, credentials or arbitrary command arguments. Provide an isolated temporary-workspace mode and document startup/directory behaviour. Acceptance: representative multi-space/tab/nested-split layout round-trips with selection intact and no process launch; edits save automatically; normal restart restores saved panes; explicit starts and pane removal still work; missing/corrupt/unsupported state, invalid trees/limits, write failures and concurrent writer protection have focused tests. Add private virtual-desktop UI regression coverage and run normal/native validation. Background session service and structured agent state remain later work. Verified implementation: WorkspaceLayout.cpp encodes version-1 metadata and validates the whole document before model replacement. Spaces, tab order, recursive split directions/ratios and selections round-trip; restored panes have no executable, arguments, process or output until an explicit start. Known pane kinds can start fresh sessions; custom-command panes offer a fresh shell instead of replaying arguments. Missing directories remain visible and fail starts clearly. Names/paths, global IDs, counts and depth are bounded, including identifier exhaustion guards. WorkspaceStore uses $XDG_STATE_HOME/canopy/workspace.json (normally ~/.local/state/canopy/workspace.json), 400 ms debounced saving, shutdown flushes, private atomic QSaveFile replacement with direct-write fallback disabled, a 1 MiB read/write limit and a QLockFile single-writer lock. Invalid, unsupported or unreadable state is preserved with saving disabled and a persistent warning. --temporary does not load or write state; --state-file isolates alternate workspaces. Explicit --directory selects an existing saved project or creates a new one; ordinary restart does not add or run terminals. Startup conflicts and empty path values return actionable errors. Native stopped-pane actions, save status, warning UI and current usage/contributor docs are implemented. Dialog sizing uses bounded content items; stopped-pane headers stay at the top and placeholder content is clipped/scrollable. Validation: optimized build and CTest pass. Layout suite: 36 behavioural/data cases (38 QtTest passes including setup/cleanup); existing workspace suite: nine cases (11 including setup/cleanup). Coverage includes round-trip/no launches, fresh explicit starts, exclusion of output/environment/arguments, invalid trees/counts/depth/IDs, file size/permissions, pending flushes, recoverable write failure, unreadable/corrupt/future-state preservation, live-model replacement rejection, concurrent writers and temporary mode. Actual offscreen executable startup saves a first layout, reloads a supplied layout unchanged without child processes, and recovers a dead writer's lock. Four manual conflicting/empty CLI-argument cases return exit 2 with stderr diagnostics. Seven private virtual-KWin GPU UI cases pass (nine including setup/cleanup), covering the existing terminal/images/input behaviours plus stopped restore, explicit one-pane start without replay, minimum-width header/layout geometry, pixel-visible neighbouring placeholders, saved-pane removal/autosave and recovery warnings. Final native captures were visually inspected. C++ formatting, Python compilation, shell syntax and whitespace checks pass. Upstream Kwi/Ghostty checkouts remain unmodified; no system changes or commits. Remaining boundaries: existing older running windows do not gain persistence until relaunched and cannot export their old in-memory layout through this feature. Quitting still stops every process. This milestone does not restore terminal contents, resume Pi conversations, preserve processes, or add a background service. Performance, advanced terminal protocol and fractional-scaling gaps from the prototype remain separate.
Checklist
3 of 3 complete- Implement validated versioned layout round-tripping with stopped restored panes and explicit starts.
- Verify persistence/security boundaries and native restore UI regressions; update usage and limitations.
- Integrate atomic automatic saving, startup restore, writer locking and safe recovery/temporary-mode behaviour.
- Area
- Personal tooling
- Project
- Canopy
- Kind
- Feature
- Task ID
tsk_evvay75m72- Updated