@integrity-labs/agt-cli 0.28.1169 → 0.28.1171

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.
Files changed (30) hide show
  1. package/dist/bin/agt.js +6 -6
  2. package/dist/{chunk-IRTKOKUI.js → chunk-47P33SZF.js} +4 -1
  3. package/dist/chunk-47P33SZF.js.map +1 -0
  4. package/dist/{chunk-SJ7ZLQXN.js → chunk-DJNCIWVG.js} +2 -2
  5. package/dist/{chunk-LNWG6TUG.js → chunk-EK6JVOBH.js} +3 -3
  6. package/dist/{chunk-KDOITWQH.js → chunk-JB23A42P.js} +2 -2
  7. package/dist/{chunk-UE66JYZN.js → chunk-TJ4MVWNH.js} +5 -5
  8. package/dist/{claude-code-updater-7N6Z6VM3.js → claude-code-updater-PQYMHNQT.js} +3 -3
  9. package/dist/{claude-pair-runtime-4PUDIE65.js → claude-pair-runtime-RKDNAYEU.js} +3 -3
  10. package/dist/lib/manager-worker.js +134 -45
  11. package/dist/lib/manager-worker.js.map +1 -1
  12. package/dist/mcp/direct-chat-channel.js +3 -0
  13. package/dist/mcp/index.js +3 -0
  14. package/dist/mcp/origami.js +3 -0
  15. package/dist/mcp/slack-channel.js +3 -0
  16. package/dist/mcp/telegram-channel.js +3 -0
  17. package/dist/{persistent-session-GB4SLWPX.js → persistent-session-2365YL7P.js} +4 -4
  18. package/dist/{responsiveness-probe-GIID6ZH2.js → responsiveness-probe-7HARR32R.js} +4 -4
  19. package/dist/{session-auth-dead-ZTHC2VD4.js → session-auth-dead-2JJLKURE.js} +3 -3
  20. package/package.json +1 -1
  21. package/dist/chunk-IRTKOKUI.js.map +0 -1
  22. /package/dist/{chunk-SJ7ZLQXN.js.map → chunk-DJNCIWVG.js.map} +0 -0
  23. /package/dist/{chunk-LNWG6TUG.js.map → chunk-EK6JVOBH.js.map} +0 -0
  24. /package/dist/{chunk-KDOITWQH.js.map → chunk-JB23A42P.js.map} +0 -0
  25. /package/dist/{chunk-UE66JYZN.js.map → chunk-TJ4MVWNH.js.map} +0 -0
  26. /package/dist/{claude-code-updater-7N6Z6VM3.js.map → claude-code-updater-PQYMHNQT.js.map} +0 -0
  27. /package/dist/{claude-pair-runtime-4PUDIE65.js.map → claude-pair-runtime-RKDNAYEU.js.map} +0 -0
  28. /package/dist/{persistent-session-GB4SLWPX.js.map → persistent-session-2365YL7P.js.map} +0 -0
  29. /package/dist/{responsiveness-probe-GIID6ZH2.js.map → responsiveness-probe-7HARR32R.js.map} +0 -0
  30. /package/dist/{session-auth-dead-ZTHC2VD4.js.map → session-auth-dead-2JJLKURE.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  encodeClaudeProjectPath
3
- } from "./chunk-IRTKOKUI.js";
3
+ } from "./chunk-47P33SZF.js";
4
4
 
5
5
  // src/lib/daily-session.ts
6
6
  import { randomUUID } from "crypto";
@@ -235,4 +235,4 @@ export {
235
235
  peekCurrentSession,
236
236
  readDailySessionPin
237
237
  };
238
- //# sourceMappingURL=chunk-SJ7ZLQXN.js.map
238
+ //# sourceMappingURL=chunk-DJNCIWVG.js.map
@@ -4,7 +4,7 @@ import {
4
4
  rotateDailySession,
5
5
  sessionFileExists,
6
6
  todayLocalIso
7
- } from "./chunk-SJ7ZLQXN.js";
7
+ } from "./chunk-DJNCIWVG.js";
8
8
  import {
9
9
  classifyUnanswerablePane,
10
10
  findUsageLimitResetHint,
@@ -47,7 +47,7 @@ import {
47
47
  remoteMcpConnectionEnvInfix,
48
48
  remoteMcpConnectionLabel,
49
49
  remoteMcpConnectionScopedEnvVar
50
- } from "./chunk-IRTKOKUI.js";
50
+ } from "./chunk-47P33SZF.js";
51
51
  import {
52
52
  CLAUDE_CONFIG_DIR_ENV,
53
53
  archiveLegacyClaudeJson,
@@ -6130,4 +6130,4 @@ export {
6130
6130
  stopAllSessionsAndWait,
6131
6131
  getProjectDir
6132
6132
  };
6133
- //# sourceMappingURL=chunk-LNWG6TUG.js.map
6133
+ //# sourceMappingURL=chunk-EK6JVOBH.js.map
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-XWVM4KPK.js";
5
5
  import {
6
6
  FORCED_UPDATE_HARD_DEADLINE_MS
7
- } from "./chunk-IRTKOKUI.js";
7
+ } from "./chunk-47P33SZF.js";
8
8
  import {
9
9
  effectiveClaudeJsonPath
10
10
  } from "./chunk-EL5MWGGH.js";
@@ -722,4 +722,4 @@ export {
722
722
  probeClaudeInstalls,
723
723
  maybeUpdateClaudeCode
724
724
  };
725
- //# sourceMappingURL=chunk-KDOITWQH.js.map
725
+ //# sourceMappingURL=chunk-JB23A42P.js.map
@@ -16,11 +16,11 @@ import {
16
16
  parseEnvFileEntries,
17
17
  parseEnvIntegrations,
18
18
  shellQuote
19
- } from "./chunk-LNWG6TUG.js";
19
+ } from "./chunk-EK6JVOBH.js";
20
20
  import {
21
21
  readDailySessionPin,
22
22
  sessionTranscriptDir
23
- } from "./chunk-SJ7ZLQXN.js";
23
+ } from "./chunk-DJNCIWVG.js";
24
24
  import {
25
25
  classifyUnanswerablePane,
26
26
  isConsumerTermsDialogVisible,
@@ -90,7 +90,7 @@ import {
90
90
  scanConfigForLiteralSecrets,
91
91
  worseConnectivityOutcome,
92
92
  wrapScheduledTaskPrompt
93
- } from "./chunk-IRTKOKUI.js";
93
+ } from "./chunk-47P33SZF.js";
94
94
  import {
95
95
  claudeJsonPathFor,
96
96
  effectiveClaudeJsonPath,
@@ -8078,7 +8078,7 @@ function exchangeFailureKind(err) {
8078
8078
  }
8079
8079
 
8080
8080
  // src/lib/api-client.ts
8081
- var agtCliVersion = true ? "0.28.1169" : "dev";
8081
+ var agtCliVersion = true ? "0.28.1171" : "dev";
8082
8082
  var lastConfigHash = null;
8083
8083
  function setConfigHash(hash) {
8084
8084
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -13235,4 +13235,4 @@ export {
13235
13235
  managerInstallSystemUnitCommand,
13236
13236
  managerUninstallSystemUnitCommand
13237
13237
  };
13238
- //# sourceMappingURL=chunk-UE66JYZN.js.map
13238
+ //# sourceMappingURL=chunk-TJ4MVWNH.js.map
@@ -13,9 +13,9 @@ import {
13
13
  probeClaudeInstalls,
14
14
  readsAsNativeInstall,
15
15
  shouldRunClaudeCodeUpdater
16
- } from "./chunk-KDOITWQH.js";
16
+ } from "./chunk-JB23A42P.js";
17
17
  import "./chunk-XWVM4KPK.js";
18
- import "./chunk-IRTKOKUI.js";
18
+ import "./chunk-47P33SZF.js";
19
19
  import "./chunk-EL5MWGGH.js";
20
20
  import "./chunk-DGUM43GV.js";
21
21
  export {
@@ -34,4 +34,4 @@ export {
34
34
  readsAsNativeInstall,
35
35
  shouldRunClaudeCodeUpdater
36
36
  };
37
- //# sourceMappingURL=claude-code-updater-7N6Z6VM3.js.map
37
+ //# sourceMappingURL=claude-code-updater-PQYMHNQT.js.map
@@ -8,7 +8,7 @@ import {
8
8
  import {
9
9
  redactPaneFrame,
10
10
  sanitizeTerminalFrame
11
- } from "./chunk-IRTKOKUI.js";
11
+ } from "./chunk-47P33SZF.js";
12
12
  import {
13
13
  CLAUDE_CONFIG_DIR_ENV,
14
14
  claudeConfigDirFor,
@@ -321,7 +321,7 @@ async function spawnPairSession(session) {
321
321
  return { ok: true };
322
322
  } catch {
323
323
  }
324
- const { resolveClaudeBinary } = await import("./persistent-session-GB4SLWPX.js");
324
+ const { resolveClaudeBinary } = await import("./persistent-session-2365YL7P.js");
325
325
  const claudeBin = resolveClaudeBinary();
326
326
  const pairEnv = {
327
327
  ...process.env,
@@ -836,4 +836,4 @@ export {
836
836
  startClaudePair,
837
837
  submitClaudePairCode
838
838
  };
839
- //# sourceMappingURL=claude-pair-runtime-4PUDIE65.js.map
839
+ //# sourceMappingURL=claude-pair-runtime-RKDNAYEU.js.map
@@ -77,7 +77,7 @@ import {
77
77
  setConfigHash,
78
78
  shellGuard,
79
79
  tripClass
80
- } from "../chunk-UE66JYZN.js";
80
+ } from "../chunk-TJ4MVWNH.js";
81
81
  import {
82
82
  CLAUDE_CODE_SECURITY_FLOOR,
83
83
  SELF_UPDATE_TIMEOUTS,
@@ -91,7 +91,7 @@ import {
91
91
  runSafeCleanup,
92
92
  tightestDiskStat,
93
93
  withPackageCacheLock
94
- } from "../chunk-KDOITWQH.js";
94
+ } from "../chunk-JB23A42P.js";
95
95
  import {
96
96
  getProjectDir as getProjectDir2,
97
97
  getReadyTasks,
@@ -178,7 +178,7 @@ import {
178
178
  webFetchBaselineValue,
179
179
  webFetchRestartNeeded,
180
180
  writeEgressAllowlist
181
- } from "../chunk-LNWG6TUG.js";
181
+ } from "../chunk-EK6JVOBH.js";
182
182
  import {
183
183
  isAgentIdle,
184
184
  isStaleForToday,
@@ -187,7 +187,7 @@ import {
187
187
  sessionTranscriptDir,
188
188
  subagentActivityAgeSeconds,
189
189
  transcriptActivityAgeSeconds
190
- } from "../chunk-SJ7ZLQXN.js";
190
+ } from "../chunk-DJNCIWVG.js";
191
191
  import {
192
192
  classifyUnanswerablePane,
193
193
  focusedConfirmDialogBlock,
@@ -305,7 +305,7 @@ import {
305
305
  serializeAccountEnforcementMarker,
306
306
  stabiliseResetInstant,
307
307
  sumTranscriptUsageInWindow
308
- } from "../chunk-IRTKOKUI.js";
308
+ } from "../chunk-47P33SZF.js";
309
309
  import {
310
310
  CLAUDE_CONFIG_DIR_ENV,
311
311
  claudeConfigDirFor,
@@ -970,7 +970,9 @@ function claudeCodeUpgradeThrottled() {
970
970
 
971
971
  // src/lib/claude-pair-loop.ts
972
972
  var PAIR_LOOP_ACTIVE_INTERVAL_MS = 2e3;
973
- var PAIR_LOOP_IDLE_INTERVAL_MS = 1e4;
973
+ var PAIR_LOOP_IDLE_INTERVAL_MS = 3e4;
974
+ var PAIR_LOOP_FIRST_TICK_MS = 1e4;
975
+ var PAIR_LOOP_FAILURE_BASE_MS = 1e4;
974
976
  var PAIR_LOOP_MAX_BACKOFF_MS = 12e4;
975
977
  var PAIR_LOOP_ARMED_MAX_MS = 15 * 6e4;
976
978
  function pairLoopArmed(opts) {
@@ -993,7 +995,8 @@ function pairLoopArmed(opts) {
993
995
  function nextPairLoopDelayMs(armed, consecutiveFailures) {
994
996
  if (consecutiveFailures > 0) {
995
997
  const exp = Math.min(consecutiveFailures - 1, 16);
996
- return Math.min(PAIR_LOOP_IDLE_INTERVAL_MS * 2 ** exp, PAIR_LOOP_MAX_BACKOFF_MS);
998
+ const backoff = Math.min(PAIR_LOOP_FAILURE_BASE_MS * 2 ** exp, PAIR_LOOP_MAX_BACKOFF_MS);
999
+ return armed ? backoff : Math.max(backoff, PAIR_LOOP_IDLE_INTERVAL_MS);
997
1000
  }
998
1001
  return armed ? PAIR_LOOP_ACTIVE_INTERVAL_MS : PAIR_LOOP_IDLE_INTERVAL_MS;
999
1002
  }
@@ -1013,11 +1016,11 @@ var ClaudePairLoop = class {
1013
1016
  inFlightTick = null;
1014
1017
  setTimer;
1015
1018
  clearTimer;
1016
- /** Arm the loop. The first tick runs after one idle interval. Idempotent. */
1019
+ /** Arm the loop. The first tick runs after {@link PAIR_LOOP_FIRST_TICK_MS}. Idempotent. */
1017
1020
  start() {
1018
1021
  if (this.started) return;
1019
1022
  this.started = true;
1020
- this.schedule(PAIR_LOOP_IDLE_INTERVAL_MS);
1023
+ this.schedule(PAIR_LOOP_FIRST_TICK_MS);
1021
1024
  }
1022
1025
  /**
1023
1026
  * Disarm the loop. No new tick starts, and a callback from this generation
@@ -7452,6 +7455,21 @@ function createTickBoardFetcher(fetchBoard) {
7452
7455
  return inflight;
7453
7456
  };
7454
7457
  }
7458
+ async function fetchBoardThroughGate(opts) {
7459
+ const now = opts.now ?? Date.now;
7460
+ const token = opts.gate.beginFetch(opts.key);
7461
+ if (!opts.gate.shouldFetch(opts.key, now())) {
7462
+ const held = opts.held();
7463
+ if (held !== void 0) {
7464
+ opts.onDecision?.("gated");
7465
+ return held;
7466
+ }
7467
+ }
7468
+ const rows = await opts.fetch();
7469
+ opts.gate.markFetched(opts.key, token, now());
7470
+ opts.onDecision?.("fetched");
7471
+ return rows;
7472
+ }
7455
7473
 
7456
7474
  // src/lib/kanban-board-token.ts
7457
7475
  var BoardTokenCache = class {
@@ -7510,6 +7528,20 @@ var BoardTokenCache = class {
7510
7528
  }
7511
7529
  return rows;
7512
7530
  }
7531
+ /**
7532
+ * ENG-11720: the raw rows of the last board a successful request returned, or
7533
+ * undefined when none is held. Served by the `/host/my-kanban` fetch gate
7534
+ * while it is closed. Returns the held array itself: the one caller re-maps
7535
+ * it through `sanitizeBoardItem` on every serve, which is what keeps the
7536
+ * consumers from aliasing it (see the header).
7537
+ *
7538
+ * Counts nothing. The stats above describe what the conditional REQUEST did,
7539
+ * and a gated pass made no request — counting it as `unchanged` would report
7540
+ * a server-confirmed hit that never happened.
7541
+ */
7542
+ held(agentId) {
7543
+ return this.entries.get(agentId)?.rows;
7544
+ }
7513
7545
  /**
7514
7546
  * Drop an agent's board. Teardown must call this: a board left behind is
7515
7547
  * served to the agent if it is later RE-ADDED, which is exactly when its work
@@ -7583,6 +7615,13 @@ function createFetchGate(ttlMs) {
7583
7615
  }
7584
7616
  };
7585
7617
  }
7618
+ async function runIfDue(gate, key, fn, now = Date.now) {
7619
+ const token = gate.beginFetch(key);
7620
+ if (!gate.shouldFetch(key, now())) return { ran: false };
7621
+ const value = await fn();
7622
+ gate.markFetched(key, token, now());
7623
+ return { ran: true, value };
7624
+ }
7586
7625
  function forceGates(gates, agentId) {
7587
7626
  for (const gate of gates) {
7588
7627
  if (agentId === void 0) gate.forceAll();
@@ -13898,7 +13937,15 @@ function recordLatency(ms) {
13898
13937
  }
13899
13938
  }
13900
13939
  function startRealtimeKanban(config2) {
13901
- const { agentIds, onTodayItem, onCompletion, log: log2 } = config2;
13940
+ const { agentIds, onTodayItem, onCompletion, onBoardChanged, log: log2 } = config2;
13941
+ const boardChanged = (agentId) => {
13942
+ if (!onBoardChanged || !agentId) return;
13943
+ try {
13944
+ onBoardChanged(agentId);
13945
+ } catch (err) {
13946
+ log2(`[realtime] Kanban board-change handler error: ${err.message}`);
13947
+ }
13948
+ };
13902
13949
  if (agentIds.length === 0) return;
13903
13950
  const sb = ensureClient(config2);
13904
13951
  const filterStr = agentIds.length === 1 ? `agent_id=eq.${agentIds[0]}` : `agent_id=in.(${agentIds.join(",")})`;
@@ -13909,6 +13956,7 @@ function startRealtimeKanban(config2) {
13909
13956
  filter: filterStr
13910
13957
  }, (payload) => {
13911
13958
  const item = payload.new;
13959
+ boardChanged(item?.agent_id);
13912
13960
  if (item.status === "todo") {
13913
13961
  log2(`[realtime] New kanban item in 'todo': item_id=${item.id} agent=${item.agent_id}`);
13914
13962
  onTodayItem(item);
@@ -13921,6 +13969,7 @@ function startRealtimeKanban(config2) {
13921
13969
  }, (payload) => {
13922
13970
  const item = payload.new;
13923
13971
  const old = payload.old;
13972
+ boardChanged(item?.agent_id);
13924
13973
  if (item.status === "todo" && old.status !== "todo") {
13925
13974
  log2(`[realtime] Kanban item moved to 'todo': item_id=${item.id} agent=${item.agent_id}`);
13926
13975
  onTodayItem(item);
@@ -15082,7 +15131,7 @@ var pendingDayRolloverReset = /* @__PURE__ */ new Set();
15082
15131
  var dayRolloverInboundHold = /* @__PURE__ */ new Map();
15083
15132
  var INBOUND_HOLD_EPISODE_GAP_MS = 12e4;
15084
15133
  async function channelInboundActivityAgeSecondsFor(codeName) {
15085
- const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-GIID6ZH2.js");
15134
+ const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-7HARR32R.js");
15086
15135
  const newest = newestPendingInboundActivityMtimeMs(dirname11(paneLogPath(codeName)));
15087
15136
  if (newest === null) return null;
15088
15137
  return Math.max(0, Math.floor((Date.now() - newest) / 1e3));
@@ -15830,6 +15879,7 @@ function clearAgentCaches(agentId, codeName) {
15830
15879
  pendingRecoveryCost.delete(codeName);
15831
15880
  lastRefreshPayload.delete(agentId);
15832
15881
  boardTokenCache.forget(agentId);
15882
+ boardFetchGate.forget(agentId);
15833
15883
  refreshFetchGate.forget(agentId);
15834
15884
  memoriesFetchGate.forget(agentId);
15835
15885
  secretsFetchGate.forget(agentId);
@@ -15878,7 +15928,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
15878
15928
  var lastVersionCheckAt = 0;
15879
15929
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
15880
15930
  var lastResponsivenessProbeAt = 0;
15881
- var agtCliVersion = true ? "0.28.1169" : "dev";
15931
+ var agtCliVersion = true ? "0.28.1171" : "dev";
15882
15932
  function resolveBrewPath(execFileSync3) {
15883
15933
  try {
15884
15934
  const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -17627,6 +17677,11 @@ var integrationsFetchGate = createFetchGate(DESIRED_STATE_FETCH_TTL_MS);
17627
17677
  var lastIntegrationsPayload = /* @__PURE__ */ new Map();
17628
17678
  var quarantinedFetchGate = createFetchGate(DESIRED_STATE_FETCH_TTL_MS);
17629
17679
  var lastQuarantinedPayload = /* @__PURE__ */ new Map();
17680
+ var MY_KANBAN_FETCH_TTL_MS = 3e4;
17681
+ var boardFetchGate = createFetchGate(MY_KANBAN_FETCH_TTL_MS);
17682
+ var RECURRING_SPAWN_INTERVAL_MS = 6e4;
17683
+ var RECURRING_SPAWN_GATE_KEY = "host";
17684
+ var recurringSpawnGate = createFetchGate(RECURRING_SPAWN_INTERVAL_MS);
17630
17685
  function forceIntegrationsFetch(agentId) {
17631
17686
  integrationsFetchGate.forceNext(agentId);
17632
17687
  quarantinedFetchGate.forceNext(agentId);
@@ -17639,13 +17694,20 @@ var pollCycleQuarantinedFetches = 0;
17639
17694
  var pollCycleQuarantinedSkips = 0;
17640
17695
  var pollCycleMemoriesUnchanged = 0;
17641
17696
  var pollCycleMemoriesFull = 0;
17697
+ var pollCycleBoardFetched = 0;
17698
+ var pollCycleBoardGated = 0;
17642
17699
  var DESIRED_STATE_FETCH_GATES = [
17643
17700
  refreshFetchGate,
17644
17701
  memoriesFetchGate,
17645
17702
  secretsFetchGate,
17646
17703
  defaultSchedulesFetchGate,
17647
17704
  integrationsFetchGate,
17648
- quarantinedFetchGate
17705
+ quarantinedFetchGate,
17706
+ // ENG-11720. None of the lanes reaching here changes the board (the board
17707
+ // has its own push, `onBoardChanged`), so this entry is the maintenance rule
17708
+ // above applied, not a freshness requirement. Cost: one board round trip for
17709
+ // the pushed agent, which is the pre-gate every-pass behaviour at worst.
17710
+ boardFetchGate
17649
17711
  ];
17650
17712
  function forceRefreshFetch(agentId) {
17651
17713
  forceGates(DESIRED_STATE_FETCH_GATES, agentId);
@@ -17678,7 +17740,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
17678
17740
  if (codeNames.length === 0) return;
17679
17741
  void (async () => {
17680
17742
  try {
17681
- const { collectDiagnostics } = await import("../persistent-session-GB4SLWPX.js");
17743
+ const { collectDiagnostics } = await import("../persistent-session-2365YL7P.js");
17682
17744
  await api.post("/host/heartbeat", {
17683
17745
  host_id: hostId,
17684
17746
  agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
@@ -17821,7 +17883,7 @@ async function pollCycleInner() {
17821
17883
  }
17822
17884
  try {
17823
17885
  const { detectHostSecurity } = await import("../host-security-KQYYZZVW.js");
17824
- const { collectDiagnostics } = await import("../persistent-session-GB4SLWPX.js");
17886
+ const { collectDiagnostics } = await import("../persistent-session-2365YL7P.js");
17825
17887
  const diagCodeNames = [...agentState.persistentSessionAgents];
17826
17888
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor) : void 0;
17827
17889
  let tailscaleHostname;
@@ -18025,7 +18087,7 @@ async function pollCycleInner() {
18025
18087
  setConfigHash(hbResp?.config_hash ?? null);
18026
18088
  try {
18027
18089
  const desiredClaudeCodeVersion = hbResp?.desired_claude_code_version?.trim();
18028
- const { maybeUpdateClaudeCode, shouldRunClaudeCodeUpdater } = await import("../claude-code-updater-7N6Z6VM3.js");
18090
+ const { maybeUpdateClaudeCode, shouldRunClaudeCodeUpdater } = await import("../claude-code-updater-PQYMHNQT.js");
18029
18091
  const securityFloor = currentSecurityFloor();
18030
18092
  claudeUpdaterInFlight = true;
18031
18093
  if (desiredClaudeCodeVersion && (claudePairLoop.busy || claudePairingInProgress())) {
@@ -18060,7 +18122,7 @@ async function pollCycleInner() {
18060
18122
  collectPanelessActivityProbes,
18061
18123
  getResponsivenessIntervalMs,
18062
18124
  occupancyQualificationClassifications
18063
- } = await import("../responsiveness-probe-GIID6ZH2.js");
18125
+ } = await import("../responsiveness-probe-7HARR32R.js");
18064
18126
  const probeIntervalMs = getResponsivenessIntervalMs();
18065
18127
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
18066
18128
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -18177,7 +18239,7 @@ async function pollCycleInner() {
18177
18239
  collectResponsivenessProbes,
18178
18240
  livePendingInboundOldestAgeSeconds,
18179
18241
  parkPendingInbound
18180
- } = await import("../responsiveness-probe-GIID6ZH2.js");
18242
+ } = await import("../responsiveness-probe-7HARR32R.js");
18181
18243
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-M6AFZWNU.js");
18182
18244
  const wedgeNow = /* @__PURE__ */ new Date();
18183
18245
  const liveAgents = agentState.persistentSessionAgents;
@@ -18463,7 +18525,7 @@ async function pollCycleInner() {
18463
18525
  }
18464
18526
  }
18465
18527
  );
18466
- const { parkPendingInbound } = await import("../responsiveness-probe-GIID6ZH2.js");
18528
+ const { parkPendingInbound } = await import("../responsiveness-probe-7HARR32R.js");
18467
18529
  const { parked, deadLettered } = parkPendingInbound(codeName, new Date(fatalNowMs));
18468
18530
  paneFatalStreak.delete(codeName);
18469
18531
  paneFatalRestarts.set(codeName, [...history, fatalNowMs]);
@@ -18494,7 +18556,7 @@ async function pollCycleInner() {
18494
18556
  TRANSCRIPT_MOUNT_ESCALATION_REFRESH_MS,
18495
18557
  bindSourceEscalations
18496
18558
  } = await import("../transcript-mount-health-OHE6IVJV.js");
18497
- const { transcriptBindSourcesFor, ensureTranscriptBindSources } = await import("../persistent-session-GB4SLWPX.js");
18559
+ const { transcriptBindSourcesFor, ensureTranscriptBindSources } = await import("../persistent-session-2365YL7P.js");
18498
18560
  const mountConfig = resolveTranscriptMountConfig();
18499
18561
  const liveAgents = agentState.persistentSessionAgents;
18500
18562
  for (const tracked of [
@@ -18659,7 +18721,7 @@ async function pollCycleInner() {
18659
18721
  }
18660
18722
  try {
18661
18723
  const { scrapeMcpFailedBannerCount } = await import("../pane-mcp-banner-scraper-VR5QGP3J.js");
18662
- const { probeSessionAuth } = await import("../session-auth-dead-ZTHC2VD4.js");
18724
+ const { probeSessionAuth } = await import("../session-auth-dead-2JJLKURE.js");
18663
18725
  const observations = [];
18664
18726
  const pendingCacheCommits = [];
18665
18727
  const modelApiErrorReportingOn = hostFlagStore().getBoolean("model-api-error-reporting");
@@ -19062,6 +19124,8 @@ async function pollCycleInner() {
19062
19124
  pollCycleQuarantinedSkips = 0;
19063
19125
  pollCycleMemoriesUnchanged = 0;
19064
19126
  pollCycleMemoriesFull = 0;
19127
+ pollCycleBoardFetched = 0;
19128
+ pollCycleBoardGated = 0;
19065
19129
  boardTokenCache.resetStats();
19066
19130
  for (const agent of processOrder) {
19067
19131
  if (restartInFlight.has(agent.agent_id)) {
@@ -19103,7 +19167,7 @@ async function pollCycleInner() {
19103
19167
  }
19104
19168
  const boardStats = boardTokenCache.stats();
19105
19169
  log(
19106
- `[poll-cycle] agents=${processOrder.length} refresh_fetched=${pollCycleFetches} refresh_skipped=${pollCycleFetchSkips} memories_unchanged=${pollCycleMemoriesUnchanged} memories_full=${pollCycleMemoriesFull} board_unchanged=${boardStats.unchanged} board_full=${boardStats.full} board_refetch=${boardStats.refetch} integrations_fetched=${pollCycleIntegrationsFetches} integrations_skipped=${pollCycleIntegrationsSkips} quarantined_fetched=${pollCycleQuarantinedFetches} quarantined_skipped=${pollCycleQuarantinedSkips} duration_ms=${Date.now() - cycleStartedAt}`
19170
+ `[poll-cycle] agents=${processOrder.length} refresh_fetched=${pollCycleFetches} refresh_skipped=${pollCycleFetchSkips} memories_unchanged=${pollCycleMemoriesUnchanged} memories_full=${pollCycleMemoriesFull} board_unchanged=${boardStats.unchanged} board_full=${boardStats.full} board_refetch=${boardStats.refetch} board_fetched=${pollCycleBoardFetched} board_gated=${pollCycleBoardGated} integrations_fetched=${pollCycleIntegrationsFetches} integrations_skipped=${pollCycleIntegrationsSkips} quarantined_fetched=${pollCycleQuarantinedFetches} quarantined_skipped=${pollCycleQuarantinedSkips} duration_ms=${Date.now() - cycleStartedAt}`
19107
19171
  );
19108
19172
  void maybeReportActivityCache({ api, log });
19109
19173
  const crossAgentPrune = managedPruneLedger.summarize();
@@ -19340,9 +19404,13 @@ async function pollCycleInner() {
19340
19404
  ensureRealtimeKanbanStarted(agentStates);
19341
19405
  ensureRealtimeIntegrationContextStarted(agentStates);
19342
19406
  try {
19343
- const spawnData = await api.post("/host/kanban/recurring/spawn");
19344
- if (spawnData.spawned > 0) {
19345
- log(`Spawned ${spawnData.spawned} recurring kanban item(s)`);
19407
+ const spawn = await runIfDue(
19408
+ recurringSpawnGate,
19409
+ RECURRING_SPAWN_GATE_KEY,
19410
+ () => api.post("/host/kanban/recurring/spawn")
19411
+ );
19412
+ if (spawn.ran && spawn.value.spawned > 0) {
19413
+ log(`Spawned ${spawn.value.spawned} recurring kanban item(s)`);
19346
19414
  }
19347
19415
  } catch {
19348
19416
  }
@@ -21491,23 +21559,35 @@ async function processAgent(agent, agentStates, managedToolkits) {
21491
21559
  }
21492
21560
  }
21493
21561
  const fetchTickBoard = createTickBoardFetcher(async () => {
21494
- const knownToken = boardTokenCache.tokenFor(agent.agent_id);
21495
- const post = (token) => api.post("/host/my-kanban", {
21496
- agent_id: agent.agent_id,
21497
- // ENG-9585: this is the ONLY caller that polls (every ~10s, per agent),
21498
- // and it reads exactly `BoardItem`. `description` and `notes` are 57.8%
21499
- // of the payload and are read here by nothing — but the `kanban_list` MCP
21500
- // tool and `agt kanban` DO read them, so the route cannot simply drop
21501
- // them. Asking for the lean shape is this caller saying what it needs;
21502
- // every other caller keeps the full payload by default.
21503
- detail: "board",
21504
- ...token ? { known_token: token } : {}
21562
+ const rawRows = await fetchBoardThroughGate({
21563
+ key: agent.agent_id,
21564
+ gate: boardFetchGate,
21565
+ held: () => boardTokenCache.held(agent.agent_id),
21566
+ onDecision: (decision) => {
21567
+ if (decision === "gated") pollCycleBoardGated += 1;
21568
+ else pollCycleBoardFetched += 1;
21569
+ },
21570
+ fetch: async () => {
21571
+ const knownToken = boardTokenCache.tokenFor(agent.agent_id);
21572
+ const post = (token) => api.post("/host/my-kanban", {
21573
+ agent_id: agent.agent_id,
21574
+ // ENG-9585: this is the ONLY caller that polls (every ~10s, per agent),
21575
+ // and it reads exactly `BoardItem`. `description` and `notes` are 57.8%
21576
+ // of the payload and are read here by nothing — but the `kanban_list` MCP
21577
+ // tool and `agt kanban` DO read them, so the route cannot simply drop
21578
+ // them. Asking for the lean shape is this caller saying what it needs;
21579
+ // every other caller keeps the full payload by default.
21580
+ detail: "board",
21581
+ ...token ? { known_token: token } : {}
21582
+ });
21583
+ let rows = boardTokenCache.resolve(agent.agent_id, await post(knownToken));
21584
+ if (rows === null) {
21585
+ rows = boardTokenCache.resolve(agent.agent_id, await post(void 0)) ?? [];
21586
+ }
21587
+ return rows;
21588
+ }
21505
21589
  });
21506
- let rows = boardTokenCache.resolve(agent.agent_id, await post(knownToken));
21507
- if (rows === null) {
21508
- rows = boardTokenCache.resolve(agent.agent_id, await post(void 0)) ?? [];
21509
- }
21510
- return rows.map(sanitizeBoardItem);
21590
+ return rawRows.map(sanitizeBoardItem);
21511
21591
  });
21512
21592
  let boardItems = [];
21513
21593
  let boardItemsStale = false;
@@ -22110,6 +22190,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
22110
22190
  reason: `Timed out \u2014 in progress for ${age} minutes with no update`
22111
22191
  });
22112
22192
  reapAction = reapResult.action ?? null;
22193
+ boardFetchGate.forceNext(agentId);
22113
22194
  log(
22114
22195
  `Reap result for item_id=${item.id}: updated=${reapResult.updated} action=${reapResult.action ?? reapResult.reason ?? "none"}`
22115
22196
  );
@@ -23329,7 +23410,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
23329
23410
  try {
23330
23411
  const freshId = rotateSessionForWedge(codeName);
23331
23412
  consecutiveWedgeCycles.delete(codeName);
23332
- const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-GIID6ZH2.js");
23413
+ const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-7HARR32R.js");
23333
23414
  const { parked, deadLettered } = parkForRestart(codeName, /* @__PURE__ */ new Date());
23334
23415
  const parkNote = parked > 0 ? `, ${parked} inbound parked` : "";
23335
23416
  const deadNote = deadLettered > 0 ? `, ${deadLettered} undeliverable dead-lettered` : "";
@@ -23372,7 +23453,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
23372
23453
  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}`));
23373
23454
  void (async () => {
23374
23455
  try {
23375
- const { collectDiagnostics } = await import("../persistent-session-GB4SLWPX.js");
23456
+ const { collectDiagnostics } = await import("../persistent-session-2365YL7P.js");
23376
23457
  await api.post("/host/heartbeat", {
23377
23458
  host_id: hostId,
23378
23459
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
@@ -23423,7 +23504,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
23423
23504
  }
23424
23505
  try {
23425
23506
  const hostId = await getHostId();
23426
- const { collectDiagnostics } = await import("../persistent-session-GB4SLWPX.js");
23507
+ const { collectDiagnostics } = await import("../persistent-session-2365YL7P.js");
23427
23508
  await api.post("/host/heartbeat", {
23428
23509
  host_id: hostId,
23429
23510
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
@@ -23495,6 +23576,14 @@ function ensureRealtimeKanbanStarted(agentStates) {
23495
23576
  supabaseAnonKey: exchange.supabaseAnonKey,
23496
23577
  token: exchange.token,
23497
23578
  agentIds: activeAgentIds,
23579
+ // ENG-11720: what makes the `/host/my-kanban` gate safe. Any change to one
23580
+ // of this agent's cards reopens it, so the next pass fetches — no early
23581
+ // poll, because a card change is not urgent enough to pull a whole cycle
23582
+ // forward, and forces are counters, so a burst of UPDATEs (embedding
23583
+ // writes, notes) still costs at most one fetch per pass.
23584
+ onBoardChanged: (agentId) => {
23585
+ boardFetchGate.forceNext(agentId);
23586
+ },
23498
23587
  onTodayItem: (item) => {
23499
23588
  if (item.source_type === "scheduled_task") return;
23500
23589
  const agent = agentStates.find((a) => a.agentId === item.agent_id);
@@ -24117,7 +24206,7 @@ async function processClaudePairSessions(agents) {
24117
24206
  snapshotPairConfig,
24118
24207
  // ENG-11659: result -> report body + the manager.log line that records it.
24119
24208
  planPairStartReport
24120
- } = await import("../claude-pair-runtime-4PUDIE65.js");
24209
+ } = await import("../claude-pair-runtime-RKDNAYEU.js");
24121
24210
  const { resetClaudeSignin, describeSigninResetForLog, describeSigninResetFailure } = await import("../claude-signin-reset-EF3UO5IK.js");
24122
24211
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
24123
24212
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);