@integrity-labs/agt-cli 0.28.826 → 0.28.828

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-BOHUJCZL.js");
103
+ const { resolveClaudeBinary } = await import("./persistent-session-6YTEDS3H.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-SWB525DM.js.map
376
+ //# sourceMappingURL=claude-pair-runtime-UTDZXJKO.js.map
@@ -14,6 +14,7 @@ import {
14
14
  decidePin,
15
15
  defaultFlagsCachePath,
16
16
  deriveMcpServerKey,
17
+ describeChannelWriteFailure,
17
18
  describeStartupCompletion,
18
19
  diffEnvIntegrations,
19
20
  drainTranscriptFlushDeps,
@@ -59,7 +60,7 @@ import {
59
60
  safeWriteJsonAtomic,
60
61
  setConfigHash,
61
62
  tripClass
62
- } from "../chunk-JO7QTVLM.js";
63
+ } from "../chunk-FBJFYF3F.js";
63
64
  import {
64
65
  getProjectDir as getProjectDir2,
65
66
  getReadyTasks,
@@ -100,6 +101,7 @@ import {
100
101
  paneLogPath,
101
102
  parseEnvIntegrations,
102
103
  parseModelPolicy,
104
+ policyResolvedModel,
103
105
  prepareForRespawn,
104
106
  readChannelServerEnv,
105
107
  readDirectChatSessionState,
@@ -124,7 +126,7 @@ import {
124
126
  takeZombieDetection,
125
127
  toOpencodeModel,
126
128
  writeEgressAllowlist
127
- } from "../chunk-Q3JUZZDB.js";
129
+ } from "../chunk-6HTCP6D5.js";
128
130
  import {
129
131
  ACCOUNT_ENFORCEMENT_MARKER_FILENAME,
130
132
  AnchorSessionClient,
@@ -12926,7 +12928,7 @@ var pendingDayRolloverReset = /* @__PURE__ */ new Set();
12926
12928
  var dayRolloverInboundHold = /* @__PURE__ */ new Map();
12927
12929
  var INBOUND_HOLD_EPISODE_GAP_MS = 12e4;
12928
12930
  async function channelInboundActivityAgeSecondsFor(codeName) {
12929
- const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-5DYKPYPP.js");
12931
+ const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-TIEZW3XP.js");
12930
12932
  const newest = newestPendingInboundActivityMtimeMs(dirname10(paneLogPath(codeName)));
12931
12933
  if (newest === null) return null;
12932
12934
  return Math.max(0, Math.floor((Date.now() - newest) / 1e3));
@@ -13594,7 +13596,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
13594
13596
  var lastVersionCheckAt = 0;
13595
13597
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
13596
13598
  var lastResponsivenessProbeAt = 0;
13597
- var agtCliVersion = true ? "0.28.826" : "dev";
13599
+ var agtCliVersion = true ? "0.28.828" : "dev";
13598
13600
  function resolveBrewPath(execFileSync2) {
13599
13601
  try {
13600
13602
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -15184,7 +15186,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
15184
15186
  if (codeNames.length === 0) return;
15185
15187
  void (async () => {
15186
15188
  try {
15187
- const { collectDiagnostics } = await import("../persistent-session-BOHUJCZL.js");
15189
+ const { collectDiagnostics } = await import("../persistent-session-6YTEDS3H.js");
15188
15190
  await api.post("/host/heartbeat", {
15189
15191
  host_id: hostId,
15190
15192
  agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -15239,6 +15241,7 @@ async function pollCycleInner() {
15239
15241
  stopPersistentSessionAndForgetMcpBaseline(codeName, breakerReason);
15240
15242
  agentState.persistentSessionAgents.delete(codeName);
15241
15243
  claudeAuthTupleBySession.delete(codeName);
15244
+ modelPolicyModelBySession.delete(codeName);
15242
15245
  },
15243
15246
  getTelegramTokens: (codeName) => {
15244
15247
  const t = agentChannelTokens.get(codeName);
@@ -15325,7 +15328,7 @@ async function pollCycleInner() {
15325
15328
  }
15326
15329
  try {
15327
15330
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
15328
- const { collectDiagnostics } = await import("../persistent-session-BOHUJCZL.js");
15331
+ const { collectDiagnostics } = await import("../persistent-session-6YTEDS3H.js");
15329
15332
  const diagCodeNames = [...agentState.persistentSessionAgents];
15330
15333
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor) : void 0;
15331
15334
  let tailscaleHostname;
@@ -15494,7 +15497,7 @@ async function pollCycleInner() {
15494
15497
  collectPanelessActivityProbes,
15495
15498
  getResponsivenessIntervalMs,
15496
15499
  occupancyQualificationClassifications
15497
- } = await import("../responsiveness-probe-5DYKPYPP.js");
15500
+ } = await import("../responsiveness-probe-TIEZW3XP.js");
15498
15501
  const probeIntervalMs = getResponsivenessIntervalMs();
15499
15502
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
15500
15503
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -15611,7 +15614,7 @@ async function pollCycleInner() {
15611
15614
  collectResponsivenessProbes,
15612
15615
  livePendingInboundOldestAgeSeconds,
15613
15616
  parkPendingInbound
15614
- } = await import("../responsiveness-probe-5DYKPYPP.js");
15617
+ } = await import("../responsiveness-probe-TIEZW3XP.js");
15615
15618
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
15616
15619
  const wedgeNow = /* @__PURE__ */ new Date();
15617
15620
  const liveAgents = agentState.persistentSessionAgents;
@@ -17071,7 +17074,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
17071
17074
  );
17072
17075
  }
17073
17076
  }
17074
- frameworkAdapter.writeChannelCredentials(
17077
+ const writeOutcome = frameworkAdapter.writeChannelCredentials(
17075
17078
  agent.code_name,
17076
17079
  channelId,
17077
17080
  entry.config,
@@ -17099,12 +17102,16 @@ async function processAgent(agent, agentStates, managedToolkits) {
17099
17102
  const landed = frameworkAdapter.hasChannelCredentials?.(agent.code_name, channelId) ?? true;
17100
17103
  if (!landed) {
17101
17104
  channelConfigConverged = false;
17102
- channelConfigFailureReason = `credentials for ${channelId} reported a clean write but did not land on disk (reason=${reason}) \u2014 likely a missing credential field, or the guarded .mcp.json write was rejected by the secret lint / config validator`;
17105
+ channelConfigFailureReason = describeChannelWriteFailure(
17106
+ writeOutcome,
17107
+ channelId,
17108
+ reason
17109
+ );
17103
17110
  const attempts = (channelWriteFailureCounts.get(cacheKey) ?? 0) + 1;
17104
17111
  channelWriteFailureCounts.set(cacheKey, attempts);
17105
17112
  if (attempts === 1 || attempts % CHANNEL_WRITE_FAILURE_ESCALATE_EVERY === 0) {
17106
17113
  log(
17107
- `ERROR: channel credentials for '${agent.code_name}/${channelId}' did NOT land on disk after a write that reported no error (reason=${reason}, attempt ${attempts}). The write was silently skipped \u2014 likely a missing credential field, or the guarded .mcp.json write was rejected by the secret lint / config validator (its reason is printed once per fingerprint on stderr). The channel will stay unusable until this is resolved; not re-logging every cycle.`
17114
+ `ERROR: channel credentials for '${agent.code_name}/${channelId}' did NOT land on disk (attempt ${attempts}). ${channelConfigFailureReason} The channel will stay unusable until this is resolved; not re-logging every cycle.`
17108
17115
  );
17109
17116
  }
17110
17117
  } else {
@@ -19054,6 +19061,7 @@ var DAY_ROLLOVER_INBOUND_GRACE_SEC = 60;
19054
19061
  var DAY_ROLLOVER_INBOUND_DEFER_MAX_MIN = 10;
19055
19062
  var persistentSessionStuckTracker = new PersistentSessionStuckTracker();
19056
19063
  var claudeAuthTupleBySession = /* @__PURE__ */ new Map();
19064
+ var modelPolicyModelBySession = /* @__PURE__ */ new Map();
19057
19065
  var opencodeCredentialFingerprintBySession = /* @__PURE__ */ new Map();
19058
19066
  var egressAllowlistBySession = /* @__PURE__ */ new Map();
19059
19067
  function deriveEgressAllowlist(toolsRaw, policy) {
@@ -19264,6 +19272,7 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
19264
19272
  });
19265
19273
  agentState.persistentSessionAgents.delete(codeName);
19266
19274
  claudeAuthTupleBySession.delete(codeName);
19275
+ modelPolicyModelBySession.delete(codeName);
19267
19276
  }
19268
19277
  return {
19269
19278
  decision: "skipped-auth-resolve-failed",
@@ -19315,28 +19324,49 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
19315
19324
  claudeAccountFingerprint,
19316
19325
  modelPolicyComponent: modelPolicyAuthComponent(modelPolicy)
19317
19326
  });
19327
+ const currentPolicyModel = policyResolvedModel({
19328
+ policy: modelPolicy,
19329
+ openRouterMode: Boolean(openRouterForAgent),
19330
+ // The same null the launcher config carries — see `modelPolicyGatewayToken`
19331
+ // at the spawn call site below, where its absence is deliberate until
19332
+ // ENG-9481 decides what a gateway credential is. Both sites must move
19333
+ // together: a token here and not there (or the reverse) resolves a gateway
19334
+ // binding `blocked` for one and honoured for the other, and the recorded
19335
+ // baseline would then describe an agent that does not exist.
19336
+ gatewayToken: null,
19337
+ codeName
19338
+ });
19318
19339
  const recordedAuthTuple = claudeAuthTupleBySession.get(codeName);
19340
+ const recordedPolicyModel = modelPolicyModelBySession.get(codeName);
19319
19341
  if (recordedAuthTuple && recordedAuthTuple !== currentAuthTuple && isSessionHealthy(codeName)) {
19320
19342
  const authTupleDiff = diffAuthTuples(recordedAuthTuple, currentAuthTuple);
19321
19343
  log(
19322
19344
  `[persistent-session] Auth config changed for '${codeName}' (${recordedAuthTuple} \u2192 ${currentAuthTuple}) \u2014 ${authTupleDiff.summary} \u2014 restarting session`
19323
19345
  );
19324
- const failoverNotice = failoverRestartNotice({
19346
+ const policyNotice = failoverRestartNotice({
19325
19347
  components: authTupleDiff.components,
19326
- policy: modelPolicy
19348
+ policy: modelPolicy,
19349
+ previousModel: recordedPolicyModel,
19350
+ currentModel: currentPolicyModel
19327
19351
  });
19328
- if (failoverNotice && isSessionHealthy(codeName)) {
19352
+ if (policyNotice && isSessionHealthy(codeName)) {
19329
19353
  const status = await injectMessageWithStatus(
19330
19354
  codeName,
19331
19355
  "system",
19332
- failoverNotice + BACK_ONLINE_GREETING_GUIDANCE,
19333
- { task_name: "model-policy-failover" },
19356
+ policyNotice.text + BACK_ONLINE_GREETING_GUIDANCE,
19357
+ // ENG-10113: the label follows the DECISION, not the call site. One
19358
+ // function now produces two events, and filing a model change under
19359
+ // `model-policy-failover` would put a wrong word in a record an operator
19360
+ // later reads back as evidence of a failover that never happened.
19361
+ { task_name: `model-policy-${policyNotice.reason}` },
19334
19362
  log
19335
19363
  ).catch(() => ({ delivered: false, fallbackUsed: false }));
19336
19364
  if (status.fallbackUsed) {
19337
19365
  await new Promise((r) => setTimeout(r, 3e3));
19338
19366
  } else {
19339
- log(`[model-policy] Failover notice not delivered to '${codeName}' \u2014 restarting anyway`);
19367
+ log(
19368
+ `[model-policy] ${policyNotice.reason} notice not delivered to '${codeName}' \u2014 restarting anyway`
19369
+ );
19340
19370
  }
19341
19371
  }
19342
19372
  stopPersistentSessionAndForgetMcpBaseline(codeName, "auth-tuple-change", void 0, void 0, {
@@ -19607,6 +19637,8 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash20("sha256")
19607
19637
  });
19608
19638
  agentState.persistentSessionAgents.add(codeName);
19609
19639
  claudeAuthTupleBySession.set(codeName, currentAuthTuple);
19640
+ if (currentPolicyModel) modelPolicyModelBySession.set(codeName, currentPolicyModel);
19641
+ else modelPolicyModelBySession.delete(codeName);
19610
19642
  seedSessionLaunchBaselines(codeName, projectDir);
19611
19643
  return {
19612
19644
  decision: "spawn",
@@ -19646,6 +19678,8 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash20("sha256")
19646
19678
  }
19647
19679
  if (!claudeAuthTupleBySession.has(codeName)) {
19648
19680
  claudeAuthTupleBySession.set(codeName, currentAuthTuple);
19681
+ if (currentPolicyModel) modelPolicyModelBySession.set(codeName, currentPolicyModel);
19682
+ else modelPolicyModelBySession.delete(codeName);
19649
19683
  }
19650
19684
  const stableTasksHash = createHash20("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
19651
19685
  const prevHash = agentState.knownTasksHashes.get(agent.agent_id);
@@ -19969,7 +20003,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
19969
20003
  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}`));
19970
20004
  void (async () => {
19971
20005
  try {
19972
- const { collectDiagnostics } = await import("../persistent-session-BOHUJCZL.js");
20006
+ const { collectDiagnostics } = await import("../persistent-session-6YTEDS3H.js");
19973
20007
  await api.post("/host/heartbeat", {
19974
20008
  host_id: hostId,
19975
20009
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -20015,7 +20049,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
20015
20049
  }
20016
20050
  try {
20017
20051
  const hostId = await getHostId();
20018
- const { collectDiagnostics } = await import("../persistent-session-BOHUJCZL.js");
20052
+ const { collectDiagnostics } = await import("../persistent-session-6YTEDS3H.js");
20019
20053
  await api.post("/host/heartbeat", {
20020
20054
  host_id: hostId,
20021
20055
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -20651,7 +20685,7 @@ async function processClaudePairSessions(agents) {
20651
20685
  killPairSession,
20652
20686
  pairTmuxSession,
20653
20687
  finalizeClaudePairOnboarding
20654
- } = await import("../claude-pair-runtime-SWB525DM.js");
20688
+ } = await import("../claude-pair-runtime-UTDZXJKO.js");
20655
20689
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
20656
20690
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
20657
20691
  const killed = await killPairSession(pairTmuxSession(pairId));