opencode-swarm 6.55.0 → 6.56.0

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/index.js CHANGED
@@ -67,9 +67,9 @@ var init_tool_names = __esm(() => {
67
67
  "doc_scan",
68
68
  "doc_extract",
69
69
  "curator_analyze",
70
- "knowledgeAdd",
71
- "knowledgeRecall",
72
- "knowledgeRemove",
70
+ "knowledge_add",
71
+ "knowledge_recall",
72
+ "knowledge_remove",
73
73
  "co_change_analyzer",
74
74
  "search",
75
75
  "batch_symbols",
@@ -203,9 +203,9 @@ var init_constants = __esm(() => {
203
203
  "doc_scan",
204
204
  "doc_extract",
205
205
  "curator_analyze",
206
- "knowledgeAdd",
207
- "knowledgeRecall",
208
- "knowledgeRemove",
206
+ "knowledge_add",
207
+ "knowledge_recall",
208
+ "knowledge_remove",
209
209
  "co_change_analyzer",
210
210
  "suggest_patch"
211
211
  ],
@@ -222,7 +222,7 @@ var init_constants = __esm(() => {
222
222
  "symbols",
223
223
  "todo_extract",
224
224
  "doc_scan",
225
- "knowledgeRecall"
225
+ "knowledge_recall"
226
226
  ],
227
227
  coder: [
228
228
  "diff",
@@ -234,8 +234,8 @@ var init_constants = __esm(() => {
234
234
  "search",
235
235
  "build_check",
236
236
  "syntax_check",
237
- "knowledgeAdd",
238
- "knowledgeRecall"
237
+ "knowledge_add",
238
+ "knowledge_recall"
239
239
  ],
240
240
  test_engineer: [
241
241
  "test_runner",
@@ -258,7 +258,7 @@ var init_constants = __esm(() => {
258
258
  "retrieve_summary",
259
259
  "schema_drift",
260
260
  "symbols",
261
- "knowledgeRecall"
261
+ "knowledge_recall"
262
262
  ],
263
263
  reviewer: [
264
264
  "diff",
@@ -274,7 +274,7 @@ var init_constants = __esm(() => {
274
274
  "test_runner",
275
275
  "sast_scan",
276
276
  "placeholder_scan",
277
- "knowledgeRecall",
277
+ "knowledge_recall",
278
278
  "search",
279
279
  "batch_symbols",
280
280
  "suggest_patch"
@@ -285,7 +285,7 @@ var init_constants = __esm(() => {
285
285
  "imports",
286
286
  "retrieve_summary",
287
287
  "symbols",
288
- "knowledgeRecall"
288
+ "knowledge_recall"
289
289
  ],
290
290
  critic_sounding_board: [
291
291
  "complexity_hotspots",
@@ -293,7 +293,7 @@ var init_constants = __esm(() => {
293
293
  "imports",
294
294
  "retrieve_summary",
295
295
  "symbols",
296
- "knowledgeRecall"
296
+ "knowledge_recall"
297
297
  ],
298
298
  critic_drift_verifier: [
299
299
  "complexity_hotspots",
@@ -301,7 +301,7 @@ var init_constants = __esm(() => {
301
301
  "imports",
302
302
  "retrieve_summary",
303
303
  "symbols",
304
- "knowledgeRecall"
304
+ "knowledge_recall"
305
305
  ],
306
306
  critic_oversight: [
307
307
  "complexity_hotspots",
@@ -309,7 +309,7 @@ var init_constants = __esm(() => {
309
309
  "imports",
310
310
  "retrieve_summary",
311
311
  "symbols",
312
- "knowledgeRecall"
312
+ "knowledge_recall"
313
313
  ],
314
314
  docs: [
315
315
  "detect_domains",
@@ -320,16 +320,16 @@ var init_constants = __esm(() => {
320
320
  "schema_drift",
321
321
  "symbols",
322
322
  "todo_extract",
323
- "knowledgeRecall"
323
+ "knowledge_recall"
324
324
  ],
325
325
  designer: [
326
326
  "extract_code_blocks",
327
327
  "retrieve_summary",
328
328
  "symbols",
329
- "knowledgeRecall"
329
+ "knowledge_recall"
330
330
  ],
331
- curator_init: ["knowledgeRecall"],
332
- curator_phase: ["knowledgeRecall"]
331
+ curator_init: ["knowledge_recall"],
332
+ curator_phase: ["knowledge_recall"]
333
333
  };
334
334
  WRITE_TOOL_NAMES = [
335
335
  "write",
@@ -371,9 +371,9 @@ var init_constants = __esm(() => {
371
371
  doc_scan: "scan project documentation files and build an index manifest",
372
372
  doc_extract: "extract actionable constraints from project documentation",
373
373
  curator_analyze: "run curator phase analysis and optionally apply knowledge recommendations",
374
- knowledgeAdd: "store a new lesson in the knowledge base",
375
- knowledgeRecall: "search the knowledge base for relevant past decisions",
376
- knowledgeRemove: "delete an outdated knowledge entry by ID",
374
+ knowledge_add: "store a new lesson in the knowledge base",
375
+ knowledge_recall: "search the knowledge base for relevant past decisions",
376
+ knowledge_remove: "delete an outdated knowledge entry by ID",
377
377
  knowledge_query: "query swarm or hive knowledge with optional filters",
378
378
  co_change_analyzer: "detect hidden couplings by analyzing git history",
379
379
  check_gate_status: "check the gate status of a specific task",
@@ -15036,6 +15036,7 @@ var init_schema = __esm(() => {
15036
15036
  auto_promote_days: exports_external.number().min(1).max(3650).default(90),
15037
15037
  max_inject_count: exports_external.number().min(0).max(50).default(5),
15038
15038
  inject_char_budget: exports_external.number().min(200).max(1e4).default(2000),
15039
+ context_budget_threshold: exports_external.number().int().positive().optional(),
15039
15040
  max_lesson_display_chars: exports_external.number().min(40).max(280).default(120),
15040
15041
  dedup_threshold: exports_external.number().min(0).max(1).default(0.6),
15041
15042
  scope_filter: exports_external.array(exports_external.string()).default(["global"]),
@@ -15809,11 +15810,153 @@ var init_manager = __esm(() => {
15809
15810
  };
15810
15811
  });
15811
15812
 
15813
+ // src/environment/profile.ts
15814
+ function detectHostOS() {
15815
+ switch (process.platform) {
15816
+ case "win32":
15817
+ return "windows";
15818
+ case "darwin":
15819
+ return "macos";
15820
+ case "linux":
15821
+ return "linux";
15822
+ default:
15823
+ return "unknown";
15824
+ }
15825
+ }
15826
+ function detectShellFamily() {
15827
+ const psModulePath = process.env["PSModulePath"];
15828
+ if (psModulePath)
15829
+ return "powershell";
15830
+ const comspec = process.env["ComSpec"] ?? "";
15831
+ if (comspec.toLowerCase().includes("cmd.exe"))
15832
+ return "cmd";
15833
+ const shell = process.env["SHELL"] ?? "";
15834
+ if (shell.includes("bash"))
15835
+ return "bash";
15836
+ if (shell.includes("zsh"))
15837
+ return "zsh";
15838
+ if (shell.includes("/sh"))
15839
+ return "sh";
15840
+ return "unknown";
15841
+ }
15842
+ function detectExecutionMode(hostOS) {
15843
+ const wslDistro = process.env["WSL_DISTRO_NAME"];
15844
+ if (wslDistro)
15845
+ return "wsl";
15846
+ if (hostOS === "linux") {
15847
+ const containerEnvs = [
15848
+ "DOCKER_CONTAINER",
15849
+ "KUBERNETES_SERVICE_HOST",
15850
+ "CONTAINER"
15851
+ ];
15852
+ if (containerEnvs.some((k) => process.env[k]))
15853
+ return "docker";
15854
+ }
15855
+ return "native";
15856
+ }
15857
+ function deriveOperatingMode(hostOS, executionMode) {
15858
+ if (hostOS === "linux")
15859
+ return "linux";
15860
+ if (hostOS === "macos")
15861
+ return "macos-native";
15862
+ if (hostOS === "windows")
15863
+ return "windows-native";
15864
+ return "unknown";
15865
+ }
15866
+ function buildCommandPolicy(profile) {
15867
+ if (profile.isWindowsNative) {
15868
+ return {
15869
+ preferredShell: "powershell",
15870
+ avoidPosixExamples: true,
15871
+ preferNodeApis: true,
15872
+ preferToolingOverShell: true,
15873
+ pathExampleStyle: "windows",
15874
+ examples: {
15875
+ listDir: "Get-ChildItem -Force",
15876
+ removeFile: "Remove-Item file.tmp",
15877
+ setEnv: '$env:DEBUG = "1"',
15878
+ printEnv: "$env:PATH",
15879
+ searchText: 'Get-ChildItem -Recurse src | Select-String "foo"'
15880
+ }
15881
+ };
15882
+ }
15883
+ return {
15884
+ preferredShell: profile.shellFamily === "unknown" ? "bash" : profile.shellFamily,
15885
+ avoidPosixExamples: false,
15886
+ preferNodeApis: true,
15887
+ preferToolingOverShell: true,
15888
+ pathExampleStyle: "posix",
15889
+ examples: {
15890
+ listDir: "ls -la",
15891
+ removeFile: "rm file.tmp",
15892
+ setEnv: "export DEBUG=1",
15893
+ printEnv: "echo $PATH",
15894
+ searchText: 'grep -R "foo" src/'
15895
+ }
15896
+ };
15897
+ }
15898
+ function detectEnvironmentProfile() {
15899
+ const hostOS = detectHostOS();
15900
+ const shellFamily = detectShellFamily();
15901
+ const executionMode = detectExecutionMode(hostOS);
15902
+ const operatingMode = deriveOperatingMode(hostOS, executionMode);
15903
+ const isWindowsNative = hostOS === "windows" && executionMode === "native";
15904
+ const isWindowsDocker = false;
15905
+ const isWSL = executionMode === "wsl";
15906
+ const pathStyle = hostOS === "windows" && !isWindowsDocker ? "windows" : "posix";
15907
+ const shellCommandPreference = isWindowsNative ? "powershell-native" : "posix-native";
15908
+ return {
15909
+ hostOS,
15910
+ shellFamily,
15911
+ executionMode,
15912
+ operatingMode,
15913
+ isWindowsNative,
15914
+ isWindowsDocker,
15915
+ isWSL,
15916
+ pathStyle,
15917
+ shellCommandPreference,
15918
+ evidence: {
15919
+ processPlatform: process.platform,
15920
+ comspec: process.env["ComSpec"],
15921
+ psModulePath: process.env["PSModulePath"],
15922
+ termProgram: process.env["TERM_PROGRAM"],
15923
+ shell: process.env["SHELL"],
15924
+ wslDistroName: process.env["WSL_DISTRO_NAME"],
15925
+ containerMarkers: [
15926
+ "DOCKER_CONTAINER",
15927
+ "KUBERNETES_SERVICE_HOST",
15928
+ "CONTAINER"
15929
+ ].filter((k) => !!process.env[k])
15930
+ }
15931
+ };
15932
+ }
15933
+ function deriveCommandPolicy(profile) {
15934
+ return buildCommandPolicy(profile);
15935
+ }
15936
+
15812
15937
  // src/telemetry.ts
15938
+ var exports_telemetry = {};
15939
+ __export(exports_telemetry, {
15940
+ telemetry: () => telemetry,
15941
+ rotateTelemetryIfNeeded: () => rotateTelemetryIfNeeded,
15942
+ resetTelemetryForTesting: () => resetTelemetryForTesting,
15943
+ initTelemetry: () => initTelemetry,
15944
+ emit: () => emit,
15945
+ addTelemetryListener: () => addTelemetryListener
15946
+ });
15813
15947
  import * as fs4 from "fs";
15814
15948
  import { createWriteStream } from "fs";
15815
15949
  import * as os2 from "os";
15816
15950
  import * as path4 from "path";
15951
+ function resetTelemetryForTesting() {
15952
+ _disabled = false;
15953
+ _projectDirectory = null;
15954
+ _listeners.length = 0;
15955
+ if (_writeStream !== null) {
15956
+ _writeStream.end();
15957
+ _writeStream = null;
15958
+ }
15959
+ }
15817
15960
  function initTelemetry(projectDirectory) {
15818
15961
  if (_writeStream !== null || _disabled) {
15819
15962
  return;
@@ -15858,6 +16001,34 @@ function emit(event, data) {
15858
16001
  }
15859
16002
  } catch {}
15860
16003
  }
16004
+ function addTelemetryListener(callback) {
16005
+ _listeners.push(callback);
16006
+ }
16007
+ function rotateTelemetryIfNeeded(maxBytes = 10 * 1024 * 1024) {
16008
+ try {
16009
+ if (_projectDirectory === null) {
16010
+ return;
16011
+ }
16012
+ const telemetryPath = path4.join(_projectDirectory, ".swarm", "telemetry.jsonl");
16013
+ if (!fs4.existsSync(telemetryPath)) {
16014
+ return;
16015
+ }
16016
+ const stats = fs4.statSync(telemetryPath);
16017
+ if (stats.size < maxBytes) {
16018
+ return;
16019
+ }
16020
+ const rotatedPath = path4.join(_projectDirectory, ".swarm", "telemetry.jsonl.1");
16021
+ fs4.renameSync(telemetryPath, rotatedPath);
16022
+ if (_writeStream !== null) {
16023
+ _writeStream.end();
16024
+ _writeStream = createWriteStream(telemetryPath, { flags: "a" });
16025
+ _writeStream.on("error", () => {
16026
+ _disabled = true;
16027
+ _writeStream = null;
16028
+ });
16029
+ }
16030
+ } catch {}
16031
+ }
15861
16032
  var _writeStream = null, _projectDirectory = null, _listeners, _disabled = false, telemetry;
15862
16033
  var init_telemetry = __esm(() => {
15863
16034
  _listeners = [];
@@ -15930,6 +16101,14 @@ var init_telemetry = __esm(() => {
15930
16101
  deadlockCount,
15931
16102
  phase
15932
16103
  });
16104
+ },
16105
+ environmentDetected(sessionId, hostOS, shellFamily, executionMode) {
16106
+ emit("environment_detected", {
16107
+ sessionId,
16108
+ hostOS,
16109
+ shellFamily,
16110
+ executionMode
16111
+ });
15933
16112
  }
15934
16113
  };
15935
16114
  });
@@ -15940,6 +16119,7 @@ __export(exports_state, {
15940
16119
  updateAgentEventTime: () => updateAgentEventTime,
15941
16120
  swarmState: () => swarmState,
15942
16121
  startAgentSession: () => startAgentSession,
16122
+ setSessionEnvironment: () => setSessionEnvironment,
15943
16123
  resetSwarmState: () => resetSwarmState,
15944
16124
  rehydrateSessionFromDisk: () => rehydrateSessionFromDisk,
15945
16125
  recordPhaseAgentDispatch: () => recordPhaseAgentDispatch,
@@ -15947,8 +16127,10 @@ __export(exports_state, {
15947
16127
  hasActiveTurboMode: () => hasActiveTurboMode,
15948
16128
  hasActiveFullAuto: () => hasActiveFullAuto,
15949
16129
  getTaskState: () => getTaskState,
16130
+ getSessionEnvironment: () => getSessionEnvironment,
15950
16131
  getAgentSession: () => getAgentSession,
15951
16132
  getActiveWindow: () => getActiveWindow,
16133
+ ensureSessionEnvironment: () => ensureSessionEnvironment,
15952
16134
  ensureAgentSession: () => ensureAgentSession,
15953
16135
  endAgentSession: () => endAgentSession,
15954
16136
  buildRehydrationCache: () => buildRehydrationCache,
@@ -15972,6 +16154,7 @@ function resetSwarmState() {
15972
16154
  swarmState.curatorPhaseAgentNames = [];
15973
16155
  _rehydrationCache = null;
15974
16156
  swarmState.fullAutoEnabledInConfig = false;
16157
+ swarmState.environmentProfiles.clear();
15975
16158
  }
15976
16159
  function startAgentSession(sessionId, agentName, staleDurationMs = 7200000, directory) {
15977
16160
  const now = Date.now();
@@ -16429,6 +16612,23 @@ function hasActiveFullAuto(sessionID) {
16429
16612
  }
16430
16613
  return false;
16431
16614
  }
16615
+ function setSessionEnvironment(sessionId, profile) {
16616
+ swarmState.environmentProfiles.set(sessionId, profile);
16617
+ }
16618
+ function getSessionEnvironment(sessionId) {
16619
+ return swarmState.environmentProfiles.get(sessionId);
16620
+ }
16621
+ function ensureSessionEnvironment(sessionId) {
16622
+ const existing = swarmState.environmentProfiles.get(sessionId);
16623
+ if (existing)
16624
+ return existing;
16625
+ const profile = detectEnvironmentProfile();
16626
+ swarmState.environmentProfiles.set(sessionId, profile);
16627
+ Promise.resolve().then(() => (init_telemetry(), exports_telemetry)).then(({ telemetry: telemetry2 }) => {
16628
+ telemetry2.environmentDetected(sessionId, profile.hostOS, profile.shellFamily, profile.executionMode);
16629
+ }).catch(() => {});
16630
+ return profile;
16631
+ }
16432
16632
  var _rehydrationCache = null, swarmState;
16433
16633
  var init_state = __esm(() => {
16434
16634
  init_constants();
@@ -16447,7 +16647,8 @@ var init_state = __esm(() => {
16447
16647
  lastBudgetPct: 0,
16448
16648
  agentSessions: new Map,
16449
16649
  pendingRehydrations: new Set,
16450
- fullAutoEnabledInConfig: false
16650
+ fullAutoEnabledInConfig: false,
16651
+ environmentProfiles: new Map
16451
16652
  };
16452
16653
  });
16453
16654
 
@@ -29113,6 +29314,16 @@ var init_dist = __esm(() => {
29113
29314
  });
29114
29315
 
29115
29316
  // src/tools/create-tool.ts
29317
+ function classifyToolError(error93) {
29318
+ const msg = (error93 instanceof Error ? error93.message : String(error93)).toLowerCase();
29319
+ if (msg.includes("not registered") || msg.includes("unknown tool"))
29320
+ return "not_registered";
29321
+ if (msg.includes("not whitelisted") || msg.includes("not allowed"))
29322
+ return "not_whitelisted";
29323
+ if (msg.includes("enoent") || msg.includes("command not found") || msg.includes("binary not found") || msg.includes("no such file or directory"))
29324
+ return "binary_missing";
29325
+ return "execution_error";
29326
+ }
29116
29327
  function createSwarmTool(opts) {
29117
29328
  return tool({
29118
29329
  description: opts.description,
@@ -29125,6 +29336,7 @@ function createSwarmTool(opts) {
29125
29336
  const message = error93 instanceof Error ? error93.message : String(error93);
29126
29337
  return JSON.stringify({
29127
29338
  success: false,
29339
+ failure_class: classifyToolError(error93),
29128
29340
  message: "Tool execution failed",
29129
29341
  errors: [message]
29130
29342
  }, null, 2);
@@ -34562,6 +34774,152 @@ var init_discovery = __esm(() => {
34562
34774
  });
34563
34775
  });
34564
34776
 
34777
+ // src/services/tool-doctor.ts
34778
+ var exports_tool_doctor = {};
34779
+ __export(exports_tool_doctor, {
34780
+ runToolDoctor: () => runToolDoctor,
34781
+ getBinaryReadinessAdvisory: () => getBinaryReadinessAdvisory
34782
+ });
34783
+ import * as fs13 from "fs";
34784
+ import * as path22 from "path";
34785
+ function extractRegisteredToolKeys(indexPath) {
34786
+ const registeredKeys = new Set;
34787
+ try {
34788
+ const content = fs13.readFileSync(indexPath, "utf-8");
34789
+ const toolBlockMatch = content.match(/tool:\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}/s);
34790
+ if (!toolBlockMatch) {
34791
+ return registeredKeys;
34792
+ }
34793
+ const toolBlock = toolBlockMatch[1];
34794
+ const keyPattern = /^\s*(\w+)(?:\s*:|,)/gm;
34795
+ for (const match of toolBlock.matchAll(keyPattern)) {
34796
+ registeredKeys.add(match[1]);
34797
+ }
34798
+ } catch (_error) {}
34799
+ return registeredKeys;
34800
+ }
34801
+ function checkAgentToolMapAlignment(registeredKeys) {
34802
+ const findings = [];
34803
+ for (const [agentName, tools] of Object.entries(AGENT_TOOL_MAP)) {
34804
+ for (const toolName of tools) {
34805
+ if (!registeredKeys.has(toolName)) {
34806
+ findings.push({
34807
+ id: `agent-tool-map-mismatch-${agentName}-${toolName}`,
34808
+ title: "AGENT_TOOL_MAP alignment gap",
34809
+ description: `Tool "${toolName}" is assigned to agent "${agentName}" in AGENT_TOOL_MAP but is not registered in the plugin's tool: {} block. The agent will not be able to use this tool.`,
34810
+ severity: "warn",
34811
+ path: `AGENT_TOOL_MAP.${agentName}`,
34812
+ currentValue: toolName,
34813
+ autoFixable: false
34814
+ });
34815
+ }
34816
+ }
34817
+ }
34818
+ return findings;
34819
+ }
34820
+ function checkBinaryReadiness() {
34821
+ const findings = [];
34822
+ for (const { binary: binary2, language } of BINARY_CHECKLIST) {
34823
+ if (!isCommandAvailable(binary2)) {
34824
+ findings.push({
34825
+ id: `missing-binary-${binary2}`,
34826
+ title: "Class 3 tool binary not found",
34827
+ description: `Binary "${binary2}" is not available on PATH. ${language} linting will not be available. Install ${binary2} to enable ${language} language support.`,
34828
+ severity: "warn",
34829
+ path: `toolchain.${binary2}`,
34830
+ currentValue: undefined,
34831
+ autoFixable: false
34832
+ });
34833
+ }
34834
+ }
34835
+ return findings;
34836
+ }
34837
+ function getBinaryReadinessAdvisory() {
34838
+ const findings = checkBinaryReadiness();
34839
+ if (findings.length === 0)
34840
+ return null;
34841
+ const lines = findings.map((f) => `- MISSING BINARY: ${f.currentValue ?? f.path?.split(".")[1] ?? "unknown"} \u2014 ${f.description}`);
34842
+ return [
34843
+ "[PRE-FLIGHT ADVISORY] The following Class 3 tool binaries were not found on PATH at session start.",
34844
+ "These tools will soft-skip at invocation. Plan tasks accordingly.",
34845
+ ...lines
34846
+ ].join(`
34847
+ `);
34848
+ }
34849
+ function runToolDoctor(_directory, pluginRoot) {
34850
+ const findings = [];
34851
+ const resolvedPluginRoot = pluginRoot ?? path22.resolve(import.meta.dir, "..", "..");
34852
+ const indexPath = path22.join(resolvedPluginRoot, "src", "index.ts");
34853
+ if (!fs13.existsSync(indexPath)) {
34854
+ return {
34855
+ findings: [
34856
+ {
34857
+ id: "plugin-src-unavailable",
34858
+ title: "Plugin source not available",
34859
+ description: `Tool registration check requires plugin source files. Expected: ${indexPath}. This check is available in development environments; in production npm installs, only compiled dist/ is present.`,
34860
+ severity: "warn",
34861
+ path: indexPath,
34862
+ currentValue: undefined,
34863
+ autoFixable: false
34864
+ }
34865
+ ],
34866
+ summary: { info: 0, warn: 1, error: 0 },
34867
+ hasAutoFixableIssues: false,
34868
+ timestamp: Date.now(),
34869
+ configSource: indexPath
34870
+ };
34871
+ }
34872
+ const registeredKeys = extractRegisteredToolKeys(indexPath);
34873
+ for (const toolName of TOOL_NAMES) {
34874
+ if (!registeredKeys.has(toolName)) {
34875
+ findings.push({
34876
+ id: `missing-tool-registration-${toolName}`,
34877
+ title: "Missing tool registration",
34878
+ description: `Tool "${toolName}" is defined in TOOL_NAMES but is not registered in the plugin's tool: {} block. This means the tool will not be available at runtime.`,
34879
+ severity: "error",
34880
+ path: `tool.${toolName}`,
34881
+ currentValue: undefined,
34882
+ autoFixable: false
34883
+ });
34884
+ }
34885
+ }
34886
+ findings.push(...checkAgentToolMapAlignment(registeredKeys));
34887
+ findings.push(...checkBinaryReadiness());
34888
+ const summary = {
34889
+ info: findings.filter((f) => f.severity === "info").length,
34890
+ warn: findings.filter((f) => f.severity === "warn").length,
34891
+ error: findings.filter((f) => f.severity === "error").length
34892
+ };
34893
+ const hasAutoFixableIssues = false;
34894
+ return {
34895
+ findings,
34896
+ summary,
34897
+ hasAutoFixableIssues,
34898
+ timestamp: Date.now(),
34899
+ configSource: indexPath
34900
+ };
34901
+ }
34902
+ var BINARY_CHECKLIST;
34903
+ var init_tool_doctor = __esm(() => {
34904
+ init_discovery();
34905
+ init_constants();
34906
+ init_tool_names();
34907
+ BINARY_CHECKLIST = [
34908
+ { binary: "ruff", language: "Python" },
34909
+ { binary: "cargo", language: "Rust (via clippy)" },
34910
+ { binary: "golangci-lint", language: "Go" },
34911
+ { binary: "mvn", language: "Java (Maven)" },
34912
+ { binary: "gradle", language: "Java (Gradle)" },
34913
+ { binary: "dotnet", language: ".NET" },
34914
+ { binary: "swift", language: "Swift" },
34915
+ { binary: "swiftlint", language: "Swift (linting)" },
34916
+ { binary: "dart", language: "Dart" },
34917
+ { binary: "flutter", language: "Flutter/Dart" },
34918
+ { binary: "biome", language: "JS/TS (already in project)" },
34919
+ { binary: "eslint", language: "JS/TS" }
34920
+ ];
34921
+ });
34922
+
34565
34923
  // src/services/evidence-summary-service.ts
34566
34924
  var exports_evidence_summary_service = {};
34567
34925
  __export(exports_evidence_summary_service, {
@@ -37846,13 +38204,13 @@ __export(exports_evidence_summary_integration, {
37846
38204
  EvidenceSummaryIntegration: () => EvidenceSummaryIntegration
37847
38205
  });
37848
38206
  import { existsSync as existsSync21, mkdirSync as mkdirSync10, writeFileSync as writeFileSync5 } from "fs";
37849
- import * as path34 from "path";
38207
+ import * as path35 from "path";
37850
38208
  function persistSummary(swarmDir, artifact, filename) {
37851
- const swarmPath = path34.join(swarmDir, ".swarm");
38209
+ const swarmPath = path35.join(swarmDir, ".swarm");
37852
38210
  if (!existsSync21(swarmPath)) {
37853
38211
  mkdirSync10(swarmPath, { recursive: true });
37854
38212
  }
37855
- const artifactPath = path34.join(swarmPath, filename);
38213
+ const artifactPath = path35.join(swarmPath, filename);
37856
38214
  const content = JSON.stringify(artifact, null, 2);
37857
38215
  writeFileSync5(artifactPath, content, "utf-8");
37858
38216
  log("[EvidenceSummaryIntegration] Summary persisted", {
@@ -37971,7 +38329,7 @@ __export(exports_status_artifact, {
37971
38329
  AutomationStatusArtifact: () => AutomationStatusArtifact
37972
38330
  });
37973
38331
  import * as fs25 from "fs";
37974
- import * as path36 from "path";
38332
+ import * as path37 from "path";
37975
38333
  function createEmptySnapshot(mode, capabilities) {
37976
38334
  return {
37977
38335
  timestamp: Date.now(),
@@ -38030,7 +38388,7 @@ class AutomationStatusArtifact {
38030
38388
  });
38031
38389
  }
38032
38390
  getFilePath() {
38033
- return path36.join(this.swarmDir, this.filename);
38391
+ return path37.join(this.swarmDir, this.filename);
38034
38392
  }
38035
38393
  load() {
38036
38394
  const filePath = this.getFilePath();
@@ -38440,7 +38798,7 @@ __export(exports_gate_evidence, {
38440
38798
  DEFAULT_REQUIRED_GATES: () => DEFAULT_REQUIRED_GATES
38441
38799
  });
38442
38800
  import { mkdirSync as mkdirSync12, readFileSync as readFileSync18, renameSync as renameSync10, unlinkSync as unlinkSync5 } from "fs";
38443
- import * as path38 from "path";
38801
+ import * as path39 from "path";
38444
38802
  function isValidTaskId2(taskId) {
38445
38803
  if (!taskId)
38446
38804
  return false;
@@ -38487,10 +38845,10 @@ function expandRequiredGates(existingGates, newAgentType) {
38487
38845
  return combined.sort();
38488
38846
  }
38489
38847
  function getEvidenceDir(directory) {
38490
- return path38.join(directory, ".swarm", "evidence");
38848
+ return path39.join(directory, ".swarm", "evidence");
38491
38849
  }
38492
38850
  function getEvidencePath(directory, taskId) {
38493
- return path38.join(getEvidenceDir(directory), `${taskId}.json`);
38851
+ return path39.join(getEvidenceDir(directory), `${taskId}.json`);
38494
38852
  }
38495
38853
  function readExisting(evidencePath) {
38496
38854
  try {
@@ -38601,12 +38959,12 @@ __export(exports_review_receipt, {
38601
38959
  });
38602
38960
  import * as crypto5 from "crypto";
38603
38961
  import * as fs31 from "fs";
38604
- import * as path41 from "path";
38962
+ import * as path42 from "path";
38605
38963
  function resolveReceiptsDir(directory) {
38606
- return path41.join(directory, ".swarm", "review-receipts");
38964
+ return path42.join(directory, ".swarm", "review-receipts");
38607
38965
  }
38608
38966
  function resolveReceiptIndexPath(directory) {
38609
- return path41.join(resolveReceiptsDir(directory), "index.json");
38967
+ return path42.join(resolveReceiptsDir(directory), "index.json");
38610
38968
  }
38611
38969
  function buildReceiptFilename(id, date9) {
38612
38970
  const dateStr = date9.toISOString().slice(0, 10);
@@ -38645,7 +39003,7 @@ async function readReceiptIndex(directory) {
38645
39003
  }
38646
39004
  async function writeReceiptIndex(directory, index) {
38647
39005
  const indexPath = resolveReceiptIndexPath(directory);
38648
- const dir = path41.dirname(indexPath);
39006
+ const dir = path42.dirname(indexPath);
38649
39007
  await fs31.promises.mkdir(dir, { recursive: true });
38650
39008
  const tmpPath = `${indexPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
38651
39009
  await fs31.promises.writeFile(tmpPath, JSON.stringify(index, null, 2), "utf-8");
@@ -38656,7 +39014,7 @@ async function persistReviewReceipt(directory, receipt) {
38656
39014
  await fs31.promises.mkdir(receiptsDir, { recursive: true });
38657
39015
  const now = new Date(receipt.reviewed_at);
38658
39016
  const filename = buildReceiptFilename(receipt.id, now);
38659
- const receiptPath = path41.join(receiptsDir, filename);
39017
+ const receiptPath = path42.join(receiptsDir, filename);
38660
39018
  const tmpPath = `${receiptPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
38661
39019
  await fs31.promises.writeFile(tmpPath, JSON.stringify(receipt, null, 2), "utf-8");
38662
39020
  fs31.renameSync(tmpPath, receiptPath);
@@ -38678,7 +39036,7 @@ async function readReceiptById(directory, receiptId) {
38678
39036
  const entry = index.entries.find((e) => e.id === receiptId);
38679
39037
  if (!entry)
38680
39038
  return null;
38681
- const receiptPath = path41.join(resolveReceiptsDir(directory), entry.filename);
39039
+ const receiptPath = path42.join(resolveReceiptsDir(directory), entry.filename);
38682
39040
  try {
38683
39041
  const content = await fs31.promises.readFile(receiptPath, "utf-8");
38684
39042
  return JSON.parse(content);
@@ -38691,7 +39049,7 @@ async function readReceiptsByScopeHash(directory, scopeHash) {
38691
39049
  const matching = index.entries.filter((e) => e.scope_hash === scopeHash).sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
38692
39050
  const receipts = [];
38693
39051
  for (const entry of matching) {
38694
- const receiptPath = path41.join(resolveReceiptsDir(directory), entry.filename);
39052
+ const receiptPath = path42.join(resolveReceiptsDir(directory), entry.filename);
38695
39053
  try {
38696
39054
  const content = await fs31.promises.readFile(receiptPath, "utf-8");
38697
39055
  receipts.push(JSON.parse(content));
@@ -38704,7 +39062,7 @@ async function readAllReceipts(directory) {
38704
39062
  const sorted = [...index.entries].sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
38705
39063
  const receipts = [];
38706
39064
  for (const entry of sorted) {
38707
- const receiptPath = path41.join(resolveReceiptsDir(directory), entry.filename);
39065
+ const receiptPath = path42.join(resolveReceiptsDir(directory), entry.filename);
38708
39066
  try {
38709
39067
  const content = await fs31.promises.readFile(receiptPath, "utf-8");
38710
39068
  receipts.push(JSON.parse(content));
@@ -38839,14 +39197,14 @@ __export(exports_doc_scan, {
38839
39197
  });
38840
39198
  import * as crypto6 from "crypto";
38841
39199
  import * as fs34 from "fs";
38842
- import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
38843
- import * as path45 from "path";
39200
+ import { mkdir as mkdir7, readFile as readFile6, writeFile as writeFile6 } from "fs/promises";
39201
+ import * as path46 from "path";
38844
39202
  function normalizeSeparators(filePath) {
38845
39203
  return filePath.replace(/\\/g, "/");
38846
39204
  }
38847
39205
  function matchesDocPattern(filePath, patterns) {
38848
39206
  const normalizedPath = normalizeSeparators(filePath);
38849
- const basename6 = path45.basename(filePath);
39207
+ const basename6 = path46.basename(filePath);
38850
39208
  for (const pattern of patterns) {
38851
39209
  if (!pattern.includes("/") && !pattern.includes("\\")) {
38852
39210
  if (basename6 === pattern) {
@@ -38902,7 +39260,7 @@ function stripMarkdown(text) {
38902
39260
  return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*\u2022]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
38903
39261
  }
38904
39262
  async function scanDocIndex(directory) {
38905
- const manifestPath = path45.join(directory, ".swarm", "doc-manifest.json");
39263
+ const manifestPath = path46.join(directory, ".swarm", "doc-manifest.json");
38906
39264
  const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
38907
39265
  const extraPatterns = [
38908
39266
  "ARCHITECTURE.md",
@@ -38919,7 +39277,7 @@ async function scanDocIndex(directory) {
38919
39277
  let cacheValid = true;
38920
39278
  for (const file3 of existingManifest.files) {
38921
39279
  try {
38922
- const fullPath = path45.join(directory, file3.path);
39280
+ const fullPath = path46.join(directory, file3.path);
38923
39281
  const stat2 = fs34.statSync(fullPath);
38924
39282
  if (stat2.mtimeMs > new Date(existingManifest.scanned_at).getTime()) {
38925
39283
  cacheValid = false;
@@ -38949,7 +39307,7 @@ async function scanDocIndex(directory) {
38949
39307
  }
38950
39308
  const entries = rawEntries.filter((e) => typeof e === "string");
38951
39309
  for (const entry of entries) {
38952
- const fullPath = path45.join(directory, entry);
39310
+ const fullPath = path46.join(directory, entry);
38953
39311
  let stat2;
38954
39312
  try {
38955
39313
  stat2 = fs34.statSync(fullPath);
@@ -38985,7 +39343,7 @@ async function scanDocIndex(directory) {
38985
39343
  } catch {
38986
39344
  continue;
38987
39345
  }
38988
- const { title, summary } = extractTitleAndSummary(content, path45.basename(entry));
39346
+ const { title, summary } = extractTitleAndSummary(content, path46.basename(entry));
38989
39347
  const lineCount = content.split(`
38990
39348
  `).length;
38991
39349
  discoveredFiles.push({
@@ -39011,8 +39369,8 @@ async function scanDocIndex(directory) {
39011
39369
  files: discoveredFiles
39012
39370
  };
39013
39371
  try {
39014
- await mkdir6(path45.dirname(manifestPath), { recursive: true });
39015
- await writeFile5(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
39372
+ await mkdir7(path46.dirname(manifestPath), { recursive: true });
39373
+ await writeFile6(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
39016
39374
  } catch {}
39017
39375
  return { manifest, cached: false };
39018
39376
  }
@@ -39050,7 +39408,7 @@ function extractConstraintsFromContent(content) {
39050
39408
  return constraints;
39051
39409
  }
39052
39410
  async function extractDocConstraints(directory, taskFiles, taskDescription) {
39053
- const manifestPath = path45.join(directory, ".swarm", "doc-manifest.json");
39411
+ const manifestPath = path46.join(directory, ".swarm", "doc-manifest.json");
39054
39412
  let manifest;
39055
39413
  try {
39056
39414
  const content = await readFile6(manifestPath, "utf-8");
@@ -39076,7 +39434,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
39076
39434
  }
39077
39435
  let fullContent;
39078
39436
  try {
39079
- fullContent = await readFile6(path45.join(directory, docFile.path), "utf-8");
39437
+ fullContent = await readFile6(path46.join(directory, docFile.path), "utf-8");
39080
39438
  } catch {
39081
39439
  skippedCount++;
39082
39440
  continue;
@@ -39099,7 +39457,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
39099
39457
  tier: "swarm",
39100
39458
  lesson: constraint,
39101
39459
  category: "architecture",
39102
- tags: ["doc-scan", path45.basename(docFile.path)],
39460
+ tags: ["doc-scan", path46.basename(docFile.path)],
39103
39461
  scope: "global",
39104
39462
  confidence: 0.5,
39105
39463
  status: "candidate",
@@ -39172,7 +39530,7 @@ var init_doc_scan = __esm(() => {
39172
39530
  }
39173
39531
  } catch {}
39174
39532
  if (force) {
39175
- const manifestPath = path45.join(directory, ".swarm", "doc-manifest.json");
39533
+ const manifestPath = path46.join(directory, ".swarm", "doc-manifest.json");
39176
39534
  try {
39177
39535
  fs34.unlinkSync(manifestPath);
39178
39536
  } catch {}
@@ -39218,6 +39576,49 @@ var init_doc_scan = __esm(() => {
39218
39576
  });
39219
39577
  });
39220
39578
 
39579
+ // src/environment/prompt-renderer.ts
39580
+ var exports_prompt_renderer = {};
39581
+ __export(exports_prompt_renderer, {
39582
+ renderEnvironmentPrompt: () => renderEnvironmentPrompt
39583
+ });
39584
+ function renderEnvironmentPrompt(profile, audience) {
39585
+ const policy = deriveCommandPolicy(profile);
39586
+ const header = [
39587
+ "RUNTIME ENVIRONMENT",
39588
+ `- Host OS: ${profile.hostOS}`,
39589
+ `- Shell family: ${profile.shellFamily}`,
39590
+ `- Execution mode: ${profile.executionMode}`,
39591
+ `- Path style: ${profile.pathStyle}`
39592
+ ].join(`
39593
+ `);
39594
+ if (audience === "coder") {
39595
+ return [
39596
+ header,
39597
+ policy.avoidPosixExamples ? "- Command policy: Prefer PowerShell-native commands and Node.js APIs. Do not start with POSIX commands (ls, grep, rm, cat, export, pwd) unless the environment profile indicates Docker, WSL, or a POSIX shell." : "- Command policy: Use POSIX-native commands and Node.js APIs.",
39598
+ "",
39599
+ "EXECUTION ENVIRONMENT AWARENESS",
39600
+ "- This session includes a runtime environment profile. Follow it exactly.",
39601
+ "- Decision ladder when shell commands are necessary:",
39602
+ " 1. Prefer swarm tools and Node.js fs/path APIs.",
39603
+ " 2. Use shell only when the task truly requires it.",
39604
+ " 3. When shell commands are needed, match the active shell family above."
39605
+ ].join(`
39606
+ `);
39607
+ }
39608
+ return [
39609
+ header,
39610
+ `- Test execution policy: Always execute tests via the swarm test runner tool.`,
39611
+ policy.avoidPosixExamples ? " Do not describe POSIX shell setup commands unless the profile indicates Docker, WSL, or POSIX shell." : " Use POSIX semantics for test commands.",
39612
+ "",
39613
+ "ENVIRONMENT-SPECIFIC TEST EXECUTION RULES",
39614
+ profile.isWindowsNative ? "- Native Windows + PowerShell: Assume PowerShell semantics for paths and env vars. Prefer Pester for PowerShell modules where appropriate." : profile.isWindowsDocker ? "- Windows + Docker: Host paths are Windows-style; in-container operations use POSIX semantics." : "- Linux/macOS: Use POSIX semantics for all shell-related reasoning.",
39615
+ "- In all modes: prefer the swarm test runner over ad hoc shell commands.",
39616
+ "- When tests are skipped due to environment issues, explicitly mention the environment profile assumptions in your verdict."
39617
+ ].join(`
39618
+ `);
39619
+ }
39620
+ var init_prompt_renderer = () => {};
39621
+
39221
39622
  // src/hooks/curator-drift.ts
39222
39623
  var exports_curator_drift = {};
39223
39624
  __export(exports_curator_drift, {
@@ -39227,9 +39628,9 @@ __export(exports_curator_drift, {
39227
39628
  buildDriftInjectionText: () => buildDriftInjectionText
39228
39629
  });
39229
39630
  import * as fs37 from "fs";
39230
- import * as path48 from "path";
39631
+ import * as path49 from "path";
39231
39632
  async function readPriorDriftReports(directory) {
39232
- const swarmDir = path48.join(directory, ".swarm");
39633
+ const swarmDir = path49.join(directory, ".swarm");
39233
39634
  const entries = await fs37.promises.readdir(swarmDir).catch(() => null);
39234
39635
  if (entries === null)
39235
39636
  return [];
@@ -39256,7 +39657,7 @@ async function readPriorDriftReports(directory) {
39256
39657
  async function writeDriftReport(directory, report) {
39257
39658
  const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
39258
39659
  const filePath = validateSwarmPath(directory, filename);
39259
- const swarmDir = path48.dirname(filePath);
39660
+ const swarmDir = path49.dirname(filePath);
39260
39661
  await fs37.promises.mkdir(swarmDir, { recursive: true });
39261
39662
  try {
39262
39663
  await fs37.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
@@ -40849,11 +41250,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
40849
41250
  throw toThrow;
40850
41251
  }, "quit_");
40851
41252
  var scriptDirectory = "";
40852
- function locateFile(path58) {
41253
+ function locateFile(path59) {
40853
41254
  if (Module["locateFile"]) {
40854
- return Module["locateFile"](path58, scriptDirectory);
41255
+ return Module["locateFile"](path59, scriptDirectory);
40855
41256
  }
40856
- return scriptDirectory + path58;
41257
+ return scriptDirectory + path59;
40857
41258
  }
40858
41259
  __name(locateFile, "locateFile");
40859
41260
  var readAsync, readBinary;
@@ -42602,13 +43003,13 @@ __export(exports_runtime, {
42602
43003
  getInitializedLanguages: () => getInitializedLanguages,
42603
43004
  clearParserCache: () => clearParserCache
42604
43005
  });
42605
- import * as path58 from "path";
43006
+ import * as path59 from "path";
42606
43007
  import { fileURLToPath as fileURLToPath2 } from "url";
42607
43008
  async function initTreeSitter() {
42608
43009
  if (treeSitterInitialized) {
42609
43010
  return;
42610
43011
  }
42611
- const thisDir = path58.dirname(fileURLToPath2(import.meta.url));
43012
+ const thisDir = path59.dirname(fileURLToPath2(import.meta.url));
42612
43013
  const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
42613
43014
  if (isSource) {
42614
43015
  await Parser.init();
@@ -42616,7 +43017,7 @@ async function initTreeSitter() {
42616
43017
  const grammarsDir = getGrammarsDirAbsolute();
42617
43018
  await Parser.init({
42618
43019
  locateFile(scriptName) {
42619
- return path58.join(grammarsDir, scriptName);
43020
+ return path59.join(grammarsDir, scriptName);
42620
43021
  }
42621
43022
  });
42622
43023
  }
@@ -42637,9 +43038,9 @@ function getWasmFileName(languageId) {
42637
43038
  return `tree-sitter-${sanitized}.wasm`;
42638
43039
  }
42639
43040
  function getGrammarsDirAbsolute() {
42640
- const thisDir = path58.dirname(fileURLToPath2(import.meta.url));
43041
+ const thisDir = path59.dirname(fileURLToPath2(import.meta.url));
42641
43042
  const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
42642
- return isSource ? path58.join(thisDir, "grammars") : path58.join(thisDir, "lang", "grammars");
43043
+ return isSource ? path59.join(thisDir, "grammars") : path59.join(thisDir, "lang", "grammars");
42643
43044
  }
42644
43045
  async function loadGrammar(languageId) {
42645
43046
  if (typeof languageId !== "string" || languageId.length > 100) {
@@ -42655,7 +43056,7 @@ async function loadGrammar(languageId) {
42655
43056
  await initTreeSitter();
42656
43057
  const parser = new Parser;
42657
43058
  const wasmFileName = getWasmFileName(normalizedId);
42658
- const wasmPath = path58.join(getGrammarsDirAbsolute(), wasmFileName);
43059
+ const wasmPath = path59.join(getGrammarsDirAbsolute(), wasmFileName);
42659
43060
  const { existsSync: existsSync36 } = await import("fs");
42660
43061
  if (!existsSync36(wasmPath)) {
42661
43062
  throw new Error(`Grammar file not found for ${languageId}: ${wasmPath}
@@ -42690,7 +43091,7 @@ async function isGrammarAvailable(languageId) {
42690
43091
  }
42691
43092
  try {
42692
43093
  const wasmFileName = getWasmFileName(normalizedId);
42693
- const wasmPath = path58.join(getGrammarsDirAbsolute(), wasmFileName);
43094
+ const wasmPath = path59.join(getGrammarsDirAbsolute(), wasmFileName);
42694
43095
  const { statSync: statSync15 } = await import("fs");
42695
43096
  statSync15(wasmPath);
42696
43097
  return true;
@@ -42739,12 +43140,14 @@ var init_runtime = __esm(() => {
42739
43140
  });
42740
43141
 
42741
43142
  // src/index.ts
42742
- import * as path77 from "path";
43143
+ import * as path78 from "path";
42743
43144
 
42744
43145
  // src/agents/index.ts
42745
43146
  init_config();
42746
43147
  init_constants();
42747
43148
  init_schema();
43149
+ import { mkdir as mkdir5, writeFile as writeFile5 } from "fs/promises";
43150
+ import * as path34 from "path";
42748
43151
 
42749
43152
  // src/commands/agents.ts
42750
43153
  function handleAgentsCommand(agents, guardrails) {
@@ -46984,6 +47387,30 @@ async function getDiagnoseData(directory) {
46984
47387
  checks5.push(await checkEventStreamIntegrity(directory));
46985
47388
  checks5.push(await checkSteeringDirectives(directory));
46986
47389
  checks5.push(await checkCurator(directory));
47390
+ try {
47391
+ const evidenceDir = path19.join(directory, ".swarm", "evidence");
47392
+ const snapshotFiles = existsSync8(evidenceDir) ? readdirSync2(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
47393
+ if (snapshotFiles.length > 0) {
47394
+ const latest = snapshotFiles.sort().pop();
47395
+ checks5.push({
47396
+ name: "Agent Tool Snapshots",
47397
+ status: "\u2705",
47398
+ detail: `${snapshotFiles.length} snapshot(s) found \u2014 latest: ${latest}`
47399
+ });
47400
+ } else {
47401
+ checks5.push({
47402
+ name: "Agent Tool Snapshots",
47403
+ status: "\u2705",
47404
+ detail: "No snapshots yet (snapshots written on next session start)"
47405
+ });
47406
+ }
47407
+ } catch {
47408
+ checks5.push({
47409
+ name: "Agent Tool Snapshots",
47410
+ status: "\u2705",
47411
+ detail: "No snapshots yet (snapshots written on next session start)"
47412
+ });
47413
+ }
46987
47414
  const passCount = checks5.filter((c) => c.status === "\u2705").length;
46988
47415
  const totalCount = checks5.length;
46989
47416
  const allPassed = passCount === totalCount;
@@ -47012,134 +47439,7 @@ async function handleDiagnoseCommand(directory, _args) {
47012
47439
  // src/commands/doctor.ts
47013
47440
  init_loader();
47014
47441
  init_config_doctor();
47015
-
47016
- // src/services/tool-doctor.ts
47017
- init_discovery();
47018
- init_constants();
47019
- init_tool_names();
47020
- import * as fs13 from "fs";
47021
- import * as path22 from "path";
47022
- var BINARY_CHECKLIST = [
47023
- { binary: "ruff", language: "Python" },
47024
- { binary: "cargo", language: "Rust (via clippy)" },
47025
- { binary: "golangci-lint", language: "Go" },
47026
- { binary: "mvn", language: "Java (Maven)" },
47027
- { binary: "gradle", language: "Java (Gradle)" },
47028
- { binary: "dotnet", language: ".NET" },
47029
- { binary: "swift", language: "Swift" },
47030
- { binary: "swiftlint", language: "Swift (linting)" },
47031
- { binary: "dart", language: "Dart" },
47032
- { binary: "flutter", language: "Flutter/Dart" },
47033
- { binary: "biome", language: "JS/TS (already in project)" },
47034
- { binary: "eslint", language: "JS/TS" }
47035
- ];
47036
- function extractRegisteredToolKeys(indexPath) {
47037
- const registeredKeys = new Set;
47038
- try {
47039
- const content = fs13.readFileSync(indexPath, "utf-8");
47040
- const toolBlockMatch = content.match(/tool:\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}/s);
47041
- if (!toolBlockMatch) {
47042
- return registeredKeys;
47043
- }
47044
- const toolBlock = toolBlockMatch[1];
47045
- const keyPattern = /^\s*(\w+)(?:\s*:|,)/gm;
47046
- for (const match of toolBlock.matchAll(keyPattern)) {
47047
- registeredKeys.add(match[1]);
47048
- }
47049
- } catch (_error) {}
47050
- return registeredKeys;
47051
- }
47052
- function checkAgentToolMapAlignment(registeredKeys) {
47053
- const findings = [];
47054
- for (const [agentName, tools] of Object.entries(AGENT_TOOL_MAP)) {
47055
- for (const toolName of tools) {
47056
- if (!registeredKeys.has(toolName)) {
47057
- findings.push({
47058
- id: `agent-tool-map-mismatch-${agentName}-${toolName}`,
47059
- title: "AGENT_TOOL_MAP alignment gap",
47060
- description: `Tool "${toolName}" is assigned to agent "${agentName}" in AGENT_TOOL_MAP but is not registered in the plugin's tool: {} block. The agent will not be able to use this tool.`,
47061
- severity: "warn",
47062
- path: `AGENT_TOOL_MAP.${agentName}`,
47063
- currentValue: toolName,
47064
- autoFixable: false
47065
- });
47066
- }
47067
- }
47068
- }
47069
- return findings;
47070
- }
47071
- function checkBinaryReadiness() {
47072
- const findings = [];
47073
- for (const { binary: binary2, language } of BINARY_CHECKLIST) {
47074
- if (!isCommandAvailable(binary2)) {
47075
- findings.push({
47076
- id: `missing-binary-${binary2}`,
47077
- title: "Class 3 tool binary not found",
47078
- description: `Binary "${binary2}" is not available on PATH. ${language} linting will not be available. Install ${binary2} to enable ${language} language support.`,
47079
- severity: "warn",
47080
- path: `toolchain.${binary2}`,
47081
- currentValue: undefined,
47082
- autoFixable: false
47083
- });
47084
- }
47085
- }
47086
- return findings;
47087
- }
47088
- function runToolDoctor(_directory, pluginRoot) {
47089
- const findings = [];
47090
- const resolvedPluginRoot = pluginRoot ?? path22.resolve(import.meta.dir, "..", "..");
47091
- const indexPath = path22.join(resolvedPluginRoot, "src", "index.ts");
47092
- if (!fs13.existsSync(indexPath)) {
47093
- return {
47094
- findings: [
47095
- {
47096
- id: "plugin-src-unavailable",
47097
- title: "Plugin source not available",
47098
- description: `Tool registration check requires plugin source files. Expected: ${indexPath}. This check is available in development environments; in production npm installs, only compiled dist/ is present.`,
47099
- severity: "warn",
47100
- path: indexPath,
47101
- currentValue: undefined,
47102
- autoFixable: false
47103
- }
47104
- ],
47105
- summary: { info: 0, warn: 1, error: 0 },
47106
- hasAutoFixableIssues: false,
47107
- timestamp: Date.now(),
47108
- configSource: indexPath
47109
- };
47110
- }
47111
- const registeredKeys = extractRegisteredToolKeys(indexPath);
47112
- for (const toolName of TOOL_NAMES) {
47113
- if (!registeredKeys.has(toolName)) {
47114
- findings.push({
47115
- id: `missing-tool-registration-${toolName}`,
47116
- title: "Missing tool registration",
47117
- description: `Tool "${toolName}" is defined in TOOL_NAMES but is not registered in the plugin's tool: {} block. This means the tool will not be available at runtime.`,
47118
- severity: "error",
47119
- path: `tool.${toolName}`,
47120
- currentValue: undefined,
47121
- autoFixable: false
47122
- });
47123
- }
47124
- }
47125
- findings.push(...checkAgentToolMapAlignment(registeredKeys));
47126
- findings.push(...checkBinaryReadiness());
47127
- const summary = {
47128
- info: findings.filter((f) => f.severity === "info").length,
47129
- warn: findings.filter((f) => f.severity === "warn").length,
47130
- error: findings.filter((f) => f.severity === "error").length
47131
- };
47132
- const hasAutoFixableIssues = false;
47133
- return {
47134
- findings,
47135
- summary,
47136
- hasAutoFixableIssues,
47137
- timestamp: Date.now(),
47138
- configSource: indexPath
47139
- };
47140
- }
47141
-
47142
- // src/commands/doctor.ts
47442
+ init_tool_doctor();
47143
47443
  function formatToolDoctorMarkdown(result) {
47144
47444
  const lines = [
47145
47445
  "## Tool Doctor Report",
@@ -53285,12 +53585,13 @@ function createAgents(config3) {
53285
53585
  }
53286
53586
  return allAgents;
53287
53587
  }
53288
- function getAgentConfigs(config3) {
53588
+ function getAgentConfigs(config3, directory, sessionId) {
53289
53589
  const agents = createAgents(config3);
53290
53590
  const toolFilterEnabled = config3?.tool_filter?.enabled ?? true;
53291
53591
  const toolFilterOverrides = config3?.tool_filter?.overrides ?? {};
53292
53592
  const warnedMissingWhitelist = new Set;
53293
- return Object.fromEntries(agents.map((agent) => {
53593
+ const agentToolSnapshot = {};
53594
+ const result = Object.fromEntries(agents.map((agent) => {
53294
53595
  const sdkConfig = {
53295
53596
  ...agent.config,
53296
53597
  description: agent.description
@@ -53307,6 +53608,7 @@ function getAgentConfigs(config3) {
53307
53608
  const baseAgentName = stripKnownSwarmPrefix(agent.name);
53308
53609
  if (!toolFilterEnabled) {
53309
53610
  sdkConfig.tools = agent.config.tools ?? {};
53611
+ agentToolSnapshot[agent.name] = Object.keys(sdkConfig.tools ?? {}).filter((k) => sdkConfig.tools[k] !== false);
53310
53612
  return [agent.name, sdkConfig];
53311
53613
  }
53312
53614
  let allowedTools;
@@ -53339,8 +53641,21 @@ function getAgentConfigs(config3) {
53339
53641
  edit: false
53340
53642
  };
53341
53643
  }
53644
+ agentToolSnapshot[agent.name] = Object.keys(sdkConfig.tools ?? {}).filter((k) => sdkConfig.tools[k] !== false);
53342
53645
  return [agent.name, sdkConfig];
53343
53646
  }));
53647
+ if (directory) {
53648
+ const sid = sessionId ?? `init-${Date.now()}`;
53649
+ const evidenceDir = path34.join(directory, ".swarm", "evidence");
53650
+ const filename = `agent-tools-${sid}.json`;
53651
+ const snapshotData = JSON.stringify({
53652
+ sessionId: sid,
53653
+ generatedAt: new Date().toISOString(),
53654
+ agents: agentToolSnapshot
53655
+ }, null, 2);
53656
+ mkdir5(evidenceDir, { recursive: true }).then(() => writeFile5(path34.join(evidenceDir, filename), snapshotData)).catch(() => {});
53657
+ }
53658
+ return result;
53344
53659
  }
53345
53660
 
53346
53661
  // src/background/index.ts
@@ -53351,7 +53666,7 @@ init_evidence_summary_integration();
53351
53666
  init_manager2();
53352
53667
  init_utils();
53353
53668
  import * as fs24 from "fs";
53354
- import * as path35 from "path";
53669
+ import * as path36 from "path";
53355
53670
 
53356
53671
  class PlanSyncWorker {
53357
53672
  directory;
@@ -53375,10 +53690,10 @@ class PlanSyncWorker {
53375
53690
  this.onSyncComplete = options.onSyncComplete;
53376
53691
  }
53377
53692
  getSwarmDir() {
53378
- return path35.resolve(this.directory, ".swarm");
53693
+ return path36.resolve(this.directory, ".swarm");
53379
53694
  }
53380
53695
  getPlanJsonPath() {
53381
- return path35.join(this.getSwarmDir(), "plan.json");
53696
+ return path36.join(this.getSwarmDir(), "plan.json");
53382
53697
  }
53383
53698
  start() {
53384
53699
  if (this.disposed) {
@@ -53597,8 +53912,8 @@ class PlanSyncWorker {
53597
53912
  checkForUnauthorizedWrite() {
53598
53913
  try {
53599
53914
  const swarmDir = this.getSwarmDir();
53600
- const planJsonPath = path35.join(swarmDir, "plan.json");
53601
- const markerPath = path35.join(swarmDir, ".plan-write-marker");
53915
+ const planJsonPath = path36.join(swarmDir, "plan.json");
53916
+ const markerPath = path36.join(swarmDir, ".plan-write-marker");
53602
53917
  const planStats = fs24.statSync(planJsonPath);
53603
53918
  const planMtimeMs = planStats.mtimeMs;
53604
53919
  const markerContent = fs24.readFileSync(markerPath, "utf8");
@@ -53747,11 +54062,11 @@ async function doFlush(directory) {
53747
54062
  const activitySection = renderActivitySection();
53748
54063
  const updated = replaceOrAppendSection(existing, "## Agent Activity", activitySection);
53749
54064
  const flushedCount = swarmState.pendingEvents;
53750
- const path37 = nodePath2.join(directory, ".swarm", "context.md");
53751
- const tempPath = `${path37}.tmp`;
54065
+ const path38 = nodePath2.join(directory, ".swarm", "context.md");
54066
+ const tempPath = `${path38}.tmp`;
53752
54067
  try {
53753
54068
  await Bun.write(tempPath, updated);
53754
- renameSync9(tempPath, path37);
54069
+ renameSync9(tempPath, path38);
53755
54070
  } catch (writeError) {
53756
54071
  try {
53757
54072
  unlinkSync4(tempPath);
@@ -53801,7 +54116,7 @@ ${content.substring(endIndex + 1)}`;
53801
54116
  // src/hooks/compaction-customizer.ts
53802
54117
  init_manager2();
53803
54118
  import * as fs26 from "fs";
53804
- import { join as join33 } from "path";
54119
+ import { join as join34 } from "path";
53805
54120
  init_utils2();
53806
54121
  function createCompactionCustomizerHook(config3, directory) {
53807
54122
  const enabled = config3.hooks?.compaction !== false;
@@ -53847,7 +54162,7 @@ function createCompactionCustomizerHook(config3, directory) {
53847
54162
  }
53848
54163
  }
53849
54164
  try {
53850
- const summariesDir = join33(directory, ".swarm", "summaries");
54165
+ const summariesDir = join34(directory, ".swarm", "summaries");
53851
54166
  const files = await fs26.promises.readdir(summariesDir);
53852
54167
  if (files.length > 0) {
53853
54168
  const count = files.length;
@@ -54429,7 +54744,7 @@ function createCuratorLLMDelegate(directory, mode = "init", sessionId) {
54429
54744
  // src/hooks/delegation-gate.ts
54430
54745
  init_schema();
54431
54746
  import * as fs27 from "fs";
54432
- import * as path39 from "path";
54747
+ import * as path40 from "path";
54433
54748
 
54434
54749
  // src/parallel/review-router.ts
54435
54750
  async function computeComplexity(directory, changedFiles) {
@@ -54442,8 +54757,8 @@ async function computeComplexity(directory, changedFiles) {
54442
54757
  }
54443
54758
  try {
54444
54759
  const fs27 = await import("fs");
54445
- const path37 = await import("path");
54446
- const filePath = path37.join(directory, file3);
54760
+ const path38 = await import("path");
54761
+ const filePath = path38.join(directory, file3);
54447
54762
  if (!fs27.existsSync(filePath)) {
54448
54763
  continue;
54449
54764
  }
@@ -54496,7 +54811,7 @@ init_state();
54496
54811
  init_telemetry();
54497
54812
 
54498
54813
  // src/hooks/guardrails.ts
54499
- import * as path37 from "path";
54814
+ import * as path38 from "path";
54500
54815
  init_constants();
54501
54816
  init_schema();
54502
54817
 
@@ -54694,10 +55009,10 @@ function isArchitect(sessionId) {
54694
55009
  function isOutsideSwarmDir(filePath, directory) {
54695
55010
  if (!filePath)
54696
55011
  return false;
54697
- const swarmDir = path37.resolve(directory, ".swarm");
54698
- const resolved = path37.resolve(directory, filePath);
54699
- const relative5 = path37.relative(swarmDir, resolved);
54700
- return relative5.startsWith("..") || path37.isAbsolute(relative5);
55012
+ const swarmDir = path38.resolve(directory, ".swarm");
55013
+ const resolved = path38.resolve(directory, filePath);
55014
+ const relative5 = path38.relative(swarmDir, resolved);
55015
+ return relative5.startsWith("..") || path38.isAbsolute(relative5);
54701
55016
  }
54702
55017
  function isSourceCodePath(filePath) {
54703
55018
  if (!filePath)
@@ -54765,13 +55080,13 @@ function getCurrentTaskId(sessionId) {
54765
55080
  }
54766
55081
  function isInDeclaredScope(filePath, scopeEntries, cwd) {
54767
55082
  const dir = cwd ?? process.cwd();
54768
- const resolvedFile = path37.resolve(dir, filePath);
55083
+ const resolvedFile = path38.resolve(dir, filePath);
54769
55084
  return scopeEntries.some((scope) => {
54770
- const resolvedScope = path37.resolve(dir, scope);
55085
+ const resolvedScope = path38.resolve(dir, scope);
54771
55086
  if (resolvedFile === resolvedScope)
54772
55087
  return true;
54773
- const rel = path37.relative(resolvedScope, resolvedFile);
54774
- return rel.length > 0 && !rel.startsWith("..") && !path37.isAbsolute(rel);
55088
+ const rel = path38.relative(resolvedScope, resolvedFile);
55089
+ return rel.length > 0 && !rel.startsWith("..") && !path38.isAbsolute(rel);
54775
55090
  });
54776
55091
  }
54777
55092
  function createGuardrailsHooks(directory, directoryOrConfig, config3, authorityConfig) {
@@ -55030,18 +55345,18 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3, authorityC
55030
55345
  const toolArgs = args2;
55031
55346
  const targetPath = toolArgs?.filePath ?? toolArgs?.path ?? toolArgs?.file ?? toolArgs?.target;
55032
55347
  if (typeof targetPath === "string" && targetPath.length > 0) {
55033
- const resolvedTarget = path37.resolve(effectiveDirectory, targetPath).toLowerCase();
55034
- const planMdPath = path37.resolve(effectiveDirectory, ".swarm", "plan.md").toLowerCase();
55035
- const planJsonPath = path37.resolve(effectiveDirectory, ".swarm", "plan.json").toLowerCase();
55348
+ const resolvedTarget = path38.resolve(effectiveDirectory, targetPath).toLowerCase();
55349
+ const planMdPath = path38.resolve(effectiveDirectory, ".swarm", "plan.md").toLowerCase();
55350
+ const planJsonPath = path38.resolve(effectiveDirectory, ".swarm", "plan.json").toLowerCase();
55036
55351
  if (resolvedTarget === planMdPath || resolvedTarget === planJsonPath) {
55037
55352
  throw new Error("PLAN STATE VIOLATION: Direct writes to .swarm/plan.md and .swarm/plan.json are blocked. " + "plan.md is auto-regenerated from plan.json by PlanSyncWorker. " + "Use update_task_status() to mark tasks complete, " + "phase_complete() for phase transitions, or " + "save_plan to create/restructure plans.");
55038
55353
  }
55039
55354
  }
55040
55355
  if (!targetPath && (tool3 === "apply_patch" || tool3 === "patch")) {
55041
55356
  for (const p of extractPatchTargetPaths(tool3, args2)) {
55042
- const resolvedP = path37.resolve(effectiveDirectory, p);
55043
- const planMdPath = path37.resolve(effectiveDirectory, ".swarm", "plan.md").toLowerCase();
55044
- const planJsonPath = path37.resolve(effectiveDirectory, ".swarm", "plan.json").toLowerCase();
55357
+ const resolvedP = path38.resolve(effectiveDirectory, p);
55358
+ const planMdPath = path38.resolve(effectiveDirectory, ".swarm", "plan.md").toLowerCase();
55359
+ const planJsonPath = path38.resolve(effectiveDirectory, ".swarm", "plan.json").toLowerCase();
55045
55360
  if (resolvedP.toLowerCase() === planMdPath || resolvedP.toLowerCase() === planJsonPath) {
55046
55361
  throw new Error("PLAN STATE VIOLATION: Direct writes to .swarm/plan.md and .swarm/plan.json are blocked. " + "plan.md is auto-regenerated from plan.json by PlanSyncWorker. " + "Use update_task_status() to mark tasks complete, " + "phase_complete() for phase transitions, or " + "save_plan to create/restructure plans.");
55047
55362
  }
@@ -55060,7 +55375,7 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3, authorityC
55060
55375
  }
55061
55376
  }
55062
55377
  }
55063
- if (typeof targetPath === "string" && targetPath.length > 0 && isOutsideSwarmDir(targetPath, effectiveDirectory) && isSourceCodePath(path37.relative(effectiveDirectory, path37.resolve(effectiveDirectory, targetPath)))) {
55378
+ if (typeof targetPath === "string" && targetPath.length > 0 && isOutsideSwarmDir(targetPath, effectiveDirectory) && isSourceCodePath(path38.relative(effectiveDirectory, path38.resolve(effectiveDirectory, targetPath)))) {
55064
55379
  const session = swarmState.agentSessions.get(sessionID);
55065
55380
  if (session) {
55066
55381
  session.architectWriteCount++;
@@ -55762,8 +56077,8 @@ function checkFileAuthorityWithRules(agentName, filePath, cwd, effectiveRules) {
55762
56077
  const normalizedAgent = agentName.toLowerCase();
55763
56078
  const strippedAgent = stripKnownSwarmPrefix(agentName).toLowerCase();
55764
56079
  const dir = cwd || process.cwd();
55765
- const resolved = path37.resolve(dir, filePath);
55766
- const normalizedPath = path37.relative(dir, resolved).replace(/\\/g, "/");
56080
+ const resolved = path38.resolve(dir, filePath);
56081
+ const normalizedPath = path38.relative(dir, resolved).replace(/\\/g, "/");
55767
56082
  const rules = effectiveRules[normalizedAgent] ?? effectiveRules[strippedAgent];
55768
56083
  if (!rules) {
55769
56084
  return { allowed: false, reason: `Unknown agent: ${agentName}` };
@@ -55845,10 +56160,10 @@ async function getEvidenceTaskId(session, directory) {
55845
56160
  if (typeof directory !== "string" || directory.length === 0) {
55846
56161
  return null;
55847
56162
  }
55848
- const resolvedDirectory = path39.resolve(directory);
55849
- const planPath = path39.join(resolvedDirectory, ".swarm", "plan.json");
55850
- const resolvedPlanPath = path39.resolve(planPath);
55851
- if (!resolvedPlanPath.startsWith(resolvedDirectory + path39.sep) && resolvedPlanPath !== resolvedDirectory) {
56163
+ const resolvedDirectory = path40.resolve(directory);
56164
+ const planPath = path40.join(resolvedDirectory, ".swarm", "plan.json");
56165
+ const resolvedPlanPath = path40.resolve(planPath);
56166
+ if (!resolvedPlanPath.startsWith(resolvedDirectory + path40.sep) && resolvedPlanPath !== resolvedDirectory) {
55852
56167
  return null;
55853
56168
  }
55854
56169
  const planContent = await fs27.promises.readFile(resolvedPlanPath, "utf-8");
@@ -56519,20 +56834,20 @@ init_schema();
56519
56834
  // src/parallel/file-locks.ts
56520
56835
  var import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
56521
56836
  import * as fs29 from "fs";
56522
- import * as path40 from "path";
56837
+ import * as path41 from "path";
56523
56838
  var LOCKS_DIR = ".swarm/locks";
56524
56839
  var LOCK_TIMEOUT_MS = 5 * 60 * 1000;
56525
56840
  function getLockFilePath(directory, filePath) {
56526
- const normalized = path40.resolve(directory, filePath);
56527
- if (!normalized.startsWith(path40.resolve(directory))) {
56841
+ const normalized = path41.resolve(directory, filePath);
56842
+ if (!normalized.startsWith(path41.resolve(directory))) {
56528
56843
  throw new Error("Invalid file path: path traversal not allowed");
56529
56844
  }
56530
56845
  const hash3 = Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
56531
- return path40.join(directory, LOCKS_DIR, `${hash3}.lock`);
56846
+ return path41.join(directory, LOCKS_DIR, `${hash3}.lock`);
56532
56847
  }
56533
56848
  async function tryAcquireLock(directory, filePath, agent, taskId) {
56534
56849
  const lockPath = getLockFilePath(directory, filePath);
56535
- const locksDir = path40.dirname(lockPath);
56850
+ const locksDir = path41.dirname(lockPath);
56536
56851
  if (!fs29.existsSync(locksDir)) {
56537
56852
  fs29.mkdirSync(locksDir, { recursive: true });
56538
56853
  }
@@ -57194,7 +57509,7 @@ function consolidateSystemMessages(messages) {
57194
57509
  // src/hooks/phase-monitor.ts
57195
57510
  init_schema();
57196
57511
  init_manager2();
57197
- import * as path42 from "path";
57512
+ import * as path43 from "path";
57198
57513
  init_utils2();
57199
57514
  function createPhaseMonitorHook(directory, preflightManager, curatorRunner, delegateFactory) {
57200
57515
  let lastKnownPhase = null;
@@ -57215,10 +57530,10 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner, dele
57215
57530
  const llmDelegate = delegateFactory?.(sessionId);
57216
57531
  const initResult = await runner(directory, curatorConfig, llmDelegate);
57217
57532
  if (initResult.briefing) {
57218
- const briefingPath = path42.join(directory, ".swarm", "curator-briefing.md");
57219
- const { mkdir: mkdir5, writeFile: writeFile5 } = await import("fs/promises");
57220
- await mkdir5(path42.dirname(briefingPath), { recursive: true });
57221
- await writeFile5(briefingPath, initResult.briefing, "utf-8");
57533
+ const briefingPath = path43.join(directory, ".swarm", "curator-briefing.md");
57534
+ const { mkdir: mkdir6, writeFile: writeFile6 } = await import("fs/promises");
57535
+ await mkdir6(path43.dirname(briefingPath), { recursive: true });
57536
+ await writeFile6(briefingPath, initResult.briefing, "utf-8");
57222
57537
  const { buildApprovedReceipt: buildApprovedReceipt2, persistReviewReceipt: persistReviewReceipt2 } = await Promise.resolve().then(() => (init_review_receipt(), exports_review_receipt));
57223
57538
  const initReceipt = buildApprovedReceipt2({
57224
57539
  agent: "curator",
@@ -57351,14 +57666,14 @@ init_manager();
57351
57666
  init_detector();
57352
57667
  init_manager2();
57353
57668
  import * as fs35 from "fs";
57354
- import * as path46 from "path";
57669
+ import * as path47 from "path";
57355
57670
 
57356
57671
  // src/services/decision-drift-analyzer.ts
57357
57672
  init_utils2();
57358
57673
  init_manager2();
57359
57674
  init_utils();
57360
57675
  import * as fs32 from "fs";
57361
- import * as path43 from "path";
57676
+ import * as path44 from "path";
57362
57677
  var DEFAULT_DRIFT_CONFIG = {
57363
57678
  staleThresholdPhases: 1,
57364
57679
  detectContradictions: true,
@@ -57512,7 +57827,7 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
57512
57827
  currentPhase = legacyPhase;
57513
57828
  }
57514
57829
  }
57515
- const contextPath = path43.join(directory, ".swarm", "context.md");
57830
+ const contextPath = path44.join(directory, ".swarm", "context.md");
57516
57831
  let contextContent = "";
57517
57832
  try {
57518
57833
  if (fs32.existsSync(contextPath)) {
@@ -57643,7 +57958,7 @@ init_utils();
57643
57958
  init_constants();
57644
57959
  init_schema();
57645
57960
  import * as fs33 from "fs/promises";
57646
- import * as path44 from "path";
57961
+ import * as path45 from "path";
57647
57962
  function safeGet(obj, key) {
57648
57963
  if (!obj || !Object.hasOwn(obj, key))
57649
57964
  return;
@@ -57873,9 +58188,9 @@ async function handleDebuggingSpiral(match, taskId, directory) {
57873
58188
  let eventLogged = false;
57874
58189
  let checkpointCreated = false;
57875
58190
  try {
57876
- const swarmDir = path44.join(directory, ".swarm");
58191
+ const swarmDir = path45.join(directory, ".swarm");
57877
58192
  await fs33.mkdir(swarmDir, { recursive: true });
57878
- const eventsPath = path44.join(swarmDir, "events.jsonl");
58193
+ const eventsPath = path45.join(swarmDir, "events.jsonl");
57879
58194
  await fs33.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
57880
58195
  `);
57881
58196
  eventLogged = true;
@@ -58302,7 +58617,7 @@ function createSystemEnhancerHook(config3, directory) {
58302
58617
  await fs35.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
58303
58618
  warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
58304
58619
  try {
58305
- const projectName = path46.basename(path46.resolve(directory));
58620
+ const projectName = path47.basename(path47.resolve(directory));
58306
58621
  const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
58307
58622
  const knowledgePath = resolveSwarmKnowledgePath(directory);
58308
58623
  const existingEntries = await readKnowledge(knowledgePath);
@@ -58599,6 +58914,30 @@ ${budgetWarning}`);
58599
58914
  }
58600
58915
  }
58601
58916
  }
58917
+ try {
58918
+ const activeAgent_binary = swarmState.activeAgent.get(_input.sessionID ?? "");
58919
+ const isArchitect_binary = !activeAgent_binary || stripKnownSwarmPrefix(activeAgent_binary) === "architect";
58920
+ if (isArchitect_binary) {
58921
+ const { getBinaryReadinessAdvisory: getBinaryReadinessAdvisory2 } = await Promise.resolve().then(() => (init_tool_doctor(), exports_tool_doctor));
58922
+ const advisory = getBinaryReadinessAdvisory2();
58923
+ if (advisory) {
58924
+ tryInject(advisory);
58925
+ }
58926
+ }
58927
+ } catch {}
58928
+ try {
58929
+ const activeAgent_env = swarmState.activeAgent.get(_input.sessionID ?? "");
58930
+ const agentBase_env = stripKnownSwarmPrefix(activeAgent_env ?? "").toLowerCase();
58931
+ if (agentBase_env === "coder" || agentBase_env === "test_engineer") {
58932
+ const { ensureSessionEnvironment: ensureSessionEnvironment2 } = await Promise.resolve().then(() => (init_state(), exports_state));
58933
+ const { renderEnvironmentPrompt: renderEnvironmentPrompt2 } = await Promise.resolve().then(() => (init_prompt_renderer(), exports_prompt_renderer));
58934
+ const envSessionId = _input.sessionID ?? "unknown";
58935
+ const profile = ensureSessionEnvironment2(envSessionId);
58936
+ const audience = agentBase_env === "coder" ? "coder" : "testengineer";
58937
+ const envPrompt = renderEnvironmentPrompt2(profile, audience);
58938
+ tryInject(envPrompt);
58939
+ }
58940
+ } catch {}
58602
58941
  return;
58603
58942
  }
58604
58943
  const mode_b = await detectArchitectMode(directory);
@@ -58999,6 +59338,44 @@ ${handoffBlock}`;
58999
59338
  } catch {}
59000
59339
  }
59001
59340
  }
59341
+ try {
59342
+ const activeAgent_binary_b = swarmState.activeAgent.get(_input.sessionID ?? "");
59343
+ const isArchitect_binary_b = !activeAgent_binary_b || stripKnownSwarmPrefix(activeAgent_binary_b) === "architect";
59344
+ if (isArchitect_binary_b) {
59345
+ const { getBinaryReadinessAdvisory: getBinaryReadinessAdvisory2 } = await Promise.resolve().then(() => (init_tool_doctor(), exports_tool_doctor));
59346
+ const advisory_b = getBinaryReadinessAdvisory2();
59347
+ if (advisory_b) {
59348
+ candidates.push({
59349
+ id: `candidate-${idCounter++}`,
59350
+ kind: "agent_context",
59351
+ text: advisory_b,
59352
+ tokens: estimateTokens(advisory_b),
59353
+ priority: 3,
59354
+ metadata: { contentType: "prose" }
59355
+ });
59356
+ }
59357
+ }
59358
+ } catch {}
59359
+ try {
59360
+ const activeAgent_env_b = swarmState.activeAgent.get(_input.sessionID ?? "");
59361
+ const agentBase_env_b = stripKnownSwarmPrefix(activeAgent_env_b ?? "").toLowerCase();
59362
+ if (agentBase_env_b === "coder" || agentBase_env_b === "test_engineer") {
59363
+ const { ensureSessionEnvironment: ensureSessionEnvironment2 } = await Promise.resolve().then(() => (init_state(), exports_state));
59364
+ const { renderEnvironmentPrompt: renderEnvironmentPrompt2 } = await Promise.resolve().then(() => (init_prompt_renderer(), exports_prompt_renderer));
59365
+ const envSessionId_b = _input.sessionID ?? "unknown";
59366
+ const profile_b = ensureSessionEnvironment2(envSessionId_b);
59367
+ const audience_b = agentBase_env_b === "coder" ? "coder" : "testengineer";
59368
+ const envPrompt_b = renderEnvironmentPrompt2(profile_b, audience_b);
59369
+ candidates.push({
59370
+ id: `candidate-${idCounter++}`,
59371
+ kind: "agent_context",
59372
+ text: envPrompt_b,
59373
+ tokens: estimateTokens(envPrompt_b),
59374
+ priority: 2,
59375
+ metadata: { contentType: "prose" }
59376
+ });
59377
+ }
59378
+ } catch {}
59002
59379
  const ranked = rankCandidates(candidates, effectiveConfig);
59003
59380
  for (const candidate of ranked) {
59004
59381
  if (injectedTokens + candidate.tokens > maxInjectionTokens) {
@@ -59485,7 +59862,7 @@ function isReadTool(toolName) {
59485
59862
 
59486
59863
  // src/hooks/incremental-verify.ts
59487
59864
  import * as fs36 from "fs";
59488
- import * as path47 from "path";
59865
+ import * as path48 from "path";
59489
59866
 
59490
59867
  // src/hooks/spawn-helper.ts
59491
59868
  import * as child_process5 from "child_process";
@@ -59563,18 +59940,18 @@ function spawnAsync(command, cwd, timeoutMs) {
59563
59940
  // src/hooks/incremental-verify.ts
59564
59941
  var emittedSkipAdvisories = new Set;
59565
59942
  function detectPackageManager(projectDir) {
59566
- if (fs36.existsSync(path47.join(projectDir, "bun.lockb")))
59943
+ if (fs36.existsSync(path48.join(projectDir, "bun.lockb")))
59567
59944
  return "bun";
59568
- if (fs36.existsSync(path47.join(projectDir, "pnpm-lock.yaml")))
59945
+ if (fs36.existsSync(path48.join(projectDir, "pnpm-lock.yaml")))
59569
59946
  return "pnpm";
59570
- if (fs36.existsSync(path47.join(projectDir, "yarn.lock")))
59947
+ if (fs36.existsSync(path48.join(projectDir, "yarn.lock")))
59571
59948
  return "yarn";
59572
- if (fs36.existsSync(path47.join(projectDir, "package-lock.json")))
59949
+ if (fs36.existsSync(path48.join(projectDir, "package-lock.json")))
59573
59950
  return "npm";
59574
59951
  return "bun";
59575
59952
  }
59576
59953
  function detectTypecheckCommand(projectDir) {
59577
- const pkgPath = path47.join(projectDir, "package.json");
59954
+ const pkgPath = path48.join(projectDir, "package.json");
59578
59955
  if (fs36.existsSync(pkgPath)) {
59579
59956
  try {
59580
59957
  const pkg = JSON.parse(fs36.readFileSync(pkgPath, "utf8"));
@@ -59591,8 +59968,8 @@ function detectTypecheckCommand(projectDir) {
59591
59968
  ...pkg.dependencies,
59592
59969
  ...pkg.devDependencies
59593
59970
  };
59594
- if (!deps?.typescript && !fs36.existsSync(path47.join(projectDir, "tsconfig.json"))) {}
59595
- const hasTSMarkers = deps?.typescript || fs36.existsSync(path47.join(projectDir, "tsconfig.json"));
59971
+ if (!deps?.typescript && !fs36.existsSync(path48.join(projectDir, "tsconfig.json"))) {}
59972
+ const hasTSMarkers = deps?.typescript || fs36.existsSync(path48.join(projectDir, "tsconfig.json"));
59596
59973
  if (hasTSMarkers) {
59597
59974
  return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
59598
59975
  }
@@ -59600,13 +59977,13 @@ function detectTypecheckCommand(projectDir) {
59600
59977
  return null;
59601
59978
  }
59602
59979
  }
59603
- if (fs36.existsSync(path47.join(projectDir, "go.mod"))) {
59980
+ if (fs36.existsSync(path48.join(projectDir, "go.mod"))) {
59604
59981
  return { command: ["go", "vet", "./..."], language: "go" };
59605
59982
  }
59606
- if (fs36.existsSync(path47.join(projectDir, "Cargo.toml"))) {
59983
+ if (fs36.existsSync(path48.join(projectDir, "Cargo.toml"))) {
59607
59984
  return { command: ["cargo", "check"], language: "rust" };
59608
59985
  }
59609
- if (fs36.existsSync(path47.join(projectDir, "pyproject.toml")) || fs36.existsSync(path47.join(projectDir, "requirements.txt")) || fs36.existsSync(path47.join(projectDir, "setup.py"))) {
59986
+ if (fs36.existsSync(path48.join(projectDir, "pyproject.toml")) || fs36.existsSync(path48.join(projectDir, "requirements.txt")) || fs36.existsSync(path48.join(projectDir, "setup.py"))) {
59610
59987
  return { command: null, language: "python" };
59611
59988
  }
59612
59989
  try {
@@ -59847,7 +60224,7 @@ function createKnowledgeInjectorHook(directory, config3) {
59847
60224
  return sum + (msg.parts?.reduce((s, p) => s + (p.text?.length ?? 0), 0) ?? 0);
59848
60225
  }, 0);
59849
60226
  const headroomChars = MODEL_LIMIT_CHARS - existingChars;
59850
- const MIN_INJECT_CHARS = 300;
60227
+ const MIN_INJECT_CHARS = config3.context_budget_threshold ?? 300;
59851
60228
  if (headroomChars < MIN_INJECT_CHARS) {
59852
60229
  console.warn(`[knowledge-injector] Skipping: only ${headroomChars} chars of headroom remain (existing: ${existingChars}, limit: ${MODEL_LIMIT_CHARS})`);
59853
60230
  return;
@@ -59945,7 +60322,7 @@ ${freshPreamble}` : `<curator_briefing>${truncatedBriefing}</curator_briefing>`;
59945
60322
  init_constants();
59946
60323
  init_schema();
59947
60324
  init_state();
59948
- import * as path49 from "path";
60325
+ import * as path50 from "path";
59949
60326
  var WRITE_TOOLS = new Set(WRITE_TOOL_NAMES);
59950
60327
  function createScopeGuardHook(config3, directory, injectAdvisory) {
59951
60328
  const enabled = config3.enabled ?? true;
@@ -59997,13 +60374,13 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
59997
60374
  }
59998
60375
  function isFileInScope(filePath, scopeEntries, directory) {
59999
60376
  const dir = directory ?? process.cwd();
60000
- const resolvedFile = path49.resolve(dir, filePath);
60377
+ const resolvedFile = path50.resolve(dir, filePath);
60001
60378
  return scopeEntries.some((scope) => {
60002
- const resolvedScope = path49.resolve(dir, scope);
60379
+ const resolvedScope = path50.resolve(dir, scope);
60003
60380
  if (resolvedFile === resolvedScope)
60004
60381
  return true;
60005
- const rel = path49.relative(resolvedScope, resolvedFile);
60006
- return rel.length > 0 && !rel.startsWith("..") && !path49.isAbsolute(rel);
60382
+ const rel = path50.relative(resolvedScope, resolvedFile);
60383
+ return rel.length > 0 && !rel.startsWith("..") && !path50.isAbsolute(rel);
60007
60384
  });
60008
60385
  }
60009
60386
 
@@ -60054,7 +60431,7 @@ function createSelfReviewHook(config3, injectAdvisory) {
60054
60431
 
60055
60432
  // src/hooks/slop-detector.ts
60056
60433
  import * as fs38 from "fs";
60057
- import * as path50 from "path";
60434
+ import * as path51 from "path";
60058
60435
  var WRITE_EDIT_TOOLS = new Set([
60059
60436
  "write",
60060
60437
  "edit",
@@ -60104,7 +60481,7 @@ function walkFiles(dir, exts, deadline) {
60104
60481
  break;
60105
60482
  if (entry.isSymbolicLink())
60106
60483
  continue;
60107
- const full = path50.join(dir, entry.name);
60484
+ const full = path51.join(dir, entry.name);
60108
60485
  if (entry.isDirectory()) {
60109
60486
  if (entry.name === "node_modules" || entry.name === ".git")
60110
60487
  continue;
@@ -60119,7 +60496,7 @@ function walkFiles(dir, exts, deadline) {
60119
60496
  return results;
60120
60497
  }
60121
60498
  function checkDeadExports(content, projectDir, startTime) {
60122
- const hasPackageJson = fs38.existsSync(path50.join(projectDir, "package.json"));
60499
+ const hasPackageJson = fs38.existsSync(path51.join(projectDir, "package.json"));
60123
60500
  if (!hasPackageJson)
60124
60501
  return null;
60125
60502
  const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
@@ -60531,13 +60908,13 @@ init_telemetry();
60531
60908
  init_tool();
60532
60909
  init_create_tool();
60533
60910
  import * as fs41 from "fs";
60534
- import * as path52 from "path";
60911
+ import * as path53 from "path";
60535
60912
 
60536
60913
  // src/tools/symbols.ts
60537
60914
  init_tool();
60538
60915
  init_create_tool();
60539
60916
  import * as fs40 from "fs";
60540
- import * as path51 from "path";
60917
+ import * as path52 from "path";
60541
60918
  var MAX_FILE_SIZE_BYTES2 = 1024 * 1024;
60542
60919
  var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
60543
60920
  function containsWindowsAttacks(str) {
@@ -60554,11 +60931,11 @@ function containsWindowsAttacks(str) {
60554
60931
  }
60555
60932
  function isPathInWorkspace(filePath, workspace) {
60556
60933
  try {
60557
- const resolvedPath = path51.resolve(workspace, filePath);
60934
+ const resolvedPath = path52.resolve(workspace, filePath);
60558
60935
  const realWorkspace = fs40.realpathSync(workspace);
60559
60936
  const realResolvedPath = fs40.realpathSync(resolvedPath);
60560
- const relativePath = path51.relative(realWorkspace, realResolvedPath);
60561
- if (relativePath.startsWith("..") || path51.isAbsolute(relativePath)) {
60937
+ const relativePath = path52.relative(realWorkspace, realResolvedPath);
60938
+ if (relativePath.startsWith("..") || path52.isAbsolute(relativePath)) {
60562
60939
  return false;
60563
60940
  }
60564
60941
  return true;
@@ -60570,7 +60947,7 @@ function validatePathForRead(filePath, workspace) {
60570
60947
  return isPathInWorkspace(filePath, workspace);
60571
60948
  }
60572
60949
  function extractTSSymbols(filePath, cwd) {
60573
- const fullPath = path51.join(cwd, filePath);
60950
+ const fullPath = path52.join(cwd, filePath);
60574
60951
  if (!validatePathForRead(fullPath, cwd)) {
60575
60952
  return [];
60576
60953
  }
@@ -60722,7 +61099,7 @@ function extractTSSymbols(filePath, cwd) {
60722
61099
  });
60723
61100
  }
60724
61101
  function extractPythonSymbols(filePath, cwd) {
60725
- const fullPath = path51.join(cwd, filePath);
61102
+ const fullPath = path52.join(cwd, filePath);
60726
61103
  if (!validatePathForRead(fullPath, cwd)) {
60727
61104
  return [];
60728
61105
  }
@@ -60805,7 +61182,7 @@ var symbols = createSwarmTool({
60805
61182
  }, null, 2);
60806
61183
  }
60807
61184
  const cwd = directory;
60808
- const ext = path51.extname(file3);
61185
+ const ext = path52.extname(file3);
60809
61186
  if (containsControlChars(file3)) {
60810
61187
  return JSON.stringify({
60811
61188
  file: file3,
@@ -60881,14 +61258,14 @@ function containsWindowsAttacks2(str) {
60881
61258
  }
60882
61259
  function isPathInWorkspace2(filePath, workspace) {
60883
61260
  try {
60884
- const resolvedPath = path52.resolve(workspace, filePath);
61261
+ const resolvedPath = path53.resolve(workspace, filePath);
60885
61262
  if (!fs41.existsSync(resolvedPath)) {
60886
61263
  return true;
60887
61264
  }
60888
61265
  const realWorkspace = fs41.realpathSync(workspace);
60889
61266
  const realResolvedPath = fs41.realpathSync(resolvedPath);
60890
- const relativePath = path52.relative(realWorkspace, realResolvedPath);
60891
- if (relativePath.startsWith("..") || path52.isAbsolute(relativePath)) {
61267
+ const relativePath = path53.relative(realWorkspace, realResolvedPath);
61268
+ if (relativePath.startsWith("..") || path53.isAbsolute(relativePath)) {
60892
61269
  return false;
60893
61270
  }
60894
61271
  return true;
@@ -60897,7 +61274,7 @@ function isPathInWorkspace2(filePath, workspace) {
60897
61274
  }
60898
61275
  }
60899
61276
  function processFile(file3, cwd, exportedOnly) {
60900
- const ext = path52.extname(file3);
61277
+ const ext = path53.extname(file3);
60901
61278
  if (containsControlChars(file3)) {
60902
61279
  return {
60903
61280
  file: file3,
@@ -60930,7 +61307,7 @@ function processFile(file3, cwd, exportedOnly) {
60930
61307
  errorType: "path-outside-workspace"
60931
61308
  };
60932
61309
  }
60933
- const fullPath = path52.join(cwd, file3);
61310
+ const fullPath = path53.join(cwd, file3);
60934
61311
  if (!fs41.existsSync(fullPath)) {
60935
61312
  return {
60936
61313
  file: file3,
@@ -61221,7 +61598,7 @@ init_manager();
61221
61598
  init_create_tool();
61222
61599
  init_resolve_working_directory();
61223
61600
  import * as fs42 from "fs";
61224
- import * as path53 from "path";
61601
+ import * as path54 from "path";
61225
61602
  var EVIDENCE_DIR = ".swarm/evidence";
61226
61603
  var TASK_ID_PATTERN2 = /^\d+\.\d+(\.\d+)*$/;
61227
61604
  function isValidTaskId3(taskId) {
@@ -61238,9 +61615,9 @@ function isValidTaskId3(taskId) {
61238
61615
  return TASK_ID_PATTERN2.test(taskId);
61239
61616
  }
61240
61617
  function isPathWithinSwarm(filePath, workspaceRoot) {
61241
- const normalizedWorkspace = path53.resolve(workspaceRoot);
61242
- const swarmPath = path53.join(normalizedWorkspace, ".swarm", "evidence");
61243
- const normalizedPath = path53.resolve(filePath);
61618
+ const normalizedWorkspace = path54.resolve(workspaceRoot);
61619
+ const swarmPath = path54.join(normalizedWorkspace, ".swarm", "evidence");
61620
+ const normalizedPath = path54.resolve(filePath);
61244
61621
  return normalizedPath.startsWith(swarmPath);
61245
61622
  }
61246
61623
  function readEvidenceFile(evidencePath) {
@@ -61321,7 +61698,7 @@ var check_gate_status = createSwarmTool({
61321
61698
  };
61322
61699
  return JSON.stringify(errorResult, null, 2);
61323
61700
  }
61324
- const evidencePath = path53.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
61701
+ const evidencePath = path54.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
61325
61702
  if (!isPathWithinSwarm(evidencePath, directory)) {
61326
61703
  const errorResult = {
61327
61704
  taskId: taskIdInput,
@@ -61418,7 +61795,7 @@ init_state();
61418
61795
  init_create_tool();
61419
61796
  init_resolve_working_directory();
61420
61797
  import * as fs43 from "fs";
61421
- import * as path54 from "path";
61798
+ import * as path55 from "path";
61422
61799
  function extractMatches(regex, text) {
61423
61800
  return Array.from(text.matchAll(regex));
61424
61801
  }
@@ -61570,10 +61947,10 @@ async function executeCompletionVerify(args2, directory) {
61570
61947
  let hasFileReadFailure = false;
61571
61948
  for (const filePath of fileTargets) {
61572
61949
  const normalizedPath = filePath.replace(/\\/g, "/");
61573
- const resolvedPath = path54.resolve(directory, normalizedPath);
61574
- const projectRoot = path54.resolve(directory);
61575
- const relative9 = path54.relative(projectRoot, resolvedPath);
61576
- const withinProject = relative9 === "" || !relative9.startsWith("..") && !path54.isAbsolute(relative9);
61950
+ const resolvedPath = path55.resolve(directory, normalizedPath);
61951
+ const projectRoot = path55.resolve(directory);
61952
+ const relative9 = path55.relative(projectRoot, resolvedPath);
61953
+ const withinProject = relative9 === "" || !relative9.startsWith("..") && !path55.isAbsolute(relative9);
61577
61954
  if (!withinProject) {
61578
61955
  blockedTasks.push({
61579
61956
  task_id: task.id,
@@ -61628,8 +62005,8 @@ async function executeCompletionVerify(args2, directory) {
61628
62005
  blockedTasks
61629
62006
  };
61630
62007
  try {
61631
- const evidenceDir = path54.join(directory, ".swarm", "evidence", `${phase}`);
61632
- const evidencePath = path54.join(evidenceDir, "completion-verify.json");
62008
+ const evidenceDir = path55.join(directory, ".swarm", "evidence", `${phase}`);
62009
+ const evidencePath = path55.join(evidenceDir, "completion-verify.json");
61633
62010
  fs43.mkdirSync(evidenceDir, { recursive: true });
61634
62011
  const evidenceBundle = {
61635
62012
  schema_version: "1.0.0",
@@ -61706,11 +62083,11 @@ var completion_verify = createSwarmTool({
61706
62083
  // src/tools/complexity-hotspots.ts
61707
62084
  init_dist();
61708
62085
  import * as fs45 from "fs";
61709
- import * as path56 from "path";
62086
+ import * as path57 from "path";
61710
62087
 
61711
62088
  // src/quality/metrics.ts
61712
62089
  import * as fs44 from "fs";
61713
- import * as path55 from "path";
62090
+ import * as path56 from "path";
61714
62091
  var MAX_FILE_SIZE_BYTES3 = 256 * 1024;
61715
62092
  var MIN_DUPLICATION_LINES = 10;
61716
62093
  function estimateCyclomaticComplexity(content) {
@@ -61762,7 +62139,7 @@ async function computeComplexityDelta(files, workingDir) {
61762
62139
  let totalComplexity = 0;
61763
62140
  const analyzedFiles = [];
61764
62141
  for (const file3 of files) {
61765
- const fullPath = path55.isAbsolute(file3) ? file3 : path55.join(workingDir, file3);
62142
+ const fullPath = path56.isAbsolute(file3) ? file3 : path56.join(workingDir, file3);
61766
62143
  if (!fs44.existsSync(fullPath)) {
61767
62144
  continue;
61768
62145
  }
@@ -61885,7 +62262,7 @@ function countGoExports(content) {
61885
62262
  function getExportCountForFile(filePath) {
61886
62263
  try {
61887
62264
  const content = fs44.readFileSync(filePath, "utf-8");
61888
- const ext = path55.extname(filePath).toLowerCase();
62265
+ const ext = path56.extname(filePath).toLowerCase();
61889
62266
  switch (ext) {
61890
62267
  case ".ts":
61891
62268
  case ".tsx":
@@ -61911,7 +62288,7 @@ async function computePublicApiDelta(files, workingDir) {
61911
62288
  let totalExports = 0;
61912
62289
  const analyzedFiles = [];
61913
62290
  for (const file3 of files) {
61914
- const fullPath = path55.isAbsolute(file3) ? file3 : path55.join(workingDir, file3);
62291
+ const fullPath = path56.isAbsolute(file3) ? file3 : path56.join(workingDir, file3);
61915
62292
  if (!fs44.existsSync(fullPath)) {
61916
62293
  continue;
61917
62294
  }
@@ -61945,7 +62322,7 @@ async function computeDuplicationRatio(files, workingDir) {
61945
62322
  let duplicateLines = 0;
61946
62323
  const analyzedFiles = [];
61947
62324
  for (const file3 of files) {
61948
- const fullPath = path55.isAbsolute(file3) ? file3 : path55.join(workingDir, file3);
62325
+ const fullPath = path56.isAbsolute(file3) ? file3 : path56.join(workingDir, file3);
61949
62326
  if (!fs44.existsSync(fullPath)) {
61950
62327
  continue;
61951
62328
  }
@@ -61978,8 +62355,8 @@ function countCodeLines(content) {
61978
62355
  return lines.length;
61979
62356
  }
61980
62357
  function isTestFile(filePath) {
61981
- const basename8 = path55.basename(filePath);
61982
- const _ext = path55.extname(filePath).toLowerCase();
62358
+ const basename8 = path56.basename(filePath);
62359
+ const _ext = path56.extname(filePath).toLowerCase();
61983
62360
  const testPatterns = [
61984
62361
  ".test.",
61985
62362
  ".spec.",
@@ -62060,8 +62437,8 @@ function matchGlobSegment(globSegments, pathSegments) {
62060
62437
  }
62061
62438
  return gIndex === globSegments.length && pIndex === pathSegments.length;
62062
62439
  }
62063
- function matchesGlobSegment(path56, glob) {
62064
- const normalizedPath = path56.replace(/\\/g, "/");
62440
+ function matchesGlobSegment(path57, glob) {
62441
+ const normalizedPath = path57.replace(/\\/g, "/");
62065
62442
  const normalizedGlob = glob.replace(/\\/g, "/");
62066
62443
  if (normalizedPath.includes("//")) {
62067
62444
  return false;
@@ -62092,8 +62469,8 @@ function simpleGlobToRegex2(glob) {
62092
62469
  function hasGlobstar(glob) {
62093
62470
  return glob.includes("**");
62094
62471
  }
62095
- function globMatches(path56, glob) {
62096
- const normalizedPath = path56.replace(/\\/g, "/");
62472
+ function globMatches(path57, glob) {
62473
+ const normalizedPath = path57.replace(/\\/g, "/");
62097
62474
  if (!glob || glob === "") {
62098
62475
  if (normalizedPath.includes("//")) {
62099
62476
  return false;
@@ -62129,7 +62506,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
62129
62506
  async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
62130
62507
  let testLines = 0;
62131
62508
  let codeLines = 0;
62132
- const srcDir = path55.join(workingDir, "src");
62509
+ const srcDir = path56.join(workingDir, "src");
62133
62510
  if (fs44.existsSync(srcDir)) {
62134
62511
  await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
62135
62512
  codeLines += lines;
@@ -62137,14 +62514,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
62137
62514
  }
62138
62515
  const possibleSrcDirs = ["lib", "app", "source", "core"];
62139
62516
  for (const dir of possibleSrcDirs) {
62140
- const dirPath = path55.join(workingDir, dir);
62517
+ const dirPath = path56.join(workingDir, dir);
62141
62518
  if (fs44.existsSync(dirPath)) {
62142
62519
  await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
62143
62520
  codeLines += lines;
62144
62521
  });
62145
62522
  }
62146
62523
  }
62147
- const testsDir = path55.join(workingDir, "tests");
62524
+ const testsDir = path56.join(workingDir, "tests");
62148
62525
  if (fs44.existsSync(testsDir)) {
62149
62526
  await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
62150
62527
  testLines += lines;
@@ -62152,7 +62529,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
62152
62529
  }
62153
62530
  const possibleTestDirs = ["test", "__tests__", "specs"];
62154
62531
  for (const dir of possibleTestDirs) {
62155
- const dirPath = path55.join(workingDir, dir);
62532
+ const dirPath = path56.join(workingDir, dir);
62156
62533
  if (fs44.existsSync(dirPath) && dirPath !== testsDir) {
62157
62534
  await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
62158
62535
  testLines += lines;
@@ -62167,7 +62544,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
62167
62544
  try {
62168
62545
  const entries = fs44.readdirSync(dirPath, { withFileTypes: true });
62169
62546
  for (const entry of entries) {
62170
- const fullPath = path55.join(dirPath, entry.name);
62547
+ const fullPath = path56.join(dirPath, entry.name);
62171
62548
  if (entry.isDirectory()) {
62172
62549
  if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
62173
62550
  continue;
@@ -62175,7 +62552,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
62175
62552
  await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
62176
62553
  } else if (entry.isFile()) {
62177
62554
  const relativePath = fullPath.replace(`${dirPath}/`, "");
62178
- const ext = path55.extname(entry.name).toLowerCase();
62555
+ const ext = path56.extname(entry.name).toLowerCase();
62179
62556
  const validExts = [
62180
62557
  ".ts",
62181
62558
  ".tsx",
@@ -62427,7 +62804,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
62427
62804
  const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
62428
62805
  const filteredChurn = new Map;
62429
62806
  for (const [file3, count] of churnMap) {
62430
- const ext = path56.extname(file3).toLowerCase();
62807
+ const ext = path57.extname(file3).toLowerCase();
62431
62808
  if (extSet.has(ext)) {
62432
62809
  filteredChurn.set(file3, count);
62433
62810
  }
@@ -62438,7 +62815,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
62438
62815
  for (const [file3, churnCount] of filteredChurn) {
62439
62816
  let fullPath = file3;
62440
62817
  if (!fs45.existsSync(fullPath)) {
62441
- fullPath = path56.join(cwd, file3);
62818
+ fullPath = path57.join(cwd, file3);
62442
62819
  }
62443
62820
  const complexity = getComplexityForFile2(fullPath);
62444
62821
  if (complexity !== null) {
@@ -62705,7 +63082,7 @@ init_tool();
62705
63082
  init_state();
62706
63083
  init_create_tool();
62707
63084
  import * as fs46 from "fs";
62708
- import * as path57 from "path";
63085
+ import * as path58 from "path";
62709
63086
  function validateTaskIdFormat(taskId) {
62710
63087
  const taskIdPattern = /^\d+\.\d+(\.\d+)*$/;
62711
63088
  if (!taskIdPattern.test(taskId)) {
@@ -62783,8 +63160,8 @@ async function executeDeclareScope(args2, fallbackDir) {
62783
63160
  };
62784
63161
  }
62785
63162
  }
62786
- normalizedDir = path57.normalize(args2.working_directory);
62787
- const pathParts = normalizedDir.split(path57.sep);
63163
+ normalizedDir = path58.normalize(args2.working_directory);
63164
+ const pathParts = normalizedDir.split(path58.sep);
62788
63165
  if (pathParts.includes("..")) {
62789
63166
  return {
62790
63167
  success: false,
@@ -62794,10 +63171,10 @@ async function executeDeclareScope(args2, fallbackDir) {
62794
63171
  ]
62795
63172
  };
62796
63173
  }
62797
- const resolvedDir = path57.resolve(normalizedDir);
63174
+ const resolvedDir = path58.resolve(normalizedDir);
62798
63175
  try {
62799
63176
  const realPath = fs46.realpathSync(resolvedDir);
62800
- const planPath2 = path57.join(realPath, ".swarm", "plan.json");
63177
+ const planPath2 = path58.join(realPath, ".swarm", "plan.json");
62801
63178
  if (!fs46.existsSync(planPath2)) {
62802
63179
  return {
62803
63180
  success: false,
@@ -62821,7 +63198,7 @@ async function executeDeclareScope(args2, fallbackDir) {
62821
63198
  console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
62822
63199
  }
62823
63200
  const directory = normalizedDir || fallbackDir;
62824
- const planPath = path57.resolve(directory, ".swarm", "plan.json");
63201
+ const planPath = path58.resolve(directory, ".swarm", "plan.json");
62825
63202
  if (!fs46.existsSync(planPath)) {
62826
63203
  return {
62827
63204
  success: false,
@@ -62863,8 +63240,8 @@ async function executeDeclareScope(args2, fallbackDir) {
62863
63240
  const normalizeErrors = [];
62864
63241
  const dir = normalizedDir || fallbackDir || process.cwd();
62865
63242
  const mergedFiles = rawMergedFiles.map((file3) => {
62866
- if (path57.isAbsolute(file3)) {
62867
- const relativePath = path57.relative(dir, file3).replace(/\\/g, "/");
63243
+ if (path58.isAbsolute(file3)) {
63244
+ const relativePath = path58.relative(dir, file3).replace(/\\/g, "/");
62868
63245
  if (relativePath.startsWith("..")) {
62869
63246
  normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
62870
63247
  return file3;
@@ -63203,20 +63580,20 @@ function validateBase(base) {
63203
63580
  function validatePaths(paths) {
63204
63581
  if (!paths)
63205
63582
  return null;
63206
- for (const path59 of paths) {
63207
- if (!path59 || path59.length === 0) {
63583
+ for (const path60 of paths) {
63584
+ if (!path60 || path60.length === 0) {
63208
63585
  return "empty path not allowed";
63209
63586
  }
63210
- if (path59.length > MAX_PATH_LENGTH) {
63587
+ if (path60.length > MAX_PATH_LENGTH) {
63211
63588
  return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
63212
63589
  }
63213
- if (SHELL_METACHARACTERS2.test(path59)) {
63590
+ if (SHELL_METACHARACTERS2.test(path60)) {
63214
63591
  return "path contains shell metacharacters";
63215
63592
  }
63216
- if (path59.startsWith("-")) {
63593
+ if (path60.startsWith("-")) {
63217
63594
  return 'path cannot start with "-" (option-like arguments not allowed)';
63218
63595
  }
63219
- if (CONTROL_CHAR_PATTERN2.test(path59)) {
63596
+ if (CONTROL_CHAR_PATTERN2.test(path60)) {
63220
63597
  return "path contains control characters";
63221
63598
  }
63222
63599
  }
@@ -63297,8 +63674,8 @@ var diff = createSwarmTool({
63297
63674
  if (parts2.length >= 3) {
63298
63675
  const additions = parseInt(parts2[0], 10) || 0;
63299
63676
  const deletions = parseInt(parts2[1], 10) || 0;
63300
- const path59 = parts2[2];
63301
- files.push({ path: path59, additions, deletions });
63677
+ const path60 = parts2[2];
63678
+ files.push({ path: path60, additions, deletions });
63302
63679
  }
63303
63680
  }
63304
63681
  const contractChanges = [];
@@ -63581,7 +63958,7 @@ Use these as DOMAIN values when delegating to @sme.`;
63581
63958
  init_dist();
63582
63959
  init_create_tool();
63583
63960
  import * as fs47 from "fs";
63584
- import * as path59 from "path";
63961
+ import * as path60 from "path";
63585
63962
  var MAX_FILE_SIZE_BYTES5 = 1024 * 1024;
63586
63963
  var MAX_EVIDENCE_FILES = 1000;
63587
63964
  var EVIDENCE_DIR2 = ".swarm/evidence";
@@ -63608,9 +63985,9 @@ function validateRequiredTypes(input) {
63608
63985
  return null;
63609
63986
  }
63610
63987
  function isPathWithinSwarm2(filePath, cwd) {
63611
- const normalizedCwd = path59.resolve(cwd);
63612
- const swarmPath = path59.join(normalizedCwd, ".swarm");
63613
- const normalizedPath = path59.resolve(filePath);
63988
+ const normalizedCwd = path60.resolve(cwd);
63989
+ const swarmPath = path60.join(normalizedCwd, ".swarm");
63990
+ const normalizedPath = path60.resolve(filePath);
63614
63991
  return normalizedPath.startsWith(swarmPath);
63615
63992
  }
63616
63993
  function parseCompletedTasks(planContent) {
@@ -63640,10 +64017,10 @@ function readEvidenceFiles(evidenceDir, _cwd) {
63640
64017
  if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
63641
64018
  continue;
63642
64019
  }
63643
- const filePath = path59.join(evidenceDir, filename);
64020
+ const filePath = path60.join(evidenceDir, filename);
63644
64021
  try {
63645
- const resolvedPath = path59.resolve(filePath);
63646
- const evidenceDirResolved = path59.resolve(evidenceDir);
64022
+ const resolvedPath = path60.resolve(filePath);
64023
+ const evidenceDirResolved = path60.resolve(evidenceDir);
63647
64024
  if (!resolvedPath.startsWith(evidenceDirResolved)) {
63648
64025
  continue;
63649
64026
  }
@@ -63761,7 +64138,7 @@ var evidence_check = createSwarmTool({
63761
64138
  return JSON.stringify(errorResult, null, 2);
63762
64139
  }
63763
64140
  const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
63764
- const planPath = path59.join(cwd, PLAN_FILE);
64141
+ const planPath = path60.join(cwd, PLAN_FILE);
63765
64142
  if (!isPathWithinSwarm2(planPath, cwd)) {
63766
64143
  const errorResult = {
63767
64144
  error: "plan file path validation failed",
@@ -63793,7 +64170,7 @@ var evidence_check = createSwarmTool({
63793
64170
  };
63794
64171
  return JSON.stringify(result2, null, 2);
63795
64172
  }
63796
- const evidenceDir = path59.join(cwd, EVIDENCE_DIR2);
64173
+ const evidenceDir = path60.join(cwd, EVIDENCE_DIR2);
63797
64174
  const evidence = readEvidenceFiles(evidenceDir, cwd);
63798
64175
  const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
63799
64176
  const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
@@ -63811,7 +64188,7 @@ var evidence_check = createSwarmTool({
63811
64188
  init_tool();
63812
64189
  init_create_tool();
63813
64190
  import * as fs48 from "fs";
63814
- import * as path60 from "path";
64191
+ import * as path61 from "path";
63815
64192
  var EXT_MAP = {
63816
64193
  python: ".py",
63817
64194
  py: ".py",
@@ -63892,12 +64269,12 @@ var extract_code_blocks = createSwarmTool({
63892
64269
  if (prefix) {
63893
64270
  filename = `${prefix}_${filename}`;
63894
64271
  }
63895
- let filepath = path60.join(targetDir, filename);
63896
- const base = path60.basename(filepath, path60.extname(filepath));
63897
- const ext = path60.extname(filepath);
64272
+ let filepath = path61.join(targetDir, filename);
64273
+ const base = path61.basename(filepath, path61.extname(filepath));
64274
+ const ext = path61.extname(filepath);
63898
64275
  let counter = 1;
63899
64276
  while (fs48.existsSync(filepath)) {
63900
- filepath = path60.join(targetDir, `${base}_${counter}${ext}`);
64277
+ filepath = path61.join(targetDir, `${base}_${counter}${ext}`);
63901
64278
  counter++;
63902
64279
  }
63903
64280
  try {
@@ -64018,7 +64395,7 @@ var gitingest = createSwarmTool({
64018
64395
  init_dist();
64019
64396
  init_create_tool();
64020
64397
  import * as fs49 from "fs";
64021
- import * as path61 from "path";
64398
+ import * as path62 from "path";
64022
64399
  var MAX_FILE_PATH_LENGTH2 = 500;
64023
64400
  var MAX_SYMBOL_LENGTH = 256;
64024
64401
  var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
@@ -64066,7 +64443,7 @@ function validateSymbolInput(symbol3) {
64066
64443
  return null;
64067
64444
  }
64068
64445
  function isBinaryFile2(filePath, buffer) {
64069
- const ext = path61.extname(filePath).toLowerCase();
64446
+ const ext = path62.extname(filePath).toLowerCase();
64070
64447
  if (ext === ".json" || ext === ".md" || ext === ".txt") {
64071
64448
  return false;
64072
64449
  }
@@ -64090,15 +64467,15 @@ function parseImports(content, targetFile, targetSymbol) {
64090
64467
  const imports = [];
64091
64468
  let _resolvedTarget;
64092
64469
  try {
64093
- _resolvedTarget = path61.resolve(targetFile);
64470
+ _resolvedTarget = path62.resolve(targetFile);
64094
64471
  } catch {
64095
64472
  _resolvedTarget = targetFile;
64096
64473
  }
64097
- const targetBasename = path61.basename(targetFile, path61.extname(targetFile));
64474
+ const targetBasename = path62.basename(targetFile, path62.extname(targetFile));
64098
64475
  const targetWithExt = targetFile;
64099
64476
  const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
64100
- const normalizedTargetWithExt = path61.normalize(targetWithExt).replace(/\\/g, "/");
64101
- const normalizedTargetWithoutExt = path61.normalize(targetWithoutExt).replace(/\\/g, "/");
64477
+ const normalizedTargetWithExt = path62.normalize(targetWithExt).replace(/\\/g, "/");
64478
+ const normalizedTargetWithoutExt = path62.normalize(targetWithoutExt).replace(/\\/g, "/");
64102
64479
  const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
64103
64480
  for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
64104
64481
  const modulePath = match[1] || match[2] || match[3];
@@ -64121,9 +64498,9 @@ function parseImports(content, targetFile, targetSymbol) {
64121
64498
  }
64122
64499
  const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
64123
64500
  let isMatch = false;
64124
- const _targetDir = path61.dirname(targetFile);
64125
- const targetExt = path61.extname(targetFile);
64126
- const targetBasenameNoExt = path61.basename(targetFile, targetExt);
64501
+ const _targetDir = path62.dirname(targetFile);
64502
+ const targetExt = path62.extname(targetFile);
64503
+ const targetBasenameNoExt = path62.basename(targetFile, targetExt);
64127
64504
  const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
64128
64505
  const moduleName = modulePath.split(/[/\\]/).pop() || "";
64129
64506
  const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
@@ -64191,10 +64568,10 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
64191
64568
  entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
64192
64569
  for (const entry of entries) {
64193
64570
  if (SKIP_DIRECTORIES3.has(entry)) {
64194
- stats.skippedDirs.push(path61.join(dir, entry));
64571
+ stats.skippedDirs.push(path62.join(dir, entry));
64195
64572
  continue;
64196
64573
  }
64197
- const fullPath = path61.join(dir, entry);
64574
+ const fullPath = path62.join(dir, entry);
64198
64575
  let stat2;
64199
64576
  try {
64200
64577
  stat2 = fs49.statSync(fullPath);
@@ -64208,7 +64585,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
64208
64585
  if (stat2.isDirectory()) {
64209
64586
  findSourceFiles(fullPath, files, stats);
64210
64587
  } else if (stat2.isFile()) {
64211
- const ext = path61.extname(fullPath).toLowerCase();
64588
+ const ext = path62.extname(fullPath).toLowerCase();
64212
64589
  if (SUPPORTED_EXTENSIONS.includes(ext)) {
64213
64590
  files.push(fullPath);
64214
64591
  }
@@ -64265,7 +64642,7 @@ var imports = createSwarmTool({
64265
64642
  return JSON.stringify(errorResult, null, 2);
64266
64643
  }
64267
64644
  try {
64268
- const targetFile = path61.resolve(file3);
64645
+ const targetFile = path62.resolve(file3);
64269
64646
  if (!fs49.existsSync(targetFile)) {
64270
64647
  const errorResult = {
64271
64648
  error: `target file not found: ${file3}`,
@@ -64287,7 +64664,7 @@ var imports = createSwarmTool({
64287
64664
  };
64288
64665
  return JSON.stringify(errorResult, null, 2);
64289
64666
  }
64290
- const baseDir = path61.dirname(targetFile);
64667
+ const baseDir = path62.dirname(targetFile);
64291
64668
  const scanStats = {
64292
64669
  skippedDirs: [],
64293
64670
  skippedFiles: 0,
@@ -64388,7 +64765,7 @@ var VALID_CATEGORIES2 = [
64388
64765
  "integration",
64389
64766
  "other"
64390
64767
  ];
64391
- var knowledgeAdd = createSwarmTool({
64768
+ var knowledge_add = createSwarmTool({
64392
64769
  description: "Store a new lesson in the knowledge base for future reference. The lesson will be available for retrieval via knowledge_recall.",
64393
64770
  args: {
64394
64771
  lesson: tool.schema.string().min(15).max(280).describe("The lesson to store (15-280 characters)"),
@@ -64748,7 +65125,7 @@ var knowledge_query = createSwarmTool({
64748
65125
  init_dist();
64749
65126
  init_knowledge_store();
64750
65127
  init_create_tool();
64751
- var knowledgeRecall = createSwarmTool({
65128
+ var knowledge_recall = createSwarmTool({
64752
65129
  description: "Search the knowledge base for relevant past decisions, patterns, and lessons learned. Returns ranked results by semantic similarity.",
64753
65130
  args: {
64754
65131
  query: tool.schema.string().min(3).describe("Natural language search query"),
@@ -64832,7 +65209,7 @@ var knowledgeRecall = createSwarmTool({
64832
65209
  init_dist();
64833
65210
  init_knowledge_store();
64834
65211
  init_create_tool();
64835
- var knowledgeRemove = createSwarmTool({
65212
+ var knowledge_remove = createSwarmTool({
64836
65213
  description: "Delete an outdated knowledge entry by ID. Double-deletion is idempotent \u2014 removing a non-existent entry returns a clear message without error.",
64837
65214
  args: {
64838
65215
  id: tool.schema.string().min(1).describe("UUID of the knowledge entry to remove")
@@ -64897,7 +65274,7 @@ init_config();
64897
65274
  init_schema();
64898
65275
  init_manager();
64899
65276
  import * as fs50 from "fs";
64900
- import * as path62 from "path";
65277
+ import * as path63 from "path";
64901
65278
  init_review_receipt();
64902
65279
  init_utils2();
64903
65280
  init_ledger();
@@ -65122,7 +65499,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
65122
65499
  safeWarn(`[phase_complete] Completion verify error (non-blocking):`, completionError);
65123
65500
  }
65124
65501
  try {
65125
- const driftEvidencePath = path62.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
65502
+ const driftEvidencePath = path63.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
65126
65503
  let driftVerdictFound = false;
65127
65504
  let driftVerdictApproved = false;
65128
65505
  try {
@@ -65156,7 +65533,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
65156
65533
  driftVerdictFound = false;
65157
65534
  }
65158
65535
  if (!driftVerdictFound) {
65159
- const specPath = path62.join(dir, ".swarm", "spec.md");
65536
+ const specPath = path63.join(dir, ".swarm", "spec.md");
65160
65537
  const specExists = fs50.existsSync(specPath);
65161
65538
  if (!specExists) {
65162
65539
  let incompleteTaskCount = 0;
@@ -65208,7 +65585,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
65208
65585
  const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
65209
65586
  if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
65210
65587
  try {
65211
- const projectName = path62.basename(dir);
65588
+ const projectName = path63.basename(dir);
65212
65589
  const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
65213
65590
  if (curationResult) {
65214
65591
  const sessionState = swarmState.agentSessions.get(sessionID);
@@ -65555,7 +65932,7 @@ init_discovery();
65555
65932
  init_utils();
65556
65933
  init_create_tool();
65557
65934
  import * as fs51 from "fs";
65558
- import * as path63 from "path";
65935
+ import * as path64 from "path";
65559
65936
  var MAX_OUTPUT_BYTES5 = 52428800;
65560
65937
  var AUDIT_TIMEOUT_MS = 120000;
65561
65938
  function isValidEcosystem(value) {
@@ -65583,16 +65960,16 @@ function validateArgs3(args2) {
65583
65960
  function detectEcosystems(directory) {
65584
65961
  const ecosystems = [];
65585
65962
  const cwd = directory;
65586
- if (fs51.existsSync(path63.join(cwd, "package.json"))) {
65963
+ if (fs51.existsSync(path64.join(cwd, "package.json"))) {
65587
65964
  ecosystems.push("npm");
65588
65965
  }
65589
- if (fs51.existsSync(path63.join(cwd, "pyproject.toml")) || fs51.existsSync(path63.join(cwd, "requirements.txt"))) {
65966
+ if (fs51.existsSync(path64.join(cwd, "pyproject.toml")) || fs51.existsSync(path64.join(cwd, "requirements.txt"))) {
65590
65967
  ecosystems.push("pip");
65591
65968
  }
65592
- if (fs51.existsSync(path63.join(cwd, "Cargo.toml"))) {
65969
+ if (fs51.existsSync(path64.join(cwd, "Cargo.toml"))) {
65593
65970
  ecosystems.push("cargo");
65594
65971
  }
65595
- if (fs51.existsSync(path63.join(cwd, "go.mod"))) {
65972
+ if (fs51.existsSync(path64.join(cwd, "go.mod"))) {
65596
65973
  ecosystems.push("go");
65597
65974
  }
65598
65975
  try {
@@ -65601,13 +65978,13 @@ function detectEcosystems(directory) {
65601
65978
  ecosystems.push("dotnet");
65602
65979
  }
65603
65980
  } catch {}
65604
- if (fs51.existsSync(path63.join(cwd, "Gemfile")) || fs51.existsSync(path63.join(cwd, "Gemfile.lock"))) {
65981
+ if (fs51.existsSync(path64.join(cwd, "Gemfile")) || fs51.existsSync(path64.join(cwd, "Gemfile.lock"))) {
65605
65982
  ecosystems.push("ruby");
65606
65983
  }
65607
- if (fs51.existsSync(path63.join(cwd, "pubspec.yaml"))) {
65984
+ if (fs51.existsSync(path64.join(cwd, "pubspec.yaml"))) {
65608
65985
  ecosystems.push("dart");
65609
65986
  }
65610
- if (fs51.existsSync(path63.join(cwd, "composer.lock"))) {
65987
+ if (fs51.existsSync(path64.join(cwd, "composer.lock"))) {
65611
65988
  ecosystems.push("composer");
65612
65989
  }
65613
65990
  return ecosystems;
@@ -66767,7 +67144,7 @@ var pkg_audit = createSwarmTool({
66767
67144
  init_dist();
66768
67145
  init_manager();
66769
67146
  import * as fs52 from "fs";
66770
- import * as path64 from "path";
67147
+ import * as path65 from "path";
66771
67148
  init_utils();
66772
67149
  init_create_tool();
66773
67150
  var MAX_FILE_SIZE = 1024 * 1024;
@@ -66886,7 +67263,7 @@ function isScaffoldFile(filePath) {
66886
67263
  if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
66887
67264
  return true;
66888
67265
  }
66889
- const filename = path64.basename(filePath);
67266
+ const filename = path65.basename(filePath);
66890
67267
  if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
66891
67268
  return true;
66892
67269
  }
@@ -66903,7 +67280,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
66903
67280
  if (regex.test(normalizedPath)) {
66904
67281
  return true;
66905
67282
  }
66906
- const filename = path64.basename(filePath);
67283
+ const filename = path65.basename(filePath);
66907
67284
  const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
66908
67285
  if (filenameRegex.test(filename)) {
66909
67286
  return true;
@@ -66912,7 +67289,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
66912
67289
  return false;
66913
67290
  }
66914
67291
  function isParserSupported(filePath) {
66915
- const ext = path64.extname(filePath).toLowerCase();
67292
+ const ext = path65.extname(filePath).toLowerCase();
66916
67293
  return SUPPORTED_PARSER_EXTENSIONS.has(ext);
66917
67294
  }
66918
67295
  function isPlanFile(filePath) {
@@ -67096,9 +67473,9 @@ async function placeholderScan(input, directory) {
67096
67473
  let filesScanned = 0;
67097
67474
  const filesWithFindings = new Set;
67098
67475
  for (const filePath of changed_files) {
67099
- const fullPath = path64.isAbsolute(filePath) ? filePath : path64.resolve(directory, filePath);
67100
- const resolvedDirectory = path64.resolve(directory);
67101
- if (!fullPath.startsWith(resolvedDirectory + path64.sep) && fullPath !== resolvedDirectory) {
67476
+ const fullPath = path65.isAbsolute(filePath) ? filePath : path65.resolve(directory, filePath);
67477
+ const resolvedDirectory = path65.resolve(directory);
67478
+ if (!fullPath.startsWith(resolvedDirectory + path65.sep) && fullPath !== resolvedDirectory) {
67102
67479
  continue;
67103
67480
  }
67104
67481
  if (!fs52.existsSync(fullPath)) {
@@ -67176,7 +67553,7 @@ var placeholder_scan = createSwarmTool({
67176
67553
  // src/tools/pre-check-batch.ts
67177
67554
  init_dist();
67178
67555
  import * as fs54 from "fs";
67179
- import * as path66 from "path";
67556
+ import * as path67 from "path";
67180
67557
 
67181
67558
  // node_modules/yocto-queue/index.js
67182
67559
  class Node2 {
@@ -67470,7 +67847,7 @@ init_dist();
67470
67847
  init_manager();
67471
67848
  init_detector();
67472
67849
  import * as fs53 from "fs";
67473
- import * as path65 from "path";
67850
+ import * as path66 from "path";
67474
67851
  import { extname as extname14 } from "path";
67475
67852
 
67476
67853
  // src/sast/rules/c.ts
@@ -68466,9 +68843,9 @@ async function sastScan(input, directory, config3) {
68466
68843
  _filesSkipped++;
68467
68844
  continue;
68468
68845
  }
68469
- const resolvedPath = path65.isAbsolute(filePath) ? filePath : path65.resolve(directory, filePath);
68470
- const resolvedDirectory = path65.resolve(directory);
68471
- if (!resolvedPath.startsWith(resolvedDirectory + path65.sep) && resolvedPath !== resolvedDirectory) {
68846
+ const resolvedPath = path66.isAbsolute(filePath) ? filePath : path66.resolve(directory, filePath);
68847
+ const resolvedDirectory = path66.resolve(directory);
68848
+ if (!resolvedPath.startsWith(resolvedDirectory + path66.sep) && resolvedPath !== resolvedDirectory) {
68472
68849
  _filesSkipped++;
68473
68850
  continue;
68474
68851
  }
@@ -68670,18 +69047,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
68670
69047
  let resolved;
68671
69048
  const isWinAbs = isWindowsAbsolutePath(inputPath);
68672
69049
  if (isWinAbs) {
68673
- resolved = path66.win32.resolve(inputPath);
68674
- } else if (path66.isAbsolute(inputPath)) {
68675
- resolved = path66.resolve(inputPath);
69050
+ resolved = path67.win32.resolve(inputPath);
69051
+ } else if (path67.isAbsolute(inputPath)) {
69052
+ resolved = path67.resolve(inputPath);
68676
69053
  } else {
68677
- resolved = path66.resolve(baseDir, inputPath);
69054
+ resolved = path67.resolve(baseDir, inputPath);
68678
69055
  }
68679
- const workspaceResolved = path66.resolve(workspaceDir);
69056
+ const workspaceResolved = path67.resolve(workspaceDir);
68680
69057
  let relative11;
68681
69058
  if (isWinAbs) {
68682
- relative11 = path66.win32.relative(workspaceResolved, resolved);
69059
+ relative11 = path67.win32.relative(workspaceResolved, resolved);
68683
69060
  } else {
68684
- relative11 = path66.relative(workspaceResolved, resolved);
69061
+ relative11 = path67.relative(workspaceResolved, resolved);
68685
69062
  }
68686
69063
  if (relative11.startsWith("..")) {
68687
69064
  return "path traversal detected";
@@ -68746,7 +69123,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
68746
69123
  if (typeof file3 !== "string") {
68747
69124
  continue;
68748
69125
  }
68749
- const resolvedPath = path66.resolve(file3);
69126
+ const resolvedPath = path67.resolve(file3);
68750
69127
  const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
68751
69128
  if (validationError) {
68752
69129
  continue;
@@ -68903,7 +69280,7 @@ async function runSecretscanWithFiles(files, directory) {
68903
69280
  skippedFiles++;
68904
69281
  continue;
68905
69282
  }
68906
- const resolvedPath = path66.resolve(file3);
69283
+ const resolvedPath = path67.resolve(file3);
68907
69284
  const validationError = validatePath(resolvedPath, directory, directory);
68908
69285
  if (validationError) {
68909
69286
  skippedFiles++;
@@ -68921,7 +69298,7 @@ async function runSecretscanWithFiles(files, directory) {
68921
69298
  };
68922
69299
  }
68923
69300
  for (const file3 of validatedFiles) {
68924
- const ext = path66.extname(file3).toLowerCase();
69301
+ const ext = path67.extname(file3).toLowerCase();
68925
69302
  if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
68926
69303
  skippedFiles++;
68927
69304
  continue;
@@ -69127,7 +69504,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
69127
69504
  const preexistingFindings = [];
69128
69505
  for (const finding of findings) {
69129
69506
  const filePath = finding.location.file;
69130
- const normalised = path66.relative(directory, filePath).replace(/\\/g, "/");
69507
+ const normalised = path67.relative(directory, filePath).replace(/\\/g, "/");
69131
69508
  const changedLines = changedLineRanges.get(normalised);
69132
69509
  if (changedLines && changedLines.has(finding.location.line)) {
69133
69510
  newFindings.push(finding);
@@ -69178,7 +69555,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
69178
69555
  warn(`pre_check_batch: Invalid file path: ${file3}`);
69179
69556
  continue;
69180
69557
  }
69181
- changedFiles.push(path66.resolve(directory, file3));
69558
+ changedFiles.push(path67.resolve(directory, file3));
69182
69559
  }
69183
69560
  if (changedFiles.length === 0) {
69184
69561
  warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
@@ -69366,7 +69743,7 @@ var pre_check_batch = createSwarmTool({
69366
69743
  };
69367
69744
  return JSON.stringify(errorResult, null, 2);
69368
69745
  }
69369
- const resolvedDirectory = path66.resolve(typedArgs.directory);
69746
+ const resolvedDirectory = path67.resolve(typedArgs.directory);
69370
69747
  const workspaceAnchor = resolvedDirectory;
69371
69748
  const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
69372
69749
  if (dirError) {
@@ -69473,7 +69850,7 @@ ${paginatedContent}`;
69473
69850
  // src/tools/save-plan.ts
69474
69851
  init_tool();
69475
69852
  import * as fs55 from "fs";
69476
- import * as path67 from "path";
69853
+ import * as path68 from "path";
69477
69854
  init_ledger();
69478
69855
  init_manager2();
69479
69856
  init_state();
@@ -69611,7 +69988,7 @@ async function executeSavePlan(args2, fallbackDir) {
69611
69988
  }
69612
69989
  await writeCheckpoint(dir).catch(() => {});
69613
69990
  try {
69614
- const markerPath = path67.join(dir, ".swarm", ".plan-write-marker");
69991
+ const markerPath = path68.join(dir, ".swarm", ".plan-write-marker");
69615
69992
  const marker = JSON.stringify({
69616
69993
  source: "save_plan",
69617
69994
  timestamp: new Date().toISOString(),
@@ -69634,7 +70011,7 @@ async function executeSavePlan(args2, fallbackDir) {
69634
70011
  return {
69635
70012
  success: true,
69636
70013
  message: "Plan saved successfully",
69637
- plan_path: path67.join(dir, ".swarm", "plan.json"),
70014
+ plan_path: path68.join(dir, ".swarm", "plan.json"),
69638
70015
  phases_count: plan.phases.length,
69639
70016
  tasks_count: tasksCount,
69640
70017
  ...warnings.length > 0 ? { warnings } : {}
@@ -69679,7 +70056,7 @@ var save_plan = createSwarmTool({
69679
70056
  init_dist();
69680
70057
  init_manager();
69681
70058
  import * as fs56 from "fs";
69682
- import * as path68 from "path";
70059
+ import * as path69 from "path";
69683
70060
 
69684
70061
  // src/sbom/detectors/index.ts
69685
70062
  init_utils();
@@ -70529,7 +70906,7 @@ function findManifestFiles(rootDir) {
70529
70906
  try {
70530
70907
  const entries = fs56.readdirSync(dir, { withFileTypes: true });
70531
70908
  for (const entry of entries) {
70532
- const fullPath = path68.join(dir, entry.name);
70909
+ const fullPath = path69.join(dir, entry.name);
70533
70910
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
70534
70911
  continue;
70535
70912
  }
@@ -70538,7 +70915,7 @@ function findManifestFiles(rootDir) {
70538
70915
  } else if (entry.isFile()) {
70539
70916
  for (const pattern of patterns) {
70540
70917
  if (simpleGlobToRegex(pattern).test(entry.name)) {
70541
- manifestFiles.push(path68.relative(rootDir, fullPath));
70918
+ manifestFiles.push(path69.relative(rootDir, fullPath));
70542
70919
  break;
70543
70920
  }
70544
70921
  }
@@ -70556,11 +70933,11 @@ function findManifestFilesInDirs(directories, workingDir) {
70556
70933
  try {
70557
70934
  const entries = fs56.readdirSync(dir, { withFileTypes: true });
70558
70935
  for (const entry of entries) {
70559
- const fullPath = path68.join(dir, entry.name);
70936
+ const fullPath = path69.join(dir, entry.name);
70560
70937
  if (entry.isFile()) {
70561
70938
  for (const pattern of patterns) {
70562
70939
  if (simpleGlobToRegex(pattern).test(entry.name)) {
70563
- found.push(path68.relative(workingDir, fullPath));
70940
+ found.push(path69.relative(workingDir, fullPath));
70564
70941
  break;
70565
70942
  }
70566
70943
  }
@@ -70573,11 +70950,11 @@ function findManifestFilesInDirs(directories, workingDir) {
70573
70950
  function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
70574
70951
  const dirs = new Set;
70575
70952
  for (const file3 of changedFiles) {
70576
- let currentDir = path68.dirname(file3);
70953
+ let currentDir = path69.dirname(file3);
70577
70954
  while (true) {
70578
- if (currentDir && currentDir !== "." && currentDir !== path68.sep) {
70579
- dirs.add(path68.join(workingDir, currentDir));
70580
- const parent = path68.dirname(currentDir);
70955
+ if (currentDir && currentDir !== "." && currentDir !== path69.sep) {
70956
+ dirs.add(path69.join(workingDir, currentDir));
70957
+ const parent = path69.dirname(currentDir);
70581
70958
  if (parent === currentDir)
70582
70959
  break;
70583
70960
  currentDir = parent;
@@ -70661,7 +71038,7 @@ var sbom_generate = createSwarmTool({
70661
71038
  const changedFiles = obj.changed_files;
70662
71039
  const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
70663
71040
  const workingDir = directory;
70664
- const outputDir = path68.isAbsolute(relativeOutputDir) ? relativeOutputDir : path68.join(workingDir, relativeOutputDir);
71041
+ const outputDir = path69.isAbsolute(relativeOutputDir) ? relativeOutputDir : path69.join(workingDir, relativeOutputDir);
70665
71042
  let manifestFiles = [];
70666
71043
  if (scope === "all") {
70667
71044
  manifestFiles = findManifestFiles(workingDir);
@@ -70684,7 +71061,7 @@ var sbom_generate = createSwarmTool({
70684
71061
  const processedFiles = [];
70685
71062
  for (const manifestFile of manifestFiles) {
70686
71063
  try {
70687
- const fullPath = path68.isAbsolute(manifestFile) ? manifestFile : path68.join(workingDir, manifestFile);
71064
+ const fullPath = path69.isAbsolute(manifestFile) ? manifestFile : path69.join(workingDir, manifestFile);
70688
71065
  if (!fs56.existsSync(fullPath)) {
70689
71066
  continue;
70690
71067
  }
@@ -70701,7 +71078,7 @@ var sbom_generate = createSwarmTool({
70701
71078
  const bom = generateCycloneDX(allComponents);
70702
71079
  const bomJson = serializeCycloneDX(bom);
70703
71080
  const filename = generateSbomFilename();
70704
- const outputPath = path68.join(outputDir, filename);
71081
+ const outputPath = path69.join(outputDir, filename);
70705
71082
  fs56.writeFileSync(outputPath, bomJson, "utf-8");
70706
71083
  const verdict = processedFiles.length > 0 ? "pass" : "pass";
70707
71084
  try {
@@ -70745,7 +71122,7 @@ var sbom_generate = createSwarmTool({
70745
71122
  init_dist();
70746
71123
  init_create_tool();
70747
71124
  import * as fs57 from "fs";
70748
- import * as path69 from "path";
71125
+ import * as path70 from "path";
70749
71126
  var SPEC_CANDIDATES = [
70750
71127
  "openapi.json",
70751
71128
  "openapi.yaml",
@@ -70777,12 +71154,12 @@ function normalizePath2(p) {
70777
71154
  }
70778
71155
  function discoverSpecFile(cwd, specFileArg) {
70779
71156
  if (specFileArg) {
70780
- const resolvedPath = path69.resolve(cwd, specFileArg);
70781
- const normalizedCwd = cwd.endsWith(path69.sep) ? cwd : cwd + path69.sep;
71157
+ const resolvedPath = path70.resolve(cwd, specFileArg);
71158
+ const normalizedCwd = cwd.endsWith(path70.sep) ? cwd : cwd + path70.sep;
70782
71159
  if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
70783
71160
  throw new Error("Invalid spec_file: path traversal detected");
70784
71161
  }
70785
- const ext = path69.extname(resolvedPath).toLowerCase();
71162
+ const ext = path70.extname(resolvedPath).toLowerCase();
70786
71163
  if (!ALLOWED_EXTENSIONS.includes(ext)) {
70787
71164
  throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
70788
71165
  }
@@ -70796,7 +71173,7 @@ function discoverSpecFile(cwd, specFileArg) {
70796
71173
  return resolvedPath;
70797
71174
  }
70798
71175
  for (const candidate of SPEC_CANDIDATES) {
70799
- const candidatePath = path69.resolve(cwd, candidate);
71176
+ const candidatePath = path70.resolve(cwd, candidate);
70800
71177
  if (fs57.existsSync(candidatePath)) {
70801
71178
  const stats = fs57.statSync(candidatePath);
70802
71179
  if (stats.size <= MAX_SPEC_SIZE) {
@@ -70808,7 +71185,7 @@ function discoverSpecFile(cwd, specFileArg) {
70808
71185
  }
70809
71186
  function parseSpec(specFile) {
70810
71187
  const content = fs57.readFileSync(specFile, "utf-8");
70811
- const ext = path69.extname(specFile).toLowerCase();
71188
+ const ext = path70.extname(specFile).toLowerCase();
70812
71189
  if (ext === ".json") {
70813
71190
  return parseJsonSpec(content);
70814
71191
  }
@@ -70884,7 +71261,7 @@ function extractRoutes(cwd) {
70884
71261
  return;
70885
71262
  }
70886
71263
  for (const entry of entries) {
70887
- const fullPath = path69.join(dir, entry.name);
71264
+ const fullPath = path70.join(dir, entry.name);
70888
71265
  if (entry.isSymbolicLink()) {
70889
71266
  continue;
70890
71267
  }
@@ -70894,7 +71271,7 @@ function extractRoutes(cwd) {
70894
71271
  }
70895
71272
  walkDir(fullPath);
70896
71273
  } else if (entry.isFile()) {
70897
- const ext = path69.extname(entry.name).toLowerCase();
71274
+ const ext = path70.extname(entry.name).toLowerCase();
70898
71275
  const baseName = entry.name.toLowerCase();
70899
71276
  if (![".ts", ".js", ".mjs"].includes(ext)) {
70900
71277
  continue;
@@ -71060,7 +71437,7 @@ var schema_drift = createSwarmTool({
71060
71437
  init_tool();
71061
71438
  init_create_tool();
71062
71439
  import * as fs58 from "fs";
71063
- import * as path70 from "path";
71440
+ import * as path71 from "path";
71064
71441
  var DEFAULT_MAX_RESULTS = 100;
71065
71442
  var DEFAULT_MAX_LINES = 200;
71066
71443
  var REGEX_TIMEOUT_MS = 5000;
@@ -71096,11 +71473,11 @@ function containsWindowsAttacks3(str) {
71096
71473
  }
71097
71474
  function isPathInWorkspace3(filePath, workspace) {
71098
71475
  try {
71099
- const resolvedPath = path70.resolve(workspace, filePath);
71476
+ const resolvedPath = path71.resolve(workspace, filePath);
71100
71477
  const realWorkspace = fs58.realpathSync(workspace);
71101
71478
  const realResolvedPath = fs58.realpathSync(resolvedPath);
71102
- const relativePath = path70.relative(realWorkspace, realResolvedPath);
71103
- if (relativePath.startsWith("..") || path70.isAbsolute(relativePath)) {
71479
+ const relativePath = path71.relative(realWorkspace, realResolvedPath);
71480
+ if (relativePath.startsWith("..") || path71.isAbsolute(relativePath)) {
71104
71481
  return false;
71105
71482
  }
71106
71483
  return true;
@@ -71113,11 +71490,11 @@ function validatePathForRead2(filePath, workspace) {
71113
71490
  }
71114
71491
  function findRgInEnvPath() {
71115
71492
  const searchPath = process.env.PATH ?? "";
71116
- for (const dir of searchPath.split(path70.delimiter)) {
71493
+ for (const dir of searchPath.split(path71.delimiter)) {
71117
71494
  if (!dir)
71118
71495
  continue;
71119
71496
  const isWindows = process.platform === "win32";
71120
- const candidate = path70.join(dir, isWindows ? "rg.exe" : "rg");
71497
+ const candidate = path71.join(dir, isWindows ? "rg.exe" : "rg");
71121
71498
  if (fs58.existsSync(candidate))
71122
71499
  return candidate;
71123
71500
  }
@@ -71247,8 +71624,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
71247
71624
  try {
71248
71625
  const entries = fs58.readdirSync(dir, { withFileTypes: true });
71249
71626
  for (const entry of entries) {
71250
- const fullPath = path70.join(dir, entry.name);
71251
- const relativePath = path70.relative(workspace, fullPath);
71627
+ const fullPath = path71.join(dir, entry.name);
71628
+ const relativePath = path71.relative(workspace, fullPath);
71252
71629
  if (!validatePathForRead2(fullPath, workspace)) {
71253
71630
  continue;
71254
71631
  }
@@ -71289,7 +71666,7 @@ async function fallbackSearch(opts) {
71289
71666
  const matches = [];
71290
71667
  let total = 0;
71291
71668
  for (const file3 of files) {
71292
- const fullPath = path70.join(opts.workspace, file3);
71669
+ const fullPath = path71.join(opts.workspace, file3);
71293
71670
  if (!validatePathForRead2(fullPath, opts.workspace)) {
71294
71671
  continue;
71295
71672
  }
@@ -71460,7 +71837,7 @@ init_secretscan();
71460
71837
  init_tool();
71461
71838
  init_create_tool();
71462
71839
  import * as fs59 from "fs";
71463
- import * as path71 from "path";
71840
+ import * as path72 from "path";
71464
71841
  var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
71465
71842
  function containsWindowsAttacks4(str) {
71466
71843
  if (/:[^\\/]/.test(str))
@@ -71474,14 +71851,14 @@ function containsWindowsAttacks4(str) {
71474
71851
  }
71475
71852
  function isPathInWorkspace4(filePath, workspace) {
71476
71853
  try {
71477
- const resolvedPath = path71.resolve(workspace, filePath);
71854
+ const resolvedPath = path72.resolve(workspace, filePath);
71478
71855
  if (!fs59.existsSync(resolvedPath)) {
71479
71856
  return true;
71480
71857
  }
71481
71858
  const realWorkspace = fs59.realpathSync(workspace);
71482
71859
  const realResolvedPath = fs59.realpathSync(resolvedPath);
71483
- const relativePath = path71.relative(realWorkspace, realResolvedPath);
71484
- if (relativePath.startsWith("..") || path71.isAbsolute(relativePath)) {
71860
+ const relativePath = path72.relative(realWorkspace, realResolvedPath);
71861
+ if (relativePath.startsWith("..") || path72.isAbsolute(relativePath)) {
71485
71862
  return false;
71486
71863
  }
71487
71864
  return true;
@@ -71689,7 +72066,7 @@ var suggestPatch = createSwarmTool({
71689
72066
  });
71690
72067
  continue;
71691
72068
  }
71692
- const fullPath = path71.resolve(directory, change.file);
72069
+ const fullPath = path72.resolve(directory, change.file);
71693
72070
  if (!fs59.existsSync(fullPath)) {
71694
72071
  errors5.push({
71695
72072
  success: false,
@@ -71785,7 +72162,7 @@ init_dist();
71785
72162
  init_manager();
71786
72163
  init_detector();
71787
72164
  import * as fs60 from "fs";
71788
- import * as path72 from "path";
72165
+ import * as path73 from "path";
71789
72166
  init_create_tool();
71790
72167
  var MAX_FILE_SIZE2 = 5 * 1024 * 1024;
71791
72168
  var BINARY_CHECK_BYTES = 8192;
@@ -71838,7 +72215,7 @@ async function syntaxCheck(input, directory, config3) {
71838
72215
  if (languages?.length) {
71839
72216
  const lowerLangs = languages.map((l) => l.toLowerCase());
71840
72217
  filesToCheck = filesToCheck.filter((file3) => {
71841
- const ext = path72.extname(file3.path).toLowerCase();
72218
+ const ext = path73.extname(file3.path).toLowerCase();
71842
72219
  const langDef = getLanguageForExtension(ext);
71843
72220
  const fileProfile = getProfileForFile(file3.path);
71844
72221
  const langId = fileProfile?.id || langDef?.id;
@@ -71851,7 +72228,7 @@ async function syntaxCheck(input, directory, config3) {
71851
72228
  let skippedCount = 0;
71852
72229
  for (const fileInfo of filesToCheck) {
71853
72230
  const { path: filePath } = fileInfo;
71854
- const fullPath = path72.isAbsolute(filePath) ? filePath : path72.join(directory, filePath);
72231
+ const fullPath = path73.isAbsolute(filePath) ? filePath : path73.join(directory, filePath);
71855
72232
  const result = {
71856
72233
  path: filePath,
71857
72234
  language: "",
@@ -71900,7 +72277,7 @@ async function syntaxCheck(input, directory, config3) {
71900
72277
  results.push(result);
71901
72278
  continue;
71902
72279
  }
71903
- const ext = path72.extname(filePath).toLowerCase();
72280
+ const ext = path73.extname(filePath).toLowerCase();
71904
72281
  const langDef = getLanguageForExtension(ext);
71905
72282
  result.language = profile?.id || langDef?.id || "unknown";
71906
72283
  const errors5 = extractSyntaxErrors(parser, content);
@@ -71962,7 +72339,7 @@ init_dist();
71962
72339
  init_utils();
71963
72340
  init_create_tool();
71964
72341
  import * as fs61 from "fs";
71965
- import * as path73 from "path";
72342
+ import * as path74 from "path";
71966
72343
  var MAX_TEXT_LENGTH = 200;
71967
72344
  var MAX_FILE_SIZE_BYTES9 = 1024 * 1024;
71968
72345
  var SUPPORTED_EXTENSIONS2 = new Set([
@@ -72028,9 +72405,9 @@ function validatePathsInput(paths, cwd) {
72028
72405
  return { error: "paths contains path traversal", resolvedPath: null };
72029
72406
  }
72030
72407
  try {
72031
- const resolvedPath = path73.resolve(paths);
72032
- const normalizedCwd = path73.resolve(cwd);
72033
- const normalizedResolved = path73.resolve(resolvedPath);
72408
+ const resolvedPath = path74.resolve(paths);
72409
+ const normalizedCwd = path74.resolve(cwd);
72410
+ const normalizedResolved = path74.resolve(resolvedPath);
72034
72411
  if (!normalizedResolved.startsWith(normalizedCwd)) {
72035
72412
  return {
72036
72413
  error: "paths must be within the current working directory",
@@ -72046,7 +72423,7 @@ function validatePathsInput(paths, cwd) {
72046
72423
  }
72047
72424
  }
72048
72425
  function isSupportedExtension(filePath) {
72049
- const ext = path73.extname(filePath).toLowerCase();
72426
+ const ext = path74.extname(filePath).toLowerCase();
72050
72427
  return SUPPORTED_EXTENSIONS2.has(ext);
72051
72428
  }
72052
72429
  function findSourceFiles2(dir, files = []) {
@@ -72061,7 +72438,7 @@ function findSourceFiles2(dir, files = []) {
72061
72438
  if (SKIP_DIRECTORIES4.has(entry)) {
72062
72439
  continue;
72063
72440
  }
72064
- const fullPath = path73.join(dir, entry);
72441
+ const fullPath = path74.join(dir, entry);
72065
72442
  let stat2;
72066
72443
  try {
72067
72444
  stat2 = fs61.statSync(fullPath);
@@ -72173,7 +72550,7 @@ var todo_extract = createSwarmTool({
72173
72550
  filesToScan.push(scanPath);
72174
72551
  } else {
72175
72552
  const errorResult = {
72176
- error: `unsupported file extension: ${path73.extname(scanPath)}`,
72553
+ error: `unsupported file extension: ${path74.extname(scanPath)}`,
72177
72554
  total: 0,
72178
72555
  byPriority: { high: 0, medium: 0, low: 0 },
72179
72556
  entries: []
@@ -72220,14 +72597,14 @@ init_tool();
72220
72597
  init_schema();
72221
72598
  init_gate_evidence();
72222
72599
  import * as fs63 from "fs";
72223
- import * as path75 from "path";
72600
+ import * as path76 from "path";
72224
72601
 
72225
72602
  // src/hooks/diff-scope.ts
72226
72603
  import * as fs62 from "fs";
72227
- import * as path74 from "path";
72604
+ import * as path75 from "path";
72228
72605
  function getDeclaredScope(taskId, directory) {
72229
72606
  try {
72230
- const planPath = path74.join(directory, ".swarm", "plan.json");
72607
+ const planPath = path75.join(directory, ".swarm", "plan.json");
72231
72608
  if (!fs62.existsSync(planPath))
72232
72609
  return null;
72233
72610
  const raw = fs62.readFileSync(planPath, "utf-8");
@@ -72344,7 +72721,7 @@ var TIER_3_PATTERNS = [
72344
72721
  ];
72345
72722
  function matchesTier3Pattern(files) {
72346
72723
  for (const file3 of files) {
72347
- const fileName = path75.basename(file3);
72724
+ const fileName = path76.basename(file3);
72348
72725
  for (const pattern of TIER_3_PATTERNS) {
72349
72726
  if (pattern.test(fileName)) {
72350
72727
  return true;
@@ -72358,7 +72735,7 @@ function checkReviewerGate(taskId, workingDirectory) {
72358
72735
  if (hasActiveTurboMode()) {
72359
72736
  const resolvedDir2 = workingDirectory;
72360
72737
  try {
72361
- const planPath = path75.join(resolvedDir2, ".swarm", "plan.json");
72738
+ const planPath = path76.join(resolvedDir2, ".swarm", "plan.json");
72362
72739
  const planRaw = fs63.readFileSync(planPath, "utf-8");
72363
72740
  const plan = JSON.parse(planRaw);
72364
72741
  for (const planPhase of plan.phases ?? []) {
@@ -72425,7 +72802,7 @@ function checkReviewerGate(taskId, workingDirectory) {
72425
72802
  }
72426
72803
  try {
72427
72804
  const resolvedDir2 = workingDirectory;
72428
- const planPath = path75.join(resolvedDir2, ".swarm", "plan.json");
72805
+ const planPath = path76.join(resolvedDir2, ".swarm", "plan.json");
72429
72806
  const planRaw = fs63.readFileSync(planPath, "utf-8");
72430
72807
  const plan = JSON.parse(planRaw);
72431
72808
  for (const planPhase of plan.phases ?? []) {
@@ -72608,8 +72985,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
72608
72985
  };
72609
72986
  }
72610
72987
  }
72611
- normalizedDir = path75.normalize(args2.working_directory);
72612
- const pathParts = normalizedDir.split(path75.sep);
72988
+ normalizedDir = path76.normalize(args2.working_directory);
72989
+ const pathParts = normalizedDir.split(path76.sep);
72613
72990
  if (pathParts.includes("..")) {
72614
72991
  return {
72615
72992
  success: false,
@@ -72619,10 +72996,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
72619
72996
  ]
72620
72997
  };
72621
72998
  }
72622
- const resolvedDir = path75.resolve(normalizedDir);
72999
+ const resolvedDir = path76.resolve(normalizedDir);
72623
73000
  try {
72624
73001
  const realPath = fs63.realpathSync(resolvedDir);
72625
- const planPath = path75.join(realPath, ".swarm", "plan.json");
73002
+ const planPath = path76.join(realPath, ".swarm", "plan.json");
72626
73003
  if (!fs63.existsSync(planPath)) {
72627
73004
  return {
72628
73005
  success: false,
@@ -72654,8 +73031,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
72654
73031
  }
72655
73032
  if (args2.status === "in_progress") {
72656
73033
  try {
72657
- const evidencePath = path75.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
72658
- fs63.mkdirSync(path75.dirname(evidencePath), { recursive: true });
73034
+ const evidencePath = path76.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
73035
+ fs63.mkdirSync(path76.dirname(evidencePath), { recursive: true });
72659
73036
  const fd = fs63.openSync(evidencePath, "wx");
72660
73037
  let writeOk = false;
72661
73038
  try {
@@ -72680,7 +73057,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
72680
73057
  recoverTaskStateFromDelegations(args2.task_id);
72681
73058
  let phaseRequiresReviewer = true;
72682
73059
  try {
72683
- const planPath = path75.join(directory, ".swarm", "plan.json");
73060
+ const planPath = path76.join(directory, ".swarm", "plan.json");
72684
73061
  const planRaw = fs63.readFileSync(planPath, "utf-8");
72685
73062
  const plan = JSON.parse(planRaw);
72686
73063
  const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
@@ -72780,7 +73157,7 @@ init_tool();
72780
73157
  init_utils2();
72781
73158
  init_create_tool();
72782
73159
  import fs64 from "fs";
72783
- import path76 from "path";
73160
+ import path77 from "path";
72784
73161
  function normalizeVerdict(verdict) {
72785
73162
  switch (verdict) {
72786
73163
  case "APPROVED":
@@ -72827,7 +73204,7 @@ async function executeWriteDriftEvidence(args2, directory) {
72827
73204
  entries: [evidenceEntry]
72828
73205
  };
72829
73206
  const filename = "drift-verifier.json";
72830
- const relativePath = path76.join("evidence", String(phase), filename);
73207
+ const relativePath = path77.join("evidence", String(phase), filename);
72831
73208
  let validatedPath;
72832
73209
  try {
72833
73210
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -72838,10 +73215,10 @@ async function executeWriteDriftEvidence(args2, directory) {
72838
73215
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
72839
73216
  }, null, 2);
72840
73217
  }
72841
- const evidenceDir = path76.dirname(validatedPath);
73218
+ const evidenceDir = path77.dirname(validatedPath);
72842
73219
  try {
72843
73220
  await fs64.promises.mkdir(evidenceDir, { recursive: true });
72844
- const tempPath = path76.join(evidenceDir, `.${filename}.tmp`);
73221
+ const tempPath = path77.join(evidenceDir, `.${filename}.tmp`);
72845
73222
  await fs64.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
72846
73223
  await fs64.promises.rename(tempPath, validatedPath);
72847
73224
  return JSON.stringify({
@@ -72932,7 +73309,7 @@ var OpenCodeSwarm = async (ctx) => {
72932
73309
  swarmState.opencodeClient = ctx.client;
72933
73310
  await loadSnapshot(ctx.directory);
72934
73311
  initTelemetry(ctx.directory);
72935
- const agents = getAgentConfigs(config3);
73312
+ const agents = getAgentConfigs(config3, ctx.directory);
72936
73313
  const agentDefinitions = createAgents(config3);
72937
73314
  swarmState.curatorInitAgentNames = Object.keys(agents).filter((k) => k === "curator_init" || k.endsWith("_curator_init"));
72938
73315
  swarmState.curatorPhaseAgentNames = Object.keys(agents).filter((k) => k === "curator_phase" || k.endsWith("_curator_phase"));
@@ -73044,7 +73421,7 @@ var OpenCodeSwarm = async (ctx) => {
73044
73421
  const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
73045
73422
  preflightTriggerManager = new PTM(automationConfig);
73046
73423
  const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
73047
- const swarmDir = path77.resolve(ctx.directory, ".swarm");
73424
+ const swarmDir = path78.resolve(ctx.directory, ".swarm");
73048
73425
  statusArtifact = new ASA(swarmDir);
73049
73426
  statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
73050
73427
  if (automationConfig.capabilities?.evidence_auto_summaries === true) {
@@ -73150,9 +73527,9 @@ var OpenCodeSwarm = async (ctx) => {
73150
73527
  completion_verify,
73151
73528
  complexity_hotspots,
73152
73529
  curator_analyze,
73153
- knowledgeAdd,
73154
- knowledgeRecall,
73155
- knowledgeRemove,
73530
+ knowledge_add,
73531
+ knowledge_recall,
73532
+ knowledge_remove,
73156
73533
  co_change_analyzer,
73157
73534
  detect_domains,
73158
73535
  doc_extract,