@integrity-labs/agt-cli 0.28.383 → 0.28.385

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-4LAOXUQD.js");
103
+ const { resolveClaudeBinary } = await import("./persistent-session-MDQVHXKX.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-PERAQ2PL.js.map
376
+ //# sourceMappingURL=claude-pair-runtime-OIK6HKPS.js.map
@@ -43,7 +43,7 @@ import {
43
43
  resolveEffectivePinRaw,
44
44
  safeWriteJsonAtomic,
45
45
  setConfigHash
46
- } from "../chunk-RBXCFAWL.js";
46
+ } from "../chunk-P3SY6KTF.js";
47
47
  import {
48
48
  getProjectDir as getProjectDir2,
49
49
  getReadyTasks,
@@ -145,16 +145,16 @@ import {
145
145
  toOpencodeModel,
146
146
  transcriptActivityAgeSeconds,
147
147
  writeEgressAllowlist
148
- } from "../chunk-Q433LFRY.js";
148
+ } from "../chunk-MQHDPJZD.js";
149
149
  import {
150
150
  reapOrphanChannelMcps
151
151
  } from "../chunk-XWVM4KPK.js";
152
152
 
153
153
  // src/lib/manager-worker.ts
154
- import { createHash as createHash14 } from "crypto";
155
- import { readFileSync as readFileSync17, writeFileSync as writeFileSync11, mkdirSync as mkdirSync9, existsSync as existsSync11, rmSync as rmSync5, readdirSync as readdirSync5, statSync as statSync4, copyFileSync } from "fs";
154
+ import { createHash as createHash13 } from "crypto";
155
+ import { readFileSync as readFileSync17, writeFileSync as writeFileSync11, mkdirSync as mkdirSync8, existsSync as existsSync11, rmSync as rmSync5, readdirSync as readdirSync5, statSync as statSync4, copyFileSync } from "fs";
156
156
  import { execFileSync as syncExecFile } from "child_process";
157
- import { join as join21, dirname as dirname6, delimiter as pathDelimiter } from "path";
157
+ import { join as join21, dirname as dirname5, delimiter as pathDelimiter } from "path";
158
158
  import { homedir as homedir10 } from "os";
159
159
  import { fileURLToPath } from "url";
160
160
 
@@ -4987,35 +4987,10 @@ function closeScheduledRunsForCode(codeName, outcome, reason) {
4987
4987
  }
4988
4988
 
4989
4989
  // src/lib/manager/scheduler/kanban-route.ts
4990
- import { createHash as createHash9 } from "crypto";
4991
- import { writeFileSync as writeFileSync8, renameSync, mkdirSync as mkdirSync6 } from "fs";
4992
- import { homedir as homedir7 } from "os";
4993
- import { join as join17, dirname as dirname5 } from "path";
4994
-
4995
- // src/lib/manager/scheduler/notify.ts
4996
4990
  import { createHash as createHash8 } from "crypto";
4997
- async function enqueueScheduledTaskNotice(opts) {
4998
- try {
4999
- const res = await api.post(
5000
- "/host/scheduled-task/notify",
5001
- {
5002
- agent_id: opts.agentId,
5003
- task_id: opts.taskId,
5004
- card_id: opts.cardId,
5005
- content: opts.content,
5006
- run_id: opts.runId ?? void 0
5007
- }
5008
- );
5009
- return res.ok === true;
5010
- } catch (err) {
5011
- const errText = err instanceof Error ? err.message : String(err);
5012
- const errId = createHash8("sha256").update(errText).digest("hex").slice(0, 12);
5013
- log(
5014
- `[scheduled-kanban] notice enqueue failed for agent_id=${opts.agentId} task_id=${opts.taskId} error_id=${errId}`
5015
- );
5016
- return false;
5017
- }
5018
- }
4991
+ import { writeFileSync as writeFileSync8, renameSync } from "fs";
4992
+ import { homedir as homedir7 } from "os";
4993
+ import { join as join17 } from "path";
5019
4994
 
5020
4995
  // src/lib/manager/delivery/scheduled-output.ts
5021
4996
  async function deliverScheduledTaskOutput(agentCodeName, agentId, rawTarget, body, taskId) {
@@ -5361,24 +5336,22 @@ async function routeScheduledTaskViaKanban(codeName, agentId, task, prompt) {
5361
5336
  ` + formatRunMarker(run_id) : `A scheduled task just fired and it is now a card on YOUR board that YOU work. The schedule only controls WHEN this card arrives, not who executes it: nothing else runs it for you, so do the work yourself now. Card: id=${kanban_item_id} title=${JSON.stringify(task.name)}. Call kanban_move("${kanban_item_id}", "in_progress"), do the work described on the card, then write the finished result onto the card and mark it done. Do NOT send, post, or message the result to anyone yourself \u2014 the result you write on the card IS the message that will be delivered to the user; delivery happens automatically from the card.
5362
5337
  ` + suppressionTeaching + formatRunMarker(run_id);
5363
5338
  stampScheduledTurnMarker(codeName, task.taskId, resolveScheduledSlackTarget(task));
5364
- const enqueued = await enqueueScheduledTaskNotice({
5365
- agentId,
5366
- taskId: task.taskId,
5367
- cardId: kanban_item_id,
5368
- content: nudge,
5369
- runId: run_id
5370
- });
5371
- if (!enqueued) {
5372
- log(`[scheduled-kanban] durable nudge enqueue failed for task '${task.name}' on '${codeName}' - closing card + run`);
5373
- void finishRun(run_id, "failed", { outcomeMessage: "scheduled-task durable nudge enqueue failed", completeKanbanItemId: kanban_item_id });
5374
- return false;
5375
- }
5339
+ let injectStatus;
5376
5340
  try {
5377
- const doorbell = directChatDoorbellPath(agentId, homedir7());
5378
- mkdirSync6(dirname5(doorbell), { recursive: true });
5379
- writeFileSync8(doorbell, String(Date.now()));
5341
+ injectStatus = await injectMessageWithStatus(codeName, "task", nudge, { task_name: "scheduled-task-do-now" }, log);
5380
5342
  } catch (err) {
5381
- log(`[scheduled-kanban] doorbell ring failed for '${codeName}': ${err.message} (notice still queued)`);
5343
+ log(`[scheduled-kanban] nudge injection threw for task '${task.name}' on '${codeName}': ${err.message} \u2014 closing card + falling back to claude -p`);
5344
+ void finishRun(run_id, "failed", { outcomeMessage: "scheduled-task nudge delivery threw", completeKanbanItemId: kanban_item_id });
5345
+ return false;
5346
+ }
5347
+ const { delivered, fallbackUsed } = injectStatus;
5348
+ if (!delivered && !fallbackUsed) {
5349
+ log(`[scheduled-kanban] nudge delivery failed for task '${task.name}' on '${codeName}' \u2014 closing card + falling back to claude -p`);
5350
+ void finishRun(run_id, "failed", { outcomeMessage: "scheduled-task nudge delivery failed", completeKanbanItemId: kanban_item_id });
5351
+ return false;
5352
+ }
5353
+ if (!delivered && fallbackUsed) {
5354
+ log(`[scheduled-kanban] nudge sent via send-keys (unverified) for task '${task.name}' on '${codeName}' \u2014 proceeding without oneshot fallback`);
5382
5355
  }
5383
5356
  trackScheduledRun(codeName, kanban_item_id, run_id);
5384
5357
  log(`[scheduled-kanban] Routed task '${task.name}' for '${codeName}' via todo card ${kanban_item_id} run_id=${run_id}`);
@@ -5423,24 +5396,24 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
5423
5396
  const assertion = parseDeliverAssertion(rawOutput);
5424
5397
  if (!assertion.deliver) {
5425
5398
  const trimmed = (rawOutput ?? "").trim();
5426
- const outputHash = trimmed.length === 0 ? "empty" : createHash9("sha256").update(trimmed).digest("hex").slice(0, 12);
5399
+ const outputHash = trimmed.length === 0 ? "empty" : createHash8("sha256").update(trimmed).digest("hex").slice(0, 12);
5427
5400
  log(`[claude-scheduler] Suppressed by delivery_policy=conditional for '${codeName}' (template=${templateId}, task=${delivery?.taskId ?? "n/a"}) \u2014 ${assertion.vacuous ? "deliver marker had a vacuous reason" : "no deliver marker"}; output_len=${trimmed.length} output_hash=${outputHash}`);
5428
5401
  if (delivery?.mode === "announce" && delivery.to) {
5429
5402
  await reportDeliveryStatus(agentId, delivery.taskId, { status: "skipped", error_code: "SUPPRESSED_BY_POLICY" });
5430
5403
  }
5431
5404
  return { ok: true };
5432
5405
  }
5433
- const reasonHash = createHash9("sha256").update(assertion.reason ?? "").digest("hex").slice(0, 12);
5406
+ const reasonHash = createHash8("sha256").update(assertion.reason ?? "").digest("hex").slice(0, 12);
5434
5407
  log(`[claude-scheduler] Delivering conditional run for '${codeName}' (template=${templateId}, task=${delivery?.taskId ?? "n/a"}) \u2014 agent asserted a concrete trigger (reason_len=${(assertion.reason ?? "").length} reason_hash=${reasonHash})`);
5435
5408
  rawOutput = assertion.deliverable;
5436
5409
  }
5437
5410
  const classification = classifyOutput(rawOutput);
5438
5411
  if (classification.action === "suppress") {
5439
5412
  const trimmed = (rawOutput ?? "").trim();
5440
- const outputHash = trimmed.length === 0 ? "empty" : createHash9("sha256").update(trimmed).digest("hex").slice(0, 12);
5413
+ const outputHash = trimmed.length === 0 ? "empty" : createHash8("sha256").update(trimmed).digest("hex").slice(0, 12);
5441
5414
  log(`[claude-scheduler] Suppressing delivery for '${codeName}' (template=${templateId}, task=${delivery?.taskId ?? "n/a"}) \u2014 output_len=${trimmed.length} output_hash=${outputHash}`);
5442
5415
  if (classification.suppressedNotes) {
5443
- const notesHash = createHash9("sha256").update(classification.suppressedNotes).digest("hex").slice(0, 12);
5416
+ const notesHash = createHash8("sha256").update(classification.suppressedNotes).digest("hex").slice(0, 12);
5444
5417
  log(`[claude-scheduler] Suppressed notes for '${codeName}' (task=${delivery?.taskId ?? "n/a"}) \u2014 notes_len=${classification.suppressedNotes.length} notes_hash=${notesHash}`);
5445
5418
  }
5446
5419
  if (delivery?.mode === "announce" && delivery.to) {
@@ -5506,7 +5479,7 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
5506
5479
  }
5507
5480
 
5508
5481
  // src/lib/manager/scheduler/execution.ts
5509
- import { createHash as createHash10 } from "crypto";
5482
+ import { createHash as createHash9 } from "crypto";
5510
5483
  import { homedir as homedir8 } from "os";
5511
5484
  import { join as join18 } from "path";
5512
5485
  function claudePidFilePath() {
@@ -5530,10 +5503,10 @@ function unregisterClaudeSpawn(pid) {
5530
5503
  }
5531
5504
  async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData) {
5532
5505
  const codeName = agent.code_name;
5533
- const stableTasksHash = createHash10("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
5534
- const boardHash = boardItems.length > 0 ? createHash10("sha256").update(JSON.stringify(boardItems.map((b) => ({ id: b.id, title: b.title, status: b.status, priority: b.priority, deliverable: b.deliverable })))).digest("hex").slice(0, 16) : "empty";
5506
+ const stableTasksHash = createHash9("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
5507
+ const boardHash = boardItems.length > 0 ? createHash9("sha256").update(JSON.stringify(boardItems.map((b) => ({ id: b.id, title: b.title, status: b.status, priority: b.priority, deliverable: b.deliverable })))).digest("hex").slice(0, 16) : "empty";
5535
5508
  const resolvedModels = resolveModelChain(refreshData);
5536
- const modelsHash = createHash10("sha256").update(JSON.stringify(resolvedModels)).digest("hex").slice(0, 16);
5509
+ const modelsHash = createHash9("sha256").update(JSON.stringify(resolvedModels)).digest("hex").slice(0, 16);
5537
5510
  const combinedHash = `${stableTasksHash}:${boardHash}:${modelsHash}`;
5538
5511
  const prevHash = agentState.knownTasksHashes.get(agent.agent_id);
5539
5512
  if (combinedHash !== prevHash) {
@@ -5571,7 +5544,7 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
5571
5544
  }
5572
5545
 
5573
5546
  // src/lib/opencode-slack-ingest.ts
5574
- import { createHash as createHash11 } from "crypto";
5547
+ import { createHash as createHash10 } from "crypto";
5575
5548
 
5576
5549
  // ../../packages/core/dist/channels/slack-rich-text.js
5577
5550
  var MAX_DEPTH = 12;
@@ -6507,7 +6480,7 @@ function startSlackIngest(config2) {
6507
6480
  // src/lib/opencode-slack-ingest.ts
6508
6481
  var ingests = /* @__PURE__ */ new Map();
6509
6482
  function fingerprint(params) {
6510
- return createHash11("sha256").update(
6483
+ return createHash10("sha256").update(
6511
6484
  JSON.stringify({
6512
6485
  appToken: params.appToken,
6513
6486
  botToken: params.botToken,
@@ -6588,7 +6561,7 @@ function stopAllOpencodeSlackIngests(log2) {
6588
6561
  }
6589
6562
 
6590
6563
  // src/lib/manager/opencode-scheduler.ts
6591
- import { createHash as createHash12 } from "crypto";
6564
+ import { createHash as createHash11 } from "crypto";
6592
6565
  var MAX_OPENCODE_SCHED_CONCURRENCY = 2;
6593
6566
  var opencodeSchedulerStates = /* @__PURE__ */ new Map();
6594
6567
  var inFlightOpencodeTasks = /* @__PURE__ */ new Set();
@@ -6602,7 +6575,7 @@ function shouldDeliver(task, reply) {
6602
6575
  }
6603
6576
  async function syncAndCheckOpencodeScheduler(agent, tasks, refreshData) {
6604
6577
  const codeName = agent.code_name;
6605
- const tasksHash = createHash12("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
6578
+ const tasksHash = createHash11("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
6606
6579
  if (knownOpencodeTaskHashes.get(agent.agent_id) !== tasksHash) {
6607
6580
  const taskInputs = tasks.map((t) => buildSchedulerTaskInput(t));
6608
6581
  const state8 = syncTasksToScheduler(codeName, agent.agent_id, taskInputs);
@@ -6680,8 +6653,8 @@ async function fireOpencodeScheduledTask(agent, task) {
6680
6653
  }
6681
6654
 
6682
6655
  // src/lib/opencode-telegram-ingest.ts
6683
- import { createHash as createHash13 } from "crypto";
6684
- import { existsSync as existsSync9, mkdirSync as mkdirSync7, readFileSync as readFileSync15, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync9 } from "fs";
6656
+ import { createHash as createHash12 } from "crypto";
6657
+ import { existsSync as existsSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync15, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync9 } from "fs";
6685
6658
  import { randomUUID } from "crypto";
6686
6659
  import { join as join19 } from "path";
6687
6660
 
@@ -7216,7 +7189,7 @@ function anySignal(signals) {
7216
7189
  // src/lib/opencode-telegram-ingest.ts
7217
7190
  var ingests2 = /* @__PURE__ */ new Map();
7218
7191
  function fingerprint2(params) {
7219
- return createHash13("sha256").update(
7192
+ return createHash12("sha256").update(
7220
7193
  JSON.stringify({
7221
7194
  botToken: params.botToken,
7222
7195
  allowedChats: [...params.allowedChats].sort(),
@@ -7258,7 +7231,7 @@ function createFileOffsetStore(codeName, log2, currentBotId) {
7258
7231
  if (!filePath || !dir) return;
7259
7232
  const tmpPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;
7260
7233
  try {
7261
- mkdirSync7(dir, { recursive: true, mode: 448 });
7234
+ mkdirSync6(dir, { recursive: true, mode: 448 });
7262
7235
  writeFileSync9(
7263
7236
  tmpPath,
7264
7237
  JSON.stringify({
@@ -7490,7 +7463,7 @@ function partitionActionableByPoison(actionable, states, config2) {
7490
7463
  }
7491
7464
 
7492
7465
  // src/lib/restart-flags.ts
7493
- import { existsSync as existsSync10, mkdirSync as mkdirSync8, readdirSync as readdirSync4, readFileSync as readFileSync16, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync10 } from "fs";
7466
+ import { existsSync as existsSync10, mkdirSync as mkdirSync7, readdirSync as readdirSync4, readFileSync as readFileSync16, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync10 } from "fs";
7494
7467
  import { homedir as homedir9 } from "os";
7495
7468
  import { join as join20 } from "path";
7496
7469
  import { randomUUID as randomUUID2 } from "crypto";
@@ -8234,6 +8207,7 @@ function hasRevokedResiduals(state7) {
8234
8207
  return state7.gatewayRunning || state7.portAllocated || state7.provisionDirExists;
8235
8208
  }
8236
8209
  var pendingSessionRestarts = /* @__PURE__ */ new Map();
8210
+ var lastRestartWasExternal = /* @__PURE__ */ new Map();
8237
8211
  var pendingRestartVerifications = /* @__PURE__ */ new Map();
8238
8212
  var restartBreaker = new RestartBreaker();
8239
8213
  var reportedTrips = /* @__PURE__ */ new Map();
@@ -8772,7 +8746,7 @@ var sessionLaunchManagedStructure = /* @__PURE__ */ new Map();
8772
8746
  function projectMcpHash(_codeName, projectDir) {
8773
8747
  try {
8774
8748
  const raw = readFileSync17(join21(projectDir, ".mcp.json"), "utf-8");
8775
- return createHash14("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
8749
+ return createHash13("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
8776
8750
  } catch {
8777
8751
  return null;
8778
8752
  }
@@ -8934,6 +8908,7 @@ function stopPersistentSessionAndForgetMcpBaseline(codeName, breakerReason, gate
8934
8908
  }
8935
8909
  cancelPendingSessionRestart(codeName);
8936
8910
  stopPersistentSession(codeName, log);
8911
+ lastRestartWasExternal.set(codeName, gateReason !== "mcp-presence-reaper");
8937
8912
  runningMcpHashes.delete(codeName);
8938
8913
  runningMcpServerKeys.delete(codeName);
8939
8914
  runningChannelSecretHashes.delete(codeName);
@@ -9120,7 +9095,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
9120
9095
  var lastVersionCheckAt = 0;
9121
9096
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
9122
9097
  var lastResponsivenessProbeAt = 0;
9123
- var agtCliVersion = true ? "0.28.383" : "dev";
9098
+ var agtCliVersion = true ? "0.28.385" : "dev";
9124
9099
  function resolveBrewPath(execFileSync2) {
9125
9100
  try {
9126
9101
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -9215,7 +9190,7 @@ async function ensureToolkitCli(toolkitSlug) {
9215
9190
  toolkitCliEnsured.add(toolkitSlug);
9216
9191
  return;
9217
9192
  }
9218
- brewBinDir = dirname6(brewPath);
9193
+ brewBinDir = dirname5(brewPath);
9219
9194
  const isRoot = typeof process.getuid === "function" && process.getuid() === 0;
9220
9195
  log(`[toolkit-install] ${toolkitSlug}: installing via brew (${pkg})\u2026`);
9221
9196
  if (isRoot) {
@@ -9425,7 +9400,7 @@ function ensureClaudeManagedSettings(path = claudeManagedSettingsPath()) {
9425
9400
  }
9426
9401
  if (settings.channelsEnabled === true) return "ok";
9427
9402
  settings.channelsEnabled = true;
9428
- mkdirSync9(dirname6(path), { recursive: true });
9403
+ mkdirSync8(dirname5(path), { recursive: true });
9429
9404
  writeFileSync11(path, `${JSON.stringify(settings, null, 2)}
9430
9405
  `);
9431
9406
  log(`[managed-settings] set channelsEnabled:true in ${path} (ENG-5786 \u2014 unblocks Claude Code channels)`);
@@ -9521,7 +9496,7 @@ async function ensureFrameworkBinary(frameworkId) {
9521
9496
  log(`Claude Code install failed: ${err.message}`);
9522
9497
  return;
9523
9498
  }
9524
- const brewBinDir = dirname6(brewPath);
9499
+ const brewBinDir = dirname5(brewPath);
9525
9500
  if (!process.env.PATH?.split(":").includes(brewBinDir)) {
9526
9501
  process.env.PATH = `${brewBinDir}:${process.env.PATH ?? ""}`;
9527
9502
  }
@@ -9955,7 +9930,7 @@ function ensureEvalEmptyMcpConfig() {
9955
9930
  if (evalEmptyMcpConfigPath && existsSync11(evalEmptyMcpConfigPath)) return evalEmptyMcpConfigPath;
9956
9931
  const dir = join21(homedir10(), ".augmented");
9957
9932
  try {
9958
- mkdirSync9(dir, { recursive: true });
9933
+ mkdirSync8(dir, { recursive: true });
9959
9934
  } catch {
9960
9935
  }
9961
9936
  const p = join21(dir, ".eval-empty-mcp.json");
@@ -10249,7 +10224,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
10249
10224
  if (codeNames.length === 0) return;
10250
10225
  void (async () => {
10251
10226
  try {
10252
- const { collectDiagnostics } = await import("../persistent-session-4LAOXUQD.js");
10227
+ const { collectDiagnostics } = await import("../persistent-session-MDQVHXKX.js");
10253
10228
  await api.post("/host/heartbeat", {
10254
10229
  host_id: hostId,
10255
10230
  agent_diagnostics: collectDiagnostics(codeNames)
@@ -10348,7 +10323,7 @@ async function pollCycle() {
10348
10323
  }
10349
10324
  try {
10350
10325
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
10351
- const { collectDiagnostics } = await import("../persistent-session-4LAOXUQD.js");
10326
+ const { collectDiagnostics } = await import("../persistent-session-MDQVHXKX.js");
10352
10327
  const diagCodeNames = [...agentState.persistentSessionAgents];
10353
10328
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
10354
10329
  let tailscaleHostname;
@@ -10378,7 +10353,7 @@ async function pollCycle() {
10378
10353
  claudeAuth = await detectClaudeAuth();
10379
10354
  } catch (err) {
10380
10355
  const errText = err instanceof Error ? err.message : String(err);
10381
- const errId = createHash14("sha256").update(errText).digest("hex").slice(0, 12);
10356
+ const errId = createHash13("sha256").update(errText).digest("hex").slice(0, 12);
10382
10357
  log(`Claude auth detection failed (error_id=${errId})`);
10383
10358
  }
10384
10359
  const hostHasClaudeCode = state6.agents.some(
@@ -10503,7 +10478,7 @@ async function pollCycle() {
10503
10478
  const {
10504
10479
  collectResponsivenessProbes,
10505
10480
  getResponsivenessIntervalMs
10506
- } = await import("../responsiveness-probe-XLANB346.js");
10481
+ } = await import("../responsiveness-probe-CG7XM7GL.js");
10507
10482
  const probeIntervalMs = getResponsivenessIntervalMs();
10508
10483
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
10509
10484
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -10535,7 +10510,7 @@ async function pollCycle() {
10535
10510
  collectResponsivenessProbes,
10536
10511
  livePendingInboundOldestAgeSeconds,
10537
10512
  parkPendingInbound
10538
- } = await import("../responsiveness-probe-XLANB346.js");
10513
+ } = await import("../responsiveness-probe-CG7XM7GL.js");
10539
10514
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-HYOOQV4A.js");
10540
10515
  const wedgeNow = /* @__PURE__ */ new Date();
10541
10516
  const liveAgents = agentState.persistentSessionAgents;
@@ -11337,7 +11312,7 @@ async function processAgent(agent, agentStates) {
11337
11312
  try {
11338
11313
  const artifacts = generateArtifacts(agent, refreshData, frameworkAdapter);
11339
11314
  const changedFiles = [];
11340
- mkdirSync9(agentDir, { recursive: true });
11315
+ mkdirSync8(agentDir, { recursive: true });
11341
11316
  for (const artifact of artifacts) {
11342
11317
  const filePath = join21(agentDir, artifact.relativePath);
11343
11318
  let existingHash;
@@ -11415,7 +11390,7 @@ async function processAgent(agent, agentStates) {
11415
11390
  log(`${verb} '${agent.code_name}': ${fileNames}`);
11416
11391
  for (const file of changedFiles) {
11417
11392
  const filePath = join21(agentDir, file.relativePath);
11418
- mkdirSync9(dirname6(filePath), { recursive: true });
11393
+ mkdirSync8(dirname5(filePath), { recursive: true });
11419
11394
  if (file.relativePath === ".mcp.json") {
11420
11395
  safeWriteJsonAtomic(filePath, file.content, { mode: 384 });
11421
11396
  } else {
@@ -11747,7 +11722,7 @@ async function processAgent(agent, agentStates) {
11747
11722
  const writeDmNoticeMarkers = isChannelAddRestart ? () => {
11748
11723
  try {
11749
11724
  const agentAugmentedDir = join21(homedir10(), ".augmented", agent.code_name);
11750
- mkdirSync9(agentAugmentedDir, { recursive: true });
11725
+ mkdirSync8(agentAugmentedDir, { recursive: true });
11751
11726
  const markerJson = JSON.stringify({
11752
11727
  version: 1,
11753
11728
  at: (/* @__PURE__ */ new Date()).toISOString(),
@@ -11830,7 +11805,7 @@ async function processAgent(agent, agentStates) {
11830
11805
  const behaviourSubset = extractMsTeamsBehaviourSubset(
11831
11806
  msteamsEntry?.config
11832
11807
  );
11833
- const behaviourHash = createHash14("sha256").update(canonicalJson(behaviourSubset)).digest("hex");
11808
+ const behaviourHash = createHash13("sha256").update(canonicalJson(behaviourSubset)).digest("hex");
11834
11809
  const prevBehaviourHash = agentState.knownMsTeamsBehaviourHashes.get(agent.agent_id);
11835
11810
  const msteamsBehaviourRestrictive = isMsTeamsBehaviourRestrictive(behaviourSubset);
11836
11811
  const behaviourDecision = decideSenderPolicyRestart({
@@ -11886,7 +11861,7 @@ async function processAgent(agent, agentStates) {
11886
11861
  const slackBehaviourSubset = extractSlackBehaviourSubset(
11887
11862
  slackEntry?.config
11888
11863
  );
11889
- const slackBehaviourHash = createHash14("sha256").update(canonicalJson(slackBehaviourSubset)).digest("hex");
11864
+ const slackBehaviourHash = createHash13("sha256").update(canonicalJson(slackBehaviourSubset)).digest("hex");
11890
11865
  const prevSlackBehaviourHash = agentState.knownSlackBehaviourHashes.get(agent.agent_id);
11891
11866
  const slackBehaviourRestrictive = isSlackBehaviourRestrictive(slackBehaviourSubset);
11892
11867
  const slackBehaviourDecision = decideSenderPolicyRestart({
@@ -11944,8 +11919,8 @@ async function processAgent(agent, agentStates) {
11944
11919
  try {
11945
11920
  const agentProvisionDir = agentDir;
11946
11921
  const projectDir = join21(homedir10(), ".augmented", agent.code_name, "project");
11947
- mkdirSync9(agentProvisionDir, { recursive: true });
11948
- mkdirSync9(projectDir, { recursive: true });
11922
+ mkdirSync8(agentProvisionDir, { recursive: true });
11923
+ mkdirSync8(projectDir, { recursive: true });
11949
11924
  const provisionMcpPath = join21(agentProvisionDir, ".mcp.json");
11950
11925
  const projectMcpPath = join21(projectDir, ".mcp.json");
11951
11926
  let mcpConfig = { mcpServers: {} };
@@ -12270,10 +12245,10 @@ async function processAgent(agent, agentStates) {
12270
12245
  desiredEntries.push({ serverId, url, headers: mcpHeaders, name: tk.toolkit_name });
12271
12246
  }
12272
12247
  const hashBasis = desiredEntries.slice().sort((a, b) => a.serverId.localeCompare(b.serverId)).map((e) => {
12273
- const headersHash = createHash14("sha256").update(canonicalJson(e.headers ?? {})).digest("hex").slice(0, 16);
12248
+ const headersHash = createHash13("sha256").update(canonicalJson(e.headers ?? {})).digest("hex").slice(0, 16);
12274
12249
  return `${e.serverId}|${e.url}|${headersHash}`;
12275
12250
  }).join("\n");
12276
- const mcpHash = createHash14("sha256").update(hashBasis).digest("hex").slice(0, 16);
12251
+ const mcpHash = createHash13("sha256").update(hashBasis).digest("hex").slice(0, 16);
12277
12252
  const prevMcpHash = agentState.knownManagedMcpHashes.get(agent.agent_id);
12278
12253
  const structureHash = managedMcpStructureHash(desiredEntries);
12279
12254
  const prevStructureHash = agentState.knownManagedMcpStructure.get(agent.agent_id);
@@ -12288,7 +12263,7 @@ async function processAgent(agent, agentStates) {
12288
12263
  if (mcpHash !== prevMcpHash) {
12289
12264
  for (const e of desiredEntries) {
12290
12265
  frameworkAdapter.writeMcpServer(agent.code_name, e.serverId, { url: e.url, headers: e.headers });
12291
- const urlHash = createHash14("sha256").update(e.url).digest("hex").slice(0, 12);
12266
+ const urlHash = createHash13("sha256").update(e.url).digest("hex").slice(0, 12);
12292
12267
  log(`[managed-toolkit] ${agent.code_name}: wrote '${e.name}' (serverId=${e.serverId}, url_hash=${urlHash})`);
12293
12268
  }
12294
12269
  if (frameworkAdapter.removeMcpServer && frameworkAdapter.getMcpPath) {
@@ -12397,7 +12372,7 @@ async function processAgent(agent, agentStates) {
12397
12372
  if (frameworkAdapter.installSkillFiles) {
12398
12373
  const currentIntegrationSkillIds = /* @__PURE__ */ new Set();
12399
12374
  const installedIntegrationSkills = [];
12400
- const { createHash: createHash15 } = await import("crypto");
12375
+ const { createHash: createHash14 } = await import("crypto");
12401
12376
  const refreshAny = refreshData;
12402
12377
  const contexts = refreshAny.integration_contexts ?? refreshAny.plugin_contexts ?? [];
12403
12378
  const contextBySlug = /* @__PURE__ */ new Map();
@@ -12426,7 +12401,7 @@ async function processAgent(agent, agentStates) {
12426
12401
  )
12427
12402
  }));
12428
12403
  const bundle = buildIntegrationBundle(renderedScopes);
12429
- const contentHash = createHash15("sha256").update(bundleFingerprint(bundle.files)).digest("hex").slice(0, 12);
12404
+ const contentHash = createHash14("sha256").update(bundleFingerprint(bundle.files)).digest("hex").slice(0, 12);
12430
12405
  const hashKey = `plugin-skill:${agent.agent_id}:${integrationSkillId}`;
12431
12406
  if (agentState.knownSkillHashes.get(hashKey) === contentHash) continue;
12432
12407
  frameworkAdapter.installSkillFiles(agent.code_name, integrationSkillId, bundle.files);
@@ -12493,7 +12468,7 @@ async function processAgent(agent, agentStates) {
12493
12468
  const plan = planGlobalSkillSync(
12494
12469
  [...globalSkillsPayload ?? [], ...sharedSkillsPayload ?? []],
12495
12470
  prevIds,
12496
- (content) => createHash15("sha256").update(content).digest("hex").slice(0, 12),
12471
+ (content) => createHash14("sha256").update(content).digest("hex").slice(0, 12),
12497
12472
  (skillId) => agentState.knownSkillHashes.get(`global-skill:${agent.agent_id}:${skillId}`),
12498
12473
  { desiredResolved }
12499
12474
  );
@@ -12544,7 +12519,7 @@ async function processAgent(agent, agentStates) {
12544
12519
  const slug = hook.integration_slug ?? hook.plugin_slug;
12545
12520
  if (!slug) continue;
12546
12521
  try {
12547
- const scriptHash = createHash15("sha256").update(hook.script).digest("hex").slice(0, 12);
12522
+ const scriptHash = createHash14("sha256").update(hook.script).digest("hex").slice(0, 12);
12548
12523
  const hookKey = `${agent.agent_id}:${frameworkAdapter.id}:plugin-hook:${slug}:on_install`;
12549
12524
  if (agentState.knownSkillHashes.get(hookKey) === scriptHash) continue;
12550
12525
  const result = await frameworkAdapter.executePluginHook({
@@ -12559,9 +12534,9 @@ async function processAgent(agent, agentStates) {
12559
12534
  } else if (result.timedOut) {
12560
12535
  log(`Integration hook on_install '${slug}' TIMED OUT for '${agent.code_name}' after ${result.durationMs}ms`);
12561
12536
  } else {
12562
- const stderrHash = createHash15("sha256").update(result.stderr).digest("hex").slice(0, 12);
12537
+ const stderrHash = createHash14("sha256").update(result.stderr).digest("hex").slice(0, 12);
12563
12538
  const missingCmd = result.exitCode === 127 ? extractCommandNotFound(result.stderr) : null;
12564
- const missingCmdHash = missingCmd ? createHash15("sha256").update(missingCmd).digest("hex").slice(0, 8) : null;
12539
+ const missingCmdHash = missingCmd ? createHash14("sha256").update(missingCmd).digest("hex").slice(0, 8) : null;
12565
12540
  log(
12566
12541
  `Integration hook on_install '${slug}' exited ${result.exitCode} for '${agent.code_name}' ` + (missingCmdHash ? `[missing_command_hash=${missingCmdHash}] ` : "") + `[stderr_hash=${stderrHash} stderr_len=${result.stderr.length}]`
12567
12542
  );
@@ -12750,6 +12725,14 @@ async function processAgent(agent, agentStates) {
12750
12725
  // but-not-yet-live MCP, so don't let the reaper re-fire + inflate the
12751
12726
  // McpReaperRestartsHourly metric into a false flapping alarm.
12752
12727
  restartPending: pendingSessionRestarts.has(agent.code_name),
12728
+ // ENG-8013 (storm-awareness): tell the reaper whether THIS session
12729
+ // generation was born from an external respawn (integration-change /
12730
+ // channel-set-change / day-rollover / wedge / operator restart, or a
12731
+ // storm) vs the reaper's own recovery restart. When external, a missing
12732
+ // channel MCP is churn collateral and must not accrue quarantine budget,
12733
+ // the durable fix for the ENG-8003 storm-quarantine incident. Absent map
12734
+ // entry (first boot) → false → count normally.
12735
+ currentGenerationExternallyStarted: lastRestartWasExternal.get(agent.code_name) ?? false,
12753
12736
  // ENG-5441 / ENG-5547: a mcp-presence-reaper restart counts against
12754
12737
  // the agent-wide breaker ONLY when several distinct MCP servers are
12755
12738
  // missing at once — a thrashing collection that rotates restarts of
@@ -13350,7 +13333,7 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
13350
13333
  const ctx = getLastFailureContext(codeName);
13351
13334
  const recovery = prepareForRespawn(codeName);
13352
13335
  const tailSummary = !ctx.tail ? "" : KNOWN_SAFE_TAIL_SIGNATURES.has(ctx.signature) ? `; last pane output (${PANE_TAIL_PREVIEW_LINES} of ~20 lines):
13353
- ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash14("sha256").update(ctx.tail).digest("hex").slice(0, 12)} (raw at ~/.augmented/${codeName}/pane.log)`;
13336
+ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash13("sha256").update(ctx.tail).digest("hex").slice(0, 12)} (raw at ~/.augmented/${codeName}/pane.log)`;
13354
13337
  const sigSummary = ctx.signature !== "unknown" ? `; signature=${ctx.signature}` : "";
13355
13338
  const recoverySummary = recovery ? `; recovery=${recovery}` : "";
13356
13339
  log(
@@ -13364,7 +13347,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash14("sha256")
13364
13347
  );
13365
13348
  getHostId().then((hostId) => {
13366
13349
  if (!hostId) return;
13367
- const paneTailHash = zombie.paneTail ? `sha256:${createHash14("sha256").update(zombie.paneTail).digest("hex").slice(0, 12)}` : null;
13350
+ const paneTailHash = zombie.paneTail ? `sha256:${createHash13("sha256").update(zombie.paneTail).digest("hex").slice(0, 12)}` : null;
13368
13351
  return api.post("/host/events", {
13369
13352
  host_id: hostId,
13370
13353
  agent_code_name: codeName,
@@ -13513,7 +13496,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash14("sha256")
13513
13496
  if (!claudeAuthTupleBySession.has(codeName)) {
13514
13497
  claudeAuthTupleBySession.set(codeName, currentAuthTuple);
13515
13498
  }
13516
- const stableTasksHash = createHash14("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
13499
+ const stableTasksHash = createHash13("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
13517
13500
  const prevHash = agentState.knownTasksHashes.get(agent.agent_id);
13518
13501
  if (stableTasksHash !== prevHash) {
13519
13502
  const taskInputs = tasks.map((t) => buildSchedulerTaskInput(t));
@@ -13730,7 +13713,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
13730
13713
  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}`));
13731
13714
  void (async () => {
13732
13715
  try {
13733
- const { collectDiagnostics } = await import("../persistent-session-4LAOXUQD.js");
13716
+ const { collectDiagnostics } = await import("../persistent-session-MDQVHXKX.js");
13734
13717
  await api.post("/host/heartbeat", {
13735
13718
  host_id: hostId,
13736
13719
  agent_diagnostics: collectDiagnostics([codeName])
@@ -13780,7 +13763,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
13780
13763
  }
13781
13764
  try {
13782
13765
  const hostId = await getHostId();
13783
- const { collectDiagnostics } = await import("../persistent-session-4LAOXUQD.js");
13766
+ const { collectDiagnostics } = await import("../persistent-session-MDQVHXKX.js");
13784
13767
  await api.post("/host/heartbeat", {
13785
13768
  host_id: hostId,
13786
13769
  agent_diagnostics: collectDiagnostics([codeName])
@@ -14066,7 +14049,7 @@ async function processDirectChatMessage(agent, msg) {
14066
14049
  if (useDoorbell) {
14067
14050
  try {
14068
14051
  const doorbell = directChatDoorbellPath(agent.agentId, homedir10());
14069
- mkdirSync9(dirname6(doorbell), { recursive: true });
14052
+ mkdirSync8(dirname5(doorbell), { recursive: true });
14070
14053
  writeFileSync11(doorbell, String(Date.now()));
14071
14054
  log(`[direct-chat] Doorbell rung for '${agent.codeName}' (msg=${msg.id}) \u2014 in-session MCP will pull via the cursor`);
14072
14055
  return;
@@ -14176,7 +14159,7 @@ ${formatRunMarker(run_id)}` : KANBAN_CHECK_COMMAND;
14176
14159
  if (run_id) openInjectedRunByCode.set(codeName, run_id);
14177
14160
  try {
14178
14161
  const doorbell = directChatDoorbellPath(agentId, homedir10());
14179
- mkdirSync9(dirname6(doorbell), { recursive: true });
14162
+ mkdirSync8(dirname5(doorbell), { recursive: true });
14180
14163
  writeFileSync11(doorbell, String(Date.now()));
14181
14164
  } catch (err) {
14182
14165
  log(`[kanban] doorbell ring failed for '${codeName}': ${err.message} (notice still queued)`);
@@ -14233,7 +14216,7 @@ async function processClaudePairSessions(agents) {
14233
14216
  killPairSession,
14234
14217
  pairTmuxSession,
14235
14218
  finalizeClaudePairOnboarding
14236
- } = await import("../claude-pair-runtime-PERAQ2PL.js");
14219
+ } = await import("../claude-pair-runtime-OIK6HKPS.js");
14237
14220
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
14238
14221
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
14239
14222
  const killed = await killPairSession(pairTmuxSession(pairId));
@@ -14503,7 +14486,7 @@ async function syncMemories(agent, configDir, log2) {
14503
14486
  if (!file.endsWith(".md")) continue;
14504
14487
  try {
14505
14488
  const raw = readFileSync17(join21(memoryDir, file), "utf-8");
14506
- const fileHash = createHash14("sha256").update(raw).digest("hex").slice(0, 16);
14489
+ const fileHash = createHash13("sha256").update(raw).digest("hex").slice(0, 16);
14507
14490
  currentHashes.set(file, fileHash);
14508
14491
  if (prevHashes.get(file) === fileHash) continue;
14509
14492
  const parsed = parseMemoryFile(raw, file.replace(/\.md$/, ""));
@@ -14541,21 +14524,21 @@ async function syncMemories(agent, configDir, log2) {
14541
14524
  }
14542
14525
  async function downloadMemories(agent, memoryDir, log2, { force }) {
14543
14526
  const localFiles = existsSync11(memoryDir) ? readdirSync5(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
14544
- const localListHash = createHash14("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
14527
+ const localListHash = createHash13("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
14545
14528
  const prevLocalHash = lastLocalFileHash.get(agent.agent_id);
14546
14529
  const prevDownload = lastDownloadHash.get(agent.agent_id);
14547
14530
  try {
14548
14531
  const dbMemories = await api.post("/host/memories", {
14549
14532
  agent_id: agent.agent_id
14550
14533
  });
14551
- const responseHash = createHash14("sha256").update(JSON.stringify(dbMemories.memories ?? [])).digest("hex").slice(0, 16);
14534
+ const responseHash = createHash13("sha256").update(JSON.stringify(dbMemories.memories ?? [])).digest("hex").slice(0, 16);
14552
14535
  if (!force && prevDownload && prevLocalHash === localListHash && lastDownloadHash.get(agent.agent_id) === responseHash) {
14553
14536
  return true;
14554
14537
  }
14555
14538
  lastDownloadHash.set(agent.agent_id, responseHash);
14556
14539
  lastLocalFileHash.set(agent.agent_id, localListHash);
14557
14540
  if (dbMemories.memories?.length) {
14558
- mkdirSync9(memoryDir, { recursive: true });
14541
+ mkdirSync8(memoryDir, { recursive: true });
14559
14542
  let written = 0;
14560
14543
  let overwritten = 0;
14561
14544
  for (let i = 0; i < dbMemories.memories.length; i++) {
@@ -14587,7 +14570,7 @@ ${mem.content}
14587
14570
  }
14588
14571
  if (written > 0 || overwritten > 0) {
14589
14572
  const updatedFiles = readdirSync5(memoryDir).filter((f) => f.endsWith(".md")).sort();
14590
- lastLocalFileHash.set(agent.agent_id, createHash14("sha256").update(updatedFiles.join(",")).digest("hex").slice(0, 16));
14573
+ lastLocalFileHash.set(agent.agent_id, createHash13("sha256").update(updatedFiles.join(",")).digest("hex").slice(0, 16));
14591
14574
  log2(`Memory download for '${agent.code_name}': wrote ${written} new, overwrote ${overwritten} stale`);
14592
14575
  }
14593
14576
  }
@@ -14982,8 +14965,8 @@ function restartRunningChannelMcps(basenames) {
14982
14965
  }
14983
14966
  function deployMcpAssets() {
14984
14967
  const targetDir = join21(homedir10(), ".augmented", "_mcp");
14985
- mkdirSync9(targetDir, { recursive: true });
14986
- const moduleDir = dirname6(fileURLToPath(import.meta.url));
14968
+ mkdirSync8(targetDir, { recursive: true });
14969
+ const moduleDir = dirname5(fileURLToPath(import.meta.url));
14987
14970
  let mcpSourceDir = "";
14988
14971
  let dir = moduleDir;
14989
14972
  for (let i = 0; i < 6; i++) {
@@ -14992,7 +14975,7 @@ function deployMcpAssets() {
14992
14975
  mcpSourceDir = candidate;
14993
14976
  break;
14994
14977
  }
14995
- const parent = dirname6(dir);
14978
+ const parent = dirname5(dir);
14996
14979
  if (parent === dir) break;
14997
14980
  dir = parent;
14998
14981
  }
@@ -15004,7 +14987,7 @@ function deployMcpAssets() {
15004
14987
  const fileHash = (p) => {
15005
14988
  try {
15006
14989
  if (!existsSync11(p)) return null;
15007
- return createHash14("sha256").update(readFileSync17(p)).digest("hex");
14990
+ return createHash13("sha256").update(readFileSync17(p)).digest("hex");
15008
14991
  } catch {
15009
14992
  return null;
15010
14993
  }