@integrity-labs/agt-cli 0.28.451 → 0.28.452

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-MY5HPJUW.js";
43
+ } from "../chunk-WOZINHUT.js";
44
44
  import {
45
45
  AnchorSessionClient,
46
46
  CHANNEL_REGISTRY,
@@ -4830,7 +4830,7 @@ import { execFileSync, execSync } from "child_process";
4830
4830
  import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
4831
4831
  import chalk18 from "chalk";
4832
4832
  import ora16 from "ora";
4833
- var cliVersion = true ? "0.28.451" : "dev";
4833
+ var cliVersion = true ? "0.28.452" : "dev";
4834
4834
  async function fetchLatestVersion() {
4835
4835
  const host2 = getHost();
4836
4836
  if (!host2) return null;
@@ -6002,7 +6002,7 @@ function handleError(err) {
6002
6002
  }
6003
6003
 
6004
6004
  // src/bin/agt.ts
6005
- var cliVersion2 = true ? "0.28.451" : "dev";
6005
+ var cliVersion2 = true ? "0.28.452" : "dev";
6006
6006
  var program = new Command();
6007
6007
  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");
6008
6008
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -4910,7 +4910,7 @@ function requireHost() {
4910
4910
  }
4911
4911
 
4912
4912
  // src/lib/api-client.ts
4913
- var agtCliVersion = true ? "0.28.451" : "dev";
4913
+ var agtCliVersion = true ? "0.28.452" : "dev";
4914
4914
  var lastConfigHash = null;
4915
4915
  function setConfigHash(hash) {
4916
4916
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -7411,4 +7411,4 @@ export {
7411
7411
  managerInstallSystemUnitCommand,
7412
7412
  managerUninstallSystemUnitCommand
7413
7413
  };
7414
- //# sourceMappingURL=chunk-MY5HPJUW.js.map
7414
+ //# sourceMappingURL=chunk-WOZINHUT.js.map
@@ -42,7 +42,7 @@ import {
42
42
  resolveEffectivePinRaw,
43
43
  safeWriteJsonAtomic,
44
44
  setConfigHash
45
- } from "../chunk-MY5HPJUW.js";
45
+ } from "../chunk-WOZINHUT.js";
46
46
  import {
47
47
  getProjectDir as getProjectDir2,
48
48
  getReadyTasks,
@@ -841,6 +841,14 @@ function logClaudeMdCeilingTransition(codeName, report, log2) {
841
841
  function reaperRestartBreakerReason(activeKeys) {
842
842
  return activeKeys.length >= 2 ? "mcp-presence-reaper" : void 0;
843
843
  }
844
+ var KNOWN_REASON_CLASS_MAP = {
845
+ crash: true,
846
+ provisioning: true,
847
+ "credential-rotation": true
848
+ };
849
+ var KNOWN_REASON_CLASSES = new Set(
850
+ Object.keys(KNOWN_REASON_CLASS_MAP)
851
+ );
844
852
  var PROVISIONING_RELOAD_REASONS = /* @__PURE__ */ new Set([
845
853
  "hot-reload-mcp",
846
854
  "managed-mcp-churn",
@@ -897,6 +905,11 @@ function maxProvisioningBucket(events) {
897
905
  }
898
906
  return best;
899
907
  }
908
+ function tripClass(trip) {
909
+ if (trip.trippedClass) return trip.trippedClass;
910
+ if (!Array.isArray(trip.eventsAtTrip) || trip.eventsAtTrip.length === 0) return "crash";
911
+ return trip.eventsAtTrip.every((e) => isProvisioningReloadReason(e.reason)) ? "provisioning" : "crash";
912
+ }
900
913
  var DEFAULT_MAX = 2;
901
914
  var DEFAULT_WINDOW_MS = 6e5;
902
915
  var DEFAULT_PROVISIONING_MAX = 5;
@@ -1007,7 +1020,10 @@ var RestartBreaker = class {
1007
1020
  const trip = {
1008
1021
  trippedAt: at,
1009
1022
  eventsAtTrip: [...tripEvents],
1010
- statusMessage: formatStatusMessage(tripEvents, tripWindowMs, trippedClass, provBucket.key)
1023
+ statusMessage: formatStatusMessage(tripEvents, tripWindowMs, trippedClass, provBucket.key),
1024
+ // ENG-7577: persist the tripping class so the recovery path can gate on
1025
+ // it after a manager restart, without re-deriving it from prose.
1026
+ trippedClass
1011
1027
  };
1012
1028
  this.trips.set(codeName, trip);
1013
1029
  this.events.delete(codeName);
@@ -1048,7 +1064,11 @@ var RestartBreaker = class {
1048
1064
  if (!saved) return;
1049
1065
  for (const [codeName, trip] of Object.entries(saved)) {
1050
1066
  if (trip && typeof trip.trippedAt === "number" && Array.isArray(trip.eventsAtTrip)) {
1051
- this.trips.set(codeName, trip);
1067
+ const klass = trip.trippedClass;
1068
+ this.trips.set(
1069
+ codeName,
1070
+ klass === void 0 || KNOWN_REASON_CLASSES.has(klass) ? trip : { ...trip, trippedClass: void 0 }
1071
+ );
1052
1072
  }
1053
1073
  }
1054
1074
  }
@@ -1275,6 +1295,9 @@ function decideAutoResume(opts) {
1275
1295
  const { trip, marker, config: config2, now } = opts;
1276
1296
  if (!config2.enabled) return { action: "skip", reason: "disabled" };
1277
1297
  if (!trip) return { action: "skip", reason: "no-trip" };
1298
+ if (tripClass(trip) !== "provisioning") {
1299
+ return { action: "skip", reason: "class-not-eligible" };
1300
+ }
1278
1301
  if (marker && now - marker.autoResumedAt < config2.backoffResetMs) {
1279
1302
  return { action: "skip", reason: "already-auto-resumed" };
1280
1303
  }
@@ -1296,6 +1319,28 @@ function hydrateAutoResumeMarkers(saved) {
1296
1319
  return map;
1297
1320
  }
1298
1321
 
1322
+ // src/lib/breaker-stale-trip.ts
1323
+ var DEFAULT_STALE_TRIP_SETTLE_MS = 12e4;
1324
+ var MIN_STALE_TRIP_SETTLE_MS = 1e3;
1325
+ function readStaleTripSettleMs() {
1326
+ return Math.max(
1327
+ MIN_STALE_TRIP_SETTLE_MS,
1328
+ readEnvNumber("AGT_RESTART_BREAKER_STALE_TRIP_SETTLE_MS", DEFAULT_STALE_TRIP_SETTLE_MS)
1329
+ );
1330
+ }
1331
+ function decideStaleTripClear(opts) {
1332
+ const { trip, agentStatus, killSwitched, settleMs, now } = opts;
1333
+ if (!trip) return { action: "hold", reason: "no-trip" };
1334
+ if (agentStatus !== "active" || killSwitched) {
1335
+ return { action: "hold", reason: "pause-in-force" };
1336
+ }
1337
+ const ageMs = now - trip.trippedAt;
1338
+ if (ageMs < settleMs) {
1339
+ return { action: "hold", reason: "settling", remainingMs: settleMs - ageMs };
1340
+ }
1341
+ return { action: "clear", ageMs };
1342
+ }
1343
+
1299
1344
  // src/lib/resume-reconciler.ts
1300
1345
  var DEFAULT_MIN_HEALTHY_CYCLES = 2;
1301
1346
  var DEFAULT_BACKOFF_RESET_MS2 = 864e5;
@@ -8905,6 +8950,33 @@ function maybeReportCurrentTrip(codeName) {
8905
8950
  log(`[circuit-breaker] Failed to report trip for '${codeName}' to API: ${err.message}`);
8906
8951
  });
8907
8952
  }
8953
+ function maybeClearStaleTrip(agent) {
8954
+ const codeName = agent.code_name;
8955
+ const trip = restartBreaker.getTrip(codeName);
8956
+ const decision = decideStaleTripClear({
8957
+ trip,
8958
+ agentStatus: agent.status,
8959
+ killSwitched: Boolean(agent.kill_switch),
8960
+ settleMs: readStaleTripSettleMs(),
8961
+ now: Date.now()
8962
+ });
8963
+ if (decision.action !== "clear") return;
8964
+ restartBreaker.clear(codeName);
8965
+ reportedTrips.delete(codeName);
8966
+ dependencyRecoveryLedger.clear(codeName);
8967
+ log(
8968
+ `[circuit-breaker] agent=${codeName} cleared STALE trip \u2014 authoritative status=active while a trip was held (age=${Math.round(decision.ageMs / 6e4)}min, trippedAt=${new Date(trip.trippedAt).toISOString()}); the pause this trip caused is no longer in force (ENG-7577)`
8969
+ );
8970
+ const marker = autoResumeMarkers.get(codeName);
8971
+ const isSelfResume = marker !== void 0 && Date.now() - marker.autoResumedAt < AUTO_RESUME_SELF_WINDOW_MS;
8972
+ if (!isSelfResume) autoResumeMarkers.delete(codeName);
8973
+ state6 = {
8974
+ ...state6,
8975
+ circuitBreakerTrips: restartBreaker.serialize(),
8976
+ circuitBreakerAutoResumes: Object.fromEntries(autoResumeMarkers.entries())
8977
+ };
8978
+ send({ type: "state-update", state: state6 });
8979
+ }
8908
8980
  var autoResumeMarkers = /* @__PURE__ */ new Map();
8909
8981
  var autoResumeInFlight = /* @__PURE__ */ new Set();
8910
8982
  var AUTO_RESUME_SELF_WINDOW_MS = 12e4;
@@ -8931,11 +9003,11 @@ function maybeAutoResume(agent) {
8931
9003
  now: Date.now()
8932
9004
  });
8933
9005
  if (decision.action === "skip") {
8934
- if ((decision.reason === "already-auto-resumed" || decision.reason === "not-quiet-yet") && trip) {
9006
+ if ((decision.reason === "already-auto-resumed" || decision.reason === "not-quiet-yet" || decision.reason === "class-not-eligible") && trip) {
8935
9007
  const key = `${codeName}:${trip.trippedAt}`;
8936
9008
  if (autoResumeLoggedSkips.get(key) !== decision.reason) {
8937
9009
  autoResumeLoggedSkips.set(key, decision.reason);
8938
- const detail = decision.reason === "not-quiet-yet" ? ` (~${Math.ceil((decision.remainingMs ?? 0) / 6e4)}min remaining)` : " \u2014 credit spent for this cycle; operator resume re-arms it";
9010
+ const detail = decision.reason === "not-quiet-yet" ? ` (~${Math.ceil((decision.remainingMs ?? 0) / 6e4)}min remaining)` : decision.reason === "class-not-eligible" ? ` class=${tripClass(trip)} \u2014 the blind quiet-timer only auto-recovers provisioning-reload trips; this one stays paused for an operator (ENG-7577)` : " \u2014 credit spent for this cycle; operator resume re-arms it";
8939
9011
  log(`[auto-resume] agent=${codeName} decision=skip reason=${decision.reason}${detail} (ENG-6088)`);
8940
9012
  }
8941
9013
  }
@@ -9810,7 +9882,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
9810
9882
  var lastVersionCheckAt = 0;
9811
9883
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
9812
9884
  var lastResponsivenessProbeAt = 0;
9813
- var agtCliVersion = true ? "0.28.451" : "dev";
9885
+ var agtCliVersion = true ? "0.28.452" : "dev";
9814
9886
  function resolveBrewPath(execFileSync2) {
9815
9887
  try {
9816
9888
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -11801,6 +11873,7 @@ async function processAgent(agent, agentStates) {
11801
11873
  const previousKnownStatus = agentState.knownStatuses.get(agent.agent_id);
11802
11874
  agentState.agentDisplayNames.set(agent.code_name, agent.display_name);
11803
11875
  agentState.codeNameToAgentId.set(agent.code_name, agent.agent_id);
11876
+ maybeClearStaleTrip(agent);
11804
11877
  maybeReportCurrentTrip(agent.code_name);
11805
11878
  if (agent.framework) {
11806
11879
  agentFrameworkCache.set(agent.code_name, agent.framework);
@@ -11943,6 +12016,7 @@ async function processAgent(agent, agentStates) {
11943
12016
  if (previousStatus === "paused" && agent.status === "active" && restartBreaker.isTripped(agent.code_name)) {
11944
12017
  restartBreaker.clear(agent.code_name);
11945
12018
  reportedTrips.delete(agent.code_name);
12019
+ dependencyRecoveryLedger.clear(agent.code_name);
11946
12020
  log(`[circuit-breaker] Cleared trip for '${agent.code_name}' on operator resume (paused \u2192 active)`);
11947
12021
  }
11948
12022
  if (previousStatus === "paused" && agent.status === "active") {