@integrity-labs/agt-cli 0.24.3 → 0.24.4

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
@@ -26,7 +26,7 @@ import {
26
26
  success,
27
27
  table,
28
28
  warn
29
- } from "../chunk-KVIKKWXB.js";
29
+ } from "../chunk-3TYBPBDA.js";
30
30
  import {
31
31
  CHANNEL_REGISTRY,
32
32
  DEPLOYMENT_TEMPLATES,
@@ -3736,7 +3736,7 @@ import { execFileSync, execSync } from "child_process";
3736
3736
  import { existsSync as existsSync5, realpathSync } from "fs";
3737
3737
  import chalk17 from "chalk";
3738
3738
  import ora15 from "ora";
3739
- var cliVersion = true ? "0.24.3" : "dev";
3739
+ var cliVersion = true ? "0.24.4" : "dev";
3740
3740
  async function fetchLatestVersion() {
3741
3741
  const host2 = getHost();
3742
3742
  if (!host2) return null;
@@ -4268,7 +4268,7 @@ function handleError(err) {
4268
4268
  }
4269
4269
 
4270
4270
  // src/bin/agt.ts
4271
- var cliVersion2 = true ? "0.24.3" : "dev";
4271
+ var cliVersion2 = true ? "0.24.4" : "dev";
4272
4272
  var program = new Command();
4273
4273
  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");
4274
4274
  program.hook("preAction", (thisCommand) => {
@@ -6717,4 +6717,4 @@ export {
6717
6717
  managerInstallSystemUnitCommand,
6718
6718
  managerUninstallSystemUnitCommand
6719
6719
  };
6720
- //# sourceMappingURL=chunk-KVIKKWXB.js.map
6720
+ //# sourceMappingURL=chunk-3TYBPBDA.js.map
@@ -12,7 +12,7 @@ import {
12
12
  provisionOrientHook,
13
13
  provisionStopHook,
14
14
  requireHost
15
- } from "../chunk-KVIKKWXB.js";
15
+ } from "../chunk-3TYBPBDA.js";
16
16
  import {
17
17
  findTaskByTemplate,
18
18
  getProjectDir as getProjectDir2,
@@ -69,7 +69,7 @@ import {
69
69
  } from "../chunk-ECDTRQLA.js";
70
70
 
71
71
  // src/lib/manager-worker.ts
72
- import { createHash as createHash2 } from "crypto";
72
+ import { createHash as createHash3 } from "crypto";
73
73
  import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, appendFileSync, mkdirSync as mkdirSync2, chmodSync, existsSync as existsSync4, rmSync as rmSync2, readdirSync as readdirSync3, statSync as statSync2, unlinkSync, copyFileSync } from "fs";
74
74
  import https from "https";
75
75
  import { execFileSync as syncExecFile } from "child_process";
@@ -78,15 +78,30 @@ import { homedir as homedir4 } from "os";
78
78
  import { fileURLToPath } from "url";
79
79
 
80
80
  // src/lib/mcp-config-drift.ts
81
+ import { createHash } from "crypto";
81
82
  function decideMcpDriftAction(currentHash, knownHash) {
82
83
  if (!currentHash) return { kind: "no-config" };
83
84
  if (!knownHash) return { kind: "baseline", hash: currentHash };
84
85
  if (knownHash === currentHash) return { kind: "no-drift" };
85
86
  return { kind: "drift", previous: knownHash, current: currentHash };
86
87
  }
88
+ function decideMcpRestartOnDrift(previousKeys, currentKeys) {
89
+ if (!previousKeys || !currentKeys) {
90
+ return { restart: true, membershipUnknown: true, addedOrRemoved: [] };
91
+ }
92
+ const addedOrRemoved = [];
93
+ for (const k of currentKeys) if (!previousKeys.has(k)) addedOrRemoved.push(k);
94
+ for (const k of previousKeys) if (!currentKeys.has(k)) addedOrRemoved.push(k);
95
+ addedOrRemoved.sort();
96
+ return { restart: addedOrRemoved.length > 0, membershipUnknown: false, addedOrRemoved };
97
+ }
98
+ function managedMcpStructureHash(entries) {
99
+ const basis = entries.slice().sort((a, b) => a.serverId.localeCompare(b.serverId)).map((e) => `${e.serverId}|${Object.keys(e.headers ?? {}).sort().join(",")}`).join("\n");
100
+ return createHash("sha256").update(basis).digest("hex").slice(0, 16);
101
+ }
87
102
 
88
103
  // src/lib/integration-hash.ts
89
- import { createHash } from "crypto";
104
+ import { createHash as createHash2 } from "crypto";
90
105
  function canonicalize(value) {
91
106
  if (Array.isArray(value)) return value.map(canonicalize);
92
107
  if (value && typeof value === "object") {
@@ -103,7 +118,7 @@ function computeIntegrationsHash(integrations) {
103
118
  const payload = integrations.map(
104
119
  (i) => `${i.definition_id}:${JSON.stringify(canonicalize(i.credentials ?? {}))}:${JSON.stringify(canonicalize(i.config ?? {}))}`
105
120
  );
106
- return createHash("sha256").update(JSON.stringify(payload)).digest("hex").slice(0, 16);
121
+ return createHash2("sha256").update(JSON.stringify(payload)).digest("hex").slice(0, 16);
107
122
  }
108
123
 
109
124
  // src/lib/stale-mcp-reaper.ts
@@ -2627,7 +2642,7 @@ var runningMcpServerKeys = /* @__PURE__ */ new Map();
2627
2642
  function projectMcpHash(_codeName, projectDir) {
2628
2643
  try {
2629
2644
  const raw = readFileSync5(join6(projectDir, ".mcp.json"), "utf-8");
2630
- return createHash2("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
2645
+ return createHash3("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
2631
2646
  } catch {
2632
2647
  return null;
2633
2648
  }
@@ -2671,33 +2686,34 @@ function checkMcpConfigDriftAndScheduleRestart(codeName, projectDir) {
2671
2686
  }
2672
2687
  case "drift": {
2673
2688
  log(
2674
- `[hot-reload] .mcp.json content changed for '${codeName}' (${action.previous.slice(0, 12)} \u2192 ${action.current.slice(0, 12)}); scheduling restart (ENG-4897)`
2689
+ `[hot-reload] .mcp.json content changed for '${codeName}' (${action.previous.slice(0, 12)} \u2192 ${action.current.slice(0, 12)}) (ENG-4897)`
2675
2690
  );
2676
2691
  const previousKeys = runningMcpServerKeys.get(codeName);
2677
2692
  const currentKeys = projectMcpKeys(codeName, projectDir);
2678
- if (!previousKeys || !currentKeys) {
2693
+ const decision = decideMcpRestartOnDrift(previousKeys, currentKeys);
2694
+ if (decision.membershipUnknown) {
2679
2695
  clearPresenceReaperState(codeName);
2680
2696
  log(
2681
- `[hot-reload] .mcp.json key membership unavailable for '${codeName}' \u2014 clearing full presence-reaper state (ENG-5285)`
2697
+ `[hot-reload] .mcp.json key membership unavailable for '${codeName}' \u2014 clearing full presence-reaper state and restarting (ENG-5285/ENG-5537)`
2698
+ );
2699
+ } else if (decision.restart) {
2700
+ clearPresenceReaperStateForKeys(codeName, new Set(decision.addedOrRemoved));
2701
+ log(
2702
+ `[hot-reload] .mcp.json membership changed for '${codeName}': ${decision.addedOrRemoved.length} key(s) added/removed [${decision.addedOrRemoved.join(", ")}] \u2014 reaper state cleared for those keys only (ENG-5285)`
2682
2703
  );
2683
2704
  } else {
2684
- const addedOrRemoved = /* @__PURE__ */ new Set();
2685
- for (const k of currentKeys) if (!previousKeys.has(k)) addedOrRemoved.add(k);
2686
- for (const k of previousKeys) if (!currentKeys.has(k)) addedOrRemoved.add(k);
2687
- if (addedOrRemoved.size > 0) {
2688
- clearPresenceReaperStateForKeys(codeName, addedOrRemoved);
2689
- log(
2690
- `[hot-reload] .mcp.json membership changed for '${codeName}': ${addedOrRemoved.size} key(s) added/removed [${Array.from(addedOrRemoved).sort().join(", ")}] \u2014 reaper state cleared for those keys only (ENG-5285)`
2691
- );
2692
- } else {
2693
- log(
2694
- `[hot-reload] .mcp.json value-only drift for '${codeName}' \u2014 preserving presence-reaper state for the unchanged declared key set (ENG-5285)`
2695
- );
2696
- }
2705
+ log(
2706
+ `[hot-reload] .mcp.json value-only drift for '${codeName}' \u2014 preserving presence-reaper state and NOT restarting (ENG-5285/ENG-5537)`
2707
+ );
2708
+ }
2709
+ if (decision.restart) {
2710
+ scheduleSessionRestart(codeName, 0, ".mcp.json content change (ENG-4897)");
2711
+ runningMcpHashes.delete(codeName);
2712
+ runningMcpServerKeys.delete(codeName);
2713
+ } else {
2714
+ runningMcpHashes.set(codeName, action.current);
2715
+ if (currentKeys) runningMcpServerKeys.set(codeName, currentKeys);
2697
2716
  }
2698
- scheduleSessionRestart(codeName, 0, ".mcp.json content change (ENG-4897)");
2699
- runningMcpHashes.delete(codeName);
2700
- runningMcpServerKeys.delete(codeName);
2701
2717
  return;
2702
2718
  }
2703
2719
  }
@@ -2707,6 +2723,7 @@ var knownModels = /* @__PURE__ */ new Map();
2707
2723
  var knownTasksHashes = /* @__PURE__ */ new Map();
2708
2724
  var knownIntegrationHashes = /* @__PURE__ */ new Map();
2709
2725
  var knownManagedMcpHashes = /* @__PURE__ */ new Map();
2726
+ var knownManagedMcpStructure = /* @__PURE__ */ new Map();
2710
2727
  var knownSkillHashes = /* @__PURE__ */ new Map();
2711
2728
  var managedToolkitIdByAgentAndServerId = /* @__PURE__ */ new Map();
2712
2729
  function managedToolkitMapKey(agentId, serverId) {
@@ -2758,6 +2775,7 @@ function clearAgentCaches(agentId, codeName) {
2758
2775
  knownTasksHashes.delete(agentId);
2759
2776
  knownIntegrationHashes.delete(agentId);
2760
2777
  knownManagedMcpHashes.delete(agentId);
2778
+ knownManagedMcpStructure.delete(agentId);
2761
2779
  agentDisplayNames.delete(codeName);
2762
2780
  codeNameToAgentId.delete(codeName);
2763
2781
  agentFrameworkCache.delete(codeName);
@@ -2788,7 +2806,7 @@ var cachedFrameworkVersion = null;
2788
2806
  var lastVersionCheckAt = 0;
2789
2807
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
2790
2808
  var lastResponsivenessProbeAt = 0;
2791
- var agtCliVersion = true ? "0.24.3" : "dev";
2809
+ var agtCliVersion = true ? "0.24.4" : "dev";
2792
2810
  function resolveBrewPath(execFileSync4) {
2793
2811
  try {
2794
2812
  const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -3367,7 +3385,7 @@ function log(msg) {
3367
3385
  }
3368
3386
  }
3369
3387
  function sha256(content) {
3370
- return createHash2("sha256").update(content, "utf8").digest("hex");
3388
+ return createHash3("sha256").update(content, "utf8").digest("hex");
3371
3389
  }
3372
3390
  function hashFile(filePath) {
3373
3391
  try {
@@ -3777,7 +3795,7 @@ async function pollCycle() {
3777
3795
  claudeAuth = await detectClaudeAuth();
3778
3796
  } catch (err) {
3779
3797
  const errText = err instanceof Error ? err.message : String(err);
3780
- const errId = createHash2("sha256").update(errText).digest("hex").slice(0, 12);
3798
+ const errId = createHash3("sha256").update(errText).digest("hex").slice(0, 12);
3781
3799
  log(`Claude auth detection failed (error_id=${errId})`);
3782
3800
  }
3783
3801
  await api.post("/host/heartbeat", {
@@ -4497,7 +4515,7 @@ async function processAgent(agent, agentStates) {
4497
4515
  const peersForHash = channelId === "telegram" ? extractCharterTelegramPeers(refreshData.charter?.raw_content ?? "", gateContext) : channelId === "slack" ? extractCharterSlackPeers(refreshData.charter?.raw_content ?? "", gateContext) : null;
4498
4516
  const sessionModeForHash = refreshData.agent.session_mode;
4499
4517
  const CHANNEL_WRITE_VERSION = 5;
4500
- const configHash = createHash2("sha256").update(
4518
+ const configHash = createHash3("sha256").update(
4501
4519
  canonicalJson({
4502
4520
  writeVersion: CHANNEL_WRITE_VERSION,
4503
4521
  config: entry.config,
@@ -4759,15 +4777,17 @@ async function processAgent(agent, agentStates) {
4759
4777
  desiredEntries.push({ serverId, url, headers: mcpHeaders, name: tk.toolkit_name });
4760
4778
  }
4761
4779
  const hashBasis = desiredEntries.slice().sort((a, b) => a.serverId.localeCompare(b.serverId)).map((e) => {
4762
- const headersHash = createHash2("sha256").update(canonicalJson(e.headers ?? {})).digest("hex").slice(0, 16);
4780
+ const headersHash = createHash3("sha256").update(canonicalJson(e.headers ?? {})).digest("hex").slice(0, 16);
4763
4781
  return `${e.serverId}|${e.url}|${headersHash}`;
4764
4782
  }).join("\n");
4765
- const mcpHash = createHash2("sha256").update(hashBasis).digest("hex").slice(0, 16);
4783
+ const mcpHash = createHash3("sha256").update(hashBasis).digest("hex").slice(0, 16);
4766
4784
  const prevMcpHash = knownManagedMcpHashes.get(agent.agent_id);
4785
+ const structureHash = managedMcpStructureHash(desiredEntries);
4786
+ const prevStructureHash = knownManagedMcpStructure.get(agent.agent_id);
4767
4787
  if (mcpHash !== prevMcpHash) {
4768
4788
  for (const e of desiredEntries) {
4769
4789
  frameworkAdapter.writeMcpServer(agent.code_name, e.serverId, { url: e.url, headers: e.headers });
4770
- const urlHash = createHash2("sha256").update(e.url).digest("hex").slice(0, 12);
4790
+ const urlHash = createHash3("sha256").update(e.url).digest("hex").slice(0, 12);
4771
4791
  log(`[managed-toolkit] ${agent.code_name}: wrote '${e.name}' (serverId=${e.serverId}, url_hash=${urlHash})`);
4772
4792
  }
4773
4793
  if (frameworkAdapter.removeMcpServer && frameworkAdapter.getMcpPath) {
@@ -4801,7 +4821,8 @@ async function processAgent(agent, agentStates) {
4801
4821
  }
4802
4822
  }
4803
4823
  knownManagedMcpHashes.set(agent.agent_id, mcpHash);
4804
- if (prevMcpHash !== void 0 && fwForMcp === "claude-code" && isSessionHealthy(agent.code_name)) {
4824
+ knownManagedMcpStructure.set(agent.agent_id, structureHash);
4825
+ if (prevStructureHash !== void 0 && structureHash !== prevStructureHash && fwForMcp === "claude-code" && isSessionHealthy(agent.code_name)) {
4805
4826
  const mcpNames = agentToolkits.map((tk) => tk.toolkit_name).join(", ") || "none (all removed)";
4806
4827
  log(`[hot-reload] MCP servers changed for '${agent.code_name}': ${mcpNames} \u2014 restarting session`);
4807
4828
  const restartNotice = agentToolkits.length > 0 ? `New MCP tool servers have been configured: ${mcpNames}. Note: MCP servers require a session restart to connect. Your manager will restart your session shortly.` : "Managed MCP tool servers were removed. Your manager will restart your session shortly so the session drops those tools.";
@@ -4889,7 +4910,7 @@ async function processAgent(agent, agentStates) {
4889
4910
  if (frameworkAdapter.installSkillFiles) {
4890
4911
  const currentIntegrationSkillIds = /* @__PURE__ */ new Set();
4891
4912
  const installedIntegrationSkills = [];
4892
- const { createHash: createHash3 } = await import("crypto");
4913
+ const { createHash: createHash4 } = await import("crypto");
4893
4914
  const refreshAny = refreshData;
4894
4915
  const contexts = refreshAny.integration_contexts ?? refreshAny.plugin_contexts ?? [];
4895
4916
  const contextBySlug = /* @__PURE__ */ new Map();
@@ -4918,7 +4939,7 @@ async function processAgent(agent, agentStates) {
4918
4939
  )
4919
4940
  }));
4920
4941
  const bundle = buildIntegrationBundle(renderedScopes);
4921
- const contentHash = createHash3("sha256").update(bundleFingerprint(bundle.files)).digest("hex").slice(0, 12);
4942
+ const contentHash = createHash4("sha256").update(bundleFingerprint(bundle.files)).digest("hex").slice(0, 12);
4922
4943
  const hashKey = `plugin-skill:${agent.agent_id}:${integrationSkillId}`;
4923
4944
  if (knownSkillHashes.get(hashKey) === contentHash) continue;
4924
4945
  frameworkAdapter.installSkillFiles(agent.code_name, integrationSkillId, bundle.files);
@@ -4987,7 +5008,7 @@ async function processAgent(agent, agentStates) {
4987
5008
  const slug = hook.integration_slug ?? hook.plugin_slug;
4988
5009
  if (!slug) continue;
4989
5010
  try {
4990
- const scriptHash = createHash3("sha256").update(hook.script).digest("hex").slice(0, 12);
5011
+ const scriptHash = createHash4("sha256").update(hook.script).digest("hex").slice(0, 12);
4991
5012
  const hookKey = `${agent.agent_id}:${frameworkAdapter.id}:plugin-hook:${slug}:on_install`;
4992
5013
  if (knownSkillHashes.get(hookKey) === scriptHash) continue;
4993
5014
  const result = await frameworkAdapter.executePluginHook({
@@ -5002,9 +5023,9 @@ async function processAgent(agent, agentStates) {
5002
5023
  } else if (result.timedOut) {
5003
5024
  log(`Integration hook on_install '${slug}' TIMED OUT for '${agent.code_name}' after ${result.durationMs}ms`);
5004
5025
  } else {
5005
- const stderrHash = createHash3("sha256").update(result.stderr).digest("hex").slice(0, 12);
5026
+ const stderrHash = createHash4("sha256").update(result.stderr).digest("hex").slice(0, 12);
5006
5027
  const missingCmd = result.exitCode === 127 ? extractCommandNotFound(result.stderr) : null;
5007
- const missingCmdHash = missingCmd ? createHash3("sha256").update(missingCmd).digest("hex").slice(0, 8) : null;
5028
+ const missingCmdHash = missingCmd ? createHash4("sha256").update(missingCmd).digest("hex").slice(0, 8) : null;
5008
5029
  log(
5009
5030
  `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}]`
5010
5031
  );
@@ -5194,10 +5215,10 @@ async function processAgent(agent, agentStates) {
5194
5215
  } else if (agentFw === "claude-code" && tasks.length > 0) {
5195
5216
  await syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData);
5196
5217
  } else if (frameworkAdapter.syncScheduledTasks && gatewayRunning && gatewayPort) {
5197
- const stableTasksHash = createHash2("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
5198
- const boardHash = boardItems.length > 0 ? createHash2("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";
5218
+ const stableTasksHash = createHash3("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
5219
+ const boardHash = boardItems.length > 0 ? createHash3("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";
5199
5220
  const resolvedModels = resolveModelChain(refreshData);
5200
- const modelsHash = createHash2("sha256").update(JSON.stringify(resolvedModels)).digest("hex").slice(0, 16);
5221
+ const modelsHash = createHash3("sha256").update(JSON.stringify(resolvedModels)).digest("hex").slice(0, 16);
5201
5222
  const combinedHash = `${stableTasksHash}:${boardHash}:${modelsHash}`;
5202
5223
  const prevTasksHash = knownTasksHashes.get(agent.agent_id);
5203
5224
  if (combinedHash !== prevTasksHash) {
@@ -5577,10 +5598,10 @@ var MAX_CLAUDE_CONCURRENCY = 2;
5577
5598
  var claudeSchedulerStates = /* @__PURE__ */ new Map();
5578
5599
  async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData) {
5579
5600
  const codeName = agent.code_name;
5580
- const stableTasksHash = createHash2("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
5581
- const boardHash = boardItems.length > 0 ? createHash2("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";
5601
+ const stableTasksHash = createHash3("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
5602
+ const boardHash = boardItems.length > 0 ? createHash3("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";
5582
5603
  const resolvedModels = resolveModelChain(refreshData);
5583
- const modelsHash = createHash2("sha256").update(JSON.stringify(resolvedModels)).digest("hex").slice(0, 16);
5604
+ const modelsHash = createHash3("sha256").update(JSON.stringify(resolvedModels)).digest("hex").slice(0, 16);
5584
5605
  const combinedHash = `${stableTasksHash}:${boardHash}:${modelsHash}`;
5585
5606
  const prevHash = knownTasksHashes.get(agent.agent_id);
5586
5607
  if (combinedHash !== prevHash) {
@@ -5658,7 +5679,7 @@ async function startRun(opts) {
5658
5679
  return { run_id: res.run_id ?? null, kanban_item_id: res.kanban_item_id ?? null };
5659
5680
  } catch (err) {
5660
5681
  const errText = err instanceof Error ? err.message : String(err);
5661
- const errId = createHash2("sha256").update(errText).digest("hex").slice(0, 12);
5682
+ const errId = createHash3("sha256").update(errText).digest("hex").slice(0, 12);
5662
5683
  log(`[runs] start failed for agent_id=${opts.agent_id} source_type=${opts.source_type} error_id=${errId}`);
5663
5684
  return { run_id: null, kanban_item_id: null };
5664
5685
  }
@@ -5675,7 +5696,7 @@ async function finishRun(runId, outcome, options = {}) {
5675
5696
  });
5676
5697
  } catch (err) {
5677
5698
  const errText = err instanceof Error ? err.message : String(err);
5678
- const errId = createHash2("sha256").update(errText).digest("hex").slice(0, 12);
5699
+ const errId = createHash3("sha256").update(errText).digest("hex").slice(0, 12);
5679
5700
  log(`[runs] finish failed for run_id=${runId} outcome=${outcome} error_id=${errId}`);
5680
5701
  }
5681
5702
  }
@@ -5692,7 +5713,7 @@ async function fetchPriorScheduledRuns(agentId, taskId) {
5692
5713
  return rows.filter((r) => typeof r.output_text === "string" && r.output_text.length > 0).map((r) => ({ startedAt: r.started_at, output: r.output_text }));
5693
5714
  } catch (err) {
5694
5715
  const errText = err instanceof Error ? err.message : String(err);
5695
- const errId = createHash2("sha256").update(errText).digest("hex").slice(0, 12);
5716
+ const errId = createHash3("sha256").update(errText).digest("hex").slice(0, 12);
5696
5717
  log(`[runs] prior-runs lookup failed for task_id=${taskId} error_id=${errId}`);
5697
5718
  return [];
5698
5719
  }
@@ -5826,10 +5847,10 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
5826
5847
  const classification = classifyOutput(rawOutput);
5827
5848
  if (classification.action === "suppress") {
5828
5849
  const trimmed = (rawOutput ?? "").trim();
5829
- const outputHash = trimmed.length === 0 ? "empty" : createHash2("sha256").update(trimmed).digest("hex").slice(0, 12);
5850
+ const outputHash = trimmed.length === 0 ? "empty" : createHash3("sha256").update(trimmed).digest("hex").slice(0, 12);
5830
5851
  log(`[claude-scheduler] Suppressing delivery for '${codeName}' (template=${templateId}, task=${delivery?.taskId ?? "n/a"}) \u2014 output_len=${trimmed.length} output_hash=${outputHash}`);
5831
5852
  if (classification.suppressedNotes) {
5832
- const notesHash = createHash2("sha256").update(classification.suppressedNotes).digest("hex").slice(0, 12);
5853
+ const notesHash = createHash3("sha256").update(classification.suppressedNotes).digest("hex").slice(0, 12);
5833
5854
  log(`[claude-scheduler] Suppressed notes for '${codeName}' (task=${delivery?.taskId ?? "n/a"}) \u2014 notes_len=${classification.suppressedNotes.length} notes_hash=${notesHash}`);
5834
5855
  }
5835
5856
  if (delivery?.mode === "announce" && delivery.to) {
@@ -6051,7 +6072,7 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
6051
6072
  const ctx = getLastFailureContext(codeName);
6052
6073
  const recovery = prepareForRespawn(codeName);
6053
6074
  const tailSummary = !ctx.tail ? "" : KNOWN_SAFE_TAIL_SIGNATURES.has(ctx.signature) ? `; last pane output (${PANE_TAIL_PREVIEW_LINES} of ~20 lines):
6054
- ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash2("sha256").update(ctx.tail).digest("hex").slice(0, 12)} (raw at ~/.augmented/${codeName}/pane.log)`;
6075
+ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash3("sha256").update(ctx.tail).digest("hex").slice(0, 12)} (raw at ~/.augmented/${codeName}/pane.log)`;
6055
6076
  const sigSummary = ctx.signature !== "unknown" ? `; signature=${ctx.signature}` : "";
6056
6077
  const recoverySummary = recovery ? `; recovery=${recovery}` : "";
6057
6078
  log(
@@ -6065,7 +6086,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash2("sha256").
6065
6086
  );
6066
6087
  getHostId().then((hostId) => {
6067
6088
  if (!hostId) return;
6068
- const paneTailHash = zombie.paneTail ? `sha256:${createHash2("sha256").update(zombie.paneTail).digest("hex").slice(0, 12)}` : null;
6089
+ const paneTailHash = zombie.paneTail ? `sha256:${createHash3("sha256").update(zombie.paneTail).digest("hex").slice(0, 12)}` : null;
6069
6090
  return api.post("/host/events", {
6070
6091
  host_id: hostId,
6071
6092
  agent_code_name: codeName,
@@ -6132,7 +6153,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash2("sha256").
6132
6153
  if (!claudeAuthTupleBySession.has(codeName)) {
6133
6154
  claudeAuthTupleBySession.set(codeName, currentAuthTuple);
6134
6155
  }
6135
- const stableTasksHash = createHash2("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
6156
+ const stableTasksHash = createHash3("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
6136
6157
  const prevHash = knownTasksHashes.get(agent.agent_id);
6137
6158
  if (stableTasksHash !== prevHash) {
6138
6159
  const taskInputs = tasks.map((t) => ({
@@ -6616,7 +6637,7 @@ ${escapeXml(msg.content)}
6616
6637
  log(`[direct-chat] Reply sent for '${agent.codeName}'`);
6617
6638
  } catch (err) {
6618
6639
  const errMsg = err instanceof Error ? err.message : String(err);
6619
- const errorId = createHash2("sha256").update(errMsg).digest("hex").slice(0, 12);
6640
+ const errorId = createHash3("sha256").update(errMsg).digest("hex").slice(0, 12);
6620
6641
  log(`[direct-chat] Failed to process message for '${agent.codeName}': error_id=${errorId} error=${errMsg.slice(0, 500)}`);
6621
6642
  try {
6622
6643
  await api.post("/host/direct-chat/reply", {
@@ -7847,7 +7868,7 @@ async function syncMemories(agent, configDir, log2) {
7847
7868
  if (!file.endsWith(".md")) continue;
7848
7869
  try {
7849
7870
  const raw = readFileSync5(join6(memoryDir, file), "utf-8");
7850
- const fileHash = createHash2("sha256").update(raw).digest("hex").slice(0, 16);
7871
+ const fileHash = createHash3("sha256").update(raw).digest("hex").slice(0, 16);
7851
7872
  currentHashes.set(file, fileHash);
7852
7873
  if (prevHashes.get(file) === fileHash) continue;
7853
7874
  const parsed = parseMemoryFile(raw, file.replace(/\.md$/, ""));
@@ -7885,14 +7906,14 @@ async function syncMemories(agent, configDir, log2) {
7885
7906
  }
7886
7907
  async function downloadMemories(agent, memoryDir, log2, { force }) {
7887
7908
  const localFiles = existsSync4(memoryDir) ? readdirSync3(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
7888
- const localListHash = createHash2("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
7909
+ const localListHash = createHash3("sha256").update(localFiles.join(",")).digest("hex").slice(0, 16);
7889
7910
  const prevLocalHash = lastLocalFileHash.get(agent.agent_id);
7890
7911
  const prevDownload = lastDownloadHash.get(agent.agent_id);
7891
7912
  try {
7892
7913
  const dbMemories = await api.post("/host/memories", {
7893
7914
  agent_id: agent.agent_id
7894
7915
  });
7895
- const responseHash = createHash2("sha256").update(JSON.stringify(dbMemories.memories ?? [])).digest("hex").slice(0, 16);
7916
+ const responseHash = createHash3("sha256").update(JSON.stringify(dbMemories.memories ?? [])).digest("hex").slice(0, 16);
7896
7917
  if (!force && prevDownload && prevLocalHash === localListHash && lastDownloadHash.get(agent.agent_id) === responseHash) {
7897
7918
  return true;
7898
7919
  }
@@ -7931,7 +7952,7 @@ ${mem.content}
7931
7952
  }
7932
7953
  if (written > 0 || overwritten > 0) {
7933
7954
  const updatedFiles = readdirSync3(memoryDir).filter((f) => f.endsWith(".md")).sort();
7934
- lastLocalFileHash.set(agent.agent_id, createHash2("sha256").update(updatedFiles.join(",")).digest("hex").slice(0, 16));
7955
+ lastLocalFileHash.set(agent.agent_id, createHash3("sha256").update(updatedFiles.join(",")).digest("hex").slice(0, 16));
7935
7956
  log2(`Memory download for '${agent.code_name}': wrote ${written} new, overwrote ${overwritten} stale`);
7936
7957
  }
7937
7958
  }
@@ -8216,7 +8237,7 @@ function deployMcpAssets() {
8216
8237
  const fileHash = (p) => {
8217
8238
  try {
8218
8239
  if (!existsSync4(p)) return null;
8219
- return createHash2("sha256").update(readFileSync5(p)).digest("hex");
8240
+ return createHash3("sha256").update(readFileSync5(p)).digest("hex");
8220
8241
  } catch {
8221
8242
  return null;
8222
8243
  }