@integrity-labs/agt-cli 0.28.548 → 0.28.550

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.
@@ -53,7 +53,7 @@ import {
53
53
  safeWriteJsonAtomic,
54
54
  setConfigHash,
55
55
  tripClass
56
- } from "../chunk-GYBGWZJP.js";
56
+ } from "../chunk-VSFKVITC.js";
57
57
  import {
58
58
  getProjectDir as getProjectDir2,
59
59
  getReadyTasks,
@@ -4623,6 +4623,19 @@ function shouldNudgeUnchangedBoard(signature, state7, now, fullCadenceMs, maxCad
4623
4623
  if (state7.signature !== signature) return true;
4624
4624
  return now - state7.nudgedAt >= nudgeIntervalForCount(state7.nudgeCount ?? 1, fullCadenceMs, maxCadenceMs);
4625
4625
  }
4626
+ function failureRetryIntervalForCount(failureCount, baseMs, maxMs) {
4627
+ const exponent = Math.max(0, Math.min(failureCount - 1, 8));
4628
+ return Math.min(baseMs * 3 ** exponent, Math.max(maxMs, baseMs));
4629
+ }
4630
+ var KANBAN_NOTICE_BREAKER_THRESHOLD = 5;
4631
+ function shouldAttemptNoticeEnqueue(state7, now, baseMs, maxMs, breakerThreshold = KANBAN_NOTICE_BREAKER_THRESHOLD) {
4632
+ const failures = state7?.failureCount ?? 0;
4633
+ if (failures <= 0) return { attempt: true, breakerOpen: false };
4634
+ const breakerOpen = failures >= breakerThreshold;
4635
+ const failedAt = state7?.failedAt;
4636
+ const due = failedAt === void 0 || failedAt > now || now - failedAt >= failureRetryIntervalForCount(failures, baseMs, maxMs);
4637
+ return { attempt: due, breakerOpen };
4638
+ }
4626
4639
  var BOARD_INJECT_TEMPLATES = /* @__PURE__ */ new Set(["morning-plan", "task-update", "hourly-status", "end-of-day-summary"]);
4627
4640
  function parseStandupSummary(summary) {
4628
4641
  const lines = summary.split("\n");
@@ -4892,10 +4905,17 @@ function loadKanbanNudgeState(target, configDir) {
4892
4905
  if (!value || typeof value !== "object") continue;
4893
4906
  const v = value;
4894
4907
  if (typeof v.signature !== "string" || typeof v.nudgedAt !== "number" || !Number.isFinite(v.nudgedAt)) continue;
4908
+ const failureCount = typeof v.failureCount === "number" && Number.isFinite(v.failureCount) && v.failureCount >= 1 ? Math.floor(v.failureCount) : void 0;
4909
+ const failedAt = typeof v.failedAt === "number" && Number.isFinite(v.failedAt) ? v.failedAt : void 0;
4895
4910
  target.set(codeName, {
4896
4911
  signature: v.signature,
4897
4912
  nudgedAt: v.nudgedAt,
4898
- nudgeCount: typeof v.nudgeCount === "number" && Number.isFinite(v.nudgeCount) && v.nudgeCount >= 1 ? Math.floor(v.nudgeCount) : 1
4913
+ nudgeCount: typeof v.nudgeCount === "number" && Number.isFinite(v.nudgeCount) && v.nudgeCount >= 1 ? Math.floor(v.nudgeCount) : 1,
4914
+ // Only carry the pair when the count is real: a failedAt with no count
4915
+ // cannot gate anything, and a count with no timestamp is handled as
4916
+ // "due now" by shouldAttemptNoticeEnqueue rather than wedging the agent.
4917
+ ...failureCount !== void 0 ? { failureCount } : {},
4918
+ ...failureCount !== void 0 && failedAt !== void 0 ? { failedAt } : {}
4899
4919
  });
4900
4920
  }
4901
4921
  }
@@ -10482,7 +10502,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
10482
10502
  var lastVersionCheckAt = 0;
10483
10503
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
10484
10504
  var lastResponsivenessProbeAt = 0;
10485
- var agtCliVersion = true ? "0.28.548" : "dev";
10505
+ var agtCliVersion = true ? "0.28.550" : "dev";
10486
10506
  function resolveBrewPath(execFileSync2) {
10487
10507
  try {
10488
10508
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -16170,6 +16190,13 @@ ${formatRunMarker(run_id)}` : KANBAN_CHECK_COMMAND;
16170
16190
  return true;
16171
16191
  }
16172
16192
  async function maybeInjectKanbanCheck(codeName, agentId, actionableCount, signature) {
16193
+ const failureGate = shouldAttemptNoticeEnqueue(
16194
+ getKanbanNudgeState(codeName),
16195
+ Date.now(),
16196
+ KANBAN_HYBRID_DEBOUNCE_MS,
16197
+ KANBAN_HYBRID_MAX_CADENCE_MS
16198
+ );
16199
+ if (!failureGate.attempt) return;
16173
16200
  if (!shouldNudgeUnchangedBoard(
16174
16201
  signature,
16175
16202
  getKanbanNudgeState(codeName),
@@ -16184,8 +16211,14 @@ async function maybeInjectKanbanCheck(codeName, agentId, actionableCount, signat
16184
16211
  return;
16185
16212
  }
16186
16213
  lastKanbanInjectAt.set(codeName, Date.now());
16214
+ const priorState = getKanbanNudgeState(codeName);
16187
16215
  const ok = await injectKanbanCheckViaDirectChat(codeName, agentId, actionableCount);
16188
16216
  if (ok) {
16217
+ if ((priorState?.failureCount ?? 0) > 0) {
16218
+ log(
16219
+ `[manager-worker] kanban notice rail RECOVERED for '${codeName}' after ${priorState?.failureCount} consecutive failures`
16220
+ );
16221
+ }
16189
16222
  setKanbanNudgeState(codeName, {
16190
16223
  signature,
16191
16224
  nudgedAt: Date.now(),
@@ -16193,7 +16226,42 @@ async function maybeInjectKanbanCheck(codeName, agentId, actionableCount, signat
16193
16226
  });
16194
16227
  return;
16195
16228
  }
16196
- log(`[manager-worker] kanban direct-chat enqueue failed for '${codeName}' - will re-nudge next tick`);
16229
+ const failureCount = (priorState?.failureCount ?? 0) + 1;
16230
+ setKanbanNudgeState(codeName, {
16231
+ signature: priorState?.signature ?? signature,
16232
+ nudgedAt: priorState?.nudgedAt ?? 0,
16233
+ ...priorState?.nudgeCount !== void 0 ? { nudgeCount: priorState.nudgeCount } : {},
16234
+ failureCount,
16235
+ failedAt: Date.now()
16236
+ });
16237
+ if (failureCount === KANBAN_NOTICE_BREAKER_THRESHOLD) {
16238
+ log(
16239
+ `[manager-worker] kanban notice rail BREAKER OPEN for '${codeName}' \u2014 ${failureCount} consecutive enqueue failures; retries continue at the capped interval`
16240
+ );
16241
+ getHostId().then((hostId) => {
16242
+ if (!hostId) return;
16243
+ return api.post("/host/events", {
16244
+ host_id: hostId,
16245
+ agent_code_name: codeName,
16246
+ event_type: "manager.kanban_notice_breaker_open",
16247
+ payload: {
16248
+ agent_code_name: codeName,
16249
+ agent_id: agentId,
16250
+ consecutive_failures: failureCount,
16251
+ retry_interval_ms: KANBAN_HYBRID_MAX_CADENCE_MS
16252
+ },
16253
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
16254
+ });
16255
+ }).catch((err) => {
16256
+ log(
16257
+ `[manager-worker] failed to forward kanban breaker event for '${codeName}': ${err.message}`
16258
+ );
16259
+ });
16260
+ return;
16261
+ }
16262
+ log(
16263
+ `[manager-worker] kanban direct-chat enqueue failed for '${codeName}' (${failureCount} consecutive) - backing off before the next attempt`
16264
+ );
16197
16265
  }
16198
16266
  var lastHarvestAt = /* @__PURE__ */ new Map();
16199
16267
  var HARVEST_INTERVAL_MS = 3 * 60 * 1e3;