@integrity-labs/agt-cli 0.28.62 → 0.28.64

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.
@@ -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-5PEPYSMG.js");
103
+ const { resolveClaudeBinary } = await import("./persistent-session-WJBIN6WM.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-QSRMTD7I.js.map
376
+ //# sourceMappingURL=claude-pair-runtime-SPP3CUBA.js.map
@@ -27,7 +27,7 @@ import {
27
27
  requireHost,
28
28
  safeWriteJsonAtomic,
29
29
  setConfigHash
30
- } from "../chunk-QQGXIZVB.js";
30
+ } from "../chunk-JY3LAHBG.js";
31
31
  import {
32
32
  getProjectDir as getProjectDir2,
33
33
  getReadyTasks,
@@ -65,7 +65,7 @@ import {
65
65
  takeWatchdogGiveUpCount,
66
66
  takeZombieDetection,
67
67
  transcriptActivityAgeSeconds
68
- } from "../chunk-AKOF4VV5.js";
68
+ } from "../chunk-4P7HUXWI.js";
69
69
  import {
70
70
  FLAGS_SCHEMA_VERSION,
71
71
  FLAG_REGISTRY,
@@ -96,7 +96,7 @@ import {
96
96
  resolveDmTarget,
97
97
  sumTranscriptUsageInWindow,
98
98
  wrapScheduledTaskPrompt
99
- } from "../chunk-7F2K3RRD.js";
99
+ } from "../chunk-XKAJW4EX.js";
100
100
  import {
101
101
  parsePsRows,
102
102
  reapOrphanChannelMcps
@@ -1060,6 +1060,8 @@ function formatStatusMessage(events, windowMs) {
1060
1060
  var DEFAULT_WINDOW_MS2 = 6e5;
1061
1061
  var DEFAULT_MIN_TRANSITIONS = 4;
1062
1062
  var DEFAULT_MIN_DISTINCT = 2;
1063
+ var DEFAULT_LONG_WINDOW_MS = 36e5;
1064
+ var DEFAULT_LONG_MIN_TRANSITIONS = 4;
1063
1065
  function readEnvNumber2(name, fallback) {
1064
1066
  const raw = process.env[name];
1065
1067
  if (!raw) return fallback;
@@ -1073,6 +1075,8 @@ var McpFlapDampener = class {
1073
1075
  windowMs;
1074
1076
  minTransitions;
1075
1077
  minDistinct;
1078
+ longWindowMs;
1079
+ longMinTransitions;
1076
1080
  now;
1077
1081
  history = /* @__PURE__ */ new Map();
1078
1082
  flapping = /* @__PURE__ */ new Set();
@@ -1080,6 +1084,8 @@ var McpFlapDampener = class {
1080
1084
  this.windowMs = opts.windowMs ?? readEnvNumber2("AGT_MCP_FLAP_WINDOW_MS", DEFAULT_WINDOW_MS2);
1081
1085
  this.minTransitions = opts.minTransitions ?? readEnvNumber2("AGT_MCP_FLAP_MIN_TRANSITIONS", DEFAULT_MIN_TRANSITIONS);
1082
1086
  this.minDistinct = opts.minDistinct ?? readEnvNumber2("AGT_MCP_FLAP_MIN_DISTINCT", DEFAULT_MIN_DISTINCT);
1087
+ this.longWindowMs = opts.longWindowMs ?? readEnvNumber2("AGT_MCP_FLAP_LONG_WINDOW_MS", DEFAULT_LONG_WINDOW_MS);
1088
+ this.longMinTransitions = opts.longMinTransitions ?? readEnvNumber2("AGT_MCP_FLAP_LONG_MIN_TRANSITIONS", DEFAULT_LONG_MIN_TRANSITIONS);
1083
1089
  this.now = opts.now ?? Date.now;
1084
1090
  if (!Number.isFinite(this.windowMs) || this.windowMs < 1e3) {
1085
1091
  throw new Error("mcp-flap-dampener windowMs must be a finite number >= 1000");
@@ -1090,6 +1096,12 @@ var McpFlapDampener = class {
1090
1096
  if (!Number.isFinite(this.minDistinct) || this.minDistinct < 2) {
1091
1097
  throw new Error("mcp-flap-dampener minDistinct must be a finite number >= 2");
1092
1098
  }
1099
+ if (!Number.isFinite(this.longWindowMs) || this.longWindowMs < this.windowMs) {
1100
+ throw new Error("mcp-flap-dampener longWindowMs must be a finite number >= windowMs");
1101
+ }
1102
+ if (!Number.isFinite(this.longMinTransitions) || this.longMinTransitions < 2) {
1103
+ throw new Error("mcp-flap-dampener longMinTransitions must be a finite number >= 2");
1104
+ }
1093
1105
  }
1094
1106
  key(codeName, channel) {
1095
1107
  return `${codeName}\0${channel}`;
@@ -1103,34 +1115,58 @@ var McpFlapDampener = class {
1103
1115
  record(codeName, channel, signature) {
1104
1116
  const k = this.key(codeName, channel);
1105
1117
  const at = this.now();
1106
- const cutoff = at - this.windowMs;
1118
+ const cutoff = at - this.longWindowMs;
1107
1119
  const prior = (this.history.get(k) ?? []).filter((o) => o.at >= cutoff);
1108
1120
  prior.push({ sig: signature, at });
1109
1121
  this.history.set(k, prior);
1110
- let transitions = 0;
1111
- for (let i = 1; i < prior.length; i++) {
1112
- if (prior[i].sig !== prior[i - 1].sig) transitions++;
1113
- }
1114
- const distinctStates = new Set(prior.map((o) => o.sig)).size;
1115
- const revisited = prior.slice(0, -1).some((o, i) => o.sig === signature && i !== prior.length - 2);
1122
+ const fast = this.windowMetrics(prior, at - this.windowMs);
1123
+ const slow = this.windowMetrics(prior, at - this.longWindowMs);
1124
+ const fastOsc = fast.transitions >= this.minTransitions && fast.distinctStates >= this.minDistinct && fast.revisited;
1125
+ const slowOsc = slow.transitions >= this.longMinTransitions && slow.distinctStates >= this.minDistinct && slow.revisited;
1126
+ const oscillating = fastOsc || slowOsc;
1127
+ const tier = fastOsc ? "fast" : slowOsc ? "slow" : null;
1116
1128
  const transitionNow = prior.length >= 2 && prior[prior.length - 1].sig !== prior[prior.length - 2].sig;
1117
- const oscillating = transitions >= this.minTransitions && distinctStates >= this.minDistinct && revisited;
1118
1129
  const wasFlapping = this.flapping.has(k);
1119
1130
  let onset = false;
1120
1131
  if (wasFlapping) {
1121
- if (!transitionNow) this.flapping.delete(k);
1132
+ if (!transitionNow) {
1133
+ this.flapping.delete(k);
1134
+ this.history.set(k, [{ sig: signature, at }]);
1135
+ }
1122
1136
  } else if (transitionNow && oscillating) {
1123
1137
  this.flapping.add(k);
1124
1138
  onset = true;
1125
1139
  }
1140
+ const reported = tier === "slow" ? slow : fast;
1126
1141
  return {
1127
1142
  flapping: this.flapping.has(k),
1128
- distinctStates,
1129
- transitions,
1143
+ distinctStates: reported.distinctStates,
1144
+ transitions: reported.transitions,
1130
1145
  windowCount: prior.length,
1131
- onset
1146
+ onset,
1147
+ tier,
1148
+ longTransitions: slow.transitions,
1149
+ longDistinctStates: slow.distinctStates
1132
1150
  };
1133
1151
  }
1152
+ /**
1153
+ * Transitions / distinct signatures / revisit flag for the observations that
1154
+ * fall inside `[windowStart, now]`. The latest observation (the one just
1155
+ * recorded) is always in-window. A revisit = the latest signature appears
1156
+ * earlier in the sub-window but NOT as the immediately-preceding observation,
1157
+ * so strictly-monotonic growth (A→B→C→D) never counts as a revisit.
1158
+ */
1159
+ windowMetrics(prior, windowStart) {
1160
+ const inWin = prior.filter((o) => o.at >= windowStart);
1161
+ let transitions = 0;
1162
+ for (let i = 1; i < inWin.length; i++) {
1163
+ if (inWin[i].sig !== inWin[i - 1].sig) transitions++;
1164
+ }
1165
+ const distinctStates = new Set(inWin.map((o) => o.sig)).size;
1166
+ const latest = inWin[inWin.length - 1];
1167
+ const revisited = latest ? inWin.slice(0, -1).some((o, i) => o.sig === latest.sig && i !== inWin.length - 2) : false;
1168
+ return { transitions, distinctStates, revisited };
1169
+ }
1134
1170
  /** True if (codeName, channel) is currently dampened. */
1135
1171
  isFlapping(codeName, channel) {
1136
1172
  return this.flapping.has(this.key(codeName, channel));
@@ -6582,7 +6618,7 @@ function checkMcpConfigDriftAndScheduleRestart(codeName, projectDir) {
6582
6618
  );
6583
6619
  } else if (flapSuppressed) {
6584
6620
  log(
6585
- `[mcp-flap-dampener] .mcp.json membership drift for '${codeName}' [${decision.addedOrRemoved.join(", ")}] held \u2014 managed-MCP set is flapping, adopting baseline WITHOUT restart until it settles (ENG-6123)`
6621
+ `[mcp-flap-dampener] .mcp.json membership drift for '${codeName}' [${decision.addedOrRemoved.join(", ")}] held \u2014 managed-MCP set is flapping, adopting baseline WITHOUT restart until it settles (ENG-6123, ENG-6512)`
6586
6622
  );
6587
6623
  } else if (decision.restart) {
6588
6624
  clearPresenceReaperStateForKeys(codeName, new Set(decision.addedOrRemoved));
@@ -6698,7 +6734,7 @@ var cachedMaintenanceWindow = null;
6698
6734
  var lastVersionCheckAt = 0;
6699
6735
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
6700
6736
  var lastResponsivenessProbeAt = 0;
6701
- var agtCliVersion = true ? "0.28.62" : "dev";
6737
+ var agtCliVersion = true ? "0.28.64" : "dev";
6702
6738
  function resolveBrewPath(execFileSync4) {
6703
6739
  try {
6704
6740
  const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -7806,7 +7842,7 @@ async function pollCycle() {
7806
7842
  }
7807
7843
  try {
7808
7844
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
7809
- const { collectDiagnostics } = await import("../persistent-session-5PEPYSMG.js");
7845
+ const { collectDiagnostics } = await import("../persistent-session-WJBIN6WM.js");
7810
7846
  const diagCodeNames = [...agentState.persistentSessionAgents];
7811
7847
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
7812
7848
  let tailscaleHostname;
@@ -7907,7 +7943,7 @@ async function pollCycle() {
7907
7943
  const {
7908
7944
  collectResponsivenessProbes,
7909
7945
  getResponsivenessIntervalMs
7910
- } = await import("../responsiveness-probe-HG23JDG2.js");
7946
+ } = await import("../responsiveness-probe-XVWLBSSH.js");
7911
7947
  const probeIntervalMs = getResponsivenessIntervalMs();
7912
7948
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
7913
7949
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -7939,7 +7975,7 @@ async function pollCycle() {
7939
7975
  collectResponsivenessProbes,
7940
7976
  livePendingInboundOldestAgeSeconds,
7941
7977
  parkPendingInbound
7942
- } = await import("../responsiveness-probe-HG23JDG2.js");
7978
+ } = await import("../responsiveness-probe-XVWLBSSH.js");
7943
7979
  const { getProjectDir: wedgeProjectDir } = await import("../claude-scheduler-FATCLHDM.js");
7944
7980
  const wedgeNow = /* @__PURE__ */ new Date();
7945
7981
  const liveAgents = agentState.persistentSessionAgents;
@@ -9314,7 +9350,7 @@ async function processAgent(agent, agentStates) {
9314
9350
  const intFlap = mcpFlapDampener.record(agent.code_name, FLAP_CHANNEL_INTEGRATIONS, intMembership);
9315
9351
  if (intFlap.onset) {
9316
9352
  log(
9317
- `[mcp-flap-dampener] integration set for '${agent.code_name}' is FLAPPING (${intFlap.transitions} transitions / ${intFlap.distinctStates} states in window) \u2014 suppressing integration-update notices until it settles (ENG-6123)`
9353
+ `[mcp-flap-dampener] integration set for '${agent.code_name}' is FLAPPING (${intFlap.tier} tier: ${intFlap.transitions} transitions / ${intFlap.distinctStates} states in window) \u2014 suppressing integration-update notices until it settles (ENG-6123, ENG-6512)`
9318
9354
  );
9319
9355
  recordConfigChurnEvent(agent.agent_id, agent.code_name, FLAP_CHANNEL_INTEGRATIONS, intMembership);
9320
9356
  }
@@ -9403,7 +9439,7 @@ async function processAgent(agent, agentStates) {
9403
9439
  const mcpFlap = mcpFlapDampener.record(agent.code_name, FLAP_CHANNEL_MANAGED_MCP, mcpMembership);
9404
9440
  if (mcpFlap.onset) {
9405
9441
  log(
9406
- `[mcp-flap-dampener] managed-MCP set for '${agent.code_name}' is FLAPPING (${mcpFlap.transitions} transitions / ${mcpFlap.distinctStates} states in window) \u2014 suppressing mcp-update notice + restart until it settles (ENG-6123)`
9442
+ `[mcp-flap-dampener] managed-MCP set for '${agent.code_name}' is FLAPPING (${mcpFlap.tier} tier: ${mcpFlap.transitions} transitions / ${mcpFlap.distinctStates} states in window) \u2014 suppressing mcp-update notice + restart until it settles (ENG-6123, ENG-6512)`
9407
9443
  );
9408
9444
  recordConfigChurnEvent(agent.agent_id, agent.code_name, FLAP_CHANNEL_MANAGED_MCP, mcpMembership);
9409
9445
  }
@@ -11373,7 +11409,7 @@ async function processClaudePairSessions(agents) {
11373
11409
  killPairSession,
11374
11410
  pairTmuxSession,
11375
11411
  finalizeClaudePairOnboarding
11376
- } = await import("../claude-pair-runtime-QSRMTD7I.js");
11412
+ } = await import("../claude-pair-runtime-SPP3CUBA.js");
11377
11413
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
11378
11414
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
11379
11415
  const killed = await killPairSession(pairTmuxSession(pairId));