@timurproko/a1 0.2.7-dev.767 → 0.2.7-dev.779
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.
- package/README.md +30 -0
- package/bin/cli.js +4 -0
- package/bin/tab-launch-context.d.ts +3 -0
- package/bin/tab-launch-context.js +52 -3
- package/bin/ui.js +6 -3
- package/dist/app/session-shell/session-shell-root.d.ts +2 -1
- package/dist/app/session-shell/session-shell-root.js +2 -2
- package/dist/app/session-shell/session-shell.js +4 -8
- package/dist/app/session-shell/shell-host.d.ts +2 -0
- package/dist/app/session-shell/shell-host.js +20 -1
- package/dist/cli/dispatch.d.ts +11 -1
- package/dist/cli/dispatch.js +79 -5
- package/dist/cli/tabs-request.d.ts +7 -0
- package/dist/cli/tabs-request.js +1 -0
- package/dist/cli/tabs.d.ts +14 -0
- package/dist/cli/tabs.js +140 -0
- package/dist/composition/owned-ui.d.ts +8 -2
- package/dist/composition/owned-ui.js +109 -12
- package/dist/features/launch/index.d.ts +1 -1
- package/dist/features/launch/intent.d.ts +3 -1
- package/dist/features/launch/intent.js +7 -4
- package/dist/features/resident-tab/auto-name.d.ts +11 -0
- package/dist/features/resident-tab/auto-name.js +42 -0
- package/dist/features/resident-tab/index.d.ts +3 -0
- package/dist/features/resident-tab/index.js +3 -0
- package/dist/features/resident-tab/shortcuts.d.ts +10 -0
- package/dist/features/resident-tab/shortcuts.js +35 -0
- package/dist/features/resident-tab/status-deriver.d.ts +9 -0
- package/dist/features/resident-tab/status-deriver.js +15 -0
- package/dist/foundation/launch-context/index.d.ts +4 -0
- package/dist/foundation/launch-context/index.js +10 -0
- package/dist/foundation/release/bootstrap.d.ts +4 -2
- package/dist/foundation/release/bootstrap.js +11 -8
- package/dist/foundation/release/cohort-state.d.ts +1 -1
- package/dist/foundation/release/cohort-state.js +1 -1
- package/dist/foundation/release/release-gc.d.ts +3 -0
- package/dist/foundation/release/release-gc.js +44 -8
- package/dist/foundation/resident-tabs/bounded-host-command.d.ts +16 -0
- package/dist/foundation/resident-tabs/bounded-host-command.js +35 -0
- package/dist/foundation/resident-tabs/bridge-client.d.ts +18 -3
- package/dist/foundation/resident-tabs/bridge-client.js +87 -7
- package/dist/foundation/resident-tabs/doctor.d.ts +29 -0
- package/dist/foundation/resident-tabs/doctor.js +166 -0
- package/dist/foundation/resident-tabs/ensure-terminal-host.d.ts +2 -1
- package/dist/foundation/resident-tabs/ensure-terminal-host.js +33 -7
- package/dist/foundation/resident-tabs/index.d.ts +7 -1
- package/dist/foundation/resident-tabs/index.js +4 -1
- package/dist/foundation/resident-tabs/maintenance.d.ts +42 -0
- package/dist/foundation/resident-tabs/maintenance.js +78 -0
- package/dist/foundation/resident-tabs/release-holds.d.ts +27 -0
- package/dist/foundation/resident-tabs/release-holds.js +77 -0
- package/dist/foundation/resident-tabs/routing.d.ts +4 -3
- package/dist/foundation/resident-tabs/routing.js +6 -4
- package/dist/foundation/resident-tabs/settings.d.ts +7 -2
- package/dist/foundation/resident-tabs/settings.js +17 -16
- package/dist/foundation/resident-tabs/terminal-host-artifact.d.ts +18 -0
- package/dist/foundation/resident-tabs/terminal-host-artifact.js +53 -0
- package/dist/foundation/resident-tabs/zip-archive.d.ts +9 -0
- package/dist/foundation/resident-tabs/zip-archive.js +56 -0
- package/dist/foundation/session-writer-lock/index.d.ts +5 -0
- package/dist/foundation/session-writer-lock/index.js +13 -9
- package/dist/integrations/pi/components/shell-footer-status.d.ts +1 -1
- package/dist/integrations/pi/components/shell-footer-status.js +2 -2
- package/dist/integrations/pi/components/shell-hotkey-sections.js +1 -1
- package/dist/integrations/pi/components/shell-presenters-info.d.ts +4 -2
- package/dist/integrations/pi/components/shell-presenters-info.js +38 -4
- package/dist/integrations/pi/components/upstream/components/session-footer.d.ts +2 -1
- package/dist/integrations/pi/components/upstream/components/session-footer.js +7 -4
- package/dist/integrations/pi/engine/adapter.d.ts +1 -0
- package/dist/integrations/pi/engine/adapter.js +3 -0
- package/dist/integrations/pi/engine/prompt-suggestions.d.ts +1 -0
- package/dist/integrations/pi/engine/prompt-suggestions.js +40 -0
- package/dist/native/darwin-arm64/a1_session_lock.node +0 -0
- package/dist/native/darwin-arm64/manifest.json +2 -2
- package/dist/native/darwin-arm64/process-guardian +0 -0
- package/dist/native/darwin-arm64/terminal-host +0 -0
- package/dist/native/darwin-arm64/terminal-host-THIRD-PARTY-NOTICES.txt +10500 -0
- package/dist/native/darwin-arm64/terminal-host.manifest.json +44 -0
- package/dist/native/darwin-x64/a1_session_lock.node +0 -0
- package/dist/native/darwin-x64/manifest.json +20 -0
- package/dist/native/darwin-x64/process-guardian +0 -0
- package/dist/native/darwin-x64/terminal-host +0 -0
- package/dist/native/darwin-x64/terminal-host-THIRD-PARTY-NOTICES.txt +10737 -0
- package/dist/native/darwin-x64/terminal-host.manifest.json +44 -0
- package/dist/native/linux-x64/a1_session_lock.node +0 -0
- package/dist/native/linux-x64/manifest.json +2 -2
- package/dist/native/linux-x64/process-guardian +0 -0
- package/dist/native/linux-x64/terminal-host +0 -0
- package/dist/native/linux-x64/terminal-host-THIRD-PARTY-NOTICES.txt +11226 -0
- package/dist/native/linux-x64/terminal-host.manifest.json +44 -0
- package/dist/native/win32-x64/a1_session_lock.node +0 -0
- package/dist/native/win32-x64/manifest.json +2 -2
- package/dist/native/win32-x64/process-guardian.exe +0 -0
- package/dist/native/win32-x64/terminal-host-THIRD-PARTY-NOTICES.txt +10757 -0
- package/dist/native/win32-x64/terminal-host.exe +0 -0
- package/dist/native/win32-x64/terminal-host.manifest.json +44 -0
- package/dist/ui/settings/declarations.d.ts +19 -43
- package/dist/ui/settings/declarations.js +19 -35
- package/dist/ui/settings/index.d.ts +1 -1
- package/dist/ui/settings/index.js +1 -1
- package/dist/ui/settings/manager.d.ts +1 -0
- package/dist/ui/settings/manager.js +9 -1
- package/dist/ui/settings/migrations.js +12 -0
- package/dist/ui/settings/resolution.d.ts +0 -2
- package/dist/ui/settings/resolution.js +1 -13
- package/dist/ui/settings/sections.js +0 -4
- package/docs/architecture/evidence/resident-tabs/linux-x64.md +37 -0
- package/docs/architecture/evidence/resident-tabs/macos-arm64.md +36 -0
- package/docs/architecture/evidence/resident-tabs/macos-x64.md +35 -0
- package/docs/architecture/evidence/resident-tabs/windows-x64.md +36 -0
- package/docs/architecture/internal-naming.md +2 -0
- package/docs/architecture/process-guardian-provenance.md +2 -0
- package/docs/architecture/resident-tabs-requirements.md +1 -563
- package/docs/architecture/resident-tabs.md +166 -94
- package/docs/architecture/terminal-host-provenance.md +13 -3
- package/docs/architecture/toolchain.md +1 -1
- package/docs/ci-release-runbook.md +2 -2
- package/docs/features/launch-profiles.md +11 -8
- package/docs/manual-resident-tabs-acceptance.md +51 -0
- package/docs/openspec-archive-automation.md +15 -3
- package/docs/validation.md +9 -1
- package/package.json +5 -1
|
@@ -1,255 +1,11 @@
|
|
|
1
1
|
# Resident tabs — target requirements
|
|
2
2
|
|
|
3
|
-
Status:
|
|
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
|
|
3
|
+
Status: one requirement remains outside the delivered milestones. Milestones 1–6 moved every other requirement into their OpenSpec changes, and the canonical specs now hold them. This file keeps only what no milestone has delivered yet; it binds nothing until a later change adopts it. See [`resident-tabs.md`](resident-tabs.md#roadmap).
|
|
172
4
|
|
|
173
5
|
## Capability: `resident-terminal-host`
|
|
174
6
|
|
|
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
7
|
### ADDED Requirements
|
|
180
8
|
|
|
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
9
|
#### Requirement: Host topology mutations are revisioned and atomic
|
|
254
10
|
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
11
|
|
|
@@ -260,321 +16,3 @@ Client/server topology messages SHALL use the generation-1 protocol established
|
|
|
260
16
|
##### Scenario: Newer client calls an unavailable method
|
|
261
17
|
- **WHEN** a newer same-generation client attaches to an older server that lacks one optional topology method
|
|
262
18
|
- **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
|