@integrity-labs/agt-cli 0.28.1010 → 0.28.1012

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.
@@ -64,7 +64,7 @@ import {
64
64
  safeWriteJsonAtomic,
65
65
  setConfigHash,
66
66
  tripClass
67
- } from "../chunk-V6HO4MUI.js";
67
+ } from "../chunk-O3DODZVZ.js";
68
68
  import {
69
69
  getProjectDir as getProjectDir2,
70
70
  getReadyTasks,
@@ -77,8 +77,10 @@ import {
77
77
  CHANNEL_SECRET_ENV_KEYS,
78
78
  CLAUDE_MANAGED_SETTINGS_DIR,
79
79
  ChildProcessError,
80
+ DEFAULT_KILL_AFTER_MS,
80
81
  agentRuntimeKey,
81
82
  applyBlockedPromptVerdict,
83
+ boundedArgv,
82
84
  buildEgressAllowlist,
83
85
  checkChannelInputs,
84
86
  collectChannelSpawnSecrets,
@@ -95,6 +97,7 @@ import {
95
97
  getProjectDir,
96
98
  getSessionState,
97
99
  hardBoundedCapture,
100
+ hasTimeoutBinary,
98
101
  hashFile,
99
102
  injectMessage,
100
103
  injectMessageWithStatus,
@@ -142,7 +145,7 @@ import {
142
145
  takeZombieDetection,
143
146
  toOpencodeModel,
144
147
  writeEgressAllowlist
145
- } from "../chunk-HSYBLAWA.js";
148
+ } from "../chunk-K73BIWKA.js";
146
149
  import {
147
150
  ACCOUNT_ENFORCEMENT_MARKER_FILENAME,
148
151
  AnchorSessionClient,
@@ -241,7 +244,7 @@ import {
241
244
  subagentActivityAgeSeconds,
242
245
  sumTranscriptUsageInWindow,
243
246
  transcriptActivityAgeSeconds
244
- } from "../chunk-OPDT2OE5.js";
247
+ } from "../chunk-LV72A4BE.js";
245
248
  import "../chunk-DHWNVVX4.js";
246
249
  import {
247
250
  reapOrphanChannelMcps
@@ -7652,8 +7655,8 @@ function shouldNudgeUnchangedBoard(signature, state9, now, fullCadenceMs, maxCad
7652
7655
  if (state9.signature !== signature) return true;
7653
7656
  return now - state9.nudgedAt >= nudgeIntervalForCount(state9.nudgeCount ?? 1, fullCadenceMs, maxCadenceMs);
7654
7657
  }
7655
- function failureRetryIntervalForCount(failureCount, baseMs, maxMs) {
7656
- const exponent = Math.max(0, Math.min(failureCount - 1, 8));
7658
+ function failureRetryIntervalForCount(failureCount2, baseMs, maxMs) {
7659
+ const exponent = Math.max(0, Math.min(failureCount2 - 1, 8));
7657
7660
  return Math.min(baseMs * 3 ** exponent, Math.max(maxMs, baseMs));
7658
7661
  }
7659
7662
  var KANBAN_NOTICE_BREAKER_THRESHOLD = 5;
@@ -7911,7 +7914,7 @@ function loadKanbanNudgeState(target, configDir) {
7911
7914
  if (!value || typeof value !== "object") continue;
7912
7915
  const v = value;
7913
7916
  if (typeof v.signature !== "string" || typeof v.nudgedAt !== "number" || !Number.isFinite(v.nudgedAt)) continue;
7914
- const failureCount = typeof v.failureCount === "number" && Number.isFinite(v.failureCount) && v.failureCount >= 1 ? Math.floor(v.failureCount) : void 0;
7917
+ const failureCount2 = typeof v.failureCount === "number" && Number.isFinite(v.failureCount) && v.failureCount >= 1 ? Math.floor(v.failureCount) : void 0;
7915
7918
  const failedAt = typeof v.failedAt === "number" && Number.isFinite(v.failedAt) ? v.failedAt : void 0;
7916
7919
  target.set(codeName, {
7917
7920
  signature: v.signature,
@@ -7920,8 +7923,8 @@ function loadKanbanNudgeState(target, configDir) {
7920
7923
  // Only carry the pair when the count is real: a failedAt with no count
7921
7924
  // cannot gate anything, and a count with no timestamp is handled as
7922
7925
  // "due now" by shouldAttemptNoticeEnqueue rather than wedging the agent.
7923
- ...failureCount !== void 0 ? { failureCount } : {},
7924
- ...failureCount !== void 0 && failedAt !== void 0 ? { failedAt } : {}
7926
+ ...failureCount2 !== void 0 ? { failureCount: failureCount2 } : {},
7927
+ ...failureCount2 !== void 0 && failedAt !== void 0 ? { failedAt } : {}
7925
7928
  });
7926
7929
  }
7927
7930
  }
@@ -9764,6 +9767,105 @@ function stopPidPressureSampler() {
9764
9767
  timer2 = null;
9765
9768
  }
9766
9769
 
9770
+ // src/lib/runtime-version-sampler.ts
9771
+ import { execFileSync as execFileSync2 } from "child_process";
9772
+ import { execFile as execFileCb } from "child_process";
9773
+ import { promisify as promisify2 } from "util";
9774
+ var execFileAsync2 = promisify2(execFileCb);
9775
+ var SAMPLE_INTERVAL_MS3 = 5 * 6e4;
9776
+ var lastSample2 = /* @__PURE__ */ new Map();
9777
+ var failureCount = /* @__PURE__ */ new Map();
9778
+ async function readVersionReal(codeName) {
9779
+ const timeoutMs = 1e4;
9780
+ timeoutBinaryAvailable ??= hasTimeoutBinary(execFileSync2);
9781
+ const { execFile: file, execArgs } = boundedArgv(
9782
+ "docker",
9783
+ ["exec", `agt-${codeName}`, "claude", "--version"],
9784
+ timeoutMs,
9785
+ DEFAULT_KILL_AFTER_MS,
9786
+ timeoutBinaryAvailable
9787
+ );
9788
+ try {
9789
+ const { stdout } = await execFileAsync2(file, execArgs, {
9790
+ encoding: "utf-8",
9791
+ timeout: timeoutBinaryAvailable ? timeoutMs + DEFAULT_KILL_AFTER_MS + 5e3 : timeoutMs
9792
+ });
9793
+ return String(stdout ?? "");
9794
+ } catch {
9795
+ return null;
9796
+ }
9797
+ }
9798
+ var timeoutBinaryAvailable;
9799
+ function parseClaudeVersion(raw) {
9800
+ if (raw == null) return null;
9801
+ const m = raw.trim().match(/\b(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)\b/);
9802
+ return m ? m[1] : null;
9803
+ }
9804
+ async function sampleRuntimeVersionFor(codeName, io = {}) {
9805
+ const isolated = io.isolatedFor?.(codeName) ?? effectiveIsolationMode(codeName) === "docker";
9806
+ if (!isolated) {
9807
+ lastSample2.delete(codeName);
9808
+ failureCount.delete(codeName);
9809
+ return { state: "not-isolated", version: null, sampledAt: null, failures: 0 };
9810
+ }
9811
+ const resolveDir = io.resolveCgroupDir ?? resolveCgroupDirReal;
9812
+ const readVersion = io.readVersion ?? readVersionReal;
9813
+ const now = io.now ?? Date.now;
9814
+ const dir = resolveDir(codeName);
9815
+ if (dir == null) {
9816
+ const failures = (failureCount.get(codeName) ?? 0) + 1;
9817
+ failureCount.set(codeName, failures);
9818
+ lastSample2.delete(codeName);
9819
+ return { state: "error", version: null, sampledAt: null, failures };
9820
+ }
9821
+ const cached = lastSample2.get(codeName);
9822
+ if (cached && cached.dir === dir) return cached.sample;
9823
+ const version = parseClaudeVersion(await readVersion(codeName));
9824
+ if (version == null) {
9825
+ const failures = (failureCount.get(codeName) ?? 0) + 1;
9826
+ failureCount.set(codeName, failures);
9827
+ lastSample2.delete(codeName);
9828
+ return { state: "error", version: null, sampledAt: null, failures };
9829
+ }
9830
+ failureCount.delete(codeName);
9831
+ const sample = {
9832
+ state: "ok",
9833
+ version,
9834
+ sampledAt: new Date(now()).toISOString(),
9835
+ failures: 0
9836
+ };
9837
+ lastSample2.set(codeName, { dir, sample });
9838
+ return sample;
9839
+ }
9840
+ async function sampleRuntimeVersionOnce(codeNames, io = {}) {
9841
+ for (const codeName of codeNames) await sampleRuntimeVersionFor(codeName, io);
9842
+ }
9843
+ function runtimeVersionFor(codeName) {
9844
+ const cached = lastSample2.get(codeName);
9845
+ if (cached) return cached.sample;
9846
+ const failures = failureCount.get(codeName) ?? 0;
9847
+ if (failures > 0) return { state: "error", version: null, sampledAt: null, failures };
9848
+ return { state: "unsampled", version: null, sampledAt: null, failures: 0 };
9849
+ }
9850
+ var timer3 = null;
9851
+ var sampling = false;
9852
+ function startRuntimeVersionSampler(liveAgents, io = {}) {
9853
+ if (timer3) return;
9854
+ timer3 = setInterval(() => {
9855
+ if (sampling) return;
9856
+ sampling = true;
9857
+ void sampleRuntimeVersionOnce(liveAgents(), io).catch(() => {
9858
+ }).finally(() => {
9859
+ sampling = false;
9860
+ });
9861
+ }, SAMPLE_INTERVAL_MS3);
9862
+ timer3.unref?.();
9863
+ }
9864
+ function stopRuntimeVersionSampler() {
9865
+ if (timer3) clearInterval(timer3);
9866
+ timer3 = null;
9867
+ }
9868
+
9767
9869
  // src/lib/opencode-slack-ingest.ts
9768
9870
  import { createHash as createHash17 } from "crypto";
9769
9871
 
@@ -13247,7 +13349,7 @@ function scheduleSessionRestart(codeName, delayMs, reason, breakerReason = "hot-
13247
13349
  clearTimeout(existing.timer);
13248
13350
  log(`[hot-reload] Coalesced restart for '${codeName}': replacing pending timer with ${reason}`);
13249
13351
  }
13250
- const timer3 = setTimeout(() => {
13352
+ const timer4 = setTimeout(() => {
13251
13353
  pendingSessionRestarts.delete(codeName);
13252
13354
  const gate = restartGateFor(codeName, breakerReason);
13253
13355
  if (gate !== "bypass" && gate !== "proceed") {
@@ -13335,8 +13437,8 @@ function scheduleSessionRestart(codeName, delayMs, reason, breakerReason = "hot-
13335
13437
  void respawnAgentAfterMcpStop(codeName, reason);
13336
13438
  }
13337
13439
  }, delayMs);
13338
- timer3.unref?.();
13339
- pendingSessionRestarts.set(codeName, { timer: timer3, reason, breakerReason, beforeStop, auditDetail });
13440
+ timer4.unref?.();
13441
+ pendingSessionRestarts.set(codeName, { timer: timer4, reason, breakerReason, beforeStop, auditDetail });
13340
13442
  }
13341
13443
  function cancelPendingSessionRestart(codeName) {
13342
13444
  pendingRestartVerifications.delete(codeName);
@@ -13465,7 +13567,7 @@ var pendingDayRolloverReset = /* @__PURE__ */ new Set();
13465
13567
  var dayRolloverInboundHold = /* @__PURE__ */ new Map();
13466
13568
  var INBOUND_HOLD_EPISODE_GAP_MS = 12e4;
13467
13569
  async function channelInboundActivityAgeSecondsFor(codeName) {
13468
- const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-ETSEM5K6.js");
13570
+ const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-RSVGRS63.js");
13469
13571
  const newest = newestPendingInboundActivityMtimeMs(dirname11(paneLogPath(codeName)));
13470
13572
  if (newest === null) return null;
13471
13573
  return Math.max(0, Math.floor((Date.now() - newest) / 1e3));
@@ -14208,10 +14310,10 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
14208
14310
  var lastVersionCheckAt = 0;
14209
14311
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
14210
14312
  var lastResponsivenessProbeAt = 0;
14211
- var agtCliVersion = true ? "0.28.1010" : "dev";
14212
- function resolveBrewPath(execFileSync2) {
14313
+ var agtCliVersion = true ? "0.28.1012" : "dev";
14314
+ function resolveBrewPath(execFileSync3) {
14213
14315
  try {
14214
- const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
14316
+ const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
14215
14317
  if (out) return out;
14216
14318
  } catch {
14217
14319
  }
@@ -14225,7 +14327,7 @@ function resolveBrewPath(execFileSync2) {
14225
14327
  }
14226
14328
  return null;
14227
14329
  }
14228
- function claudeBinaryInstalled(execFileSync2) {
14330
+ function claudeBinaryInstalled(execFileSync3) {
14229
14331
  const canonical = [
14230
14332
  "/home/linuxbrew/.linuxbrew/bin/claude",
14231
14333
  "/opt/homebrew/bin/claude",
@@ -14233,7 +14335,7 @@ function claudeBinaryInstalled(execFileSync2) {
14233
14335
  ];
14234
14336
  if (canonical.some((path) => existsSync19(path))) return true;
14235
14337
  try {
14236
- execFileSync2("which", ["claude"], { timeout: 5e3 });
14338
+ execFileSync3("which", ["claude"], { timeout: 5e3 });
14237
14339
  return true;
14238
14340
  } catch {
14239
14341
  return false;
@@ -14267,9 +14369,9 @@ async function ensureToolkitCli(toolkitSlug) {
14267
14369
  }
14268
14370
  const { binary, installer, package: pkg, script } = integration.cli_tool;
14269
14371
  const resolvedInstaller = installer ?? "manual";
14270
- const { execFileSync: execFileSync2, execSync } = await import("child_process");
14372
+ const { execFileSync: execFileSync3, execSync } = await import("child_process");
14271
14373
  try {
14272
- execFileSync2("which", [binary], { timeout: 5e3, stdio: "pipe" });
14374
+ execFileSync3("which", [binary], { timeout: 5e3, stdio: "pipe" });
14273
14375
  toolkitCliEnsured.add(toolkitSlug);
14274
14376
  toolkitCliRetryAfter.delete(toolkitSlug);
14275
14377
  toolkitCliFailureCount.delete(toolkitSlug);
@@ -14290,14 +14392,14 @@ async function ensureToolkitCli(toolkitSlug) {
14290
14392
  return;
14291
14393
  }
14292
14394
  log(`[toolkit-install] ${toolkitSlug}: installing via npm (${pkg})\u2026`);
14293
- execFileSync2("npm", ["install", "-g", pkg], { timeout: 18e4, stdio: "pipe" });
14395
+ execFileSync3("npm", ["install", "-g", pkg], { timeout: 18e4, stdio: "pipe" });
14294
14396
  } else if (resolvedInstaller === "brew") {
14295
14397
  if (!pkg) {
14296
14398
  log(`[toolkit-install] ${toolkitSlug}: installer=brew but no package declared`);
14297
14399
  toolkitCliEnsured.add(toolkitSlug);
14298
14400
  return;
14299
14401
  }
14300
- const brewPath = resolveBrewPath(execFileSync2);
14402
+ const brewPath = resolveBrewPath(execFileSync3);
14301
14403
  if (!brewPath) {
14302
14404
  log(`[toolkit-install] ${toolkitSlug}: installer=brew but Homebrew not available \u2014 install manually: brew install ${pkg}`);
14303
14405
  toolkitCliEnsured.add(toolkitSlug);
@@ -14307,9 +14409,9 @@ async function ensureToolkitCli(toolkitSlug) {
14307
14409
  const isRoot = typeof process.getuid === "function" && process.getuid() === 0;
14308
14410
  log(`[toolkit-install] ${toolkitSlug}: installing via brew (${pkg})\u2026`);
14309
14411
  if (isRoot) {
14310
- execFileSync2("sudo", ["-u", "ec2-user", "-H", brewPath, "install", pkg], { timeout: 18e4, stdio: "pipe", cwd: "/tmp" });
14412
+ execFileSync3("sudo", ["-u", "ec2-user", "-H", brewPath, "install", pkg], { timeout: 18e4, stdio: "pipe", cwd: "/tmp" });
14311
14413
  } else {
14312
- execFileSync2(brewPath, ["install", pkg], { timeout: 18e4, stdio: "pipe" });
14414
+ execFileSync3(brewPath, ["install", pkg], { timeout: 18e4, stdio: "pipe" });
14313
14415
  }
14314
14416
  } else if (resolvedInstaller === "script") {
14315
14417
  if (!script) {
@@ -14331,7 +14433,7 @@ async function ensureToolkitCli(toolkitSlug) {
14331
14433
  process.env.PATH = `${brewBinDir}:${process.env.PATH ?? ""}`;
14332
14434
  }
14333
14435
  try {
14334
- execFileSync2("which", [binary], { timeout: 5e3, stdio: "pipe" });
14436
+ execFileSync3("which", [binary], { timeout: 5e3, stdio: "pipe" });
14335
14437
  log(`[toolkit-install] ${toolkitSlug}: installed \u2014 ${binary} now on PATH`);
14336
14438
  toolkitCliEnsured.add(toolkitSlug);
14337
14439
  toolkitCliRetryAfter.delete(toolkitSlug);
@@ -14379,16 +14481,16 @@ async function ensureIsolationImage(imageUri) {
14379
14481
  }
14380
14482
  isolationImageInFlight.add(imageUri);
14381
14483
  try {
14382
- const { execFileSync: execFileSync2 } = await import("child_process");
14484
+ const { execFileSync: execFileSync3 } = await import("child_process");
14383
14485
  try {
14384
- execFileSync2("which", ["docker"], { timeout: 5e3, stdio: "pipe" });
14486
+ execFileSync3("which", ["docker"], { timeout: 5e3, stdio: "pipe" });
14385
14487
  } catch {
14386
14488
  recordIsolationImageFailure(imageUri, `'docker' not found on host - required to pull the isolation image (install it, then the manager retries)`);
14387
14489
  return;
14388
14490
  }
14389
14491
  const hasAws = (() => {
14390
14492
  try {
14391
- execFileSync2("which", ["aws"], { timeout: 5e3, stdio: "pipe" });
14493
+ execFileSync3("which", ["aws"], { timeout: 5e3, stdio: "pipe" });
14392
14494
  return true;
14393
14495
  } catch {
14394
14496
  return false;
@@ -14397,11 +14499,11 @@ async function ensureIsolationImage(imageUri) {
14397
14499
  if (isPublic) {
14398
14500
  if (hasAws) {
14399
14501
  try {
14400
- const password = execFileSync2("aws", ["ecr-public", "get-login-password", "--region", "us-east-1"], {
14502
+ const password = execFileSync3("aws", ["ecr-public", "get-login-password", "--region", "us-east-1"], {
14401
14503
  timeout: 3e4,
14402
14504
  stdio: ["ignore", "pipe", "pipe"]
14403
14505
  }).toString().trim();
14404
- execFileSync2("docker", ["login", "--username", "AWS", "--password-stdin", "public.ecr.aws"], {
14506
+ execFileSync3("docker", ["login", "--username", "AWS", "--password-stdin", "public.ecr.aws"], {
14405
14507
  input: password,
14406
14508
  timeout: 3e4,
14407
14509
  stdio: ["pipe", "pipe", "pipe"]
@@ -14416,11 +14518,11 @@ async function ensureIsolationImage(imageUri) {
14416
14518
  return;
14417
14519
  }
14418
14520
  try {
14419
- const password = execFileSync2("aws", ["ecr", "get-login-password", "--region", privRegion], {
14521
+ const password = execFileSync3("aws", ["ecr", "get-login-password", "--region", privRegion], {
14420
14522
  timeout: 3e4,
14421
14523
  stdio: ["ignore", "pipe", "pipe"]
14422
14524
  }).toString().trim();
14423
- execFileSync2("docker", ["login", "--username", "AWS", "--password-stdin", registry], {
14525
+ execFileSync3("docker", ["login", "--username", "AWS", "--password-stdin", registry], {
14424
14526
  input: password,
14425
14527
  timeout: 3e4,
14426
14528
  stdio: ["pipe", "pipe", "pipe"]
@@ -14501,7 +14603,7 @@ function runAsync(cmd, args, opts) {
14501
14603
  let stdout = "";
14502
14604
  let stderr = "";
14503
14605
  let settled = false;
14504
- const timer3 = setTimeout(() => {
14606
+ const timer4 = setTimeout(() => {
14505
14607
  child.kill("SIGTERM");
14506
14608
  if (settled) return;
14507
14609
  settled = true;
@@ -14522,13 +14624,13 @@ function runAsync(cmd, args, opts) {
14522
14624
  child.on("error", (err) => {
14523
14625
  if (settled) return;
14524
14626
  settled = true;
14525
- clearTimeout(timer3);
14627
+ clearTimeout(timer4);
14526
14628
  reject(err);
14527
14629
  });
14528
14630
  child.on("close", (code) => {
14529
14631
  if (settled) return;
14530
14632
  settled = true;
14531
- clearTimeout(timer3);
14633
+ clearTimeout(timer4);
14532
14634
  resolve2({ code: code ?? -1, stdout, stderr });
14533
14635
  });
14534
14636
  }).catch(reject);
@@ -14583,11 +14685,11 @@ function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
14583
14685
  }
14584
14686
  var OPENCODE_NPM_VERSION = "1.18.3";
14585
14687
  async function ensureOpencodeBinary() {
14586
- const { execFileSync: execFileSync2 } = await import("child_process");
14688
+ const { execFileSync: execFileSync3 } = await import("child_process");
14587
14689
  const bin = process.env["AGT_OPENCODE_BIN"]?.trim() || "opencode";
14588
14690
  const probe = () => {
14589
14691
  try {
14590
- execFileSync2(bin, ["--version"], { stdio: "ignore", timeout: 1e4 });
14692
+ execFileSync3(bin, ["--version"], { stdio: "ignore", timeout: 1e4 });
14591
14693
  return true;
14592
14694
  } catch {
14593
14695
  return false;
@@ -14608,7 +14710,7 @@ async function ensureOpencodeBinary() {
14608
14710
  return false;
14609
14711
  }
14610
14712
  try {
14611
- const prefix = execFileSync2("npm", ["prefix", "-g"], { encoding: "utf-8", timeout: 1e4 }).trim();
14713
+ const prefix = execFileSync3("npm", ["prefix", "-g"], { encoding: "utf-8", timeout: 1e4 }).trim();
14612
14714
  if (prefix) {
14613
14715
  const npmBin = join42(prefix, "bin");
14614
14716
  const current = (process.env.PATH ?? "").split(pathDelimiter);
@@ -14640,8 +14742,8 @@ async function ensureFrameworkBinary(frameworkId) {
14640
14742
  }
14641
14743
  frameworkBinaryChecked.add(frameworkId);
14642
14744
  lastManagedSettingsStatus = ensureClaudeManagedSettings();
14643
- const { execFileSync: execFileSync2 } = await import("child_process");
14644
- const brewPath = resolveBrewPath(execFileSync2);
14745
+ const { execFileSync: execFileSync3 } = await import("child_process");
14746
+ const brewPath = resolveBrewPath(execFileSync3);
14645
14747
  if (!brewPath) {
14646
14748
  log("Homebrew not found (no `brew` on PATH, no /home/linuxbrew/.linuxbrew/bin/brew). Cannot auto-install Claude Code. Install manually: https://claude.ai/download");
14647
14749
  return;
@@ -14654,7 +14756,7 @@ async function ensureFrameworkBinary(frameworkId) {
14654
14756
  }
14655
14757
  return runAsync(brewPath, args, opts);
14656
14758
  };
14657
- const claudeExists = claudeBinaryInstalled(execFileSync2);
14759
+ const claudeExists = claudeBinaryInstalled(execFileSync3);
14658
14760
  if (!claudeExists) {
14659
14761
  log(`Claude Code binary not found \u2014 installing via Homebrew${isRoot ? " (as ec2-user via sudo)" : ""}...`);
14660
14762
  try {
@@ -14689,13 +14791,13 @@ async function maybeUpgradeClaudeCode() {
14689
14791
  }
14690
14792
  claudeCodeUpgradeInFlight = true;
14691
14793
  stampClaudeCodeUpgradeMarker();
14692
- const { execFileSync: execFileSync2 } = await import("child_process");
14693
- const brewPath = resolveBrewPath(execFileSync2);
14794
+ const { execFileSync: execFileSync3 } = await import("child_process");
14795
+ const brewPath = resolveBrewPath(execFileSync3);
14694
14796
  if (!brewPath) {
14695
14797
  claudeCodeUpgradeInFlight = false;
14696
14798
  return;
14697
14799
  }
14698
- if (!claudeBinaryInstalled(execFileSync2)) {
14800
+ if (!claudeBinaryInstalled(execFileSync3)) {
14699
14801
  claudeCodeUpgradeInFlight = false;
14700
14802
  return;
14701
14803
  }
@@ -14825,8 +14927,8 @@ async function checkAndUpdateCli(opts) {
14825
14927
  }
14826
14928
  }
14827
14929
  async function checkAndUpdateCliViaBrew(force = false) {
14828
- const { execFileSync: execFileSync2 } = await import("child_process");
14829
- const brewPath = resolveBrewPath(execFileSync2);
14930
+ const { execFileSync: execFileSync3 } = await import("child_process");
14931
+ const brewPath = resolveBrewPath(execFileSync3);
14830
14932
  if (!brewPath) return "noop";
14831
14933
  {
14832
14934
  const brewPinRaw = resolveAgtCliPinRaw();
@@ -14853,13 +14955,13 @@ async function checkAndUpdateCliViaBrew(force = false) {
14853
14955
  }
14854
14956
  let metadataFresh = true;
14855
14957
  try {
14856
- execFileSync2(brewPath, ["update", "--quiet"], { timeout: 6e4, stdio: "pipe" });
14958
+ execFileSync3(brewPath, ["update", "--quiet"], { timeout: 6e4, stdio: "pipe" });
14857
14959
  } catch (err) {
14858
14960
  metadataFresh = false;
14859
14961
  log(`[self-update] brew update failed (continuing with stale cache): ${err.message}`);
14860
14962
  }
14861
14963
  try {
14862
- const outdated = execFileSync2(brewPath, ["outdated", "--json=v2"], {
14964
+ const outdated = execFileSync3(brewPath, ["outdated", "--json=v2"], {
14863
14965
  timeout: 3e4,
14864
14966
  encoding: "utf-8"
14865
14967
  });
@@ -14894,7 +14996,7 @@ async function checkAndUpdateCliViaBrew(force = false) {
14894
14996
  const brewInstallHold = await selfUpdateDeviceStateHold(force);
14895
14997
  if (brewInstallHold) return brewInstallHold;
14896
14998
  try {
14897
- execFileSync2(brewPath, ["upgrade", "integrity-labs/tap/agt"], {
14999
+ execFileSync3(brewPath, ["upgrade", "integrity-labs/tap/agt"], {
14898
15000
  timeout: 12e4,
14899
15001
  stdio: "pipe"
14900
15002
  });
@@ -15071,7 +15173,7 @@ async function fetchUrgentDistTagVersion() {
15071
15173
  }
15072
15174
  }
15073
15175
  async function installAgtCliViaNpm(version, reasonLabel, force = false) {
15074
- const { execFileSync: execFileSync2 } = await import("child_process");
15176
+ const { execFileSync: execFileSync3 } = await import("child_process");
15075
15177
  const isRoot = typeof process.getuid === "function" && process.getuid() === 0;
15076
15178
  const cmd = isRoot ? "npm" : "sudo";
15077
15179
  const installArgs = [
@@ -15084,14 +15186,14 @@ async function installAgtCliViaNpm(version, reasonLabel, force = false) {
15084
15186
  const npmInstallHold = await selfUpdateDeviceStateHold(force);
15085
15187
  if (npmInstallHold) return npmInstallHold;
15086
15188
  try {
15087
- execFileSync2(cmd, args, { timeout: 18e4, stdio: "pipe" });
15189
+ execFileSync3(cmd, args, { timeout: 18e4, stdio: "pipe" });
15088
15190
  } catch (err) {
15089
15191
  log(`[self-update] npm upgrade failed: ${err.message}`);
15090
15192
  return "failed";
15091
15193
  }
15092
15194
  let smokeOk = false;
15093
15195
  try {
15094
- const out = execFileSync2("agt", ["--version"], { timeout: 15e3, stdio: "pipe" }).toString();
15196
+ const out = execFileSync3("agt", ["--version"], { timeout: 15e3, stdio: "pipe" }).toString();
15095
15197
  smokeOk = isAgtVersionSmokeOk(out, version);
15096
15198
  if (!smokeOk) {
15097
15199
  log(
@@ -15156,8 +15258,8 @@ function effectiveRuntimeAuthenticated() {
15156
15258
  async function maybeProbeClaudeRuntimeAuth() {
15157
15259
  if (runtimeAuthProbeInFlight) return;
15158
15260
  if (Date.now() - lastRuntimeAuthProbeAt < RUNTIME_AUTH_PROBE_INTERVAL_MS) return;
15159
- const { execFileSync: execFileSync2 } = await import("child_process");
15160
- if (!claudeBinaryInstalled(execFileSync2)) return;
15261
+ const { execFileSync: execFileSync3 } = await import("child_process");
15262
+ if (!claudeBinaryInstalled(execFileSync3)) return;
15161
15263
  runtimeAuthProbeInFlight = true;
15162
15264
  lastRuntimeAuthProbeAt = Date.now();
15163
15265
  try {
@@ -15266,8 +15368,8 @@ async function runHostUsageCommand() {
15266
15368
  }
15267
15369
  }
15268
15370
  async function maybePollHostUsageFromCycle() {
15269
- const { execFileSync: execFileSync2 } = await import("child_process");
15270
- if (!claudeBinaryInstalled(execFileSync2)) return;
15371
+ const { execFileSync: execFileSync3 } = await import("child_process");
15372
+ if (!claudeBinaryInstalled(execFileSync3)) return;
15271
15373
  await maybePollHostUsage({
15272
15374
  api,
15273
15375
  runUsageCommand: runHostUsageCommand,
@@ -15842,10 +15944,10 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
15842
15944
  if (codeNames.length === 0) return;
15843
15945
  void (async () => {
15844
15946
  try {
15845
- const { collectDiagnostics } = await import("../persistent-session-NLQ6AASM.js");
15947
+ const { collectDiagnostics } = await import("../persistent-session-KPASTJIV.js");
15846
15948
  await api.post("/host/heartbeat", {
15847
15949
  host_id: hostId,
15848
- agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
15950
+ agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
15849
15951
  });
15850
15952
  } catch (err) {
15851
15953
  log(`[restart] post-respawn diagnostics flush failed: ${err.message}`);
@@ -15908,7 +16010,7 @@ async function pollCycleInner() {
15908
16010
  getSlackToken: (codeName) => agentChannelTokens.get(codeName)?.slack ?? null,
15909
16011
  sendSlack: async (botToken, body) => {
15910
16012
  const controller = new AbortController();
15911
- const timer3 = setTimeout(() => controller.abort(), 5e3);
16013
+ const timer4 = setTimeout(() => controller.abort(), 5e3);
15912
16014
  try {
15913
16015
  const res = await fetch("https://slack.com/api/chat.postMessage", {
15914
16016
  method: "POST",
@@ -15925,7 +16027,7 @@ async function pollCycleInner() {
15925
16027
  const isAbort = err.name === "AbortError";
15926
16028
  return { ok: false, error: isAbort ? "timeout" : err.message };
15927
16029
  } finally {
15928
- clearTimeout(timer3);
16030
+ clearTimeout(timer4);
15929
16031
  }
15930
16032
  },
15931
16033
  // ENG-6399: report the restart to audit_log via POST /host/restart-event.
@@ -15984,9 +16086,9 @@ async function pollCycleInner() {
15984
16086
  }
15985
16087
  try {
15986
16088
  const { detectHostSecurity } = await import("../host-security-KQYYZZVW.js");
15987
- const { collectDiagnostics } = await import("../persistent-session-NLQ6AASM.js");
16089
+ const { collectDiagnostics } = await import("../persistent-session-KPASTJIV.js");
15988
16090
  const diagCodeNames = [...agentState.persistentSessionAgents];
15989
- const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor) : void 0;
16091
+ const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor) : void 0;
15990
16092
  let tailscaleHostname;
15991
16093
  try {
15992
16094
  const { execSync: es } = await import("child_process");
@@ -16160,7 +16262,7 @@ async function pollCycleInner() {
16160
16262
  collectPanelessActivityProbes,
16161
16263
  getResponsivenessIntervalMs,
16162
16264
  occupancyQualificationClassifications
16163
- } = await import("../responsiveness-probe-ETSEM5K6.js");
16265
+ } = await import("../responsiveness-probe-RSVGRS63.js");
16164
16266
  const probeIntervalMs = getResponsivenessIntervalMs();
16165
16267
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
16166
16268
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -16277,7 +16379,7 @@ async function pollCycleInner() {
16277
16379
  collectResponsivenessProbes,
16278
16380
  livePendingInboundOldestAgeSeconds,
16279
16381
  parkPendingInbound
16280
- } = await import("../responsiveness-probe-ETSEM5K6.js");
16382
+ } = await import("../responsiveness-probe-RSVGRS63.js");
16281
16383
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-M6AFZWNU.js");
16282
16384
  const wedgeNow = /* @__PURE__ */ new Date();
16283
16385
  const liveAgents = agentState.persistentSessionAgents;
@@ -16433,7 +16535,7 @@ async function pollCycleInner() {
16433
16535
  }
16434
16536
  try {
16435
16537
  const { scrapeMcpFailedBannerCount } = await import("../pane-mcp-banner-scraper-VR5QGP3J.js");
16436
- const { probeSessionAuth } = await import("../session-auth-dead-J3MNBHCZ.js");
16538
+ const { probeSessionAuth } = await import("../session-auth-dead-YV2X4AGF.js");
16437
16539
  const observations = [];
16438
16540
  const pendingCacheCommits = [];
16439
16541
  const modelApiErrorReportingOn = hostFlagStore().getBoolean("model-api-error-reporting");
@@ -20813,7 +20915,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
20813
20915
  try {
20814
20916
  const freshId = rotateSessionForWedge(codeName);
20815
20917
  consecutiveWedgeCycles.delete(codeName);
20816
- const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-ETSEM5K6.js");
20918
+ const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-RSVGRS63.js");
20817
20919
  const { parked, deadLettered } = parkForRestart(codeName, /* @__PURE__ */ new Date());
20818
20920
  const parkNote = parked > 0 ? `, ${parked} inbound parked` : "";
20819
20921
  const deadNote = deadLettered > 0 ? `, ${deadLettered} undeliverable dead-lettered` : "";
@@ -20856,10 +20958,10 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
20856
20958
  void api.post("/host/restart-ack", { host_id: hostId, agent_id: agentId, restart_requested_at: requestedAt }).catch((err) => log(`[restart-lane] ack failed for '${codeName}': ${err.message}`));
20857
20959
  void (async () => {
20858
20960
  try {
20859
- const { collectDiagnostics } = await import("../persistent-session-NLQ6AASM.js");
20961
+ const { collectDiagnostics } = await import("../persistent-session-KPASTJIV.js");
20860
20962
  await api.post("/host/heartbeat", {
20861
20963
  host_id: hostId,
20862
- agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
20964
+ agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
20863
20965
  });
20864
20966
  } catch (err) {
20865
20967
  log(`[restart-lane] post-respawn diagnostics flush failed for '${codeName}': ${err.message}`);
@@ -20907,10 +21009,10 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
20907
21009
  }
20908
21010
  try {
20909
21011
  const hostId = await getHostId();
20910
- const { collectDiagnostics } = await import("../persistent-session-NLQ6AASM.js");
21012
+ const { collectDiagnostics } = await import("../persistent-session-KPASTJIV.js");
20911
21013
  await api.post("/host/heartbeat", {
20912
21014
  host_id: hostId,
20913
- agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
21015
+ agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
20914
21016
  });
20915
21017
  } catch (err) {
20916
21018
  log(`[fast-mcp-respawn] post-respawn diagnostics flush failed for '${codeName}': ${err.message}`);
@@ -21508,17 +21610,17 @@ async function maybeInjectKanbanCheck(codeName, agentId, actionableCount, signat
21508
21610
  });
21509
21611
  return;
21510
21612
  }
21511
- const failureCount = (priorState?.failureCount ?? 0) + 1;
21613
+ const failureCount2 = (priorState?.failureCount ?? 0) + 1;
21512
21614
  setKanbanNudgeState(codeName, {
21513
21615
  signature: priorState?.signature ?? signature,
21514
21616
  nudgedAt: priorState?.nudgedAt ?? 0,
21515
21617
  ...priorState?.nudgeCount !== void 0 ? { nudgeCount: priorState.nudgeCount } : {},
21516
- failureCount,
21618
+ failureCount: failureCount2,
21517
21619
  failedAt: Date.now()
21518
21620
  });
21519
- if (failureCount === KANBAN_NOTICE_BREAKER_THRESHOLD) {
21621
+ if (failureCount2 === KANBAN_NOTICE_BREAKER_THRESHOLD) {
21520
21622
  log(
21521
- `[manager-worker] kanban notice rail BREAKER OPEN for '${codeName}' \u2014 ${failureCount} consecutive enqueue failures; retries continue at the capped interval`
21623
+ `[manager-worker] kanban notice rail BREAKER OPEN for '${codeName}' \u2014 ${failureCount2} consecutive enqueue failures; retries continue at the capped interval`
21522
21624
  );
21523
21625
  getHostId().then((hostId) => {
21524
21626
  if (!hostId) return;
@@ -21529,7 +21631,7 @@ async function maybeInjectKanbanCheck(codeName, agentId, actionableCount, signat
21529
21631
  payload: {
21530
21632
  agent_code_name: codeName,
21531
21633
  agent_id: agentId,
21532
- consecutive_failures: failureCount,
21634
+ consecutive_failures: failureCount2,
21533
21635
  retry_interval_ms: KANBAN_HYBRID_MAX_CADENCE_MS
21534
21636
  },
21535
21637
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
@@ -21542,7 +21644,7 @@ async function maybeInjectKanbanCheck(codeName, agentId, actionableCount, signat
21542
21644
  return;
21543
21645
  }
21544
21646
  log(
21545
- `[manager-worker] kanban direct-chat enqueue failed for '${codeName}' (${failureCount} consecutive) - backing off before the next attempt`
21647
+ `[manager-worker] kanban direct-chat enqueue failed for '${codeName}' (${failureCount2} consecutive) - backing off before the next attempt`
21546
21648
  );
21547
21649
  }
21548
21650
  var lastHarvestAt = /* @__PURE__ */ new Map();
@@ -21578,7 +21680,7 @@ async function processClaudePairSessions(agents) {
21578
21680
  // cannot take it for itself — by the time it runs, the write it is looking
21579
21681
  // for may already have happened.
21580
21682
  snapshotPairConfig
21581
- } = await import("../claude-pair-runtime-EQDC53WO.js");
21683
+ } = await import("../claude-pair-runtime-NPXBXUSE.js");
21582
21684
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
21583
21685
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
21584
21686
  const killed = await killPairSession(pairTmuxSession(pairId));
@@ -22399,6 +22501,7 @@ function startPolling() {
22399
22501
  livenessTimer.unref();
22400
22502
  startPaneOccupancySampler(() => agentState.persistentSessionAgents);
22401
22503
  startPidPressureSampler(() => agentState.persistentSessionAgents);
22504
+ startRuntimeVersionSampler(() => agentState.persistentSessionAgents);
22402
22505
  {
22403
22506
  const seedOutcome = seedClaudeConfigFromLegacy({ log });
22404
22507
  const configDirUsable = claudeConfigDirIsReady();
@@ -22564,6 +22667,7 @@ async function stopPolling(opts = {}) {
22564
22667
  }
22565
22668
  stopPaneOccupancySampler();
22566
22669
  stopPidPressureSampler();
22670
+ stopRuntimeVersionSampler();
22567
22671
  const shutdownTimer = setTimeout(() => {
22568
22672
  log("Shutdown timeout exceeded (15s), forcing exit");
22569
22673
  process.exit(opts.forcedExitCode ?? 1);