@zixt/host 0.0.80 → 0.0.82

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +676 -328
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -16,22 +16,22 @@ import { fstatSync } from "node:fs";
16
16
  import {
17
17
  access as access2,
18
18
  lstat as lstat5,
19
- mkdir as mkdir4,
19
+ mkdir as mkdir5,
20
20
  open as open4,
21
- readFile as readFile6,
21
+ readFile as readFile7,
22
22
  readlink,
23
- readdir as readdir3,
23
+ readdir as readdir4,
24
24
  rename as rename3,
25
- rm as rm4,
25
+ rm as rm5,
26
26
  symlink
27
27
  } from "node:fs/promises";
28
- import { basename as basename3, dirname as dirname4, isAbsolute as isAbsolute8, join as join7, relative as relative4, resolve as resolve5, sep as sep4 } from "node:path";
29
- import { homedir as homedir2 } from "node:os";
28
+ import { basename as basename3, dirname as dirname4, isAbsolute as isAbsolute9, join as join8, relative as relative4, resolve as resolve5, sep as sep4 } from "node:path";
29
+ import { homedir as homedir3 } from "node:os";
30
30
 
31
31
  // package.json
32
32
  var package_default = {
33
33
  name: "@zixt/host",
34
- version: "0.0.80",
34
+ version: "0.0.82",
35
35
  type: "module",
36
36
  exports: {
37
37
  ".": "./src/client.ts",
@@ -14661,6 +14661,8 @@ var ID_PREFIXES = {
14661
14661
  conversationEvent: "cve",
14662
14662
  /** One human-confirmed integration action prepared by the Manager. */
14663
14663
  managerIntegrationAction: "mia",
14664
+ /** One Manager-prepared secure Credential entry card (MG-17). */
14665
+ managerCredentialRequest: "mcr",
14664
14666
  /** One Manager inference call's token-metering row (MG-8). */
14665
14667
  managerUsage: "mgu",
14666
14668
  /** One ordered Manager reply awaiting Slack delivery. */
@@ -14712,6 +14714,10 @@ var ManagerIntegrationActionId = idSchema(
14712
14714
  ID_PREFIXES.managerIntegrationAction,
14713
14715
  "Manager integration action id"
14714
14716
  );
14717
+ var ManagerCredentialRequestId = idSchema(
14718
+ ID_PREFIXES.managerCredentialRequest,
14719
+ "Manager credential request id"
14720
+ );
14715
14721
  var ManagerEmailInboxId = idSchema(
14716
14722
  ID_PREFIXES.managerEmailInbox,
14717
14723
  "Manager email inbox id"
@@ -18331,7 +18337,9 @@ var ConversationEventProjection = external_exports.discriminatedUnion("kind", [
18331
18337
  taskId: TaskId.nullable(),
18332
18338
  agentId: AgentId.nullable(),
18333
18339
  /** Present only for a confirmation card; OAuth authority never appears here. */
18334
- integrationActionId: ManagerIntegrationActionId.nullable().optional()
18340
+ integrationActionId: ManagerIntegrationActionId.nullable().optional(),
18341
+ /** Present only for a secure Credential entry card; never a value (MG-17). */
18342
+ credentialRequestId: ManagerCredentialRequestId.nullable().optional()
18335
18343
  }).strict(),
18336
18344
  /** A mirrored child-Task event: what the teammate wrote or became. */
18337
18345
  external_exports.object({
@@ -18397,6 +18405,48 @@ var ManagerIntegrationActionResponse = external_exports.object({
18397
18405
  action: ManagerIntegrationActionProjection,
18398
18406
  oauth: ManagerIntegrationOAuthStart.nullable()
18399
18407
  }).strict();
18408
+ var ManagerCredentialRequestStatus = external_exports.enum([
18409
+ "awaiting_entry",
18410
+ "storing",
18411
+ "stored",
18412
+ "cancelled",
18413
+ "expired",
18414
+ "failed"
18415
+ ]);
18416
+ var ManagerCredentialRequestProjection = external_exports.object({
18417
+ id: ManagerCredentialRequestId,
18418
+ conversationId: ConversationId,
18419
+ /** The Credential name, exactly as it will appear in Credentials. */
18420
+ name: external_exports.string().min(1).max(120),
18421
+ /** `env` reaches a Task as an environment variable; `web_login` fills a sign-in form. */
18422
+ kind: external_exports.enum(["env", "web_login"]),
18423
+ /** Saved as the Credential's description so teammates know what they hold. */
18424
+ purpose: external_exports.string().max(500).nullable(),
18425
+ scope: external_exports.enum(["organization", "teammates"]),
18426
+ /** Named teammates for a teammate-scoped Credential; empty for organization scope. */
18427
+ teammates: external_exports.array(external_exports.object({ agentId: AgentId, name: external_exports.string().min(1).max(200) }).strict()).max(100),
18428
+ /** Suggested sign-in page for a website login; the person can correct it. */
18429
+ loginUrl: external_exports.url().max(2e3).nullable(),
18430
+ status: ManagerCredentialRequestStatus,
18431
+ outcome: external_exports.string().max(1e3).nullable(),
18432
+ createdAt: external_exports.string(),
18433
+ expiresAt: external_exports.string()
18434
+ }).strict();
18435
+ var SubmitManagerCredentialRequest = external_exports.object({
18436
+ requestId: external_exports.uuid(),
18437
+ /** env kind. */
18438
+ value: external_exports.string().min(1).max(1e4).optional(),
18439
+ /** web_login kind. */
18440
+ webLogin: WebLoginValue.optional()
18441
+ }).strict().superRefine((request, ctx) => {
18442
+ if (request.value === void 0 === (request.webLogin === void 0)) {
18443
+ ctx.addIssue({
18444
+ code: "custom",
18445
+ path: ["value"],
18446
+ message: "submit exactly one of value or webLogin, matching the requested kind"
18447
+ });
18448
+ }
18449
+ });
18400
18450
  var NonEmptyTaskRunnerSelection = TaskRunnerSelection.refine(
18401
18451
  (selection) => selection.type !== void 0 || selection.model !== void 0 || selection.effort !== void 0,
18402
18452
  "choose at least one runtime preference"
@@ -20892,6 +20942,7 @@ var WORKER_WATCHDOG_FILE_ENV = "ZIXT_HOST_WORKER_WATCHDOG_FILE";
20892
20942
  var WORKER_WATCHDOG_BOUNDARY_PID_ENV = "ZIXT_MANAGED_PROCESS_BOUNDARY_PID";
20893
20943
  var WORKER_WATCHDOG_MESSAGE = "zixt.host.worker-heartbeat.v1";
20894
20944
  var WORKER_READINESS_MESSAGE = "zixt.host.worker-readiness.v1";
20945
+ var WORKER_SHUTDOWN_MESSAGE = "zixt.host.worker-shutdown.v1";
20895
20946
  var WORKER_HEARTBEAT_MS = 1e3;
20896
20947
  var SAFE_NONCE = /^[A-Za-z0-9_-]{16,200}$/;
20897
20948
  function createWorkerWatchdogLaunch(ownershipDirectory) {
@@ -20917,10 +20968,16 @@ function isWorkerReadinessMilestone(value, launch, pid) {
20917
20968
  const message = value;
20918
20969
  return message.type === WORKER_READINESS_MESSAGE && message.nonce === launch.nonce && typeof message.pid === "number" && Number.isSafeInteger(message.pid) && message.pid === pid && typeof message.sequence === "number" && Number.isSafeInteger(message.sequence) && message.sequence > 0 && typeof message.heartbeatSequence === "number" && Number.isSafeInteger(message.heartbeatSequence) && message.heartbeatSequence > 0;
20919
20970
  }
20971
+ function isWorkerShutdownIntent(value, launch, pid) {
20972
+ if (!value || typeof value !== "object") return false;
20973
+ const message = value;
20974
+ return message.type === WORKER_SHUTDOWN_MESSAGE && message.nonce === launch.nonce && typeof message.pid === "number" && Number.isSafeInteger(message.pid) && message.pid === pid && typeof message.sequence === "number" && Number.isSafeInteger(message.sequence) && message.sequence > 0 && typeof message.exitCode === "number" && Number.isSafeInteger(message.exitCode) && message.exitCode >= 0 && message.exitCode <= 255 && typeof message.activeTasks === "number" && Number.isSafeInteger(message.activeTasks) && message.activeTasks >= 0;
20975
+ }
20920
20976
  var heartbeatActive = false;
20921
20977
  var heartbeatUsesIpc = false;
20922
20978
  var heartbeatHasDurableOwner = false;
20923
20979
  var readinessReporter = null;
20980
+ var shutdownReporter = null;
20924
20981
  function createWorkerWatchdogSendDrain() {
20925
20982
  let pending = 0;
20926
20983
  const drained = [];
@@ -20957,6 +21014,7 @@ function startWorkerWatchdogHeartbeat(env = process.env, argv = process.argv.sli
20957
21014
  heartbeatUsesIpc = false;
20958
21015
  heartbeatHasDurableOwner = false;
20959
21016
  readinessReporter = null;
21017
+ shutdownReporter = null;
20960
21018
  return { active: false, argv: ownership.argv, async stop() {
20961
21019
  } };
20962
21020
  }
@@ -20968,6 +21026,7 @@ function startWorkerWatchdogHeartbeat(env = process.env, argv = process.argv.sli
20968
21026
  heartbeatUsesIpc = false;
20969
21027
  heartbeatHasDurableOwner = false;
20970
21028
  readinessReporter = null;
21029
+ shutdownReporter = null;
20971
21030
  return { active: false, argv: ownership.argv, async stop() {
20972
21031
  } };
20973
21032
  }
@@ -20979,6 +21038,7 @@ function startWorkerWatchdogHeartbeat(env = process.env, argv = process.argv.sli
20979
21038
  heartbeatUsesIpc = false;
20980
21039
  heartbeatHasDurableOwner = false;
20981
21040
  readinessReporter = null;
21041
+ shutdownReporter = null;
20982
21042
  return { active: false, argv: ownership.argv, async stop() {
20983
21043
  } };
20984
21044
  }
@@ -20987,6 +21047,7 @@ function startWorkerWatchdogHeartbeat(env = process.env, argv = process.argv.sli
20987
21047
  heartbeatUsesIpc = false;
20988
21048
  heartbeatHasDurableOwner = false;
20989
21049
  readinessReporter = null;
21050
+ shutdownReporter = null;
20990
21051
  return { active: false, argv: ownership.argv, async stop() {
20991
21052
  } };
20992
21053
  }
@@ -21019,6 +21080,32 @@ function startWorkerWatchdogHeartbeat(env = process.env, argv = process.argv.sli
21019
21080
  return false;
21020
21081
  }
21021
21082
  };
21083
+ let shutdownSequence = 0;
21084
+ const reportShutdown = (exitCode, activeTasks) => {
21085
+ if (stopped || !ipc || sequence === 0 || !process.connected || typeof process.send !== "function") {
21086
+ return false;
21087
+ }
21088
+ const message = {
21089
+ type: WORKER_SHUTDOWN_MESSAGE,
21090
+ nonce,
21091
+ pid: boundaryPid,
21092
+ sequence: ++shutdownSequence,
21093
+ exitCode,
21094
+ activeTasks
21095
+ };
21096
+ const sendComplete = sendDrain.begin();
21097
+ try {
21098
+ process.send(message, (error52) => {
21099
+ sendComplete();
21100
+ if (error52) stop();
21101
+ });
21102
+ return true;
21103
+ } catch {
21104
+ sendComplete();
21105
+ stop();
21106
+ return false;
21107
+ }
21108
+ };
21022
21109
  const stop = async () => {
21023
21110
  if (!stopped) {
21024
21111
  stopped = true;
@@ -21026,6 +21113,7 @@ function startWorkerWatchdogHeartbeat(env = process.env, argv = process.argv.sli
21026
21113
  heartbeatUsesIpc = false;
21027
21114
  heartbeatHasDurableOwner = false;
21028
21115
  if (readinessReporter === reportReadiness) readinessReporter = null;
21116
+ if (shutdownReporter === reportShutdown) shutdownReporter = null;
21029
21117
  clearInterval(timer);
21030
21118
  process.off("disconnect", onDisconnect);
21031
21119
  }
@@ -21079,11 +21167,15 @@ function startWorkerWatchdogHeartbeat(env = process.env, argv = process.argv.sli
21079
21167
  heartbeatHasDurableOwner = ipc;
21080
21168
  heartbeatActive = true;
21081
21169
  readinessReporter = ipc ? reportReadiness : null;
21170
+ shutdownReporter = ipc ? reportShutdown : null;
21082
21171
  return { active: true, argv: ownership.argv, stop };
21083
21172
  }
21084
21173
  function reportWorkerReadiness() {
21085
21174
  return readinessReporter?.() ?? false;
21086
21175
  }
21176
+ function reportWorkerShutdown(exitCode, activeTasks) {
21177
+ return shutdownReporter?.(exitCode, activeTasks) ?? false;
21178
+ }
21087
21179
  function workerWatchdogIsActive() {
21088
21180
  return heartbeatActive && heartbeatHasDurableOwner && heartbeatUsesIpc && process.connected;
21089
21181
  }
@@ -24042,27 +24134,135 @@ function createReleaseStateStore(root) {
24042
24134
  };
24043
24135
  }
24044
24136
 
24137
+ // src/worker-diagnostics.ts
24138
+ import { randomUUID as randomUUID2 } from "node:crypto";
24139
+ import { mkdir as mkdir3, readdir as readdir2, readFile as readFile5, rm as rm3, writeFile } from "node:fs/promises";
24140
+ import { homedir } from "node:os";
24141
+ import { isAbsolute as isAbsolute6, join as join6 } from "node:path";
24142
+ var WORKER_DIAGNOSTICS_DIR_ENV = "ZIXT_HOST_DIAGNOSTICS_DIR";
24143
+ var RETAINED_RECORDS = 20;
24144
+ var STDERR_TAIL_LINES = 40;
24145
+ var STDERR_LINE_LIMIT = 800;
24146
+ var RECORD_TTL_MS = 7 * 24 * 60 * 6e4;
24147
+ var RECORD_FILE = /^[0-9a-f-]{36}\.json$/;
24148
+ function defaultWorkerDiagnosticsRoot() {
24149
+ return join6(homedir(), ".zixt", "host-diagnostics");
24150
+ }
24151
+ function configuredWorkerDiagnosticsRoot(env = process.env) {
24152
+ const configured = env[WORKER_DIAGNOSTICS_DIR_ENV];
24153
+ return typeof configured === "string" && isAbsolute6(configured) ? configured : null;
24154
+ }
24155
+ function boundedStderr(lines) {
24156
+ return lines.slice(-STDERR_TAIL_LINES).map(
24157
+ (line) => line.length > STDERR_LINE_LIMIT ? `${line.slice(0, STDERR_LINE_LIMIT)}\u2026` : line
24158
+ );
24159
+ }
24160
+ async function recordWorkerExit(root, record2) {
24161
+ try {
24162
+ await mkdir3(root, { recursive: true, mode: 448 });
24163
+ const stored = {
24164
+ ...record2,
24165
+ schema: 1,
24166
+ stderr: boundedStderr(record2.stderr)
24167
+ };
24168
+ await writeFile(join6(root, `${randomUUID2()}.json`), JSON.stringify(stored), {
24169
+ encoding: "utf8",
24170
+ mode: 384
24171
+ });
24172
+ await pruneWorkerExits(root, Date.parse(record2.at));
24173
+ return true;
24174
+ } catch {
24175
+ return false;
24176
+ }
24177
+ }
24178
+ function parseRecord2(raw) {
24179
+ let value;
24180
+ try {
24181
+ value = JSON.parse(raw);
24182
+ } catch {
24183
+ return null;
24184
+ }
24185
+ if (!value || typeof value !== "object") return null;
24186
+ const record2 = value;
24187
+ if (record2.schema !== 1 || typeof record2.at !== "string" || !Number.isFinite(Date.parse(record2.at)))
24188
+ return null;
24189
+ if (!Array.isArray(record2.stderr) || record2.stderr.some((line) => typeof line !== "string")) {
24190
+ return null;
24191
+ }
24192
+ return { ...record2, stderr: boundedStderr(record2.stderr) };
24193
+ }
24194
+ async function readWorkerExits(root) {
24195
+ let names;
24196
+ try {
24197
+ names = await readdir2(root);
24198
+ } catch {
24199
+ return [];
24200
+ }
24201
+ const stored = [];
24202
+ for (const name of names) {
24203
+ if (!RECORD_FILE.test(name)) continue;
24204
+ const file2 = join6(root, name);
24205
+ try {
24206
+ const record2 = parseRecord2(await readFile5(file2, "utf8"));
24207
+ if (record2) stored.push({ file: file2, record: record2 });
24208
+ } catch {
24209
+ }
24210
+ }
24211
+ return stored.sort((a, b) => Date.parse(a.record.at) - Date.parse(b.record.at));
24212
+ }
24213
+ async function forgetWorkerExits(files) {
24214
+ await Promise.all(files.map((file2) => rm3(file2, { force: true }).catch(() => {
24215
+ })));
24216
+ }
24217
+ async function pruneWorkerExits(root, nowMs) {
24218
+ const stored = await readWorkerExits(root);
24219
+ const expired = stored.filter(({ record: record2 }) => nowMs - Date.parse(record2.at) > RECORD_TTL_MS);
24220
+ const surplus = stored.filter((entry) => !expired.includes(entry)).slice(0, Math.max(0, stored.length - expired.length - RETAINED_RECORDS));
24221
+ await forgetWorkerExits([...expired, ...surplus].map(({ file: file2 }) => file2));
24222
+ }
24223
+ var CONTAINMENT_SUMMARY = {
24224
+ watchdog_liveness: "stopped answering the supervisor and was terminated",
24225
+ watchdog_shutdown_deadline: "did not finish stopping and was terminated",
24226
+ probation_readiness: "did not prove cloud readiness during probation",
24227
+ probation_commit: "could not commit its probation evidence"
24228
+ };
24229
+ function describeWorkerExit(record2) {
24230
+ return {
24231
+ summary: record2.containment ? CONTAINMENT_SUMMARY[record2.containment] : record2.signal ? `was killed by ${record2.signal}` : `exited unexpectedly with code ${record2.code ?? "unknown"}`,
24232
+ context: {
24233
+ ...record2.version ? { version: record2.version } : {},
24234
+ ...record2.pid === null ? {} : { pid: record2.pid },
24235
+ exit: record2.signal ?? (record2.code === null ? "unknown" : String(record2.code)),
24236
+ uptime: `${Math.round(record2.uptimeMs / 100) / 10}s`,
24237
+ announced: record2.announcedExitCode === null ? "none" : record2.announcedExitCode === UPDATE_EXIT_CODE ? `update (${record2.announcedExitCode})` : String(record2.announcedExitCode),
24238
+ heartbeats: record2.heartbeats,
24239
+ readiness: record2.readinessMilestones,
24240
+ ...record2.msSinceHeartbeat === null ? {} : { sinceHeartbeat: `${record2.msSinceHeartbeat}ms` }
24241
+ }
24242
+ };
24243
+ }
24244
+
24045
24245
  // src/runners/run-artifacts.ts
24046
24246
  import { spawn as spawn4 } from "node:child_process";
24047
24247
  import {
24048
24248
  chmod as chmod2,
24049
24249
  lstat as lstat4,
24050
- mkdir as mkdir3,
24250
+ mkdir as mkdir4,
24051
24251
  open as open3,
24052
- readdir as readdir2,
24053
- readFile as readFile5,
24252
+ readdir as readdir3,
24253
+ readFile as readFile6,
24054
24254
  realpath as realpath3,
24055
24255
  rename as rename2,
24056
- rm as rm3,
24057
- writeFile
24256
+ rm as rm4,
24257
+ writeFile as writeFile2
24058
24258
  } from "node:fs/promises";
24059
- import { homedir } from "node:os";
24060
- import { dirname as dirname3, isAbsolute as isAbsolute7, join as join6, relative as relative3, resolve as resolve4, sep as sep3, win32 as win322 } from "node:path";
24259
+ import { homedir as homedir2 } from "node:os";
24260
+ import { dirname as dirname3, isAbsolute as isAbsolute8, join as join7, relative as relative3, resolve as resolve4, sep as sep3, win32 as win322 } from "node:path";
24061
24261
 
24062
24262
  // src/windows-job.ts
24063
24263
  import { spawn as spawn3 } from "node:child_process";
24064
- import { randomUUID as randomUUID2 } from "node:crypto";
24065
- import { isAbsolute as isAbsolute6, win32 } from "node:path";
24264
+ import { randomUUID as randomUUID3 } from "node:crypto";
24265
+ import { isAbsolute as isAbsolute7, win32 } from "node:path";
24066
24266
  var WINDOWS_CONTAINMENT_GATE_ENV = "ZIXT_WINDOWS_CONTAINMENT_GATE";
24067
24267
  var WINDOWS_CONTAINMENT_GATE_PREFIX = "__ZIXT_WINDOWS_CONTAINMENT_READY__";
24068
24268
  var WINDOWS_POST_CONTAINMENT_CWD_ENV = "ZIXT_WINDOWS_POST_CONTAINMENT_CWD";
@@ -24373,7 +24573,7 @@ async function createWindowsJobContainment(pid, options) {
24373
24573
  throw new Error("Windows Job Object timeout is invalid");
24374
24574
  }
24375
24575
  const env = options.env ?? process.env;
24376
- const nonce = randomUUID2();
24576
+ const nonce = randomUUID3();
24377
24577
  const encodedSource = encodedPowershellSource(WINDOWS_JOB_HELPER_SOURCE);
24378
24578
  const helper = options.spawnHelper ? options.spawnHelper(nonce, encodedSource) : spawn3(
24379
24579
  options.powershellCommand ?? defaultPowershellCommand(env),
@@ -24558,7 +24758,7 @@ async function awaitWindowsContainmentGate(env = process.env, input = process.st
24558
24758
  const postContainmentCwd = env[WINDOWS_POST_CONTAINMENT_CWD_ENV];
24559
24759
  delete env[WINDOWS_POST_CONTAINMENT_CWD_ENV];
24560
24760
  if (postContainmentCwd !== void 0) {
24561
- if (!isAbsolute6(postContainmentCwd)) return finish(false);
24761
+ if (!isAbsolute7(postContainmentCwd)) return finish(false);
24562
24762
  try {
24563
24763
  process.chdir(postContainmentCwd);
24564
24764
  } catch {
@@ -24796,7 +24996,7 @@ foreach ($path in $paths) {
24796
24996
  }
24797
24997
  `;
24798
24998
  function defaultRunArtifactRoot() {
24799
- return join6(homedir(), ".zixt", "run-artifacts");
24999
+ return join7(homedir2(), ".zixt", "run-artifacts");
24800
25000
  }
24801
25001
  function requireSafeSegment(value, field) {
24802
25002
  if (!SAFE_SEGMENT.test(value)) {
@@ -24808,7 +25008,7 @@ function isMissing(error52) {
24808
25008
  }
24809
25009
  function assertBelow(parent, child) {
24810
25010
  const path = relative3(parent, child);
24811
- const escapes = path === "" || path === ".." || path.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) || isAbsolute7(path);
25011
+ const escapes = path === "" || path === ".." || path.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) || isAbsolute8(path);
24812
25012
  if (escapes) throw new Error("run artifact path escapes its private root");
24813
25013
  }
24814
25014
  async function requireRealDirectory(path, label) {
@@ -24843,7 +25043,7 @@ async function prepareRoot(root) {
24843
25043
  const absolute = resolve4(root);
24844
25044
  let realProfile;
24845
25045
  if (process.platform === "win32") {
24846
- const profile = resolve4(homedir());
25046
+ const profile = resolve4(homedir2());
24847
25047
  assertWindowsProfileBoundary(profile, absolute);
24848
25048
  await rejectWindowsSymlinkAncestors(profile, absolute);
24849
25049
  realProfile = await realpath3(profile);
@@ -24852,7 +25052,7 @@ async function prepareRoot(root) {
24852
25052
  await lstat4(absolute);
24853
25053
  } catch (error52) {
24854
25054
  if (!isMissing(error52)) throw error52;
24855
- await mkdir3(absolute, { recursive: true, mode: DIRECTORY_MODE });
25055
+ await mkdir4(absolute, { recursive: true, mode: DIRECTORY_MODE });
24856
25056
  }
24857
25057
  const real = await requireRealDirectory(absolute, "run artifact root");
24858
25058
  if (realProfile) assertWindowsProfileBoundary(realProfile, real);
@@ -24860,14 +25060,14 @@ async function prepareRoot(root) {
24860
25060
  return real;
24861
25061
  }
24862
25062
  async function prepareAgentRoot(root, agentId) {
24863
- const path = join6(root, agentId);
25063
+ const path = join7(root, agentId);
24864
25064
  assertBelow(root, path);
24865
25065
  try {
24866
25066
  await lstat4(path);
24867
25067
  } catch (error52) {
24868
25068
  if (!isMissing(error52)) throw error52;
24869
25069
  try {
24870
- await mkdir3(path, { mode: DIRECTORY_MODE });
25070
+ await mkdir4(path, { mode: DIRECTORY_MODE });
24871
25071
  } catch (mkdirError) {
24872
25072
  if (mkdirError.code !== "EEXIST") throw mkdirError;
24873
25073
  }
@@ -24883,7 +25083,7 @@ async function lockDownWindowsDirectories(paths) {
24883
25083
  if (!windowsRoot || !win322.isAbsolute(windowsRoot)) {
24884
25084
  throw new Error("private Windows run-artifact ACL authority is unavailable");
24885
25085
  }
24886
- const powershell = join6(windowsRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
25086
+ const powershell = join7(windowsRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
24887
25087
  const encoded = Buffer.from(WINDOWS_PRIVATE_DACL_SCRIPT, "utf16le").toString("base64");
24888
25088
  await new Promise((resolvePromise, reject3) => {
24889
25089
  const helper = spawn4(
@@ -24925,16 +25125,16 @@ async function lockDownWindowsDirectories(paths) {
24925
25125
  });
24926
25126
  }
24927
25127
  async function createPrivateDirectory(parent, name) {
24928
- const path = join6(parent, name);
25128
+ const path = join7(parent, name);
24929
25129
  assertBelow(parent, path);
24930
- await mkdir3(path, { mode: DIRECTORY_MODE });
25130
+ await mkdir4(path, { mode: DIRECTORY_MODE });
24931
25131
  await chmod2(path, DIRECTORY_MODE);
24932
25132
  const real = await realpath3(path);
24933
25133
  assertBelow(parent, real);
24934
25134
  return real;
24935
25135
  }
24936
25136
  async function writePrivateFile(path, content) {
24937
- await writeFile(path, content, { flag: "wx", mode: FILE_MODE });
25137
+ await writeFile2(path, content, { flag: "wx", mode: FILE_MODE });
24938
25138
  await chmod2(path, FILE_MODE);
24939
25139
  }
24940
25140
  function quotePosix(value) {
@@ -24954,24 +25154,24 @@ async function createRunArtifacts(input) {
24954
25154
  requireSafeSegment(input.agentId, "agentId");
24955
25155
  requireSafeSegment(input.runToken, "runToken");
24956
25156
  const root = await prepareRoot(input.root);
24957
- const removeTree = input.removeTree ?? ((path) => rm3(path, { recursive: true, force: true }));
25157
+ const removeTree = input.removeTree ?? ((path) => rm4(path, { recursive: true, force: true }));
24958
25158
  const cleanupRetryDelayMs = input.cleanupRetryDelayMs ?? CLEANUP_RETRY_DELAY_MS;
24959
25159
  const agentRoot = await prepareAgentRoot(root, input.agentId);
24960
25160
  await lockDownWindowsDirectories([root, agentRoot]);
24961
- const runRoot = join6(agentRoot, input.runToken);
25161
+ const runRoot = join7(agentRoot, input.runToken);
24962
25162
  assertBelow(agentRoot, runRoot);
24963
25163
  try {
24964
- await mkdir3(runRoot, { mode: DIRECTORY_MODE });
25164
+ await mkdir4(runRoot, { mode: DIRECTORY_MODE });
24965
25165
  await chmod2(runRoot, DIRECTORY_MODE);
24966
25166
  const realRunRoot = await realpath3(runRoot);
24967
25167
  assertBelow(agentRoot, realRunRoot);
24968
25168
  const emptyGithubConfigDirectory = await createPrivateDirectory(realRunRoot, "gh-config");
24969
25169
  const emptyGitHooksDirectory = await createPrivateDirectory(realRunRoot, "git-hooks");
24970
25170
  const gitBridgesDirectory = await createPrivateDirectory(realRunRoot, "git-bridges");
24971
- const denySshScript = join6(realRunRoot, "deny-ssh.cjs");
24972
- const runnerWrapperScript = join6(realRunRoot, "runner-wrapper.cjs");
24973
- const systemPromptPath = join6(realRunRoot, "system-prompt.txt");
24974
- const mcpConfigPath = join6(realRunRoot, "mcp.json");
25171
+ const denySshScript = join7(realRunRoot, "deny-ssh.cjs");
25172
+ const runnerWrapperScript = join7(realRunRoot, "runner-wrapper.cjs");
25173
+ const systemPromptPath = join7(realRunRoot, "system-prompt.txt");
25174
+ const mcpConfigPath = join7(realRunRoot, "mcp.json");
24975
25175
  await writePrivateFile(denySshScript, "process.exitCode = 127;");
24976
25176
  await writePrivateFile(runnerWrapperScript, RUNNER_GUARDIAN);
24977
25177
  return {
@@ -25016,7 +25216,7 @@ async function sweepOrphanedRunArtifacts(root) {
25016
25216
  const absolute = resolve4(root);
25017
25217
  let realProfile;
25018
25218
  if (process.platform === "win32") {
25019
- const profile = resolve4(homedir());
25219
+ const profile = resolve4(homedir2());
25020
25220
  assertWindowsProfileBoundary(profile, absolute);
25021
25221
  await rejectWindowsSymlinkAncestors(profile, absolute);
25022
25222
  realProfile = await realpath3(profile);
@@ -25031,24 +25231,24 @@ async function sweepOrphanedRunArtifacts(root) {
25031
25231
  if (realProfile) assertWindowsProfileBoundary(realProfile, realRoot);
25032
25232
  await chmod2(realRoot, DIRECTORY_MODE);
25033
25233
  await lockDownWindowsDirectories([realRoot]);
25034
- const agents = await readdir2(realRoot, { withFileTypes: true });
25234
+ const agents = await readdir3(realRoot, { withFileTypes: true });
25035
25235
  let removed = 0;
25036
25236
  for (const agent of agents) {
25037
25237
  if (!SAFE_SEGMENT.test(agent.name) || !agent.isDirectory() || agent.isSymbolicLink()) continue;
25038
- const agentPath = join6(realRoot, agent.name);
25039
- const runs = await readdir2(agentPath, { withFileTypes: true });
25238
+ const agentPath = join7(realRoot, agent.name);
25239
+ const runs = await readdir3(agentPath, { withFileTypes: true });
25040
25240
  for (const run3 of runs) {
25041
25241
  if (!SAFE_SEGMENT.test(run3.name) || !run3.isDirectory() || run3.isSymbolicLink()) continue;
25042
- const runPath = join6(agentPath, run3.name);
25242
+ const runPath = join7(agentPath, run3.name);
25043
25243
  assertBelow(agentPath, runPath);
25044
- await rm3(runPath, { recursive: true, force: true });
25244
+ await rm4(runPath, { recursive: true, force: true });
25045
25245
  removed++;
25046
25246
  }
25047
25247
  }
25048
25248
  return removed;
25049
25249
  }
25050
25250
  function defaultRunRegistryRoot() {
25051
- return join6(homedir(), ".zixt", "run-registry");
25251
+ return join7(homedir2(), ".zixt", "run-registry");
25052
25252
  }
25053
25253
  async function terminateRecordedRunProcesses(registryRoot = defaultRunRegistryRoot(), terminate = terminateRecordedProcessTree) {
25054
25254
  const entries = await readRecordedRunAssignmentEntriesStrict(registryRoot);
@@ -25074,7 +25274,7 @@ async function syncRunRegistryDirectory(path) {
25074
25274
  }
25075
25275
  }
25076
25276
  async function ensureDurableRunRegistryRoot(registryRoot, syncDirectory8) {
25077
- const firstCreated = await mkdir3(registryRoot, { recursive: true, mode: DIRECTORY_MODE });
25277
+ const firstCreated = await mkdir4(registryRoot, { recursive: true, mode: DIRECTORY_MODE });
25078
25278
  if (firstCreated && process.platform !== "win32") {
25079
25279
  const first = resolve4(firstCreated);
25080
25280
  const target = resolve4(registryRoot);
@@ -25082,15 +25282,15 @@ async function ensureDurableRunRegistryRoot(registryRoot, syncDirectory8) {
25082
25282
  let current = first;
25083
25283
  for (const part of relative3(first, target).split(sep3).filter(Boolean)) {
25084
25284
  await syncDirectory8(current);
25085
- current = join6(current, part);
25285
+ current = join7(current, part);
25086
25286
  }
25087
25287
  }
25088
25288
  await chmod2(registryRoot, DIRECTORY_MODE);
25089
25289
  }
25090
25290
  async function recordRunAssignment(runToken, record2, registryRoot = defaultRunRegistryRoot(), options = {}) {
25091
25291
  if (!SAFE_SEGMENT.test(runToken)) return false;
25092
- const destination = join6(registryRoot, `${runToken}.json`);
25093
- const temporary = join6(registryRoot, `.${runToken}.${process.pid}.${Date.now()}.tmp`);
25292
+ const destination = join7(registryRoot, `${runToken}.json`);
25293
+ const temporary = join7(registryRoot, `.${runToken}.${process.pid}.${Date.now()}.tmp`);
25094
25294
  let handle;
25095
25295
  try {
25096
25296
  const syncDirectory8 = options.syncDirectory ?? syncRunRegistryDirectory;
@@ -25110,7 +25310,7 @@ async function recordRunAssignment(runToken, record2, registryRoot = defaultRunR
25110
25310
  } finally {
25111
25311
  await handle?.close().catch(() => {
25112
25312
  });
25113
- await rm3(temporary, { force: true }).catch(() => {
25313
+ await rm4(temporary, { force: true }).catch(() => {
25114
25314
  });
25115
25315
  }
25116
25316
  }
@@ -25122,7 +25322,7 @@ async function forgetRunAssignment(runToken, registryRoot = defaultRunRegistryRo
25122
25322
  if (retainingAssignments) return;
25123
25323
  if (!SAFE_SEGMENT.test(runToken)) return;
25124
25324
  try {
25125
- await rm3(join6(registryRoot, `${runToken}.json`), { force: true });
25325
+ await rm4(join7(registryRoot, `${runToken}.json`), { force: true });
25126
25326
  } catch {
25127
25327
  }
25128
25328
  }
@@ -25156,7 +25356,7 @@ function parseAssignment(text) {
25156
25356
  async function readRecordedRunAssignmentEntries(registryRoot = defaultRunRegistryRoot()) {
25157
25357
  let entries;
25158
25358
  try {
25159
- entries = await readdir2(registryRoot, { withFileTypes: true });
25359
+ entries = await readdir3(registryRoot, { withFileTypes: true });
25160
25360
  } catch {
25161
25361
  return [];
25162
25362
  }
@@ -25167,7 +25367,7 @@ async function readRecordedRunAssignmentEntries(registryRoot = defaultRunRegistr
25167
25367
  if (!SAFE_SEGMENT.test(runToken)) continue;
25168
25368
  let text;
25169
25369
  try {
25170
- text = await readFile5(join6(registryRoot, entry.name), "utf8");
25370
+ text = await readFile6(join7(registryRoot, entry.name), "utf8");
25171
25371
  } catch {
25172
25372
  continue;
25173
25373
  }
@@ -25189,7 +25389,7 @@ async function readRecordedRunAssignmentEntriesStrict(registryRoot = defaultRunR
25189
25389
  }
25190
25390
  let entries;
25191
25391
  try {
25192
- entries = await readdir2(registryRoot, { withFileTypes: true });
25392
+ entries = await readdir3(registryRoot, { withFileTypes: true });
25193
25393
  } catch {
25194
25394
  throw new Error("run registry state could not be observed");
25195
25395
  }
@@ -25203,7 +25403,7 @@ async function readRecordedRunAssignmentEntriesStrict(registryRoot = defaultRunR
25203
25403
  }
25204
25404
  let text;
25205
25405
  try {
25206
- text = await readFile5(join6(registryRoot, entry.name), "utf8");
25406
+ text = await readFile6(join7(registryRoot, entry.name), "utf8");
25207
25407
  } catch {
25208
25408
  throw new Error("committed run registry witness could not be read");
25209
25409
  }
@@ -25220,13 +25420,13 @@ async function forgetAcknowledgedRunAssignments(assignments, registryRoot = defa
25220
25420
  );
25221
25421
  const entries = await readRecordedRunAssignmentEntries(registryRoot);
25222
25422
  await Promise.all(
25223
- entries.filter(({ record: record2 }) => acknowledged.has(`${record2.taskId}:${record2.epoch}`)).map(({ runToken }) => rm3(join6(registryRoot, `${runToken}.json`), { force: true }))
25423
+ entries.filter(({ record: record2 }) => acknowledged.has(`${record2.taskId}:${record2.epoch}`)).map(({ runToken }) => rm4(join7(registryRoot, `${runToken}.json`), { force: true }))
25224
25424
  );
25225
25425
  }
25226
25426
  async function forgetSupersededRunAssignments(taskId, epoch, registryRoot = defaultRunRegistryRoot()) {
25227
25427
  const entries = await readRecordedRunAssignmentEntries(registryRoot);
25228
25428
  await Promise.all(
25229
- entries.filter(({ record: record2 }) => record2.taskId === taskId && record2.epoch < epoch).map(({ runToken }) => rm3(join6(registryRoot, `${runToken}.json`), { force: true }))
25429
+ entries.filter(({ record: record2 }) => record2.taskId === taskId && record2.epoch < epoch).map(({ runToken }) => rm4(join7(registryRoot, `${runToken}.json`), { force: true }))
25230
25430
  );
25231
25431
  }
25232
25432
 
@@ -25237,6 +25437,7 @@ var WORKER_ROLE = "worker";
25237
25437
  var WORKER_PROXY_ROLE = "worker_proxy";
25238
25438
  var SUPERVISOR_ROLE = "supervisor";
25239
25439
  var WORKER_PROXY_ENTRY_ENV = "ZIXT_HOST_WORKER_PROXY_ENTRY";
25440
+ var HOST_CONSOLE_COLOR_ENV = "ZIXT_HOST_CONSOLE_COLOR";
25240
25441
  var SUPERVISOR_PROTOCOL_ENV = "ZIXT_HOST_SUPERVISOR_PROTOCOL";
25241
25442
  var SUPERVISOR_VERSION_ENV = "ZIXT_HOST_SUPERVISOR_VERSION";
25242
25443
  var SUPERVISOR_PROTOCOL = "2";
@@ -25252,6 +25453,8 @@ var INSTALL_TIMEOUT_MS = 5 * 6e4;
25252
25453
  var WORKER_WATCHDOG_CHECK_MS = 1e3;
25253
25454
  var WORKER_WATCHDOG_TIMEOUT_MS = 15e3;
25254
25455
  var WORKER_WATCHDOG_STARTUP_MS = 6e4;
25456
+ var WORKER_SHUTDOWN_DEADLINE_MS = 6e4;
25457
+ var WORKER_STDERR_TAIL_LINES = 40;
25255
25458
  var WORKER_READINESS_TIMEOUT_MS = 9e4;
25256
25459
  var CLEANUP_ATTEMPTS2 = 3;
25257
25460
  var VERSION_DIR = /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/;
@@ -25267,8 +25470,28 @@ function signalWorkerGroup(child, signal) {
25267
25470
  } catch {
25268
25471
  }
25269
25472
  }
25473
+ function captureWorkerStderr(child) {
25474
+ const stderr = child.stderr;
25475
+ if (!stderr) return () => [];
25476
+ const lines = [];
25477
+ let partial2 = "";
25478
+ stderr.on("data", (chunk) => {
25479
+ const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
25480
+ process.stderr.write(text);
25481
+ partial2 += text;
25482
+ const complete = partial2.split(/\r?\n/);
25483
+ partial2 = complete.pop() ?? "";
25484
+ for (const line of complete) {
25485
+ lines.push(line);
25486
+ if (lines.length > WORKER_STDERR_TAIL_LINES) lines.shift();
25487
+ }
25488
+ });
25489
+ stderr.on("error", () => {
25490
+ });
25491
+ return () => (partial2 ? [...lines, partial2] : [...lines]).slice(-WORKER_STDERR_TAIL_LINES);
25492
+ }
25270
25493
  function versionsRoot() {
25271
- return process.env.ZIXT_HOST_VERSIONS_DIR ?? join7(homedir2(), ".zixt", "host-versions");
25494
+ return process.env.ZIXT_HOST_VERSIONS_DIR ?? join8(homedir3(), ".zixt", "host-versions");
25272
25495
  }
25273
25496
  function npmCommand(platform = process.platform) {
25274
25497
  return platform === "win32" ? "npm.cmd" : "npm";
@@ -25277,19 +25500,19 @@ function windowsInstallerCommandLine(command, args) {
25277
25500
  return [command, ...args].map(quoteForCmd).join(" ");
25278
25501
  }
25279
25502
  function installedReleaseEntry(version2, root = versionsRoot()) {
25280
- return join7(root, version2, "node_modules", PACKAGE_NAME, "dist", "index.js");
25503
+ return join8(root, version2, "node_modules", PACKAGE_NAME, "dist", "index.js");
25281
25504
  }
25282
25505
  function releaseEntryAtPrefix(prefix) {
25283
- return join7(prefix, "node_modules", PACKAGE_NAME, "dist", "index.js");
25506
+ return join8(prefix, "node_modules", PACKAGE_NAME, "dist", "index.js");
25284
25507
  }
25285
25508
  function releaseManifestAtPrefix(prefix) {
25286
- return join7(prefix, "node_modules", PACKAGE_NAME, "package.json");
25509
+ return join8(prefix, "node_modules", PACKAGE_NAME, "package.json");
25287
25510
  }
25288
25511
  async function validReleaseAtPrefix(prefix, version2) {
25289
25512
  try {
25290
25513
  const [entry, manifestText] = await Promise.all([
25291
25514
  lstat5(releaseEntryAtPrefix(prefix)),
25292
- readFile6(releaseManifestAtPrefix(prefix), "utf8")
25515
+ readFile7(releaseManifestAtPrefix(prefix), "utf8")
25293
25516
  ]);
25294
25517
  if (!entry.isFile()) return false;
25295
25518
  const manifest = JSON.parse(manifestText);
@@ -25308,9 +25531,9 @@ async function syncDirectory3(path) {
25308
25531
  }
25309
25532
  }
25310
25533
  function installedReleaseVersion(entry, root = versionsRoot()) {
25311
- if (!isAbsolute8(entry)) return null;
25534
+ if (!isAbsolute9(entry)) return null;
25312
25535
  const relativeEntry = relative4(resolve5(root), resolve5(entry));
25313
- if (!relativeEntry || relativeEntry.startsWith(`..${sep4}`) || isAbsolute8(relativeEntry)) {
25536
+ if (!relativeEntry || relativeEntry.startsWith(`..${sep4}`) || isAbsolute9(relativeEntry)) {
25314
25537
  return null;
25315
25538
  }
25316
25539
  const version2 = relativeEntry.split(sep4)[0];
@@ -25318,10 +25541,10 @@ function installedReleaseVersion(entry, root = versionsRoot()) {
25318
25541
  return resolve5(entry) === resolve5(installedReleaseEntry(version2, root)) ? version2 : null;
25319
25542
  }
25320
25543
  function currentReleaseEntry(root = versionsRoot(), platform = process.platform) {
25321
- return join7(root, platform === "win32" ? "current-launcher.cjs" : CURRENT_RELEASE_ENTRY);
25544
+ return join8(root, platform === "win32" ? "current-launcher.cjs" : CURRENT_RELEASE_ENTRY);
25322
25545
  }
25323
25546
  function windowsReleasePointer(root = versionsRoot()) {
25324
- return join7(root, WINDOWS_RELEASE_POINTER);
25547
+ return join8(root, WINDOWS_RELEASE_POINTER);
25325
25548
  }
25326
25549
  var WINDOWS_STABLE_LAUNCHER = `${WINDOWS_LAUNCHER_MARKER}
25327
25550
  'use strict';
@@ -25357,8 +25580,8 @@ child.once('exit', (code) => process.exit(code == null ? 1 : code));
25357
25580
  `;
25358
25581
  async function replaceDurableFile(path, contents, sync = syncDirectory3) {
25359
25582
  const parent = dirname4(path);
25360
- await mkdir4(parent, { recursive: true, mode: 448 });
25361
- const temporary = join7(parent, `.${CURRENT_RELEASE_ENTRY}.${process.pid}.${crypto.randomUUID()}`);
25583
+ await mkdir5(parent, { recursive: true, mode: 448 });
25584
+ const temporary = join8(parent, `.${CURRENT_RELEASE_ENTRY}.${process.pid}.${crypto.randomUUID()}`);
25362
25585
  const handle = await open4(temporary, "wx", 384);
25363
25586
  try {
25364
25587
  await handle.writeFile(contents, "utf8");
@@ -25368,7 +25591,7 @@ async function replaceDurableFile(path, contents, sync = syncDirectory3) {
25368
25591
  await sync(parent);
25369
25592
  } catch (error52) {
25370
25593
  await handle.close().catch(() => void 0);
25371
- await rm4(temporary, { force: true }).catch(() => void 0);
25594
+ await rm5(temporary, { force: true }).catch(() => void 0);
25372
25595
  throw error52;
25373
25596
  }
25374
25597
  }
@@ -25378,7 +25601,7 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
25378
25601
  }
25379
25602
  await access2(entry);
25380
25603
  if (platform === "win32") {
25381
- await mkdir4(root, { recursive: true, mode: 448 });
25604
+ await mkdir5(root, { recursive: true, mode: 448 });
25382
25605
  const launcher = currentReleaseEntry(root, platform);
25383
25606
  const existingLauncher = await lstat5(launcher).catch((error52) => {
25384
25607
  if (error52.code === "ENOENT") return null;
@@ -25388,7 +25611,7 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
25388
25611
  if (!existingLauncher.isFile()) {
25389
25612
  throw new Error("the Zixt Host Windows launcher is not a regular file");
25390
25613
  }
25391
- const contents = await readFile6(launcher, "utf8");
25614
+ const contents = await readFile7(launcher, "utf8");
25392
25615
  if (!contents.startsWith(WINDOWS_LAUNCHER_OWNED_MARKER)) {
25393
25616
  throw new Error("the Zixt Host Windows launcher is not owned by Zixt");
25394
25617
  }
@@ -25409,7 +25632,7 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
25409
25632
  }
25410
25633
  let prior;
25411
25634
  try {
25412
- prior = JSON.parse(await readFile6(pointerPath, "utf8"));
25635
+ prior = JSON.parse(await readFile7(pointerPath, "utf8"));
25413
25636
  } catch {
25414
25637
  throw new Error("the Zixt Host Windows release pointer is invalid");
25415
25638
  }
@@ -25427,7 +25650,7 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
25427
25650
  return launcher;
25428
25651
  }
25429
25652
  if (platform !== "linux" && platform !== "darwin") return entry;
25430
- await mkdir4(root, { recursive: true, mode: 448 });
25653
+ await mkdir5(root, { recursive: true, mode: 448 });
25431
25654
  const current = currentReleaseEntry(root, platform);
25432
25655
  const existing = await lstat5(current).catch((error52) => {
25433
25656
  if (error52.code === "ENOENT") return null;
@@ -25436,13 +25659,13 @@ async function activateInstalledRelease(entry, root = versionsRoot(), platform =
25436
25659
  if (existing && !existing.isSymbolicLink()) {
25437
25660
  throw new Error("the Zixt Host current-release entry is not a symbolic link");
25438
25661
  }
25439
- const temporary = join7(root, `.${CURRENT_RELEASE_ENTRY}.${process.pid}.${crypto.randomUUID()}`);
25662
+ const temporary = join8(root, `.${CURRENT_RELEASE_ENTRY}.${process.pid}.${crypto.randomUUID()}`);
25440
25663
  try {
25441
25664
  await symlink(entry, temporary, "file");
25442
25665
  await rename3(temporary, current);
25443
25666
  await sync(root);
25444
25667
  } catch (error52) {
25445
- await rm4(temporary, { force: true }).catch(() => void 0);
25668
+ await rm5(temporary, { force: true }).catch(() => void 0);
25446
25669
  throw error52;
25447
25670
  }
25448
25671
  return current;
@@ -25453,7 +25676,7 @@ async function activatedReleaseVersion(root = versionsRoot(), platform = process
25453
25676
  const pointerPath = windowsReleasePointer(root);
25454
25677
  const metadata = await lstat5(pointerPath);
25455
25678
  if (!metadata.isFile() || metadata.size > 4 * 1024) return null;
25456
- const value = JSON.parse(await readFile6(pointerPath, "utf8"));
25679
+ const value = JSON.parse(await readFile7(pointerPath, "utf8"));
25457
25680
  return value.schema === 1 && typeof value.entry === "string" ? installedReleaseVersion(value.entry, root) : null;
25458
25681
  } catch {
25459
25682
  return null;
@@ -25567,13 +25790,13 @@ async function installRelease(version2, options = {}) {
25567
25790
  const platform = options.platform ?? process.platform;
25568
25791
  const installerCommand = options.installerCommand ?? npmCommand(platform);
25569
25792
  const root = options.root ?? versionsRoot();
25570
- const prefix = join7(root, version2);
25793
+ const prefix = join8(root, version2);
25571
25794
  const entry = installedReleaseEntry(version2, root);
25572
25795
  if (await validReleaseAtPrefix(prefix, version2)) return entry;
25573
25796
  if (options.signal?.aborted) return null;
25574
- await mkdir4(root, { recursive: true, mode: 448 });
25575
- const staging = join7(root, `.install-${version2}-${process.pid}-${crypto.randomUUID()}`);
25576
- const quarantine = join7(root, `.invalid-${version2}-${process.pid}-${crypto.randomUUID()}`);
25797
+ await mkdir5(root, { recursive: true, mode: 448 });
25798
+ const staging = join8(root, `.install-${version2}-${process.pid}-${crypto.randomUUID()}`);
25799
+ const quarantine = join8(root, `.invalid-${version2}-${process.pid}-${crypto.randomUUID()}`);
25577
25800
  const usesWindowsInstallerGuardian = platform === "win32" && options.spawnInstaller === void 0;
25578
25801
  const installerGateNonce = usesWindowsInstallerGuardian ? crypto.randomUUID() : null;
25579
25802
  const installerArguments = (installPrefix, installVersion) => [
@@ -25605,7 +25828,7 @@ async function installRelease(version2, options = {}) {
25605
25828
  try {
25606
25829
  child = spawnInstaller(staging, version2);
25607
25830
  } catch {
25608
- await rm4(staging, { recursive: true, force: true }).catch(() => void 0);
25831
+ await rm5(staging, { recursive: true, force: true }).catch(() => void 0);
25609
25832
  return null;
25610
25833
  }
25611
25834
  let resolveChildExited;
@@ -25755,8 +25978,8 @@ async function installRelease(version2, options = {}) {
25755
25978
  await syncDirectory3(root);
25756
25979
  return await validReleaseAtPrefix(prefix, version2) ? entry : null;
25757
25980
  } finally {
25758
- await rm4(staging, { recursive: true, force: true }).catch(() => void 0);
25759
- await rm4(quarantine, { recursive: true, force: true }).catch(() => void 0);
25981
+ await rm5(staging, { recursive: true, force: true }).catch(() => void 0);
25982
+ await rm5(quarantine, { recursive: true, force: true }).catch(() => void 0);
25760
25983
  }
25761
25984
  }
25762
25985
  async function pruneInstalledVersions(keep, root = versionsRoot()) {
@@ -25764,17 +25987,17 @@ async function pruneInstalledVersions(keep, root = versionsRoot()) {
25764
25987
  const running = process.argv[1] ? resolve5(process.argv[1]) : null;
25765
25988
  let entries;
25766
25989
  try {
25767
- entries = await readdir3(root);
25990
+ entries = await readdir4(root);
25768
25991
  } catch {
25769
25992
  return [];
25770
25993
  }
25771
25994
  const removed = [];
25772
25995
  for (const name of entries) {
25773
25996
  if (protectedDirs.has(name) || !VERSION_DIR.test(name)) continue;
25774
- const dir = join7(root, name);
25997
+ const dir = join8(root, name);
25775
25998
  if (running && running.startsWith(`${dir}${sep4}`)) continue;
25776
25999
  try {
25777
- await rm4(dir, { recursive: true, force: true });
26000
+ await rm5(dir, { recursive: true, force: true });
25778
26001
  removed.push(name);
25779
26002
  } catch {
25780
26003
  }
@@ -25785,7 +26008,7 @@ function durableState(phase, candidateVersion, fallbackVersion) {
25785
26008
  return { schema: 1, phase, candidateVersion, fallbackVersion };
25786
26009
  }
25787
26010
  async function validInstalledRelease(version2, root = versionsRoot()) {
25788
- return validReleaseAtPrefix(join7(root, version2), version2);
26011
+ return validReleaseAtPrefix(join8(root, version2), version2);
25789
26012
  }
25790
26013
  async function recoverDurableReleaseState(store, runningVersion, activeBootVersion, activate, log2) {
25791
26014
  const state = await store.load();
@@ -25874,7 +26097,7 @@ async function recoverDurableReleaseState(store, runningVersion, activeBootVersi
25874
26097
  }
25875
26098
  return rolledBack();
25876
26099
  }
25877
- function defaultSpawn(command, argv, supervisorVersion, watchdog, compatibilityOwnership, containmentGateNonce, platform = process.platform) {
26100
+ function defaultSpawn(command, argv, supervisorVersion, watchdog, compatibilityOwnership, containmentGateNonce, platform = process.platform, diagnosticsRoot2 = null) {
25878
26101
  const ownership = watchdog ?? compatibilityOwnership;
25879
26102
  const compatibilityProxy = watchdog === null && compatibilityOwnership !== null;
25880
26103
  const env = {
@@ -25894,14 +26117,21 @@ function defaultSpawn(command, argv, supervisorVersion, watchdog, compatibilityO
25894
26117
  if (!containmentGateNonce) delete env[WINDOWS_POST_CONTAINMENT_CWD_ENV];
25895
26118
  if (supervisorVersion) env[SUPERVISOR_VERSION_ENV] = supervisorVersion;
25896
26119
  else delete env[SUPERVISOR_VERSION_ENV];
26120
+ delete env[WORKER_DIAGNOSTICS_DIR_ENV];
26121
+ if (diagnosticsRoot2) env[WORKER_DIAGNOSTICS_DIR_ENV] = diagnosticsRoot2;
26122
+ delete env[HOST_CONSOLE_COLOR_ENV];
26123
+ if (process.stderr.isTTY === true && process.env.NO_COLOR === void 0) {
26124
+ env[HOST_CONSOLE_COLOR_ENV] = "1";
26125
+ }
25897
26126
  delete env.ZIXT_HOST_REJECT_VERSION;
25898
26127
  if (command.rejectedVersion) env.ZIXT_HOST_REJECT_VERSION = command.rejectedVersion;
25899
26128
  const entry = compatibilityProxy ? process.argv[1] ?? "" : command.entry ?? process.argv[1] ?? "";
25900
26129
  const child = spawn5(process.execPath, [entry, ...argv, ...ownership?.argv ?? []], {
25901
26130
  // stdin is a pipe this process owns: closing it is how the worker is
25902
26131
  // asked to stop, which works identically on Windows, where there is no
25903
- // real SIGINT to send. stdout/stderr stay the person's terminal.
25904
- stdio: watchdog ? ["pipe", "inherit", "inherit", "ipc"] : ["pipe", "inherit", "inherit"],
26132
+ // real SIGINT to send. stdout stays the person's terminal; stderr is teed
26133
+ // through this process so a crash stack survives the exit that hid it.
26134
+ stdio: watchdog ? ["pipe", "inherit", "pipe", "ipc"] : ["pipe", "inherit", "pipe"],
25905
26135
  env,
25906
26136
  ...containmentGateNonce ? {
25907
26137
  cwd: ownership?.ownershipFile ? dirname4(ownership.ownershipFile) : dirname4(entry)
@@ -25933,7 +26163,7 @@ async function runWorkerCompatibilityProxy(env = process.env, argv = process.arg
25933
26163
  const ownership = consumeWorkerOwnershipArguments(argv, env);
25934
26164
  const nonce = env[WORKER_WATCHDOG_NONCE_ENV];
25935
26165
  const ownershipFile = env[WORKER_OWNERSHIP_FILE_ENV];
25936
- if (typeof target !== "string" || !isAbsolute8(target) || typeof nonce !== "string" || typeof ownershipFile !== "string" || !ownership.requested || !ownership.valid) {
26166
+ if (typeof target !== "string" || !isAbsolute9(target) || typeof nonce !== "string" || typeof ownershipFile !== "string" || !ownership.requested || !ownership.valid) {
25937
26167
  return 1;
25938
26168
  }
25939
26169
  if (!recordWorkerOwnership(ownershipFile, nonce)) return 1;
@@ -26004,7 +26234,7 @@ async function launchHostSupervisor(options = {}) {
26004
26234
  const generationNonce = ownershipDirectory ? basename3(ownershipDirectory) : null;
26005
26235
  if (ownershipDirectory && generationNonce) {
26006
26236
  env[LAUNCHER_OWNERSHIP_DIR_ENV] = ownershipDirectory;
26007
- env[SUPERVISOR_OWNERSHIP_FILE_ENV] = join7(ownershipDirectory, `${generationNonce}.json`);
26237
+ env[SUPERVISOR_OWNERSHIP_FILE_ENV] = join8(ownershipDirectory, `${generationNonce}.json`);
26008
26238
  } else {
26009
26239
  delete env[LAUNCHER_OWNERSHIP_DIR_ENV];
26010
26240
  }
@@ -26027,8 +26257,8 @@ async function launchHostSupervisor(options = {}) {
26027
26257
  });
26028
26258
  const customDelay = options.delay;
26029
26259
  const ownsWorkerBoundary = options.spawnSupervisor === void 0 || options.ownershipRoot !== void 0;
26030
- const ownershipRoot = options.ownershipRoot ?? join7(versionsRoot(), "launcher-ownership");
26031
- const runRegistryRoot2 = options.runRegistryRoot ?? (options.ownershipRoot ? join7(dirname4(options.ownershipRoot), "run-registry") : defaultRunRegistryRoot());
26260
+ const ownershipRoot = options.ownershipRoot ?? join8(versionsRoot(), "launcher-ownership");
26261
+ const runRegistryRoot2 = options.runRegistryRoot ?? (options.ownershipRoot ? join8(dirname4(options.ownershipRoot), "run-registry") : defaultRunRegistryRoot());
26032
26262
  const terminateRecordedOwnership = options.terminateRecordedOwnership ?? terminateRecordedProcessTree;
26033
26263
  const createSupervisorContainment = options.createSupervisorContainment ?? (platform === "win32" && options.spawnSupervisor === void 0 ? async (target, identityNonce, signal) => {
26034
26264
  if (!target.pid) throw new Error("supervisor process id is unavailable");
@@ -26295,10 +26525,10 @@ async function superviseHost(options = {}) {
26295
26525
  const log2 = options.log ?? ((message) => console.error(message));
26296
26526
  const signalWorker = options.signalWorker ?? signalWorkerGroup;
26297
26527
  const inheritedOwnershipDirectory = process.env[LAUNCHER_OWNERSHIP_DIR_ENV];
26298
- const launcherOwnershipDirectory = productionLifecycle && typeof inheritedOwnershipDirectory === "string" && isAbsolute8(inheritedOwnershipDirectory) ? inheritedOwnershipDirectory : null;
26528
+ const launcherOwnershipDirectory = productionLifecycle && typeof inheritedOwnershipDirectory === "string" && isAbsolute9(inheritedOwnershipDirectory) ? inheritedOwnershipDirectory : null;
26299
26529
  if (productionLifecycle && isSupervisorRole() && launcherOwnershipDirectory) {
26300
26530
  const generationNonce = basename3(launcherOwnershipDirectory);
26301
- const expectedOwnershipFile = join7(launcherOwnershipDirectory, `${generationNonce}.json`);
26531
+ const expectedOwnershipFile = join8(launcherOwnershipDirectory, `${generationNonce}.json`);
26302
26532
  const configuredOwnershipFile = process.env[SUPERVISOR_OWNERSHIP_FILE_ENV];
26303
26533
  if (process.argv0 !== generationNonce || configuredOwnershipFile !== expectedOwnershipFile || !recordWorkerOwnership(expectedOwnershipFile, generationNonce)) {
26304
26534
  log2("Zixt Host: supervisor ownership could not be committed; refusing to start a worker");
@@ -26310,12 +26540,14 @@ async function superviseHost(options = {}) {
26310
26540
  const workerWatchdogTimeoutMs = options.workerWatchdogTimeoutMs ?? WORKER_WATCHDOG_TIMEOUT_MS;
26311
26541
  const workerWatchdogStartupMs = options.workerWatchdogStartupMs ?? WORKER_WATCHDOG_STARTUP_MS;
26312
26542
  const workerReadinessTimeoutMs = options.workerReadinessTimeoutMs ?? WORKER_READINESS_TIMEOUT_MS;
26543
+ const workerShutdownDeadlineMs = options.workerShutdownDeadlineMs ?? WORKER_SHUTDOWN_DEADLINE_MS;
26313
26544
  const releaseProbationMs = options.releaseProbationMs ?? RELEASE_PROBATION_MS;
26314
- if (!Number.isSafeInteger(workerWatchdogCheckMs) || workerWatchdogCheckMs < 10 || workerWatchdogCheckMs > 6e4 || !Number.isSafeInteger(workerWatchdogTimeoutMs) || workerWatchdogTimeoutMs < workerWatchdogCheckMs * 2 || workerWatchdogTimeoutMs > 10 * 6e4 || !Number.isSafeInteger(workerWatchdogStartupMs) || workerWatchdogStartupMs < workerWatchdogCheckMs * 2 || workerWatchdogStartupMs > 10 * 6e4 || !Number.isSafeInteger(workerReadinessTimeoutMs) || workerReadinessTimeoutMs < workerWatchdogCheckMs * 2 || workerReadinessTimeoutMs > 10 * 6e4 || !Number.isSafeInteger(releaseProbationMs) || releaseProbationMs < 10 || releaseProbationMs > 24 * 60 * 6e4) {
26545
+ if (!Number.isSafeInteger(workerWatchdogCheckMs) || workerWatchdogCheckMs < 10 || workerWatchdogCheckMs > 6e4 || !Number.isSafeInteger(workerWatchdogTimeoutMs) || workerWatchdogTimeoutMs < workerWatchdogCheckMs * 2 || workerWatchdogTimeoutMs > 10 * 6e4 || !Number.isSafeInteger(workerWatchdogStartupMs) || workerWatchdogStartupMs < workerWatchdogCheckMs * 2 || workerWatchdogStartupMs > 10 * 6e4 || !Number.isSafeInteger(workerReadinessTimeoutMs) || workerReadinessTimeoutMs < workerWatchdogCheckMs * 2 || workerReadinessTimeoutMs > 10 * 6e4 || !Number.isSafeInteger(workerShutdownDeadlineMs) || workerShutdownDeadlineMs < workerWatchdogCheckMs * 2 || workerShutdownDeadlineMs > 10 * 6e4 || !Number.isSafeInteger(releaseProbationMs) || releaseProbationMs < 10 || releaseProbationMs > 24 * 60 * 6e4) {
26315
26546
  throw new Error("worker watchdog durations are invalid");
26316
26547
  }
26317
26548
  const activeVersion = await activatedReleaseVersion();
26318
26549
  const supervisorVersion = options.currentVersion !== void 0 ? options.currentVersion : process.env[SUPERVISOR_VERSION_ENV] ?? activeVersion ?? (productionLifecycle ? package_default.version : null);
26550
+ const workerDiagnosticsRoot = options.workerDiagnosticsRoot === void 0 ? productionLifecycle ? defaultWorkerDiagnosticsRoot() : null : options.workerDiagnosticsRoot;
26319
26551
  const spawnWorker = options.spawnWorker ?? ((command2, watchdog, compatibilityOwnership, containmentGateNonce) => defaultSpawn(
26320
26552
  command2,
26321
26553
  argv,
@@ -26323,7 +26555,8 @@ async function superviseHost(options = {}) {
26323
26555
  watchdog,
26324
26556
  compatibilityOwnership,
26325
26557
  containmentGateNonce,
26326
- platform
26558
+ platform,
26559
+ workerDiagnosticsRoot
26327
26560
  ));
26328
26561
  const install = options.installVersion ?? ((version2, signal) => installRelease(version2, signal ? { signal } : {}));
26329
26562
  const cleanupWorker = options.cleanupWorker ?? (options.spawnWorker ? async () => {
@@ -26424,6 +26657,16 @@ async function superviseHost(options = {}) {
26424
26657
  }
26425
26658
  return false;
26426
26659
  };
26660
+ const reportWorkerExit = async (record2, next) => {
26661
+ const { summary, context } = describeWorkerExit(record2);
26662
+ const detail = Object.entries(context).map(([key, value]) => `${key}=${value}`).join(" ");
26663
+ log2(`Zixt Host: worker ${summary}; ${next} (${detail})`);
26664
+ for (const line of record2.stderr) log2(`Zixt Host: worker stderr | ${line}`);
26665
+ if (!workerDiagnosticsRoot) return;
26666
+ if (!await recordWorkerExit(workerDiagnosticsRoot, record2)) {
26667
+ log2("Zixt Host: this exit could not be journalled, so the cloud will not receive it");
26668
+ }
26669
+ };
26427
26670
  const directCommand = (candidate) => {
26428
26671
  if (candidate.entry !== null || candidate.version === null) {
26429
26672
  return { entry: candidate.entry, version: candidate.version };
@@ -26518,6 +26761,7 @@ async function superviseHost(options = {}) {
26518
26761
  if (shuttingDown2) return 0;
26519
26762
  child = spawnWorker(command, watchdogLaunch, compatibilityOwnership, containmentGateNonce);
26520
26763
  const watchedChild = child;
26764
+ const workerStderr = captureWorkerStderr(watchedChild);
26521
26765
  let resolveChildExited;
26522
26766
  const childExited = new Promise((resolve18) => {
26523
26767
  resolveChildExited = resolve18;
@@ -26575,10 +26819,14 @@ async function superviseHost(options = {}) {
26575
26819
  let watchdogTimer;
26576
26820
  let watchdogTriggered = false;
26577
26821
  let watchdogCleanup = null;
26822
+ let containmentReason = null;
26578
26823
  let lastWatchdogHeartbeatAt = now();
26579
26824
  let lastWatchdogSequence = 0;
26580
26825
  let lastReadinessAt = 0;
26581
26826
  let lastReadinessSequence = 0;
26827
+ let announcedExitCode = null;
26828
+ let announcedShutdownAt = 0;
26829
+ let lastShutdownSequence = 0;
26582
26830
  const onWatchdogMessage = (message) => {
26583
26831
  if (watchdogLaunch && isWorkerWatchdogHeartbeat(message, watchdogLaunch, watchedChild.pid) && message.sequence > lastWatchdogSequence) {
26584
26832
  lastWatchdogSequence = message.sequence;
@@ -26590,10 +26838,19 @@ async function superviseHost(options = {}) {
26590
26838
  lastReadinessSequence = message.sequence;
26591
26839
  lastReadinessAt = now();
26592
26840
  }
26841
+ if (watchdogLaunch && isWorkerShutdownIntent(message, watchdogLaunch, watchedChild.pid) && message.sequence > lastShutdownSequence) {
26842
+ lastShutdownSequence = message.sequence;
26843
+ announcedExitCode = message.exitCode;
26844
+ announcedShutdownAt = now();
26845
+ log2(
26846
+ `Zixt Host: worker is stopping with code ${message.exitCode} (activeTasks=${message.activeTasks})`
26847
+ );
26848
+ }
26593
26849
  };
26594
- const containWorker = (message) => {
26850
+ const containWorker = (message, reason) => {
26595
26851
  if (shuttingDown2 || watchdogTriggered) return;
26596
26852
  watchdogTriggered = true;
26853
+ containmentReason = reason;
26597
26854
  if (watchdogTimer) clearInterval(watchdogTimer);
26598
26855
  watchdogTimer = void 0;
26599
26856
  log2(message);
@@ -26607,11 +26864,23 @@ async function superviseHost(options = {}) {
26607
26864
  if (watchdogLaunch) {
26608
26865
  watchedChild.on("message", onWatchdogMessage);
26609
26866
  watchdogTimer = setInterval(() => {
26610
- if (shuttingDown2 || watchdogTriggered || now() - lastWatchdogHeartbeatAt < (lastWatchdogSequence === 0 ? workerWatchdogStartupMs : workerWatchdogTimeoutMs)) {
26867
+ if (shuttingDown2 || watchdogTriggered) return;
26868
+ if (announcedExitCode !== null) {
26869
+ if (now() - announcedShutdownAt < workerShutdownDeadlineMs) return;
26870
+ containWorker(
26871
+ `Zixt Host: worker did not finish stopping within ${Math.round(
26872
+ workerShutdownDeadlineMs / 1e3
26873
+ )}s; terminating it and honouring the announced exit ${announcedExitCode}`,
26874
+ "watchdog_shutdown_deadline"
26875
+ );
26876
+ return;
26877
+ }
26878
+ if (now() - lastWatchdogHeartbeatAt < (lastWatchdogSequence === 0 ? workerWatchdogStartupMs : workerWatchdogTimeoutMs)) {
26611
26879
  return;
26612
26880
  }
26613
26881
  containWorker(
26614
- "Zixt Host: worker watchdog expired; terminating the unresponsive worker before restart"
26882
+ "Zixt Host: worker watchdog expired; terminating the unresponsive worker before restart",
26883
+ "watchdog_liveness"
26615
26884
  );
26616
26885
  }, workerWatchdogCheckMs);
26617
26886
  watchdogTimer.unref?.();
@@ -26623,7 +26892,8 @@ async function superviseHost(options = {}) {
26623
26892
  probationValidationTimer = setTimeout(() => {
26624
26893
  if (lastWatchdogSequence === 0 || now() - lastWatchdogHeartbeatAt >= workerWatchdogTimeoutMs || lastReadinessSequence === 0 || now() - lastReadinessAt >= workerReadinessTimeoutMs) {
26625
26894
  containWorker(
26626
- `Zixt Host: ${candidateVersion} did not prove cloud readiness during probation; restoring the previous working release`
26895
+ `Zixt Host: ${candidateVersion} did not prove cloud readiness during probation; restoring the previous working release`,
26896
+ "probation_readiness"
26627
26897
  );
26628
26898
  return;
26629
26899
  }
@@ -26632,7 +26902,8 @@ async function superviseHost(options = {}) {
26632
26902
  `Zixt Host: could not persist ${candidateVersion} probation evidence (${error52 instanceof Error ? error52.message : "unknown error"}); restoring the previous working release`
26633
26903
  );
26634
26904
  containWorker(
26635
- `Zixt Host: ${candidateVersion} probation could not be committed; containing the candidate`
26905
+ `Zixt Host: ${candidateVersion} probation could not be committed; containing the candidate`,
26906
+ "probation_commit"
26636
26907
  );
26637
26908
  });
26638
26909
  }, releaseProbationMs);
@@ -26647,6 +26918,22 @@ async function superviseHost(options = {}) {
26647
26918
  if (stopEscalation) clearTimeout(stopEscalation);
26648
26919
  stopEscalation = void 0;
26649
26920
  const runtimeMs = Math.max(0, now() - startedAt);
26921
+ const effectiveCode = watchdogTriggered && announcedExitCode === UPDATE_EXIT_CODE ? UPDATE_EXIT_CODE : code;
26922
+ const workerExit = {
26923
+ schema: 1,
26924
+ at: new Date(now()).toISOString(),
26925
+ version: command.version,
26926
+ pid: exitedChild.pid ?? null,
26927
+ code,
26928
+ signal,
26929
+ uptimeMs: runtimeMs,
26930
+ announcedExitCode,
26931
+ containment: containmentReason,
26932
+ msSinceHeartbeat: lastWatchdogSequence === 0 ? null : now() - lastWatchdogHeartbeatAt,
26933
+ heartbeats: lastWatchdogSequence,
26934
+ readinessMilestones: lastReadinessSequence,
26935
+ stderr: workerStderr()
26936
+ };
26650
26937
  if (probationValidationCommit) await probationValidationCommit;
26651
26938
  const orderlyValidatedBoundary = signal === null && !watchdogTriggered && (code === 0 || code === UPDATE_EXIT_CODE) && (releaseState === null && runtimeMs >= releaseProbationMs || releaseState?.phase === "validated" && command.version === releaseState.candidateVersion);
26652
26939
  if (orderlyValidatedBoundary && command.version) {
@@ -26679,12 +26966,13 @@ async function superviseHost(options = {}) {
26679
26966
  return 1;
26680
26967
  }
26681
26968
  if (!watchdogTriggered && (code === 0 || code === DO_NOT_RESTART_EXIT_CODE)) {
26969
+ if (code === DO_NOT_RESTART_EXIT_CODE) {
26970
+ await reportWorkerExit(workerExit, "this Machine needs attention before it can restart");
26971
+ }
26682
26972
  return code;
26683
26973
  }
26684
- if (code !== UPDATE_EXIT_CODE) {
26685
- log2(
26686
- `Zixt Host: worker ${signal ? `was killed by ${signal}` : `exited unexpectedly with code ${code ?? "unknown"}`}; restarting`
26687
- );
26974
+ if (effectiveCode !== UPDATE_EXIT_CODE) {
26975
+ await reportWorkerExit(workerExit, "restarting");
26688
26976
  if (rollbackCandidate && command.version === rollbackCandidate.failedVersion) {
26689
26977
  const failedVersion = rollbackCandidate.failedVersion;
26690
26978
  await restoreFallback(failedVersion, rollbackCandidate.command);
@@ -26695,6 +26983,9 @@ async function superviseHost(options = {}) {
26695
26983
  if (!await waitAfterCrash(runtimeMs)) return 0;
26696
26984
  continue;
26697
26985
  }
26986
+ if (watchdogTriggered) {
26987
+ await reportWorkerExit(workerExit, "installing the update it asked for anyway");
26988
+ }
26698
26989
  consecutiveCrashes = 0;
26699
26990
  if (orderlyValidatedBoundary) rollbackCandidate = null;
26700
26991
  const target = await published();
@@ -26819,15 +27110,47 @@ async function superviseHost(options = {}) {
26819
27110
  }
26820
27111
  }
26821
27112
 
27113
+ // src/worker-shutdown.ts
27114
+ var IDLE_SHUTDOWN_DEADLINE_MS = 2e3;
27115
+ var RECOVERING_SHUTDOWN_DEADLINE_MS = 3e4;
27116
+ var FORCED_EXIT_DRAIN_MS = 1e3;
27117
+ var defaultSchedule = (run3, ms) => {
27118
+ setTimeout(run3, ms).unref?.();
27119
+ };
27120
+ function beginWorkerShutdown(options) {
27121
+ const announce = options.announce ?? reportWorkerShutdown;
27122
+ const finish = options.finish ?? finishWorkerProcess;
27123
+ const exit = options.exit ?? ((code) => process.exit(code));
27124
+ const schedule = options.schedule ?? defaultSchedule;
27125
+ announce(options.exitCode, options.activeTasks);
27126
+ const recoveringLiveRuns = options.activeTasks > 0;
27127
+ const deadlineMs = recoveringLiveRuns ? RECOVERING_SHUTDOWN_DEADLINE_MS : IDLE_SHUTDOWN_DEADLINE_MS;
27128
+ const forcedExitCode = recoveringLiveRuns ? 1 : options.exitCode;
27129
+ let teardownCompleted = false;
27130
+ schedule(() => {
27131
+ const code = teardownCompleted ? options.exitCode : forcedExitCode;
27132
+ options.onForcedExit?.({ deadlineMs, code, teardownCompleted });
27133
+ void options.stopHeartbeat().then(() => {
27134
+ finish(code);
27135
+ schedule(() => exit(code), FORCED_EXIT_DRAIN_MS);
27136
+ });
27137
+ }, deadlineMs);
27138
+ void options.teardown().then(() => {
27139
+ teardownCompleted = true;
27140
+ return options.stopHeartbeat();
27141
+ }).then(() => finish(options.exitCode)).catch(() => {
27142
+ });
27143
+ }
27144
+
26822
27145
  // src/index.ts
26823
- import { homedir as homedir13, hostname as hostname3 } from "node:os";
27146
+ import { homedir as homedir14, hostname as hostname3 } from "node:os";
26824
27147
 
26825
27148
  // src/hardware.ts
26826
27149
  import { existsSync } from "node:fs";
26827
27150
  import { statfs } from "node:fs/promises";
26828
- import { cpus, freemem, homedir as homedir3, totalmem } from "node:os";
27151
+ import { cpus, freemem, homedir as homedir4, totalmem } from "node:os";
26829
27152
  import { dirname as dirname5, resolve as resolve6 } from "node:path";
26830
- async function machineHardware(workRoot = homedir3()) {
27153
+ async function machineHardware(workRoot = homedir4()) {
26831
27154
  return {
26832
27155
  // A container or cgroup can hide processors from this count; it is what
26833
27156
  // this process can see, which is what its Tasks will actually get.
@@ -27049,17 +27372,17 @@ function createDemoBrowserAdapterFactory() {
27049
27372
  }
27050
27373
 
27051
27374
  // src/browser/manager.ts
27052
- import { lstat as lstat6, mkdir as mkdir5, open as open5, opendir, readFile as readFile7, rename as rename4, rm as rm5 } from "node:fs/promises";
27053
- import { homedir as homedir4 } from "node:os";
27054
- import { dirname as dirname6, join as join8, resolve as resolve7 } from "node:path";
27375
+ import { lstat as lstat6, mkdir as mkdir6, open as open5, opendir, readFile as readFile8, rename as rename4, rm as rm6 } from "node:fs/promises";
27376
+ import { homedir as homedir5 } from "node:os";
27377
+ import { dirname as dirname6, join as join9, resolve as resolve7 } from "node:path";
27055
27378
  var SAFE_SEGMENT2 = /^[A-Za-z0-9_-]{1,200}$/;
27056
27379
  var FRAME_MIN_INTERVAL_MS = 100;
27057
27380
  var IDLE_TIMEOUT_MS = 15 * 6e4;
27058
27381
  var BrowserManager = class {
27059
27382
  constructor(opts) {
27060
27383
  this.opts = opts;
27061
- this.profileRoot = opts.profileRoot ?? join8(homedir4(), ".zixt", "browser-profiles");
27062
- this.profileStateRoot = join8(this.profileRoot, ".profile-state");
27384
+ this.profileRoot = opts.profileRoot ?? join9(homedir5(), ".zixt", "browser-profiles");
27385
+ this.profileStateRoot = join9(this.profileRoot, ".profile-state");
27063
27386
  this.viewport = opts.viewport ?? BROWSER_DEFAULT_VIEWPORT;
27064
27387
  this.idleTimeoutMs = opts.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
27065
27388
  this.frameMinIntervalMs = opts.frameMinIntervalMs ?? FRAME_MIN_INTERVAL_MS;
@@ -27157,7 +27480,7 @@ var BrowserManager = class {
27157
27480
  return target;
27158
27481
  }
27159
27482
  async ensureOwnedDirectory(path) {
27160
- await mkdir5(path, { recursive: true, mode: 448 });
27483
+ await mkdir6(path, { recursive: true, mode: 448 });
27161
27484
  const stat3 = await lstat6(path);
27162
27485
  if (!stat3.isDirectory() || stat3.isSymbolicLink()) {
27163
27486
  throw new Error("browser profile root must be an owned directory, not a symbolic link");
@@ -27193,7 +27516,7 @@ var BrowserManager = class {
27193
27516
  }
27194
27517
  async readProfileState(agentId) {
27195
27518
  try {
27196
- const raw = JSON.parse(await readFile7(this.statePath(agentId), "utf8"));
27519
+ const raw = JSON.parse(await readFile8(this.statePath(agentId), "utf8"));
27197
27520
  if (typeof raw !== "object" || raw === null || !Number.isInteger(raw.revision) || Number(raw.revision) < 0 || !["allowed", "purged"].includes(String(raw.state))) {
27198
27521
  throw new Error("browser profile lifecycle marker is invalid");
27199
27522
  }
@@ -27223,7 +27546,7 @@ var BrowserManager = class {
27223
27546
  await this.syncDirectory(this.profileStateRoot);
27224
27547
  await this.syncDirectory(this.profileRoot);
27225
27548
  } catch (error52) {
27226
- await rm5(temporary, { force: true }).catch(() => {
27549
+ await rm6(temporary, { force: true }).catch(() => {
27227
27550
  });
27228
27551
  throw error52;
27229
27552
  }
@@ -27299,7 +27622,7 @@ var BrowserManager = class {
27299
27622
  } catch (error52) {
27300
27623
  if (error52.code !== "ENOENT") throw error52;
27301
27624
  }
27302
- await mkdir5(profileDir, { recursive: true, mode: 448 });
27625
+ await mkdir6(profileDir, { recursive: true, mode: 448 });
27303
27626
  const adapter = await this.opts.factory.open({
27304
27627
  agentId,
27305
27628
  profileDir,
@@ -27378,7 +27701,7 @@ var BrowserManager = class {
27378
27701
  purgeId
27379
27702
  });
27380
27703
  await this.closeLocked(agentId, "stopped");
27381
- await rm5(this.profilePath(agentId), { recursive: true, force: true, maxRetries: 3 });
27704
+ await rm6(this.profilePath(agentId), { recursive: true, force: true, maxRetries: 3 });
27382
27705
  await this.syncDirectory(this.profileRoot);
27383
27706
  });
27384
27707
  }
@@ -28078,10 +28401,10 @@ function createPlaywrightBrowserAdapterFactory(dependencies = {}) {
28078
28401
 
28079
28402
  // src/runners/cli-runner.ts
28080
28403
  import { spawn as spawn8 } from "node:child_process";
28081
- import { randomUUID as randomUUID10 } from "node:crypto";
28082
- import { lstat as lstat11, mkdir as mkdir10, realpath as realpath8 } from "node:fs/promises";
28083
- import { homedir as homedir5 } from "node:os";
28084
- import { dirname as dirname8, isAbsolute as isAbsolute14, join as join14, resolve as resolve10 } from "node:path";
28404
+ import { randomUUID as randomUUID11 } from "node:crypto";
28405
+ import { lstat as lstat11, mkdir as mkdir11, realpath as realpath8 } from "node:fs/promises";
28406
+ import { homedir as homedir6 } from "node:os";
28407
+ import { dirname as dirname8, isAbsolute as isAbsolute15, join as join15, resolve as resolve10 } from "node:path";
28085
28408
 
28086
28409
  // src/tool-packs/browser/authentication-wall.ts
28087
28410
  var AUTH_PATH_SEGMENT = /(?:^|\/)(?:log[-_]?in|sign[-_]?in|sso|saml|auth|authorize|authenticate|oauth2?|session\/new|checkpoint)(?:\/|$)/i;
@@ -28462,7 +28785,7 @@ function createBrowserToolPack(deps) {
28462
28785
  }
28463
28786
 
28464
28787
  // src/tool-packs/provider-intents.ts
28465
- import { createHash as createHash2, randomUUID as randomUUID3 } from "node:crypto";
28788
+ import { createHash as createHash2, randomUUID as randomUUID4 } from "node:crypto";
28466
28789
 
28467
28790
  // src/tool-packs/github/rest-transport.ts
28468
28791
  var MAX_RESPONSE_BYTES = 2 * 1024 * 1024;
@@ -28760,7 +29083,7 @@ function terminalForError(intentId2, error52) {
28760
29083
  }
28761
29084
  async function settle(context, terminal) {
28762
29085
  try {
28763
- const result = await context.settleProviderIntent(randomUUID3(), terminal);
29086
+ const result = await context.settleProviderIntent(randomUUID4(), terminal);
28764
29087
  if (!result.ok) return { ok: false, error: result.error || RECORDING_FAILED };
28765
29088
  return null;
28766
29089
  } catch {
@@ -30252,7 +30575,7 @@ function createPullRequestTools(runtime) {
30252
30575
  }
30253
30576
 
30254
30577
  // src/tool-packs/github/repository-creation.ts
30255
- import { randomUUID as randomUUID4 } from "node:crypto";
30578
+ import { randomUUID as randomUUID5 } from "node:crypto";
30256
30579
  var RECORDING_FAILED2 = "The provider call completed, but Zixt could not record its outcome. Do not retry; wait for reconciliation.";
30257
30580
  var CLONE_WARNING = "The repository was created, but Zixt could not prepare its local workspace. Do not create it again.";
30258
30581
  var REPOSITORY_ACCESS_WARNING = "Repository created, but GitHub access is still needed. Ask a GitHub organization owner to add this repository in the GitHub App settings, then use Check access in Zixt. Do not create it again.";
@@ -30508,7 +30831,7 @@ function failure(error52) {
30508
30831
  }
30509
30832
  function createGithubRepositoryCreator(input) {
30510
30833
  const now = input.now ?? (() => /* @__PURE__ */ new Date());
30511
- const terminalRequestId = input.terminalRequestId ?? randomUUID4;
30834
+ const terminalRequestId = input.terminalRequestId ?? randomUUID5;
30512
30835
  return async (rawArgs) => {
30513
30836
  let args;
30514
30837
  try {
@@ -30697,7 +31020,7 @@ function createGithubRepositoryCreator(input) {
30697
31020
  }
30698
31021
 
30699
31022
  // src/tool-packs/github/push.ts
30700
- import { randomUUID as randomUUID5 } from "node:crypto";
31023
+ import { randomUUID as randomUUID6 } from "node:crypto";
30701
31024
  var COMMIT_SHA = /^[a-f0-9]{40}(?:[a-f0-9]{24})?$/;
30702
31025
  var RECORDING_FAILED3 = "The provider call completed, but Zixt could not record its outcome. Do not retry; wait for reconciliation.";
30703
31026
  function claimResult3(value) {
@@ -30737,7 +31060,7 @@ function error51(message) {
30737
31060
  }
30738
31061
  function createGithubPushOrchestrator(input) {
30739
31062
  const now = input.now ?? (() => /* @__PURE__ */ new Date());
30740
- const terminalRequestId = input.terminalRequestId ?? randomUUID5;
31063
+ const terminalRequestId = input.terminalRequestId ?? randomUUID6;
30741
31064
  return async (rawArgs) => {
30742
31065
  try {
30743
31066
  const args = rawArgs;
@@ -30899,15 +31222,15 @@ function createGithubPushOrchestrator(input) {
30899
31222
 
30900
31223
  // src/tool-packs/github/git-bridge.ts
30901
31224
  import { spawn as spawn6 } from "node:child_process";
30902
- import { randomUUID as randomUUID7 } from "node:crypto";
30903
- import { chmod as chmod4, lstat as lstat8, mkdir as mkdir6, realpath as realpath5, rm as rm6 } from "node:fs/promises";
30904
- import { dirname as dirname7, isAbsolute as isAbsolute10, join as join10, relative as relative6 } from "node:path";
31225
+ import { randomUUID as randomUUID8 } from "node:crypto";
31226
+ import { chmod as chmod4, lstat as lstat8, mkdir as mkdir7, realpath as realpath5, rm as rm7 } from "node:fs/promises";
31227
+ import { dirname as dirname7, isAbsolute as isAbsolute11, join as join11, relative as relative6 } from "node:path";
30905
31228
 
30906
31229
  // src/tool-packs/github/git-credential-broker.ts
30907
31230
  import { createServer } from "node:http";
30908
- import { randomBytes, randomUUID as randomUUID6, timingSafeEqual } from "node:crypto";
30909
- import { chmod as chmod3, lstat as lstat7, realpath as realpath4, writeFile as writeFile2 } from "node:fs/promises";
30910
- import { isAbsolute as isAbsolute9, join as join9, relative as relative5 } from "node:path";
31231
+ import { randomBytes, randomUUID as randomUUID7, timingSafeEqual } from "node:crypto";
31232
+ import { chmod as chmod3, lstat as lstat7, realpath as realpath4, writeFile as writeFile3 } from "node:fs/promises";
31233
+ import { isAbsolute as isAbsolute10, join as join10, relative as relative5 } from "node:path";
30911
31234
  var MAX_REQUEST_BYTES = 16 * 1024;
30912
31235
  var FILE_MODE2 = 384;
30913
31236
  var HELPER_SOURCE = String.raw`'use strict';
@@ -31021,7 +31344,7 @@ async function readBoundedBody2(request) {
31021
31344
  }
31022
31345
  function assertChildPath(parent, child) {
31023
31346
  const path = relative5(parent, child);
31024
- if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute9(path)) {
31347
+ if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute10(path)) {
31025
31348
  throw new Error("Git credential helper path escaped its private run directory");
31026
31349
  }
31027
31350
  }
@@ -31036,9 +31359,9 @@ async function createGithubGitCredentialBroker(input) {
31036
31359
  throw new Error("Git credential broker requires a private real run directory");
31037
31360
  }
31038
31361
  const runRoot = await realpath4(input.runArtifactsRoot);
31039
- const helperPath = join9(runRoot, `git-credential-${randomUUID6()}.cjs`);
31362
+ const helperPath = join10(runRoot, `git-credential-${randomUUID7()}.cjs`);
31040
31363
  assertChildPath(runRoot, helperPath);
31041
- await writeFile2(helperPath, HELPER_SOURCE, { flag: "wx", mode: FILE_MODE2 });
31364
+ await writeFile3(helperPath, HELPER_SOURCE, { flag: "wx", mode: FILE_MODE2 });
31042
31365
  await chmod3(helperPath, FILE_MODE2);
31043
31366
  const capability2 = randomBytes(32).toString("base64url");
31044
31367
  const expectedPath = `${input.repositoryFullName}.git`;
@@ -31136,7 +31459,7 @@ ${stderr}`;
31136
31459
  }
31137
31460
  function assertBelow2(parent, child, label) {
31138
31461
  const path = relative6(parent, child);
31139
- if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute10(path)) {
31462
+ if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute11(path)) {
31140
31463
  throw new GithubGitProcessError("invalid_input");
31141
31464
  }
31142
31465
  void label;
@@ -31151,7 +31474,7 @@ async function requireRealDirectory2(path, label) {
31151
31474
  }
31152
31475
  async function validateTokenlessPaths(command) {
31153
31476
  if (command.kind === "clone-from-bridge") {
31154
- if (!isAbsolute10(command.destination)) throw new GithubGitProcessError("invalid_input");
31477
+ if (!isAbsolute11(command.destination)) throw new GithubGitProcessError("invalid_input");
31155
31478
  const parent = await requireRealDirectory2(dirname7(command.destination), "clone parent");
31156
31479
  assertBelow2(parent, command.destination, "clone destination");
31157
31480
  const destination = await lstat8(command.destination).catch((error52) => {
@@ -31162,7 +31485,7 @@ async function validateTokenlessPaths(command) {
31162
31485
  return;
31163
31486
  }
31164
31487
  if ("repositoryPath" in command) {
31165
- if (!isAbsolute10(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
31488
+ if (!isAbsolute11(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
31166
31489
  const repositoryPath5 = await requireRealDirectory2(command.repositoryPath, "repository path");
31167
31490
  if (repositoryPath5 !== command.repositoryPath) throw new GithubGitProcessError("invalid_input");
31168
31491
  }
@@ -31242,7 +31565,7 @@ async function runGit(input, args, env) {
31242
31565
  if (input.authoritySignal.aborted || input.cancelledNow()) {
31243
31566
  throw new GithubGitProcessError("cancelled");
31244
31567
  }
31245
- if (!isAbsolute10(input.executablePath)) throw new GithubGitProcessError("invalid_input");
31568
+ if (!isAbsolute11(input.executablePath)) throw new GithubGitProcessError("invalid_input");
31246
31569
  const timeoutMs = input.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
31247
31570
  if (!Number.isInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > DEFAULT_TIMEOUT_MS2) {
31248
31571
  throw new GithubGitProcessError("invalid_input");
@@ -31348,7 +31671,7 @@ function tokenlessArgs(command) {
31348
31671
  switch (command.kind) {
31349
31672
  case "clone-from-bridge":
31350
31673
  assertRef(command.branch);
31351
- if (!isAbsolute10(command.destination)) throw new GithubGitProcessError("invalid_input");
31674
+ if (!isAbsolute11(command.destination)) throw new GithubGitProcessError("invalid_input");
31352
31675
  return [
31353
31676
  "clone",
31354
31677
  "--no-recurse-submodules",
@@ -31360,7 +31683,7 @@ function tokenlessArgs(command) {
31360
31683
  ];
31361
31684
  case "fetch-from-bridge":
31362
31685
  assertFetchRefspecs(command.refspecs);
31363
- if (!isAbsolute10(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
31686
+ if (!isAbsolute11(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
31364
31687
  return [
31365
31688
  "-C",
31366
31689
  command.repositoryPath,
@@ -31372,7 +31695,7 @@ function tokenlessArgs(command) {
31372
31695
  ...command.refspecs
31373
31696
  ];
31374
31697
  case "copy-commit-to-bridge":
31375
- if (!isAbsolute10(command.repositoryPath) || !SHA.test(command.sha)) {
31698
+ if (!isAbsolute11(command.repositoryPath) || !SHA.test(command.sha)) {
31376
31699
  throw new GithubGitProcessError("invalid_input");
31377
31700
  }
31378
31701
  return [
@@ -31384,11 +31707,11 @@ function tokenlessArgs(command) {
31384
31707
  `${command.sha}:refs/zixt/push-source`
31385
31708
  ];
31386
31709
  case "rev-parse":
31387
- if (!isAbsolute10(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
31710
+ if (!isAbsolute11(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
31388
31711
  assertRef(command.ref);
31389
31712
  return ["-C", command.repositoryPath, "rev-parse", "--verify", `${command.ref}^{commit}`];
31390
31713
  case "remote-configure":
31391
- if (!isAbsolute10(command.repositoryPath) || !REPOSITORY.test(command.repositoryFullName)) {
31714
+ if (!isAbsolute11(command.repositoryPath) || !REPOSITORY.test(command.repositoryFullName)) {
31392
31715
  throw new GithubGitProcessError("invalid_input");
31393
31716
  }
31394
31717
  return [
@@ -31400,7 +31723,7 @@ function tokenlessArgs(command) {
31400
31723
  `https://github.com/${command.repositoryFullName}.git`
31401
31724
  ];
31402
31725
  case "status":
31403
- if (!isAbsolute10(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
31726
+ if (!isAbsolute11(command.repositoryPath)) throw new GithubGitProcessError("invalid_input");
31404
31727
  return [
31405
31728
  "-C",
31406
31729
  command.repositoryPath,
@@ -31430,7 +31753,7 @@ function createGithubGitBridge(input) {
31430
31753
  })();
31431
31754
  const requireBridge = async (value) => {
31432
31755
  const current = await roots();
31433
- if (!isAbsolute10(value) || !active.has(value)) throw new GithubGitProcessError("invalid_input");
31756
+ if (!isAbsolute11(value) || !active.has(value)) throw new GithubGitProcessError("invalid_input");
31434
31757
  const real = await requireRealDirectory2(value, "git bridge");
31435
31758
  assertBelow2(current.bridges, real, "git bridge");
31436
31759
  if (real !== value) throw new GithubGitProcessError("invalid_input");
@@ -31440,9 +31763,9 @@ function createGithubGitBridge(input) {
31440
31763
  async createPrivateBridge() {
31441
31764
  if (closed) throw new GithubGitProcessError("cancelled");
31442
31765
  const current = await roots();
31443
- const path = join10(current.bridges, `${randomUUID7()}.git`);
31766
+ const path = join11(current.bridges, `${randomUUID8()}.git`);
31444
31767
  assertBelow2(current.bridges, path, "git bridge");
31445
- await mkdir6(path, { mode: DIRECTORY_MODE2 });
31768
+ await mkdir7(path, { mode: DIRECTORY_MODE2 });
31446
31769
  await chmod4(path, DIRECTORY_MODE2);
31447
31770
  try {
31448
31771
  await runGit(
@@ -31458,16 +31781,16 @@ function createGithubGitBridge(input) {
31458
31781
  );
31459
31782
  const real = await requireRealDirectory2(path, "git bridge");
31460
31783
  assertBelow2(current.bridges, real, "git bridge");
31461
- const hooks = join10(real, "hooks");
31462
- await rm6(hooks, { recursive: true, force: true });
31463
- await mkdir6(hooks, { mode: DIRECTORY_MODE2 });
31784
+ const hooks = join11(real, "hooks");
31785
+ await rm7(hooks, { recursive: true, force: true });
31786
+ await mkdir7(hooks, { mode: DIRECTORY_MODE2 });
31464
31787
  await chmod4(hooks, DIRECTORY_MODE2);
31465
- const config2 = join10(real, "config");
31788
+ const config2 = join11(real, "config");
31466
31789
  await chmod4(config2, 384);
31467
31790
  active.add(real);
31468
31791
  return real;
31469
31792
  } catch (error52) {
31470
- await rm6(path, { recursive: true, force: true }).catch(() => {
31793
+ await rm7(path, { recursive: true, force: true }).catch(() => {
31471
31794
  });
31472
31795
  throw error52;
31473
31796
  }
@@ -31561,7 +31884,7 @@ function createGithubGitBridge(input) {
31561
31884
  },
31562
31885
  async destroyPrivateBridge(path) {
31563
31886
  const bridge = await requireBridge(path);
31564
- await rm6(bridge, { recursive: true, force: true });
31887
+ await rm7(bridge, { recursive: true, force: true });
31565
31888
  active.delete(bridge);
31566
31889
  credentialed2.delete(bridge);
31567
31890
  },
@@ -31569,7 +31892,7 @@ function createGithubGitBridge(input) {
31569
31892
  if (closed) return;
31570
31893
  closed = true;
31571
31894
  const paths = [...active];
31572
- await Promise.all(paths.map((path) => rm6(path, { recursive: true, force: true })));
31895
+ await Promise.all(paths.map((path) => rm7(path, { recursive: true, force: true })));
31573
31896
  active.clear();
31574
31897
  credentialed2.clear();
31575
31898
  }
@@ -31909,9 +32232,9 @@ function createRepositoryTools(runtime) {
31909
32232
  }
31910
32233
 
31911
32234
  // src/tool-packs/github/workspace.ts
31912
- import { randomUUID as randomUUID8 } from "node:crypto";
31913
- import { chmod as chmod5, lstat as lstat9, mkdir as mkdir7, readFile as readFile8, realpath as realpath6, rename as rename5, rm as rm7, writeFile as writeFile3 } from "node:fs/promises";
31914
- import { isAbsolute as isAbsolute11, join as join11, relative as relative7, resolve as resolve8 } from "node:path";
32235
+ import { randomUUID as randomUUID9 } from "node:crypto";
32236
+ import { chmod as chmod5, lstat as lstat9, mkdir as mkdir8, readFile as readFile9, realpath as realpath6, rename as rename5, rm as rm8, writeFile as writeFile4 } from "node:fs/promises";
32237
+ import { isAbsolute as isAbsolute12, join as join12, relative as relative7, resolve as resolve8 } from "node:path";
31915
32238
  var SAFE_LOCAL_ID = /^[A-Za-z0-9_-]{1,200}$/;
31916
32239
  var FULL_NAME2 = /^[A-Za-z0-9_.-]{1,100}\/[A-Za-z0-9_.-]{1,100}$/;
31917
32240
  var DIRECTORY_MODE3 = 448;
@@ -31929,7 +32252,7 @@ function hasControlCharacter2(value) {
31929
32252
  }
31930
32253
  function assertBelow3(parent, child, label) {
31931
32254
  const path = relative7(parent, child);
31932
- if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute11(path)) {
32255
+ if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute12(path)) {
31933
32256
  throw new Error(`${label} escaped the task workspace`);
31934
32257
  }
31935
32258
  }
@@ -31948,10 +32271,10 @@ async function requireRealDirectory3(path, label) {
31948
32271
  return real;
31949
32272
  }
31950
32273
  async function createOrRequirePrivateDirectory(parent, name, label) {
31951
- const path = join11(parent, name);
32274
+ const path = join12(parent, name);
31952
32275
  assertBelow3(parent, path, label);
31953
32276
  try {
31954
- await mkdir7(path, { mode: DIRECTORY_MODE3 });
32277
+ await mkdir8(path, { mode: DIRECTORY_MODE3 });
31955
32278
  } catch (error52) {
31956
32279
  if (error52.code !== "EEXIST") throw error52;
31957
32280
  }
@@ -32031,8 +32354,8 @@ async function createGithubWorkspaceService(input) {
32031
32354
  if (expectedFullName !== void 0 && repository.fullName !== expectedFullName) {
32032
32355
  throw new Error("GitHub repository name does not match this task grant");
32033
32356
  }
32034
- const destination = join11(repositoriesRoot, parsed.data);
32035
- const metadataPath = join11(metadataRoot, `${parsed.data}.json`);
32357
+ const destination = join12(repositoriesRoot, parsed.data);
32358
+ const metadataPath = join12(metadataRoot, `${parsed.data}.json`);
32036
32359
  if (!await pathExists(destination) || !await pathExists(metadataPath)) {
32037
32360
  throw new Error("GitHub repository workspace has not been prepared");
32038
32361
  }
@@ -32040,7 +32363,7 @@ async function createGithubWorkspaceService(input) {
32040
32363
  if (!metadataEntry.isFile() || metadataEntry.isSymbolicLink()) {
32041
32364
  throw new Error("GitHub workspace metadata is invalid");
32042
32365
  }
32043
- const metadata = parseMetadata(await readFile8(metadataPath, "utf8"));
32366
+ const metadata = parseMetadata(await readFile9(metadataPath, "utf8"));
32044
32367
  if (metadata.repositoryId !== parsed.data || metadata.fullName !== repository.fullName || !samePath(metadata.path, destination)) {
32045
32368
  throw new Error("GitHub workspace metadata does not match this repository");
32046
32369
  }
@@ -32049,14 +32372,14 @@ async function createGithubWorkspaceService(input) {
32049
32372
  return real;
32050
32373
  };
32051
32374
  const cloneRepository = async (clone2) => {
32052
- const destination = join11(repositoriesRoot, clone2.repositoryId);
32053
- const metadataPath = join11(metadataRoot, `${clone2.repositoryId}.json`);
32375
+ const destination = join12(repositoriesRoot, clone2.repositoryId);
32376
+ const metadataPath = join12(metadataRoot, `${clone2.repositoryId}.json`);
32054
32377
  assertBelow3(repositoriesRoot, destination, "repository path");
32055
32378
  assertBelow3(metadataRoot, metadataPath, "repository metadata");
32056
32379
  if (await pathExists(destination) || await pathExists(metadataPath)) {
32057
32380
  throw new Error("GitHub repository workspace already exists or is inconsistent");
32058
32381
  }
32059
- const temporary = join11(repositoriesRoot, `.clone-${randomUUID8()}`);
32382
+ const temporary = join12(repositoriesRoot, `.clone-${randomUUID9()}`);
32060
32383
  assertBelow3(repositoriesRoot, temporary, "temporary clone");
32061
32384
  try {
32062
32385
  await input.git.clone({
@@ -32081,9 +32404,9 @@ async function createGithubWorkspaceService(input) {
32081
32404
  path: destination,
32082
32405
  ...clone2.createIntentId === void 0 ? {} : { createIntentId: clone2.createIntentId }
32083
32406
  };
32084
- const metadataTemporary = join11(metadataRoot, `.${clone2.repositoryId}-${randomUUID8()}.tmp`);
32407
+ const metadataTemporary = join12(metadataRoot, `.${clone2.repositoryId}-${randomUUID9()}.tmp`);
32085
32408
  assertBelow3(metadataRoot, metadataTemporary, "temporary repository metadata");
32086
- await writeFile3(metadataTemporary, `${JSON.stringify(metadata)}
32409
+ await writeFile4(metadataTemporary, `${JSON.stringify(metadata)}
32087
32410
  `, {
32088
32411
  flag: "wx",
32089
32412
  mode: FILE_MODE3
@@ -32094,11 +32417,11 @@ async function createGithubWorkspaceService(input) {
32094
32417
  try {
32095
32418
  await rename5(metadataTemporary, metadataPath);
32096
32419
  } catch (error52) {
32097
- await rm7(destination, { recursive: true, force: true });
32420
+ await rm8(destination, { recursive: true, force: true });
32098
32421
  throw error52;
32099
32422
  }
32100
32423
  } finally {
32101
- await rm7(metadataTemporary, { force: true }).catch(() => {
32424
+ await rm8(metadataTemporary, { force: true }).catch(() => {
32102
32425
  });
32103
32426
  }
32104
32427
  const path = await requireRealDirectory3(destination, "GitHub repository");
@@ -32110,14 +32433,14 @@ async function createGithubWorkspaceService(input) {
32110
32433
  headSha
32111
32434
  };
32112
32435
  } finally {
32113
- await rm7(temporary, { recursive: true, force: true }).catch(() => {
32436
+ await rm8(temporary, { recursive: true, force: true }).catch(() => {
32114
32437
  });
32115
32438
  }
32116
32439
  };
32117
32440
  const prepareRepository = async (authority) => {
32118
32441
  const { repository } = authority;
32119
- const destination = join11(repositoriesRoot, repository.repositoryId);
32120
- const metadataPath = join11(metadataRoot, `${repository.repositoryId}.json`);
32442
+ const destination = join12(repositoriesRoot, repository.repositoryId);
32443
+ const metadataPath = join12(metadataRoot, `${repository.repositoryId}.json`);
32121
32444
  assertBelow3(repositoriesRoot, destination, "repository path");
32122
32445
  assertBelow3(metadataRoot, metadataPath, "repository metadata");
32123
32446
  return withWorkspaceLock(destination, async () => {
@@ -32142,7 +32465,7 @@ async function createGithubWorkspaceService(input) {
32142
32465
  if (!metadataEntry.isFile() || metadataEntry.isSymbolicLink()) {
32143
32466
  throw new Error("GitHub workspace metadata is invalid");
32144
32467
  }
32145
- const metadata = parseMetadata(await readFile8(metadataPath, "utf8"));
32468
+ const metadata = parseMetadata(await readFile9(metadataPath, "utf8"));
32146
32469
  if (metadata.repositoryId !== repository.repositoryId || metadata.fullName !== repository.fullName || !samePath(metadata.path, destination)) {
32147
32470
  throw new Error("GitHub workspace metadata does not match this repository");
32148
32471
  }
@@ -32282,7 +32605,7 @@ async function createGithubWorkspaceService(input) {
32282
32605
  throw new Error("GitHub created repository is outside this installation");
32283
32606
  }
32284
32607
  parseGitRef(cloneInput.repository.defaultBranch, "default branch");
32285
- return withWorkspaceLock(join11(repositoriesRoot, repositoryId2), async () => {
32608
+ return withWorkspaceLock(join12(repositoriesRoot, repositoryId2), async () => {
32286
32609
  const prepared = await cloneRepository({
32287
32610
  repositoryId: repositoryId2,
32288
32611
  fullName: cloneInput.repository.fullName,
@@ -32689,7 +33012,7 @@ function createGithubToolPackFactory(options = {}) {
32689
33012
  var githubToolPackFactory = createGithubToolPackFactory();
32690
33013
 
32691
33014
  // src/runners/linear-api.ts
32692
- import { createHash as createHash3, randomUUID as randomUUID9 } from "node:crypto";
33015
+ import { createHash as createHash3, randomUUID as randomUUID10 } from "node:crypto";
32693
33016
  var MAX_RESPONSE_BYTES2 = 2 * 1024 * 1024;
32694
33017
  var MAX_RESULT_STRING = 1e5;
32695
33018
  var MAX_RESULT_ARRAY = 100;
@@ -33212,7 +33535,7 @@ function operationFor(name, args, appUserId, heldBy) {
33212
33535
  case "linear_create_comment": {
33213
33536
  const issueId = requiredString(args, "issue_id");
33214
33537
  const body = requiredString(args, "body", 1e5);
33215
- const commentId = randomUUID9();
33538
+ const commentId = randomUUID10();
33216
33539
  return {
33217
33540
  query: `mutation ZixtLinearCreateComment($input: CommentCreateInput!) {
33218
33541
  commentCreate(input: $input) { success comment { ${COMMENT_FIELDS} } }
@@ -33823,8 +34146,8 @@ function createDefaultToolPackRegistry() {
33823
34146
  }
33824
34147
 
33825
34148
  // src/runners/attachments.ts
33826
- import { mkdir as mkdir8, writeFile as writeFile4 } from "node:fs/promises";
33827
- import { join as join12 } from "node:path";
34149
+ import { mkdir as mkdir9, writeFile as writeFile5 } from "node:fs/promises";
34150
+ import { join as join13 } from "node:path";
33828
34151
  var WINDOWS_RESERVED = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\..*)?$/i;
33829
34152
  function sanitizeAttachmentFileName(name) {
33830
34153
  const base = name.split(/[/\\]/).pop() ?? "";
@@ -33853,10 +34176,10 @@ async function materializeAttachments(task, taskRoot) {
33853
34176
  `attached file "${attachment.name}" arrived incomplete (${bytes.byteLength} of ${attachment.size} bytes)`
33854
34177
  );
33855
34178
  }
33856
- const directory = join12(taskRoot, ".zixt-attachments", task.taskId, attachment.id);
33857
- await mkdir8(directory, { recursive: true });
33858
- const path = join12(directory, sanitizeAttachmentFileName(attachment.name));
33859
- await writeFile4(path, bytes);
34179
+ const directory = join13(taskRoot, ".zixt-attachments", task.taskId, attachment.id);
34180
+ await mkdir9(directory, { recursive: true });
34181
+ const path = join13(directory, sanitizeAttachmentFileName(attachment.name));
34182
+ await writeFile5(path, bytes);
33860
34183
  materialized.push({
33861
34184
  path,
33862
34185
  name: attachment.name,
@@ -34820,7 +35143,7 @@ function createAskUserServer() {
34820
35143
  }
34821
35144
 
34822
35145
  // src/runners/runner-env.ts
34823
- import { delimiter as delimiter2, isAbsolute as isAbsolute12 } from "node:path";
35146
+ import { delimiter as delimiter2, isAbsolute as isAbsolute13 } from "node:path";
34824
35147
  var PROVIDER_AUTHORITY_PREFIXES = ["GH_", "GITHUB_", "GIT_", "SSH_"];
34825
35148
  var HOST_AUTHORITY_PREFIXES = [
34826
35149
  "ZIXT_",
@@ -34879,7 +35202,7 @@ function inheritedValue(env, name) {
34879
35202
  }
34880
35203
  function sanitizeInheritedSearchPath(path) {
34881
35204
  if (!path) return "";
34882
- return path.split(delimiter2).filter((entry) => entry !== "" && isAbsolute12(entry)).join(delimiter2);
35205
+ return path.split(delimiter2).filter((entry) => entry !== "" && isAbsolute13(entry)).join(delimiter2);
34883
35206
  }
34884
35207
  function buildRunnerEnv(input) {
34885
35208
  const env = {};
@@ -34960,9 +35283,9 @@ function buildRunnerEnv(input) {
34960
35283
  // src/runners/github-shell-auth.ts
34961
35284
  import { execFile } from "node:child_process";
34962
35285
  import { randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
34963
- import { chmod as chmod6, lstat as lstat10, mkdir as mkdir9, realpath as realpath7, writeFile as writeFile5 } from "node:fs/promises";
35286
+ import { chmod as chmod6, lstat as lstat10, mkdir as mkdir10, realpath as realpath7, writeFile as writeFile6 } from "node:fs/promises";
34964
35287
  import { createServer as createServer3 } from "node:http";
34965
- import { isAbsolute as isAbsolute13, join as join13, relative as relative8 } from "node:path";
35288
+ import { isAbsolute as isAbsolute14, join as join14, relative as relative8 } from "node:path";
34966
35289
  var MAX_REQUEST_BYTES2 = 16 * 1024;
34967
35290
  var DIRECTORY_MODE4 = 448;
34968
35291
  var PRIVATE_FILE_MODE = 384;
@@ -35168,7 +35491,7 @@ function parseGhInvocation(body) {
35168
35491
  }
35169
35492
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
35170
35493
  const { args, cwd } = value;
35171
- if (!Array.isArray(args) || args.length > 256 || args.some((argument) => typeof argument !== "string" || argument.length > 4096) || typeof cwd !== "string" || cwd.length === 0 || cwd.length > 4096 || !isAbsolute13(cwd)) {
35494
+ if (!Array.isArray(args) || args.length > 256 || args.some((argument) => typeof argument !== "string" || argument.length > 4096) || typeof cwd !== "string" || cwd.length === 0 || cwd.length > 4096 || !isAbsolute14(cwd)) {
35172
35495
  return null;
35173
35496
  }
35174
35497
  return { args, cwd };
@@ -35327,7 +35650,7 @@ function activationCredential(grant, now = Date.now()) {
35327
35650
  }
35328
35651
  function assertChildPath2(parent, child) {
35329
35652
  const path = relative8(parent, child);
35330
- if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute13(path)) {
35653
+ if (!path || path === ".." || path.startsWith("../") || path.startsWith("..\\") || isAbsolute14(path)) {
35331
35654
  throw new Error("GitHub shell helper path escaped its private run directory");
35332
35655
  }
35333
35656
  }
@@ -35338,7 +35661,7 @@ function quoteForPosixShell(value) {
35338
35661
  return quoteForGitShell2(value);
35339
35662
  }
35340
35663
  async function writePrivate(path, content, executable = false) {
35341
- await writeFile5(path, content, {
35664
+ await writeFile6(path, content, {
35342
35665
  flag: "wx",
35343
35666
  mode: executable ? EXECUTABLE_FILE_MODE : PRIVATE_FILE_MODE
35344
35667
  });
@@ -35350,7 +35673,7 @@ async function prepareHelpers(input) {
35350
35673
  throw new Error("GitHub shell authentication requires a private real run directory");
35351
35674
  }
35352
35675
  const runRoot = await realpath7(input.runRoot);
35353
- const helperPath = join13(runRoot, "github-shell-git-credential.cjs");
35676
+ const helperPath = join14(runRoot, "github-shell-git-credential.cjs");
35354
35677
  assertChildPath2(runRoot, helperPath);
35355
35678
  await writePrivate(helperPath, GIT_HELPER_SOURCE);
35356
35679
  if (!input.ghExecutablePath) {
@@ -35361,14 +35684,14 @@ async function prepareHelpers(input) {
35361
35684
  wrapperSourcePath: null
35362
35685
  };
35363
35686
  }
35364
- const shellToolsDirectory = join13(runRoot, "shell-tools");
35687
+ const shellToolsDirectory = join14(runRoot, "shell-tools");
35365
35688
  assertChildPath2(runRoot, shellToolsDirectory);
35366
- await mkdir9(shellToolsDirectory, { mode: DIRECTORY_MODE4 });
35689
+ await mkdir10(shellToolsDirectory, { mode: DIRECTORY_MODE4 });
35367
35690
  await chmod6(shellToolsDirectory, DIRECTORY_MODE4);
35368
- const wrapperSourcePath = join13(runRoot, "github-shell-gh-wrapper.cjs");
35691
+ const wrapperSourcePath = join14(runRoot, "github-shell-gh-wrapper.cjs");
35369
35692
  assertChildPath2(runRoot, wrapperSourcePath);
35370
35693
  await writePrivate(wrapperSourcePath, GH_WRAPPER_SOURCE);
35371
- const wrapperPath = join13(shellToolsDirectory, process.platform === "win32" ? "gh.cmd" : "gh");
35694
+ const wrapperPath = join14(shellToolsDirectory, process.platform === "win32" ? "gh.cmd" : "gh");
35372
35695
  assertChildPath2(runRoot, wrapperPath);
35373
35696
  const launcher = process.platform === "win32" ? `@"${process.execPath.replaceAll('"', '""')}" "${wrapperSourcePath.replaceAll('"', '""')}" %*\r
35374
35697
  ` : `#!/bin/sh
@@ -36162,7 +36485,7 @@ async function settlesWithin(promise2, timeoutMs) {
36162
36485
  }
36163
36486
  }
36164
36487
  function defaultRunnerWorkspaceRoot() {
36165
- return join14(homedir5(), ".zixt", "workspaces");
36488
+ return join15(homedir6(), ".zixt", "workspaces");
36166
36489
  }
36167
36490
  function defaultRunnerArtifactRoot() {
36168
36491
  return defaultRunArtifactRoot();
@@ -36211,7 +36534,7 @@ function createCliRunner(adapter, opts = {}) {
36211
36534
  const prefixArgs = opts.commandPrefixArgs ?? [];
36212
36535
  const maxWallTimeMs = opts.maxWallTimeMs;
36213
36536
  const workspaceRoot = opts.workspaceRoot ?? defaultRunnerWorkspaceRoot();
36214
- const artifactRoot = opts.artifactRoot ?? (opts.workspaceRoot === void 0 ? defaultRunnerArtifactRoot() : join14(dirname8(workspaceRoot), "run-artifacts"));
36537
+ const artifactRoot = opts.artifactRoot ?? (opts.workspaceRoot === void 0 ? defaultRunnerArtifactRoot() : join15(dirname8(workspaceRoot), "run-artifacts"));
36215
36538
  const runRegistryRoot2 = opts.runRegistryRoot ?? defaultRunRegistryRoot();
36216
36539
  const createArtifacts = opts.createArtifacts ?? createRunArtifacts;
36217
36540
  const toolPackRegistry2 = opts.toolPackRegistry ?? createDefaultToolPackRegistry();
@@ -36229,7 +36552,7 @@ function createCliRunner(adapter, opts = {}) {
36229
36552
  };
36230
36553
  const askUserServer = createAskUserServer();
36231
36554
  const windowsRoot = process.env.SystemRoot ?? process.env.WINDIR;
36232
- const windowsComspecCandidate = process.platform === "win32" && windowsRoot ? join14(windowsRoot, "System32", "cmd.exe") : void 0;
36555
+ const windowsComspecCandidate = process.platform === "win32" && windowsRoot ? join15(windowsRoot, "System32", "cmd.exe") : void 0;
36233
36556
  let safetyFailure;
36234
36557
  return async (task) => {
36235
36558
  if (safetyFailure) {
@@ -36269,8 +36592,8 @@ function createCliRunner(adapter, opts = {}) {
36269
36592
  usage: { inputTokens: 0, outputTokens: 0 }
36270
36593
  };
36271
36594
  }
36272
- const taskRoot = join14(workspaceRoot, task.agentId);
36273
- await mkdir10(taskRoot, { recursive: true });
36595
+ const taskRoot = join15(workspaceRoot, task.agentId);
36596
+ await mkdir11(taskRoot, { recursive: true });
36274
36597
  if (task.cancelledNow()) return cancelledBeforeRun();
36275
36598
  const configuredWorkspace = task.spec.workspace;
36276
36599
  let cwd = taskRoot;
@@ -36316,7 +36639,7 @@ function createCliRunner(adapter, opts = {}) {
36316
36639
  summaryEvidence: "host_observed"
36317
36640
  };
36318
36641
  }
36319
- const runToken = randomUUID10();
36642
+ const runToken = randomUUID11();
36320
36643
  const artifacts = await createArtifacts({
36321
36644
  root: artifactRoot,
36322
36645
  agentId: task.agentId,
@@ -36577,7 +36900,7 @@ ${attachmentSection}` : prompt;
36577
36900
  let changed = false;
36578
36901
  for (const path of paths) {
36579
36902
  if (!path || path.length > 4096) continue;
36580
- const absolutePath = isAbsolute14(path) ? path : resolve10(cwd, path);
36903
+ const absolutePath = isAbsolute15(path) ? path : resolve10(cwd, path);
36581
36904
  const directory = dirname8(absolutePath);
36582
36905
  observedWorkingDirectories.delete(directory);
36583
36906
  observedWorkingDirectories.add(directory);
@@ -36658,8 +36981,8 @@ ${attachmentSection}` : prompt;
36658
36981
  }
36659
36982
  comspec = resolvedWindowsComspec;
36660
36983
  }
36661
- const exitMarker = `__ZIXT_RUNNER_EXIT_${randomUUID10()}__`;
36662
- const guardianNonce = randomUUID10();
36984
+ const exitMarker = `__ZIXT_RUNNER_EXIT_${randomUUID11()}__`;
36985
+ const guardianNonce = randomUUID11();
36663
36986
  return runCliProcess({
36664
36987
  command: resolvedCommand,
36665
36988
  args,
@@ -37012,7 +37335,7 @@ function runCliProcess(options) {
37012
37335
  }
37013
37336
  return new Promise((resolve18) => {
37014
37337
  const platform = options.platform ?? process.platform;
37015
- const containmentGateNonce = options.guardian && platform === "win32" ? randomUUID10() : void 0;
37338
+ const containmentGateNonce = options.guardian && platform === "win32" ? randomUUID11() : void 0;
37016
37339
  const child = options.guardian ? spawn8(
37017
37340
  options.guardian.nodeCommand,
37018
37341
  [
@@ -37301,17 +37624,17 @@ function runCliProcess(options) {
37301
37624
  }
37302
37625
 
37303
37626
  // src/runners/claude-code.ts
37304
- import { randomUUID as randomUUID11 } from "node:crypto";
37627
+ import { randomUUID as randomUUID12 } from "node:crypto";
37305
37628
 
37306
37629
  // src/runners/runtime-observation.ts
37307
- import { open as open6, readdir as readdir4, realpath as realpath9 } from "node:fs/promises";
37308
- import { homedir as homedir6 } from "node:os";
37309
- import { join as join15 } from "node:path";
37630
+ import { open as open6, readdir as readdir5, realpath as realpath9 } from "node:fs/promises";
37631
+ import { homedir as homedir7 } from "node:os";
37632
+ import { join as join16 } from "node:path";
37310
37633
  var READ_WINDOW_BYTES = 1024 * 1024;
37311
37634
  var CATALOG_TIMEOUT_MS = 15e3;
37312
37635
  var CATALOG_OUTPUT_LIMIT_BYTES = 4 * 1024 * 1024;
37313
37636
  function homeFrom(env) {
37314
- return env["HOME"] || env["USERPROFILE"] || homedir6();
37637
+ return env["HOME"] || env["USERPROFILE"] || homedir7();
37315
37638
  }
37316
37639
  async function readHead(path) {
37317
37640
  let handle;
@@ -37366,9 +37689,9 @@ function displayValue(value, maxLength) {
37366
37689
  return trimmed;
37367
37690
  }
37368
37691
  function claudeTranscriptPath(input) {
37369
- const configDir = input.env["CLAUDE_CONFIG_DIR"] || join15(homeFrom(input.env), ".claude");
37692
+ const configDir = input.env["CLAUDE_CONFIG_DIR"] || join16(homeFrom(input.env), ".claude");
37370
37693
  const slug = input.resolvedCwd.replace(/[^a-zA-Z0-9]/g, "-");
37371
- return join15(configDir, "projects", slug, `${input.sessionId}.jsonl`);
37694
+ return join16(configDir, "projects", slug, `${input.sessionId}.jsonl`);
37372
37695
  }
37373
37696
  async function readClaudeSessionEffort(input) {
37374
37697
  const resolvedCwd = await realpath9(input.cwd).catch(() => input.cwd);
@@ -37383,19 +37706,19 @@ async function readClaudeSessionEffort(input) {
37383
37706
  return null;
37384
37707
  }
37385
37708
  async function newestDirectories(root, limit) {
37386
- const entries = await readdir4(root, { withFileTypes: true }).catch(() => []);
37387
- return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort((left, right) => right.localeCompare(left)).slice(0, limit).map((name) => join15(root, name));
37709
+ const entries = await readdir5(root, { withFileTypes: true }).catch(() => []);
37710
+ return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort((left, right) => right.localeCompare(left)).slice(0, limit).map((name) => join16(root, name));
37388
37711
  }
37389
37712
  async function findCodexRolloutPath(input) {
37390
- const codexHome = input.env["CODEX_HOME"] || join15(homeFrom(input.env), ".codex");
37391
- const sessions = join15(codexHome, "sessions");
37713
+ const codexHome = input.env["CODEX_HOME"] || join16(homeFrom(input.env), ".codex");
37714
+ const sessions = join16(codexHome, "sessions");
37392
37715
  const suffix = `-${input.threadId}.jsonl`;
37393
37716
  for (const year of await newestDirectories(sessions, 2)) {
37394
37717
  for (const month of await newestDirectories(year, 2)) {
37395
37718
  for (const day of await newestDirectories(month, 3)) {
37396
- const files = await readdir4(day).catch(() => []);
37719
+ const files = await readdir5(day).catch(() => []);
37397
37720
  const match = files.find((name) => name.endsWith(suffix));
37398
- if (match) return join15(day, match);
37721
+ if (match) return join16(day, match);
37399
37722
  }
37400
37723
  }
37401
37724
  }
@@ -37493,7 +37816,7 @@ var claudeCodeAdapter = {
37493
37816
  input.gitDetected,
37494
37817
  liveInput
37495
37818
  );
37496
- const sessionId = input.task.spec.sessionKey ?? randomUUID11();
37819
+ const sessionId = input.task.spec.sessionKey ?? randomUUID12();
37497
37820
  const observeRuntime = createRuntimeReporter(input, sessionId);
37498
37821
  return {
37499
37822
  argsFor: (mode) => [
@@ -37612,7 +37935,7 @@ function createClaudeLiveParser(onStream, onSessionModel) {
37612
37935
  ...parser,
37613
37936
  async start(writer, prompt) {
37614
37937
  write = writer;
37615
- await writer(input(randomUUID11(), prompt));
37938
+ await writer(input(randomUUID12(), prompt));
37616
37939
  },
37617
37940
  async steer(followUp) {
37618
37941
  if (!write) return false;
@@ -37779,22 +38102,22 @@ function improveErrorMessage(error52) {
37779
38102
  }
37780
38103
 
37781
38104
  // src/runners/codex.ts
37782
- import { mkdir as mkdir11, readFile as readFile9, writeFile as writeFile6 } from "node:fs/promises";
37783
- import { randomUUID as randomUUID12 } from "node:crypto";
37784
- import { homedir as homedir7 } from "node:os";
37785
- import { join as join16 } from "node:path";
38105
+ import { mkdir as mkdir12, readFile as readFile10, writeFile as writeFile7 } from "node:fs/promises";
38106
+ import { randomUUID as randomUUID13 } from "node:crypto";
38107
+ import { homedir as homedir8 } from "node:os";
38108
+ import { join as join17 } from "node:path";
37786
38109
  var CODEX_NOT_FOUND_MESSAGE = "The `codex` CLI was not found on this Machine. Install it (npm install -g @openai/codex) and sign in with `codex login`, or switch the agent to API-key auth.";
37787
38110
  function defaultCodexThreadIndexRoot() {
37788
- return join16(homedir7(), ".zixt", "codex-threads");
38111
+ return join17(homedir8(), ".zixt", "codex-threads");
37789
38112
  }
37790
38113
  var SAFE_SEGMENT3 = /^[A-Za-z0-9_-]{1,200}$/;
37791
38114
  function threadIndexPath(root, agentId, sessionKey) {
37792
38115
  if (!SAFE_SEGMENT3.test(agentId) || !SAFE_SEGMENT3.test(sessionKey)) return null;
37793
- return join16(root, agentId, `${sessionKey}.json`);
38116
+ return join17(root, agentId, `${sessionKey}.json`);
37794
38117
  }
37795
38118
  async function readThreadId(path) {
37796
38119
  try {
37797
- const parsed = JSON.parse(await readFile9(path, "utf8"));
38120
+ const parsed = JSON.parse(await readFile10(path, "utf8"));
37798
38121
  return typeof parsed.threadId === "string" && /^[A-Za-z0-9-]{1,120}$/.test(parsed.threadId) ? parsed.threadId : null;
37799
38122
  } catch {
37800
38123
  return null;
@@ -37885,7 +38208,7 @@ ${value}` : value;
37885
38208
  const recordedThreadId = indexPath ? await readThreadId(indexPath) : null;
37886
38209
  const rememberThread = (threadId) => {
37887
38210
  if (!indexPath) return;
37888
- void mkdir11(join16(threadIndexRoot, task.agentId), { recursive: true }).then(() => writeFile6(indexPath, JSON.stringify({ threadId }), "utf8")).catch(() => {
38211
+ void mkdir12(join17(threadIndexRoot, task.agentId), { recursive: true }).then(() => writeFile7(indexPath, JSON.stringify({ threadId }), "utf8")).catch(() => {
37889
38212
  });
37890
38213
  };
37891
38214
  const observeRuntime = (threadId) => {
@@ -37989,7 +38312,7 @@ function createCodexAppServerParser(onStream, options) {
37989
38312
  params: {
37990
38313
  threadId,
37991
38314
  input: [{ type: "text", text: prompt }],
37992
- clientUserMessageId: randomUUID12(),
38315
+ clientUserMessageId: randomUUID13(),
37993
38316
  ...options.model ? { model: options.model } : {},
37994
38317
  ...options.effort ? { effort: options.effort } : {}
37995
38318
  }
@@ -38350,7 +38673,7 @@ function improveCodexErrorMessage(error52) {
38350
38673
  // src/runners/git-preflight.ts
38351
38674
  import { spawn as spawn9 } from "node:child_process";
38352
38675
  import { realpath as realpath10 } from "node:fs/promises";
38353
- import { isAbsolute as isAbsolute15, resolve as resolve11 } from "node:path";
38676
+ import { isAbsolute as isAbsolute16, resolve as resolve11 } from "node:path";
38354
38677
  var OUTPUT_LIMIT = 8192;
38355
38678
  var DEFAULT_TIMEOUT_MS4 = 1e4;
38356
38679
  var VERSION_PATTERN = /^git version [^\r\n]{1,108}$/;
@@ -38366,7 +38689,7 @@ function unavailable(error52, checkedAt, executablePath = null) {
38366
38689
  async function preflightGit(options = {}) {
38367
38690
  const checkedAt = (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString();
38368
38691
  const configured = options.command;
38369
- if (configured !== void 0 && !isAbsolute15(configured)) {
38692
+ if (configured !== void 0 && !isAbsolute16(configured)) {
38370
38693
  return unavailable("configured git command must be an absolute file", checkedAt);
38371
38694
  }
38372
38695
  const trustedCwd = await realpath10(resolve11(options.trustedCwd ?? process.cwd())).catch(() => null);
@@ -38621,9 +38944,9 @@ function run2(command, args) {
38621
38944
  // src/linux-service.ts
38622
38945
  import { spawn as spawn10 } from "node:child_process";
38623
38946
  import { constants as constants2 } from "node:fs";
38624
- import { access as access4, chmod as chmod7, mkdir as mkdir12, open as open7, rename as rename6, rm as rm8 } from "node:fs/promises";
38625
- import { homedir as homedir8, userInfo } from "node:os";
38626
- import { basename as basename4, dirname as dirname9, join as join17, relative as relative9, resolve as resolve12, sep as sep5 } from "node:path";
38947
+ import { access as access4, chmod as chmod7, mkdir as mkdir13, open as open7, rename as rename6, rm as rm9 } from "node:fs/promises";
38948
+ import { homedir as homedir9, userInfo } from "node:os";
38949
+ import { basename as basename4, dirname as dirname9, join as join18, relative as relative9, resolve as resolve12, sep as sep5 } from "node:path";
38627
38950
  var SERVICE_NAME = "zixt-host.service";
38628
38951
  var SYSTEM_SERVICE_COMMAND_TIMEOUT_MS = 7e4;
38629
38952
  var SERVICE_STABILITY_DELAY_MS = 2e3;
@@ -38724,7 +39047,7 @@ async function defaultSyncDirectory(path) {
38724
39047
  }
38725
39048
  }
38726
39049
  async function ensureDirectory(path, mode, syncDirectory8) {
38727
- const firstCreated = await mkdir12(path, { recursive: true, mode });
39050
+ const firstCreated = await mkdir13(path, { recursive: true, mode });
38728
39051
  if (!firstCreated) return;
38729
39052
  const first = resolve12(firstCreated);
38730
39053
  const target = resolve12(path);
@@ -38733,13 +39056,13 @@ async function ensureDirectory(path, mode, syncDirectory8) {
38733
39056
  const descendants = relative9(first, target);
38734
39057
  for (const part of descendants ? descendants.split(sep5) : []) {
38735
39058
  await syncDirectory8(current);
38736
- current = join17(current, part);
39059
+ current = join18(current, part);
38737
39060
  }
38738
39061
  }
38739
39062
  async function replacePrivateFile(path, contents, mode, syncDirectory8) {
38740
39063
  const parent = dirname9(path);
38741
39064
  await ensureDirectory(parent, 448, syncDirectory8);
38742
- const temporary = join17(parent, `.${basename4(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
39065
+ const temporary = join18(parent, `.${basename4(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
38743
39066
  const handle = await open7(temporary, "wx", mode);
38744
39067
  try {
38745
39068
  await handle.writeFile(contents, "utf8");
@@ -38750,7 +39073,7 @@ async function replacePrivateFile(path, contents, mode, syncDirectory8) {
38750
39073
  await syncDirectory8(parent);
38751
39074
  } catch (error52) {
38752
39075
  await handle.close().catch(() => void 0);
38753
- await rm8(temporary, { force: true }).catch(() => void 0);
39076
+ await rm9(temporary, { force: true }).catch(() => void 0);
38754
39077
  throw error52;
38755
39078
  }
38756
39079
  }
@@ -38783,7 +39106,7 @@ async function installLinuxService(options) {
38783
39106
  throw new Error("Linux automatic startup is available only on Linux.");
38784
39107
  }
38785
39108
  const env = options.env ?? process.env;
38786
- const home = options.home ?? homedir8();
39109
+ const home = options.home ?? homedir9();
38787
39110
  const username = oneLine(options.username ?? userInfo().username, "user name");
38788
39111
  const token2 = oneLine(options.token, "pairing code");
38789
39112
  const path = oneLine(
@@ -38791,11 +39114,11 @@ async function installLinuxService(options) {
38791
39114
  "command search path"
38792
39115
  );
38793
39116
  const cloudUrl = options.cloudUrl ? oneLine(options.cloudUrl, "Zixt Cloud address") : void 0;
38794
- const xdgConfigHome = env.XDG_CONFIG_HOME ? oneLine(env.XDG_CONFIG_HOME, "Linux configuration path") : join17(home, ".config");
38795
- const configRoot = options.serviceConfigRoot ?? join17(xdgConfigHome, "zixt");
38796
- const unitRoot = options.userUnitRoot ?? join17(xdgConfigHome, "systemd", "user");
38797
- const environmentPath = join17(configRoot, "host.env");
38798
- const unitPath = join17(unitRoot, SERVICE_NAME);
39117
+ const xdgConfigHome = env.XDG_CONFIG_HOME ? oneLine(env.XDG_CONFIG_HOME, "Linux configuration path") : join18(home, ".config");
39118
+ const configRoot = options.serviceConfigRoot ?? join18(xdgConfigHome, "zixt");
39119
+ const unitRoot = options.userUnitRoot ?? join18(xdgConfigHome, "systemd", "user");
39120
+ const environmentPath = join18(configRoot, "host.env");
39121
+ const unitPath = join18(unitRoot, SERVICE_NAME);
38799
39122
  const installVersion = options.installVersion ?? installRelease;
38800
39123
  const activateVersion = options.activateVersion ?? (options.installVersion ? async (entry) => entry : activateInstalledRelease);
38801
39124
  const resolveCommand = options.resolveCommand ?? defaultResolveCommand;
@@ -38914,9 +39237,9 @@ async function installLinuxService(options) {
38914
39237
  // src/macos-service.ts
38915
39238
  import { spawn as spawn11 } from "node:child_process";
38916
39239
  import { constants as constants3 } from "node:fs";
38917
- import { access as access5, chmod as chmod8, mkdir as mkdir13, open as open8, rename as rename7, rm as rm9 } from "node:fs/promises";
38918
- import { homedir as homedir9, userInfo as userInfo2 } from "node:os";
38919
- import { basename as basename5, dirname as dirname10, join as join18, relative as relative10, resolve as resolve13, sep as sep6 } from "node:path";
39240
+ import { access as access5, chmod as chmod8, mkdir as mkdir14, open as open8, rename as rename7, rm as rm10 } from "node:fs/promises";
39241
+ import { homedir as homedir10, userInfo as userInfo2 } from "node:os";
39242
+ import { basename as basename5, dirname as dirname10, join as join19, relative as relative10, resolve as resolve13, sep as sep6 } from "node:path";
38920
39243
  var LAUNCH_AGENT_LABEL = "ai.zixt.host";
38921
39244
  var SERVICE_STABILITY_DELAY_MS2 = 2e3;
38922
39245
  var COMMAND_TIMEOUT_MS2 = 7e4;
@@ -38940,7 +39263,7 @@ async function syncDirectory4(path) {
38940
39263
  }
38941
39264
  }
38942
39265
  async function ensureDirectory2(path, sync) {
38943
- const firstCreated = await mkdir13(path, { recursive: true, mode: 448 });
39266
+ const firstCreated = await mkdir14(path, { recursive: true, mode: 448 });
38944
39267
  if (!firstCreated) return;
38945
39268
  const first = resolve13(firstCreated);
38946
39269
  const target = resolve13(path);
@@ -38948,13 +39271,13 @@ async function ensureDirectory2(path, sync) {
38948
39271
  let current = first;
38949
39272
  for (const part of relative10(first, target).split(sep6).filter(Boolean)) {
38950
39273
  await sync(current);
38951
- current = join18(current, part);
39274
+ current = join19(current, part);
38952
39275
  }
38953
39276
  }
38954
39277
  async function replacePrivateFile2(path, contents, mode, sync) {
38955
39278
  const parent = dirname10(path);
38956
39279
  await ensureDirectory2(parent, sync);
38957
- const temporary = join18(parent, `.${basename5(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
39280
+ const temporary = join19(parent, `.${basename5(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
38958
39281
  const handle = await open8(temporary, "wx", mode);
38959
39282
  try {
38960
39283
  await handle.writeFile(contents, "utf8");
@@ -38965,7 +39288,7 @@ async function replacePrivateFile2(path, contents, mode, sync) {
38965
39288
  await sync(parent);
38966
39289
  } catch (error52) {
38967
39290
  await handle.close().catch(() => void 0);
38968
- await rm9(temporary, { force: true }).catch(() => void 0);
39291
+ await rm10(temporary, { force: true }).catch(() => void 0);
38969
39292
  throw error52;
38970
39293
  }
38971
39294
  }
@@ -39042,7 +39365,7 @@ async function installMacosService(options) {
39042
39365
  throw new Error("macOS automatic startup is available only on macOS.");
39043
39366
  }
39044
39367
  const env = options.env ?? process.env;
39045
- const home = options.home ?? homedir9();
39368
+ const home = options.home ?? homedir10();
39046
39369
  const uid = options.uid ?? userInfo2().uid;
39047
39370
  if (!Number.isSafeInteger(uid) || uid < 0) throw new Error("macOS user id is invalid.");
39048
39371
  const token2 = oneLine2(options.token, "pairing code");
@@ -39051,14 +39374,14 @@ async function installMacosService(options) {
39051
39374
  options.path ?? env.PATH ?? "/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin",
39052
39375
  "command search path"
39053
39376
  );
39054
- const configRoot = options.configRoot ?? join18(home, "Library", "Application Support", "Zixt");
39055
- const launchAgentsRoot = options.launchAgentsRoot ?? join18(home, "Library", "LaunchAgents");
39056
- const logRoot = options.logRoot ?? join18(home, "Library", "Logs", "Zixt");
39057
- const configPath = join18(configRoot, "host.env");
39058
- const launcherPath = join18(configRoot, "host-launcher.sh");
39059
- const plistPath = join18(launchAgentsRoot, `${LAUNCH_AGENT_LABEL}.plist`);
39060
- const stdoutPath = join18(logRoot, "host.log");
39061
- const stderrPath = join18(logRoot, "host-error.log");
39377
+ const configRoot = options.configRoot ?? join19(home, "Library", "Application Support", "Zixt");
39378
+ const launchAgentsRoot = options.launchAgentsRoot ?? join19(home, "Library", "LaunchAgents");
39379
+ const logRoot = options.logRoot ?? join19(home, "Library", "Logs", "Zixt");
39380
+ const configPath = join19(configRoot, "host.env");
39381
+ const launcherPath = join19(configRoot, "host-launcher.sh");
39382
+ const plistPath = join19(launchAgentsRoot, `${LAUNCH_AGENT_LABEL}.plist`);
39383
+ const stdoutPath = join19(logRoot, "host.log");
39384
+ const stderrPath = join19(logRoot, "host-error.log");
39062
39385
  const installVersion = options.installVersion ?? installRelease;
39063
39386
  const activateVersion = options.activateVersion ?? (options.installVersion ? async (entry) => entry : (entry) => activateInstalledRelease(entry));
39064
39387
  const resolveCommand = options.resolveCommand ?? (async () => defaultResolveCommand2());
@@ -39145,9 +39468,9 @@ async function installMacosService(options) {
39145
39468
  // src/windows-service.ts
39146
39469
  import { spawn as spawn12 } from "node:child_process";
39147
39470
  import { constants as constants4 } from "node:fs";
39148
- import { access as access6, mkdir as mkdir14, open as open9, readFile as readFile10, rename as rename8, rm as rm10 } from "node:fs/promises";
39149
- import { homedir as homedir10 } from "node:os";
39150
- import { basename as basename6, dirname as dirname11, isAbsolute as isAbsolute16, join as join19, relative as relative11, resolve as resolve14, sep as sep7 } from "node:path";
39471
+ import { access as access6, mkdir as mkdir15, open as open9, readFile as readFile11, rename as rename8, rm as rm11 } from "node:fs/promises";
39472
+ import { homedir as homedir11 } from "node:os";
39473
+ import { basename as basename6, dirname as dirname11, isAbsolute as isAbsolute17, join as join20, relative as relative11, resolve as resolve14, sep as sep7 } from "node:path";
39151
39474
  var TASK_NAME = "Zixt Host";
39152
39475
  var COMMAND_TIMEOUT_MS3 = 7e4;
39153
39476
  var SERVICE_STABILITY_DELAY_MS3 = 2e3;
@@ -39173,7 +39496,7 @@ async function syncDirectory5(path) {
39173
39496
  }
39174
39497
  }
39175
39498
  async function ensureDirectory3(path, sync) {
39176
- const firstCreated = await mkdir14(path, { recursive: true, mode: 448 });
39499
+ const firstCreated = await mkdir15(path, { recursive: true, mode: 448 });
39177
39500
  if (!firstCreated) return;
39178
39501
  const first = resolve14(firstCreated);
39179
39502
  const target = resolve14(path);
@@ -39181,13 +39504,13 @@ async function ensureDirectory3(path, sync) {
39181
39504
  let current = first;
39182
39505
  for (const part of relative11(first, target).split(sep7).filter(Boolean)) {
39183
39506
  await sync(current);
39184
- current = join19(current, part);
39507
+ current = join20(current, part);
39185
39508
  }
39186
39509
  }
39187
39510
  async function replacePrivateFile3(path, contents, sync) {
39188
39511
  const parent = dirname11(path);
39189
39512
  await ensureDirectory3(parent, sync);
39190
- const temporary = join19(parent, `.${basename6(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
39513
+ const temporary = join20(parent, `.${basename6(path)}.${process.pid}.${crypto.randomUUID()}.tmp`);
39191
39514
  const handle = await open9(temporary, "wx", 384);
39192
39515
  try {
39193
39516
  await handle.writeFile(contents, "utf8");
@@ -39197,7 +39520,7 @@ async function replacePrivateFile3(path, contents, sync) {
39197
39520
  await sync(parent);
39198
39521
  } catch (error52) {
39199
39522
  await handle.close().catch(() => void 0);
39200
- await rm10(temporary, { force: true }).catch(() => void 0);
39523
+ await rm11(temporary, { force: true }).catch(() => void 0);
39201
39524
  throw error52;
39202
39525
  }
39203
39526
  }
@@ -39241,8 +39564,8 @@ async function runChild(command, args, env, input) {
39241
39564
  }
39242
39565
  async function defaultResolveCommand3(name, env) {
39243
39566
  const root = env.SYSTEMROOT ?? env.WINDIR;
39244
- if (!root || !isAbsolute16(root)) return null;
39245
- const candidate = name === "powershell" ? join19(root, "System32", "WindowsPowerShell", "v1.0", "powershell.exe") : join19(root, "System32", `${name}.exe`);
39567
+ if (!root || !isAbsolute17(root)) return null;
39568
+ const candidate = name === "powershell" ? join20(root, "System32", "WindowsPowerShell", "v1.0", "powershell.exe") : join20(root, "System32", `${name}.exe`);
39246
39569
  return access6(candidate, constants4.X_OK).then(
39247
39570
  () => candidate,
39248
39571
  () => null
@@ -39330,7 +39653,7 @@ exit $code
39330
39653
  }
39331
39654
  async function defaultObserveStatus(path, generation) {
39332
39655
  try {
39333
- const text = (await readFile10(path, "utf8")).replace(/^\uFEFF/, "");
39656
+ const text = (await readFile11(path, "utf8")).replace(/^\uFEFF/, "");
39334
39657
  const value = JSON.parse(text);
39335
39658
  if (value.schema !== 1 || value.generation !== generation || typeof value.pid !== "number" || !Number.isSafeInteger(value.pid) || value.pid <= 0) {
39336
39659
  return null;
@@ -39371,19 +39694,19 @@ async function installWindowsService(options) {
39371
39694
  throw new Error("Windows automatic startup is available only on Windows.");
39372
39695
  }
39373
39696
  const env = options.env ?? process.env;
39374
- const home = options.home ?? homedir10();
39697
+ const home = options.home ?? homedir11();
39375
39698
  const localAppData = options.localAppData ?? env.LOCALAPPDATA;
39376
- if (!localAppData || !isAbsolute16(localAppData)) {
39699
+ if (!localAppData || !isAbsolute17(localAppData)) {
39377
39700
  throw new Error("Windows local application data path is unavailable.");
39378
39701
  }
39379
39702
  const token2 = oneLine3(options.token, "pairing code");
39380
39703
  const cloudUrl = options.cloudUrl ? oneLine3(options.cloudUrl, "Zixt Cloud address") : void 0;
39381
39704
  const path = oneLine3(options.path ?? env.PATH ?? "", "command search path");
39382
- const configRoot = options.configRoot ?? join19(localAppData, "Zixt", "Host");
39383
- const configPath = join19(configRoot, "host.json");
39384
- const launcherPath = join19(configRoot, "host-launcher.ps1");
39385
- const taskXmlPath = join19(configRoot, "host-task.xml");
39386
- const statusPath = join19(configRoot, "host-status.json");
39705
+ const configRoot = options.configRoot ?? join20(localAppData, "Zixt", "Host");
39706
+ const configPath = join20(configRoot, "host.json");
39707
+ const launcherPath = join20(configRoot, "host-launcher.ps1");
39708
+ const taskXmlPath = join20(configRoot, "host-task.xml");
39709
+ const statusPath = join20(configRoot, "host-status.json");
39387
39710
  const installVersion = options.installVersion ?? installRelease;
39388
39711
  const activateVersion = options.activateVersion ?? (options.installVersion ? async (entry) => entry : (entry) => activateInstalledRelease(entry));
39389
39712
  const resolveCommand = options.resolveCommand ?? ((name) => defaultResolveCommand3(name, env));
@@ -39432,7 +39755,7 @@ async function installWindowsService(options) {
39432
39755
  );
39433
39756
  await replacePrivateFile3(launcherPath, launcherSource2(configPath, statusPath), sync);
39434
39757
  await replacePrivateFile3(taskXmlPath, taskXml({ sid, powershell, launcherPath, home }), sync);
39435
- await rm10(statusPath, { force: true });
39758
+ await rm11(statusPath, { force: true });
39436
39759
  const acl = await run3(icacls, [
39437
39760
  configRoot,
39438
39761
  "/inheritance:r",
@@ -39484,23 +39807,23 @@ async function installSystemService(options) {
39484
39807
  }
39485
39808
 
39486
39809
  // src/terminal-outcomes.ts
39487
- import { chmod as chmod9, lstat as lstat12, mkdir as mkdir15, open as open10, readdir as readdir5, readFile as readFile11, rename as rename9, rm as rm11 } from "node:fs/promises";
39488
- import { homedir as homedir11 } from "node:os";
39489
- import { dirname as dirname12, join as join20, relative as relative12, resolve as resolve15, sep as sep8 } from "node:path";
39810
+ import { chmod as chmod9, lstat as lstat12, mkdir as mkdir16, open as open10, readdir as readdir6, readFile as readFile12, rename as rename9, rm as rm12 } from "node:fs/promises";
39811
+ import { homedir as homedir12 } from "node:os";
39812
+ import { dirname as dirname12, join as join21, relative as relative12, resolve as resolve15, sep as sep8 } from "node:path";
39490
39813
  var DIRECTORY_MODE5 = 448;
39491
39814
  var FILE_MODE4 = 384;
39492
39815
  var MAX_OUTCOME_BYTES = 4 * 1024 * 1024;
39493
39816
  var HOST_DIRECTORY = /^hst_[0-9a-f]{32}$/;
39494
39817
  var OUTCOME_FILE = /^(tsk_[0-9a-f]{32})\.([1-9][0-9]*)\.json$/;
39495
39818
  function defaultTerminalOutcomeRoot() {
39496
- return join20(homedir11(), ".zixt", "terminal-outcomes");
39819
+ return join21(homedir12(), ".zixt", "terminal-outcomes");
39497
39820
  }
39498
39821
  function hostOutcomeRoot(root, hostId) {
39499
39822
  if (!HOST_DIRECTORY.test(hostId)) throw new Error("terminal outcome Host identity is malformed");
39500
- return join20(root, hostId);
39823
+ return join21(root, hostId);
39501
39824
  }
39502
39825
  function outcomePath(root, hostId, taskId, epoch) {
39503
- return join20(hostOutcomeRoot(root, hostId), `${taskId}.${epoch}.json`);
39826
+ return join21(hostOutcomeRoot(root, hostId), `${taskId}.${epoch}.json`);
39504
39827
  }
39505
39828
  async function syncDirectory6(root) {
39506
39829
  if (process.platform === "win32") return;
@@ -39512,7 +39835,7 @@ async function syncDirectory6(root) {
39512
39835
  }
39513
39836
  }
39514
39837
  async function requirePrivateRoot(root, sync = syncDirectory6) {
39515
- const firstCreated = await mkdir15(root, { recursive: true, mode: DIRECTORY_MODE5 });
39838
+ const firstCreated = await mkdir16(root, { recursive: true, mode: DIRECTORY_MODE5 });
39516
39839
  if (firstCreated) {
39517
39840
  const first = resolve15(firstCreated);
39518
39841
  const target = resolve15(root);
@@ -39520,7 +39843,7 @@ async function requirePrivateRoot(root, sync = syncDirectory6) {
39520
39843
  let current = first;
39521
39844
  for (const part of relative12(first, target).split(sep8).filter(Boolean)) {
39522
39845
  await sync(current);
39523
- current = join20(current, part);
39846
+ current = join21(current, part);
39524
39847
  }
39525
39848
  }
39526
39849
  const stat3 = await lstat12(root);
@@ -39551,7 +39874,7 @@ async function recordTerminalOutcome(hostId, input, root = defaultTerminalOutcom
39551
39874
  const destination = outcomePath(root, hostId, outcome.taskId, outcome.epoch);
39552
39875
  try {
39553
39876
  const existing = parseCommittedOutcome(
39554
- await readFile11(destination, { encoding: "utf8", flag: "r" }),
39877
+ await readFile12(destination, { encoding: "utf8", flag: "r" }),
39555
39878
  outcome.taskId,
39556
39879
  outcome.epoch
39557
39880
  );
@@ -39560,7 +39883,7 @@ async function recordTerminalOutcome(hostId, input, root = defaultTerminalOutcom
39560
39883
  } catch (error52) {
39561
39884
  if (error52.code !== "ENOENT") throw error52;
39562
39885
  }
39563
- const temporary = join20(
39886
+ const temporary = join21(
39564
39887
  scopedRoot,
39565
39888
  `.${outcome.taskId}.${outcome.epoch}.${process.pid}.${Date.now()}.${outcome.resultId}.tmp`
39566
39889
  );
@@ -39577,7 +39900,7 @@ async function recordTerminalOutcome(hostId, input, root = defaultTerminalOutcom
39577
39900
  } finally {
39578
39901
  await handle?.close().catch(() => {
39579
39902
  });
39580
- await rm11(temporary, { force: true }).catch(() => {
39903
+ await rm12(temporary, { force: true }).catch(() => {
39581
39904
  });
39582
39905
  }
39583
39906
  }
@@ -39593,7 +39916,7 @@ async function readTerminalOutcomesStrict(root = defaultTerminalOutcomeRoot()) {
39593
39916
  throw new Error("terminal outcome journal root is not a trusted directory");
39594
39917
  }
39595
39918
  await chmod9(root, DIRECTORY_MODE5);
39596
- const hostEntries = await readdir5(root, { withFileTypes: true });
39919
+ const hostEntries = await readdir6(root, { withFileTypes: true });
39597
39920
  const outcomes = [];
39598
39921
  const resultIds = /* @__PURE__ */ new Set();
39599
39922
  for (const hostEntry of hostEntries) {
@@ -39606,20 +39929,20 @@ async function readTerminalOutcomesStrict(root = defaultTerminalOutcomeRoot()) {
39606
39929
  throw new Error("terminal outcome Host scope is not a trusted directory");
39607
39930
  }
39608
39931
  await chmod9(scopedRoot, DIRECTORY_MODE5);
39609
- const entries = await readdir5(scopedRoot, { withFileTypes: true });
39932
+ const entries = await readdir6(scopedRoot, { withFileTypes: true });
39610
39933
  for (const entry of entries) {
39611
39934
  if (!entry.name.endsWith(".json")) continue;
39612
39935
  const match = OUTCOME_FILE.exec(entry.name);
39613
39936
  if (!match || !entry.isFile() || entry.isSymbolicLink()) {
39614
39937
  throw new Error("committed terminal outcome is not a trusted regular file");
39615
39938
  }
39616
- const path = join20(scopedRoot, entry.name);
39939
+ const path = join21(scopedRoot, entry.name);
39617
39940
  const stat3 = await lstat12(path);
39618
39941
  if (!stat3.isFile() || stat3.isSymbolicLink() || stat3.size > MAX_OUTCOME_BYTES) {
39619
39942
  throw new Error("committed terminal outcome is not a trusted regular file");
39620
39943
  }
39621
39944
  const outcome = parseCommittedOutcome(
39622
- await readFile11(path, "utf8"),
39945
+ await readFile12(path, "utf8"),
39623
39946
  match[1],
39624
39947
  Number(match[2])
39625
39948
  );
@@ -39646,7 +39969,7 @@ async function forgetAcknowledgedTerminalOutcomes(refs, root = defaultTerminalOu
39646
39969
  if (acknowledged.get(`${hostId}:${outcome.taskId}:${outcome.epoch}`) !== outcome.resultId) {
39647
39970
  continue;
39648
39971
  }
39649
- await rm11(outcomePath(root, hostId, outcome.taskId, outcome.epoch), { force: true });
39972
+ await rm12(outcomePath(root, hostId, outcome.taskId, outcome.epoch), { force: true });
39650
39973
  changedHostRoots.add(hostOutcomeRoot(root, hostId));
39651
39974
  }
39652
39975
  for (const scopedRoot of changedHostRoots) await syncDirectory6(scopedRoot);
@@ -39658,22 +39981,22 @@ async function forgetSupersededTerminalOutcomes(hostId, taskId, epoch, root = de
39658
39981
  if (scoped.hostId !== hostId) continue;
39659
39982
  const { outcome } = scoped;
39660
39983
  if (outcome.taskId !== taskId || outcome.epoch >= epoch) continue;
39661
- await rm11(outcomePath(root, hostId, outcome.taskId, outcome.epoch), { force: true });
39984
+ await rm12(outcomePath(root, hostId, outcome.taskId, outcome.epoch), { force: true });
39662
39985
  removed = true;
39663
39986
  }
39664
39987
  if (removed) await syncDirectory6(hostOutcomeRoot(root, hostId));
39665
39988
  }
39666
39989
 
39667
39990
  // src/accepted-assignments.ts
39668
- import { chmod as chmod10, lstat as lstat13, mkdir as mkdir16, open as open11, readdir as readdir6, rename as rename10, rm as rm12 } from "node:fs/promises";
39669
- import { homedir as homedir12 } from "node:os";
39670
- import { dirname as dirname13, join as join21, relative as relative13, resolve as resolve16, sep as sep9 } from "node:path";
39991
+ import { chmod as chmod10, lstat as lstat13, mkdir as mkdir17, open as open11, readdir as readdir7, rename as rename10, rm as rm13 } from "node:fs/promises";
39992
+ import { homedir as homedir13 } from "node:os";
39993
+ import { dirname as dirname13, join as join22, relative as relative13, resolve as resolve16, sep as sep9 } from "node:path";
39671
39994
  var DIRECTORY_MODE6 = 448;
39672
39995
  var FILE_MODE5 = 384;
39673
39996
  var CLAIM_FILE = /^(tsk_[0-9a-f]{32})\.([1-9][0-9]*)\.json$/;
39674
39997
  var TASK_ID = /^tsk_[0-9a-f]{32}$/;
39675
39998
  function defaultAcceptedAssignmentRoot() {
39676
- return join21(homedir12(), ".zixt", "accepted-assignments");
39999
+ return join22(homedir13(), ".zixt", "accepted-assignments");
39677
40000
  }
39678
40001
  async function syncDirectory7(root) {
39679
40002
  if (process.platform === "win32") return;
@@ -39685,7 +40008,7 @@ async function syncDirectory7(root) {
39685
40008
  }
39686
40009
  }
39687
40010
  async function requirePrivateRoot2(root, sync = syncDirectory7) {
39688
- const firstCreated = await mkdir16(root, { recursive: true, mode: DIRECTORY_MODE6 });
40011
+ const firstCreated = await mkdir17(root, { recursive: true, mode: DIRECTORY_MODE6 });
39689
40012
  if (firstCreated) {
39690
40013
  const first = resolve16(firstCreated);
39691
40014
  const target = resolve16(root);
@@ -39693,7 +40016,7 @@ async function requirePrivateRoot2(root, sync = syncDirectory7) {
39693
40016
  let current = first;
39694
40017
  for (const part of relative13(first, target).split(sep9).filter(Boolean)) {
39695
40018
  await sync(current);
39696
- current = join21(current, part);
40019
+ current = join22(current, part);
39697
40020
  }
39698
40021
  }
39699
40022
  const stat3 = await lstat13(root);
@@ -39707,7 +40030,7 @@ function claimPath(root, taskId, epoch) {
39707
40030
  if (!Number.isSafeInteger(epoch) || epoch < 1) {
39708
40031
  throw new Error("accepted assignment epoch is malformed");
39709
40032
  }
39710
- return join21(root, `${taskId}.${epoch}.json`);
40033
+ return join22(root, `${taskId}.${epoch}.json`);
39711
40034
  }
39712
40035
  async function recordAcceptedAssignment(assignment, root = defaultAcceptedAssignmentRoot(), options = {}) {
39713
40036
  const sync = options.syncDirectory ?? syncDirectory7;
@@ -39717,7 +40040,7 @@ async function recordAcceptedAssignment(assignment, root = defaultAcceptedAssign
39717
40040
  } catch {
39718
40041
  return false;
39719
40042
  }
39720
- const temporary = join21(
40043
+ const temporary = join22(
39721
40044
  root,
39722
40045
  `.${assignment.taskId}.${assignment.epoch}.${process.pid}.${Date.now()}.tmp`
39723
40046
  );
@@ -39737,7 +40060,7 @@ async function recordAcceptedAssignment(assignment, root = defaultAcceptedAssign
39737
40060
  } finally {
39738
40061
  await handle?.close().catch(() => {
39739
40062
  });
39740
- await rm12(temporary, { force: true }).catch(() => {
40063
+ await rm13(temporary, { force: true }).catch(() => {
39741
40064
  });
39742
40065
  }
39743
40066
  }
@@ -39754,7 +40077,7 @@ async function recoverAcceptedAssignments(root = defaultAcceptedAssignmentRoot()
39754
40077
  }
39755
40078
  await chmod10(root, DIRECTORY_MODE6);
39756
40079
  const claims = [];
39757
- for (const entry of await readdir6(root, { withFileTypes: true })) {
40080
+ for (const entry of await readdir7(root, { withFileTypes: true })) {
39758
40081
  if (!entry.isFile()) continue;
39759
40082
  const match = CLAIM_FILE.exec(entry.name);
39760
40083
  if (!match) continue;
@@ -39771,7 +40094,7 @@ async function forgetAcceptedAssignment(assignment, root = defaultAcceptedAssign
39771
40094
  } catch {
39772
40095
  return;
39773
40096
  }
39774
- await rm12(path, { force: true }).catch(() => {
40097
+ await rm13(path, { force: true }).catch(() => {
39775
40098
  });
39776
40099
  }
39777
40100
  async function forgetAcknowledgedAcceptedAssignments(assignments, root = defaultAcceptedAssignmentRoot()) {
@@ -39880,23 +40203,23 @@ function createHostLogger(options = {}) {
39880
40203
  }
39881
40204
 
39882
40205
  // src/demo-state.ts
39883
- import { isAbsolute as isAbsolute17, join as join22, parse as parse3, resolve as resolve17 } from "node:path";
40206
+ import { isAbsolute as isAbsolute18, join as join23, parse as parse3, resolve as resolve17 } from "node:path";
39884
40207
  var DEMO_STATE_ROOT_ENV = "ZIXT_DEMO_STATE_ROOT";
39885
40208
  function resolveDemoHostStatePaths(env = process.env) {
39886
40209
  const configured = env.ZIXT_RUNNER === "demo" ? env[DEMO_STATE_ROOT_ENV] : void 0;
39887
40210
  if (!configured) return null;
39888
40211
  const root = resolve17(configured);
39889
- if (!isAbsolute17(configured) || root === parse3(root).root) {
40212
+ if (!isAbsolute18(configured) || root === parse3(root).root) {
39890
40213
  throw new Error(`${DEMO_STATE_ROOT_ENV} must be a dedicated absolute directory`);
39891
40214
  }
39892
40215
  return {
39893
- runRegistryRoot: join22(root, "run-registry"),
39894
- terminalOutcomeRoot: join22(root, "terminal-outcomes"),
39895
- acceptedAssignmentRoot: join22(root, "accepted-assignments"),
39896
- runArtifactRoot: join22(root, "run-artifacts"),
39897
- browserProfileRoot: join22(root, "browser-profiles"),
39898
- runnerWorkspaceRoot: join22(root, "workspaces"),
39899
- codexThreadIndexRoot: join22(root, "codex-threads")
40216
+ runRegistryRoot: join23(root, "run-registry"),
40217
+ terminalOutcomeRoot: join23(root, "terminal-outcomes"),
40218
+ acceptedAssignmentRoot: join23(root, "accepted-assignments"),
40219
+ runArtifactRoot: join23(root, "run-artifacts"),
40220
+ browserProfileRoot: join23(root, "browser-profiles"),
40221
+ runnerWorkspaceRoot: join23(root, "workspaces"),
40222
+ codexThreadIndexRoot: join23(root, "codex-threads")
39900
40223
  };
39901
40224
  }
39902
40225
 
@@ -40058,7 +40381,7 @@ try {
40058
40381
  console.error(hostHelpText());
40059
40382
  process.exit(DO_NOT_RESTART_EXIT_CODE);
40060
40383
  }
40061
- var colorOverride = forcedColor(cliOptions.color);
40384
+ var colorOverride = forcedColor(cliOptions.color) ?? (process.env[HOST_CONSOLE_COLOR_ENV] === "1" ? true : void 0);
40062
40385
  var hostConsoleTail = [];
40063
40386
  var hostConsoleSequence = 0;
40064
40387
  var clientForConsole = {};
@@ -40322,7 +40645,7 @@ async function telemetry() {
40322
40645
  // Measured per heartbeat: free memory and free disk are only useful while
40323
40646
  // they are current, and a demo Host reports its own private root so the
40324
40647
  // number describes the filesystem its Tasks would really write to.
40325
- hardware: await machineHardware(runnerWorkspaceRoot ?? homedir13()),
40648
+ hardware: await machineHardware(runnerWorkspaceRoot ?? homedir14()),
40326
40649
  capabilities: {
40327
40650
  linearToolPack: providerToolPacks.some(
40328
40651
  (pack) => pack.provider === "linear" && pack.health === "ready"
@@ -40493,6 +40816,9 @@ var client = new HostClient({
40493
40816
  switch (status) {
40494
40817
  case "connected":
40495
40818
  log.success("Connected to Zixt Cloud", connectionContext);
40819
+ if (reportedWorkerExits.length > 0) {
40820
+ void forgetWorkerExits(reportedWorkerExits.map(({ file: file2 }) => file2));
40821
+ }
40496
40822
  break;
40497
40823
  case "disconnected":
40498
40824
  log.warn("Connection lost; retrying", {
@@ -40531,6 +40857,18 @@ var client = new HostClient({
40531
40857
  browser: browserManager
40532
40858
  });
40533
40859
  clientForConsole.current = client;
40860
+ var diagnosticsRoot = configuredWorkerDiagnosticsRoot();
40861
+ var reportedWorkerExits = diagnosticsRoot ? await readWorkerExits(diagnosticsRoot) : [];
40862
+ for (const { record: record2 } of reportedWorkerExits) {
40863
+ const { summary, context } = describeWorkerExit(record2);
40864
+ log.error(`The previous Zixt Host worker ${summary}`, {
40865
+ machine,
40866
+ at: record2.at,
40867
+ ...context,
40868
+ next: "This Machine restarted itself; report it if the same exit repeats"
40869
+ });
40870
+ for (const line of record2.stderr) log.error("Previous worker output", { machine, line });
40871
+ }
40534
40872
  log.info("Starting Zixt Host", connectionContext);
40535
40873
  client.start();
40536
40874
  var shuttingDown = false;
@@ -40539,14 +40877,24 @@ function shutdown(exitCode = 0) {
40539
40877
  shuttingDown = true;
40540
40878
  retainRunAssignments();
40541
40879
  log.info("Stopping Zixt Host", { machine, activeTasks: activeSessions });
40542
- const recoveringLiveRuns = activeSessions > 0;
40543
- setTimeout(
40544
- () => {
40545
- finishWorkerProcess(recoveringLiveRuns ? 1 : exitCode);
40546
- },
40547
- recoveringLiveRuns ? 3e4 : 2e3
40548
- ).unref();
40549
- void workerWatchdog.stop().then(() => client.stop()).then(() => finishWorkerProcess(exitCode));
40880
+ beginWorkerShutdown({
40881
+ activeTasks: activeSessions,
40882
+ exitCode,
40883
+ teardown: () => client.stop(),
40884
+ stopHeartbeat: () => workerWatchdog.stop(),
40885
+ onForcedExit: ({ deadlineMs, code, teardownCompleted }) => {
40886
+ log.warn(
40887
+ teardownCompleted ? "Zixt Host finished stopping but the process stayed alive; exiting now" : "Zixt Host did not finish stopping in time; exiting now",
40888
+ {
40889
+ machine,
40890
+ deadline: formatDuration(deadlineMs),
40891
+ exit: code,
40892
+ activeTasks: activeSessions,
40893
+ next: "The Host restarts automatically; report this if it repeats"
40894
+ }
40895
+ );
40896
+ }
40897
+ });
40550
40898
  }
40551
40899
  stopUpdateWatch = !packagedBuild ? () => {
40552
40900
  } : watchForUpdates({