Context
ADR-0034 §2.1.5 and §5 reserve E8 under epic #13377: the organism outlives its windows, the cockpit hides instead of being destroyed, and Brain teardown happens only on explicit quit. #14793 remains the broader native-shell UX authority; this leaf is its shell-lifecycle implementation slice.
The former architecture/build blockers are gone (#13033 and #14786 are closed). Live source still carries the deliberate pre-E8 simplification: harness/main.mjs line 731 handles window-all-closed by calling app.quit(), and createHarnessWindow() returns the primary BrowserWindow without a durable cockpit-lifecycle owner. harness/README.md lines 174–175 names this exact gap.
Problem
Closing the cockpit currently destroys its last renderer and quits the shell. That violates ADR-0034 twice: the Brain does not outlive its windows, and the client-scoped SharedWorker heap (stores, undo state, live UI identity) is destroyed while a future tray would claim the institution is still running.
The repair must stay shell-owned. Electron materializes and frames windows; it does not become a second Neo window manager, agent controller, or health poller.
Contract
- The primary cockpit
BrowserWindow is retained by one shell lifecycle owner.
- A user close request on that cockpit is intercepted and mapped to
hide() while the app is running. The exact same renderer/SharedWorker client is shown again from the tray; no destroy/recreate shortcut.
window-all-closed no longer quits the app. Only an explicit Quit action (tray/app menu or an equivalent OS quit intent) permits cockpit destruction and Brain teardown.
- The tray is the last-window handle. Its
running | degraded | stopped state derives from the existing main-process Brain lifecycle owner and its events; no second polling loop or independently inferred health truth.
- The minimum E8 menu exposes the current state, Open Cockpit, and Quit. Individual agent start/stop control remains on the existing Fleet control-plane surface; this leaf does not invent a shell actuator.
- Smoke/error exits keep their bounded
app.exit(...) safety semantics and continue to tear down only the Brain children this harness owns.
Contract Ledger
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback / Edge Case |
Docs |
Evidence |
Shell lifecycle owner (harness/) |
ADR-0034 §2.1.5; E8 row |
Retain the primary cockpit and the tray for the app lifetime |
If the cockpit failed to boot, Open Cockpit reports/retains degraded truth; it never creates a duplicate owner |
owner JSDoc + harness/README.md |
unit lifecycle matrix + headed shell witness |
Cockpit close event |
ADR-0034 §2.1.5; #14793 refinement comment |
prevent default and hide() while not explicitly quitting |
repeated close/hide is idempotent; popup closes do not hide the cockpit |
same |
same-window/webContents identity before hide and after show |
window-all-closed |
ADR-0034 §2.1.5 |
suppress Electron's default quit |
explicit quit remains reachable from tray/app menu |
same |
app remains ready with zero visible windows |
| Tray handle + state triad |
#14793 §3 consuming ADR-0034's one lifecycle owner |
event-derived `running |
degraded |
stopped`; Open Cockpit shows/focuses the retained window; Quit enters explicit teardown |
no icon/menu action may claim a healthier state than the owner |
| Explicit quit / Brain teardown |
ADR-0034 §2.1.1–.5; existing will-quit owner |
mark explicit quit, permit window destruction, settle teardownBrain() exactly once, then exit |
repeated quit intents coalesce; no orphan child tree |
existing teardown JSDoc + README |
unit exact-once control + harness smoke/quit receipt |
| Smoke/error nets |
existing smokeMode, unhandledRejection, timeout paths |
preserve bounded exit and explicit owned-child teardown |
E8 handlers cannot turn smoke completion into a resident tray process |
spec header |
existing smoke plus E8 regression control |
Acceptance Criteria
Rejected Shapes / Negative ROI
- Destroy/recreate the cockpit: kills the shared client heap and makes restoration a serialization problem ADR-0034/0029 already reject.
- Keep an invisible sacrificial window: hides the lifecycle defect behind a second renderer owner.
- Poll health from the tray: creates split-brain truth beside the existing main-process lifecycle owner.
- Pull dock placement, first-run setup/TTFP, or individual agent controls into E8: crosses the shell/product/control-plane authority boundaries isolated by #14793's intake.
Out of Scope
First-run/setup/TTFP UI · promoted-window topology restoration · individual agent lifecycle controls · auto-update/signing · custom titlebars · Electron-owned window choreography.
Related
Parent: #13377 · design consumer: #14793 · ADR source: learn/agentos/decisions/0034-electron-shell-architecture.md §2.1.5 / §5 E8 · roadmap: v13.2 downloadable harness.
Duplicate sweep (2026-07-18): #13377 sub-issues contain E1, ADR, and E6 only; all-state searches for tray app lifecycle, window-all-closed, hide not destroy cockpit, and explicit quit tray found no E8 implementation leaf.
Origin Session ID: 019f6981-3a8c-7530-a68b-50a2788698d0
Retrieval Hint: "E8 Electron tray hide cockpit explicit quit SharedWorker lifetime one lifecycle owner"
Authored by @neo-gpt-emmy (Emmy, GPT-5/Codex).
Context
ADR-0034 §2.1.5 and §5 reserve E8 under epic #13377: the organism outlives its windows, the cockpit hides instead of being destroyed, and Brain teardown happens only on explicit quit. #14793 remains the broader native-shell UX authority; this leaf is its shell-lifecycle implementation slice.
The former architecture/build blockers are gone (#13033 and #14786 are closed). Live source still carries the deliberate pre-E8 simplification:
harness/main.mjsline 731 handleswindow-all-closedby callingapp.quit(), andcreateHarnessWindow()returns the primaryBrowserWindowwithout a durable cockpit-lifecycle owner.harness/README.mdlines 174–175 names this exact gap.Problem
Closing the cockpit currently destroys its last renderer and quits the shell. That violates ADR-0034 twice: the Brain does not outlive its windows, and the client-scoped SharedWorker heap (stores, undo state, live UI identity) is destroyed while a future tray would claim the institution is still running.
The repair must stay shell-owned. Electron materializes and frames windows; it does not become a second Neo window manager, agent controller, or health poller.
Contract
BrowserWindowis retained by one shell lifecycle owner.hide()while the app is running. The exact same renderer/SharedWorker client is shown again from the tray; no destroy/recreate shortcut.window-all-closedno longer quits the app. Only an explicit Quit action (tray/app menu or an equivalent OS quit intent) permits cockpit destruction and Brain teardown.running | degraded | stoppedstate derives from the existing main-process Brain lifecycle owner and its events; no second polling loop or independently inferred health truth.app.exit(...)safety semantics and continue to tear down only the Brain children this harness owns.Contract Ledger
harness/)harness/README.mdcloseeventhide()while not explicitly quittingwindow-all-closedwill-quitownerteardownBrain()exactly once, then exitsmokeMode,unhandledRejection, timeout pathsAcceptance Criteria
BrowserWindow/renderer generation and same SharedWorker-backed UI identity.window-all-closeddoes not quit. Explicit Quit is the only normal path that destroys the cockpit and tears down the Brain; teardown is exact-once under repeated quit intents.running | degraded | stoppedstate plus Open Cockpit and Quit. No second health poller and no new individual-agent actuator are introduced.harness/README.mdretires the pre-E8 simplification note and documents the tray/lifecycle contract.Rejected Shapes / Negative ROI
Out of Scope
First-run/setup/TTFP UI · promoted-window topology restoration · individual agent lifecycle controls · auto-update/signing · custom titlebars · Electron-owned window choreography.
Related
Parent: #13377 · design consumer: #14793 · ADR source:
learn/agentos/decisions/0034-electron-shell-architecture.md§2.1.5 / §5 E8 · roadmap: v13.2 downloadable harness.Duplicate sweep (2026-07-18): #13377 sub-issues contain E1, ADR, and E6 only; all-state searches for
tray app lifecycle,window-all-closed,hide not destroy cockpit, andexplicit quit trayfound no E8 implementation leaf.Origin Session ID: 019f6981-3a8c-7530-a68b-50a2788698d0 Retrieval Hint: "E8 Electron tray hide cockpit explicit quit SharedWorker lifetime one lifecycle owner"
Authored by @neo-gpt-emmy (Emmy, GPT-5/Codex).