@integrity-labs/agt-cli 0.28.546 → 0.28.548

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/agt.js CHANGED
@@ -40,7 +40,7 @@ import {
40
40
  success,
41
41
  table,
42
42
  warn
43
- } from "../chunk-7WHF3QRW.js";
43
+ } from "../chunk-GYBGWZJP.js";
44
44
  import {
45
45
  AnchorSessionClient,
46
46
  CHANNEL_REGISTRY,
@@ -71,7 +71,7 @@ import {
71
71
  requiredMcpWildcard,
72
72
  resolveChannels,
73
73
  serializeManifestForSlackCli
74
- } from "../chunk-QPSEQLSI.js";
74
+ } from "../chunk-ST4PZ6RF.js";
75
75
  import "../chunk-XWVM4KPK.js";
76
76
 
77
77
  // src/bin/agt.ts
@@ -4834,7 +4834,7 @@ import { execFileSync, execSync } from "child_process";
4834
4834
  import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
4835
4835
  import chalk18 from "chalk";
4836
4836
  import ora16 from "ora";
4837
- var cliVersion = true ? "0.28.546" : "dev";
4837
+ var cliVersion = true ? "0.28.548" : "dev";
4838
4838
  async function fetchLatestVersion() {
4839
4839
  const host2 = getHost();
4840
4840
  if (!host2) return null;
@@ -6006,7 +6006,7 @@ function handleError(err) {
6006
6006
  }
6007
6007
 
6008
6008
  // src/bin/agt.ts
6009
- var cliVersion2 = true ? "0.28.546" : "dev";
6009
+ var cliVersion2 = true ? "0.28.548" : "dev";
6010
6010
  var program = new Command();
6011
6011
  program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
6012
6012
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -42,7 +42,7 @@ import {
42
42
  resolveConnectivityProbe,
43
43
  worseConnectivityOutcome,
44
44
  wrapScheduledTaskPrompt
45
- } from "./chunk-QPSEQLSI.js";
45
+ } from "./chunk-ST4PZ6RF.js";
46
46
  import {
47
47
  parsePsRows
48
48
  } from "./chunk-XWVM4KPK.js";
@@ -5549,7 +5549,7 @@ function exchangeFailureKind(err) {
5549
5549
  }
5550
5550
 
5551
5551
  // src/lib/api-client.ts
5552
- var agtCliVersion = true ? "0.28.546" : "dev";
5552
+ var agtCliVersion = true ? "0.28.548" : "dev";
5553
5553
  var lastConfigHash = null;
5554
5554
  function setConfigHash(hash) {
5555
5555
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -8861,4 +8861,4 @@ export {
8861
8861
  managerInstallSystemUnitCommand,
8862
8862
  managerUninstallSystemUnitCommand
8863
8863
  };
8864
- //# sourceMappingURL=chunk-7WHF3QRW.js.map
8864
+ //# sourceMappingURL=chunk-GYBGWZJP.js.map
@@ -15694,4 +15694,4 @@ export {
15694
15694
  stopAllSessionsAndWait,
15695
15695
  getProjectDir
15696
15696
  };
15697
- //# sourceMappingURL=chunk-QPSEQLSI.js.map
15697
+ //# sourceMappingURL=chunk-ST4PZ6RF.js.map
@@ -100,7 +100,7 @@ async function spawnPairSession(session) {
100
100
  return { ok: true };
101
101
  } catch {
102
102
  }
103
- const { resolveClaudeBinary } = await import("./persistent-session-FM5746XM.js");
103
+ const { resolveClaudeBinary } = await import("./persistent-session-KVONGDAL.js");
104
104
  const claudeBin = resolveClaudeBinary();
105
105
  const pairEnv = {
106
106
  ...process.env,
@@ -373,4 +373,4 @@ export {
373
373
  startClaudePair,
374
374
  submitClaudePairCode
375
375
  };
376
- //# sourceMappingURL=claude-pair-runtime-R3R5OWDM.js.map
376
+ //# sourceMappingURL=claude-pair-runtime-TZKJGXZU.js.map
@@ -53,7 +53,7 @@ import {
53
53
  safeWriteJsonAtomic,
54
54
  setConfigHash,
55
55
  tripClass
56
- } from "../chunk-7WHF3QRW.js";
56
+ } from "../chunk-GYBGWZJP.js";
57
57
  import {
58
58
  getProjectDir as getProjectDir2,
59
59
  getReadyTasks,
@@ -181,7 +181,7 @@ import {
181
181
  toOpencodeModel,
182
182
  transcriptActivityAgeSeconds,
183
183
  writeEgressAllowlist
184
- } from "../chunk-QPSEQLSI.js";
184
+ } from "../chunk-ST4PZ6RF.js";
185
185
  import {
186
186
  reapOrphanChannelMcps
187
187
  } from "../chunk-XWVM4KPK.js";
@@ -288,7 +288,17 @@ function decidePostRestartVerification(pending, sessionStartedAt, sessionHealthy
288
288
  return { kind: "unverified", attempt, final: attempt >= maxAttempts };
289
289
  }
290
290
  function shouldRemediateUnverifiedRestart(outcome, ctx) {
291
- return ctx.enabled && !ctx.breakerTripped && outcome.kind === "unverified" && outcome.final;
291
+ return ctx.enabled && !ctx.breakerTripped && // ENG-8581: never remediate a session whose spawn was SKIPPED because the
292
+ // host cannot authenticate to Claude. Re-respawning cannot bind tools when
293
+ // no session can start at all, so the remediation is incapable of succeeding
294
+ // and simply loops. Observed on dig-host: 28 restarts in 6h, then 21 more in
295
+ // the hour around its re-auth, none of which could ever have worked.
296
+ //
297
+ // The circuit breaker does not catch this, which is the other half of the
298
+ // ticket: a skipped spawn returns `spawnAttempted: false`, so a restart that
299
+ // is never ATTEMPTED never registers as a failing restart. The mechanism
300
+ // designed to stop the loop is structurally blind to it.
301
+ !ctx.authSkipped && outcome.kind === "unverified" && outcome.final;
292
302
  }
293
303
  function computeFirstConnectUnsettled(integrations, now, windowMs) {
294
304
  return integrations.some((i) => {
@@ -300,7 +310,11 @@ function computeFirstConnectUnsettled(integrations, now, windowMs) {
300
310
  });
301
311
  }
302
312
  function shouldDeferBindRemediationForFirstConnect(outcome, ctx) {
303
- return ctx.enabled && !ctx.breakerTripped && ctx.firstConnectUnsettled && ctx.deferralsSoFar < ctx.maxDeferrals && outcome.kind === "unverified" && outcome.final;
313
+ return ctx.enabled && !ctx.breakerTripped && // ENG-8581: an auth-skipped session has no first-connect to wait for either.
314
+ // Deferring would re-arm the verify window forever against a session that
315
+ // cannot start, burning the deferral budget on a condition no amount of
316
+ // waiting fixes. Same gate as remediation, for the same reason.
317
+ !ctx.authSkipped && ctx.firstConnectUnsettled && ctx.deferralsSoFar < ctx.maxDeferrals && outcome.kind === "unverified" && outcome.final;
304
318
  }
305
319
 
306
320
  // src/lib/integration-hash.ts
@@ -9772,6 +9786,12 @@ function cancelPendingSessionRestart(codeName) {
9772
9786
  deferLogThrottle.delete(codeName);
9773
9787
  log(`[hot-reload] Cancelled pending restart timer for '${codeName}' (another teardown path is handling it)`);
9774
9788
  }
9789
+ var lastSpawnOutcomeByAgent = /* @__PURE__ */ new Map();
9790
+ function spawnWasRefusedWithNoSession(codeName) {
9791
+ const last = lastSpawnOutcomeByAgent.get(codeName);
9792
+ if (!last) return false;
9793
+ return !last.spawnAttempted && !last.sessionHealthyAfter;
9794
+ }
9775
9795
  function bindRemediationEnabled() {
9776
9796
  return hostFlagStore().getBoolean("bind-remediation");
9777
9797
  }
@@ -9807,6 +9827,7 @@ function verifyPendingRestarts(now) {
9807
9827
  if (shouldDeferBindRemediationForFirstConnect(outcome, {
9808
9828
  enabled: bindRemediationEnabled(),
9809
9829
  breakerTripped: restartBreaker.isTripped(codeName),
9830
+ authSkipped: spawnWasRefusedWithNoSession(codeName),
9810
9831
  firstConnectUnsettled: firstConnectUnsettledByAgent.get(codeName) ?? false,
9811
9832
  deferralsSoFar: deferrals,
9812
9833
  maxDeferrals: BIND_REMEDIATION_MAX_CONNECTIVITY_DEFERRALS
@@ -9826,9 +9847,15 @@ function verifyPendingRestarts(now) {
9826
9847
  `[restart-verify] ERROR '${codeName}' did NOT respawn healthy after ${outcome.attempt} attempts following an MCP change \u2014 the live session may be stuck on its pre-restart tools. Check session health / manager.log; a manual session restart may be required (ENG-6174)`
9827
9848
  );
9828
9849
  finishRestartTiming(codeName, "failed", `${outcome.attempt} verify attempts`, log, now);
9850
+ if (bindRemediationEnabled() && spawnWasRefusedWithNoSession(codeName)) {
9851
+ log(
9852
+ `[bind-remediation] '${codeName}' NOT remediating \u2014 the last spawn was refused and no session is running (e.g. the host cannot authenticate to Claude). A re-respawn cannot bind tools when nothing can start, so this would loop without the breaker ever seeing it (ENG-8581). Fix the host, not the session.`
9853
+ );
9854
+ }
9829
9855
  if (shouldRemediateUnverifiedRestart(outcome, {
9830
9856
  enabled: bindRemediationEnabled(),
9831
- breakerTripped: restartBreaker.isTripped(codeName)
9857
+ breakerTripped: restartBreaker.isTripped(codeName),
9858
+ authSkipped: spawnWasRefusedWithNoSession(codeName)
9832
9859
  })) {
9833
9860
  const jitterMs = Math.floor(Math.random() * BIND_REMEDIATION_JITTER_MS);
9834
9861
  log(
@@ -10455,7 +10482,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
10455
10482
  var lastVersionCheckAt = 0;
10456
10483
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
10457
10484
  var lastResponsivenessProbeAt = 0;
10458
- var agtCliVersion = true ? "0.28.546" : "dev";
10485
+ var agtCliVersion = true ? "0.28.548" : "dev";
10459
10486
  function resolveBrewPath(execFileSync2) {
10460
10487
  try {
10461
10488
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -11759,7 +11786,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
11759
11786
  if (codeNames.length === 0) return;
11760
11787
  void (async () => {
11761
11788
  try {
11762
- const { collectDiagnostics } = await import("../persistent-session-FM5746XM.js");
11789
+ const { collectDiagnostics } = await import("../persistent-session-KVONGDAL.js");
11763
11790
  await api.post("/host/heartbeat", {
11764
11791
  host_id: hostId,
11765
11792
  agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor)
@@ -11867,7 +11894,7 @@ async function pollCycle() {
11867
11894
  }
11868
11895
  try {
11869
11896
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
11870
- const { collectDiagnostics } = await import("../persistent-session-FM5746XM.js");
11897
+ const { collectDiagnostics } = await import("../persistent-session-KVONGDAL.js");
11871
11898
  const diagCodeNames = [...agentState.persistentSessionAgents];
11872
11899
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor) : void 0;
11873
11900
  let tailscaleHostname;
@@ -11990,7 +12017,7 @@ async function pollCycle() {
11990
12017
  collectPanelessActivityProbes,
11991
12018
  getResponsivenessIntervalMs,
11992
12019
  occupancyQualificationClassifications
11993
- } = await import("../responsiveness-probe-WZMDBY3T.js");
12020
+ } = await import("../responsiveness-probe-OUHRYJYH.js");
11994
12021
  const probeIntervalMs = getResponsivenessIntervalMs();
11995
12022
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
11996
12023
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -12081,7 +12108,7 @@ async function pollCycle() {
12081
12108
  collectResponsivenessProbes,
12082
12109
  livePendingInboundOldestAgeSeconds,
12083
12110
  parkPendingInbound
12084
- } = await import("../responsiveness-probe-WZMDBY3T.js");
12111
+ } = await import("../responsiveness-probe-OUHRYJYH.js");
12085
12112
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
12086
12113
  const wedgeNow = /* @__PURE__ */ new Date();
12087
12114
  const liveAgents = agentState.persistentSessionAgents;
@@ -14365,6 +14392,10 @@ async function processAgent(agent, agentStates) {
14365
14392
  log(
14366
14393
  `[persistent-session-decision] agent=${agent.code_name} decision=${psResult.decision} spawn_attempted=${psResult.spawnAttempted} session_healthy_after=${psResult.sessionHealthyAfter}${detailSuffix}`
14367
14394
  );
14395
+ lastSpawnOutcomeByAgent.set(agent.code_name, {
14396
+ spawnAttempted: psResult.spawnAttempted,
14397
+ sessionHealthyAfter: psResult.sessionHealthyAfter
14398
+ });
14368
14399
  const stuck = persistentSessionStuckTracker.record({
14369
14400
  codeName: agent.code_name,
14370
14401
  sessionHealthy: psResult.sessionHealthyAfter,
@@ -15611,7 +15642,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
15611
15642
  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}`));
15612
15643
  void (async () => {
15613
15644
  try {
15614
- const { collectDiagnostics } = await import("../persistent-session-FM5746XM.js");
15645
+ const { collectDiagnostics } = await import("../persistent-session-KVONGDAL.js");
15615
15646
  await api.post("/host/heartbeat", {
15616
15647
  host_id: hostId,
15617
15648
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor)
@@ -15661,7 +15692,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
15661
15692
  }
15662
15693
  try {
15663
15694
  const hostId = await getHostId();
15664
- const { collectDiagnostics } = await import("../persistent-session-FM5746XM.js");
15695
+ const { collectDiagnostics } = await import("../persistent-session-KVONGDAL.js");
15665
15696
  await api.post("/host/heartbeat", {
15666
15697
  host_id: hostId,
15667
15698
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor)
@@ -16185,7 +16216,7 @@ async function processClaudePairSessions(agents) {
16185
16216
  killPairSession,
16186
16217
  pairTmuxSession,
16187
16218
  finalizeClaudePairOnboarding
16188
- } = await import("../claude-pair-runtime-R3R5OWDM.js");
16219
+ } = await import("../claude-pair-runtime-TZKJGXZU.js");
16189
16220
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
16190
16221
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
16191
16222
  const killed = await killPairSession(pairTmuxSession(pairId));