@integrity-labs/agt-cli 0.24.2 → 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-BXLWLI2U.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.2" : "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.2" : "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-BXLWLI2U.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-BXLWLI2U.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
@@ -790,6 +805,7 @@ async function maybeReportTokenUsage(args) {
790
805
  state2.set(codeName, next);
791
806
  return;
792
807
  }
808
+ let reported = 0;
793
809
  for (let i = 0; i < pending.length; i += MAX_ENTRIES_PER_POST) {
794
810
  const batch = pending.slice(i, i + MAX_ENTRIES_PER_POST);
795
811
  try {
@@ -802,10 +818,14 @@ async function maybeReportTokenUsage(args) {
802
818
  for (const b of batch) {
803
819
  files.set(b.sessionId, b.fp);
804
820
  }
821
+ reported += batch.length;
805
822
  } catch (err) {
806
823
  log2(`[token-usage] POST failed for '${codeName}': ${err.message}`);
807
824
  }
808
825
  }
826
+ if (reported > 0) {
827
+ log2(`[token-usage] reported ${reported} entr${reported === 1 ? "y" : "ies"} for '${codeName}'`);
828
+ }
809
829
  state2.set(codeName, next);
810
830
  }
811
831
 
@@ -2622,7 +2642,7 @@ var runningMcpServerKeys = /* @__PURE__ */ new Map();
2622
2642
  function projectMcpHash(_codeName, projectDir) {
2623
2643
  try {
2624
2644
  const raw = readFileSync5(join6(projectDir, ".mcp.json"), "utf-8");
2625
- return createHash2("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
2645
+ return createHash3("sha256").update(canonicalJson(JSON.parse(raw))).digest("hex");
2626
2646
  } catch {
2627
2647
  return null;
2628
2648
  }
@@ -2666,33 +2686,34 @@ function checkMcpConfigDriftAndScheduleRestart(codeName, projectDir) {
2666
2686
  }
2667
2687
  case "drift": {
2668
2688
  log(
2669
- `[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)`
2670
2690
  );
2671
2691
  const previousKeys = runningMcpServerKeys.get(codeName);
2672
2692
  const currentKeys = projectMcpKeys(codeName, projectDir);
2673
- if (!previousKeys || !currentKeys) {
2693
+ const decision = decideMcpRestartOnDrift(previousKeys, currentKeys);
2694
+ if (decision.membershipUnknown) {
2674
2695
  clearPresenceReaperState(codeName);
2675
2696
  log(
2676
- `[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)`
2677
2703
  );
2678
2704
  } else {
2679
- const addedOrRemoved = /* @__PURE__ */ new Set();
2680
- for (const k of currentKeys) if (!previousKeys.has(k)) addedOrRemoved.add(k);
2681
- for (const k of previousKeys) if (!currentKeys.has(k)) addedOrRemoved.add(k);
2682
- if (addedOrRemoved.size > 0) {
2683
- clearPresenceReaperStateForKeys(codeName, addedOrRemoved);
2684
- log(
2685
- `[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)`
2686
- );
2687
- } else {
2688
- log(
2689
- `[hot-reload] .mcp.json value-only drift for '${codeName}' \u2014 preserving presence-reaper state for the unchanged declared key set (ENG-5285)`
2690
- );
2691
- }
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);
2692
2716
  }
2693
- scheduleSessionRestart(codeName, 0, ".mcp.json content change (ENG-4897)");
2694
- runningMcpHashes.delete(codeName);
2695
- runningMcpServerKeys.delete(codeName);
2696
2717
  return;
2697
2718
  }
2698
2719
  }
@@ -2702,6 +2723,7 @@ var knownModels = /* @__PURE__ */ new Map();
2702
2723
  var knownTasksHashes = /* @__PURE__ */ new Map();
2703
2724
  var knownIntegrationHashes = /* @__PURE__ */ new Map();
2704
2725
  var knownManagedMcpHashes = /* @__PURE__ */ new Map();
2726
+ var knownManagedMcpStructure = /* @__PURE__ */ new Map();
2705
2727
  var knownSkillHashes = /* @__PURE__ */ new Map();
2706
2728
  var managedToolkitIdByAgentAndServerId = /* @__PURE__ */ new Map();
2707
2729
  function managedToolkitMapKey(agentId, serverId) {
@@ -2753,6 +2775,7 @@ function clearAgentCaches(agentId, codeName) {
2753
2775
  knownTasksHashes.delete(agentId);
2754
2776
  knownIntegrationHashes.delete(agentId);
2755
2777
  knownManagedMcpHashes.delete(agentId);
2778
+ knownManagedMcpStructure.delete(agentId);
2756
2779
  agentDisplayNames.delete(codeName);
2757
2780
  codeNameToAgentId.delete(codeName);
2758
2781
  agentFrameworkCache.delete(codeName);
@@ -2783,7 +2806,7 @@ var cachedFrameworkVersion = null;
2783
2806
  var lastVersionCheckAt = 0;
2784
2807
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
2785
2808
  var lastResponsivenessProbeAt = 0;
2786
- var agtCliVersion = true ? "0.24.2" : "dev";
2809
+ var agtCliVersion = true ? "0.24.4" : "dev";
2787
2810
  function resolveBrewPath(execFileSync4) {
2788
2811
  try {
2789
2812
  const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -3362,7 +3385,7 @@ function log(msg) {
3362
3385
  }
3363
3386
  }
3364
3387
  function sha256(content) {
3365
- return createHash2("sha256").update(content, "utf8").digest("hex");
3388
+ return createHash3("sha256").update(content, "utf8").digest("hex");
3366
3389
  }
3367
3390
  function hashFile(filePath) {
3368
3391
  try {
@@ -3772,7 +3795,7 @@ async function pollCycle() {
3772
3795
  claudeAuth = await detectClaudeAuth();
3773
3796
  } catch (err) {
3774
3797
  const errText = err instanceof Error ? err.message : String(err);
3775
- const errId = createHash2("sha256").update(errText).digest("hex").slice(0, 12);
3798
+ const errId = createHash3("sha256").update(errText).digest("hex").slice(0, 12);
3776
3799
  log(`Claude auth detection failed (error_id=${errId})`);
3777
3800
  }
3778
3801
  await api.post("/host/heartbeat", {
@@ -4492,7 +4515,7 @@ async function processAgent(agent, agentStates) {
4492
4515
  const peersForHash = channelId === "telegram" ? extractCharterTelegramPeers(refreshData.charter?.raw_content ?? "", gateContext) : channelId === "slack" ? extractCharterSlackPeers(refreshData.charter?.raw_content ?? "", gateContext) : null;
4493
4516
  const sessionModeForHash = refreshData.agent.session_mode;
4494
4517
  const CHANNEL_WRITE_VERSION = 5;
4495
- const configHash = createHash2("sha256").update(
4518
+ const configHash = createHash3("sha256").update(
4496
4519
  canonicalJson({
4497
4520
  writeVersion: CHANNEL_WRITE_VERSION,
4498
4521
  config: entry.config,
@@ -4754,15 +4777,17 @@ async function processAgent(agent, agentStates) {
4754
4777
  desiredEntries.push({ serverId, url, headers: mcpHeaders, name: tk.toolkit_name });
4755
4778
  }
4756
4779
  const hashBasis = desiredEntries.slice().sort((a, b) => a.serverId.localeCompare(b.serverId)).map((e) => {
4757
- 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);
4758
4781
  return `${e.serverId}|${e.url}|${headersHash}`;
4759
4782
  }).join("\n");
4760
- const mcpHash = createHash2("sha256").update(hashBasis).digest("hex").slice(0, 16);
4783
+ const mcpHash = createHash3("sha256").update(hashBasis).digest("hex").slice(0, 16);
4761
4784
  const prevMcpHash = knownManagedMcpHashes.get(agent.agent_id);
4785
+ const structureHash = managedMcpStructureHash(desiredEntries);
4786
+ const prevStructureHash = knownManagedMcpStructure.get(agent.agent_id);
4762
4787
  if (mcpHash !== prevMcpHash) {
4763
4788
  for (const e of desiredEntries) {
4764
4789
  frameworkAdapter.writeMcpServer(agent.code_name, e.serverId, { url: e.url, headers: e.headers });
4765
- 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);
4766
4791
  log(`[managed-toolkit] ${agent.code_name}: wrote '${e.name}' (serverId=${e.serverId}, url_hash=${urlHash})`);
4767
4792
  }
4768
4793
  if (frameworkAdapter.removeMcpServer && frameworkAdapter.getMcpPath) {
@@ -4796,7 +4821,8 @@ async function processAgent(agent, agentStates) {
4796
4821
  }
4797
4822
  }
4798
4823
  knownManagedMcpHashes.set(agent.agent_id, mcpHash);
4799
- 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)) {
4800
4826
  const mcpNames = agentToolkits.map((tk) => tk.toolkit_name).join(", ") || "none (all removed)";
4801
4827
  log(`[hot-reload] MCP servers changed for '${agent.code_name}': ${mcpNames} \u2014 restarting session`);
4802
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.";
@@ -4884,7 +4910,7 @@ async function processAgent(agent, agentStates) {
4884
4910
  if (frameworkAdapter.installSkillFiles) {
4885
4911
  const currentIntegrationSkillIds = /* @__PURE__ */ new Set();
4886
4912
  const installedIntegrationSkills = [];
4887
- const { createHash: createHash3 } = await import("crypto");
4913
+ const { createHash: createHash4 } = await import("crypto");
4888
4914
  const refreshAny = refreshData;
4889
4915
  const contexts = refreshAny.integration_contexts ?? refreshAny.plugin_contexts ?? [];
4890
4916
  const contextBySlug = /* @__PURE__ */ new Map();
@@ -4913,7 +4939,7 @@ async function processAgent(agent, agentStates) {
4913
4939
  )
4914
4940
  }));
4915
4941
  const bundle = buildIntegrationBundle(renderedScopes);
4916
- 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);
4917
4943
  const hashKey = `plugin-skill:${agent.agent_id}:${integrationSkillId}`;
4918
4944
  if (knownSkillHashes.get(hashKey) === contentHash) continue;
4919
4945
  frameworkAdapter.installSkillFiles(agent.code_name, integrationSkillId, bundle.files);
@@ -4982,7 +5008,7 @@ async function processAgent(agent, agentStates) {
4982
5008
  const slug = hook.integration_slug ?? hook.plugin_slug;
4983
5009
  if (!slug) continue;
4984
5010
  try {
4985
- 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);
4986
5012
  const hookKey = `${agent.agent_id}:${frameworkAdapter.id}:plugin-hook:${slug}:on_install`;
4987
5013
  if (knownSkillHashes.get(hookKey) === scriptHash) continue;
4988
5014
  const result = await frameworkAdapter.executePluginHook({
@@ -4997,9 +5023,9 @@ async function processAgent(agent, agentStates) {
4997
5023
  } else if (result.timedOut) {
4998
5024
  log(`Integration hook on_install '${slug}' TIMED OUT for '${agent.code_name}' after ${result.durationMs}ms`);
4999
5025
  } else {
5000
- 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);
5001
5027
  const missingCmd = result.exitCode === 127 ? extractCommandNotFound(result.stderr) : null;
5002
- 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;
5003
5029
  log(
5004
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}]`
5005
5031
  );
@@ -5189,10 +5215,10 @@ async function processAgent(agent, agentStates) {
5189
5215
  } else if (agentFw === "claude-code" && tasks.length > 0) {
5190
5216
  await syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData);
5191
5217
  } else if (frameworkAdapter.syncScheduledTasks && gatewayRunning && gatewayPort) {
5192
- const stableTasksHash = createHash2("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
5193
- 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";
5194
5220
  const resolvedModels = resolveModelChain(refreshData);
5195
- 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);
5196
5222
  const combinedHash = `${stableTasksHash}:${boardHash}:${modelsHash}`;
5197
5223
  const prevTasksHash = knownTasksHashes.get(agent.agent_id);
5198
5224
  if (combinedHash !== prevTasksHash) {
@@ -5572,10 +5598,10 @@ var MAX_CLAUDE_CONCURRENCY = 2;
5572
5598
  var claudeSchedulerStates = /* @__PURE__ */ new Map();
5573
5599
  async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData) {
5574
5600
  const codeName = agent.code_name;
5575
- const stableTasksHash = createHash2("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
5576
- 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";
5577
5603
  const resolvedModels = resolveModelChain(refreshData);
5578
- 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);
5579
5605
  const combinedHash = `${stableTasksHash}:${boardHash}:${modelsHash}`;
5580
5606
  const prevHash = knownTasksHashes.get(agent.agent_id);
5581
5607
  if (combinedHash !== prevHash) {
@@ -5653,7 +5679,7 @@ async function startRun(opts) {
5653
5679
  return { run_id: res.run_id ?? null, kanban_item_id: res.kanban_item_id ?? null };
5654
5680
  } catch (err) {
5655
5681
  const errText = err instanceof Error ? err.message : String(err);
5656
- const errId = createHash2("sha256").update(errText).digest("hex").slice(0, 12);
5682
+ const errId = createHash3("sha256").update(errText).digest("hex").slice(0, 12);
5657
5683
  log(`[runs] start failed for agent_id=${opts.agent_id} source_type=${opts.source_type} error_id=${errId}`);
5658
5684
  return { run_id: null, kanban_item_id: null };
5659
5685
  }
@@ -5670,7 +5696,7 @@ async function finishRun(runId, outcome, options = {}) {
5670
5696
  });
5671
5697
  } catch (err) {
5672
5698
  const errText = err instanceof Error ? err.message : String(err);
5673
- const errId = createHash2("sha256").update(errText).digest("hex").slice(0, 12);
5699
+ const errId = createHash3("sha256").update(errText).digest("hex").slice(0, 12);
5674
5700
  log(`[runs] finish failed for run_id=${runId} outcome=${outcome} error_id=${errId}`);
5675
5701
  }
5676
5702
  }
@@ -5687,7 +5713,7 @@ async function fetchPriorScheduledRuns(agentId, taskId) {
5687
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 }));
5688
5714
  } catch (err) {
5689
5715
  const errText = err instanceof Error ? err.message : String(err);
5690
- const errId = createHash2("sha256").update(errText).digest("hex").slice(0, 12);
5716
+ const errId = createHash3("sha256").update(errText).digest("hex").slice(0, 12);
5691
5717
  log(`[runs] prior-runs lookup failed for task_id=${taskId} error_id=${errId}`);
5692
5718
  return [];
5693
5719
  }
@@ -5821,10 +5847,10 @@ async function processClaudeTaskResult(codeName, agentId, templateId, rawOutput,
5821
5847
  const classification = classifyOutput(rawOutput);
5822
5848
  if (classification.action === "suppress") {
5823
5849
  const trimmed = (rawOutput ?? "").trim();
5824
- 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);
5825
5851
  log(`[claude-scheduler] Suppressing delivery for '${codeName}' (template=${templateId}, task=${delivery?.taskId ?? "n/a"}) \u2014 output_len=${trimmed.length} output_hash=${outputHash}`);
5826
5852
  if (classification.suppressedNotes) {
5827
- 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);
5828
5854
  log(`[claude-scheduler] Suppressed notes for '${codeName}' (task=${delivery?.taskId ?? "n/a"}) \u2014 notes_len=${classification.suppressedNotes.length} notes_hash=${notesHash}`);
5829
5855
  }
5830
5856
  if (delivery?.mode === "announce" && delivery.to) {
@@ -6046,7 +6072,7 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
6046
6072
  const ctx = getLastFailureContext(codeName);
6047
6073
  const recovery = prepareForRespawn(codeName);
6048
6074
  const tailSummary = !ctx.tail ? "" : KNOWN_SAFE_TAIL_SIGNATURES.has(ctx.signature) ? `; last pane output (${PANE_TAIL_PREVIEW_LINES} of ~20 lines):
6049
- ${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)`;
6050
6076
  const sigSummary = ctx.signature !== "unknown" ? `; signature=${ctx.signature}` : "";
6051
6077
  const recoverySummary = recovery ? `; recovery=${recovery}` : "";
6052
6078
  log(
@@ -6060,7 +6086,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash2("sha256").
6060
6086
  );
6061
6087
  getHostId().then((hostId) => {
6062
6088
  if (!hostId) return;
6063
- 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;
6064
6090
  return api.post("/host/events", {
6065
6091
  host_id: hostId,
6066
6092
  agent_code_name: codeName,
@@ -6127,7 +6153,7 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash2("sha256").
6127
6153
  if (!claudeAuthTupleBySession.has(codeName)) {
6128
6154
  claudeAuthTupleBySession.set(codeName, currentAuthTuple);
6129
6155
  }
6130
- 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);
6131
6157
  const prevHash = knownTasksHashes.get(agent.agent_id);
6132
6158
  if (stableTasksHash !== prevHash) {
6133
6159
  const taskInputs = tasks.map((t) => ({
@@ -6611,7 +6637,7 @@ ${escapeXml(msg.content)}
6611
6637
  log(`[direct-chat] Reply sent for '${agent.codeName}'`);
6612
6638
  } catch (err) {
6613
6639
  const errMsg = err instanceof Error ? err.message : String(err);
6614
- const errorId = createHash2("sha256").update(errMsg).digest("hex").slice(0, 12);
6640
+ const errorId = createHash3("sha256").update(errMsg).digest("hex").slice(0, 12);
6615
6641
  log(`[direct-chat] Failed to process message for '${agent.codeName}': error_id=${errorId} error=${errMsg.slice(0, 500)}`);
6616
6642
  try {
6617
6643
  await api.post("/host/direct-chat/reply", {
@@ -7842,7 +7868,7 @@ async function syncMemories(agent, configDir, log2) {
7842
7868
  if (!file.endsWith(".md")) continue;
7843
7869
  try {
7844
7870
  const raw = readFileSync5(join6(memoryDir, file), "utf-8");
7845
- const fileHash = createHash2("sha256").update(raw).digest("hex").slice(0, 16);
7871
+ const fileHash = createHash3("sha256").update(raw).digest("hex").slice(0, 16);
7846
7872
  currentHashes.set(file, fileHash);
7847
7873
  if (prevHashes.get(file) === fileHash) continue;
7848
7874
  const parsed = parseMemoryFile(raw, file.replace(/\.md$/, ""));
@@ -7880,14 +7906,14 @@ async function syncMemories(agent, configDir, log2) {
7880
7906
  }
7881
7907
  async function downloadMemories(agent, memoryDir, log2, { force }) {
7882
7908
  const localFiles = existsSync4(memoryDir) ? readdirSync3(memoryDir).filter((f) => f.endsWith(".md")).sort() : [];
7883
- 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);
7884
7910
  const prevLocalHash = lastLocalFileHash.get(agent.agent_id);
7885
7911
  const prevDownload = lastDownloadHash.get(agent.agent_id);
7886
7912
  try {
7887
7913
  const dbMemories = await api.post("/host/memories", {
7888
7914
  agent_id: agent.agent_id
7889
7915
  });
7890
- 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);
7891
7917
  if (!force && prevDownload && prevLocalHash === localListHash && lastDownloadHash.get(agent.agent_id) === responseHash) {
7892
7918
  return true;
7893
7919
  }
@@ -7926,7 +7952,7 @@ ${mem.content}
7926
7952
  }
7927
7953
  if (written > 0 || overwritten > 0) {
7928
7954
  const updatedFiles = readdirSync3(memoryDir).filter((f) => f.endsWith(".md")).sort();
7929
- 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));
7930
7956
  log2(`Memory download for '${agent.code_name}': wrote ${written} new, overwrote ${overwritten} stale`);
7931
7957
  }
7932
7958
  }
@@ -8211,7 +8237,7 @@ function deployMcpAssets() {
8211
8237
  const fileHash = (p) => {
8212
8238
  try {
8213
8239
  if (!existsSync4(p)) return null;
8214
- return createHash2("sha256").update(readFileSync5(p)).digest("hex");
8240
+ return createHash3("sha256").update(readFileSync5(p)).digest("hex");
8215
8241
  } catch {
8216
8242
  return null;
8217
8243
  }