@timurproko/a1 0.2.7-dev.754 → 0.2.7-dev.767

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/bin/guardian.js +5 -0
  2. package/bin/tab-launch-context.d.ts +23 -0
  3. package/bin/tab-launch-context.js +45 -0
  4. package/bin/ui.js +20 -5
  5. package/dist/app/session-shell/helper-pool.d.ts +3 -5
  6. package/dist/app/session-shell/helper-pool.js +3 -5
  7. package/dist/app/session-shell/session-shell-root.d.ts +29 -1
  8. package/dist/app/session-shell/session-shell-root.js +3 -2
  9. package/dist/app/session-shell/session-shell.js +153 -30
  10. package/dist/app/session-shell/session-viewport-controller.d.ts +1 -1
  11. package/dist/app/session-shell/session-viewport-controller.js +3 -3
  12. package/dist/composition/owned-ui.d.ts +20 -0
  13. package/dist/composition/owned-ui.js +76 -3
  14. package/dist/contracts/owned-ui/session-backend.d.ts +1 -0
  15. package/dist/features/owned-ui/settings-app.js +8 -35
  16. package/dist/foundation/launch-context/index.d.ts +6 -0
  17. package/dist/foundation/launch-context/index.js +15 -0
  18. package/dist/foundation/launch-guardian/main.d.ts +5 -0
  19. package/dist/foundation/launch-guardian/main.js +2 -1
  20. package/dist/foundation/release/bootstrap.d.ts +4 -0
  21. package/dist/foundation/release/bootstrap.js +44 -6
  22. package/dist/foundation/release/dependency-certification.js +54 -19
  23. package/dist/foundation/release/progress-palette.generated.d.ts +2 -2
  24. package/dist/foundation/release/progress-palette.generated.js +2 -2
  25. package/dist/foundation/resident-tabs/bridge-client.d.ts +41 -0
  26. package/dist/foundation/resident-tabs/bridge-client.js +199 -0
  27. package/dist/foundation/resident-tabs/draft-checkpoint.d.ts +27 -0
  28. package/dist/foundation/resident-tabs/draft-checkpoint.js +145 -0
  29. package/dist/foundation/resident-tabs/ensure-terminal-host.d.ts +30 -0
  30. package/dist/foundation/resident-tabs/ensure-terminal-host.js +121 -0
  31. package/dist/foundation/resident-tabs/fault-injection.d.ts +8 -0
  32. package/dist/foundation/resident-tabs/fault-injection.js +26 -0
  33. package/dist/foundation/resident-tabs/index.d.ts +6 -0
  34. package/dist/foundation/resident-tabs/index.js +3 -0
  35. package/dist/foundation/resident-tabs/prompt-journal.d.ts +65 -0
  36. package/dist/foundation/resident-tabs/prompt-journal.js +214 -0
  37. package/dist/foundation/resident-tabs/protocol.d.ts +12 -0
  38. package/dist/foundation/resident-tabs/protocol.js +195 -0
  39. package/dist/foundation/resident-tabs/recovery.d.ts +26 -0
  40. package/dist/foundation/resident-tabs/recovery.js +205 -0
  41. package/dist/foundation/resident-tabs/routing.d.ts +10 -0
  42. package/dist/foundation/resident-tabs/routing.js +8 -0
  43. package/dist/foundation/resident-tabs/session-sync.d.ts +14 -0
  44. package/dist/foundation/resident-tabs/session-sync.js +37 -0
  45. package/dist/foundation/resident-tabs/settings.d.ts +9 -0
  46. package/dist/foundation/resident-tabs/settings.js +65 -0
  47. package/dist/foundation/session-writer-lock/index.d.ts +27 -0
  48. package/dist/foundation/session-writer-lock/index.js +197 -0
  49. package/dist/foundation/startup/startup-descriptor.js +2 -2
  50. package/dist/foundation/terminal-cleanup/index.d.ts +1 -1
  51. package/dist/foundation/terminal-cleanup/index.js +1 -1
  52. package/dist/foundation/terminal-cleanup/terminal-reset.d.ts +1 -0
  53. package/dist/foundation/terminal-cleanup/terminal-reset.js +1 -0
  54. package/dist/integrations/pi/components/owned-editor-ux.d.ts +1 -1
  55. package/dist/integrations/pi/components/owned-editor-ux.js +2 -2
  56. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +4 -4
  57. package/dist/integrations/pi/components/resources/builtin-themes.js +4 -4
  58. package/dist/integrations/pi/components/shell-shared-facade.d.ts +1 -1
  59. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
  60. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +17 -4
  61. package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
  62. package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
  63. package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
  64. package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
  65. package/dist/integrations/pi/components/upstream/components/extension-editor.js +1 -1
  66. package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
  67. package/dist/integrations/pi/components/upstream/components/extension-selector.js +1 -1
  68. package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
  69. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +1 -1
  70. package/dist/integrations/pi/components/upstream/components/owned-editor.js +1 -1
  71. package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
  72. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
  73. package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
  74. package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
  75. package/dist/integrations/pi/components/upstream/components/session-selector.js +1 -1
  76. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
  77. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
  78. package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +2 -2
  79. package/dist/integrations/pi/components/upstream/components/status-indicator.js +3 -3
  80. package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
  81. package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
  82. package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
  83. package/dist/integrations/pi/components/upstream/components/thinking-selector.js +1 -1
  84. package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +0 -2
  85. package/dist/integrations/pi/components/upstream/components/tool-execution.js +41 -20
  86. package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +1 -1
  87. package/dist/integrations/pi/components/upstream/components/tree-selector.js +1 -1
  88. package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
  89. package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
  90. package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +2 -2
  91. package/dist/integrations/pi/components/upstream/history/editor-core.js +5 -5
  92. package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
  93. package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
  94. package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
  95. package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
  96. package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
  97. package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
  98. package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
  99. package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
  100. package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +1 -1
  101. package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
  102. package/dist/integrations/pi/components/upstream/theme/theme.d.ts +3 -0
  103. package/dist/integrations/pi/components/upstream/theme/theme.js +24 -1
  104. package/dist/integrations/pi/engine/adapter.js +1 -0
  105. package/dist/integrations/pi/engine/pi-settings-metadata.json +2 -2
  106. package/dist/integrations/pi/engine/resources/changelog.json +4 -4
  107. package/dist/integrations/pi/engine/runtime-integration.js +102 -29
  108. package/dist/integrations/pi/engine/session-runtime.d.ts +0 -6
  109. package/dist/integrations/pi/engine/session-runtime.js +8 -3
  110. package/dist/integrations/pi/engine/session-selection.d.ts +3 -0
  111. package/dist/integrations/pi/engine/session-selection.js +45 -9
  112. package/dist/integrations/pi/engine/workflow-contexts.js +10 -1
  113. package/dist/integrations/pi/startup-public.js +152 -222
  114. package/dist/integrations/pi/startup-public.manifest.json +266 -177
  115. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
  116. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +1 -1
  117. package/dist/native/darwin-arm64/manifest.json +1 -1
  118. package/dist/native/linux-x64/manifest.json +1 -1
  119. package/dist/native/win32-x64/manifest.json +2 -2
  120. package/dist/native/win32-x64/process-guardian.exe +0 -0
  121. package/dist/product-identity.d.ts +1 -1
  122. package/dist/product-identity.js +1 -1
  123. package/dist/product-identity.json +5 -0
  124. package/dist/runtime-payload-inventory.json +5349 -6035
  125. package/dist/ui/components/line-input.d.ts +1 -1
  126. package/dist/ui/components/prompt-input.d.ts +7 -5
  127. package/dist/ui/components/prompt-input.js +7 -7
  128. package/dist/ui/components/transcript-viewport.d.ts +6 -3
  129. package/dist/ui/components/transcript-viewport.js +13 -15
  130. package/dist/ui/settings/declarations.d.ts +49 -1
  131. package/dist/ui/settings/declarations.js +37 -1
  132. package/dist/ui/settings/index.d.ts +5 -3
  133. package/dist/ui/settings/index.js +3 -2
  134. package/dist/ui/settings/manager.d.ts +9 -3
  135. package/dist/ui/settings/manager.js +81 -29
  136. package/dist/ui/settings/migrations.d.ts +6 -0
  137. package/dist/ui/settings/migrations.js +32 -0
  138. package/dist/ui/settings/profile-document.d.ts +26 -0
  139. package/dist/ui/settings/profile-document.js +164 -0
  140. package/dist/ui/settings/resolution.d.ts +2 -0
  141. package/dist/ui/settings/resolution.js +13 -1
  142. package/dist/ui/settings/sections.js +4 -0
  143. package/docs/architecture/internal-naming.md +1 -1
  144. package/docs/architecture/resident-tabs-requirements.md +580 -0
  145. package/docs/architecture/resident-tabs.md +522 -0
  146. package/docs/architecture/terminal-host-proof-gate.md +2 -0
  147. package/docs/openspec-archive-automation.md +17 -16
  148. package/docs/validation.md +1 -1
  149. package/package.json +6 -4
@@ -0,0 +1,580 @@
1
+ # Resident tabs — target requirements
2
+
3
+ Status: target, not implemented. These are the requirements the six milestones in [`resident-tabs.md`](resident-tabs.md#roadmap) deliver. They are written as OpenSpec deltas against the canonical specs as of 2026-10-10. Each milestone change copies the requirements it implements into its own `specs/` delta, adjusts them to what it actually delivers, and removes them from this file, so this file shrinks to empty as the preview lands. Requirements here bind nothing until a milestone change merges them.
4
+
5
+ ## Capability: `multi-agent-tabs`
6
+
7
+ ### Purpose
8
+
9
+ Defines the bare-A1 tab presentation for several independent resident A1 agent sessions: tab lifecycle, naming, bridge-derived status and attention, input routing, shortcuts, commands, detach-on-quit, and reattach.
10
+
11
+ ### ADDED Requirements
12
+
13
+ #### Requirement: Bare A1 presents resident A1 sessions as tabs
14
+ When resident tabs are enabled, bare `a1` SHALL present a one-row tab strip at the top of the terminal and the viewed tab's terminal surface in all remaining rows. Each tab SHALL be an independent resident terminal session running the complete A1 owned UI with its own Pi agent session, extensions, transcript, editor, queue, model, thinking level, notices, and cwd. Only the viewed tab SHALL receive keyboard, paste, focus, and surface mouse input. The strip SHALL be present even when a single tab exists. `a1 pi` SHALL NOT present a tab strip.
15
+
16
+ ##### Scenario: First launch with no tabs
17
+ - **WHEN** the user runs bare `a1` and the profile has no resident tabs
18
+ - **THEN** A1 SHALL create one A1 tab in the launch cwd and view it
19
+
20
+ ##### Scenario: Two tabs keep separate state
21
+ - **WHEN** the user types a draft in tab 1, switches to tab 2, prompts it, and switches back
22
+ - **THEN** tab 1 SHALL show its transcript, scroll position, and draft unchanged
23
+ - **AND** the prompt SHALL have reached only the agent of tab 2
24
+
25
+ ##### Scenario: Switch while both agents work
26
+ - **WHEN** the user switches tabs while both agents stream
27
+ - **THEN** only the viewed surface and input target SHALL change, and both agents SHALL continue without pause or restart
28
+
29
+ ##### Scenario: Extension custom UI in a tab
30
+ - **WHEN** an extension renders a custom interactive component using the certified text-terminal contract
31
+ - **THEN** keyboard, mouse, paste, selection, clipboard, hyperlinks, cursor, Unicode, and alternate-screen behavior SHALL match direct single-agent bare A1
32
+ - **AND** an inline-image request SHALL use the existing text fallback rather than imply unsupported image-protocol parity
33
+
34
+ ##### Scenario: Pi comparison profile
35
+ - **WHEN** the user runs `a1 pi`
36
+ - **THEN** no tab strip, resident server, holder, or tab bridge SHALL be involved
37
+
38
+ #### Requirement: Tab chips follow the declared strip layout
39
+ Each chip SHALL render one space, an optional status glyph and space, the display name, and one space, with a maximum width of 20 terminal columns. Names SHALL be clipped with `…` at grapheme boundaries using display width. Viewed, hovered, and other chips SHALL use distinct colors resolved from the A1 theme's declared roles. When chips do not fit, the viewed chip SHALL stay visible, remaining tabs SHALL collapse into a `…` chip that opens a keyboard-navigable menu marking the viewed tab, and a trailing `+` chip SHALL always be reserved. The strip SHALL NOT wrap to a second row.
40
+
41
+ ##### Scenario: Wide names are clipped by display width
42
+ - **WHEN** a tab name contains CJK characters or emoji wider than the chip allows
43
+ - **THEN** the chip SHALL be clipped with `…` at a grapheme boundary and SHALL NOT exceed 20 columns
44
+
45
+ ##### Scenario: More tabs than fit
46
+ - **WHEN** the terminal cannot fit every chip
47
+ - **THEN** the viewed chip SHALL remain visible, a `…` chip SHALL list the hidden tabs, and next, previous, and jump keys SHALL still reach hidden tabs
48
+
49
+ #### Requirement: Tab status comes from the tab bridge, not the screen
50
+ Each chip SHALL show a glyph from the tab's structured status: shared progress frames while working, a yellow `?` in the warning color while an extension, trust, or permission request awaits the user, `✓` in the success color when a turn settled while no client viewed the tab and it has not been viewed since, `✗` in the error color when the last turn errored or the tab crashed or failed, dim progress frames while starting or restoring, dim `◌` while suspended, and no glyph when idle. A1 tab status SHALL be derived from engine events reported by A1 inside the tab through the authenticated tab bridge. It SHALL NOT be derived from terminal output, rendered cells, titles, or timing. A tab whose bridge is unavailable SHALL show only process-level states. Viewing a tab in any client SHALL clear its `✓` in every client.
51
+
52
+ ##### Scenario: Background tab needs input
53
+ - **WHEN** an extension in a background tab requests confirmation
54
+ - **THEN** that chip SHALL show a yellow `?` until the request is answered
55
+
56
+ ##### Scenario: Background tab finishes
57
+ - **WHEN** a background tab's agent completes a turn
58
+ - **THEN** its chip SHALL show `✓` until any client views it, after which the glyph SHALL clear everywhere
59
+
60
+ ##### Scenario: Terminal-looking output cannot fake a status
61
+ - **WHEN** a tab prints spinner characters, `✓`, or a title containing status words
62
+ - **THEN** the chip status SHALL remain determined by the bridge only
63
+
64
+ #### Requirement: Tab status icons are the only attention signal
65
+ Background attention SHALL be conveyed only by the tab status icons. A1 SHALL NOT emit a terminal bell, sound, terminal notification sequence, or operating-system notification for tab status changes, and SHALL NOT forward a bell character written by a tab's program to the outer terminal.
66
+
67
+ ##### Scenario: Background tab needs the user
68
+ - **WHEN** a background tab enters needs-input or finishes a turn
69
+ - **THEN** only its chip icon SHALL change, and no bell, sound, or notification SHALL be produced
70
+
71
+ ##### Scenario: A tab's program rings the bell
72
+ - **WHEN** a program running in a tab writes a bell character
73
+ - **THEN** the outer terminal SHALL NOT receive it
74
+
75
+ #### Requirement: Tabs are created, switched, and reordered from keyboard, mouse, and commands
76
+ A1 SHALL create a new A1 tab in the client's launch cwd from `Alt+A`, the `+` chip, or `/new-tab [name]`, and SHALL view it. `Alt+.` and `Alt+,` SHALL view the next and previous tab with wrap-around; `Alt+1` through `Alt+9` SHALL view that tab and `Alt+0` the tenth; `Alt+>` and `Alt+<` SHALL move the viewed tab right and left. On the strip row, a left click SHALL view a chip, dragging a chip after 250 ms or pointer movement SHALL reorder it with a `│` drop marker, and a right click SHALL open a `Rename`/`Close` menu. `/tabs` SHALL open a picker listing every tab with name, status, and cwd. Reordering SHALL use expected registry revisions. When `tabsMax` is reached, creation affordances SHALL create nothing and SHALL state the limit. A prewarmed standby tab SHALL be used for creation when available.
77
+
78
+ ##### Scenario: Create from the keyboard
79
+ - **WHEN** the user presses `Alt+A`
80
+ - **THEN** a new tab SHALL appear after the last tab, named by the default naming rule, and become viewed with an empty editor
81
+
82
+ ##### Scenario: Jump beyond the tab count
83
+ - **WHEN** the user presses `Alt+7` with three tabs
84
+ - **THEN** the viewed tab SHALL NOT change and the key SHALL NOT reach the tab
85
+
86
+ ##### Scenario: Concurrent reorder from two terminals
87
+ - **WHEN** two attached clients reorder tabs from the same registry revision
88
+ - **THEN** exactly one reorder SHALL apply and both clients SHALL converge on the committed order
89
+
90
+ #### Requirement: Tabs are renamed inline and names are the Pi session names
91
+ `F2`, the chip menu, and `/name <name>` SHALL rename a tab. `F2` and the menu SHALL open an inline chip editor in which `Enter` commits, and `Esc` or a click elsewhere cancels. A committed name SHALL be trimmed, stripped of control characters, nonempty, and at most 64 characters; invalid input SHALL keep the editor open with a concise reason. A committed name SHALL become the tab's Pi session name, SHALL be visible in every client, and SHALL be marked user-provided. New tabs SHALL be named `agent`, or `agent N` with the smallest free N. When `tabsAutoName` is enabled (default), A1 in the tab SHALL propose a lowercase hyphenated name of at most 16 characters after the first turn settles, using the tab's model with a bounded budget and a deterministic fallback from the first prompt, and SHALL never override a user-provided name.
92
+
93
+ ##### Scenario: Rename inline
94
+ - **WHEN** the user presses `F2`, types `auth-refactor`, and presses `Enter`
95
+ - **THEN** every client SHALL show `auth-refactor` and the tab's Pi session name SHALL be `auth-refactor`
96
+
97
+ ##### Scenario: User name survives auto-naming
98
+ - **WHEN** the user renames a tab before its first turn settles
99
+ - **THEN** auto-naming SHALL NOT change that name
100
+
101
+ #### Requirement: Closing a tab stops only that session after confirmation when busy
102
+ `Alt+W`, the chip menu, and `/close` SHALL close a tab. When the tab is working, awaiting input, or reports queued input, A1 SHALL ask `Stop "<name>"? Enter stop · Esc cancel` before acting. Closing SHALL request graceful shutdown of that tab's A1 process, terminate its verified tree after a bounded deadline, remove the tab from every client, and leave its Pi session resumable. Closing the last tab SHALL leave the strip with `+` and a hint rather than quit.
103
+
104
+ ##### Scenario: Close a working tab and cancel
105
+ - **WHEN** the user presses `Alt+W` on a streaming tab and then `Esc`
106
+ - **THEN** the tab SHALL remain and its agent SHALL continue
107
+
108
+ ##### Scenario: Closed session remains resumable
109
+ - **WHEN** a closed tab's session is selected with `/resume` or `a1 --session`
110
+ - **THEN** its transcript SHALL open in a tab with no lost committed entries
111
+
112
+ #### Requirement: Concurrent clients use one attributable input controller
113
+ Each tab SHALL have at most one input-controller client and a monotonic controller revision. Transfer SHALL freeze old-controller admission, account for accepted input in native, PTY and child buffers, and establish a child-observed causal boundary before acknowledging the new owner and admitting its input. A sideband acknowledgement alone SHALL NOT establish that boundary. Input and PTY resize messages SHALL carry the current controller revision; stale or read-only clients SHALL be rejected without delivering bytes. Client-scoped child requests SHALL capture an immutable origin controller identity/revision at command admission, SHALL NOT be rebound at execution, and SHALL apply only while that origin remains current. Ambiguous attribution SHALL reject the request without affecting either client; attach-local actions SHALL remain available. Terminal bytes and prompt content SHALL NOT enter the bridge.
114
+
115
+ ##### Scenario: A second terminal takes control
116
+ - **WHEN** a second client atomically claims a tab currently controlled by another client
117
+ - **THEN** the causal boundary and new owner SHALL be acknowledged before its first terminal input is delivered, the prior client SHALL become read-only, and previously buffered commands SHALL NOT be attributed to the new controller
118
+
119
+ ##### Scenario: Stale detach request arrives
120
+ - **WHEN** a bridge detach request names a controller revision that has been superseded
121
+ - **THEN** the server SHALL reject it and SHALL NOT detach either client
122
+
123
+ ##### Scenario: Delayed quit from a previous controller
124
+ - **WHEN** client A submits `/quit`, the input is delayed in a PTY or child queue, and client B claims control before it executes
125
+ - **THEN** the request SHALL retain A's old generation or be rejected as ambiguous, SHALL NOT detach B, and SHALL NOT stop the tab
126
+
127
+ ##### Scenario: Controller boundary cannot be proven
128
+ - **WHEN** transport loss or incomplete input-boundary evidence prevents reliable command attribution
129
+ - **THEN** client-scoped child commands SHALL remain disabled with a concise notice, terminal input SHALL remain usable, and local double-`Ctrl+C` SHALL still detach only its attach client
130
+
131
+ #### Requirement: Quitting bare A1 detaches from resident tabs
132
+ Pressing `Ctrl+C` twice within the existing clear/exit interval SHALL detach the local attach client from any tab. The attach client SHALL forward the first `Ctrl+C` to the viewed tab unchanged and SHALL consume a second `Ctrl+C` inside the interval as the detach request without forwarding it, so a single `Ctrl+C` keeps its ordinary meaning in the tab and a double press never ends the tab's process. Inside an A1 tab, `/quit` and `Ctrl+D` on an empty editor SHALL detach only the client identified by their immutable command-origin controller revision, and only while it is still current. When the bridge or attribution is unavailable, the child SHALL remain running and SHALL direct the user to `Ctrl+C` twice. Detaching SHALL restore the outer terminal's screen and input modes and leave every tab running. When tabs remain running, the parent terminal SHALL show a dim `N tabs still running · run a1 to return`, singular for one. `/quit-all` SHALL stop every tab after confirmation when any is busy, then detach with the ordinary resume hint.
133
+
134
+ ##### Scenario: Leave with Ctrl+C twice
135
+ - **WHEN** the user presses `Ctrl+C` twice within the clear/exit interval in any tab
136
+ - **THEN** the tab SHALL receive exactly one `Ctrl+C`, the client SHALL detach, and the tab's process SHALL keep running
137
+
138
+ ##### Scenario: Single Ctrl+C keeps its meaning
139
+ - **WHEN** the user presses `Ctrl+C` once in an A1 tab
140
+ - **THEN** A1 in the tab SHALL clear or copy exactly as in single-agent A1 and the client SHALL remain attached
141
+
142
+ ##### Scenario: Quit while a tab works
143
+ - **WHEN** the user quits while a background tab streams
144
+ - **THEN** the terminal SHALL be restored with the running-tabs hint and the tab SHALL finish its turn
145
+
146
+ ##### Scenario: Enhanced keyboard modes do not leak
147
+ - **WHEN** the client detaches after enabling enhanced keyboard or mouse reporting
148
+ - **THEN** the parent shell SHALL receive no enhanced key or mouse sequences
149
+
150
+ #### Requirement: Relaunching bare A1 reattaches every tab
151
+ Bare `a1` SHALL connect to the profile's resident server, show every tab, and view the last viewed tab from its retained terminal surface within the interactive first-paint and first-input budgets. The surface SHALL include output produced while no client was attached. A launch while the server is recovering SHALL show a non-blocking reconnecting indication rather than fail.
152
+
153
+ ##### Scenario: Close the terminal mid-turn and return
154
+ - **WHEN** the terminal running `a1` closes while a tab streams, and the user later runs `a1` in a new terminal
155
+ - **THEN** the tab SHALL show the output produced while detached and the live continuation of the turn, or its completed result
156
+
157
+ ##### Scenario: Two terminals at once
158
+ - **WHEN** bare `a1` runs in two terminals of one profile
159
+ - **THEN** both SHALL show the same tabs and each SHALL keep its own viewed tab
160
+ - **AND** only the current input controller of a tab SHALL send input or resize its PTY while the other client remains a read-only viewer until it claims control
161
+
162
+ #### Requirement: Tab shortcuts are declared, configurable, and conflict-checked
163
+ Tab shortcuts SHALL be declared with action identities, SHALL be configurable through a keybindings file, SHALL be checked at launch against A1's shortcut registry and user keybindings with conflicts reported, and SHALL appear in `/hotkeys` inside A1 tabs. The attach client SHALL consume a matched tab shortcut before input encoding and SHALL forward every other input to the viewed tab; the only `Ctrl+C` handling SHALL be the double-press detach. Defaults SHALL NOT use `Alt+[`, `Alt+]`, `Alt+Left`, `Alt+Right`, `Ctrl+L`, `Alt+Up`, or `Shift+Tab`.
164
+
165
+ ##### Scenario: Hotkeys listing
166
+ - **WHEN** the user opens `/hotkeys` inside an A1 tab
167
+ - **THEN** a Tabs section SHALL list the effective tab shortcuts
168
+
169
+ ##### Scenario: Collision with a user binding
170
+ - **WHEN** a user keybinding assigns `Alt+A` to an A1 editor action
171
+ - **THEN** launch SHALL report the conflict rather than dispatch the key ambiguously
172
+
173
+ ## Capability: `resident-terminal-host`
174
+
175
+ ### Purpose
176
+
177
+ Defines the opt-in resident capability (Windows x64, Linux x64, macOS arm64) that keeps bare-A1 tabs alive independently of any terminal: the native resident server, per-tab session holders, and attach client, together with their protocols, controller attribution, durable registry, writer authority, derived credentials, detachment, crash/reboot recovery, limits, diagnostics, and preview certification.
178
+
179
+ ### ADDED Requirements
180
+
181
+ #### Requirement: One authoritative resident server serves each user profile
182
+ A1 SHALL run at most one authoritative resident terminal-host server per operating-system user and canonical A1 profile root. Its endpoint SHALL be derived from the canonical profile home and runtime directory, SHALL be independent of the release cohort, and SHALL honor hermetic overrides. The endpoint SHALL provide discovery, while an owner-only operating-system exclusive registry-writer lease SHALL provide mutation authority. A starting server that completes a handshake with a live server SHALL exit as already running and its caller SHALL join the winner. After a failed handshake, the starter SHALL verify and terminate the recorded native owner before acquiring the released lease; if ownership or lease acquisition cannot be verified, startup SHALL fail closed. A server SHALL mutate the registry or remove its endpoint/marker only while it holds the lease and the durable epoch remains current. The server SHALL execute no A1, Pi, or extension code and SHALL own no pseudoterminal.
183
+
184
+ ##### Scenario: Two launches race
185
+ - **WHEN** two bare `a1` invocations of one profile start concurrently with no server running
186
+ - **THEN** exactly one server SHALL bind and both clients SHALL attach to it
187
+
188
+ ##### Scenario: Stale endpoint with verified owner
189
+ - **WHEN** the endpoint does not answer and its recorded native owner verifies
190
+ - **THEN** the starter SHALL terminate that exact owner, acquire its released writer lease, increment the epoch, and only then reclaim the endpoint
191
+
192
+ ##### Scenario: Stale endpoint with unverifiable owner
193
+ - **WHEN** the endpoint does not answer but its recorded owner or writer lease cannot be verified
194
+ - **THEN** A1 SHALL report recovery blocked and SHALL NOT start a second writer
195
+
196
+ ##### Scenario: Different profiles
197
+ - **WHEN** bare A1 runs with two different profile roots
198
+ - **THEN** each SHALL have its own server, registry, and tabs without cross-visibility
199
+
200
+ #### Requirement: Each tab is owned by its own session holder
201
+ Each tab SHALL be owned by exactly one native session holder process that creates and owns that tab's pseudoterminal (ConPTY on Windows), child process tree, and retained libghostty-vt terminal model with bounded scrollback, and that encodes input for the child's current terminal modes. Holders SHALL keep parsing child output whether or not any client views the tab. A holder exit SHALL affect only its tab. A server exit SHALL NOT terminate holders, their children, or their retained models. At most one live tab SHALL own a given Pi session file.
202
+
203
+ ##### Scenario: Server killed
204
+ - **WHEN** the server process is killed while tabs stream
205
+ - **THEN** every holder, child process, and retained screen SHALL continue unaffected
206
+
207
+ ##### Scenario: Holder panics
208
+ - **WHEN** one holder fails on malformed output
209
+ - **THEN** only its tab SHALL enter crash recovery and other tabs SHALL continue
210
+
211
+ ##### Scenario: Open a held session
212
+ - **WHEN** a session file already owned by a live tab is selected
213
+ - **THEN** A1 SHALL focus that tab and SHALL NOT start a second tab on the file
214
+
215
+ #### Requirement: Resident processes start outside terminal containment
216
+ The server and every holder SHALL be started through an authenticated fixed-role native resident-launch path outside the launching terminal's console and launch-instance containment. The path SHALL verify the immutable terminal-host artifact, requested role, canonical profile and request authority, SHALL NOT accept arbitrary executable/argv escape requests, and SHALL NOT enable job-wide or silent breakaway on ordinary launch-instance or tab-child jobs. On Windows it SHALL support bounded native creation outside foreign kill-on-close jobs, including WMI where necessary; on macOS and Linux it SHALL start resident roles in a new session without a controlling terminal so terminal close and hang-up do not reach them, and on macOS it SHALL keep them in the user's per-user bootstrap namespace. It and SHALL verify resulting process identity and containment before announcing resident readiness. It SHALL record the observed mode and failures. When survival cannot be established, A1 SHALL use direct fallback with one notice and preserve existing records rather than claim persistence. This lifecycle boundary SHALL NOT claim to sandbox malicious same-user code.
217
+
218
+ ##### Scenario: Close Windows Terminal
219
+ - **WHEN** the Windows Terminal window running bare `a1` is closed
220
+ - **THEN** the server, holders, and tab processes SHALL keep running and a later `a1` SHALL reattach
221
+
222
+ ##### Scenario: Close a macOS or Linux terminal or lose SSH
223
+ - **WHEN** the terminal or SSH session running bare `a1` on macOS or Linux closes or hangs up
224
+ - **THEN** the server, holders, and tab processes SHALL keep running and a later `a1` SHALL reattach
225
+
226
+ ##### Scenario: Launch inside a kill-on-close job
227
+ - **WHEN** bare `a1` starts inside a job that kills its processes on close, such as a Windows OpenSSH session
228
+ - **THEN** the server SHALL start outside that job and survive the session's end, or A1 SHALL refuse resident readiness and use the direct fallback with a notice
229
+
230
+ ##### Scenario: Ordinary descendants stay contained
231
+ - **WHEN** an ordinary process in the bare-A1 launch instance or a tab-child tree tries to leave its containment, such as `CREATE_BREAKAWAY_FROM_JOB` on Windows
232
+ - **THEN** A1 SHALL NOT grant escape, and a normal contained child SHALL still terminate with its owning tree
233
+
234
+ ##### Scenario: Resident launch request names an arbitrary executable
235
+ - **WHEN** a request supplies an unapproved executable, role, profile or request identity to the resident-launch path
236
+ - **THEN** native admission SHALL reject it without spawning a process
237
+
238
+ ##### Scenario: Contained client requests server recovery
239
+ - **WHEN** the server dies while a verified attach client remains in its ordinary kill-on-close job
240
+ - **THEN** the authorized native recovery path SHALL start a verified replacement outside that job without broadening the client's job permissions
241
+
242
+ #### Requirement: The native binary owns the complete terminal data path
243
+ Pseudoterminal output, child input, retained terminal state, input encoding, composition, and outer-terminal writes SHALL remain inside the native terminal-host binary's attach, server, and holder roles. Node SHALL NOT read, relay, parse, or render tab terminal bytes. The attach client SHALL answer no terminal queries on a child's behalf; the holder's model SHALL answer them. The attach client SHALL compose the strip row and the viewed tab's surface, SHALL offset mouse coordinates by the strip, SHALL forward clipboard writes, hyperlinks, and cursor shape from the child, SHALL NOT forward bells, and SHALL restore every outer terminal mode it enabled when it detaches or fails.
244
+
245
+ ##### Scenario: Child enables enhanced keyboard reporting
246
+ - **WHEN** an A1 tab enables an enhanced keyboard protocol and the outer terminal supports it
247
+ - **THEN** keys SHALL reach the child encoded for its mode and tab shortcuts SHALL still be intercepted
248
+
249
+ ##### Scenario: Attach client crashes
250
+ - **WHEN** the attach client exits abnormally
251
+ - **THEN** the outer terminal SHALL be restored by the surviving-owner path even when forced termination prevents in-process fatal hooks, and every tab SHALL continue
252
+
253
+ #### Requirement: Host topology mutations are revisioned and atomic
254
+ Client/server topology messages SHALL use the generation-1 protocol established by `resident-tabs-contracts`. A topology subscription SHALL begin with one complete snapshot and monotonic revision, followed by ordered changes. Every create, rename, reorder, close, retry, fresh-start, and stop-all mutation SHALL carry its expected topology or registry revision and SHALL either commit completely at the next revision or be rejected without a partial change. A method absent from an older same-generation server SHALL disable only that operation.
255
+
256
+ ##### Scenario: Two clients mutate one revision
257
+ - **WHEN** two clients submit topology mutations against the same expected revision
258
+ - **THEN** at most one SHALL commit, the stale mutation SHALL receive a typed revision conflict, and every client SHALL converge on the committed topology
259
+
260
+ ##### Scenario: Newer client calls an unavailable method
261
+ - **WHEN** a newer same-generation client attaches to an older server that lacks one optional topology method
262
+ - **THEN** attachment and unrelated operations SHALL remain available while only that method is disabled
263
+
264
+ #### Requirement: Reattach renders from retained terminal state
265
+ Viewing a tab SHALL deliver a complete retained surface of cells, attributes, hyperlinks, cursor, and modes, followed by patches against its revision. Output produced while no client viewed the tab SHALL be present because the holder's model absorbed it. Logs or replayed byte streams SHALL NOT be used to reconstruct a screen. Only viewed tabs SHALL stream surfaces to a client; status and attention SHALL stream for all tabs.
266
+
267
+ ##### Scenario: Reattach after hours detached
268
+ - **WHEN** a client views a tab that produced output for hours while detached
269
+ - **THEN** it SHALL render the tab's current screen immediately without replaying the history
270
+
271
+ #### Requirement: The tab bridge reports structured A1 state and controller identity
272
+ Each A1 tab process SHALL receive a derived per-tab/per-incarnation credential and SHALL connect an authenticated bridge to the server that reports sequenced status from engine events, the Pi session file and name, whether its last prompt was interrupted, and semantic requests. Before terminal input from a new controller is accepted, the holder and child SHALL establish a causal input-admission boundary covering previously accepted input in native, PTY, and child buffers and acknowledge the new owner. A sideband marker acknowledgement alone SHALL NOT be treated as proof of ordering across channels. Client-scoped requests SHALL retain immutable controller identity/revision captured at command admission and SHALL be rejected when stale or ambiguous, never rebound to the controller current at execution. The server SHALL send visibility and rename notifications through the bridge, and A1 SHALL reduce animation work while hidden. Bridge messages SHALL NOT carry prompt, transcript, or terminal input content. The child SHALL consume bridge credentials into private memory and remove them from inherited environments before extension loading or descendant spawn; reconnect SHALL NOT restore them to the environment. A missing bridge SHALL degrade status and disable client-scoped child requests without breaking terminal input or attach-local detach.
273
+
274
+ ##### Scenario: Pending extension request
275
+ - **WHEN** an extension in a tab opens a confirmation
276
+ - **THEN** the bridge SHALL report needs-input until it is answered
277
+
278
+ ##### Scenario: Bridge unavailable
279
+ - **WHEN** a tab's bridge cannot connect
280
+ - **THEN** the tab SHALL keep running with process-level status, terminal input and attach-local actions, while client-scoped child requests remain disabled
281
+
282
+ ##### Scenario: Buffered command crosses controller transfer
283
+ - **WHEN** an old controller's command remains buffered while a new controller is acknowledged
284
+ - **THEN** its request SHALL retain the old generation or be rejected as ambiguous, SHALL NOT acquire the new identity, and SHALL affect neither client after the old generation is superseded
285
+
286
+ #### Requirement: The tab registry is durable and lease-protected
287
+ The server SHALL write the per-profile registry only while holding the owner-only OS-exclusive writer lease and current durable epoch. Every mutation SHALL recheck that authority and commit through a temporary file, write-capable file sync, atomic rename, and directory sync before acknowledgement. The registry SHALL record each tab's identity, kind, display name and name source, order, cwd, session location, desired state, lifecycle, attention and seen positions, verified holder identity/incarnation/release, controller revision, credential-derivation inputs, restart budget, last exit, registry revision, epoch, and boot identity, and SHALL retain bounded history generations. It SHALL NOT store derived credentials, environment values, prompt text, or terminal content. An unreadable registry SHALL be quarantined, the last good generation loaded, and a notice shown; if existing state has no valid recoverable generation, recovery SHALL fail closed with preserved files rather than initialize an empty registry; persistent write failure SHALL preserve live observed state in memory, reject new durable mutations without acknowledging success, and report degraded health. A failed mutation SHALL NOT become a committed revision merely because it exists in memory.
288
+
289
+ ##### Scenario: Server killed right after a rename
290
+ - **WHEN** a rename is acknowledged and the server is then killed
291
+ - **THEN** the next server SHALL present the new name
292
+
293
+ ##### Scenario: Corrupt registry
294
+ - **WHEN** the registry cannot be parsed
295
+ - **THEN** the server SHALL quarantine it, load the last good generation, and name both in a notice
296
+
297
+ ##### Scenario: No valid registry history remains
298
+ - **WHEN** an existing registry and all retained generations fail validation
299
+ - **THEN** startup SHALL report blocked recovery, preserve the evidence, and SHALL NOT overwrite it with an empty tab set
300
+
301
+ #### Requirement: Credentials survive server replacement without entering the registry
302
+ Clients SHALL authenticate with a random owner-only client token. One random owner-only profile secret stored outside the registry SHALL derive holder and bridge credentials from tab identity and process incarnation. A replacement server SHALL reproduce the expected credential from the secret and recorded non-secret inputs, then also verify pid and native start identity before admission. Endpoint, token, secret, lease, registry, journal, and recovery-file access SHALL be restricted to the owning user. The server SHALL adopt, signal, or terminate a process only after verifying credential, recorded native identity, incarnation, and current epoch, and SHALL leave unverifiable processes untouched and reported.
303
+
304
+ ##### Scenario: Process identifier reuse
305
+ - **WHEN** a recorded holder identifier now belongs to an unrelated process
306
+ - **THEN** the server SHALL NOT adopt or terminate it and SHALL treat the tab's holder as gone
307
+
308
+ ##### Scenario: Another local user connects
309
+ - **WHEN** a process of another operating-system user connects
310
+ - **THEN** endpoint access control SHALL refuse it
311
+
312
+ #### Requirement: Updates retain the active resident cohort
313
+ Installing or activating a release SHALL NOT terminate the server, holders, or tab processes. Resident binaries and tab processes SHALL run from immutable release directories, and every release used by a live verified resident process SHALL be retained. In this version a same-generation newer client MAY attach with unsupported optional operations disabled, while the existing resident cohort remains on its release until all tabs stop. A generation mismatch SHALL report that the host must be stopped explicitly and SHALL NOT kill or recycle tabs. Automatic endpoint handoff and idle release recycling require a later change.
314
+
315
+ ##### Scenario: Update mid-turn
316
+ - **WHEN** `a1 update` runs while a tab streams
317
+ - **THEN** the turn and resident process identities SHALL remain uninterrupted and their immutable release SHALL remain retained
318
+
319
+ #### Requirement: Resident resources are bounded and observable
320
+ A1 SHALL enforce configurable limits on tab count, concurrent starts, scrollback, and client queues, each with a hard cap. When idle suspension is enabled (default 60 minutes), an idle tab with no pending request, queued input, or viewer SHALL stop its A1 process, show suspended, and resume its session on view or prompt. The server SHALL exit only after ten minutes with no running tabs and no clients. Logs SHALL rotate and SHALL exclude terminal content, prompt text, and credentials. `a1 tabs host status` SHALL report server identity, build, generation, detachment mode, tab count, and log locations.
321
+
322
+ ##### Scenario: Idle suspension
323
+ - **WHEN** an unviewed idle tab reaches the suspension interval
324
+ - **THEN** its A1 process SHALL stop, its chip SHALL show suspended, and viewing it SHALL resume the session with no lost transcript
325
+
326
+ #### Requirement: Resident tabs have non-interactive maintenance commands
327
+ A1 SHALL provide `a1 tabs` to list tabs with identity, name, status, and cwd; `a1 tabs stop <id>` and `a1 tabs stop --all`; `a1 tabs host status` and `a1 tabs host stop`, which stops tabs gracefully before the server; and `a1 tabs doctor`, which creates a bounded redacted diagnostic bundle. These commands SHALL NOT start an interactive runtime, SHALL NOT start a server merely to report that none runs, and SHALL fail concisely with nonzero status on invalid arguments.
328
+
329
+ ##### Scenario: List with no server
330
+ - **WHEN** the user runs `a1 tabs` and no server runs
331
+ - **THEN** A1 SHALL report no running tabs and SHALL NOT start a server
332
+
333
+ #### Requirement: Preview support is packaged, opt-in, certified, and reversible
334
+ The terminal-host binary SHALL ship for Windows x64, Linux x64, and macOS arm64 with artifact hashes, pinned source provenance, licenses, notices, and immutable-release placement verified before execution. `residentTabs` SHALL remain `false` by default on every platform in this change and SHALL be accepted as an opt-in preview on each platform only after exact-package automated suites and manual or isolated-worker physical evidence on that platform for terminal closure, remote-session loss, input fidelity, extension text UI, recovery, and rendering. Physical automation SHALL NOT run on an active workstation. When the setting is false, the platform unsupported, or the server cannot start safely, bare `a1` SHALL run the direct single-agent owned UI, with one notice for an attempted fallback; registry records and sessions SHALL be preserved. Default-on support on any platform and each additional platform require separate approved changes and evidence.
335
+
336
+ ##### Scenario: Server cannot start
337
+ - **WHEN** the terminal-host binary is missing, unverified, or fails its start budget
338
+ - **THEN** bare `a1` SHALL use the direct single-agent path with one notice, preserving records and applying the shared writer-lease check to any selected session rather than bypassing a live writer
339
+
340
+ ## Capability: `resident-tab-reliability`
341
+
342
+ ### Purpose
343
+
344
+ Defines the remaining reliability verification program that gates preview certification and later default enablement. Milestone 4 delivers crash recovery, liveness/progress supervision, durable recovery data, and diagnostic preservation, but does not implement or certify the `a1 tabs doctor` export; that export remains milestone 6 work.
345
+
346
+ ### ADDED Requirements
347
+
348
+ #### Requirement: Reliability evidence matches the enablement stage
349
+ The server state machine SHALL be implemented independently of I/O and SHALL be exercised by deterministic simulation and property tests that inject arbitrary interleavings of process death, message loss, reordering, delay, stale epochs, controller transfer, client churn, and mutations, asserting that no committed mutation is lost, only one registry writer exists, no session gains two live tabs, client-scoped requests remain attributable, and every desired-running tab converges to running or failed. Every persistence and IPC step SHALL expose a failure-injection point exercised by crash-point tests. Protocol decoders and surface encoders SHALL be fuzzed, and bounded chaos/fault-injection suites on each platform SHALL gate the opt-in preview. Implementation SHALL progress through contracts and platform primitives, one persistent tab, failure isolation, crash recovery, complete UX, and packaged certification, each delivered as its own change behind `residentTabs: false`, with evidence at each milestone before dependent behavior is enabled. Intermediate demonstrations SHALL NOT count as shipping acceptance. Historical v2/herdr results, Unix-only tests, and pending 2×2 proof records SHALL NOT substitute for exact-package resident evidence on each platform.
350
+
351
+ Before resident tabs may default on for a platform, a separately authorized isolated-worker soak on that platform of at least 24 hours SHALL exercise ten tabs under high-rate output and random termination of servers, holders, tab processes, and clients, controller and resize churn, blocked writes, pseudoterminal creation hangs, and rename denial. It SHALL assert zero lost journaled prompts, zero lost committed entries, zero orphaned processes, zero duplicate tabs, bounded memory and handle growth, reattach p95 under 300 ms, tab restart under 3 s, and server recovery under 2 s. Each later platform SHALL earn equivalent implementation and exact-package evidence before enablement; evidence SHALL NOT be inferred across platforms.
352
+
353
+ ##### Scenario: Opt-in preview changes resident code
354
+ - **WHEN** the preview remains disabled by default
355
+ - **THEN** deterministic, crash-point, fuzz, bounded chaos, and exact-package physical evidence SHALL be required without claiming that the later 24-hour default-on gate has passed
356
+
357
+ ##### Scenario: Prototype evidence is available
358
+ - **WHEN** a reference prototype has a passing benchmark or another platform's detach tests pass
359
+ - **THEN** A1's resident milestone and physical verdict on each platform SHALL remain unproven until its own exact-artifact evidence is recorded
360
+
361
+ ##### Scenario: Default-on soak detects a leak
362
+ - **WHEN** the authorized 24-hour soak observes handle or memory growth beyond the declared bound
363
+ - **THEN** default enablement SHALL remain blocked until the growth is fixed or the bound is explicitly re-justified in a later approved plan
364
+
365
+ ##### Scenario: Simulation finds a duplicate start
366
+ - **WHEN** a simulated interleaving produces two live incarnations for one tab
367
+ - **THEN** the test SHALL fail with the minimized event sequence
368
+
369
+ ## Capability: `a1-shell`
370
+
371
+ ### MODIFIED Requirements
372
+
373
+ #### Requirement: Interactive launch forms use the owned Pi UI pipeline
374
+ Bare `a1` SHALL launch the A1-owned product surface directly. Explicit prerelease `a1 pi` SHALL use the same owned rendering and input pipeline with A1-specific surfaces withheld and Pi's ordinary user profile selected. Profile selection SHALL NOT introduce transparent child attachment, a PTY, a terminal parser, a byte relay, or a second rendering path. The redundant `a1 ui` route SHALL NOT be exposed. On a supported platform (Windows x64, Linux x64, macOS arm64), when the opt-in `residentTabs` setting is enabled, bare `a1` SHALL instead run the native terminal-host attach client over resident tabs, each of which SHALL run the same owned product UI in its own holder-owned pseudoterminal; pseudoterminals, terminal models, and composition SHALL exist only inside the resident terminal-host capability, and `a1 pi` SHALL retain its direct presentation without resident infrastructure. Direct and Pi-comparison runtimes SHALL share only the canonical session-writer admission guard with resident runtimes; this guard SHALL NOT initialize a terminal host. This change SHALL leave `residentTabs` disabled by default and SHALL leave unsupported platforms on the direct owned path.
375
+
376
+ ##### Scenario: Launch bare A1
377
+ - **WHEN** the user runs `a1`
378
+ - **THEN** A1 SHALL start the owned product UI without requiring a profile argument
379
+
380
+ ##### Scenario: Launch after a prior exit
381
+ - **WHEN** the user runs bare A1 after a previous owned foreground session exited
382
+ - **THEN** with resident tabs disabled A1 SHALL start a fresh owned session without replaying the prior retained terminal surface
383
+ - **AND** with resident tabs enabled A1 SHALL reattach to the running tabs and present their current retained surfaces
384
+
385
+ ##### Scenario: Launch bare A1 with resident tabs
386
+ - **WHEN** the user runs `a1` on a supported platform with resident tabs explicitly enabled
387
+ - **THEN** every tab SHALL run the owned product UI, and Node SHALL NOT read, relay, or render tab terminal bytes
388
+
389
+ ##### Scenario: Resident tabs are not enabled
390
+ - **WHEN** the setting remains at its default or the platform is unsupported
391
+ - **THEN** bare A1 SHALL use the direct single-agent owned path and SHALL NOT start the resident host
392
+
393
+ ##### Scenario: Launch the Pi comparison
394
+ - **WHEN** the user runs prerelease `a1 pi`
395
+ - **THEN** A1 SHALL use the shared owned pipeline with product surfaces withheld and Pi's ordinary profile selected
396
+
397
+ ##### Scenario: Request the removed development alias
398
+ - **WHEN** the user runs `a1 ui`
399
+ - **THEN** A1 SHALL reject the unsupported profile and SHALL NOT silently select another runtime
400
+
401
+ #### Requirement: Interactive launch forms share one non-detachable instance boundary
402
+ The immutable interactive launcher SHALL establish the same non-detachable launch-instance ownership boundary before selecting bare `a1` or prerelease `a1 pi`. Both forms SHALL retain the shared owned rendering and input pipeline inside that boundary. The lifecycle layer SHALL own process containment and cleanup without reading terminal input, parsing output, reconstructing display state, or selecting a second rendering path. When resident tabs are enabled, bare `a1`'s launch instance SHALL own its attach client and every ordinary descendant that client creates, without enabling job-wide breakaway, while the resident server, session holders, and tab processes SHALL belong to the explicit resident terminal-host capability.
403
+
404
+ ##### Scenario: Launch owned A1
405
+ - **WHEN** the shell selects bare `a1` with resident tabs disabled or unsupported
406
+ - **THEN** the owned product UI and every process it creates SHALL belong to that command's launch instance
407
+
408
+ ##### Scenario: Launch owned A1 with resident tabs
409
+ - **WHEN** the shell selects bare `a1` while resident tabs are enabled
410
+ - **THEN** the attach client SHALL belong to that command's launch instance
411
+ - **AND** the resident server, holders, and tab processes SHALL be started only through the explicit resident capability and SHALL NOT be members of the launch instance
412
+
413
+ ##### Scenario: Launch the Pi comparison
414
+ - **WHEN** the shell selects prerelease `a1 pi`
415
+ - **THEN** the owned comparison UI and every process it creates SHALL belong to that command's launch instance without changing the shared rendering pipeline
416
+
417
+ ##### Scenario: Another instance is active
418
+ - **WHEN** the shell launches while one or more interactive instances already exist
419
+ - **THEN** it SHALL create another independent instance rather than acquiring a product-wide foreground slot
420
+
421
+ ## Capability: `launch-instance-lifecycle`
422
+
423
+ ### MODIFIED Requirements
424
+
425
+ #### Requirement: A launch instance owns its complete runtime process tree
426
+ A launch instance SHALL own its selected root runtime and every agent, extension, tool, daemon, helper, and descendant process created within its declared containment boundary. Default interactive instances SHALL be non-detachable; a process that must survive instance closure requires a separately specified explicit resident capability. The resident terminal host is that explicit capability: its server and session holders SHALL be started only through the authenticated fixed-role native resident-launch path, SHALL be owned and cleaned up by the resident capability rather than by any launch instance, and SHALL NOT expose a generic escape service to other components. Ordinary launch-instance and tab-child jobs SHALL NOT enable job-wide or silent breakaway; native admission SHALL verify artifact, role, profile and request authority before resident creation. This lifecycle boundary SHALL NOT claim to sandbox malicious same-user code.
427
+
428
+ ##### Scenario: Runtime starts descendants
429
+ - **WHEN** an owned UI or Pi runtime starts extension daemons, agent workers, tools, or further descendants
430
+ - **THEN** those processes SHALL remain members of the originating launch instance and SHALL NOT become unowned background runtime processes
431
+
432
+ ##### Scenario: A component requests implicit detachment
433
+ - **WHEN** an instance-owned component attempts to survive the closure of its originating instance without an explicit resident capability
434
+ - **THEN** A1 SHALL retain it within terminate-on-close ownership rather than silently detaching it
435
+
436
+ ##### Scenario: Resident tabs outlive a bare-A1 instance
437
+ - **WHEN** a bare-A1 launch instance with resident tabs enabled closes normally or through terminal loss
438
+ - **THEN** A1 SHALL terminate that instance's attach-client process tree and SHALL leave the resident server, holders, and tab processes running
439
+
440
+ ##### Scenario: Processes started inside a tab
441
+ - **WHEN** A1 running in a resident tab starts tools or extension subprocesses
442
+ - **THEN** those processes SHALL belong to that tab's holder-owned process tree and SHALL be terminated when the tab is stopped
443
+
444
+ ##### Scenario: Ordinary descendant requests job breakaway
445
+ - **WHEN** a tool or helper requests `CREATE_BREAKAWAY_FROM_JOB` inside an ordinary A1-owned job
446
+ - **THEN** A1 SHALL NOT have enabled a job-wide escape permission for it, and an ordinary contained spawn SHALL remain terminate-on-close
447
+
448
+ ##### Scenario: Forced attach termination
449
+ - **WHEN** an attach client is killed without running its own cleanup hooks
450
+ - **THEN** the surviving terminal-restoration owner SHALL restore the invoking terminal, while guardians remain lifecycle-only and resident tabs continue
451
+
452
+ #### Requirement: Explicit session selection belongs to the originating launch instance
453
+ A supported session launch SHALL carry its validated target and effective session-directory selection intact through release selection, bootstrap, containment, and owned runtime startup. A supported retry or handoff SHALL preserve that same selection. Launch metadata SHALL remain per invocation, SHALL NOT become a supervisor-wide default or leak through inherited stale session metadata, and SHALL NOT require terminal parsing or shell command evaluation. Session launch failures SHALL retain the existing instance cleanup guarantees. When resident tabs are enabled, a bare-A1 session launch SHALL deliver its selection to the resident server, which SHALL open it as a tab or focus the tab already holding it.
454
+
455
+ ##### Scenario: Launch an explicit session through an immutable release
456
+ - **WHEN** the installed command selects a persisted session and launches an approved immutable release
457
+ - **THEN** the contained owned runtime SHALL receive the same target and directory selection rather than start a fresh session
458
+
459
+ ##### Scenario: Retry the launch path
460
+ - **WHEN** a supported launch retry or release handoff occurs after session selection
461
+ - **THEN** the replacement launch attempt SHALL preserve the original selection
462
+
463
+ ##### Scenario: Resume two distinct sessions concurrently
464
+ - **WHEN** separate invocations select different saved sessions using the same profile and supervisor
465
+ - **THEN** each owned runtime SHALL receive only its invocation's selection and closing one SHALL leave the other active
466
+
467
+ ##### Scenario: Start bare A1 after a resume invocation
468
+ - **WHEN** a bare launch follows an explicit resume launch or inherits unrelated session metadata from its parent environment
469
+ - **THEN** it SHALL NOT reuse the previous selection implicitly
470
+ - **AND** with resident tabs disabled it SHALL start a fresh session, while with resident tabs enabled it SHALL reattach to the existing tabs or create one fresh tab when none exist
471
+
472
+ ##### Scenario: Resume fails after containment starts
473
+ - **WHEN** target resolution or runtime initialization fails within an owned launch instance
474
+ - **THEN** the failure SHALL propagate to the invoking command and the instance's processes SHALL be cleaned up without affecting other instances
475
+
476
+ ##### Scenario: Select a session held by a resident tab
477
+ - **WHEN** resident tabs are enabled and `a1 --session <id>` names a session already owned by a live resident tab
478
+ - **THEN** A1 SHALL focus that tab and SHALL NOT open the session in a second tab
479
+
480
+ ## Capability: `launch-profiles`
481
+
482
+ ### MODIFIED Requirements
483
+
484
+ ## Capability: `cli-session-resume`
485
+
486
+ ### MODIFIED Requirements
487
+
488
+ #### Requirement: Normal A1 accepts explicit session selection
489
+ Stable and prerelease builds SHALL support `a1 --session <path|id>` with an optional `--session-dir <dir>` before or after `--session`. Each option SHALL occur at most once and require a nonempty value. `--session-dir` alone, missing values, duplicate options, unknown trailing options, and extra positional arguments in this recognized grammar SHALL fail with a focused diagnostic and nonzero exit status before supervisor or interactive startup. Help SHALL list the supported forms. With resident tabs disabled, bare `a1` SHALL continue to start a fresh session. With resident tabs enabled, bare `a1` SHALL reattach to the profile's resident tabs, creating one fresh tab only when none exist, and a session launch SHALL open the selected session as a new tab or focus the tab already holding it. Every A1-owned session launch and in-runtime session switch on a supported platform SHALL honor the shared canonical session-writer lease, including direct/fallback launches with resident tabs disabled. A direct conflict SHALL fail safely or offer an explicit fork, not silently attach, overwrite, or start another writer. Failed switches SHALL preserve the old session and its lease; direct lease checks SHALL NOT initialize a resident host.
490
+
491
+ ##### Scenario: Select an existing session by ID
492
+ - **WHEN** the user supplies `a1 --session <id>` for a saved A1 session
493
+ - **THEN** A1 SHALL execute an interactive session launch rather than return a silent successful no-op
494
+
495
+ ##### Scenario: Supply a custom directory in either order
496
+ - **WHEN** the user supplies one valid `--session` and one valid `--session-dir` in either order
497
+ - **THEN** both invocations SHALL select the same target and effective session directory
498
+
499
+ ##### Scenario: Malformed session launch
500
+ - **WHEN** a recognized session launch has a missing or empty value, duplicate option, unrecognized additional option, extra argument, or no `--session` target
501
+ - **THEN** A1 SHALL report one concise error, exit nonzero, and start no supervisor or interactive runtime
502
+
503
+ ##### Scenario: Inspect help without launching
504
+ - **WHEN** the user runs `a1 --help` or `a1 -h`
505
+ - **THEN** help SHALL include both supported session-selection forms without launching an interactive runtime
506
+
507
+ ##### Scenario: Bare launch with resident tabs running
508
+ - **WHEN** resident tabs are enabled, two tabs are running, and the user runs bare `a1`
509
+ - **THEN** A1 SHALL show both tabs and SHALL NOT create a third tab
510
+
511
+ ##### Scenario: Session launch with resident tabs running
512
+ - **WHEN** resident tabs are enabled and the user runs `a1 --session <id>` for a session no participating writer holds
513
+ - **THEN** A1 SHALL acquire its lease, add a tab resuming that session alongside the existing tabs, and activate it
514
+
515
+ ##### Scenario: Disable tabs while a selected session remains live
516
+ - **WHEN** the user disables resident tabs and directly selects a session still held by a live tab
517
+ - **THEN** direct launch SHALL report the writer conflict without starting another writer or altering the resident session
518
+
519
+ ##### Scenario: Resume an aliased session
520
+ - **WHEN** a session selected by ID, path, or filesystem alias resolves to the same held file
521
+ - **THEN** admission SHALL consult the same native writer lease rather than create an independent path-string lease
522
+
523
+ ## Capability: `owned-pi-ui-foundation`
524
+
525
+ ### MODIFIED Requirements
526
+
527
+ #### Requirement: Graceful user quit returns control to the parent shell
528
+ The owned interactive UI SHALL treat `/quit` and the second `Ctrl+C` in the existing clear/exit chord as complete graceful-exit requests. Each route SHALL stop the agent session, dispose the owned presentation, restore all terminal modes and screen state owned by A1, terminate the interactive A1 process successfully, and return control to the invoking shell without requiring another signal or keystroke. When the owned UI runs inside a resident tab, the attach client SHALL consume the second `Ctrl+C` of the chord as a local detach request, and `/quit` and `Ctrl+D` SHALL request through the tab bridge that only the client named by the immutable command-origin input-controller revision detach, and only while that revision is current; stale, ambiguous or unavailable attribution SHALL keep the tab process running and direct the user to `Ctrl+C` twice. The tab's agent session and A1 process SHALL keep running, and the detached client SHALL complete terminal restoration and parent-shell return. The built-in quit command's autocomplete description SHALL be exactly `Quit`.
529
+
530
+ ##### Scenario: Quit with the slash command
531
+ - **WHEN** the user submits `/quit` from an active owned interactive session
532
+ - **THEN** A1 SHALL complete graceful shutdown, restore the terminal, exit successfully, and make the invoking shell prompt available
533
+ - **AND** no inactive or blank A1 fullscreen surface SHALL remain
534
+
535
+ ##### Scenario: Quit with the clear/exit chord
536
+ - **WHEN** the user presses `Ctrl+C` twice within the existing clear/exit interval
537
+ - **THEN** the second press SHALL complete the same graceful shutdown, terminal restoration, successful process exit, and parent-shell return as `/quit`
538
+
539
+ ##### Scenario: Quit inside a resident tab
540
+ - **WHEN** the user submits `/quit` or presses `Ctrl+C` twice inside a resident A1 tab
541
+ - **THEN** the attach client SHALL restore the terminal and exit successfully, and the tab's agent session SHALL keep running
542
+ - **AND** `a1 pi` SHALL continue to stop its single agent session on quit
543
+
544
+ ##### Scenario: Resident tab bridge is unavailable
545
+ - **WHEN** a quit route runs inside a resident tab whose bridge is unavailable
546
+ - **THEN** A1 SHALL NOT exit the tab process and SHALL show a concise notice that pressing `Ctrl+C` twice leaves
547
+
548
+ ##### Scenario: Quit execution is delayed across control transfer
549
+ - **WHEN** a quit command admitted under an old controller executes after control transfers
550
+ - **THEN** A1 SHALL reject its stale or ambiguous origin without detaching the new controller or exiting the tab, and SHALL offer attach-local double-`Ctrl+C` as the safe exit route
551
+
552
+ ##### Scenario: An extension retains an event-loop handle
553
+ - **WHEN** owned UI cleanup has completed but a loaded extension leaves a server, timer, or comparable event-loop handle active
554
+ - **THEN** the interactive A1 executable SHALL preserve completed terminal restoration and configured exit output
555
+ - **AND** it SHALL still terminate successfully and return control to the parent shell
556
+
557
+ ##### Scenario: Repository-local quit returns promptly
558
+ - **WHEN** a user quits an interactive A1 session launched through the supported repository-local development command
559
+ - **THEN** development-only cache persistence SHALL NOT introduce a visible post-restoration pause before the parent-shell prompt appears
560
+ - **AND** production compile-cache behavior and completed owned cleanup SHALL remain unchanged
561
+
562
+ ##### Scenario: Describe the quit command
563
+ - **WHEN** slash-command autocomplete presents the built-in `quit` command
564
+ - **THEN** its description SHALL be `Quit`
565
+ - **AND** the description SHALL NOT include `Pi`, `A1`, or another product qualifier
566
+
567
+ ## Capability: `agent-supervision`
568
+
569
+ ### ADDED Requirements
570
+
571
+ #### Requirement: Cohort updates and retention preserve resident tabs
572
+ Cohort update coordination SHALL stop and drain launch instances only. It SHALL NOT terminate the resident terminal-host server, session holders, or tab processes. In this opt-in version a compatible resident cohort remains on its immutable release until all of its tabs stop; automatic server handoff and idle-boundary recycling are deferred. Immutable release retention SHALL treat the recorded release of every live verified resident server, holder, and tab process as current ownership, and SHALL NOT collect that release while any such process uses it. A superseded supervisor cohort SHALL retire according to its own launch-instance work regardless of resident tabs.
573
+
574
+ ##### Scenario: Update with resident tabs running
575
+ - **WHEN** an update activates a new release while resident processes run from the previous release
576
+ - **THEN** supervision SHALL drain the previous cohort's launch instances without terminating resident processes
577
+
578
+ ##### Scenario: Garbage collection with a tab on an old release
579
+ - **WHEN** release cleanup evaluates a release still used by a live verified holder or tab process
580
+ - **THEN** that release SHALL be retained until the process is recycled or stopped