@timurproko/a1 0.1.1-dev.1 → 0.1.1-dev.10
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 +8 -43
- package/bin/guardian.js +22 -0
- package/bin/{a1-ui.js → ui.js} +4 -8
- package/dist/native/darwin-arm64/manifest.json +20 -0
- package/dist/native/darwin-arm64/process-guardian +0 -0
- package/dist/native/linux-x64/manifest.json +20 -0
- package/dist/native/linux-x64/process-guardian +0 -0
- package/dist/native/win32-x64/manifest.json +20 -0
- package/dist/native/win32-x64/process-guardian.exe +0 -0
- package/dist/src/composition/index.d.ts +26 -0
- package/dist/src/composition/index.js +94 -2
- package/dist/src/features/launch/initialize-profile.js +23 -2
- package/dist/src/features/launch/profiles.d.ts +1 -1
- package/dist/src/features/launch/profiles.js +2 -2
- package/dist/src/features/launch/runtime-selection.d.ts +13 -8
- package/dist/src/features/launch/runtime-selection.js +6 -6
- package/dist/src/features/owned-ui/index.d.ts +1 -0
- package/dist/src/features/owned-ui/index.js +1 -0
- package/dist/src/features/owned-ui/run.d.ts +6 -0
- package/dist/src/features/owned-ui/run.js +3 -1
- package/dist/src/features/owned-ui/settings-app.d.ts +22 -0
- package/dist/src/features/owned-ui/settings-app.js +633 -0
- package/dist/src/foundation/agent-engine-contracts/domain.d.ts +26 -0
- package/dist/src/foundation/launch-guardian/index.d.ts +1 -0
- package/dist/src/foundation/launch-guardian/index.js +1 -0
- package/dist/src/foundation/launch-guardian/main.d.ts +31 -0
- package/dist/src/foundation/launch-guardian/main.js +165 -0
- package/dist/src/foundation/lifecycle/commands.d.ts +40 -0
- package/dist/src/foundation/lifecycle/commands.js +1 -0
- package/dist/src/foundation/lifecycle/index.d.ts +2 -0
- package/dist/src/foundation/lifecycle/index.js +2 -0
- package/dist/src/foundation/lifecycle/launch-instance.d.ts +46 -0
- package/dist/src/foundation/lifecycle/launch-instance.js +134 -0
- package/dist/src/foundation/lifecycle/model.d.ts +6 -42
- package/dist/src/foundation/owned-ui-settings/declarations.d.ts +13 -0
- package/dist/src/foundation/owned-ui-settings/declarations.js +39 -0
- package/dist/src/foundation/owned-ui-settings/index.d.ts +6 -0
- package/dist/src/foundation/owned-ui-settings/index.js +6 -0
- package/dist/src/foundation/owned-ui-settings/migrations.d.ts +13 -0
- package/dist/src/foundation/owned-ui-settings/migrations.js +28 -0
- package/dist/src/foundation/owned-ui-settings/resolution.d.ts +45 -0
- package/dist/src/foundation/owned-ui-settings/resolution.js +147 -0
- package/dist/src/foundation/owned-ui-settings/sections.d.ts +70 -0
- package/dist/src/foundation/owned-ui-settings/sections.js +93 -0
- package/dist/src/foundation/owned-ui-settings/session.d.ts +44 -0
- package/dist/src/foundation/owned-ui-settings/session.js +145 -0
- package/dist/src/foundation/owned-ui-settings/store.d.ts +28 -0
- package/dist/src/foundation/owned-ui-settings/store.js +90 -0
- package/dist/src/foundation/pi-component-adapter/index.d.ts +1 -0
- package/dist/src/foundation/pi-component-adapter/index.js +1 -0
- package/dist/src/foundation/pi-component-adapter/shell-selectors-dialogs.d.ts +9 -1
- package/dist/src/foundation/pi-component-adapter/shell-selectors-dialogs.js +10 -8
- package/dist/src/foundation/pi-component-adapter/upstream/theme/theme.d.ts +8 -0
- package/dist/src/foundation/pi-component-adapter/upstream/theme/theme.js +12 -0
- package/dist/src/foundation/pi-engine-adapter/adapter.d.ts +17 -3
- package/dist/src/foundation/pi-engine-adapter/adapter.js +80 -7
- package/dist/src/foundation/pi-engine-adapter/pi-settings-metadata.json +374 -0
- package/dist/src/foundation/pi-engine-adapter/public-main-entry.js +10 -1
- package/dist/src/foundation/pi-engine-adapter/settings-integration.d.ts +40 -2
- package/dist/src/foundation/pi-engine-adapter/settings-integration.js +172 -24
- package/dist/src/foundation/pi-engine-adapter/workflows.d.ts +9 -0
- package/dist/src/foundation/pi-owned-ui-integration/index.d.ts +1 -0
- package/dist/src/foundation/pi-owned-ui-integration/index.js +1 -0
- package/dist/src/foundation/pi-owned-ui-integration/route-host.d.ts +29 -0
- package/dist/src/foundation/pi-owned-ui-integration/route-host.js +1 -0
- package/dist/src/foundation/pi-owned-ui-integration/session-shell.d.ts +6 -0
- package/dist/src/foundation/pi-owned-ui-integration/session-shell.js +71 -1
- package/dist/src/foundation/pi-tui-runtime-adapter/adapter.d.ts +6 -0
- package/dist/src/foundation/pi-tui-runtime-adapter/adapter.js +9 -0
- package/dist/src/foundation/process-containment/artifact.d.ts +1 -0
- package/dist/src/foundation/process-containment/artifact.js +34 -0
- package/dist/src/foundation/process-containment/contracts.d.ts +31 -0
- package/dist/src/foundation/process-containment/contracts.js +35 -0
- package/dist/src/foundation/process-containment/index.d.ts +5 -0
- package/dist/src/foundation/process-containment/index.js +5 -0
- package/dist/src/foundation/process-containment/linux-process-inspector.d.ts +6 -0
- package/dist/src/foundation/process-containment/linux-process-inspector.js +26 -0
- package/dist/src/foundation/process-containment/native-guardian-containment.d.ts +16 -0
- package/dist/src/foundation/process-containment/native-guardian-containment.js +139 -0
- package/dist/src/foundation/process-containment/windows-process-inspector.d.ts +17 -0
- package/dist/src/foundation/process-containment/windows-process-inspector.js +53 -0
- package/dist/src/foundation/protocol/client.d.ts +2 -1
- package/dist/src/foundation/protocol/client.js +3 -0
- package/dist/src/foundation/protocol/messages.d.ts +5 -5
- package/dist/src/foundation/protocol/messages.js +1 -1
- package/dist/src/foundation/release/bootstrap.d.ts +2 -2
- package/dist/src/foundation/release/bootstrap.js +69 -18
- package/dist/src/foundation/release/cohort-selection.js +3 -3
- package/dist/src/foundation/release/cohort-state.d.ts +3 -2
- package/dist/src/foundation/release/concurrency.d.ts +1 -0
- package/dist/src/foundation/release/concurrency.js +17 -0
- package/dist/src/foundation/release/process-cleanup.d.ts +1 -1
- package/dist/src/foundation/release/process-cleanup.js +2 -2
- package/dist/src/foundation/release/release-store.d.ts +35 -2
- package/dist/src/foundation/release/release-store.js +90 -31
- package/dist/src/foundation/release/release.d.ts +15 -0
- package/dist/src/foundation/release/release.js +65 -36
- package/dist/src/foundation/release/update.d.ts +19 -2
- package/dist/src/foundation/release/update.js +132 -16
- package/dist/src/foundation/storage/control-store.d.ts +8 -7
- package/dist/src/foundation/storage/control-store.js +105 -55
- package/dist/src/foundation/supervision/main.js +6 -5
- package/dist/src/foundation/supervision/server.d.ts +4 -2
- package/dist/src/foundation/supervision/server.js +254 -87
- package/dist/src/foundation/ui-apps/contracts.d.ts +42 -0
- package/dist/src/foundation/ui-apps/contracts.js +12 -0
- package/dist/src/foundation/ui-apps/host.d.ts +42 -0
- package/dist/src/foundation/ui-apps/host.js +152 -0
- package/dist/src/foundation/ui-apps/index.d.ts +3 -0
- package/dist/src/foundation/ui-apps/index.js +3 -0
- package/dist/src/foundation/ui-apps/registry.d.ts +11 -0
- package/dist/src/foundation/ui-apps/registry.js +32 -0
- package/dist/src/foundation/ui-components/dialog-panel.d.ts +36 -0
- package/dist/src/foundation/ui-components/dialog-panel.js +47 -0
- package/dist/src/foundation/ui-components/frame.d.ts +21 -0
- package/dist/src/foundation/ui-components/frame.js +54 -0
- package/dist/src/foundation/ui-components/index.d.ts +18 -0
- package/dist/src/foundation/ui-components/index.js +18 -0
- package/dist/src/foundation/ui-components/label.d.ts +8 -0
- package/dist/src/foundation/ui-components/label.js +36 -0
- package/dist/src/foundation/ui-components/line-input.d.ts +74 -0
- package/dist/src/foundation/ui-components/line-input.js +245 -0
- package/dist/src/foundation/ui-components/list-block.d.ts +66 -0
- package/dist/src/foundation/ui-components/list-block.js +176 -0
- package/dist/src/foundation/ui-components/list-view.d.ts +66 -0
- package/dist/src/foundation/ui-components/list-view.js +76 -0
- package/dist/src/foundation/ui-components/mouse.d.ts +15 -0
- package/dist/src/foundation/ui-components/mouse.js +46 -0
- package/dist/src/foundation/ui-components/pane.d.ts +33 -0
- package/dist/src/foundation/ui-components/pane.js +7 -0
- package/dist/src/foundation/ui-components/revision.d.ts +35 -0
- package/dist/src/foundation/ui-components/revision.js +79 -0
- package/dist/src/foundation/ui-components/scrollbar.d.ts +62 -0
- package/dist/src/foundation/ui-components/scrollbar.js +102 -0
- package/dist/src/foundation/ui-components/shortcuts.d.ts +57 -0
- package/dist/src/foundation/ui-components/shortcuts.js +81 -0
- package/dist/src/foundation/ui-components/spans.d.ts +7 -0
- package/dist/src/foundation/ui-components/spans.js +59 -0
- package/dist/src/foundation/ui-components/status-line.d.ts +16 -0
- package/dist/src/foundation/ui-components/status-line.js +14 -0
- package/dist/src/foundation/ui-components/stepper.d.ts +24 -0
- package/dist/src/foundation/ui-components/stepper.js +33 -0
- package/dist/src/foundation/ui-components/surface.d.ts +20 -0
- package/dist/src/foundation/ui-components/surface.js +38 -0
- package/dist/src/foundation/ui-components/text.d.ts +24 -0
- package/dist/src/foundation/ui-components/text.js +123 -0
- package/dist/src/foundation/ui-components/theme.d.ts +23 -0
- package/dist/src/foundation/ui-components/theme.js +13 -0
- package/dist/src/foundation/ui-components/value-menu.d.ts +41 -0
- package/dist/src/foundation/ui-components/value-menu.js +33 -0
- package/dist/src/product-identity.d.ts +2 -2
- package/dist/src/product-identity.js +2 -1
- package/dist/src/product-identity.json +8 -5
- package/docs/architecture/boundaries.md +31 -13
- package/docs/architecture/process-guardian-provenance.md +26 -0
- package/docs/architecture/toolchain.md +9 -3
- package/docs/architecture/ui-reference-provenance.md +50 -0
- package/docs/ci-release-runbook.md +67 -0
- package/docs/features/launch-profiles.md +7 -1
- package/docs/manual-launch-instance-acceptance.md +66 -0
- package/docs/manual-terminal-colour-check.md +55 -0
- package/package.json +20 -14
- package/dist/src/composition/transparent-runtime.d.ts +0 -6
- package/dist/src/composition/transparent-runtime.js +0 -19
- package/dist/src/foundation/transparent-terminal/command-resolution.d.ts +0 -13
- package/dist/src/foundation/transparent-terminal/command-resolution.js +0 -69
- package/dist/src/foundation/transparent-terminal/foreground-broker.d.ts +0 -32
- package/dist/src/foundation/transparent-terminal/foreground-broker.js +0 -87
- package/dist/src/foundation/transparent-terminal/index.d.ts +0 -4
- package/dist/src/foundation/transparent-terminal/index.js +0 -4
- package/dist/src/foundation/transparent-terminal/main.d.ts +0 -9
- package/dist/src/foundation/transparent-terminal/main.js +0 -94
- package/dist/src/foundation/transparent-terminal/native-launcher.d.ts +0 -25
- package/dist/src/foundation/transparent-terminal/native-launcher.js +0 -146
- /package/bin/{a1.js → cli.js} +0 -0
- /package/bin/{a1-supervisor.js → supervisor.js} +0 -0
|
@@ -40,7 +40,7 @@ export function createNpmProcessRunner(platform = process.platform) {
|
|
|
40
40
|
} });
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
|
-
export function createUpdateLifecycleCoordinator(environment = process.env, fileSystem = defaultFileSystem) {
|
|
43
|
+
export function createUpdateLifecycleCoordinator(environment = process.env, fileSystem = defaultFileSystem, output = defaultOutput) {
|
|
44
44
|
const paths = resolveProductPaths(environment);
|
|
45
45
|
const stateStore = new CohortStateStore(paths.dataDir);
|
|
46
46
|
return {
|
|
@@ -71,7 +71,7 @@ export function createUpdateLifecycleCoordinator(environment = process.env, file
|
|
|
71
71
|
// Explicit update consent permits bounded cleanup of an authenticated
|
|
72
72
|
// older owner that predates the update-shutdown message.
|
|
73
73
|
const cleanup = await cleanupVerifiedOwner(endpoint, {
|
|
74
|
-
|
|
74
|
+
allowLiveInstances: true,
|
|
75
75
|
reason: legacyMutableInstall ? "legacy-mutable-install" : "explicit-update",
|
|
76
76
|
});
|
|
77
77
|
if (!cleanup.terminated)
|
|
@@ -80,7 +80,7 @@ export function createUpdateLifecycleCoordinator(environment = process.env, file
|
|
|
80
80
|
else if (identity.accepted) {
|
|
81
81
|
await waitForProcessExit(endpoint.pid, 3_000).catch(async () => {
|
|
82
82
|
const cleanup = await cleanupVerifiedOwner(endpoint, {
|
|
83
|
-
|
|
83
|
+
allowLiveInstances: true,
|
|
84
84
|
reason: legacyMutableInstall ? "legacy-mutable-install" : "explicit-update",
|
|
85
85
|
});
|
|
86
86
|
if (!cleanup.terminated)
|
|
@@ -121,15 +121,91 @@ export function createUpdateLifecycleCoordinator(environment = process.env, file
|
|
|
121
121
|
},
|
|
122
122
|
};
|
|
123
123
|
}
|
|
124
|
+
const PROGRESS_BAR_WIDTH = 39;
|
|
125
|
+
const PROGRESS_TICK_MS = 200;
|
|
126
|
+
const ACTIVATION_PROGRESS = {
|
|
127
|
+
materialized: { at: 85, creepTo: 90 },
|
|
128
|
+
certified: { at: 90, creepTo: 95 },
|
|
129
|
+
"active-reference-committed": { at: 95, creepTo: 99 },
|
|
130
|
+
};
|
|
131
|
+
function renderProgressBar(percent) {
|
|
132
|
+
const bounded = Math.min(100, Math.max(0, Math.round(percent)));
|
|
133
|
+
const filled = Math.round((bounded / 100) * PROGRESS_BAR_WIDTH);
|
|
134
|
+
return `${"█".repeat(filled)}${"░".repeat(PROGRESS_BAR_WIDTH - filled)} ${bounded}%`;
|
|
135
|
+
}
|
|
136
|
+
function createUpdateProgress(output, enabled) {
|
|
137
|
+
let visible = false;
|
|
138
|
+
let current = 0;
|
|
139
|
+
let shown = -1;
|
|
140
|
+
let timer = null;
|
|
141
|
+
const draw = () => {
|
|
142
|
+
const rounded = Math.round(current);
|
|
143
|
+
if (rounded === shown)
|
|
144
|
+
return;
|
|
145
|
+
shown = rounded;
|
|
146
|
+
visible = true;
|
|
147
|
+
output.stdout(`\r${renderProgressBar(rounded)}`);
|
|
148
|
+
};
|
|
149
|
+
const stopCreep = () => {
|
|
150
|
+
if (timer !== null) {
|
|
151
|
+
clearInterval(timer);
|
|
152
|
+
timer = null;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
return {
|
|
156
|
+
set(percent, creepTo = percent) {
|
|
157
|
+
if (!enabled)
|
|
158
|
+
return;
|
|
159
|
+
stopCreep();
|
|
160
|
+
current = Math.max(current, percent);
|
|
161
|
+
shown = -1;
|
|
162
|
+
draw();
|
|
163
|
+
if (creepTo <= current)
|
|
164
|
+
return;
|
|
165
|
+
// Creep asymptotically toward (but never reach) the next milestone so
|
|
166
|
+
// long opaque phases such as npm install still show visible motion.
|
|
167
|
+
timer = setInterval(() => {
|
|
168
|
+
current = Math.min(creepTo - 0.5, current + (creepTo - current) * 0.04);
|
|
169
|
+
draw();
|
|
170
|
+
}, PROGRESS_TICK_MS);
|
|
171
|
+
timer.unref?.();
|
|
172
|
+
},
|
|
173
|
+
finish() {
|
|
174
|
+
stopCreep();
|
|
175
|
+
if (!visible)
|
|
176
|
+
return;
|
|
177
|
+
output.stdout(`\r${renderProgressBar(100)}\n`);
|
|
178
|
+
visible = false;
|
|
179
|
+
},
|
|
180
|
+
clear() {
|
|
181
|
+
stopCreep();
|
|
182
|
+
if (!visible)
|
|
183
|
+
return;
|
|
184
|
+
output.stdout(`\r${" ".repeat(PROGRESS_BAR_WIDTH + 6)}\r`);
|
|
185
|
+
visible = false;
|
|
186
|
+
shown = -1;
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
}
|
|
124
190
|
export async function runSelfUpdate(options) {
|
|
125
191
|
const fileSystem = options.fileSystem ?? defaultFileSystem;
|
|
126
192
|
const output = options.output ?? defaultOutput;
|
|
127
193
|
const runner = options.runner ?? createNpmProcessRunner();
|
|
128
194
|
const channel = options.channel ?? "stable";
|
|
129
195
|
const distTag = UPDATE_DIST_TAGS[channel];
|
|
196
|
+
const now = options.now ?? (() => performance.now());
|
|
197
|
+
const measure = async (phase, operation) => {
|
|
198
|
+
const startedAt = now();
|
|
199
|
+
try {
|
|
200
|
+
return await operation();
|
|
201
|
+
}
|
|
202
|
+
finally {
|
|
203
|
+
options.onPhaseTiming?.({ phase, durationMs: Math.max(0, now() - startedAt) });
|
|
204
|
+
}
|
|
205
|
+
};
|
|
130
206
|
let runningVersion;
|
|
131
207
|
try {
|
|
132
|
-
const packageJson = JSON.parse(await fileSystem.readFile(resolve(options.packageRoot, "package.json")));
|
|
208
|
+
const packageJson = JSON.parse(await measure("package-version", async () => await fileSystem.readFile(resolve(options.packageRoot, "package.json"))));
|
|
133
209
|
const parsedVersion = typeof packageJson.version === "string" ? validSemver(packageJson.version) : null;
|
|
134
210
|
if (parsedVersion === null)
|
|
135
211
|
throw new Error("package.json does not contain a valid semantic version");
|
|
@@ -139,7 +215,7 @@ export async function runSelfUpdate(options) {
|
|
|
139
215
|
output.stderr(`${PRODUCT_TEXT.diagnostic(`could not read its running package version: ${errorMessage(error)}`)}\n`);
|
|
140
216
|
return 1;
|
|
141
217
|
}
|
|
142
|
-
const targetLookup = await runNpm(runner, ["view", `${PRODUCT_PACKAGE}@${distTag}`, "version"], true, output, `query the npm ${distTag} channel`);
|
|
218
|
+
const targetLookup = await measure("target-resolution", async () => await runNpm(runner, ["view", `${PRODUCT_PACKAGE}@${distTag}`, "version"], true, output, `query the npm ${distTag} channel`));
|
|
143
219
|
if (targetLookup.result === null)
|
|
144
220
|
return targetLookup.exitCode;
|
|
145
221
|
const targetVersion = validSemver(targetLookup.result.stdout.trim());
|
|
@@ -147,8 +223,10 @@ export async function runSelfUpdate(options) {
|
|
|
147
223
|
output.stderr(`${PRODUCT_TEXT.diagnostic(`received a malformed ${distTag} version from npm: ${JSON.stringify(targetLookup.result.stdout.trim())}.`)}\n`);
|
|
148
224
|
return 1;
|
|
149
225
|
}
|
|
150
|
-
output.stdout(`${PRODUCT_TEXT.
|
|
151
|
-
const
|
|
226
|
+
output.stdout(`${PRODUCT_TEXT.commandName} update (${channel}): ${runningVersion} → ${targetVersion}.\n`);
|
|
227
|
+
const progress = createUpdateProgress(output, options.progress ?? (options.output === undefined && process.stdout.isTTY === true));
|
|
228
|
+
progress.set(3, 15);
|
|
229
|
+
const rootLookup = await measure("global-root", async () => await runNpm(runner, ["root", "--global"], true, output, "resolve npm's global package root"));
|
|
152
230
|
if (rootLookup.result === null)
|
|
153
231
|
return rootLookup.exitCode;
|
|
154
232
|
if (rootLookup.result.stdout.trim().length === 0) {
|
|
@@ -170,7 +248,7 @@ export async function runSelfUpdate(options) {
|
|
|
170
248
|
}
|
|
171
249
|
const environment = options.environment ?? process.env;
|
|
172
250
|
const paths = resolveProductPaths(environment);
|
|
173
|
-
const lifecycle = options.lifecycle ?? createUpdateLifecycleCoordinator(environment, fileSystem);
|
|
251
|
+
const lifecycle = options.lifecycle ?? createUpdateLifecycleCoordinator(environment, fileSystem, output);
|
|
174
252
|
const transactionStore = options.transactionStore ?? new UpdateTransactionStore(paths.dataDir);
|
|
175
253
|
let transaction = await transactionStore.read();
|
|
176
254
|
try {
|
|
@@ -180,7 +258,8 @@ export async function runSelfUpdate(options) {
|
|
|
180
258
|
await transactionStore.finish("completed");
|
|
181
259
|
}
|
|
182
260
|
await transactionStore.clearCompleted();
|
|
183
|
-
|
|
261
|
+
progress.clear();
|
|
262
|
+
output.stdout(`${PRODUCT_TEXT.commandName} is already current and active for this channel.\n`);
|
|
184
263
|
return 0;
|
|
185
264
|
}
|
|
186
265
|
const cohortState = await new CohortStateStore(paths.dataDir).read();
|
|
@@ -191,27 +270,49 @@ export async function runSelfUpdate(options) {
|
|
|
191
270
|
priorActiveReleaseId: cohortState.references.active,
|
|
192
271
|
});
|
|
193
272
|
if (phaseBefore(transaction.phase, "ownership-released")) {
|
|
194
|
-
await
|
|
195
|
-
|
|
273
|
+
await measure("ownership-release", async () => {
|
|
274
|
+
await lifecycle.shutdownVerifiedOwners(targetVersion);
|
|
275
|
+
await lifecycle.verifyPackageUnlocked(packageRoot);
|
|
276
|
+
});
|
|
196
277
|
transaction = await transactionStore.advance("ownership-released");
|
|
197
278
|
}
|
|
279
|
+
progress.set(15, 70);
|
|
198
280
|
if (phaseBefore(transaction.phase, "package-installed")) {
|
|
199
|
-
|
|
200
|
-
const installation = await runNpm(runner, ["install", "--global", `${PRODUCT_PACKAGE}@${targetVersion}`], false, output, "start the global npm installation", false);
|
|
281
|
+
const installation = await measure("npm-install", async () => await runNpm(runner, ["install", "--global", "--loglevel=error", "--no-fund", "--no-audit", `${PRODUCT_PACKAGE}@${targetVersion}`], true, output, "start the global npm installation", false));
|
|
201
282
|
if (installation.result === null)
|
|
202
283
|
throw new UpdateFailure(installation.exitCode, "npm process failed");
|
|
203
|
-
if (installation.result.code !== 0)
|
|
284
|
+
if (installation.result.code !== 0) {
|
|
285
|
+
if (installation.result.stdout.trim().length > 0)
|
|
286
|
+
output.stderr(`${installation.result.stdout.trimEnd()}\n`);
|
|
204
287
|
throw new UpdateFailure(unsuccessfulCode(installation.result.code), `npm exited with status ${formatExitCode(installation.result.code)}`);
|
|
288
|
+
}
|
|
205
289
|
transaction = await transactionStore.advance("package-installed");
|
|
206
290
|
}
|
|
207
|
-
|
|
291
|
+
progress.set(70, 75);
|
|
292
|
+
// Ownership can be reacquired after an interrupted installation (for
|
|
293
|
+
// example, if bare A1 is launched before the update is resumed). Recheck
|
|
294
|
+
// immediately before activation so recovery cannot start a second cohort.
|
|
295
|
+
await measure("ownership-release", async () => { await lifecycle.shutdownVerifiedOwners(targetVersion); });
|
|
296
|
+
progress.set(75, 85);
|
|
297
|
+
let activationPhaseStartedAt = now();
|
|
298
|
+
await lifecycle.activateInstalled(packageRoot, targetVersion, async (phase) => {
|
|
299
|
+
options.onPhaseTiming?.({ phase, durationMs: Math.max(0, now() - activationPhaseStartedAt) });
|
|
300
|
+
transaction = await transactionStore.advance(phase);
|
|
301
|
+
progress.set(ACTIVATION_PROGRESS[phase].at, ACTIVATION_PROGRESS[phase].creepTo);
|
|
302
|
+
activationPhaseStartedAt = now();
|
|
303
|
+
});
|
|
304
|
+
options.onPhaseTiming?.({ phase: "supervisor-verified", durationMs: Math.max(0, now() - activationPhaseStartedAt) });
|
|
305
|
+
const transactionStartedAt = now();
|
|
208
306
|
await transactionStore.advance("supervisor-verified");
|
|
209
307
|
await transactionStore.finish("completed");
|
|
210
308
|
await transactionStore.clearCompleted();
|
|
211
|
-
|
|
309
|
+
options.onPhaseTiming?.({ phase: "transaction-complete", durationMs: Math.max(0, now() - transactionStartedAt) });
|
|
310
|
+
progress.finish();
|
|
311
|
+
output.stdout(`${PRODUCT_TEXT.commandName} updated successfully: ${targetVersion} (${channel}).\n`);
|
|
212
312
|
return 0;
|
|
213
313
|
}
|
|
214
314
|
catch (error) {
|
|
315
|
+
progress.clear();
|
|
215
316
|
const message = errorMessage(error);
|
|
216
317
|
const rollback = options.lifecycle
|
|
217
318
|
? "previous test lifecycle retained"
|
|
@@ -222,6 +323,21 @@ export async function runSelfUpdate(options) {
|
|
|
222
323
|
return error instanceof UpdateFailure ? error.exitCode : 1;
|
|
223
324
|
}
|
|
224
325
|
}
|
|
326
|
+
export function assertUpdatePerformanceBudget(evidence, maximumPostNpmDurationMs = 30_000) {
|
|
327
|
+
const failures = [];
|
|
328
|
+
if (evidence.fileCount < 1)
|
|
329
|
+
failures.push("fixture contains no payload files");
|
|
330
|
+
if (evidence.sourceReads !== evidence.fileCount)
|
|
331
|
+
failures.push(`source payload read count is ${evidence.sourceReads} for ${evidence.fileCount} files`);
|
|
332
|
+
if (evidence.candidateWrites !== evidence.fileCount)
|
|
333
|
+
failures.push(`candidate payload write count is ${evidence.candidateWrites} for ${evidence.fileCount} files`);
|
|
334
|
+
if (evidence.verificationReads > 0)
|
|
335
|
+
failures.push(`fresh certification reread ${evidence.verificationReads} candidate files`);
|
|
336
|
+
if (evidence.postNpmDurationMs > maximumPostNpmDurationMs)
|
|
337
|
+
failures.push(`post-npm activation took ${Math.round(evidence.postNpmDurationMs)}ms; budget is ${maximumPostNpmDurationMs}ms`);
|
|
338
|
+
if (failures.length > 0)
|
|
339
|
+
throw new Error(`update performance budget failed: ${failures.join("; ")}`);
|
|
340
|
+
}
|
|
225
341
|
async function requestUpdateShutdown(metadata, targetVersion, timeoutMs) {
|
|
226
342
|
if (!processIsAlive(metadata.pid))
|
|
227
343
|
return { accepted: false, reason: "recorded owner is dead" };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DatabaseSync } from "node:sqlite";
|
|
2
2
|
import type { ManagedAgentDescriptor, PaneId, AgentRecoveryAuthority, RecoveryReferenceId, TerminalSessionLaunch, TerminalTopologySnapshot } from "../workspace-contracts/index.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type { LaunchInstance, LaunchInstanceId, LaunchInstanceOutcome, NativeProcessIdentity, ProcessContainmentIdentity } from "../lifecycle/index.js";
|
|
4
4
|
export declare const DEFAULT_WORKSPACE_ID = "workspace-default";
|
|
5
5
|
export interface WorkspaceAgentPresentation {
|
|
6
6
|
readonly unreadActivity: number;
|
|
@@ -21,12 +21,13 @@ export declare class ControlStore {
|
|
|
21
21
|
constructor(path: string, bootNonce?: string | null);
|
|
22
22
|
migrate(): void;
|
|
23
23
|
reconcilePriorBootGenerations(bootNonce: string): number;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
createLaunchInstance(instance: LaunchInstance): void;
|
|
25
|
+
activateLaunchInstance(instanceId: LaunchInstanceId, ownerClientId: string, rootIdentity: NativeProcessIdentity, containmentIdentity: ProcessContainmentIdentity, activatedAt: string): boolean;
|
|
26
|
+
beginLaunchInstanceStop(instanceId: LaunchInstanceId, ownerClientId: string, stoppingAt: string): boolean;
|
|
27
|
+
completeLaunchInstance(instanceId: LaunchInstanceId, ownerClientId: string, terminalState: "completed" | "interrupted", outcome: LaunchInstanceOutcome, completedAt: string): boolean;
|
|
28
|
+
loadActiveLaunchInstances(): LaunchInstance[];
|
|
29
|
+
loadLaunchInstance(instanceId: LaunchInstanceId): LaunchInstance | null;
|
|
30
|
+
reconcilePriorBootLaunchInstances(bootNonce: string, reconciledAt?: string): number;
|
|
30
31
|
persistWorkspaceAgent(agent: ManagedAgentDescriptor, updatedAt?: string): void;
|
|
31
32
|
persistWorkspaceAgentRecord(record: StoredWorkspaceAgent, updatedAt?: string): void;
|
|
32
33
|
replaceWorkspaceAgentRecords(records: readonly StoredWorkspaceAgent[], selectedAgentId: string | null, revision: number, updatedAt?: string): void;
|
|
@@ -3,6 +3,7 @@ import { mkdirSync } from "node:fs";
|
|
|
3
3
|
import { dirname } from "node:path";
|
|
4
4
|
import { PRODUCT_IDENTITY } from "../../product-identity.js";
|
|
5
5
|
import { assertManagedAgentDescriptor, assertRecoveryAuthority, assertTerminalSessionLaunch, assertTerminalTopologySnapshot, } from "../workspace-contracts/index.js";
|
|
6
|
+
import { assertLaunchInstance, assertLaunchInstanceOutcome, assertNativeProcessIdentity, assertProcessContainmentIdentity, } from "../lifecycle/index.js";
|
|
6
7
|
export const DEFAULT_WORKSPACE_ID = "workspace-default";
|
|
7
8
|
const INITIAL_WORKSPACE_ID = DEFAULT_WORKSPACE_ID;
|
|
8
9
|
export class ControlStore {
|
|
@@ -18,7 +19,7 @@ export class ControlStore {
|
|
|
18
19
|
this.migrate();
|
|
19
20
|
if (bootNonce !== null) {
|
|
20
21
|
this.reconcilePriorBootGenerations(bootNonce);
|
|
21
|
-
this.
|
|
22
|
+
this.reconcilePriorBootLaunchInstances(bootNonce);
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
catch (error) {
|
|
@@ -29,8 +30,8 @@ export class ControlStore {
|
|
|
29
30
|
migrate() {
|
|
30
31
|
const versionRow = this.database.prepare("PRAGMA user_version").get();
|
|
31
32
|
const version = versionRow.user_version;
|
|
32
|
-
if (version >
|
|
33
|
-
throw new Error(`control database version ${version} is newer than supported version
|
|
33
|
+
if (version > 5)
|
|
34
|
+
throw new Error(`control database version ${version} is newer than supported version 5`);
|
|
34
35
|
if (version !== 0)
|
|
35
36
|
this.#assertCurrentControlSchema();
|
|
36
37
|
if (version === 0) {
|
|
@@ -172,6 +173,41 @@ export class ControlStore {
|
|
|
172
173
|
ALTER TABLE workspaces ADD COLUMN revision INTEGER NOT NULL DEFAULT 0 CHECK (revision >= 0);
|
|
173
174
|
PRAGMA user_version = 4;
|
|
174
175
|
COMMIT;
|
|
176
|
+
`);
|
|
177
|
+
}
|
|
178
|
+
if (version <= 4) {
|
|
179
|
+
this.database.exec(`
|
|
180
|
+
BEGIN IMMEDIATE;
|
|
181
|
+
UPDATE foreground_terminal_leases
|
|
182
|
+
SET state = 'interrupted',
|
|
183
|
+
released_at = COALESCE(released_at, strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
184
|
+
outcome_json = '{"kind":"interrupted","reason":"legacy-migration","message":"legacy foreground ownership cannot prove current launch-instance liveness"}'
|
|
185
|
+
WHERE state IN ('requested', 'active');
|
|
186
|
+
DROP INDEX IF EXISTS idx_one_live_foreground_lease;
|
|
187
|
+
CREATE TABLE launch_instances (
|
|
188
|
+
id TEXT PRIMARY KEY,
|
|
189
|
+
owner_client_id TEXT NOT NULL,
|
|
190
|
+
profile_id TEXT NOT NULL CHECK (profile_id IN ('a1', 'pi', 'sandbox')),
|
|
191
|
+
state TEXT NOT NULL CHECK (state IN ('requested', 'active', 'stopping', 'completed', 'interrupted')),
|
|
192
|
+
shutdown_policy TEXT NOT NULL CHECK (shutdown_policy = 'terminate-tree-on-close'),
|
|
193
|
+
guardian_identity_json TEXT NOT NULL CHECK (json_valid(guardian_identity_json)),
|
|
194
|
+
root_identity_json TEXT CHECK (root_identity_json IS NULL OR json_valid(root_identity_json)),
|
|
195
|
+
containment_identity_json TEXT CHECK (containment_identity_json IS NULL OR json_valid(containment_identity_json)),
|
|
196
|
+
created_at TEXT NOT NULL,
|
|
197
|
+
activated_at TEXT,
|
|
198
|
+
stopping_at TEXT,
|
|
199
|
+
completed_at TEXT,
|
|
200
|
+
outcome_json TEXT CHECK (outcome_json IS NULL OR json_valid(outcome_json)),
|
|
201
|
+
owner_boot_nonce TEXT NOT NULL,
|
|
202
|
+
CHECK ((state = 'requested' AND root_identity_json IS NULL AND containment_identity_json IS NULL AND activated_at IS NULL AND stopping_at IS NULL AND completed_at IS NULL AND outcome_json IS NULL)
|
|
203
|
+
OR (state = 'active' AND root_identity_json IS NOT NULL AND containment_identity_json IS NOT NULL AND activated_at IS NOT NULL AND stopping_at IS NULL AND completed_at IS NULL AND outcome_json IS NULL)
|
|
204
|
+
OR (state = 'stopping' AND root_identity_json IS NOT NULL AND containment_identity_json IS NOT NULL AND activated_at IS NOT NULL AND stopping_at IS NOT NULL AND completed_at IS NULL AND outcome_json IS NULL)
|
|
205
|
+
OR (state IN ('completed', 'interrupted') AND completed_at IS NOT NULL AND outcome_json IS NOT NULL))
|
|
206
|
+
);
|
|
207
|
+
CREATE INDEX idx_launch_instances_owner ON launch_instances(owner_client_id, state);
|
|
208
|
+
CREATE INDEX idx_launch_instances_boot ON launch_instances(owner_boot_nonce, state);
|
|
209
|
+
PRAGMA user_version = 5;
|
|
210
|
+
COMMIT;
|
|
175
211
|
`);
|
|
176
212
|
}
|
|
177
213
|
if (version === 0) {
|
|
@@ -199,61 +235,70 @@ export class ControlStore {
|
|
|
199
235
|
return Number(result.changes);
|
|
200
236
|
});
|
|
201
237
|
}
|
|
202
|
-
|
|
238
|
+
createLaunchInstance(instance) {
|
|
203
239
|
if (this.bootNonce === null)
|
|
204
|
-
throw new Error("
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
catch (error) {
|
|
215
|
-
if (error instanceof Error && /UNIQUE constraint failed/i.test(error.message))
|
|
216
|
-
throw new Error("an exclusive foreground terminal lease is already live");
|
|
217
|
-
throw error;
|
|
218
|
-
}
|
|
240
|
+
throw new Error("launch instance storage requires a supervisor boot identity");
|
|
241
|
+
assertLaunchInstance(instance);
|
|
242
|
+
if (instance.state !== "requested")
|
|
243
|
+
throw new Error("new launch instance must be requested");
|
|
244
|
+
this.database.prepare(`INSERT INTO launch_instances
|
|
245
|
+
(id, owner_client_id, profile_id, state, shutdown_policy, guardian_identity_json, root_identity_json, containment_identity_json,
|
|
246
|
+
created_at, activated_at, stopping_at, completed_at, outcome_json, owner_boot_nonce)
|
|
247
|
+
VALUES (?, ?, ?, 'requested', ?, ?, NULL, NULL, ?, NULL, NULL, NULL, NULL, ?)`)
|
|
248
|
+
.run(instance.id, instance.ownerClientId, instance.profileId, instance.shutdownPolicy, JSON.stringify(instance.guardianIdentity), instance.createdAt, this.bootNonce);
|
|
219
249
|
}
|
|
220
|
-
|
|
250
|
+
activateLaunchInstance(instanceId, ownerClientId, rootIdentity, containmentIdentity, activatedAt) {
|
|
221
251
|
if (this.bootNonce === null)
|
|
222
|
-
throw new Error("
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
252
|
+
throw new Error("launch instance storage requires a supervisor boot identity");
|
|
253
|
+
assertNativeProcessIdentity(rootIdentity);
|
|
254
|
+
assertProcessContainmentIdentity(containmentIdentity);
|
|
255
|
+
const result = this.database.prepare(`UPDATE launch_instances
|
|
256
|
+
SET state = 'active', root_identity_json = ?, containment_identity_json = ?, activated_at = ?
|
|
257
|
+
WHERE id = ? AND owner_client_id = ? AND owner_boot_nonce = ? AND state = 'requested'`)
|
|
258
|
+
.run(JSON.stringify(rootIdentity), JSON.stringify(containmentIdentity), activatedAt, instanceId, ownerClientId, this.bootNonce);
|
|
227
259
|
return Number(result.changes) === 1;
|
|
228
260
|
}
|
|
229
|
-
|
|
261
|
+
beginLaunchInstanceStop(instanceId, ownerClientId, stoppingAt) {
|
|
230
262
|
if (this.bootNonce === null)
|
|
231
|
-
throw new Error("
|
|
232
|
-
const result = this.database.prepare(`UPDATE
|
|
233
|
-
WHERE id = ? AND
|
|
234
|
-
.run(
|
|
263
|
+
throw new Error("launch instance storage requires a supervisor boot identity");
|
|
264
|
+
const result = this.database.prepare(`UPDATE launch_instances SET state = 'stopping', stopping_at = ?
|
|
265
|
+
WHERE id = ? AND owner_client_id = ? AND owner_boot_nonce = ? AND state = 'active'`)
|
|
266
|
+
.run(stoppingAt, instanceId, ownerClientId, this.bootNonce);
|
|
235
267
|
return Number(result.changes) === 1;
|
|
236
268
|
}
|
|
237
|
-
|
|
269
|
+
completeLaunchInstance(instanceId, ownerClientId, terminalState, outcome, completedAt) {
|
|
238
270
|
if (this.bootNonce === null)
|
|
239
|
-
throw new Error("
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
271
|
+
throw new Error("launch instance storage requires a supervisor boot identity");
|
|
272
|
+
assertLaunchInstanceOutcome(outcome);
|
|
273
|
+
if (terminalState === "completed" && outcome.kind === "interrupted")
|
|
274
|
+
throw new Error("completed launch instance cannot carry an interrupted outcome");
|
|
275
|
+
if (terminalState === "interrupted" && outcome.kind !== "interrupted" && outcome.kind !== "cleanup-error") {
|
|
276
|
+
throw new Error("interrupted launch instance requires an interrupted or cleanup-error outcome");
|
|
277
|
+
}
|
|
278
|
+
const result = this.database.prepare(`UPDATE launch_instances
|
|
279
|
+
SET state = ?, completed_at = ?, outcome_json = ?
|
|
280
|
+
WHERE id = ? AND owner_client_id = ? AND owner_boot_nonce = ? AND state IN ('requested', 'active', 'stopping')`)
|
|
281
|
+
.run(terminalState, completedAt, JSON.stringify(outcome), instanceId, ownerClientId, this.bootNonce);
|
|
246
282
|
return Number(result.changes) === 1;
|
|
247
283
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
284
|
+
loadActiveLaunchInstances() {
|
|
285
|
+
return this.database.prepare(`SELECT * FROM launch_instances
|
|
286
|
+
WHERE state IN ('requested', 'active', 'stopping') ORDER BY created_at, id`).all()
|
|
287
|
+
.map(launchInstanceFromRow);
|
|
251
288
|
}
|
|
252
|
-
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
289
|
+
loadLaunchInstance(instanceId) {
|
|
290
|
+
const row = this.database.prepare("SELECT * FROM launch_instances WHERE id = ?").get(instanceId);
|
|
291
|
+
return row ? launchInstanceFromRow(row) : null;
|
|
292
|
+
}
|
|
293
|
+
reconcilePriorBootLaunchInstances(bootNonce, reconciledAt = new Date().toISOString()) {
|
|
294
|
+
const outcome = {
|
|
295
|
+
kind: "interrupted",
|
|
296
|
+
reason: "supervisor-disconnect",
|
|
297
|
+
message: "launch instance ownership ended with a prior supervisor boot",
|
|
298
|
+
};
|
|
299
|
+
const result = this.database.prepare(`UPDATE launch_instances
|
|
300
|
+
SET state = 'interrupted', completed_at = ?, outcome_json = ?
|
|
301
|
+
WHERE state IN ('requested', 'active', 'stopping') AND owner_boot_nonce <> ?`)
|
|
257
302
|
.run(reconciledAt, JSON.stringify(outcome), bootNonce);
|
|
258
303
|
return Number(result.changes);
|
|
259
304
|
}
|
|
@@ -464,17 +509,22 @@ function assertWorkspaceAgentPresentation(presentation) {
|
|
|
464
509
|
}
|
|
465
510
|
}
|
|
466
511
|
}
|
|
467
|
-
function
|
|
468
|
-
|
|
512
|
+
function launchInstanceFromRow(row) {
|
|
513
|
+
const instance = {
|
|
469
514
|
id: row.id,
|
|
470
|
-
|
|
471
|
-
|
|
515
|
+
ownerClientId: row.owner_client_id,
|
|
516
|
+
profileId: row.profile_id,
|
|
472
517
|
state: row.state,
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
518
|
+
shutdownPolicy: row.shutdown_policy,
|
|
519
|
+
guardianIdentity: JSON.parse(row.guardian_identity_json),
|
|
520
|
+
rootIdentity: row.root_identity_json ? JSON.parse(row.root_identity_json) : null,
|
|
521
|
+
containmentIdentity: row.containment_identity_json ? JSON.parse(row.containment_identity_json) : null,
|
|
522
|
+
createdAt: row.created_at,
|
|
523
|
+
activatedAt: row.activated_at,
|
|
524
|
+
stoppingAt: row.stopping_at,
|
|
525
|
+
completedAt: row.completed_at,
|
|
478
526
|
outcome: row.outcome_json ? JSON.parse(row.outcome_json) : null,
|
|
479
527
|
};
|
|
528
|
+
assertLaunchInstance(instance);
|
|
529
|
+
return instance;
|
|
480
530
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { appendFileSync, mkdirSync } from "node:fs";
|
|
3
|
-
import {
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { assertImmutableExecutionRoot, readCertifiedReleaseManifest } from "../release/index.js";
|
|
4
5
|
import { ControlStore } from "../storage/index.js";
|
|
5
6
|
import { resolveProductPaths } from "./paths.js";
|
|
6
7
|
import { SupervisorServer } from "./server.js";
|
|
@@ -10,11 +11,11 @@ export async function runSupervisor() {
|
|
|
10
11
|
mkdirSync(paths.runtimeDir, { recursive: true, mode: 0o700 });
|
|
11
12
|
const log = (message) => appendFileSync(paths.supervisorLogPath, `${new Date().toISOString()} ${message}\n`);
|
|
12
13
|
const releaseRoot = process.env[PRODUCT_IDENTITY.environment.releaseRoot];
|
|
13
|
-
|
|
14
|
+
const releaseId = process.env[PRODUCT_IDENTITY.environment.releaseId];
|
|
15
|
+
const contentDigest = process.env[PRODUCT_IDENTITY.environment.releaseDigest];
|
|
16
|
+
if (!releaseRoot || !releaseId || !contentDigest)
|
|
14
17
|
throw new Error(PRODUCT_TEXT.diagnostic("supervisor must be launched from a verified immutable release"));
|
|
15
|
-
const release = await
|
|
16
|
-
if (process.env[PRODUCT_IDENTITY.environment.releaseId] !== release.releaseId)
|
|
17
|
-
throw new Error(PRODUCT_TEXT.diagnostic("selected release identity does not match its verified manifest"));
|
|
18
|
+
const release = await readCertifiedReleaseManifest({ releaseRoot, releaseId, contentDigest }, resolve(paths.dataDir, "releases"));
|
|
18
19
|
await assertImmutableExecutionRoot(release, paths.dataDir);
|
|
19
20
|
const bootNonce = randomUUID();
|
|
20
21
|
const store = new ControlStore(paths.databasePath, bootNonce);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type SupervisorSnapshot } from "../lifecycle/index.js";
|
|
2
|
-
import type
|
|
2
|
+
import { type MaterializedRelease } from "../release/index.js";
|
|
3
3
|
import { ControlStore } from "../storage/index.js";
|
|
4
4
|
import { type ProductPaths } from "./paths.js";
|
|
5
5
|
export declare class SupervisorServer {
|
|
@@ -7,12 +7,14 @@ export declare class SupervisorServer {
|
|
|
7
7
|
readonly store: ControlStore;
|
|
8
8
|
readonly release: MaterializedRelease;
|
|
9
9
|
readonly terminateProcess: (code: number) => void;
|
|
10
|
+
readonly reconciliationDeadlineMs: number;
|
|
11
|
+
readonly shutdownDeadlineMs: number;
|
|
10
12
|
readonly id: `${string}-${string}-${string}-${string}-${string}`;
|
|
11
13
|
readonly bootNonce: string;
|
|
12
14
|
readonly pidStartIdentity: string;
|
|
13
15
|
readonly startedAt: string;
|
|
14
16
|
readonly paths: ProductPaths;
|
|
15
|
-
constructor(store: ControlStore, paths: ProductPaths | undefined, release: MaterializedRelease, bootNonce?: string, terminateProcess?: (code: number) => void);
|
|
17
|
+
constructor(store: ControlStore, paths: ProductPaths | undefined, release: MaterializedRelease, bootNonce?: string, terminateProcess?: (code: number) => void, reconciliationDeadlineMs?: number, shutdownDeadlineMs?: number);
|
|
16
18
|
snapshot(): SupervisorSnapshot;
|
|
17
19
|
listen(): Promise<void>;
|
|
18
20
|
close(stopAgents?: boolean): Promise<void>;
|