Move terminal ownership into a reattachable background service
Move live local terminal process ownership out of the Canopy UI into a private per-workspace background service. Closing/crashing the UI must not terminate service-owned agents/shells; reopening should reattach to the same PIDs with correct terminal state, scrollback and inline images. Keep explicit pane-close destructive and distinguish UI detach from service shutdown. Reuse Kwi/Ghostty parsing, input and rendering with a minimal reproducible upstream integration seam rather than a second terminal renderer. Selected design: a per-workspace canopy-sessiond owns Kwi PTYs and authoritative Ghostty terminal state; the GUI mirrors complete snapshots followed by ordered raw-output/resize/control events. A checked-in, idempotently applied Kwi patch exposes bounded snapshot encode/restore, virtual transport seams and output notification. Local IPC uses versioned length-prefixed JSON, same-UID SO_PEERCRED authentication, user-only sockets, bounded packets/queues, snapshot deadlines and 32 live/retained service sessions with 10,000 scrollback lines. Persist opaque UUID identities only; flush layout before a new background launch. A consumed-snapshot acknowledgement identifies ready GUI attachments by kernel peer PID for executable-level crash/relaunch validation. Remote pane removal waits for close acknowledgement; uncertain closure keeps its persisted identity. Empty-service shutdown checks both connections and sessions. Bound and validate local IPC, authenticate peer user and isolate endpoints by workspace. Never silently restart a missing process or replay arbitrary commands. Keep layout metadata private and exclude output, environment and arguments from disk persistence; live session data may remain only in service memory. Preserve current stopped-layout recovery when the service is gone. No reboot survival or agent conversation resumption is promised. Safety: the current Pi conversation is running in Canopy. Do not restart/close the active UI, terminate its processes, or reuse its saved workspace/socket for tests. Develop on a new feature branch and use private state paths, sockets and the isolated virtual Wayland runner. Do not commit/push without explicit permission. Acceptance: actual GUI/process detach and crash reattachment preserves the same child PID and terminal text/images/input/resize; explicit close terminates only its session; daemon loss is visible and does not auto-restart agents; protocol/resource validation and focused native/backend regressions pass. Document lifecycle controls and limitations. Verified outcome: implemented and built on feature/background-session-ownership, based on main 7aa5a86; no new commit or push. Normal valid persisted workspaces start/connect to canopy-sessiond; temporary or invalid-layout workspaces remain explicitly UI-owned. Window close detaches. Confirmed pane close waits for the service's closed/missing acknowledgement before deleting the persisted identity, including queued attachments and disconnected uncertainty. Reconnection is read-only until a fresh snapshot is installed. Stop-all is a separate confirmation naming all spaces, with visible tested Cancel/Stop buttons. The daemon preserves active/exited terminal state in RAM, recovers GUI crashes, and offers complete snapshots followed by ordered output/resize/control events. New launches flush UUID metadata first. Startup also recovers unmapped service-owned UUIDs into project tabs after layout loss without replaying arguments or starting duplicate processes. Existing pre-service windows cannot migrate live. Safety/bounds: same-UID kernel peer authentication and owner-only sockets; endpoint startup refuses ordinary files, foreign-owned nodes and live sockets. Framing, base64, identities, launch arguments/environment, dimensions and palettes are validated; snapshots/queues are bounded with deadlines. Service owns protocol replies; GUI mirrors never duplicate them. Child processes inherit the requesting GUI environment rather than the daemon's headless Qt override. Explicit shutdown escalates through Kwi's session/process-group lifecycle and was verified against a signal-ignoring child. Closed subscriptions are removed. Only in-memory service state contains terminal content, arguments or environment; disk persistence adds opaque UUIDs to the bounded layout schema. The canonical Kwi patch reproduces exactly from a clean pinned archive, and repeated bootstrap recognizes the already-applied patch. Attribution and source/build obligations are documented. Validation: all four CTest suites pass (workspace/layout/service/snapshot). Service suite: 15 behavioural cases, 17 QtTest passes with setup/cleanup; snapshot suite: four cases, six passes. Existing workspace/layout suites remain passed. Actual executable tests kill/relaunch the GUI and require a consumed-snapshot acknowledgement from that new GUI's SO_PEERCRED PID, then remove the layout and verify recovery with the same terminal PID/UUID and no duplicate process. Snapshot tests cover screen/history, alternate/bracketed-paste modes, partial UTF-8/CSI/image transmission, images, protocol replies and atomic rejection of invalid/truncated/trailing data. Service tests cover detach/input/resize, images, single query replies, oversized packets, invalid launches, empty-client idle timing, pre-reply/queued/disconnected close, daemon loss, endpoint safety, child environment and forced shutdown. Native virtual-KWin suite: eight cases, ten passes, including actual window close/reopen, same PID and rendered image pixels, same-window read-only disconnect/reconnect with search reset, real key/clipboard input, pane-close cancellation/confirmation, and stop-all cancellation/confirmation. Final captures were visually inspected on the RX 9070/OpenGL backend. Optimized build, C++/QML formatting, Python compilation, shell syntax, patch/source whitespace and private-metadata checks pass. Tests used private state files/endpoints and isolated desktops; the active conversation/window was not restarted or terminated. Review evidence: the initial static review verified lost-close-identity, connected-empty-service idle exit and insufficient GUI-relaunch assertions. Added red controls reproduced all three lifecycle failures; the corrected regressions pass. Suppressing restored GUI background enablement makes the strengthened executable reattachment check fail; restoring it passes. A scoped re-review reported no additional verified findings, but remained PARTIAL: pinned vendor sources were unavailable to its reviewers, and some upstream/lifecycle coverage could not be established. This is not a whole-project/security approval. Selected upstream implementations/APIs were separately inspected during implementation, with runtime regressions as above. Remaining limitations: no service-crash/logout/reboot survival or automatic Pi-conversation resumption; no live migration of the currently running older window; no remote machines or structured agent status. Background OSC clipboard forwarding is disabled; ordinary tested terminal copy/paste works. Service caps are 32 live/retained sessions, 10,000 scrollback lines and 64 MiB snapshots. Throughput, worst-case memory, advanced terminal protocols and fractional scaling are not performance-certified. Do not move a state file or use an incompatible older build while its service owns work.
Checklist
4 of 4 complete- Implement private authenticated service/client transport and live session lifecycle with detach/reattach semantics.
- Expose and verify bounded complete terminal snapshots through a reproducible Kwi integration patch.
- Integrate session identities and UI detach/reconnect/explicit-stop behaviour without restarting saved commands.
- Verify actual process/UI failure recovery, images/input/resize and resource limits in isolated tests; document limitations.
- Area
- Personal tooling
- Project
- Canopy
- Kind
- Feature
- Task ID
tsk_hab5636bkm- Updated