@integrity-labs/agt-cli 0.28.1149 → 0.28.1151

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-LMJH26IW.js";
43
+ } from "../chunk-MVZDF2MR.js";
44
44
  import {
45
45
  getProjectDir,
46
46
  isSessionResumeDisabled,
@@ -5512,7 +5512,7 @@ import { execFileSync, execSync } from "child_process";
5512
5512
  import { existsSync as existsSync11, realpathSync as realpathSync2 } from "fs";
5513
5513
  import chalk18 from "chalk";
5514
5514
  import ora16 from "ora";
5515
- var cliVersion = true ? "0.28.1149" : "dev";
5515
+ var cliVersion = true ? "0.28.1151" : "dev";
5516
5516
  async function fetchLatestVersion() {
5517
5517
  const host2 = getHost();
5518
5518
  if (!host2) return null;
@@ -6772,7 +6772,7 @@ function handleError(err) {
6772
6772
  }
6773
6773
 
6774
6774
  // src/bin/agt.ts
6775
- var cliVersion2 = true ? "0.28.1149" : "dev";
6775
+ var cliVersion2 = true ? "0.28.1151" : "dev";
6776
6776
  var program = new Command();
6777
6777
  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");
6778
6778
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -8078,7 +8078,7 @@ function exchangeFailureKind(err) {
8078
8078
  }
8079
8079
 
8080
8080
  // src/lib/api-client.ts
8081
- var agtCliVersion = true ? "0.28.1149" : "dev";
8081
+ var agtCliVersion = true ? "0.28.1151" : "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-LMJH26IW.js.map
13238
+ //# sourceMappingURL=chunk-MVZDF2MR.js.map
@@ -77,7 +77,7 @@ import {
77
77
  setConfigHash,
78
78
  shellGuard,
79
79
  tripClass
80
- } from "../chunk-LMJH26IW.js";
80
+ } from "../chunk-MVZDF2MR.js";
81
81
  import {
82
82
  CLAUDE_CODE_SECURITY_FLOOR,
83
83
  compareVersions
@@ -957,6 +957,156 @@ function claudeCodeUpgradeThrottled() {
957
957
  }
958
958
  }
959
959
 
960
+ // src/lib/claude-pair-loop.ts
961
+ var PAIR_LOOP_ACTIVE_INTERVAL_MS = 2e3;
962
+ var PAIR_LOOP_IDLE_INTERVAL_MS = 1e4;
963
+ var PAIR_LOOP_MAX_BACKOFF_MS = 12e4;
964
+ var PAIR_LOOP_ARMED_MAX_MS = 15 * 6e4;
965
+ function pairLoopArmed(opts) {
966
+ const max = opts.maxArmedMs ?? PAIR_LOOP_ARMED_MAX_MS;
967
+ const live = /* @__PURE__ */ new Set([...opts.spawnedPairIds, ...opts.pendingPairIds]);
968
+ for (const id of [...opts.firstSeenMs.keys()]) {
969
+ if (!live.has(id)) opts.firstSeenMs.delete(id);
970
+ }
971
+ let fresh = false;
972
+ for (const id of live) {
973
+ let seen = opts.firstSeenMs.get(id);
974
+ if (seen === void 0) {
975
+ seen = opts.nowMs;
976
+ opts.firstSeenMs.set(id, seen);
977
+ }
978
+ if (opts.nowMs - seen < max) fresh = true;
979
+ }
980
+ return fresh;
981
+ }
982
+ function nextPairLoopDelayMs(armed, consecutiveFailures) {
983
+ if (consecutiveFailures > 0) {
984
+ const exp = Math.min(consecutiveFailures - 1, 16);
985
+ return Math.min(PAIR_LOOP_IDLE_INTERVAL_MS * 2 ** exp, PAIR_LOOP_MAX_BACKOFF_MS);
986
+ }
987
+ return armed ? PAIR_LOOP_ACTIVE_INTERVAL_MS : PAIR_LOOP_IDLE_INTERVAL_MS;
988
+ }
989
+ var ClaudePairLoop = class {
990
+ constructor(deps) {
991
+ this.deps = deps;
992
+ this.setTimer = deps.setTimer ?? ((fn, ms) => setTimeout(fn, ms));
993
+ this.clearTimer = deps.clearTimer ?? ((h) => clearTimeout(h));
994
+ }
995
+ timer = null;
996
+ inFlight = false;
997
+ started = false;
998
+ consecutiveFailures = 0;
999
+ // Bumped by stop(): a timer callback from an earlier start() whose tick is
1000
+ // still in flight must not schedule a second timer chain after a restart.
1001
+ generation = 0;
1002
+ inFlightTick = null;
1003
+ setTimer;
1004
+ clearTimer;
1005
+ /** Arm the loop. The first tick runs after one idle interval. Idempotent. */
1006
+ start() {
1007
+ if (this.started) return;
1008
+ this.started = true;
1009
+ this.schedule(PAIR_LOOP_IDLE_INTERVAL_MS);
1010
+ }
1011
+ /**
1012
+ * Disarm the loop. No new tick starts, and a callback from this generation
1013
+ * will not reschedule. Returns a promise that settles when a tick already in
1014
+ * flight has finished (immediately if none), so shutdown can wait for it
1015
+ * before sweeping tmux sessions.
1016
+ */
1017
+ stop() {
1018
+ this.started = false;
1019
+ this.generation += 1;
1020
+ if (this.timer != null) this.clearTimer(this.timer);
1021
+ this.timer = null;
1022
+ const pending2 = this.inFlightTick;
1023
+ return pending2 ? pending2.then(() => void 0, () => void 0) : Promise.resolve();
1024
+ }
1025
+ /** True while started. A tick in flight checks this before spawning anything new. */
1026
+ get accepting() {
1027
+ return this.started;
1028
+ }
1029
+ get failures() {
1030
+ return this.consecutiveFailures;
1031
+ }
1032
+ /** True while a tick is running. Set synchronously before the tick starts. */
1033
+ get busy() {
1034
+ return this.inFlight;
1035
+ }
1036
+ /** One guarded pass. Safe to call from anywhere; never overlaps itself. */
1037
+ async runOnce() {
1038
+ if (!this.deps.canRun()) return "skipped-not-running";
1039
+ if (this.inFlight) return "skipped-in-flight";
1040
+ this.inFlight = true;
1041
+ try {
1042
+ const tick = this.deps.tick();
1043
+ this.inFlightTick = tick;
1044
+ await tick;
1045
+ if (this.consecutiveFailures > 0) {
1046
+ this.deps.log(`[claude-pair] loop recovered after ${this.consecutiveFailures} failed tick(s)`);
1047
+ }
1048
+ this.consecutiveFailures = 0;
1049
+ return "ran";
1050
+ } catch (err) {
1051
+ this.consecutiveFailures += 1;
1052
+ if (this.consecutiveFailures === 1 || this.consecutiveFailures % 10 === 0) {
1053
+ this.deps.log(
1054
+ `[claude-pair] poll failed (${this.consecutiveFailures} in a row): ${err?.message ?? String(err)}`
1055
+ );
1056
+ }
1057
+ return "failed";
1058
+ } finally {
1059
+ this.inFlight = false;
1060
+ this.inFlightTick = null;
1061
+ }
1062
+ }
1063
+ schedule(ms) {
1064
+ if (!this.started) return;
1065
+ const gen = this.generation;
1066
+ const h = this.setTimer(() => {
1067
+ this.timer = null;
1068
+ if (gen !== this.generation) return;
1069
+ void this.runOnce().finally(() => {
1070
+ if (gen !== this.generation) return;
1071
+ let armed = false;
1072
+ try {
1073
+ armed = this.deps.isArmed();
1074
+ } catch {
1075
+ armed = false;
1076
+ }
1077
+ this.schedule(nextPairLoopDelayMs(armed, this.consecutiveFailures));
1078
+ });
1079
+ }, ms);
1080
+ if (h && typeof h === "object" && typeof h.unref === "function") h.unref();
1081
+ this.timer = h;
1082
+ }
1083
+ };
1084
+ var PairRetryBackoff = class {
1085
+ state = /* @__PURE__ */ new Map();
1086
+ /** True while this pair is inside its backoff window: skip it this tick. */
1087
+ shouldSkip(pairId, nowMs) {
1088
+ const s = this.state.get(pairId);
1089
+ return !!s && nowMs < s.notBeforeMs;
1090
+ }
1091
+ recordFailure(pairId, nowMs) {
1092
+ const failures = (this.state.get(pairId)?.failures ?? 0) + 1;
1093
+ this.state.set(pairId, { failures, notBeforeMs: nowMs + nextPairLoopDelayMs(true, failures) });
1094
+ return failures;
1095
+ }
1096
+ /** A dispatch that completed clears the pair's backoff. */
1097
+ recordSuccess(pairId) {
1098
+ this.state.delete(pairId);
1099
+ }
1100
+ /** Forget pairs that are neither spawned nor pending any more. */
1101
+ prune(liveIds) {
1102
+ const live = new Set(liveIds);
1103
+ for (const id of [...this.state.keys()]) if (!live.has(id)) this.state.delete(id);
1104
+ }
1105
+ failuresFor(pairId) {
1106
+ return this.state.get(pairId)?.failures ?? 0;
1107
+ }
1108
+ };
1109
+
960
1110
  // src/lib/mcp-config-drift.ts
961
1111
  import { createHash } from "crypto";
962
1112
  function decideMcpDriftAction(currentHash, knownHash) {
@@ -15649,7 +15799,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
15649
15799
  var lastVersionCheckAt = 0;
15650
15800
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
15651
15801
  var lastResponsivenessProbeAt = 0;
15652
- var agtCliVersion = true ? "0.28.1149" : "dev";
15802
+ var agtCliVersion = true ? "0.28.1151" : "dev";
15653
15803
  function resolveBrewPath(execFileSync3) {
15654
15804
  try {
15655
15805
  const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -17767,7 +17917,12 @@ async function pollCycleInner() {
17767
17917
  try {
17768
17918
  const desiredClaudeCodeVersion = hbResp?.desired_claude_code_version?.trim();
17769
17919
  const { maybeUpdateClaudeCode, shouldRunClaudeCodeUpdater } = await import("../claude-code-updater-JXL4CM2V.js");
17770
- if (desiredClaudeCodeVersion && shouldRunClaudeCodeUpdater({
17920
+ claudeUpdaterInFlight = true;
17921
+ if (desiredClaudeCodeVersion && (claudePairLoop.busy || claudePairingInProgress())) {
17922
+ log(
17923
+ claudePairingInProgress() ? "[claude-code-updater] Claude re-login in progress on this host, deferring to a later cycle" : "[claude-code-updater] a claude-pair poll is mid-flight (no re-login), deferring to the next cycle"
17924
+ );
17925
+ } else if (desiredClaudeCodeVersion && shouldRunClaudeCodeUpdater({
17771
17926
  desiredVersion: desiredClaudeCodeVersion,
17772
17927
  installedVersion: cachedFrameworkVersion,
17773
17928
  windowGate: decideMaintenanceWindowGate({ window: cachedMaintenanceWindow, now: /* @__PURE__ */ new Date() })
@@ -17780,6 +17935,8 @@ async function pollCycleInner() {
17780
17935
  }
17781
17936
  } catch (err) {
17782
17937
  log(`Claude Code updater error: ${err.message}`);
17938
+ } finally {
17939
+ claudeUpdaterInFlight = false;
17783
17940
  }
17784
17941
  } catch (err) {
17785
17942
  setConfigHash(null);
@@ -18460,6 +18617,10 @@ async function pollCycleInner() {
18460
18617
  }
18461
18618
  const data = await api.post("/host/agents", { host_id: hostId });
18462
18619
  const agents = data.agents ?? [];
18620
+ pairableAgentsSnapshot = agents.map((a) => ({
18621
+ agentId: a.agent_id,
18622
+ codeName: a.code_name
18623
+ }));
18463
18624
  hostFlagStore().setMirrorAgentIds(agents.map((a) => a.agent_id));
18464
18625
  if (agents.length > 0) {
18465
18626
  if (consecutiveEmptyAgentPolls > 0) {
@@ -18881,14 +19042,6 @@ async function pollCycleInner() {
18881
19042
  clearAgentCaches(prev.agentId, prev.codeName);
18882
19043
  }
18883
19044
  }
18884
- try {
18885
- await processClaudePairSessions(agents.map((a) => ({
18886
- agentId: a.agent_id,
18887
- codeName: a.code_name
18888
- })));
18889
- } catch (err) {
18890
- log(`[claude-pair] poll failed: ${err.message}`);
18891
- }
18892
19045
  if (Date.now() - lastChannelSweepAt >= CHANNEL_SWEEP_INTERVAL_MS) {
18893
19046
  lastChannelSweepAt = Date.now();
18894
19047
  const agentCodeNames = new Set(
@@ -22269,7 +22422,11 @@ async function ensurePersistentSessionUnchecked(agent, tasks, boardItems, refres
22269
22422
  const currentPolicyId = currentPolicyModel ? modelPolicy?.policyId ?? null : null;
22270
22423
  const recordedAuthTuple = claudeAuthTupleBySession.get(codeName);
22271
22424
  const recordedPolicyModel = modelPolicyModelBySession.get(codeName);
22272
- if (recordedAuthTuple && recordedAuthTuple !== currentAuthTuple && isSessionHealthy(codeName)) {
22425
+ const authTupleChanged = Boolean(recordedAuthTuple && recordedAuthTuple !== currentAuthTuple);
22426
+ if (authTupleChanged && claudePairingInProgress()) {
22427
+ log(`[${codeName}] auth tuple changed while a Claude re-login is in progress, deferring the restart to the next cycle`);
22428
+ }
22429
+ if (recordedAuthTuple && recordedAuthTuple !== currentAuthTuple && !claudePairingInProgress() && isSessionHealthy(codeName)) {
22273
22430
  const authTupleDiff = diffAuthTuples(recordedAuthTuple, currentAuthTuple);
22274
22431
  log(
22275
22432
  `[persistent-session] Auth config changed for '${codeName}' (${recordedAuthTuple} \u2192 ${currentAuthTuple}) \u2014 ${authTupleDiff.summary} \u2014 restarting session`
@@ -22280,7 +22437,9 @@ async function ensurePersistentSessionUnchecked(agent, tasks, boardItems, refres
22280
22437
  previousModel: recordedPolicyModel,
22281
22438
  currentModel: currentPolicyModel
22282
22439
  });
22283
- if (policyNotice && isSessionHealthy(codeName)) {
22440
+ let restartNoticeLanded = false;
22441
+ const noticeAlreadyDelivered = restartNoticeDeliveredFor.get(codeName) === currentAuthTuple;
22442
+ if (policyNotice && isSessionHealthy(codeName) && !noticeAlreadyDelivered) {
22284
22443
  const status = await injectMessageWithStatus(
22285
22444
  codeName,
22286
22445
  "system",
@@ -22293,6 +22452,7 @@ async function ensurePersistentSessionUnchecked(agent, tasks, boardItems, refres
22293
22452
  log
22294
22453
  ).catch(() => ({ delivered: false, fallbackUsed: false }));
22295
22454
  if (status.fallbackUsed) {
22455
+ restartNoticeLanded = true;
22296
22456
  await new Promise((r) => setTimeout(r, 3e3));
22297
22457
  } else {
22298
22458
  log(
@@ -22300,18 +22460,35 @@ async function ensurePersistentSessionUnchecked(agent, tasks, boardItems, refres
22300
22460
  );
22301
22461
  }
22302
22462
  }
22303
- stopPersistentSessionAndForgetMcpBaseline(codeName, "auth-tuple-change", void 0, void 0, {
22304
- reason: authTupleDiff.summary,
22305
- detail: {
22306
- auth_tuple: {
22307
- changed: authTupleDiff.changed,
22308
- unchanged: authTupleDiff.unchanged,
22309
- components: authTupleDiff.components
22310
- }
22463
+ if (claudePairingInProgress()) {
22464
+ if (restartNoticeLanded) {
22465
+ restartNoticeDeliveredFor.set(codeName, currentAuthTuple);
22466
+ await injectMessageWithStatus(
22467
+ codeName,
22468
+ "system",
22469
+ "Update: the restart announced above is postponed for a moment while a Claude sign-in finishes on this host. Carry on; it will happen shortly, without a further notice.",
22470
+ { task_name: "model-policy-restart-postponed" },
22471
+ log
22472
+ ).catch(() => void 0);
22311
22473
  }
22312
- });
22313
- agentState.persistentSessionAgents.delete(codeName);
22314
- restartTrigger = "auth-tuple";
22474
+ log(
22475
+ `[${codeName}] Claude re-login in progress, deferring the auth-tuple restart to the next cycle` + (restartNoticeLanded || noticeAlreadyDelivered ? " (restart notice already delivered, not re-sent)" : "")
22476
+ );
22477
+ } else {
22478
+ restartNoticeDeliveredFor.delete(codeName);
22479
+ stopPersistentSessionAndForgetMcpBaseline(codeName, "auth-tuple-change", void 0, void 0, {
22480
+ reason: authTupleDiff.summary,
22481
+ detail: {
22482
+ auth_tuple: {
22483
+ changed: authTupleDiff.changed,
22484
+ unchanged: authTupleDiff.unchanged,
22485
+ components: authTupleDiff.components
22486
+ }
22487
+ }
22488
+ });
22489
+ agentState.persistentSessionAgents.delete(codeName);
22490
+ restartTrigger = "auth-tuple";
22491
+ }
22315
22492
  }
22316
22493
  const staleForToday = isStaleForToday(codeName, /* @__PURE__ */ new Date(), agentTimezone);
22317
22494
  if (!staleForToday) pendingDayRolloverReset.delete(codeName);
@@ -23771,6 +23948,47 @@ var boardTokenCache = new BoardTokenCache();
23771
23948
  var notifyBoardCache = /* @__PURE__ */ new Map();
23772
23949
  var notifiedWaitingHumanIds = /* @__PURE__ */ new Map();
23773
23950
  var spawnedPairIds = /* @__PURE__ */ new Set();
23951
+ var pairableAgentsSnapshot = [];
23952
+ var lastPairPendingIds = [];
23953
+ var pairFirstSeenMs = /* @__PURE__ */ new Map();
23954
+ function claudePairLoopArmed() {
23955
+ return pairLoopArmed({
23956
+ spawnedPairIds,
23957
+ pendingPairIds: lastPairPendingIds,
23958
+ firstSeenMs: pairFirstSeenMs,
23959
+ nowMs: Date.now()
23960
+ });
23961
+ }
23962
+ var pairRetryBackoff = new PairRetryBackoff();
23963
+ var restartNoticeDeliveredFor = /* @__PURE__ */ new Map();
23964
+ var claudeUpdaterInFlight = false;
23965
+ async function runClaudePairTick() {
23966
+ if (pairableAgentsSnapshot.length === 0 && spawnedPairIds.size === 0) lastPairPendingIds = [];
23967
+ if (claudeUpdaterInFlight) return;
23968
+ await processClaudePairSessions(pairableAgentsSnapshot);
23969
+ pairRetryBackoff.prune([...spawnedPairIds, ...lastPairPendingIds]);
23970
+ }
23971
+ async function _claudePairTickForTests(agents) {
23972
+ const prevRunning = running;
23973
+ running = true;
23974
+ claudePairLoop.start();
23975
+ pairableAgentsSnapshot = [...agents];
23976
+ try {
23977
+ await runClaudePairTick();
23978
+ } finally {
23979
+ void claudePairLoop.stop();
23980
+ running = prevRunning;
23981
+ }
23982
+ }
23983
+ function claudePairingInProgress() {
23984
+ return claudePairLoopArmed();
23985
+ }
23986
+ var claudePairLoop = new ClaudePairLoop({
23987
+ tick: runClaudePairTick,
23988
+ isArmed: claudePairLoopArmed,
23989
+ canRun: () => running && !!config && !restartAfterUpgrade,
23990
+ log
23991
+ });
23774
23992
  async function processClaudePairSessions(agents) {
23775
23993
  if (agents.length === 0 && spawnedPairIds.size === 0) return;
23776
23994
  const agentIds = agents.map((a) => a.agentId);
@@ -23779,6 +23997,7 @@ async function processClaudePairSessions(agents) {
23779
23997
  agent_ids: agentIds,
23780
23998
  spawned_pair_ids: Array.from(spawnedPairIds)
23781
23999
  });
24000
+ lastPairPendingIds = (pendingResp.pending ?? []).map((p) => p.pair_id);
23782
24001
  const {
23783
24002
  startClaudePair,
23784
24003
  submitClaudePairCode,
@@ -23834,6 +24053,9 @@ async function processClaudePairSessions(agents) {
23834
24053
  return resp?.no_op !== true;
23835
24054
  }
23836
24055
  for (const session of pendingResp.pending) {
24056
+ if (!running || !claudePairLoop.accepting) break;
24057
+ if (pairRetryBackoff.shouldSkip(session.pair_id, Date.now())) continue;
24058
+ let dispatchFailed = false;
23837
24059
  const codeName = codeNameByAgentId.get(session.agent_id) ?? "<unassigned>";
23838
24060
  const pairSession = pairTmuxSession(session.pair_id);
23839
24061
  try {
@@ -23930,7 +24152,13 @@ async function processClaudePairSessions(agents) {
23930
24152
  }
23931
24153
  }
23932
24154
  } catch (err) {
23933
- log(`[claude-pair] dispatch failed for pair ${session.pair_id.slice(0, 8)}: ${err.message}`);
24155
+ dispatchFailed = true;
24156
+ const failures = pairRetryBackoff.recordFailure(session.pair_id, Date.now());
24157
+ log(
24158
+ `[claude-pair] dispatch failed for pair ${session.pair_id.slice(0, 8)} (${failures} in a row, retrying in ${Math.round(nextPairLoopDelayMs(true, failures) / 1e3)}s): ${err.message}`
24159
+ );
24160
+ } finally {
24161
+ if (!dispatchFailed) pairRetryBackoff.recordSuccess(session.pair_id);
23934
24162
  }
23935
24163
  }
23936
24164
  }
@@ -24617,6 +24845,7 @@ function startPolling() {
24617
24845
  void postLivenessHeartbeat();
24618
24846
  }, LIVENESS_HEARTBEAT_INTERVAL_MS);
24619
24847
  livenessTimer.unref();
24848
+ claudePairLoop.start();
24620
24849
  startPaneOccupancySampler(() => agentState.persistentSessionAgents);
24621
24850
  startPidPressureSampler(() => agentState.persistentSessionAgents);
24622
24851
  startRuntimeVersionSampler(() => agentState.persistentSessionAgents);
@@ -24783,6 +25012,7 @@ async function stopPolling(opts = {}) {
24783
25012
  clearInterval(livenessTimer);
24784
25013
  livenessTimer = null;
24785
25014
  }
25015
+ const pairLoopDrained = claudePairLoop.stop();
24786
25016
  stopPaneOccupancySampler();
24787
25017
  stopPidPressureSampler();
24788
25018
  stopRuntimeVersionSampler();
@@ -24829,6 +25059,7 @@ async function stopPolling(opts = {}) {
24829
25059
  closeSessionRunForCode(codeName, "completed", "manager shutdown");
24830
25060
  }
24831
25061
  const drainReleaseSnapshot = snapshotDrainReleaseTargets();
25062
+ await Promise.race([pairLoopDrained, new Promise((r) => setTimeout(r, 3e3).unref())]);
24832
25063
  log("Killing tmux sessions...");
24833
25064
  try {
24834
25065
  await killAllAgtTmuxSessions();
@@ -25198,6 +25429,7 @@ export {
25198
25429
  REALTIME_REBIND_STUCK_AFTER_MS,
25199
25430
  SELF_UPDATE_LATCH_MAX_HOLD_MS,
25200
25431
  UntrustworthyToolkitResponseError,
25432
+ _claudePairTickForTests,
25201
25433
  applyMemoryTombstones,
25202
25434
  applyRestartAcks,
25203
25435
  cancelKanbanNoticeOnDrain,
@@ -25206,6 +25438,8 @@ export {
25206
25438
  claudeCodeUpgradeMarkerPath,
25207
25439
  claudeCodeUpgradeThrottled,
25208
25440
  claudeManagedSettingsPath,
25441
+ claudePairLoopArmed,
25442
+ claudePairingInProgress,
25209
25443
  coverageOf,
25210
25444
  createManagedPruneLedger,
25211
25445
  createManagedToolkitReader,