@timurproko/a1 0.2.7-dev.806 → 0.2.7-dev.809
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/dist/app/session-shell/dialog-coordinator.d.ts +42 -0
- package/dist/app/session-shell/dialog-coordinator.js +133 -0
- package/dist/app/session-shell/dock-chrome.d.ts +34 -0
- package/dist/app/session-shell/dock-chrome.js +109 -0
- package/dist/app/session-shell/exit-notice.d.ts +1 -1
- package/dist/app/session-shell/exit-notice.js +1 -1
- package/dist/app/session-shell/extension-surface.d.ts +30 -0
- package/dist/app/session-shell/extension-surface.js +105 -0
- package/dist/app/session-shell/input-surface-switch.d.ts +36 -0
- package/dist/app/session-shell/input-surface-switch.js +85 -0
- package/dist/app/session-shell/login-interaction.d.ts +27 -0
- package/dist/app/session-shell/login-interaction.js +91 -0
- package/dist/app/session-shell/prompt-submission.d.ts +48 -0
- package/dist/app/session-shell/prompt-submission.js +276 -0
- package/dist/app/session-shell/resident-tab-coordinator.d.ts +41 -0
- package/dist/app/session-shell/resident-tab-coordinator.js +120 -0
- package/dist/app/session-shell/session-concern.d.ts +22 -0
- package/dist/app/session-shell/session-concern.js +29 -0
- package/dist/app/session-shell/session-lifecycle.d.ts +29 -0
- package/dist/app/session-shell/session-lifecycle.js +49 -0
- package/dist/app/session-shell/session-shell-root.d.ts +1 -1
- package/dist/app/session-shell/session-shell-root.js +182 -931
- package/dist/app/session-shell/session-shell.d.ts +2 -8
- package/dist/app/session-shell/session-shell.js +209 -897
- package/dist/app/session-shell/settings-bindings.d.ts +17 -0
- package/dist/app/session-shell/settings-bindings.js +91 -0
- package/dist/app/session-shell/shell-editor-factory.d.ts +27 -0
- package/dist/app/session-shell/shell-editor-factory.js +102 -0
- package/dist/app/session-shell/shell-host.d.ts +6 -0
- package/dist/app/session-shell/shell-host.js +26 -4
- package/dist/app/session-shell/shell-layout.d.ts +64 -0
- package/dist/app/session-shell/shell-layout.js +18 -0
- package/dist/app/session-shell/suggestion-surface.d.ts +25 -0
- package/dist/app/session-shell/suggestion-surface.js +63 -0
- package/dist/app/session-shell/transcript-document.d.ts +78 -0
- package/dist/app/session-shell/transcript-document.js +365 -0
- package/dist/app/session-shell/viewport-layout.d.ts +31 -0
- package/dist/app/session-shell/viewport-layout.js +160 -0
- package/dist/app/session-shell/workflow-output.d.ts +33 -0
- package/dist/app/session-shell/workflow-output.js +174 -0
- package/dist/app/session-shell/workflow-router.d.ts +25 -0
- package/dist/app/session-shell/workflow-router.js +39 -0
- package/dist/composition/owned-ui.d.ts +6 -25
- package/dist/composition/owned-ui.js +48 -242
- package/dist/composition/resident-tab-bridge.d.ts +16 -0
- package/dist/composition/resident-tab-bridge.js +159 -0
- package/dist/composition/session-backend.d.ts +19 -0
- package/dist/composition/session-backend.js +1 -0
- package/dist/composition/session-runtime-registry.d.ts +20 -0
- package/dist/composition/session-runtime-registry.js +85 -0
- package/dist/composition/settings-route-host.d.ts +6 -1
- package/dist/composition/settings-route-host.js +7 -6
- package/dist/composition/startup-route.d.ts +32 -0
- package/dist/composition/startup-route.js +72 -0
- package/dist/features/owned-ui/settings-app.d.ts +4 -1
- package/dist/features/owned-ui/settings-app.js +9 -3
- package/dist/features/resident-tab/shortcut-declarations.js +1 -1
- package/dist/features/resident-tab/status-deriver.d.ts +4 -3
- package/dist/features/resident-tab/status-deriver.js +2 -5
- package/dist/foundation/release/bootstrap.js +2 -2
- package/dist/foundation/resident-tabs/bridge-client.d.ts +1 -1
- package/dist/foundation/resident-tabs/bridge-client.js +2 -1
- package/dist/foundation/resident-tabs/fixture-control.d.ts +7 -0
- package/dist/foundation/resident-tabs/fixture-control.js +35 -0
- package/dist/foundation/resident-tabs/progress-observation.d.ts +7 -0
- package/dist/foundation/resident-tabs/progress-observation.js +119 -0
- package/dist/foundation/terminal-cleanup/index.d.ts +1 -1
- package/dist/foundation/terminal-cleanup/index.js +1 -1
- package/dist/foundation/terminal-cleanup/terminal-reset.d.ts +5 -0
- package/dist/foundation/terminal-cleanup/terminal-reset.js +5 -0
- package/dist/integrations/pi/engine/adapter.d.ts +4 -77
- package/dist/integrations/pi/engine/adapter.js +85 -393
- package/dist/integrations/pi/engine/command-dispatch.d.ts +13 -0
- package/dist/integrations/pi/engine/command-dispatch.js +57 -0
- package/dist/integrations/pi/engine/host.js +2 -2
- package/dist/integrations/pi/engine/ports.d.ts +56 -0
- package/dist/integrations/pi/engine/ports.js +89 -0
- package/dist/integrations/pi/engine/session-runtime.js +5 -2
- package/dist/integrations/pi/engine/view-state.d.ts +42 -0
- package/dist/integrations/pi/engine/view-state.js +126 -0
- package/dist/integrations/pi/tui-runtime/adapter.d.ts +6 -0
- package/dist/integrations/pi/tui-runtime/adapter.js +28 -1
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +11 -0
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +30 -1
- package/dist/native/darwin-arm64/manifest.json +1 -1
- package/dist/native/darwin-arm64/terminal-host.manifest.json +3 -3
- package/dist/native/darwin-arm64/terminal-host.node +0 -0
- package/dist/native/darwin-x64/manifest.json +1 -1
- package/dist/native/darwin-x64/terminal-host.manifest.json +3 -3
- package/dist/native/darwin-x64/terminal-host.node +0 -0
- package/dist/native/linux-x64/manifest.json +1 -1
- package/dist/native/linux-x64/terminal-host.manifest.json +3 -3
- package/dist/native/linux-x64/terminal-host.node +0 -0
- package/dist/native/win32-x64/manifest.json +2 -2
- package/dist/native/win32-x64/process-guardian.node +0 -0
- package/dist/native/win32-x64/terminal-host.manifest.json +3 -3
- package/dist/native/win32-x64/terminal-host.node +0 -0
- package/dist/product-identity.d.ts +2 -2
- package/dist/product-identity.js +2 -2
- package/dist/product-identity.json +6 -0
- package/dist/ui/settings/manager.d.ts +6 -0
- package/dist/ui/settings/manager.js +25 -0
- package/docs/architecture/boundaries.md +14 -0
- package/docs/architecture/resident-tabs.md +23 -18
- package/package.json +2 -1
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
"platform": "win32",
|
|
8
8
|
"architecture": "x64",
|
|
9
9
|
"capability": "supported",
|
|
10
|
-
"builtAt": "2026-10-
|
|
10
|
+
"builtAt": "2026-10-20T08:54:21.248Z",
|
|
11
11
|
"artifact": {
|
|
12
12
|
"filename": "process-guardian.node",
|
|
13
|
-
"sha256": "
|
|
13
|
+
"sha256": "aa4a36d3cb4e7f4cb9157409bbe0215ac467140f5558ca154aaf736f6105ce9b",
|
|
14
14
|
"size": 402432
|
|
15
15
|
},
|
|
16
16
|
"provenance": {
|
|
Binary file
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
"architecture": "x64",
|
|
10
10
|
"target": "x86_64-pc-windows-msvc",
|
|
11
11
|
"capability": "supported",
|
|
12
|
-
"builtAt": "2026-10-
|
|
12
|
+
"builtAt": "2026-10-20T08:58:10.619Z",
|
|
13
13
|
"artifact": {
|
|
14
14
|
"filename": "terminal-host.node",
|
|
15
|
-
"sha256": "
|
|
16
|
-
"size":
|
|
15
|
+
"sha256": "31360962d3614f342891adae1a8f79e65c3b1a323baab396f4a9a0f32afd3d99",
|
|
16
|
+
"size": 6072320
|
|
17
17
|
},
|
|
18
18
|
"entry": {
|
|
19
19
|
"filename": "dist/foundation/resident-tabs/host-entry.js",
|
|
Binary file
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
declare const ENVIRONMENT_KEYS: readonly ["clipboardDiagnostics", "configDir", "dataDir", "databasePath", "developmentInstanceId", "developmentRoot", "endpoint", "exitNoticePath", "paneId", "probeTrace", "processGuardianPath", "prFooterPreview", "profileHome", "runtimeDir", "sessionRuntimeId", "skipVersionCheck", "startupTrace", "suggestionDiagnostics", "tabEndpoint", "tabId", "tabToken", "tabsEndpoint", "terminalHostPath", "terminalSessionId"];
|
|
1
|
+
declare const ENVIRONMENT_KEYS: readonly ["clipboardDiagnostics", "configDir", "dataDir", "databasePath", "developmentInstanceId", "developmentRoot", "endpoint", "exitNoticePath", "paneId", "probeTrace", "processGuardianPath", "prFooterPreview", "profileHome", "residentFixtureControlDir", "residentProgressObservationDir", "residentProgressRunId", "residentProgressTabId", "residentProgressTabIncarnation", "runtimeDir", "sessionRuntimeId", "skipVersionCheck", "startupTrace", "suggestionDiagnostics", "tabEndpoint", "tabId", "tabToken", "tabsEndpoint", "terminalHostPath", "terminalSessionId"];
|
|
2
2
|
declare const FILESYSTEM_KEYS: readonly ["slug", "windowsDirectory", "unixDirectory", "temporaryPrefix"];
|
|
3
3
|
declare const STATE_KEYS: readonly ["windowsControlDirectory", "unixControlDirectory", "developmentDirectory", "piAgentProfile", "piVanillaProfile", "sessionRepositoryDirectory", "sessionWorktreeClaimDirectory"];
|
|
4
4
|
declare const ENDPOINT_KEYS: readonly ["windowsPipeStem", "unixSocketFilename", "metadataFilename", "supervisorLogFilename", "databaseFilename"];
|
|
5
5
|
declare const MANIFEST_KEYS: readonly ["releaseFilename", "packageFilename"];
|
|
6
6
|
declare const PROTOCOL_KEYS: readonly ["namespace", "controlEnvelope", "supervisorSchema", "nativeHostSchema", "structuredAgentSchema", "controlStoreSchema", "promptHistorySchema", "releaseCohortSchema", "updateJournalSchema"];
|
|
7
|
-
declare const EVIDENCE_KEYS: readonly ["nativeSpikeSchema", "terminalProvenanceSchema", "terminalProofSchema", "stableReleaseSchema", "previewReleaseSchema", "releaseCertificationSchema", "previewPlatformVerdictSchema", "piSourceLedgerSchema", "piComponentParitySchema", "piEventFrameParitySchema", "startupTraceSchema", "dependencyLayerSchema", "dependencyLayerCertificationSchema", "runtimePayloadSchema"];
|
|
7
|
+
declare const EVIDENCE_KEYS: readonly ["nativeSpikeSchema", "terminalProvenanceSchema", "terminalProofSchema", "terminalTemporalSnapshotSchema", "stableReleaseSchema", "previewReleaseSchema", "releaseCertificationSchema", "previewPlatformVerdictSchema", "piSourceLedgerSchema", "piComponentParitySchema", "piEventFrameParitySchema", "startupTraceSchema", "dependencyLayerSchema", "dependencyLayerCertificationSchema", "runtimePayloadSchema"];
|
|
8
8
|
declare const ARTIFACT_KEYS: readonly ["cliEntry", "supervisorEntry", "guardianEntry", "uiEntry", "terminalHostAddon", "terminalHostEntry", "nativeCrate", "processGuardianAddon", "releaseTarballStem", "diagnosticStem"];
|
|
9
9
|
type StringRecord<Keys extends readonly string[]> = {
|
|
10
10
|
readonly [Key in Keys[number]]: string;
|
package/dist/product-identity.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import rawIdentity from "./product-identity.json" with { type: "json" };
|
|
2
2
|
const ENVIRONMENT_KEYS = [
|
|
3
3
|
"clipboardDiagnostics", "configDir", "dataDir", "databasePath", "developmentInstanceId", "developmentRoot", "endpoint", "exitNoticePath",
|
|
4
|
-
"paneId", "probeTrace", "processGuardianPath", "prFooterPreview", "profileHome", "runtimeDir", "sessionRuntimeId", "skipVersionCheck", "startupTrace", "suggestionDiagnostics", "tabEndpoint", "tabId", "tabToken", "tabsEndpoint", "terminalHostPath", "terminalSessionId",
|
|
4
|
+
"paneId", "probeTrace", "processGuardianPath", "prFooterPreview", "profileHome", "residentFixtureControlDir", "residentProgressObservationDir", "residentProgressRunId", "residentProgressTabId", "residentProgressTabIncarnation", "runtimeDir", "sessionRuntimeId", "skipVersionCheck", "startupTrace", "suggestionDiagnostics", "tabEndpoint", "tabId", "tabToken", "tabsEndpoint", "terminalHostPath", "terminalSessionId",
|
|
5
5
|
];
|
|
6
6
|
const FILESYSTEM_KEYS = ["slug", "windowsDirectory", "unixDirectory", "temporaryPrefix"];
|
|
7
7
|
const STATE_KEYS = ["windowsControlDirectory", "unixControlDirectory", "developmentDirectory", "piAgentProfile", "piVanillaProfile", "sessionRepositoryDirectory", "sessionWorktreeClaimDirectory"];
|
|
8
8
|
const ENDPOINT_KEYS = ["windowsPipeStem", "unixSocketFilename", "metadataFilename", "supervisorLogFilename", "databaseFilename"];
|
|
9
9
|
const MANIFEST_KEYS = ["releaseFilename", "packageFilename"];
|
|
10
10
|
const PROTOCOL_KEYS = ["namespace", "controlEnvelope", "supervisorSchema", "nativeHostSchema", "structuredAgentSchema", "controlStoreSchema", "promptHistorySchema", "releaseCohortSchema", "updateJournalSchema"];
|
|
11
|
-
const EVIDENCE_KEYS = ["nativeSpikeSchema", "terminalProvenanceSchema", "terminalProofSchema", "stableReleaseSchema", "previewReleaseSchema", "releaseCertificationSchema", "previewPlatformVerdictSchema", "piSourceLedgerSchema", "piComponentParitySchema", "piEventFrameParitySchema", "startupTraceSchema", "dependencyLayerSchema", "dependencyLayerCertificationSchema", "runtimePayloadSchema"];
|
|
11
|
+
const EVIDENCE_KEYS = ["nativeSpikeSchema", "terminalProvenanceSchema", "terminalProofSchema", "terminalTemporalSnapshotSchema", "stableReleaseSchema", "previewReleaseSchema", "releaseCertificationSchema", "previewPlatformVerdictSchema", "piSourceLedgerSchema", "piComponentParitySchema", "piEventFrameParitySchema", "startupTraceSchema", "dependencyLayerSchema", "dependencyLayerCertificationSchema", "runtimePayloadSchema"];
|
|
12
12
|
const ARTIFACT_KEYS = ["cliEntry", "supervisorEntry", "guardianEntry", "uiEntry", "terminalHostAddon", "terminalHostEntry", "nativeCrate", "processGuardianAddon", "releaseTarballStem", "diagnosticStem"];
|
|
13
13
|
const ROOT_KEYS = ["schema", "displayName", "commandName", "packageName", "filesystem", "environment", "state", "endpoint", "manifest", "protocol", "evidence", "artifacts"];
|
|
14
14
|
export function validateProductIdentity(value) {
|
|
@@ -23,6 +23,11 @@
|
|
|
23
23
|
"processGuardianPath": "A1_PROCESS_GUARDIAN_PATH",
|
|
24
24
|
"prFooterPreview": "A1_PR_FOOTER_PREVIEW",
|
|
25
25
|
"profileHome": "A1_PROFILE_HOME",
|
|
26
|
+
"residentFixtureControlDir": "A1_RESIDENT_FIXTURE_CONTROL_DIR",
|
|
27
|
+
"residentProgressObservationDir": "A1_RESIDENT_PROGRESS_OBSERVATION_DIR",
|
|
28
|
+
"residentProgressRunId": "A1_RESIDENT_PROGRESS_RUN_ID",
|
|
29
|
+
"residentProgressTabId": "A1_RESIDENT_PROGRESS_TAB_ID",
|
|
30
|
+
"residentProgressTabIncarnation": "A1_RESIDENT_PROGRESS_TAB_INCARNATION",
|
|
26
31
|
"runtimeDir": "A1_RUNTIME_DIR",
|
|
27
32
|
"sessionRuntimeId": "A1_SESSION_RUNTIME_ID",
|
|
28
33
|
"skipVersionCheck": "A1_SKIP_VERSION_CHECK",
|
|
@@ -70,6 +75,7 @@
|
|
|
70
75
|
"nativeSpikeSchema": "a1-native-host-spike-evidence-v1",
|
|
71
76
|
"terminalProvenanceSchema": "a1-terminal-host-provenance-v1",
|
|
72
77
|
"terminalProofSchema": "a1-terminal-host-proof-v1",
|
|
78
|
+
"terminalTemporalSnapshotSchema": "a1-terminal-temporal-snapshot-v1",
|
|
73
79
|
"stableReleaseSchema": "a1-stable-release-v1",
|
|
74
80
|
"previewReleaseSchema": "a1-preview-release-v1",
|
|
75
81
|
"releaseCertificationSchema": "a1-release-certification-v1",
|
|
@@ -47,6 +47,12 @@ export declare class OwnedSettingsManager {
|
|
|
47
47
|
/** Reads and resolves the product namespace. Never throws: every failure becomes a notice. */
|
|
48
48
|
read(): OwnedUiSettingsResolution;
|
|
49
49
|
load(): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Adopts values another process stored in the shared document. Notifies only when a
|
|
52
|
+
* resolved value differs, so a peer's own write echo stays silent. Restart-bound values
|
|
53
|
+
* keep their session-start effect and surface as pending instead.
|
|
54
|
+
*/
|
|
55
|
+
refresh(): boolean;
|
|
50
56
|
sections(): readonly OwnedUiSettingsSection[];
|
|
51
57
|
/**
|
|
52
58
|
* The value in effect for a declared setting, typed by its declaration. A restart-bound
|
|
@@ -129,6 +129,28 @@ export class OwnedSettingsManager {
|
|
|
129
129
|
this.#agentSnapshot = agent === null ? null : await snapshotOf(agent, this.#hiddenAgentSettingIds);
|
|
130
130
|
this.#notify();
|
|
131
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Adopts values another process stored in the shared document. Notifies only when a
|
|
134
|
+
* resolved value differs, so a peer's own write echo stays silent. Restart-bound values
|
|
135
|
+
* keep their session-start effect and surface as pending instead.
|
|
136
|
+
*/
|
|
137
|
+
refresh() {
|
|
138
|
+
const next = this.read();
|
|
139
|
+
if (resolvedValuesKey(next) === resolvedValuesKey(this.#resolution))
|
|
140
|
+
return false;
|
|
141
|
+
this.#resolution = next;
|
|
142
|
+
for (const setting of next.settings) {
|
|
143
|
+
const id = setting.declaration.id;
|
|
144
|
+
if (!this.#restartEffective.has(id))
|
|
145
|
+
continue;
|
|
146
|
+
if (setting.value === this.#restartEffective.get(id))
|
|
147
|
+
this.#pending.delete(id);
|
|
148
|
+
else
|
|
149
|
+
this.#pending.set(id, setting.value);
|
|
150
|
+
}
|
|
151
|
+
this.#notify();
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
132
154
|
sections() {
|
|
133
155
|
const resolution = this.#hiddenOwnedSettingIds.size === 0
|
|
134
156
|
? this.#resolution
|
|
@@ -270,6 +292,9 @@ async function snapshotOf(agent, hidden) {
|
|
|
270
292
|
return { descriptors: [], writeAdvertised: false, failure: describe(error) };
|
|
271
293
|
}
|
|
272
294
|
}
|
|
295
|
+
function resolvedValuesKey(resolution) {
|
|
296
|
+
return JSON.stringify(resolution.settings.map(setting => [setting.declaration.id, setting.value]));
|
|
297
|
+
}
|
|
273
298
|
function failed(failure) {
|
|
274
299
|
return {
|
|
275
300
|
status: "failed",
|
|
@@ -44,6 +44,20 @@ The JavaScript product path has no PTY or terminal-emulator dependency. Reintrod
|
|
|
44
44
|
|
|
45
45
|
`scripts/governance/check-architecture.mjs` enforces the structural parts of these boundaries. Cross-cutting rationale belongs here; implementation history belongs in Git and archived OpenSpec changes.
|
|
46
46
|
|
|
47
|
+
## Session shell composition
|
|
48
|
+
|
|
49
|
+
The session presenter (`src/app/session-shell/session-shell.ts`) coordinates; it does not own per-concern state. Each concern implements `SessionConcern` (`session-concern.ts`): it resets its own state in `onSessionReplaced` and releases it in `dispose`, and the presenter lists its concerns once, in reset order, in `#createConcerns`. New submission, routing, dialog, login, or resident-tab behavior goes into the concern that owns it, or a new concern added to that list. The render root (`session-shell-root.ts`) likewise picks one `ShellLayout` at construction and delegates transcript caching to `TranscriptDocument`, dock chrome to `DockChrome`, workflow output to `WorkflowOutput`, extension surfaces to `ExtensionSurface`, and the dock's input surface to `InputSurfaceSwitch`. The engine adapter serves the shell through the ports built in `src/integrations/pi/engine/ports.ts`, and the composition root delegates runtime claims, the startup release note, and the resident-tab bridge to their own modules under `src/composition/`.
|
|
50
|
+
|
|
51
|
+
## Unit size ratchet
|
|
52
|
+
|
|
53
|
+
Module boundaries do not stop one class or function inside a module from absorbing every feature. The architecture gate therefore measures every production TypeScript class under `src/` (methods and fields) and every TypeScript or Rust function under `src/` and `native/<crate>/src/` (inclusive lines), excluding vendored sources and Rust `#[cfg(test)]` code. A unit with more than 20 methods, 15 fields, or 100 function lines must be recorded in `config/baselines/size-ratchet.json`, and its recorded counts can only shrink:
|
|
54
|
+
|
|
55
|
+
- A recorded count that grows fails the gate. Split the unit instead. If growth is truly unavoidable, raise the entry by hand in the same pull request and say why in its description, so the growth is reviewed rather than silent.
|
|
56
|
+
- An unrecorded unit over a threshold fails the gate; split it before it lands.
|
|
57
|
+
- A count that shrinks, or a unit that falls below every threshold, fails until `node scripts/governance/update-size-ratchet.mjs` lowers or removes the entry. That script never adds or raises an entry; `--check` reports without writing.
|
|
58
|
+
|
|
59
|
+
The measurement in `scripts/governance/size-ratchet-policy.mjs` masks strings, comments, and regular expressions and counts braces, so it needs no build; a file whose braces do not balance is reported rather than mismeasured. Keys are `<path>::<Class>`, `<path>::<Class>.<method>`, or `<path>::<Type>::<fn>`, so moving or renaming a unit means moving its entry.
|
|
60
|
+
|
|
47
61
|
## Multi-session limits of the pinned engine
|
|
48
62
|
|
|
49
63
|
The engine host removes A1's own obstacles to several Pi sessions in one process, but three remain in the pinned Pi SDK and must be planned around, not discovered:
|
|
@@ -64,7 +64,7 @@ The read-only review used A1 `develop` at `b42b3c9e`, PR #586 at `8fdb7361`, `E:
|
|
|
64
64
|
|
|
65
65
|
### Milestone 3 failure-isolation contract (2026-10-14)
|
|
66
66
|
|
|
67
|
-
- The native `core/server.rs
|
|
67
|
+
- The native `core/server.rs`, `core/holder.rs`, and `core/attach/` state machines are deterministic and I/O-free; the production holder uses the holder core for bounded input admission and ordered writer effects, the production server uses the server core for heartbeat supervision, and the attach client steps the attach core for every interaction mode (popup, rename, drag), shortcut, deferred input, and server answer while `roles/attach.rs` keeps the connection, outer terminal, encoders, and presentation. Blocking identity/termination work runs through the bounded worker shell with deadlines and stale-incarnation filtering.
|
|
68
68
|
- Every attach, server, and holder role has an independent 15-second watchdog. Watchdog records are bounded, timestamped, owner-only metadata under the profile runtime directory; fault-only role freezes are refused by non-test release builds.
|
|
69
69
|
- Holders read PTY output continuously, use one bounded input authority, reserve complete pastes before delivery, and emit a typed uncertain-delivery result after an admitted write failure. Each holder independently refreshes the server's latest complete retained surface even while hidden. Server-to-client control lanes are frame/byte bounded, render lanes retain one replaceable full current surface, and only the viewed tab is delivered to each attach client.
|
|
70
70
|
- Server replacement is serialized by `server-start.lock` in the profile runtime directory. Recovery verifies the recorded native owner before termination, waits boundedly for the registry-writer lease, increments the durable epoch, derives holder credentials, and re-admits only exact holder/child identities and incarnations. A durable three-start/sixty-second budget stops automatic replacement; explicit `--restart` clears it.
|
|
@@ -223,13 +223,13 @@ The channels carry bounded generation-1 frames: a u32 little-endian length follo
|
|
|
223
223
|
- The server sends `bridge.visibility{visible}`, so a hidden A1 throttles animation, and `bridge.rename`, so a strip rename sets the Pi session name.
|
|
224
224
|
- The bridge is advisory. A missing or broken bridge degrades that tab to process-level status and never breaks the tab.
|
|
225
225
|
- **Backpressure:**
|
|
226
|
-
- Each client connection has a reliable, bounded control lane and a **single-slot render lane**. A newer full current surface replaces an unsent one, so a client that drains never depends on a dropped intermediate revision.
|
|
227
|
-
- The server never blocks a holder, another client, or registry writes on a slow client.
|
|
226
|
+
- Each client connection has a reliable, bounded control lane and a **single-slot render lane**. A newer full current surface replaces an unsent one, so a client that drains never depends on a dropped intermediate revision. Structured surfaces are immutable `Arc` values while routed; encoding happens outside the routing mutex, decoded structured state is capped at 8 MiB, and a superseded holder socket cannot publish into a newer incarnation.
|
|
227
|
+
- The server never blocks a holder, another client, or registry writes on a slow client. Attach and holder hot loops yield after bounded frame, byte, and two-millisecond work quanta; completed outer writes, rather than offers, advance the presentation baseline.
|
|
228
228
|
- Holders parse their PTY continuously, whether or not the tab is viewed, so a PTY is never throttled and a child never blocks on output.
|
|
229
229
|
|
|
230
230
|
### 6. Rendering, input, and outer-terminal fidelity
|
|
231
231
|
|
|
232
|
-
- **Composition.** The attach client composes row 0 (the strip) and rows `1..N` (the viewed tab's surface). The tab PTY is sized `cols × (rows − 1)`.
|
|
232
|
+
- **Composition.** The attach client composes row 0 (the strip) and rows `1..N` (the viewed tab's surface). The tab PTY is sized `cols × (rows − 1)`. Ghostty remains the sole child-terminal parser. Its stream parser reports synchronized-output begin/end/reset boundaries to the holder, which keeps mutable parser state separate from an immutable committed surface and never publishes an open transaction. A non-renewable 250 ms deadline publishes one typed recovery commit for a malformed transaction. The outer composer owns the only synchronized envelope and falls back to a full repaint only when identity, geometry generation, dimensions, or the structured base changes.
|
|
233
233
|
- **Outer modes.** The client negotiates the outer terminal's modes: raw mode, alternate screen, bracketed paste, focus events, SGR mouse, kitty keyboard protocol where available, and synchronized output.
|
|
234
234
|
- Child-requested modes are tracked in the holder's model. Input is re-encoded per child mode by libghostty-vt, which the proof already does.
|
|
235
235
|
- Mouse rows are offset by the strip. Row 0 belongs to the client.
|
|
@@ -249,8 +249,8 @@ Direct `a1 solo` is the behavioural oracle for every viewed resident child. Only
|
|
|
249
249
|
- **Typed effects.** The holder registers libghostty's clipboard-write callback, which normalizes OSC 52 and OSC 1337. A write from the viewed tab crosses as one bounded `terminal.effect`; attach writes one OSC 52 for it. A hidden tab's write is dropped, never replayed into a later view. Payloads are never logged.
|
|
250
250
|
- **Modes and cursor.** Each surface carries the child's cursor cell and modes. Attach mirrors a cursor shape the child chose and resets it on detach or failure; a default block cursor is left to the outer terminal, as direct A1 leaves it.
|
|
251
251
|
- **Shortcut projection.** The owned child projects the effective A1 keybindings plus `keybindings.json` into one assignment per tab action: a key an A1 action holds never becomes a tab shortcut, and the earlier declaration keeps a duplicated key. It publishes the projection as `bridge.shortcuts`; the server relays it as `tabs.shortcuts`, and attach dispatches and labels exactly that projection. `/hotkeys` renders the same projection. A shared case file is replayed by both resolvers.
|
|
252
|
-
- **Committed presentation.** A requested view commits only with a topology that lists it and a complete target surface. Surfaces of the committed view apply in revision order, and revisions rise across holder incarnations. A retained re-offer is marked stale and parks for at most 120 ms while the fresh frame arrives. One compositor writes strip, body, overlay, and final cursor inside a single synchronized update
|
|
253
|
-
- **Evidence.** One interaction matrix drives three layers: an owned-shell oracle that records content-free observations, role fixtures that drive real server, holder, and attach processes with a certified parity child, and
|
|
252
|
+
- **Committed presentation.** A requested view commits only with a topology that lists it and a complete target surface. Retained rows, palette/default colors, modes, and cursor are captured atomically; equal captures do not invent a revision. Surfaces of the committed view apply in revision order, and revisions rise across holder incarnations. A retained re-offer is marked stale from the request start and parks for at most 120 ms while the fresh frame arrives. One compositor writes strip, body, overlay, modes, and the viewport-clipped final cursor inside a single synchronized update. It erases suffix cells when a complete replacement row becomes shorter and restores the newest underlying surface when an overlay leaves. Clock, hover, and title-animation damage repaints only the strip and restores the child's cursor.
|
|
253
|
+
- **Evidence.** One interaction matrix drives three layers: an owned-shell oracle that records content-free observations, role fixtures that drive real server, holder, and attach processes with a certified parity child, and exact-artifact harnesses. `verify-interaction-parity.mjs` compares the bytes the same child observes directly and through the built host. `verify-resident-parallel-progress.mjs` configures the real engine against a bounded loopback streaming provider and crosses all six first-response orders with all three initial views while every turn remains unfinished behind a completion barrier. At matching 100×29 child geometry, the same real-A1 prompt also runs through isolated direct-solo and resident profiles; the native Ghostty oracle compares a content-free digest of the intermediate fixture cells and their resolved styles together with normalized cursor and mode state. It advances only at parser-reported synchronized-output boundaries, rejects unbalanced transactions or disappearing intermediate cells, and excludes only the resident strip row rather than normalizing terminal semantics. Opt-in per-process JSONL observations identify engine delivery, completed child writes, PTY ingestion, distinct holder commits, attach receipt, and completed outer paint by run/tab/incarnation/process-instance/sequence without recording terminal or conversation content; queue loss, clock faults, duplicates, stale order, and missing stages fail the report. Named pressure variants keep all turns unfinished while exercising hidden progress, repeated switching, navigation input, rename overlays, tab-local resize, a bounded 35 ms attach-receipt delay, and a 900 ms paused outer sink; every tab must retain partial animation/progress before settlement and then present its final output. A detached/reconnect variant releases all three unfinished turns after terminating the authenticated attach and exact self-reported server identity; child writes, PTY ingestion, and holder commits must continue before a replacement server and attach present every retained final output. Separate isolated exact-artifact control markers stop one target tab at engine delivery, physical child rendering, holder commit, or outer paint; each control requires its upstream stages and the other tabs to advance, then removes the stop and requires final output from all three tabs. A fifth control fragments a real owned-shell synchronized write into at most 64 physical writes without changing its bytes, records the DEC private mode 2026 transaction classification, and requires ordinary complete holder commits without deadline recovery before final output. This characterizes the built PTY/ConPTY coherence path; a passing fragmented run does not by itself assign the historical stall to that path without a failing live reproduction. The marker path is absent in ordinary sessions and is scrubbed before extensions or tools inherit the child environment, while observation callbacks remain passive and cannot select a control. CI runs the vendored Ghostty VT tests and both exact-artifact harnesses on Windows x64, Linux x64, and macOS arm64. Each platform's verdict stands alone.
|
|
254
254
|
|
|
255
255
|
### 7. Status and attention come from the tab bridge
|
|
256
256
|
|
|
@@ -262,11 +262,12 @@ Tab status is an A1-owned state machine fed by `bridge.status`:
|
|
|
262
262
|
| `idle` | settled idle | none |
|
|
263
263
|
| `working` | agent or turn start, tool execution, compaction | shared progress frames |
|
|
264
264
|
| `needs-input` | an extension UI, trust, or permission request is pending | yellow `?` (warning) |
|
|
265
|
-
| `done
|
|
266
|
-
| `
|
|
267
|
-
| `
|
|
265
|
+
| `done` | the last turn finished successfully | green `✓` success |
|
|
266
|
+
| `aborted` | the last turn was aborted | red `✗` error |
|
|
267
|
+
| `error` | the last turn ended with an error | red `✗` error |
|
|
268
|
+
| `crashed` / `restarting` / `failed` | holder or child exit, or a failed tab lifecycle (never a failed turn) | `✗` error plus a banner |
|
|
268
269
|
|
|
269
|
-
- `
|
|
270
|
+
- A `done`, `aborted`, or `error` marker stays on the chip, including after any client views the tab, until that tab's next turn starts.
|
|
270
271
|
- A tab with a broken bridge shows only process-level states.
|
|
271
272
|
- Future CLI tabs will derive status from process state, and may use BEL or OSC 9/777 from the program as an attention input.
|
|
272
273
|
- The glyph set is the same in every client. A working spinner uses the resolved A1 accent reported by that specific tab.
|
|
@@ -335,7 +336,7 @@ Tab status is an A1-owned state machine fed by `bridge.status`:
|
|
|
335
336
|
| `Alt+A` | new tab |
|
|
336
337
|
| `Alt+W` | close |
|
|
337
338
|
| `F2` | rename |
|
|
338
|
-
| `Alt
|
|
339
|
+
| `Alt+,` | open the global Settings tab, or close it while it is viewed |
|
|
339
340
|
| `Alt+1`…`Alt+9`, `Alt+0` | jump to a tab |
|
|
340
341
|
| unbound (`tabs.next` / `tabs.previous`) | next / previous, wrapping |
|
|
341
342
|
| unbound (`tabs.moveRight` / `tabs.moveLeft`) | move the tab right / left |
|
|
@@ -349,7 +350,7 @@ Tab status is an A1-owned state machine fed by `bridge.status`:
|
|
|
349
350
|
- right-click opens `Rename`/`Close` (`Close` only for Settings);
|
|
350
351
|
- dragging reorders, with a `│` drop marker, after 250 ms or once the pointer moves;
|
|
351
352
|
- `+` opens a persistent dark v2 menu with `+ Agent`, a separator, and `Settings`; hover and click remain active through the opening release.
|
|
352
|
-
- **Settings.** The strip owns one profile-global `Settings` tab. The grouped launcher
|
|
353
|
+
- **Settings.** The strip owns one profile-global `Settings` tab. The grouped launcher creates or activates it; `Alt+,` does the same from another tab and closes it while it is viewed. Esc does not close the Settings tab; closing the tab removes it. Resident Agent autocomplete omits `/settings`, and manually entering it does not open a per-Agent screen. `a1 solo` and `a1 pi` retain their existing Settings routes.
|
|
353
354
|
- **Commands inside A1 tabs:** existing `/name <name>` also renames the tab. Milestone 5 adds no tab-management slash commands: `/new-tab`, `/close`, `/tabs`, `/quit-all`, and `/restart-tab` are not exposed.
|
|
354
355
|
- **Naming:**
|
|
355
356
|
- Default names are `agent` or `agent N`.
|
|
@@ -391,13 +392,15 @@ Every queue, buffer, file, and collection the resident roles keep has a declared
|
|
|
391
392
|
| Bound | Cap | Enforced in | Test |
|
|
392
393
|
|---|---|---|---|
|
|
393
394
|
| Protocol frame | 2 MiB, nesting 64, 65,536 collection items | `native/terminal-host/src/protocol.rs`, `src/foundation/resident-tabs/protocol.ts` | `refuses_oversized_header_before_payload`; `refuses a frame header past 2 MiB before buffering its payload`, `refuses nesting past 64 levels`, `refuses a collection past 65,536 items` |
|
|
395
|
+
| Structured complete surface | 512 × 256 geometry, 65,536 cells, 4,096 styles, 4,096 links, and 8 MiB decoded state | `protocol.rs` `StructuredSurface::validate` | `structured_surfaces_fail_closed_on_dimensions_indexes_and_control_injection` |
|
|
394
396
|
| Input per message and holder input queue | 1 MiB | `protocol.rs`, `core/holder.rs`, `roles/holder.rs` | `over_capacity_paste_delivers_no_prefix` |
|
|
395
|
-
|
|
|
396
|
-
| Per-client
|
|
397
|
-
|
|
|
398
|
-
|
|
|
397
|
+
| Holder PTY ingress and work round | 64 × 16 KiB lossless chunks; at most 256 KiB or 2 ms before yielding | `roles/holder.rs` | `verify-resident-parallel-progress.mjs` concurrent and stopped-stage cases |
|
|
398
|
+
| Per-client control lane | 1,024 frames and 4 MiB | `roles/server/mod.rs` | `control_lane_is_bounded_by_frames_and_bytes` |
|
|
399
|
+
| Per-client render slot | one pending full surface; a newer one replaces it | `roles/server/mod.rs` `Peer::offer_surface` | `stalled_client_gets_one_full_current_surface` |
|
|
400
|
+
| Concurrent endpoint connections | 128 | `roles/server/mod.rs` `admit_connection` | `connections_beyond_the_cap_are_refused_and_released_slots_are_reused` |
|
|
401
|
+
| Attached viewing clients | 16 | `roles/server/mod.rs` `client_slot_available` | `attached_clients_are_capped` |
|
|
399
402
|
| Concurrent holder starts | default 2, hard 8 | `core/server.rs` | `limits_starts_and_drops_stale_completion` |
|
|
400
|
-
| Stopped tab records | 16, oldest dropped first | `roles/server.rs` `prune_stopped_records` | `stopped_records_are_bounded_oldest_first_and_live_tabs_are_kept` |
|
|
403
|
+
| Stopped tab records | 16, oldest dropped first | `roles/server/mod.rs` `prune_stopped_records` | `stopped_records_are_bounded_oldest_first_and_live_tabs_are_kept` |
|
|
401
404
|
| Prior tab-set archives | bounded history | `roles/registry.rs` | `prior_tab_sets_are_bounded` |
|
|
402
405
|
| Abandoned blocking workers | 8 | `shell/workers.rs` | `fails_fast_after_eight_abandoned_workers` |
|
|
403
406
|
| Diagnostic logs | 5 MiB × 3 generations per role | `roles/diagnostics.rs` | `logs_rotate_at_their_cap_and_keep_a_bounded_number_of_generations` |
|
|
@@ -407,7 +410,9 @@ Every queue, buffer, file, and collection the resident roles keep has a declared
|
|
|
407
410
|
| Session reconciliation read | 64 MiB | `src/foundation/resident-tabs/recovery.ts` | `refuses to scan a session past the 64 MiB reconciliation cap` |
|
|
408
411
|
| Release-hold report | 32 uncertainty reasons; 1 MiB read | `roles/release_holds.rs`, `release-holds.ts`, `bounded-host-command.ts` | `uncertainty_reasons_stay_within_their_cap`; `fails a release-hold report that pushes past its byte cap without returning a prefix` |
|
|
409
412
|
| Maintenance exchange | 5 s reads, 60 s stops, 4 MiB report | `roles/maintain.rs`, `maintenance.ts`, `bounded-host-command.ts` | `fails a maintenance report that pushes past its byte cap without returning a prefix`, `kills and rejects a command that outlives its deadline` |
|
|
410
|
-
| Attach
|
|
413
|
+
| Attach server ingress | reader queue 64 frames/4 MiB; execution queue 8 frames/4 MiB; at most 64 KiB or 2 ms before yielding | `roles/attach.rs` | `verify-resident-parallel-progress.mjs` slow-receipt and switching cases |
|
|
414
|
+
| Attach input | 1,024 parsed events; semantic input is emitted in at most 1 MiB chunks and target-bound while a view/create is pending | `roles/attach.rs` | `deferred_input_is_atomic_bounded_and_bound_to_the_requested_tab` |
|
|
415
|
+
| Outer presentation writer | one replaceable complete desired state, 8 control/effect frames, and 4 MiB effect bytes | `roles/attach.rs` `OuterWriter` | `presentation_is_one_ordered_synchronized_write`; `verify-resident-parallel-progress.mjs` paused-sink case |
|
|
411
416
|
| Doctor bundle | 25 MiB, oldest log generations dropped first | `src/foundation/resident-tabs/doctor.ts` | `drops the oldest log generations first to stay within its cap` |
|
|
412
417
|
|
|
413
418
|
### 13. Packaging and certification
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timurproko/a1",
|
|
3
|
-
"version": "0.2.7-dev.
|
|
3
|
+
"version": "0.2.7-dev.809",
|
|
4
4
|
"description": "Standalone terminal workspace for supervised native and managed agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"privateLaunchContract": "neutral-launch-v1",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"test:full": "node scripts/release/run-validation-tier.mjs full-release",
|
|
54
54
|
"test:release": "node scripts/release/run-release-gates.mjs",
|
|
55
55
|
"test:terminal-host": "node scripts/development/run-terminal-host-probe.mjs",
|
|
56
|
+
"test:resident-parallel-progress": "node scripts/development/verify-resident-parallel-progress.mjs",
|
|
56
57
|
"test:resident-chaos": "node scripts/development/run-resident-chaos.mjs --build",
|
|
57
58
|
"test:pi-engine-conformance": "vitest run test/integrations/pi/engine/conformance.test.ts test/integrations/pi/engine/runtime-integration.test.ts test/integrations/pi/engine/session-integration.test.ts",
|
|
58
59
|
"report:pi-engine-conformance": "npm run build --silent && node scripts/pi/run-pi-engine-conformance.mjs",
|