@integrity-labs/agt-cli 0.28.1014 → 0.28.1016

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.
@@ -266,7 +266,7 @@ async function spawnPairSession(session) {
266
266
  return { ok: true };
267
267
  } catch {
268
268
  }
269
- const { resolveClaudeBinary } = await import("./persistent-session-IEGA6OSO.js");
269
+ const { resolveClaudeBinary } = await import("./persistent-session-AQGEDGJR.js");
270
270
  const claudeBin = resolveClaudeBinary();
271
271
  const pairEnv = {
272
272
  ...process.env,
@@ -734,4 +734,4 @@ export {
734
734
  startClaudePair,
735
735
  submitClaudePairCode
736
736
  };
737
- //# sourceMappingURL=claude-pair-runtime-4F73QFXF.js.map
737
+ //# sourceMappingURL=claude-pair-runtime-VE6KUMQY.js.map
@@ -55,6 +55,7 @@ import {
55
55
  provisionStopHook,
56
56
  readEnvNumber,
57
57
  readHostArchiveAddress,
58
+ reapLegacyTokenFile,
58
59
  reapMissingMcpSessions,
59
60
  reapStaleMcpChildren,
60
61
  reaperRestartBreakerReason,
@@ -64,7 +65,7 @@ import {
64
65
  safeWriteJsonAtomic,
65
66
  setConfigHash,
66
67
  tripClass
67
- } from "../chunk-7QXIJNLA.js";
68
+ } from "../chunk-DFKQZGM7.js";
68
69
  import {
69
70
  getProjectDir as getProjectDir2,
70
71
  getReadyTasks,
@@ -145,7 +146,7 @@ import {
145
146
  takeZombieDetection,
146
147
  toOpencodeModel,
147
148
  writeEgressAllowlist
148
- } from "../chunk-QBQLG2PY.js";
149
+ } from "../chunk-YPS4AUHN.js";
149
150
  import {
150
151
  ACCOUNT_ENFORCEMENT_MARKER_FILENAME,
151
152
  AnchorSessionClient,
@@ -186,6 +187,7 @@ import {
186
187
  classifyCursorAdvance,
187
188
  classifyOutput,
188
189
  classifySlackPolicyBlock,
190
+ classifyTelegramPolicyBlock,
189
191
  classifyTranscriptRateLimit,
190
192
  coerceOnboardingState,
191
193
  cursorAdvanceCounterKey,
@@ -218,6 +220,7 @@ import {
218
220
  isOnboardingArea,
219
221
  isParseError,
220
222
  isResolveError,
223
+ isRespawnExemptEnvVar,
221
224
  isSelfCompletion,
222
225
  isStaleForToday,
223
226
  isSystemInjectedContent,
@@ -248,7 +251,7 @@ import {
248
251
  subagentActivityAgeSeconds,
249
252
  sumTranscriptUsageInWindow,
250
253
  transcriptActivityAgeSeconds
251
- } from "../chunk-MLCGPEN6.js";
254
+ } from "../chunk-B7XGAC54.js";
252
255
  import "../chunk-DHWNVVX4.js";
253
256
  import {
254
257
  reapOrphanChannelMcps
@@ -303,7 +306,44 @@ var TELEGRAM_RESTART_ON_CHANGE_ENV_KEYS = [
303
306
  /** Peer kill switch. A switch whose purpose is stopping something promptly. */
304
307
  "PEER_DISABLED",
305
308
  /** Derived boolean mirror of the same switch, kept for the rollout. */
306
- "TELEGRAM_PEER_DISABLED"
309
+ "TELEGRAM_PEER_DISABLED",
310
+ // ENG-9665. These are the purest case this list exists for: they ARE the
311
+ // sender policy, so a change to them is an operator changing who may talk to
312
+ // the agent, made in the console and visible there immediately. Waiting for
313
+ // an unrelated respawn would mean the console shows a restriction the running
314
+ // session is not applying - which is the exact ENG-9802 defect, and the same
315
+ // gap this file's header notes for SLACK_SENDER_POLICY.
316
+ //
317
+ // WHICH MECHANISM ACTUALLY RESPAWNS FOR THESE - Obi Wan `1c6a60a29aa5`, and
318
+ // it is `decideSenderPolicyRestart`, NOT this list's hash.
319
+ //
320
+ // Being classified here is a statement that a change is restart-worthy. It is
321
+ // NOT, for these three, the thing that delivers the restart:
322
+ // `telegramPolicyEnvFromInputs` builds the restart basis from the CHANNEL
323
+ // CONFIG, and a sender policy is not in the channel config - it is a column on
324
+ // `agents`. So these keys can never enter that hash, and the earlier comment
325
+ // here (and commit 97868b5a's message) credited a mechanism that does not
326
+ // reach them.
327
+ //
328
+ // The restart does happen, via `decideSenderPolicyRestart`, which reads the
329
+ // policy from where it actually lives and now covers telegram because
330
+ // `senderPolicyIsEnforcedOn('telegram')` is true. Deliberately NOT plumbed
331
+ // into the basis as well: that would mean two mechanisms racing to respawn on
332
+ // one edit, and the config-shaped one would be reading a value that is not in
333
+ // the config.
334
+ //
335
+ // KNOWN CONSEQUENCE, stated rather than left to be found:
336
+ // `isTelegramPolicyRestrictive` reads the basis, so it returns false for an
337
+ // agent whose ONLY Telegram restriction is a sender policy. That feeds the
338
+ // ENG-7771 unknown-baseline branch. Correct today only because
339
+ // `decideSenderPolicyRestart` covers the same agent by a different route; if
340
+ // that ever stops being true, this is where the gap reappears.
341
+ /** The mode itself. Nothing else decides more about who is admitted. */
342
+ "TELEGRAM_SENDER_POLICY",
343
+ /** manager_only's single admitted counterparty. */
344
+ "TELEGRAM_SENDER_POLICY_PRINCIPAL_ID",
345
+ /** team_only's admitted set. An edit here adds or removes people. */
346
+ "TELEGRAM_SENDER_POLICY_TEAM_PRINCIPAL_IDS"
307
347
  ];
308
348
  function telegramPolicyEnvBasis(env) {
309
349
  const parts = [];
@@ -11239,6 +11279,37 @@ function parsePeerAgentModeEnv2(raw) {
11239
11279
  return "off";
11240
11280
  }
11241
11281
 
11282
+ // ../../packages/core/dist/channels/governance/telegram-inbound-filter.js
11283
+ function isBotSender(evt) {
11284
+ return evt.from?.is_bot === true;
11285
+ }
11286
+ function isSameTeamPeer(evt) {
11287
+ const gate = evt.peerGatePath;
11288
+ return gate === "same_team" || gate === void 0;
11289
+ }
11290
+ function decideSenderPolicyForwardTelegram(evt, policy) {
11291
+ if (policy.mode === "all")
11292
+ return { forward: true };
11293
+ const fromId = evt.from?.id;
11294
+ if (fromId === void 0)
11295
+ return { forward: false, reason: "sender_policy" };
11296
+ const fromIdStr = String(fromId);
11297
+ if (policy.mode === "manager_only") {
11298
+ return policy.principalTelegramUserId && fromIdStr === policy.principalTelegramUserId ? { forward: true } : { forward: false, reason: "sender_policy" };
11299
+ }
11300
+ if (policy.mode === "team_only") {
11301
+ const list = policy.teamPrincipalTelegramUserIds;
11302
+ if (list && list.length > 0 && list.includes(fromIdStr)) {
11303
+ return { forward: true };
11304
+ }
11305
+ return isBotSender(evt) && isSameTeamPeer(evt) ? { forward: true } : { forward: false, reason: "sender_policy" };
11306
+ }
11307
+ if (policy.mode === "team_agents_only") {
11308
+ return isBotSender(evt) && isSameTeamPeer(evt) ? { forward: true } : { forward: false, reason: "sender_policy" };
11309
+ }
11310
+ return isBotSender(evt) ? { forward: true } : { forward: false, reason: "sender_policy" };
11311
+ }
11312
+
11242
11313
  // ../../packages/core/dist/channels/governance/telegram-chat-type.js
11243
11314
  function isTelegramPrivateChat(chatType) {
11244
11315
  return chatType === "private";
@@ -11252,6 +11323,7 @@ function evaluateTelegramInboundGate(evt, deps) {
11252
11323
  const content = text.length > 0 ? { forward: true } : { forward: false, reason: "empty" };
11253
11324
  let peerLeaf;
11254
11325
  let isSelf = false;
11326
+ let peerGatePath;
11255
11327
  if (isBot) {
11256
11328
  const classifierMsg = {
11257
11329
  message_id: evt.message_id,
@@ -11269,6 +11341,13 @@ function evaluateTelegramInboundGate(evt, deps) {
11269
11341
  const c = classifyPeerMessage2(classifierMsg, deps.peerConfig, deps.self);
11270
11342
  isSelf = c.kind === "self";
11271
11343
  peerLeaf = { kind: c.kind, reason: c.kind === "drop" ? c.reason : void 0 };
11344
+ peerGatePath = evt.from ? deps.peerConfig.peers.find((pr) => pr.bot_id === evt.from.id)?.gate_path : void 0;
11345
+ }
11346
+ const policy = deps.senderPolicy;
11347
+ let senderPolicyLeaf;
11348
+ if (policy) {
11349
+ const verdict = decideSenderPolicyForwardTelegram({ ...evt, peerGatePath }, policy);
11350
+ senderPolicyLeaf = verdict.forward ? { forward: true } : { forward: false, reason: classifyTelegramPolicyBlock(policy) };
11272
11351
  }
11273
11352
  const decision = decideInboundAccess({
11274
11353
  content,
@@ -11284,7 +11363,27 @@ function evaluateTelegramInboundGate(evt, deps) {
11284
11363
  // this is `{ forward: true }`, which the composer treats identically to the
11285
11364
  // field being absent.
11286
11365
  chatType: deps.privateChatsOnly && !isTelegramPrivateChat(evt.chat.type) ? { forward: false } : { forward: true },
11287
- // No sender-policy mode system and no command dispatch on the injection gate.
11366
+ // ENG-9665: the sender-policy axis, applied to ALL senders (a peer agent is
11367
+ // gated here too, before peer governance) exactly as on Slack and Teams.
11368
+ // Absent policy means `all`, which is a no-op.
11369
+ senderPolicy: senderPolicyLeaf,
11370
+ // Injection gate: no command dispatch, and NO DECLINE IS EVER SENT on this
11371
+ // path - so `sameOrg` has nothing to decide here.
11372
+ //
11373
+ // Obi Wan `2d99e22b7e8d`: this used to compute
11374
+ // `allowedChats.size > 0 && allowedChats.has(chatId)` under a comment
11375
+ // reasoning about decline-vs-silence as if it were live. It is not. This
11376
+ // function returns `{ admit, reason }` and DISCARDS `decision.decline`, and
11377
+ // `dispatchTelegramInbound` only logs and returns 'dropped_gate'. So the
11378
+ // computed value had no observable effect for any allowlist, while the
11379
+ // comment implied an agent WITH one would decline. A reader auditing the
11380
+ // insider-decline posture would have concluded opencode Telegram delivers
11381
+ // declines when it delivers silence in every case.
11382
+ //
11383
+ // `slack-sender-gate.ts` states this honestly with a flat `sameOrg: false`,
11384
+ // so this now matches its sibling. IF a decline is ever wired on this
11385
+ // runtime, this is the line to revisit - and the argument for what to put
11386
+ // here lives in telegram-channel.ts, where declines are actually sent.
11288
11387
  sameOrg: false
11289
11388
  });
11290
11389
  if (decision.kind === "drop")
@@ -11315,6 +11414,32 @@ function buildTelegramPeerClassifierConfigFromEnv(env, opts) {
11315
11414
  peer_disabled_mode: parseTelegramPeerDisabledModeEnv(env, opts?.onWarn)
11316
11415
  };
11317
11416
  }
11417
+ function buildTelegramSenderPolicyFromEnv(env, ctx) {
11418
+ const raw = (env["TELEGRAM_SENDER_POLICY"] ?? "all").trim().toLowerCase();
11419
+ const teamId = ctx.agentTeamId;
11420
+ if (raw === "all")
11421
+ return { mode: "all" };
11422
+ if (raw === "agents_only")
11423
+ return { mode: "agents_only" };
11424
+ if (raw === "team_agents_only") {
11425
+ if (!teamId)
11426
+ throw new Error("TELEGRAM_SENDER_POLICY=team_agents_only requires AGT_TEAM_ID");
11427
+ return { mode: "team_agents_only", teamId };
11428
+ }
11429
+ if (raw === "team_only") {
11430
+ if (!teamId)
11431
+ throw new Error("TELEGRAM_SENDER_POLICY=team_only requires AGT_TEAM_ID");
11432
+ const teamPrincipalTelegramUserIds = (env["TELEGRAM_SENDER_POLICY_TEAM_PRINCIPAL_IDS"] ?? "").split(",").map((s) => s.trim()).filter((s) => s.length > 0);
11433
+ return { mode: "team_only", teamId, teamPrincipalTelegramUserIds };
11434
+ }
11435
+ if (raw === "manager_only") {
11436
+ if (!teamId)
11437
+ throw new Error("TELEGRAM_SENDER_POLICY=manager_only requires AGT_TEAM_ID");
11438
+ const principalTelegramUserId = env["TELEGRAM_SENDER_POLICY_PRINCIPAL_ID"];
11439
+ return principalTelegramUserId ? { mode: "manager_only", teamId, principalTelegramUserId } : { mode: "manager_only", teamId };
11440
+ }
11441
+ throw new Error(`Invalid TELEGRAM_SENDER_POLICY=${JSON.stringify(env["TELEGRAM_SENDER_POLICY"])}`);
11442
+ }
11318
11443
 
11319
11444
  // src/lib/telegram-ingest.ts
11320
11445
  var nodeHttpsTelegramFetch = (url, init) => new Promise((resolve2, reject) => {
@@ -11373,7 +11498,7 @@ function memoryOffsetStore(initial = 0) {
11373
11498
  value = o;
11374
11499
  } };
11375
11500
  }
11376
- function resolveTelegramIngestParamsFromEnv(env) {
11501
+ function resolveTelegramIngestParamsFromEnv(env, ctx) {
11377
11502
  const botToken = env["TELEGRAM_BOT_TOKEN"];
11378
11503
  if (!botToken) return null;
11379
11504
  const ackReaction = (env["TELEGRAM_ACK_REACTION"] ?? "").trim() || "\u{1F440}";
@@ -11382,6 +11507,7 @@ function resolveTelegramIngestParamsFromEnv(env) {
11382
11507
  botToken,
11383
11508
  allowedChats: parseTelegramAllowedChatsEnv(env),
11384
11509
  peerConfig: buildTelegramPeerClassifierConfigFromEnv(env),
11510
+ senderPolicy: buildTelegramSenderPolicyFromEnv(env, ctx),
11385
11511
  ackReaction,
11386
11512
  ...skipReaction ? { skipReaction } : {}
11387
11513
  };
@@ -11439,7 +11565,12 @@ async function dispatchTelegramInbound(update, ctx) {
11439
11565
  const decision = evaluateTelegramInboundGate(msg, {
11440
11566
  allowedChats: ctx.allowedChats,
11441
11567
  peerConfig: ctx.peerConfig,
11442
- self: ctx.self
11568
+ self: ctx.self,
11569
+ // ENG-9665 / Obi Wan `526be87f0cbd`: THE LINE THAT WAS MISSING. Without it
11570
+ // `deps.senderPolicy` is undefined, which the gate treats as `all`, so the
11571
+ // registry's claim that both runtimes supply this leaf was false on this
11572
+ // path. eng-9665-opencode-sender-policy.test.ts fails if it is removed.
11573
+ senderPolicy: ctx.senderPolicy
11443
11574
  });
11444
11575
  if (!decision.admit) {
11445
11576
  ctx.log(`[telegram-ingest:${ctx.codeName}] dropped chat=${redactId(chatId)} reason=${decision.reason}`);
@@ -11546,6 +11677,7 @@ function startTelegramIngest(config2) {
11546
11677
  codeName: config2.codeName,
11547
11678
  allowedChats: config2.allowedChats,
11548
11679
  peerConfig: config2.peerConfig,
11680
+ senderPolicy: config2.senderPolicy,
11549
11681
  self: config2.self,
11550
11682
  inject: config2.inject,
11551
11683
  sendReply,
@@ -11633,6 +11765,10 @@ function fingerprint2(params) {
11633
11765
  botToken: params.botToken,
11634
11766
  allowedChats: [...params.allowedChats].sort(),
11635
11767
  peerConfig: params.peerConfig,
11768
+ // The whole policy: the mode AND the principal identities. A revocation
11769
+ // changes only the ids, so hashing the mode alone would miss exactly the
11770
+ // case `3ff390e32af6` describes.
11771
+ senderPolicy: params.senderPolicy,
11636
11772
  ackReaction: params.ackReaction ?? null,
11637
11773
  skipReaction: params.skipReaction ?? null
11638
11774
  })
@@ -11702,7 +11838,7 @@ async function ensureOpencodeTelegramIngest(opts) {
11702
11838
  stopOpencodeTelegramIngest(codeName, log2);
11703
11839
  return;
11704
11840
  }
11705
- params = resolveTelegramIngestParamsFromEnv(env);
11841
+ params = resolveTelegramIngestParamsFromEnv(env, { agentTeamId: env["AGT_TEAM_ID"] ?? null });
11706
11842
  } catch (err) {
11707
11843
  stopOpencodeTelegramIngest(codeName, log2);
11708
11844
  log2(`[telegram-ingest:${codeName}] not started: ${err instanceof Error ? err.message : String(err)}`);
@@ -11738,6 +11874,7 @@ async function ensureOpencodeTelegramIngest(opts) {
11738
11874
  botToken: params.botToken,
11739
11875
  allowedChats: params.allowedChats,
11740
11876
  peerConfig: params.peerConfig,
11877
+ senderPolicy: params.senderPolicy,
11741
11878
  self,
11742
11879
  inject: (msg) => injectOpencodeMessage(codeName, msg, { awaitReply: true }),
11743
11880
  log: log2,
@@ -13174,6 +13311,16 @@ var dependencyRecoveryLedger = new DependencyRecoveryLedger();
13174
13311
  var unstableLatchUnreported = /* @__PURE__ */ new Set();
13175
13312
  var unstableLatchReportInFlight = /* @__PURE__ */ new Set();
13176
13313
  var killPausedCodeNames = /* @__PURE__ */ new Set();
13314
+ var tokenReapWarnedCodeNames = /* @__PURE__ */ new Set();
13315
+ function reapLegacyTokenFileEdgeWarned(codeName, log2, seen = tokenReapWarnedCodeNames) {
13316
+ const removed = reapLegacyTokenFile(codeName, (message) => {
13317
+ if (seen.has(codeName)) return;
13318
+ seen.add(codeName);
13319
+ log2(message);
13320
+ });
13321
+ if (removed) seen.delete(codeName);
13322
+ return removed;
13323
+ }
13177
13324
  var notRunningCodeNames = /* @__PURE__ */ new Set();
13178
13325
  var BACK_ONLINE_GREETING_GUIDANCE = " When you reconnect, if you tell anyone you are back, start that message with a \u{1F44B} wave emoji and do not use a \u{1F7E2} green-light emoji.";
13179
13326
  function maybeAutoResume(agent) {
@@ -13642,7 +13789,7 @@ var pendingDayRolloverReset = /* @__PURE__ */ new Set();
13642
13789
  var dayRolloverInboundHold = /* @__PURE__ */ new Map();
13643
13790
  var INBOUND_HOLD_EPISODE_GAP_MS = 12e4;
13644
13791
  async function channelInboundActivityAgeSecondsFor(codeName) {
13645
- const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-KWFVG5EI.js");
13792
+ const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-BDARO76E.js");
13646
13793
  const newest = newestPendingInboundActivityMtimeMs(dirname11(paneLogPath(codeName)));
13647
13794
  if (newest === null) return null;
13648
13795
  return Math.max(0, Math.floor((Date.now() - newest) / 1e3));
@@ -14385,7 +14532,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
14385
14532
  var lastVersionCheckAt = 0;
14386
14533
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
14387
14534
  var lastResponsivenessProbeAt = 0;
14388
- var agtCliVersion = true ? "0.28.1014" : "dev";
14535
+ var agtCliVersion = true ? "0.28.1016" : "dev";
14389
14536
  function resolveBrewPath(execFileSync3) {
14390
14537
  try {
14391
14538
  const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -16020,7 +16167,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
16020
16167
  if (codeNames.length === 0) return;
16021
16168
  void (async () => {
16022
16169
  try {
16023
- const { collectDiagnostics } = await import("../persistent-session-IEGA6OSO.js");
16170
+ const { collectDiagnostics } = await import("../persistent-session-AQGEDGJR.js");
16024
16171
  await api.post("/host/heartbeat", {
16025
16172
  host_id: hostId,
16026
16173
  agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
@@ -16162,7 +16309,7 @@ async function pollCycleInner() {
16162
16309
  }
16163
16310
  try {
16164
16311
  const { detectHostSecurity } = await import("../host-security-KQYYZZVW.js");
16165
- const { collectDiagnostics } = await import("../persistent-session-IEGA6OSO.js");
16312
+ const { collectDiagnostics } = await import("../persistent-session-AQGEDGJR.js");
16166
16313
  const diagCodeNames = [...agentState.persistentSessionAgents];
16167
16314
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor) : void 0;
16168
16315
  let tailscaleHostname;
@@ -16338,7 +16485,7 @@ async function pollCycleInner() {
16338
16485
  collectPanelessActivityProbes,
16339
16486
  getResponsivenessIntervalMs,
16340
16487
  occupancyQualificationClassifications
16341
- } = await import("../responsiveness-probe-KWFVG5EI.js");
16488
+ } = await import("../responsiveness-probe-BDARO76E.js");
16342
16489
  const probeIntervalMs = getResponsivenessIntervalMs();
16343
16490
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
16344
16491
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -16455,7 +16602,7 @@ async function pollCycleInner() {
16455
16602
  collectResponsivenessProbes,
16456
16603
  livePendingInboundOldestAgeSeconds,
16457
16604
  parkPendingInbound
16458
- } = await import("../responsiveness-probe-KWFVG5EI.js");
16605
+ } = await import("../responsiveness-probe-BDARO76E.js");
16459
16606
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-M6AFZWNU.js");
16460
16607
  const wedgeNow = /* @__PURE__ */ new Date();
16461
16608
  const liveAgents = agentState.persistentSessionAgents;
@@ -16611,7 +16758,7 @@ async function pollCycleInner() {
16611
16758
  }
16612
16759
  try {
16613
16760
  const { scrapeMcpFailedBannerCount } = await import("../pane-mcp-banner-scraper-VR5QGP3J.js");
16614
- const { probeSessionAuth } = await import("../session-auth-dead-P6KOHDYJ.js");
16761
+ const { probeSessionAuth } = await import("../session-auth-dead-2CCORXIW.js");
16615
16762
  const observations = [];
16616
16763
  const pendingCacheCommits = [];
16617
16764
  const modelApiErrorReportingOn = hostFlagStore().getBoolean("model-api-error-reporting");
@@ -17371,6 +17518,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
17371
17518
  let agentDir = join42(adapter.getAgentDir(agent.code_name), "provision");
17372
17519
  if (agent.status === "draft" || agent.status === "paused") {
17373
17520
  forgetChannelSyncState(agent.agent_id);
17521
+ reapLegacyTokenFileEdgeWarned(agent.code_name, log);
17374
17522
  if (previousKnownStatus !== agent.status) {
17375
17523
  log(`Agent '${agent.code_name}' is ${agent.status}, skipping provisioning`);
17376
17524
  }
@@ -18618,9 +18766,6 @@ async function processAgent(agent, agentStates, managedToolkits) {
18618
18766
  if (rotated) {
18619
18767
  log(`OAuth token refreshed for '${agent.code_name}/${integration.definition_id}'`);
18620
18768
  }
18621
- if (frameworkAdapter.writeTokenFile) {
18622
- frameworkAdapter.writeTokenFile(agent.code_name, integrations);
18623
- }
18624
18769
  }
18625
18770
  } catch (err) {
18626
18771
  log(`OAuth token refresh failed for '${agent.code_name}/${integration.definition_id}': ${err.message}`);
@@ -18769,7 +18914,8 @@ async function processAgent(agent, agentStates, managedToolkits) {
18769
18914
  if (prevIntHash !== EMPTY_INTEGRATIONS_HASH) {
18770
18915
  try {
18771
18916
  frameworkAdapter.writeIntegrations(agent.code_name, [], agent.agent_id, {
18772
- renderClaudeMdSection: renderIntegrationsSection
18917
+ renderClaudeMdSection: renderIntegrationsSection,
18918
+ log
18773
18919
  });
18774
18920
  agentState.knownIntegrationHashes.set(agent.agent_id, EMPTY_INTEGRATIONS_HASH);
18775
18921
  log(`[ENG-8035] Pruned integration-derived MCP entries for '${agent.code_name}' (integrations.length=0)`);
@@ -18793,7 +18939,8 @@ async function processAgent(agent, agentStates, managedToolkits) {
18793
18939
  }
18794
18940
  if (frameworkAdapter.writeIntegrations) {
18795
18941
  frameworkAdapter.writeIntegrations(agent.code_name, integrations, agent.agent_id, {
18796
- renderClaudeMdSection: renderIntegrationsSection
18942
+ renderClaudeMdSection: renderIntegrationsSection,
18943
+ log
18797
18944
  });
18798
18945
  }
18799
18946
  log(`Integrations provisioned for '${agent.code_name}' (${integrations.length} integration(s))`);
@@ -18828,7 +18975,11 @@ async function processAgent(agent, agentStates, managedToolkits) {
18828
18975
  ...liveProxyExtraHeaderVars(mcpJsonForReap),
18829
18976
  ...liveProxyTokenVars(mcpJsonForReap)
18830
18977
  ]);
18831
- const respawnVars = envOnlyRespawnVars(changedVars, mcpJsonForReap, CHANNEL_SECRET_ENV_KEYS).filter((v) => !liveProxyVars.has(v) && !isControlPlaneOnlyEnvVar(v));
18978
+ const respawnVars = envOnlyRespawnVars(changedVars, mcpJsonForReap, CHANNEL_SECRET_ENV_KEYS).filter(
18979
+ (v) => !liveProxyVars.has(v) && !isControlPlaneOnlyEnvVar(v) && // ENG-10939: consumerless identity vars whose one-time
18980
+ // appearance must not interrupt a live turn.
18981
+ !isRespawnExemptEnvVar(v)
18982
+ );
18832
18983
  const envDiff = classifyEnvIntegrationsDiff(preWriteEnv, postWriteEnv);
18833
18984
  const rotatedOnlyVars = new Set(envDiff.rotated);
18834
18985
  const envRespawnReason = respawnVars.length > 0 && respawnVars.every((v) => rotatedOnlyVars.has(v)) ? "credential-rotation" : "hot-reload-mcp";
@@ -20991,7 +21142,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
20991
21142
  try {
20992
21143
  const freshId = rotateSessionForWedge(codeName);
20993
21144
  consecutiveWedgeCycles.delete(codeName);
20994
- const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-KWFVG5EI.js");
21145
+ const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-BDARO76E.js");
20995
21146
  const { parked, deadLettered } = parkForRestart(codeName, /* @__PURE__ */ new Date());
20996
21147
  const parkNote = parked > 0 ? `, ${parked} inbound parked` : "";
20997
21148
  const deadNote = deadLettered > 0 ? `, ${deadLettered} undeliverable dead-lettered` : "";
@@ -21034,7 +21185,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
21034
21185
  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}`));
21035
21186
  void (async () => {
21036
21187
  try {
21037
- const { collectDiagnostics } = await import("../persistent-session-IEGA6OSO.js");
21188
+ const { collectDiagnostics } = await import("../persistent-session-AQGEDGJR.js");
21038
21189
  await api.post("/host/heartbeat", {
21039
21190
  host_id: hostId,
21040
21191
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
@@ -21085,7 +21236,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
21085
21236
  }
21086
21237
  try {
21087
21238
  const hostId = await getHostId();
21088
- const { collectDiagnostics } = await import("../persistent-session-IEGA6OSO.js");
21239
+ const { collectDiagnostics } = await import("../persistent-session-AQGEDGJR.js");
21089
21240
  await api.post("/host/heartbeat", {
21090
21241
  host_id: hostId,
21091
21242
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
@@ -21756,7 +21907,7 @@ async function processClaudePairSessions(agents) {
21756
21907
  // cannot take it for itself — by the time it runs, the write it is looking
21757
21908
  // for may already have happened.
21758
21909
  snapshotPairConfig
21759
- } = await import("../claude-pair-runtime-4F73QFXF.js");
21910
+ } = await import("../claude-pair-runtime-VE6KUMQY.js");
21760
21911
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
21761
21912
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
21762
21913
  const killed = await killPairSession(pairTmuxSession(pairId));
@@ -22442,6 +22593,7 @@ ${mem.content}
22442
22593
  }
22443
22594
  }
22444
22595
  async function cleanupAgentFiles(codeName, agentDir) {
22596
+ reapLegacyTokenFile(codeName, log);
22445
22597
  if (existsSync19(agentDir)) {
22446
22598
  try {
22447
22599
  rmSync8(agentDir, { recursive: true, force: true });
@@ -23189,6 +23341,7 @@ export {
23189
23341
  pruneRealtimeRebindState,
23190
23342
  realtimeRebindBackoffMs,
23191
23343
  realtimeRebindDue,
23344
+ reapLegacyTokenFileEdgeWarned,
23192
23345
  recordChannelSyncFailure,
23193
23346
  recordRealtimeRebindFailure,
23194
23347
  refreshSkillsIndexInClaudeMd,