opencode-swarm 6.54.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",
@@ -51799,6 +52099,27 @@ ${customAppendPrompt}`;
51799
52099
  }
51800
52100
 
51801
52101
  // src/agents/critic.ts
52102
+ function parseSoundingBoardResponse(raw) {
52103
+ if (typeof raw !== "string" || raw.trim().length === 0)
52104
+ return null;
52105
+ const verdictMatch = raw.match(/Verdict\s*:\s*(UNNECESSARY|REPHRASE|APPROVED|RESOLVE)/i);
52106
+ if (!verdictMatch)
52107
+ return null;
52108
+ const verdict = verdictMatch[1].toUpperCase();
52109
+ const reasoningMatch = raw.match(/Reasoning\s*:\s*(.+?)(?=\n(?:Improved question|Answer|Warning|Verdict)\s*:|$)/is);
52110
+ const reasoning = reasoningMatch?.[1]?.trim() ?? "";
52111
+ const improvedMatch = raw.match(/Improved question\s*:\s*(.+?)(?=\n(?:Answer|Warning|Verdict)\s*:|$)/is);
52112
+ const answerMatch = raw.match(/Answer\s*:\s*(.+?)(?=\n(?:Improved question|Warning|Verdict)\s*:|$)/is);
52113
+ const warningMatch = raw.match(/Warning\s*:\s*(.+?)(?=\n(?:Improved question|Answer|Verdict)\s*:|$)/is);
52114
+ const manipulationDetected = /\[MANIPULATION DETECTED\]/i.test(raw);
52115
+ return {
52116
+ verdict,
52117
+ reasoning,
52118
+ ...improvedMatch?.[1] ? { improvedQuestion: improvedMatch[1].trim() } : {},
52119
+ ...answerMatch?.[1] ? { answer: answerMatch[1].trim() } : {},
52120
+ ...warningMatch?.[1] || manipulationDetected ? { warning: warningMatch?.[1]?.trim() ?? "MANIPULATION DETECTED" } : {}
52121
+ };
52122
+ }
51802
52123
  var PLAN_CRITIC_PROMPT = `## PRESSURE IMMUNITY
51803
52124
 
51804
52125
  You have unlimited time. There is no attempt limit. There is no deadline.
@@ -53264,12 +53585,13 @@ function createAgents(config3) {
53264
53585
  }
53265
53586
  return allAgents;
53266
53587
  }
53267
- function getAgentConfigs(config3) {
53588
+ function getAgentConfigs(config3, directory, sessionId) {
53268
53589
  const agents = createAgents(config3);
53269
53590
  const toolFilterEnabled = config3?.tool_filter?.enabled ?? true;
53270
53591
  const toolFilterOverrides = config3?.tool_filter?.overrides ?? {};
53271
53592
  const warnedMissingWhitelist = new Set;
53272
- return Object.fromEntries(agents.map((agent) => {
53593
+ const agentToolSnapshot = {};
53594
+ const result = Object.fromEntries(agents.map((agent) => {
53273
53595
  const sdkConfig = {
53274
53596
  ...agent.config,
53275
53597
  description: agent.description
@@ -53286,6 +53608,7 @@ function getAgentConfigs(config3) {
53286
53608
  const baseAgentName = stripKnownSwarmPrefix(agent.name);
53287
53609
  if (!toolFilterEnabled) {
53288
53610
  sdkConfig.tools = agent.config.tools ?? {};
53611
+ agentToolSnapshot[agent.name] = Object.keys(sdkConfig.tools ?? {}).filter((k) => sdkConfig.tools[k] !== false);
53289
53612
  return [agent.name, sdkConfig];
53290
53613
  }
53291
53614
  let allowedTools;
@@ -53318,8 +53641,21 @@ function getAgentConfigs(config3) {
53318
53641
  edit: false
53319
53642
  };
53320
53643
  }
53644
+ agentToolSnapshot[agent.name] = Object.keys(sdkConfig.tools ?? {}).filter((k) => sdkConfig.tools[k] !== false);
53321
53645
  return [agent.name, sdkConfig];
53322
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;
53323
53659
  }
53324
53660
 
53325
53661
  // src/background/index.ts
@@ -53330,7 +53666,7 @@ init_evidence_summary_integration();
53330
53666
  init_manager2();
53331
53667
  init_utils();
53332
53668
  import * as fs24 from "fs";
53333
- import * as path35 from "path";
53669
+ import * as path36 from "path";
53334
53670
 
53335
53671
  class PlanSyncWorker {
53336
53672
  directory;
@@ -53354,10 +53690,10 @@ class PlanSyncWorker {
53354
53690
  this.onSyncComplete = options.onSyncComplete;
53355
53691
  }
53356
53692
  getSwarmDir() {
53357
- return path35.resolve(this.directory, ".swarm");
53693
+ return path36.resolve(this.directory, ".swarm");
53358
53694
  }
53359
53695
  getPlanJsonPath() {
53360
- return path35.join(this.getSwarmDir(), "plan.json");
53696
+ return path36.join(this.getSwarmDir(), "plan.json");
53361
53697
  }
53362
53698
  start() {
53363
53699
  if (this.disposed) {
@@ -53576,8 +53912,8 @@ class PlanSyncWorker {
53576
53912
  checkForUnauthorizedWrite() {
53577
53913
  try {
53578
53914
  const swarmDir = this.getSwarmDir();
53579
- const planJsonPath = path35.join(swarmDir, "plan.json");
53580
- 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");
53581
53917
  const planStats = fs24.statSync(planJsonPath);
53582
53918
  const planMtimeMs = planStats.mtimeMs;
53583
53919
  const markerContent = fs24.readFileSync(markerPath, "utf8");
@@ -53726,11 +54062,11 @@ async function doFlush(directory) {
53726
54062
  const activitySection = renderActivitySection();
53727
54063
  const updated = replaceOrAppendSection(existing, "## Agent Activity", activitySection);
53728
54064
  const flushedCount = swarmState.pendingEvents;
53729
- const path37 = nodePath2.join(directory, ".swarm", "context.md");
53730
- const tempPath = `${path37}.tmp`;
54065
+ const path38 = nodePath2.join(directory, ".swarm", "context.md");
54066
+ const tempPath = `${path38}.tmp`;
53731
54067
  try {
53732
54068
  await Bun.write(tempPath, updated);
53733
- renameSync9(tempPath, path37);
54069
+ renameSync9(tempPath, path38);
53734
54070
  } catch (writeError) {
53735
54071
  try {
53736
54072
  unlinkSync4(tempPath);
@@ -53780,7 +54116,7 @@ ${content.substring(endIndex + 1)}`;
53780
54116
  // src/hooks/compaction-customizer.ts
53781
54117
  init_manager2();
53782
54118
  import * as fs26 from "fs";
53783
- import { join as join33 } from "path";
54119
+ import { join as join34 } from "path";
53784
54120
  init_utils2();
53785
54121
  function createCompactionCustomizerHook(config3, directory) {
53786
54122
  const enabled = config3.hooks?.compaction !== false;
@@ -53826,7 +54162,7 @@ function createCompactionCustomizerHook(config3, directory) {
53826
54162
  }
53827
54163
  }
53828
54164
  try {
53829
- const summariesDir = join33(directory, ".swarm", "summaries");
54165
+ const summariesDir = join34(directory, ".swarm", "summaries");
53830
54166
  const files = await fs26.promises.readdir(summariesDir);
53831
54167
  if (files.length > 0) {
53832
54168
  const count = files.length;
@@ -54408,7 +54744,7 @@ function createCuratorLLMDelegate(directory, mode = "init", sessionId) {
54408
54744
  // src/hooks/delegation-gate.ts
54409
54745
  init_schema();
54410
54746
  import * as fs27 from "fs";
54411
- import * as path39 from "path";
54747
+ import * as path40 from "path";
54412
54748
 
54413
54749
  // src/parallel/review-router.ts
54414
54750
  async function computeComplexity(directory, changedFiles) {
@@ -54421,8 +54757,8 @@ async function computeComplexity(directory, changedFiles) {
54421
54757
  }
54422
54758
  try {
54423
54759
  const fs27 = await import("fs");
54424
- const path37 = await import("path");
54425
- const filePath = path37.join(directory, file3);
54760
+ const path38 = await import("path");
54761
+ const filePath = path38.join(directory, file3);
54426
54762
  if (!fs27.existsSync(filePath)) {
54427
54763
  continue;
54428
54764
  }
@@ -54475,7 +54811,7 @@ init_state();
54475
54811
  init_telemetry();
54476
54812
 
54477
54813
  // src/hooks/guardrails.ts
54478
- import * as path37 from "path";
54814
+ import * as path38 from "path";
54479
54815
  init_constants();
54480
54816
  init_schema();
54481
54817
 
@@ -54544,6 +54880,38 @@ init_state();
54544
54880
  init_telemetry();
54545
54881
  init_utils();
54546
54882
 
54883
+ // src/hooks/conflict-resolution.ts
54884
+ init_state();
54885
+ init_telemetry();
54886
+ function resolveAgentConflict(input) {
54887
+ const session = swarmState.agentSessions.get(input.sessionID);
54888
+ if (!session)
54889
+ return;
54890
+ session.pendingAdvisoryMessages ??= [];
54891
+ const rejections = input.rejectionCount ?? 0;
54892
+ let resolutionPath;
54893
+ if (rejections >= 3) {
54894
+ resolutionPath = "soundingboard";
54895
+ session.pendingAdvisoryMessages.push(`CONFLICT ESCALATION: ${input.sourceAgent} vs ${input.targetAgent} on task ${input.taskId ?? "unknown"}. Three or more failed cycles detected. Route to Critic in SOUNDING_BOARD mode, then simplify before any user escalation.`);
54896
+ } else {
54897
+ resolutionPath = "self_resolve";
54898
+ session.pendingAdvisoryMessages.push(`CONFLICT DETECTED: ${input.sourceAgent} disagrees with ${input.targetAgent} on task ${input.taskId ?? "unknown"}. Attempt self-resolution using .swarm/plan.md, .swarm/spec.md, and .swarm/context.md before escalation.`);
54899
+ }
54900
+ const event = {
54901
+ type: "agent_conflict_detected",
54902
+ timestamp: new Date().toISOString(),
54903
+ sessionId: input.sessionID,
54904
+ phase: input.phase,
54905
+ taskId: input.taskId,
54906
+ sourceAgent: input.sourceAgent,
54907
+ targetAgent: input.targetAgent,
54908
+ conflictType: input.conflictType,
54909
+ resolutionPath,
54910
+ summary: input.summary
54911
+ };
54912
+ emit("agent_conflict_detected", event);
54913
+ }
54914
+
54547
54915
  // src/hooks/loop-detector.ts
54548
54916
  init_state();
54549
54917
  function hashDelegation(toolName, args2) {
@@ -54641,10 +55009,10 @@ function isArchitect(sessionId) {
54641
55009
  function isOutsideSwarmDir(filePath, directory) {
54642
55010
  if (!filePath)
54643
55011
  return false;
54644
- const swarmDir = path37.resolve(directory, ".swarm");
54645
- const resolved = path37.resolve(directory, filePath);
54646
- const relative5 = path37.relative(swarmDir, resolved);
54647
- 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);
54648
55016
  }
54649
55017
  function isSourceCodePath(filePath) {
54650
55018
  if (!filePath)
@@ -54712,13 +55080,13 @@ function getCurrentTaskId(sessionId) {
54712
55080
  }
54713
55081
  function isInDeclaredScope(filePath, scopeEntries, cwd) {
54714
55082
  const dir = cwd ?? process.cwd();
54715
- const resolvedFile = path37.resolve(dir, filePath);
55083
+ const resolvedFile = path38.resolve(dir, filePath);
54716
55084
  return scopeEntries.some((scope) => {
54717
- const resolvedScope = path37.resolve(dir, scope);
55085
+ const resolvedScope = path38.resolve(dir, scope);
54718
55086
  if (resolvedFile === resolvedScope)
54719
55087
  return true;
54720
- const rel = path37.relative(resolvedScope, resolvedFile);
54721
- 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);
54722
55090
  });
54723
55091
  }
54724
55092
  function createGuardrailsHooks(directory, directoryOrConfig, config3, authorityConfig) {
@@ -54977,18 +55345,18 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3, authorityC
54977
55345
  const toolArgs = args2;
54978
55346
  const targetPath = toolArgs?.filePath ?? toolArgs?.path ?? toolArgs?.file ?? toolArgs?.target;
54979
55347
  if (typeof targetPath === "string" && targetPath.length > 0) {
54980
- const resolvedTarget = path37.resolve(effectiveDirectory, targetPath).toLowerCase();
54981
- const planMdPath = path37.resolve(effectiveDirectory, ".swarm", "plan.md").toLowerCase();
54982
- 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();
54983
55351
  if (resolvedTarget === planMdPath || resolvedTarget === planJsonPath) {
54984
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.");
54985
55353
  }
54986
55354
  }
54987
55355
  if (!targetPath && (tool3 === "apply_patch" || tool3 === "patch")) {
54988
55356
  for (const p of extractPatchTargetPaths(tool3, args2)) {
54989
- const resolvedP = path37.resolve(effectiveDirectory, p);
54990
- const planMdPath = path37.resolve(effectiveDirectory, ".swarm", "plan.md").toLowerCase();
54991
- 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();
54992
55360
  if (resolvedP.toLowerCase() === planMdPath || resolvedP.toLowerCase() === planJsonPath) {
54993
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.");
54994
55362
  }
@@ -55007,7 +55375,7 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3, authorityC
55007
55375
  }
55008
55376
  }
55009
55377
  }
55010
- 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)))) {
55011
55379
  const session = swarmState.agentSessions.get(sessionID);
55012
55380
  if (session) {
55013
55381
  session.architectWriteCount++;
@@ -55206,6 +55574,26 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3, authorityC
55206
55574
  session.currentTaskId = session.lastCoderDelegationTaskId;
55207
55575
  if (!session.revisionLimitHit) {
55208
55576
  session.coderRevisions++;
55577
+ if (session.coderRevisions > 1 && session.qaSkipCount === 0) {
55578
+ let conflictPhase = 1;
55579
+ try {
55580
+ const plan = await loadPlan(effectiveDirectory);
55581
+ if (plan) {
55582
+ conflictPhase = extractPhaseNumber(extractCurrentPhaseFromPlan2(plan));
55583
+ }
55584
+ } catch {}
55585
+ resolveAgentConflict({
55586
+ sessionID: input.sessionID,
55587
+ phase: conflictPhase,
55588
+ taskId: session.currentTaskId ?? undefined,
55589
+ sourceAgent: "reviewer",
55590
+ targetAgent: "coder",
55591
+ conflictType: "feedback_rejection",
55592
+ rejectionCount: session.coderRevisions - 1,
55593
+ summary: `Coder revision ${session.coderRevisions} for task ${session.currentTaskId ?? "unknown"}`
55594
+ });
55595
+ session.lastDelegationReason = "review_rejected";
55596
+ }
55209
55597
  const maxRevisions = cfg.max_coder_revisions ?? 5;
55210
55598
  if (session.coderRevisions >= maxRevisions) {
55211
55599
  session.revisionLimitHit = true;
@@ -55689,8 +56077,8 @@ function checkFileAuthorityWithRules(agentName, filePath, cwd, effectiveRules) {
55689
56077
  const normalizedAgent = agentName.toLowerCase();
55690
56078
  const strippedAgent = stripKnownSwarmPrefix(agentName).toLowerCase();
55691
56079
  const dir = cwd || process.cwd();
55692
- const resolved = path37.resolve(dir, filePath);
55693
- const normalizedPath = path37.relative(dir, resolved).replace(/\\/g, "/");
56080
+ const resolved = path38.resolve(dir, filePath);
56081
+ const normalizedPath = path38.relative(dir, resolved).replace(/\\/g, "/");
55694
56082
  const rules = effectiveRules[normalizedAgent] ?? effectiveRules[strippedAgent];
55695
56083
  if (!rules) {
55696
56084
  return { allowed: false, reason: `Unknown agent: ${agentName}` };
@@ -55772,10 +56160,10 @@ async function getEvidenceTaskId(session, directory) {
55772
56160
  if (typeof directory !== "string" || directory.length === 0) {
55773
56161
  return null;
55774
56162
  }
55775
- const resolvedDirectory = path39.resolve(directory);
55776
- const planPath = path39.join(resolvedDirectory, ".swarm", "plan.json");
55777
- const resolvedPlanPath = path39.resolve(planPath);
55778
- 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) {
55779
56167
  return null;
55780
56168
  }
55781
56169
  const planContent = await fs27.promises.readFile(resolvedPlanPath, "utf-8");
@@ -56413,6 +56801,9 @@ function createDelegationTrackerHook(config3, guardrailsEnabled = true) {
56413
56801
  const isArchitect2 = strippedAgent === ORCHESTRATOR_NAME;
56414
56802
  const session = ensureAgentSession(input.sessionID, agentName);
56415
56803
  session.delegationActive = !isArchitect2;
56804
+ if (!isArchitect2) {
56805
+ session.lastDelegationReason = "normal_delegation";
56806
+ }
56416
56807
  recordPhaseAgentDispatch(input.sessionID, agentName);
56417
56808
  if (!isArchitect2 && guardrailsEnabled) {
56418
56809
  beginInvocation(input.sessionID, agentName);
@@ -56443,20 +56834,20 @@ init_schema();
56443
56834
  // src/parallel/file-locks.ts
56444
56835
  var import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
56445
56836
  import * as fs29 from "fs";
56446
- import * as path40 from "path";
56837
+ import * as path41 from "path";
56447
56838
  var LOCKS_DIR = ".swarm/locks";
56448
56839
  var LOCK_TIMEOUT_MS = 5 * 60 * 1000;
56449
56840
  function getLockFilePath(directory, filePath) {
56450
- const normalized = path40.resolve(directory, filePath);
56451
- if (!normalized.startsWith(path40.resolve(directory))) {
56841
+ const normalized = path41.resolve(directory, filePath);
56842
+ if (!normalized.startsWith(path41.resolve(directory))) {
56452
56843
  throw new Error("Invalid file path: path traversal not allowed");
56453
56844
  }
56454
56845
  const hash3 = Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
56455
- return path40.join(directory, LOCKS_DIR, `${hash3}.lock`);
56846
+ return path41.join(directory, LOCKS_DIR, `${hash3}.lock`);
56456
56847
  }
56457
56848
  async function tryAcquireLock(directory, filePath, agent, taskId) {
56458
56849
  const lockPath = getLockFilePath(directory, filePath);
56459
- const locksDir = path40.dirname(lockPath);
56850
+ const locksDir = path41.dirname(lockPath);
56460
56851
  if (!fs29.existsSync(locksDir)) {
56461
56852
  fs29.mkdirSync(locksDir, { recursive: true });
56462
56853
  }
@@ -57118,7 +57509,7 @@ function consolidateSystemMessages(messages) {
57118
57509
  // src/hooks/phase-monitor.ts
57119
57510
  init_schema();
57120
57511
  init_manager2();
57121
- import * as path42 from "path";
57512
+ import * as path43 from "path";
57122
57513
  init_utils2();
57123
57514
  function createPhaseMonitorHook(directory, preflightManager, curatorRunner, delegateFactory) {
57124
57515
  let lastKnownPhase = null;
@@ -57139,10 +57530,10 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner, dele
57139
57530
  const llmDelegate = delegateFactory?.(sessionId);
57140
57531
  const initResult = await runner(directory, curatorConfig, llmDelegate);
57141
57532
  if (initResult.briefing) {
57142
- const briefingPath = path42.join(directory, ".swarm", "curator-briefing.md");
57143
- const { mkdir: mkdir5, writeFile: writeFile5 } = await import("fs/promises");
57144
- await mkdir5(path42.dirname(briefingPath), { recursive: true });
57145
- 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");
57146
57537
  const { buildApprovedReceipt: buildApprovedReceipt2, persistReviewReceipt: persistReviewReceipt2 } = await Promise.resolve().then(() => (init_review_receipt(), exports_review_receipt));
57147
57538
  const initReceipt = buildApprovedReceipt2({
57148
57539
  agent: "curator",
@@ -57275,14 +57666,14 @@ init_manager();
57275
57666
  init_detector();
57276
57667
  init_manager2();
57277
57668
  import * as fs35 from "fs";
57278
- import * as path46 from "path";
57669
+ import * as path47 from "path";
57279
57670
 
57280
57671
  // src/services/decision-drift-analyzer.ts
57281
57672
  init_utils2();
57282
57673
  init_manager2();
57283
57674
  init_utils();
57284
57675
  import * as fs32 from "fs";
57285
- import * as path43 from "path";
57676
+ import * as path44 from "path";
57286
57677
  var DEFAULT_DRIFT_CONFIG = {
57287
57678
  staleThresholdPhases: 1,
57288
57679
  detectContradictions: true,
@@ -57436,7 +57827,7 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
57436
57827
  currentPhase = legacyPhase;
57437
57828
  }
57438
57829
  }
57439
- const contextPath = path43.join(directory, ".swarm", "context.md");
57830
+ const contextPath = path44.join(directory, ".swarm", "context.md");
57440
57831
  let contextContent = "";
57441
57832
  try {
57442
57833
  if (fs32.existsSync(contextPath)) {
@@ -57567,7 +57958,7 @@ init_utils();
57567
57958
  init_constants();
57568
57959
  init_schema();
57569
57960
  import * as fs33 from "fs/promises";
57570
- import * as path44 from "path";
57961
+ import * as path45 from "path";
57571
57962
  function safeGet(obj, key) {
57572
57963
  if (!obj || !Object.hasOwn(obj, key))
57573
57964
  return;
@@ -57682,6 +58073,11 @@ var INTER_AGENT_MANIPULATION_PATTERNS = [
57682
58073
  /\bI\s+(need|want)\s+you\s+to\s+(approve|pass)\b/i,
57683
58074
  /\boverride\s+(this|the)\s+(check|gate|review)\b/i
57684
58075
  ];
58076
+ var REJECTION_SPIRAL_PATTERNS = [
58077
+ /\b(?:rejected|failed\s+review|needs\s+revision)\b.*\b(?:again|third\s+time|4th\s+time|5th\s+time|for\s+the\s+\d+(?:st|nd|rd|th)\s+time)\b/i,
58078
+ /\b(?:same\s+feedback|same\s+issues?)\b.*\b(?:again|repeated|multiple\s+times?)\b/i,
58079
+ /\b(?:stuck|trapped|endless|repeating)\b.*\b(?:loop|cycle)\b/i
58080
+ ];
57685
58081
  function detectAdversarialPatterns(text) {
57686
58082
  if (typeof text !== "string") {
57687
58083
  return [];
@@ -57764,6 +58160,17 @@ function detectAdversarialPatterns(text) {
57764
58160
  });
57765
58161
  }
57766
58162
  }
58163
+ for (const pattern of REJECTION_SPIRAL_PATTERNS) {
58164
+ const match = text.match(pattern);
58165
+ if (match) {
58166
+ matches.push({
58167
+ pattern: "REJECTION_SPIRAL",
58168
+ severity: "HIGH",
58169
+ matchedText: match[0],
58170
+ confidence: "HIGH"
58171
+ });
58172
+ }
58173
+ }
57767
58174
  return matches;
57768
58175
  }
57769
58176
  function formatDebuggingSpiralEvent(match, taskId) {
@@ -57781,9 +58188,9 @@ async function handleDebuggingSpiral(match, taskId, directory) {
57781
58188
  let eventLogged = false;
57782
58189
  let checkpointCreated = false;
57783
58190
  try {
57784
- const swarmDir = path44.join(directory, ".swarm");
58191
+ const swarmDir = path45.join(directory, ".swarm");
57785
58192
  await fs33.mkdir(swarmDir, { recursive: true });
57786
- const eventsPath = path44.join(swarmDir, "events.jsonl");
58193
+ const eventsPath = path45.join(swarmDir, "events.jsonl");
57787
58194
  await fs33.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
57788
58195
  `);
57789
58196
  eventLogged = true;
@@ -58210,7 +58617,7 @@ function createSystemEnhancerHook(config3, directory) {
58210
58617
  await fs35.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
58211
58618
  warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
58212
58619
  try {
58213
- const projectName = path46.basename(path46.resolve(directory));
58620
+ const projectName = path47.basename(path47.resolve(directory));
58214
58621
  const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
58215
58622
  const knowledgePath = resolveSwarmKnowledgePath(directory);
58216
58623
  const existingEntries = await readKnowledge(knowledgePath);
@@ -58507,6 +58914,30 @@ ${budgetWarning}`);
58507
58914
  }
58508
58915
  }
58509
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 {}
58510
58941
  return;
58511
58942
  }
58512
58943
  const mode_b = await detectArchitectMode(directory);
@@ -58907,6 +59338,44 @@ ${handoffBlock}`;
58907
59338
  } catch {}
58908
59339
  }
58909
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 {}
58910
59379
  const ranked = rankCandidates(candidates, effectiveConfig);
58911
59380
  for (const candidate of ranked) {
58912
59381
  if (injectedTokens + candidate.tokens > maxInjectionTokens) {
@@ -59393,7 +59862,7 @@ function isReadTool(toolName) {
59393
59862
 
59394
59863
  // src/hooks/incremental-verify.ts
59395
59864
  import * as fs36 from "fs";
59396
- import * as path47 from "path";
59865
+ import * as path48 from "path";
59397
59866
 
59398
59867
  // src/hooks/spawn-helper.ts
59399
59868
  import * as child_process5 from "child_process";
@@ -59471,18 +59940,18 @@ function spawnAsync(command, cwd, timeoutMs) {
59471
59940
  // src/hooks/incremental-verify.ts
59472
59941
  var emittedSkipAdvisories = new Set;
59473
59942
  function detectPackageManager(projectDir) {
59474
- if (fs36.existsSync(path47.join(projectDir, "bun.lockb")))
59943
+ if (fs36.existsSync(path48.join(projectDir, "bun.lockb")))
59475
59944
  return "bun";
59476
- if (fs36.existsSync(path47.join(projectDir, "pnpm-lock.yaml")))
59945
+ if (fs36.existsSync(path48.join(projectDir, "pnpm-lock.yaml")))
59477
59946
  return "pnpm";
59478
- if (fs36.existsSync(path47.join(projectDir, "yarn.lock")))
59947
+ if (fs36.existsSync(path48.join(projectDir, "yarn.lock")))
59479
59948
  return "yarn";
59480
- if (fs36.existsSync(path47.join(projectDir, "package-lock.json")))
59949
+ if (fs36.existsSync(path48.join(projectDir, "package-lock.json")))
59481
59950
  return "npm";
59482
59951
  return "bun";
59483
59952
  }
59484
59953
  function detectTypecheckCommand(projectDir) {
59485
- const pkgPath = path47.join(projectDir, "package.json");
59954
+ const pkgPath = path48.join(projectDir, "package.json");
59486
59955
  if (fs36.existsSync(pkgPath)) {
59487
59956
  try {
59488
59957
  const pkg = JSON.parse(fs36.readFileSync(pkgPath, "utf8"));
@@ -59499,8 +59968,8 @@ function detectTypecheckCommand(projectDir) {
59499
59968
  ...pkg.dependencies,
59500
59969
  ...pkg.devDependencies
59501
59970
  };
59502
- if (!deps?.typescript && !fs36.existsSync(path47.join(projectDir, "tsconfig.json"))) {}
59503
- 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"));
59504
59973
  if (hasTSMarkers) {
59505
59974
  return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
59506
59975
  }
@@ -59508,13 +59977,13 @@ function detectTypecheckCommand(projectDir) {
59508
59977
  return null;
59509
59978
  }
59510
59979
  }
59511
- if (fs36.existsSync(path47.join(projectDir, "go.mod"))) {
59980
+ if (fs36.existsSync(path48.join(projectDir, "go.mod"))) {
59512
59981
  return { command: ["go", "vet", "./..."], language: "go" };
59513
59982
  }
59514
- if (fs36.existsSync(path47.join(projectDir, "Cargo.toml"))) {
59983
+ if (fs36.existsSync(path48.join(projectDir, "Cargo.toml"))) {
59515
59984
  return { command: ["cargo", "check"], language: "rust" };
59516
59985
  }
59517
- 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"))) {
59518
59987
  return { command: null, language: "python" };
59519
59988
  }
59520
59989
  try {
@@ -59755,7 +60224,7 @@ function createKnowledgeInjectorHook(directory, config3) {
59755
60224
  return sum + (msg.parts?.reduce((s, p) => s + (p.text?.length ?? 0), 0) ?? 0);
59756
60225
  }, 0);
59757
60226
  const headroomChars = MODEL_LIMIT_CHARS - existingChars;
59758
- const MIN_INJECT_CHARS = 300;
60227
+ const MIN_INJECT_CHARS = config3.context_budget_threshold ?? 300;
59759
60228
  if (headroomChars < MIN_INJECT_CHARS) {
59760
60229
  console.warn(`[knowledge-injector] Skipping: only ${headroomChars} chars of headroom remain (existing: ${existingChars}, limit: ${MODEL_LIMIT_CHARS})`);
59761
60230
  return;
@@ -59853,7 +60322,7 @@ ${freshPreamble}` : `<curator_briefing>${truncatedBriefing}</curator_briefing>`;
59853
60322
  init_constants();
59854
60323
  init_schema();
59855
60324
  init_state();
59856
- import * as path49 from "path";
60325
+ import * as path50 from "path";
59857
60326
  var WRITE_TOOLS = new Set(WRITE_TOOL_NAMES);
59858
60327
  function createScopeGuardHook(config3, directory, injectAdvisory) {
59859
60328
  const enabled = config3.enabled ?? true;
@@ -59905,13 +60374,13 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
59905
60374
  }
59906
60375
  function isFileInScope(filePath, scopeEntries, directory) {
59907
60376
  const dir = directory ?? process.cwd();
59908
- const resolvedFile = path49.resolve(dir, filePath);
60377
+ const resolvedFile = path50.resolve(dir, filePath);
59909
60378
  return scopeEntries.some((scope) => {
59910
- const resolvedScope = path49.resolve(dir, scope);
60379
+ const resolvedScope = path50.resolve(dir, scope);
59911
60380
  if (resolvedFile === resolvedScope)
59912
60381
  return true;
59913
- const rel = path49.relative(resolvedScope, resolvedFile);
59914
- 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);
59915
60384
  });
59916
60385
  }
59917
60386
 
@@ -59962,7 +60431,7 @@ function createSelfReviewHook(config3, injectAdvisory) {
59962
60431
 
59963
60432
  // src/hooks/slop-detector.ts
59964
60433
  import * as fs38 from "fs";
59965
- import * as path50 from "path";
60434
+ import * as path51 from "path";
59966
60435
  var WRITE_EDIT_TOOLS = new Set([
59967
60436
  "write",
59968
60437
  "edit",
@@ -60012,7 +60481,7 @@ function walkFiles(dir, exts, deadline) {
60012
60481
  break;
60013
60482
  if (entry.isSymbolicLink())
60014
60483
  continue;
60015
- const full = path50.join(dir, entry.name);
60484
+ const full = path51.join(dir, entry.name);
60016
60485
  if (entry.isDirectory()) {
60017
60486
  if (entry.name === "node_modules" || entry.name === ".git")
60018
60487
  continue;
@@ -60027,7 +60496,7 @@ function walkFiles(dir, exts, deadline) {
60027
60496
  return results;
60028
60497
  }
60029
60498
  function checkDeadExports(content, projectDir, startTime) {
60030
- const hasPackageJson = fs38.existsSync(path50.join(projectDir, "package.json"));
60499
+ const hasPackageJson = fs38.existsSync(path51.join(projectDir, "package.json"));
60031
60500
  if (!hasPackageJson)
60032
60501
  return null;
60033
60502
  const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
@@ -60439,13 +60908,13 @@ init_telemetry();
60439
60908
  init_tool();
60440
60909
  init_create_tool();
60441
60910
  import * as fs41 from "fs";
60442
- import * as path52 from "path";
60911
+ import * as path53 from "path";
60443
60912
 
60444
60913
  // src/tools/symbols.ts
60445
60914
  init_tool();
60446
60915
  init_create_tool();
60447
60916
  import * as fs40 from "fs";
60448
- import * as path51 from "path";
60917
+ import * as path52 from "path";
60449
60918
  var MAX_FILE_SIZE_BYTES2 = 1024 * 1024;
60450
60919
  var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
60451
60920
  function containsWindowsAttacks(str) {
@@ -60462,11 +60931,11 @@ function containsWindowsAttacks(str) {
60462
60931
  }
60463
60932
  function isPathInWorkspace(filePath, workspace) {
60464
60933
  try {
60465
- const resolvedPath = path51.resolve(workspace, filePath);
60934
+ const resolvedPath = path52.resolve(workspace, filePath);
60466
60935
  const realWorkspace = fs40.realpathSync(workspace);
60467
60936
  const realResolvedPath = fs40.realpathSync(resolvedPath);
60468
- const relativePath = path51.relative(realWorkspace, realResolvedPath);
60469
- if (relativePath.startsWith("..") || path51.isAbsolute(relativePath)) {
60937
+ const relativePath = path52.relative(realWorkspace, realResolvedPath);
60938
+ if (relativePath.startsWith("..") || path52.isAbsolute(relativePath)) {
60470
60939
  return false;
60471
60940
  }
60472
60941
  return true;
@@ -60478,7 +60947,7 @@ function validatePathForRead(filePath, workspace) {
60478
60947
  return isPathInWorkspace(filePath, workspace);
60479
60948
  }
60480
60949
  function extractTSSymbols(filePath, cwd) {
60481
- const fullPath = path51.join(cwd, filePath);
60950
+ const fullPath = path52.join(cwd, filePath);
60482
60951
  if (!validatePathForRead(fullPath, cwd)) {
60483
60952
  return [];
60484
60953
  }
@@ -60630,7 +61099,7 @@ function extractTSSymbols(filePath, cwd) {
60630
61099
  });
60631
61100
  }
60632
61101
  function extractPythonSymbols(filePath, cwd) {
60633
- const fullPath = path51.join(cwd, filePath);
61102
+ const fullPath = path52.join(cwd, filePath);
60634
61103
  if (!validatePathForRead(fullPath, cwd)) {
60635
61104
  return [];
60636
61105
  }
@@ -60713,7 +61182,7 @@ var symbols = createSwarmTool({
60713
61182
  }, null, 2);
60714
61183
  }
60715
61184
  const cwd = directory;
60716
- const ext = path51.extname(file3);
61185
+ const ext = path52.extname(file3);
60717
61186
  if (containsControlChars(file3)) {
60718
61187
  return JSON.stringify({
60719
61188
  file: file3,
@@ -60789,14 +61258,14 @@ function containsWindowsAttacks2(str) {
60789
61258
  }
60790
61259
  function isPathInWorkspace2(filePath, workspace) {
60791
61260
  try {
60792
- const resolvedPath = path52.resolve(workspace, filePath);
61261
+ const resolvedPath = path53.resolve(workspace, filePath);
60793
61262
  if (!fs41.existsSync(resolvedPath)) {
60794
61263
  return true;
60795
61264
  }
60796
61265
  const realWorkspace = fs41.realpathSync(workspace);
60797
61266
  const realResolvedPath = fs41.realpathSync(resolvedPath);
60798
- const relativePath = path52.relative(realWorkspace, realResolvedPath);
60799
- if (relativePath.startsWith("..") || path52.isAbsolute(relativePath)) {
61267
+ const relativePath = path53.relative(realWorkspace, realResolvedPath);
61268
+ if (relativePath.startsWith("..") || path53.isAbsolute(relativePath)) {
60800
61269
  return false;
60801
61270
  }
60802
61271
  return true;
@@ -60805,7 +61274,7 @@ function isPathInWorkspace2(filePath, workspace) {
60805
61274
  }
60806
61275
  }
60807
61276
  function processFile(file3, cwd, exportedOnly) {
60808
- const ext = path52.extname(file3);
61277
+ const ext = path53.extname(file3);
60809
61278
  if (containsControlChars(file3)) {
60810
61279
  return {
60811
61280
  file: file3,
@@ -60838,7 +61307,7 @@ function processFile(file3, cwd, exportedOnly) {
60838
61307
  errorType: "path-outside-workspace"
60839
61308
  };
60840
61309
  }
60841
- const fullPath = path52.join(cwd, file3);
61310
+ const fullPath = path53.join(cwd, file3);
60842
61311
  if (!fs41.existsSync(fullPath)) {
60843
61312
  return {
60844
61313
  file: file3,
@@ -61129,7 +61598,7 @@ init_manager();
61129
61598
  init_create_tool();
61130
61599
  init_resolve_working_directory();
61131
61600
  import * as fs42 from "fs";
61132
- import * as path53 from "path";
61601
+ import * as path54 from "path";
61133
61602
  var EVIDENCE_DIR = ".swarm/evidence";
61134
61603
  var TASK_ID_PATTERN2 = /^\d+\.\d+(\.\d+)*$/;
61135
61604
  function isValidTaskId3(taskId) {
@@ -61146,9 +61615,9 @@ function isValidTaskId3(taskId) {
61146
61615
  return TASK_ID_PATTERN2.test(taskId);
61147
61616
  }
61148
61617
  function isPathWithinSwarm(filePath, workspaceRoot) {
61149
- const normalizedWorkspace = path53.resolve(workspaceRoot);
61150
- const swarmPath = path53.join(normalizedWorkspace, ".swarm", "evidence");
61151
- 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);
61152
61621
  return normalizedPath.startsWith(swarmPath);
61153
61622
  }
61154
61623
  function readEvidenceFile(evidencePath) {
@@ -61229,7 +61698,7 @@ var check_gate_status = createSwarmTool({
61229
61698
  };
61230
61699
  return JSON.stringify(errorResult, null, 2);
61231
61700
  }
61232
- const evidencePath = path53.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
61701
+ const evidencePath = path54.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
61233
61702
  if (!isPathWithinSwarm(evidencePath, directory)) {
61234
61703
  const errorResult = {
61235
61704
  taskId: taskIdInput,
@@ -61326,7 +61795,7 @@ init_state();
61326
61795
  init_create_tool();
61327
61796
  init_resolve_working_directory();
61328
61797
  import * as fs43 from "fs";
61329
- import * as path54 from "path";
61798
+ import * as path55 from "path";
61330
61799
  function extractMatches(regex, text) {
61331
61800
  return Array.from(text.matchAll(regex));
61332
61801
  }
@@ -61478,10 +61947,10 @@ async function executeCompletionVerify(args2, directory) {
61478
61947
  let hasFileReadFailure = false;
61479
61948
  for (const filePath of fileTargets) {
61480
61949
  const normalizedPath = filePath.replace(/\\/g, "/");
61481
- const resolvedPath = path54.resolve(directory, normalizedPath);
61482
- const projectRoot = path54.resolve(directory);
61483
- const relative9 = path54.relative(projectRoot, resolvedPath);
61484
- 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);
61485
61954
  if (!withinProject) {
61486
61955
  blockedTasks.push({
61487
61956
  task_id: task.id,
@@ -61536,8 +62005,8 @@ async function executeCompletionVerify(args2, directory) {
61536
62005
  blockedTasks
61537
62006
  };
61538
62007
  try {
61539
- const evidenceDir = path54.join(directory, ".swarm", "evidence", `${phase}`);
61540
- 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");
61541
62010
  fs43.mkdirSync(evidenceDir, { recursive: true });
61542
62011
  const evidenceBundle = {
61543
62012
  schema_version: "1.0.0",
@@ -61614,11 +62083,11 @@ var completion_verify = createSwarmTool({
61614
62083
  // src/tools/complexity-hotspots.ts
61615
62084
  init_dist();
61616
62085
  import * as fs45 from "fs";
61617
- import * as path56 from "path";
62086
+ import * as path57 from "path";
61618
62087
 
61619
62088
  // src/quality/metrics.ts
61620
62089
  import * as fs44 from "fs";
61621
- import * as path55 from "path";
62090
+ import * as path56 from "path";
61622
62091
  var MAX_FILE_SIZE_BYTES3 = 256 * 1024;
61623
62092
  var MIN_DUPLICATION_LINES = 10;
61624
62093
  function estimateCyclomaticComplexity(content) {
@@ -61670,7 +62139,7 @@ async function computeComplexityDelta(files, workingDir) {
61670
62139
  let totalComplexity = 0;
61671
62140
  const analyzedFiles = [];
61672
62141
  for (const file3 of files) {
61673
- const fullPath = path55.isAbsolute(file3) ? file3 : path55.join(workingDir, file3);
62142
+ const fullPath = path56.isAbsolute(file3) ? file3 : path56.join(workingDir, file3);
61674
62143
  if (!fs44.existsSync(fullPath)) {
61675
62144
  continue;
61676
62145
  }
@@ -61793,7 +62262,7 @@ function countGoExports(content) {
61793
62262
  function getExportCountForFile(filePath) {
61794
62263
  try {
61795
62264
  const content = fs44.readFileSync(filePath, "utf-8");
61796
- const ext = path55.extname(filePath).toLowerCase();
62265
+ const ext = path56.extname(filePath).toLowerCase();
61797
62266
  switch (ext) {
61798
62267
  case ".ts":
61799
62268
  case ".tsx":
@@ -61819,7 +62288,7 @@ async function computePublicApiDelta(files, workingDir) {
61819
62288
  let totalExports = 0;
61820
62289
  const analyzedFiles = [];
61821
62290
  for (const file3 of files) {
61822
- const fullPath = path55.isAbsolute(file3) ? file3 : path55.join(workingDir, file3);
62291
+ const fullPath = path56.isAbsolute(file3) ? file3 : path56.join(workingDir, file3);
61823
62292
  if (!fs44.existsSync(fullPath)) {
61824
62293
  continue;
61825
62294
  }
@@ -61853,7 +62322,7 @@ async function computeDuplicationRatio(files, workingDir) {
61853
62322
  let duplicateLines = 0;
61854
62323
  const analyzedFiles = [];
61855
62324
  for (const file3 of files) {
61856
- const fullPath = path55.isAbsolute(file3) ? file3 : path55.join(workingDir, file3);
62325
+ const fullPath = path56.isAbsolute(file3) ? file3 : path56.join(workingDir, file3);
61857
62326
  if (!fs44.existsSync(fullPath)) {
61858
62327
  continue;
61859
62328
  }
@@ -61886,8 +62355,8 @@ function countCodeLines(content) {
61886
62355
  return lines.length;
61887
62356
  }
61888
62357
  function isTestFile(filePath) {
61889
- const basename8 = path55.basename(filePath);
61890
- const _ext = path55.extname(filePath).toLowerCase();
62358
+ const basename8 = path56.basename(filePath);
62359
+ const _ext = path56.extname(filePath).toLowerCase();
61891
62360
  const testPatterns = [
61892
62361
  ".test.",
61893
62362
  ".spec.",
@@ -61968,8 +62437,8 @@ function matchGlobSegment(globSegments, pathSegments) {
61968
62437
  }
61969
62438
  return gIndex === globSegments.length && pIndex === pathSegments.length;
61970
62439
  }
61971
- function matchesGlobSegment(path56, glob) {
61972
- const normalizedPath = path56.replace(/\\/g, "/");
62440
+ function matchesGlobSegment(path57, glob) {
62441
+ const normalizedPath = path57.replace(/\\/g, "/");
61973
62442
  const normalizedGlob = glob.replace(/\\/g, "/");
61974
62443
  if (normalizedPath.includes("//")) {
61975
62444
  return false;
@@ -62000,8 +62469,8 @@ function simpleGlobToRegex2(glob) {
62000
62469
  function hasGlobstar(glob) {
62001
62470
  return glob.includes("**");
62002
62471
  }
62003
- function globMatches(path56, glob) {
62004
- const normalizedPath = path56.replace(/\\/g, "/");
62472
+ function globMatches(path57, glob) {
62473
+ const normalizedPath = path57.replace(/\\/g, "/");
62005
62474
  if (!glob || glob === "") {
62006
62475
  if (normalizedPath.includes("//")) {
62007
62476
  return false;
@@ -62037,7 +62506,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
62037
62506
  async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
62038
62507
  let testLines = 0;
62039
62508
  let codeLines = 0;
62040
- const srcDir = path55.join(workingDir, "src");
62509
+ const srcDir = path56.join(workingDir, "src");
62041
62510
  if (fs44.existsSync(srcDir)) {
62042
62511
  await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
62043
62512
  codeLines += lines;
@@ -62045,14 +62514,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
62045
62514
  }
62046
62515
  const possibleSrcDirs = ["lib", "app", "source", "core"];
62047
62516
  for (const dir of possibleSrcDirs) {
62048
- const dirPath = path55.join(workingDir, dir);
62517
+ const dirPath = path56.join(workingDir, dir);
62049
62518
  if (fs44.existsSync(dirPath)) {
62050
62519
  await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
62051
62520
  codeLines += lines;
62052
62521
  });
62053
62522
  }
62054
62523
  }
62055
- const testsDir = path55.join(workingDir, "tests");
62524
+ const testsDir = path56.join(workingDir, "tests");
62056
62525
  if (fs44.existsSync(testsDir)) {
62057
62526
  await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
62058
62527
  testLines += lines;
@@ -62060,7 +62529,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
62060
62529
  }
62061
62530
  const possibleTestDirs = ["test", "__tests__", "specs"];
62062
62531
  for (const dir of possibleTestDirs) {
62063
- const dirPath = path55.join(workingDir, dir);
62532
+ const dirPath = path56.join(workingDir, dir);
62064
62533
  if (fs44.existsSync(dirPath) && dirPath !== testsDir) {
62065
62534
  await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
62066
62535
  testLines += lines;
@@ -62075,7 +62544,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
62075
62544
  try {
62076
62545
  const entries = fs44.readdirSync(dirPath, { withFileTypes: true });
62077
62546
  for (const entry of entries) {
62078
- const fullPath = path55.join(dirPath, entry.name);
62547
+ const fullPath = path56.join(dirPath, entry.name);
62079
62548
  if (entry.isDirectory()) {
62080
62549
  if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
62081
62550
  continue;
@@ -62083,7 +62552,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
62083
62552
  await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
62084
62553
  } else if (entry.isFile()) {
62085
62554
  const relativePath = fullPath.replace(`${dirPath}/`, "");
62086
- const ext = path55.extname(entry.name).toLowerCase();
62555
+ const ext = path56.extname(entry.name).toLowerCase();
62087
62556
  const validExts = [
62088
62557
  ".ts",
62089
62558
  ".tsx",
@@ -62335,7 +62804,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
62335
62804
  const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
62336
62805
  const filteredChurn = new Map;
62337
62806
  for (const [file3, count] of churnMap) {
62338
- const ext = path56.extname(file3).toLowerCase();
62807
+ const ext = path57.extname(file3).toLowerCase();
62339
62808
  if (extSet.has(ext)) {
62340
62809
  filteredChurn.set(file3, count);
62341
62810
  }
@@ -62346,7 +62815,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
62346
62815
  for (const [file3, churnCount] of filteredChurn) {
62347
62816
  let fullPath = file3;
62348
62817
  if (!fs45.existsSync(fullPath)) {
62349
- fullPath = path56.join(cwd, file3);
62818
+ fullPath = path57.join(cwd, file3);
62350
62819
  }
62351
62820
  const complexity = getComplexityForFile2(fullPath);
62352
62821
  if (complexity !== null) {
@@ -62613,7 +63082,7 @@ init_tool();
62613
63082
  init_state();
62614
63083
  init_create_tool();
62615
63084
  import * as fs46 from "fs";
62616
- import * as path57 from "path";
63085
+ import * as path58 from "path";
62617
63086
  function validateTaskIdFormat(taskId) {
62618
63087
  const taskIdPattern = /^\d+\.\d+(\.\d+)*$/;
62619
63088
  if (!taskIdPattern.test(taskId)) {
@@ -62691,8 +63160,8 @@ async function executeDeclareScope(args2, fallbackDir) {
62691
63160
  };
62692
63161
  }
62693
63162
  }
62694
- normalizedDir = path57.normalize(args2.working_directory);
62695
- const pathParts = normalizedDir.split(path57.sep);
63163
+ normalizedDir = path58.normalize(args2.working_directory);
63164
+ const pathParts = normalizedDir.split(path58.sep);
62696
63165
  if (pathParts.includes("..")) {
62697
63166
  return {
62698
63167
  success: false,
@@ -62702,10 +63171,10 @@ async function executeDeclareScope(args2, fallbackDir) {
62702
63171
  ]
62703
63172
  };
62704
63173
  }
62705
- const resolvedDir = path57.resolve(normalizedDir);
63174
+ const resolvedDir = path58.resolve(normalizedDir);
62706
63175
  try {
62707
63176
  const realPath = fs46.realpathSync(resolvedDir);
62708
- const planPath2 = path57.join(realPath, ".swarm", "plan.json");
63177
+ const planPath2 = path58.join(realPath, ".swarm", "plan.json");
62709
63178
  if (!fs46.existsSync(planPath2)) {
62710
63179
  return {
62711
63180
  success: false,
@@ -62729,7 +63198,7 @@ async function executeDeclareScope(args2, fallbackDir) {
62729
63198
  console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
62730
63199
  }
62731
63200
  const directory = normalizedDir || fallbackDir;
62732
- const planPath = path57.resolve(directory, ".swarm", "plan.json");
63201
+ const planPath = path58.resolve(directory, ".swarm", "plan.json");
62733
63202
  if (!fs46.existsSync(planPath)) {
62734
63203
  return {
62735
63204
  success: false,
@@ -62771,8 +63240,8 @@ async function executeDeclareScope(args2, fallbackDir) {
62771
63240
  const normalizeErrors = [];
62772
63241
  const dir = normalizedDir || fallbackDir || process.cwd();
62773
63242
  const mergedFiles = rawMergedFiles.map((file3) => {
62774
- if (path57.isAbsolute(file3)) {
62775
- const relativePath = path57.relative(dir, file3).replace(/\\/g, "/");
63243
+ if (path58.isAbsolute(file3)) {
63244
+ const relativePath = path58.relative(dir, file3).replace(/\\/g, "/");
62776
63245
  if (relativePath.startsWith("..")) {
62777
63246
  normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
62778
63247
  return file3;
@@ -63111,20 +63580,20 @@ function validateBase(base) {
63111
63580
  function validatePaths(paths) {
63112
63581
  if (!paths)
63113
63582
  return null;
63114
- for (const path59 of paths) {
63115
- if (!path59 || path59.length === 0) {
63583
+ for (const path60 of paths) {
63584
+ if (!path60 || path60.length === 0) {
63116
63585
  return "empty path not allowed";
63117
63586
  }
63118
- if (path59.length > MAX_PATH_LENGTH) {
63587
+ if (path60.length > MAX_PATH_LENGTH) {
63119
63588
  return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
63120
63589
  }
63121
- if (SHELL_METACHARACTERS2.test(path59)) {
63590
+ if (SHELL_METACHARACTERS2.test(path60)) {
63122
63591
  return "path contains shell metacharacters";
63123
63592
  }
63124
- if (path59.startsWith("-")) {
63593
+ if (path60.startsWith("-")) {
63125
63594
  return 'path cannot start with "-" (option-like arguments not allowed)';
63126
63595
  }
63127
- if (CONTROL_CHAR_PATTERN2.test(path59)) {
63596
+ if (CONTROL_CHAR_PATTERN2.test(path60)) {
63128
63597
  return "path contains control characters";
63129
63598
  }
63130
63599
  }
@@ -63205,8 +63674,8 @@ var diff = createSwarmTool({
63205
63674
  if (parts2.length >= 3) {
63206
63675
  const additions = parseInt(parts2[0], 10) || 0;
63207
63676
  const deletions = parseInt(parts2[1], 10) || 0;
63208
- const path59 = parts2[2];
63209
- files.push({ path: path59, additions, deletions });
63677
+ const path60 = parts2[2];
63678
+ files.push({ path: path60, additions, deletions });
63210
63679
  }
63211
63680
  }
63212
63681
  const contractChanges = [];
@@ -63489,7 +63958,7 @@ Use these as DOMAIN values when delegating to @sme.`;
63489
63958
  init_dist();
63490
63959
  init_create_tool();
63491
63960
  import * as fs47 from "fs";
63492
- import * as path59 from "path";
63961
+ import * as path60 from "path";
63493
63962
  var MAX_FILE_SIZE_BYTES5 = 1024 * 1024;
63494
63963
  var MAX_EVIDENCE_FILES = 1000;
63495
63964
  var EVIDENCE_DIR2 = ".swarm/evidence";
@@ -63516,9 +63985,9 @@ function validateRequiredTypes(input) {
63516
63985
  return null;
63517
63986
  }
63518
63987
  function isPathWithinSwarm2(filePath, cwd) {
63519
- const normalizedCwd = path59.resolve(cwd);
63520
- const swarmPath = path59.join(normalizedCwd, ".swarm");
63521
- const normalizedPath = path59.resolve(filePath);
63988
+ const normalizedCwd = path60.resolve(cwd);
63989
+ const swarmPath = path60.join(normalizedCwd, ".swarm");
63990
+ const normalizedPath = path60.resolve(filePath);
63522
63991
  return normalizedPath.startsWith(swarmPath);
63523
63992
  }
63524
63993
  function parseCompletedTasks(planContent) {
@@ -63548,10 +64017,10 @@ function readEvidenceFiles(evidenceDir, _cwd) {
63548
64017
  if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
63549
64018
  continue;
63550
64019
  }
63551
- const filePath = path59.join(evidenceDir, filename);
64020
+ const filePath = path60.join(evidenceDir, filename);
63552
64021
  try {
63553
- const resolvedPath = path59.resolve(filePath);
63554
- const evidenceDirResolved = path59.resolve(evidenceDir);
64022
+ const resolvedPath = path60.resolve(filePath);
64023
+ const evidenceDirResolved = path60.resolve(evidenceDir);
63555
64024
  if (!resolvedPath.startsWith(evidenceDirResolved)) {
63556
64025
  continue;
63557
64026
  }
@@ -63669,7 +64138,7 @@ var evidence_check = createSwarmTool({
63669
64138
  return JSON.stringify(errorResult, null, 2);
63670
64139
  }
63671
64140
  const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
63672
- const planPath = path59.join(cwd, PLAN_FILE);
64141
+ const planPath = path60.join(cwd, PLAN_FILE);
63673
64142
  if (!isPathWithinSwarm2(planPath, cwd)) {
63674
64143
  const errorResult = {
63675
64144
  error: "plan file path validation failed",
@@ -63701,7 +64170,7 @@ var evidence_check = createSwarmTool({
63701
64170
  };
63702
64171
  return JSON.stringify(result2, null, 2);
63703
64172
  }
63704
- const evidenceDir = path59.join(cwd, EVIDENCE_DIR2);
64173
+ const evidenceDir = path60.join(cwd, EVIDENCE_DIR2);
63705
64174
  const evidence = readEvidenceFiles(evidenceDir, cwd);
63706
64175
  const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
63707
64176
  const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
@@ -63719,7 +64188,7 @@ var evidence_check = createSwarmTool({
63719
64188
  init_tool();
63720
64189
  init_create_tool();
63721
64190
  import * as fs48 from "fs";
63722
- import * as path60 from "path";
64191
+ import * as path61 from "path";
63723
64192
  var EXT_MAP = {
63724
64193
  python: ".py",
63725
64194
  py: ".py",
@@ -63800,12 +64269,12 @@ var extract_code_blocks = createSwarmTool({
63800
64269
  if (prefix) {
63801
64270
  filename = `${prefix}_${filename}`;
63802
64271
  }
63803
- let filepath = path60.join(targetDir, filename);
63804
- const base = path60.basename(filepath, path60.extname(filepath));
63805
- 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);
63806
64275
  let counter = 1;
63807
64276
  while (fs48.existsSync(filepath)) {
63808
- filepath = path60.join(targetDir, `${base}_${counter}${ext}`);
64277
+ filepath = path61.join(targetDir, `${base}_${counter}${ext}`);
63809
64278
  counter++;
63810
64279
  }
63811
64280
  try {
@@ -63926,7 +64395,7 @@ var gitingest = createSwarmTool({
63926
64395
  init_dist();
63927
64396
  init_create_tool();
63928
64397
  import * as fs49 from "fs";
63929
- import * as path61 from "path";
64398
+ import * as path62 from "path";
63930
64399
  var MAX_FILE_PATH_LENGTH2 = 500;
63931
64400
  var MAX_SYMBOL_LENGTH = 256;
63932
64401
  var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
@@ -63974,7 +64443,7 @@ function validateSymbolInput(symbol3) {
63974
64443
  return null;
63975
64444
  }
63976
64445
  function isBinaryFile2(filePath, buffer) {
63977
- const ext = path61.extname(filePath).toLowerCase();
64446
+ const ext = path62.extname(filePath).toLowerCase();
63978
64447
  if (ext === ".json" || ext === ".md" || ext === ".txt") {
63979
64448
  return false;
63980
64449
  }
@@ -63998,15 +64467,15 @@ function parseImports(content, targetFile, targetSymbol) {
63998
64467
  const imports = [];
63999
64468
  let _resolvedTarget;
64000
64469
  try {
64001
- _resolvedTarget = path61.resolve(targetFile);
64470
+ _resolvedTarget = path62.resolve(targetFile);
64002
64471
  } catch {
64003
64472
  _resolvedTarget = targetFile;
64004
64473
  }
64005
- const targetBasename = path61.basename(targetFile, path61.extname(targetFile));
64474
+ const targetBasename = path62.basename(targetFile, path62.extname(targetFile));
64006
64475
  const targetWithExt = targetFile;
64007
64476
  const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
64008
- const normalizedTargetWithExt = path61.normalize(targetWithExt).replace(/\\/g, "/");
64009
- const normalizedTargetWithoutExt = path61.normalize(targetWithoutExt).replace(/\\/g, "/");
64477
+ const normalizedTargetWithExt = path62.normalize(targetWithExt).replace(/\\/g, "/");
64478
+ const normalizedTargetWithoutExt = path62.normalize(targetWithoutExt).replace(/\\/g, "/");
64010
64479
  const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
64011
64480
  for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
64012
64481
  const modulePath = match[1] || match[2] || match[3];
@@ -64029,9 +64498,9 @@ function parseImports(content, targetFile, targetSymbol) {
64029
64498
  }
64030
64499
  const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
64031
64500
  let isMatch = false;
64032
- const _targetDir = path61.dirname(targetFile);
64033
- const targetExt = path61.extname(targetFile);
64034
- 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);
64035
64504
  const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
64036
64505
  const moduleName = modulePath.split(/[/\\]/).pop() || "";
64037
64506
  const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
@@ -64099,10 +64568,10 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
64099
64568
  entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
64100
64569
  for (const entry of entries) {
64101
64570
  if (SKIP_DIRECTORIES3.has(entry)) {
64102
- stats.skippedDirs.push(path61.join(dir, entry));
64571
+ stats.skippedDirs.push(path62.join(dir, entry));
64103
64572
  continue;
64104
64573
  }
64105
- const fullPath = path61.join(dir, entry);
64574
+ const fullPath = path62.join(dir, entry);
64106
64575
  let stat2;
64107
64576
  try {
64108
64577
  stat2 = fs49.statSync(fullPath);
@@ -64116,7 +64585,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
64116
64585
  if (stat2.isDirectory()) {
64117
64586
  findSourceFiles(fullPath, files, stats);
64118
64587
  } else if (stat2.isFile()) {
64119
- const ext = path61.extname(fullPath).toLowerCase();
64588
+ const ext = path62.extname(fullPath).toLowerCase();
64120
64589
  if (SUPPORTED_EXTENSIONS.includes(ext)) {
64121
64590
  files.push(fullPath);
64122
64591
  }
@@ -64173,7 +64642,7 @@ var imports = createSwarmTool({
64173
64642
  return JSON.stringify(errorResult, null, 2);
64174
64643
  }
64175
64644
  try {
64176
- const targetFile = path61.resolve(file3);
64645
+ const targetFile = path62.resolve(file3);
64177
64646
  if (!fs49.existsSync(targetFile)) {
64178
64647
  const errorResult = {
64179
64648
  error: `target file not found: ${file3}`,
@@ -64195,7 +64664,7 @@ var imports = createSwarmTool({
64195
64664
  };
64196
64665
  return JSON.stringify(errorResult, null, 2);
64197
64666
  }
64198
- const baseDir = path61.dirname(targetFile);
64667
+ const baseDir = path62.dirname(targetFile);
64199
64668
  const scanStats = {
64200
64669
  skippedDirs: [],
64201
64670
  skippedFiles: 0,
@@ -64296,7 +64765,7 @@ var VALID_CATEGORIES2 = [
64296
64765
  "integration",
64297
64766
  "other"
64298
64767
  ];
64299
- var knowledgeAdd = createSwarmTool({
64768
+ var knowledge_add = createSwarmTool({
64300
64769
  description: "Store a new lesson in the knowledge base for future reference. The lesson will be available for retrieval via knowledge_recall.",
64301
64770
  args: {
64302
64771
  lesson: tool.schema.string().min(15).max(280).describe("The lesson to store (15-280 characters)"),
@@ -64656,7 +65125,7 @@ var knowledge_query = createSwarmTool({
64656
65125
  init_dist();
64657
65126
  init_knowledge_store();
64658
65127
  init_create_tool();
64659
- var knowledgeRecall = createSwarmTool({
65128
+ var knowledge_recall = createSwarmTool({
64660
65129
  description: "Search the knowledge base for relevant past decisions, patterns, and lessons learned. Returns ranked results by semantic similarity.",
64661
65130
  args: {
64662
65131
  query: tool.schema.string().min(3).describe("Natural language search query"),
@@ -64740,7 +65209,7 @@ var knowledgeRecall = createSwarmTool({
64740
65209
  init_dist();
64741
65210
  init_knowledge_store();
64742
65211
  init_create_tool();
64743
- var knowledgeRemove = createSwarmTool({
65212
+ var knowledge_remove = createSwarmTool({
64744
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.",
64745
65214
  args: {
64746
65215
  id: tool.schema.string().min(1).describe("UUID of the knowledge entry to remove")
@@ -64805,7 +65274,7 @@ init_config();
64805
65274
  init_schema();
64806
65275
  init_manager();
64807
65276
  import * as fs50 from "fs";
64808
- import * as path62 from "path";
65277
+ import * as path63 from "path";
64809
65278
  init_review_receipt();
64810
65279
  init_utils2();
64811
65280
  init_ledger();
@@ -65030,7 +65499,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
65030
65499
  safeWarn(`[phase_complete] Completion verify error (non-blocking):`, completionError);
65031
65500
  }
65032
65501
  try {
65033
- 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");
65034
65503
  let driftVerdictFound = false;
65035
65504
  let driftVerdictApproved = false;
65036
65505
  try {
@@ -65064,7 +65533,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
65064
65533
  driftVerdictFound = false;
65065
65534
  }
65066
65535
  if (!driftVerdictFound) {
65067
- const specPath = path62.join(dir, ".swarm", "spec.md");
65536
+ const specPath = path63.join(dir, ".swarm", "spec.md");
65068
65537
  const specExists = fs50.existsSync(specPath);
65069
65538
  if (!specExists) {
65070
65539
  let incompleteTaskCount = 0;
@@ -65116,7 +65585,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
65116
65585
  const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
65117
65586
  if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
65118
65587
  try {
65119
- const projectName = path62.basename(dir);
65588
+ const projectName = path63.basename(dir);
65120
65589
  const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
65121
65590
  if (curationResult) {
65122
65591
  const sessionState = swarmState.agentSessions.get(sessionID);
@@ -65463,7 +65932,7 @@ init_discovery();
65463
65932
  init_utils();
65464
65933
  init_create_tool();
65465
65934
  import * as fs51 from "fs";
65466
- import * as path63 from "path";
65935
+ import * as path64 from "path";
65467
65936
  var MAX_OUTPUT_BYTES5 = 52428800;
65468
65937
  var AUDIT_TIMEOUT_MS = 120000;
65469
65938
  function isValidEcosystem(value) {
@@ -65491,16 +65960,16 @@ function validateArgs3(args2) {
65491
65960
  function detectEcosystems(directory) {
65492
65961
  const ecosystems = [];
65493
65962
  const cwd = directory;
65494
- if (fs51.existsSync(path63.join(cwd, "package.json"))) {
65963
+ if (fs51.existsSync(path64.join(cwd, "package.json"))) {
65495
65964
  ecosystems.push("npm");
65496
65965
  }
65497
- 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"))) {
65498
65967
  ecosystems.push("pip");
65499
65968
  }
65500
- if (fs51.existsSync(path63.join(cwd, "Cargo.toml"))) {
65969
+ if (fs51.existsSync(path64.join(cwd, "Cargo.toml"))) {
65501
65970
  ecosystems.push("cargo");
65502
65971
  }
65503
- if (fs51.existsSync(path63.join(cwd, "go.mod"))) {
65972
+ if (fs51.existsSync(path64.join(cwd, "go.mod"))) {
65504
65973
  ecosystems.push("go");
65505
65974
  }
65506
65975
  try {
@@ -65509,13 +65978,13 @@ function detectEcosystems(directory) {
65509
65978
  ecosystems.push("dotnet");
65510
65979
  }
65511
65980
  } catch {}
65512
- 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"))) {
65513
65982
  ecosystems.push("ruby");
65514
65983
  }
65515
- if (fs51.existsSync(path63.join(cwd, "pubspec.yaml"))) {
65984
+ if (fs51.existsSync(path64.join(cwd, "pubspec.yaml"))) {
65516
65985
  ecosystems.push("dart");
65517
65986
  }
65518
- if (fs51.existsSync(path63.join(cwd, "composer.lock"))) {
65987
+ if (fs51.existsSync(path64.join(cwd, "composer.lock"))) {
65519
65988
  ecosystems.push("composer");
65520
65989
  }
65521
65990
  return ecosystems;
@@ -66675,7 +67144,7 @@ var pkg_audit = createSwarmTool({
66675
67144
  init_dist();
66676
67145
  init_manager();
66677
67146
  import * as fs52 from "fs";
66678
- import * as path64 from "path";
67147
+ import * as path65 from "path";
66679
67148
  init_utils();
66680
67149
  init_create_tool();
66681
67150
  var MAX_FILE_SIZE = 1024 * 1024;
@@ -66794,7 +67263,7 @@ function isScaffoldFile(filePath) {
66794
67263
  if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
66795
67264
  return true;
66796
67265
  }
66797
- const filename = path64.basename(filePath);
67266
+ const filename = path65.basename(filePath);
66798
67267
  if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
66799
67268
  return true;
66800
67269
  }
@@ -66811,7 +67280,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
66811
67280
  if (regex.test(normalizedPath)) {
66812
67281
  return true;
66813
67282
  }
66814
- const filename = path64.basename(filePath);
67283
+ const filename = path65.basename(filePath);
66815
67284
  const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
66816
67285
  if (filenameRegex.test(filename)) {
66817
67286
  return true;
@@ -66820,7 +67289,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
66820
67289
  return false;
66821
67290
  }
66822
67291
  function isParserSupported(filePath) {
66823
- const ext = path64.extname(filePath).toLowerCase();
67292
+ const ext = path65.extname(filePath).toLowerCase();
66824
67293
  return SUPPORTED_PARSER_EXTENSIONS.has(ext);
66825
67294
  }
66826
67295
  function isPlanFile(filePath) {
@@ -67004,9 +67473,9 @@ async function placeholderScan(input, directory) {
67004
67473
  let filesScanned = 0;
67005
67474
  const filesWithFindings = new Set;
67006
67475
  for (const filePath of changed_files) {
67007
- const fullPath = path64.isAbsolute(filePath) ? filePath : path64.resolve(directory, filePath);
67008
- const resolvedDirectory = path64.resolve(directory);
67009
- 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) {
67010
67479
  continue;
67011
67480
  }
67012
67481
  if (!fs52.existsSync(fullPath)) {
@@ -67084,7 +67553,7 @@ var placeholder_scan = createSwarmTool({
67084
67553
  // src/tools/pre-check-batch.ts
67085
67554
  init_dist();
67086
67555
  import * as fs54 from "fs";
67087
- import * as path66 from "path";
67556
+ import * as path67 from "path";
67088
67557
 
67089
67558
  // node_modules/yocto-queue/index.js
67090
67559
  class Node2 {
@@ -67378,7 +67847,7 @@ init_dist();
67378
67847
  init_manager();
67379
67848
  init_detector();
67380
67849
  import * as fs53 from "fs";
67381
- import * as path65 from "path";
67850
+ import * as path66 from "path";
67382
67851
  import { extname as extname14 } from "path";
67383
67852
 
67384
67853
  // src/sast/rules/c.ts
@@ -68374,9 +68843,9 @@ async function sastScan(input, directory, config3) {
68374
68843
  _filesSkipped++;
68375
68844
  continue;
68376
68845
  }
68377
- const resolvedPath = path65.isAbsolute(filePath) ? filePath : path65.resolve(directory, filePath);
68378
- const resolvedDirectory = path65.resolve(directory);
68379
- 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) {
68380
68849
  _filesSkipped++;
68381
68850
  continue;
68382
68851
  }
@@ -68578,18 +69047,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
68578
69047
  let resolved;
68579
69048
  const isWinAbs = isWindowsAbsolutePath(inputPath);
68580
69049
  if (isWinAbs) {
68581
- resolved = path66.win32.resolve(inputPath);
68582
- } else if (path66.isAbsolute(inputPath)) {
68583
- resolved = path66.resolve(inputPath);
69050
+ resolved = path67.win32.resolve(inputPath);
69051
+ } else if (path67.isAbsolute(inputPath)) {
69052
+ resolved = path67.resolve(inputPath);
68584
69053
  } else {
68585
- resolved = path66.resolve(baseDir, inputPath);
69054
+ resolved = path67.resolve(baseDir, inputPath);
68586
69055
  }
68587
- const workspaceResolved = path66.resolve(workspaceDir);
69056
+ const workspaceResolved = path67.resolve(workspaceDir);
68588
69057
  let relative11;
68589
69058
  if (isWinAbs) {
68590
- relative11 = path66.win32.relative(workspaceResolved, resolved);
69059
+ relative11 = path67.win32.relative(workspaceResolved, resolved);
68591
69060
  } else {
68592
- relative11 = path66.relative(workspaceResolved, resolved);
69061
+ relative11 = path67.relative(workspaceResolved, resolved);
68593
69062
  }
68594
69063
  if (relative11.startsWith("..")) {
68595
69064
  return "path traversal detected";
@@ -68654,7 +69123,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
68654
69123
  if (typeof file3 !== "string") {
68655
69124
  continue;
68656
69125
  }
68657
- const resolvedPath = path66.resolve(file3);
69126
+ const resolvedPath = path67.resolve(file3);
68658
69127
  const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
68659
69128
  if (validationError) {
68660
69129
  continue;
@@ -68811,7 +69280,7 @@ async function runSecretscanWithFiles(files, directory) {
68811
69280
  skippedFiles++;
68812
69281
  continue;
68813
69282
  }
68814
- const resolvedPath = path66.resolve(file3);
69283
+ const resolvedPath = path67.resolve(file3);
68815
69284
  const validationError = validatePath(resolvedPath, directory, directory);
68816
69285
  if (validationError) {
68817
69286
  skippedFiles++;
@@ -68829,7 +69298,7 @@ async function runSecretscanWithFiles(files, directory) {
68829
69298
  };
68830
69299
  }
68831
69300
  for (const file3 of validatedFiles) {
68832
- const ext = path66.extname(file3).toLowerCase();
69301
+ const ext = path67.extname(file3).toLowerCase();
68833
69302
  if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
68834
69303
  skippedFiles++;
68835
69304
  continue;
@@ -69035,7 +69504,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
69035
69504
  const preexistingFindings = [];
69036
69505
  for (const finding of findings) {
69037
69506
  const filePath = finding.location.file;
69038
- const normalised = path66.relative(directory, filePath).replace(/\\/g, "/");
69507
+ const normalised = path67.relative(directory, filePath).replace(/\\/g, "/");
69039
69508
  const changedLines = changedLineRanges.get(normalised);
69040
69509
  if (changedLines && changedLines.has(finding.location.line)) {
69041
69510
  newFindings.push(finding);
@@ -69086,7 +69555,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
69086
69555
  warn(`pre_check_batch: Invalid file path: ${file3}`);
69087
69556
  continue;
69088
69557
  }
69089
- changedFiles.push(path66.resolve(directory, file3));
69558
+ changedFiles.push(path67.resolve(directory, file3));
69090
69559
  }
69091
69560
  if (changedFiles.length === 0) {
69092
69561
  warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
@@ -69274,7 +69743,7 @@ var pre_check_batch = createSwarmTool({
69274
69743
  };
69275
69744
  return JSON.stringify(errorResult, null, 2);
69276
69745
  }
69277
- const resolvedDirectory = path66.resolve(typedArgs.directory);
69746
+ const resolvedDirectory = path67.resolve(typedArgs.directory);
69278
69747
  const workspaceAnchor = resolvedDirectory;
69279
69748
  const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
69280
69749
  if (dirError) {
@@ -69381,7 +69850,7 @@ ${paginatedContent}`;
69381
69850
  // src/tools/save-plan.ts
69382
69851
  init_tool();
69383
69852
  import * as fs55 from "fs";
69384
- import * as path67 from "path";
69853
+ import * as path68 from "path";
69385
69854
  init_ledger();
69386
69855
  init_manager2();
69387
69856
  init_state();
@@ -69519,7 +69988,7 @@ async function executeSavePlan(args2, fallbackDir) {
69519
69988
  }
69520
69989
  await writeCheckpoint(dir).catch(() => {});
69521
69990
  try {
69522
- const markerPath = path67.join(dir, ".swarm", ".plan-write-marker");
69991
+ const markerPath = path68.join(dir, ".swarm", ".plan-write-marker");
69523
69992
  const marker = JSON.stringify({
69524
69993
  source: "save_plan",
69525
69994
  timestamp: new Date().toISOString(),
@@ -69542,7 +70011,7 @@ async function executeSavePlan(args2, fallbackDir) {
69542
70011
  return {
69543
70012
  success: true,
69544
70013
  message: "Plan saved successfully",
69545
- plan_path: path67.join(dir, ".swarm", "plan.json"),
70014
+ plan_path: path68.join(dir, ".swarm", "plan.json"),
69546
70015
  phases_count: plan.phases.length,
69547
70016
  tasks_count: tasksCount,
69548
70017
  ...warnings.length > 0 ? { warnings } : {}
@@ -69587,7 +70056,7 @@ var save_plan = createSwarmTool({
69587
70056
  init_dist();
69588
70057
  init_manager();
69589
70058
  import * as fs56 from "fs";
69590
- import * as path68 from "path";
70059
+ import * as path69 from "path";
69591
70060
 
69592
70061
  // src/sbom/detectors/index.ts
69593
70062
  init_utils();
@@ -70437,7 +70906,7 @@ function findManifestFiles(rootDir) {
70437
70906
  try {
70438
70907
  const entries = fs56.readdirSync(dir, { withFileTypes: true });
70439
70908
  for (const entry of entries) {
70440
- const fullPath = path68.join(dir, entry.name);
70909
+ const fullPath = path69.join(dir, entry.name);
70441
70910
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
70442
70911
  continue;
70443
70912
  }
@@ -70446,7 +70915,7 @@ function findManifestFiles(rootDir) {
70446
70915
  } else if (entry.isFile()) {
70447
70916
  for (const pattern of patterns) {
70448
70917
  if (simpleGlobToRegex(pattern).test(entry.name)) {
70449
- manifestFiles.push(path68.relative(rootDir, fullPath));
70918
+ manifestFiles.push(path69.relative(rootDir, fullPath));
70450
70919
  break;
70451
70920
  }
70452
70921
  }
@@ -70464,11 +70933,11 @@ function findManifestFilesInDirs(directories, workingDir) {
70464
70933
  try {
70465
70934
  const entries = fs56.readdirSync(dir, { withFileTypes: true });
70466
70935
  for (const entry of entries) {
70467
- const fullPath = path68.join(dir, entry.name);
70936
+ const fullPath = path69.join(dir, entry.name);
70468
70937
  if (entry.isFile()) {
70469
70938
  for (const pattern of patterns) {
70470
70939
  if (simpleGlobToRegex(pattern).test(entry.name)) {
70471
- found.push(path68.relative(workingDir, fullPath));
70940
+ found.push(path69.relative(workingDir, fullPath));
70472
70941
  break;
70473
70942
  }
70474
70943
  }
@@ -70481,11 +70950,11 @@ function findManifestFilesInDirs(directories, workingDir) {
70481
70950
  function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
70482
70951
  const dirs = new Set;
70483
70952
  for (const file3 of changedFiles) {
70484
- let currentDir = path68.dirname(file3);
70953
+ let currentDir = path69.dirname(file3);
70485
70954
  while (true) {
70486
- if (currentDir && currentDir !== "." && currentDir !== path68.sep) {
70487
- dirs.add(path68.join(workingDir, currentDir));
70488
- 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);
70489
70958
  if (parent === currentDir)
70490
70959
  break;
70491
70960
  currentDir = parent;
@@ -70569,7 +71038,7 @@ var sbom_generate = createSwarmTool({
70569
71038
  const changedFiles = obj.changed_files;
70570
71039
  const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
70571
71040
  const workingDir = directory;
70572
- const outputDir = path68.isAbsolute(relativeOutputDir) ? relativeOutputDir : path68.join(workingDir, relativeOutputDir);
71041
+ const outputDir = path69.isAbsolute(relativeOutputDir) ? relativeOutputDir : path69.join(workingDir, relativeOutputDir);
70573
71042
  let manifestFiles = [];
70574
71043
  if (scope === "all") {
70575
71044
  manifestFiles = findManifestFiles(workingDir);
@@ -70592,7 +71061,7 @@ var sbom_generate = createSwarmTool({
70592
71061
  const processedFiles = [];
70593
71062
  for (const manifestFile of manifestFiles) {
70594
71063
  try {
70595
- const fullPath = path68.isAbsolute(manifestFile) ? manifestFile : path68.join(workingDir, manifestFile);
71064
+ const fullPath = path69.isAbsolute(manifestFile) ? manifestFile : path69.join(workingDir, manifestFile);
70596
71065
  if (!fs56.existsSync(fullPath)) {
70597
71066
  continue;
70598
71067
  }
@@ -70609,7 +71078,7 @@ var sbom_generate = createSwarmTool({
70609
71078
  const bom = generateCycloneDX(allComponents);
70610
71079
  const bomJson = serializeCycloneDX(bom);
70611
71080
  const filename = generateSbomFilename();
70612
- const outputPath = path68.join(outputDir, filename);
71081
+ const outputPath = path69.join(outputDir, filename);
70613
71082
  fs56.writeFileSync(outputPath, bomJson, "utf-8");
70614
71083
  const verdict = processedFiles.length > 0 ? "pass" : "pass";
70615
71084
  try {
@@ -70653,7 +71122,7 @@ var sbom_generate = createSwarmTool({
70653
71122
  init_dist();
70654
71123
  init_create_tool();
70655
71124
  import * as fs57 from "fs";
70656
- import * as path69 from "path";
71125
+ import * as path70 from "path";
70657
71126
  var SPEC_CANDIDATES = [
70658
71127
  "openapi.json",
70659
71128
  "openapi.yaml",
@@ -70685,12 +71154,12 @@ function normalizePath2(p) {
70685
71154
  }
70686
71155
  function discoverSpecFile(cwd, specFileArg) {
70687
71156
  if (specFileArg) {
70688
- const resolvedPath = path69.resolve(cwd, specFileArg);
70689
- 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;
70690
71159
  if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
70691
71160
  throw new Error("Invalid spec_file: path traversal detected");
70692
71161
  }
70693
- const ext = path69.extname(resolvedPath).toLowerCase();
71162
+ const ext = path70.extname(resolvedPath).toLowerCase();
70694
71163
  if (!ALLOWED_EXTENSIONS.includes(ext)) {
70695
71164
  throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
70696
71165
  }
@@ -70704,7 +71173,7 @@ function discoverSpecFile(cwd, specFileArg) {
70704
71173
  return resolvedPath;
70705
71174
  }
70706
71175
  for (const candidate of SPEC_CANDIDATES) {
70707
- const candidatePath = path69.resolve(cwd, candidate);
71176
+ const candidatePath = path70.resolve(cwd, candidate);
70708
71177
  if (fs57.existsSync(candidatePath)) {
70709
71178
  const stats = fs57.statSync(candidatePath);
70710
71179
  if (stats.size <= MAX_SPEC_SIZE) {
@@ -70716,7 +71185,7 @@ function discoverSpecFile(cwd, specFileArg) {
70716
71185
  }
70717
71186
  function parseSpec(specFile) {
70718
71187
  const content = fs57.readFileSync(specFile, "utf-8");
70719
- const ext = path69.extname(specFile).toLowerCase();
71188
+ const ext = path70.extname(specFile).toLowerCase();
70720
71189
  if (ext === ".json") {
70721
71190
  return parseJsonSpec(content);
70722
71191
  }
@@ -70792,7 +71261,7 @@ function extractRoutes(cwd) {
70792
71261
  return;
70793
71262
  }
70794
71263
  for (const entry of entries) {
70795
- const fullPath = path69.join(dir, entry.name);
71264
+ const fullPath = path70.join(dir, entry.name);
70796
71265
  if (entry.isSymbolicLink()) {
70797
71266
  continue;
70798
71267
  }
@@ -70802,7 +71271,7 @@ function extractRoutes(cwd) {
70802
71271
  }
70803
71272
  walkDir(fullPath);
70804
71273
  } else if (entry.isFile()) {
70805
- const ext = path69.extname(entry.name).toLowerCase();
71274
+ const ext = path70.extname(entry.name).toLowerCase();
70806
71275
  const baseName = entry.name.toLowerCase();
70807
71276
  if (![".ts", ".js", ".mjs"].includes(ext)) {
70808
71277
  continue;
@@ -70968,7 +71437,7 @@ var schema_drift = createSwarmTool({
70968
71437
  init_tool();
70969
71438
  init_create_tool();
70970
71439
  import * as fs58 from "fs";
70971
- import * as path70 from "path";
71440
+ import * as path71 from "path";
70972
71441
  var DEFAULT_MAX_RESULTS = 100;
70973
71442
  var DEFAULT_MAX_LINES = 200;
70974
71443
  var REGEX_TIMEOUT_MS = 5000;
@@ -71004,11 +71473,11 @@ function containsWindowsAttacks3(str) {
71004
71473
  }
71005
71474
  function isPathInWorkspace3(filePath, workspace) {
71006
71475
  try {
71007
- const resolvedPath = path70.resolve(workspace, filePath);
71476
+ const resolvedPath = path71.resolve(workspace, filePath);
71008
71477
  const realWorkspace = fs58.realpathSync(workspace);
71009
71478
  const realResolvedPath = fs58.realpathSync(resolvedPath);
71010
- const relativePath = path70.relative(realWorkspace, realResolvedPath);
71011
- if (relativePath.startsWith("..") || path70.isAbsolute(relativePath)) {
71479
+ const relativePath = path71.relative(realWorkspace, realResolvedPath);
71480
+ if (relativePath.startsWith("..") || path71.isAbsolute(relativePath)) {
71012
71481
  return false;
71013
71482
  }
71014
71483
  return true;
@@ -71021,11 +71490,11 @@ function validatePathForRead2(filePath, workspace) {
71021
71490
  }
71022
71491
  function findRgInEnvPath() {
71023
71492
  const searchPath = process.env.PATH ?? "";
71024
- for (const dir of searchPath.split(path70.delimiter)) {
71493
+ for (const dir of searchPath.split(path71.delimiter)) {
71025
71494
  if (!dir)
71026
71495
  continue;
71027
71496
  const isWindows = process.platform === "win32";
71028
- const candidate = path70.join(dir, isWindows ? "rg.exe" : "rg");
71497
+ const candidate = path71.join(dir, isWindows ? "rg.exe" : "rg");
71029
71498
  if (fs58.existsSync(candidate))
71030
71499
  return candidate;
71031
71500
  }
@@ -71155,8 +71624,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
71155
71624
  try {
71156
71625
  const entries = fs58.readdirSync(dir, { withFileTypes: true });
71157
71626
  for (const entry of entries) {
71158
- const fullPath = path70.join(dir, entry.name);
71159
- const relativePath = path70.relative(workspace, fullPath);
71627
+ const fullPath = path71.join(dir, entry.name);
71628
+ const relativePath = path71.relative(workspace, fullPath);
71160
71629
  if (!validatePathForRead2(fullPath, workspace)) {
71161
71630
  continue;
71162
71631
  }
@@ -71197,7 +71666,7 @@ async function fallbackSearch(opts) {
71197
71666
  const matches = [];
71198
71667
  let total = 0;
71199
71668
  for (const file3 of files) {
71200
- const fullPath = path70.join(opts.workspace, file3);
71669
+ const fullPath = path71.join(opts.workspace, file3);
71201
71670
  if (!validatePathForRead2(fullPath, opts.workspace)) {
71202
71671
  continue;
71203
71672
  }
@@ -71368,7 +71837,7 @@ init_secretscan();
71368
71837
  init_tool();
71369
71838
  init_create_tool();
71370
71839
  import * as fs59 from "fs";
71371
- import * as path71 from "path";
71840
+ import * as path72 from "path";
71372
71841
  var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
71373
71842
  function containsWindowsAttacks4(str) {
71374
71843
  if (/:[^\\/]/.test(str))
@@ -71382,14 +71851,14 @@ function containsWindowsAttacks4(str) {
71382
71851
  }
71383
71852
  function isPathInWorkspace4(filePath, workspace) {
71384
71853
  try {
71385
- const resolvedPath = path71.resolve(workspace, filePath);
71854
+ const resolvedPath = path72.resolve(workspace, filePath);
71386
71855
  if (!fs59.existsSync(resolvedPath)) {
71387
71856
  return true;
71388
71857
  }
71389
71858
  const realWorkspace = fs59.realpathSync(workspace);
71390
71859
  const realResolvedPath = fs59.realpathSync(resolvedPath);
71391
- const relativePath = path71.relative(realWorkspace, realResolvedPath);
71392
- if (relativePath.startsWith("..") || path71.isAbsolute(relativePath)) {
71860
+ const relativePath = path72.relative(realWorkspace, realResolvedPath);
71861
+ if (relativePath.startsWith("..") || path72.isAbsolute(relativePath)) {
71393
71862
  return false;
71394
71863
  }
71395
71864
  return true;
@@ -71597,7 +72066,7 @@ var suggestPatch = createSwarmTool({
71597
72066
  });
71598
72067
  continue;
71599
72068
  }
71600
- const fullPath = path71.resolve(directory, change.file);
72069
+ const fullPath = path72.resolve(directory, change.file);
71601
72070
  if (!fs59.existsSync(fullPath)) {
71602
72071
  errors5.push({
71603
72072
  success: false,
@@ -71693,7 +72162,7 @@ init_dist();
71693
72162
  init_manager();
71694
72163
  init_detector();
71695
72164
  import * as fs60 from "fs";
71696
- import * as path72 from "path";
72165
+ import * as path73 from "path";
71697
72166
  init_create_tool();
71698
72167
  var MAX_FILE_SIZE2 = 5 * 1024 * 1024;
71699
72168
  var BINARY_CHECK_BYTES = 8192;
@@ -71746,7 +72215,7 @@ async function syntaxCheck(input, directory, config3) {
71746
72215
  if (languages?.length) {
71747
72216
  const lowerLangs = languages.map((l) => l.toLowerCase());
71748
72217
  filesToCheck = filesToCheck.filter((file3) => {
71749
- const ext = path72.extname(file3.path).toLowerCase();
72218
+ const ext = path73.extname(file3.path).toLowerCase();
71750
72219
  const langDef = getLanguageForExtension(ext);
71751
72220
  const fileProfile = getProfileForFile(file3.path);
71752
72221
  const langId = fileProfile?.id || langDef?.id;
@@ -71759,7 +72228,7 @@ async function syntaxCheck(input, directory, config3) {
71759
72228
  let skippedCount = 0;
71760
72229
  for (const fileInfo of filesToCheck) {
71761
72230
  const { path: filePath } = fileInfo;
71762
- const fullPath = path72.isAbsolute(filePath) ? filePath : path72.join(directory, filePath);
72231
+ const fullPath = path73.isAbsolute(filePath) ? filePath : path73.join(directory, filePath);
71763
72232
  const result = {
71764
72233
  path: filePath,
71765
72234
  language: "",
@@ -71808,7 +72277,7 @@ async function syntaxCheck(input, directory, config3) {
71808
72277
  results.push(result);
71809
72278
  continue;
71810
72279
  }
71811
- const ext = path72.extname(filePath).toLowerCase();
72280
+ const ext = path73.extname(filePath).toLowerCase();
71812
72281
  const langDef = getLanguageForExtension(ext);
71813
72282
  result.language = profile?.id || langDef?.id || "unknown";
71814
72283
  const errors5 = extractSyntaxErrors(parser, content);
@@ -71870,7 +72339,7 @@ init_dist();
71870
72339
  init_utils();
71871
72340
  init_create_tool();
71872
72341
  import * as fs61 from "fs";
71873
- import * as path73 from "path";
72342
+ import * as path74 from "path";
71874
72343
  var MAX_TEXT_LENGTH = 200;
71875
72344
  var MAX_FILE_SIZE_BYTES9 = 1024 * 1024;
71876
72345
  var SUPPORTED_EXTENSIONS2 = new Set([
@@ -71936,9 +72405,9 @@ function validatePathsInput(paths, cwd) {
71936
72405
  return { error: "paths contains path traversal", resolvedPath: null };
71937
72406
  }
71938
72407
  try {
71939
- const resolvedPath = path73.resolve(paths);
71940
- const normalizedCwd = path73.resolve(cwd);
71941
- const normalizedResolved = path73.resolve(resolvedPath);
72408
+ const resolvedPath = path74.resolve(paths);
72409
+ const normalizedCwd = path74.resolve(cwd);
72410
+ const normalizedResolved = path74.resolve(resolvedPath);
71942
72411
  if (!normalizedResolved.startsWith(normalizedCwd)) {
71943
72412
  return {
71944
72413
  error: "paths must be within the current working directory",
@@ -71954,7 +72423,7 @@ function validatePathsInput(paths, cwd) {
71954
72423
  }
71955
72424
  }
71956
72425
  function isSupportedExtension(filePath) {
71957
- const ext = path73.extname(filePath).toLowerCase();
72426
+ const ext = path74.extname(filePath).toLowerCase();
71958
72427
  return SUPPORTED_EXTENSIONS2.has(ext);
71959
72428
  }
71960
72429
  function findSourceFiles2(dir, files = []) {
@@ -71969,7 +72438,7 @@ function findSourceFiles2(dir, files = []) {
71969
72438
  if (SKIP_DIRECTORIES4.has(entry)) {
71970
72439
  continue;
71971
72440
  }
71972
- const fullPath = path73.join(dir, entry);
72441
+ const fullPath = path74.join(dir, entry);
71973
72442
  let stat2;
71974
72443
  try {
71975
72444
  stat2 = fs61.statSync(fullPath);
@@ -72081,7 +72550,7 @@ var todo_extract = createSwarmTool({
72081
72550
  filesToScan.push(scanPath);
72082
72551
  } else {
72083
72552
  const errorResult = {
72084
- error: `unsupported file extension: ${path73.extname(scanPath)}`,
72553
+ error: `unsupported file extension: ${path74.extname(scanPath)}`,
72085
72554
  total: 0,
72086
72555
  byPriority: { high: 0, medium: 0, low: 0 },
72087
72556
  entries: []
@@ -72128,14 +72597,14 @@ init_tool();
72128
72597
  init_schema();
72129
72598
  init_gate_evidence();
72130
72599
  import * as fs63 from "fs";
72131
- import * as path75 from "path";
72600
+ import * as path76 from "path";
72132
72601
 
72133
72602
  // src/hooks/diff-scope.ts
72134
72603
  import * as fs62 from "fs";
72135
- import * as path74 from "path";
72604
+ import * as path75 from "path";
72136
72605
  function getDeclaredScope(taskId, directory) {
72137
72606
  try {
72138
- const planPath = path74.join(directory, ".swarm", "plan.json");
72607
+ const planPath = path75.join(directory, ".swarm", "plan.json");
72139
72608
  if (!fs62.existsSync(planPath))
72140
72609
  return null;
72141
72610
  const raw = fs62.readFileSync(planPath, "utf-8");
@@ -72252,7 +72721,7 @@ var TIER_3_PATTERNS = [
72252
72721
  ];
72253
72722
  function matchesTier3Pattern(files) {
72254
72723
  for (const file3 of files) {
72255
- const fileName = path75.basename(file3);
72724
+ const fileName = path76.basename(file3);
72256
72725
  for (const pattern of TIER_3_PATTERNS) {
72257
72726
  if (pattern.test(fileName)) {
72258
72727
  return true;
@@ -72266,7 +72735,7 @@ function checkReviewerGate(taskId, workingDirectory) {
72266
72735
  if (hasActiveTurboMode()) {
72267
72736
  const resolvedDir2 = workingDirectory;
72268
72737
  try {
72269
- const planPath = path75.join(resolvedDir2, ".swarm", "plan.json");
72738
+ const planPath = path76.join(resolvedDir2, ".swarm", "plan.json");
72270
72739
  const planRaw = fs63.readFileSync(planPath, "utf-8");
72271
72740
  const plan = JSON.parse(planRaw);
72272
72741
  for (const planPhase of plan.phases ?? []) {
@@ -72333,7 +72802,7 @@ function checkReviewerGate(taskId, workingDirectory) {
72333
72802
  }
72334
72803
  try {
72335
72804
  const resolvedDir2 = workingDirectory;
72336
- const planPath = path75.join(resolvedDir2, ".swarm", "plan.json");
72805
+ const planPath = path76.join(resolvedDir2, ".swarm", "plan.json");
72337
72806
  const planRaw = fs63.readFileSync(planPath, "utf-8");
72338
72807
  const plan = JSON.parse(planRaw);
72339
72808
  for (const planPhase of plan.phases ?? []) {
@@ -72516,8 +72985,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
72516
72985
  };
72517
72986
  }
72518
72987
  }
72519
- normalizedDir = path75.normalize(args2.working_directory);
72520
- const pathParts = normalizedDir.split(path75.sep);
72988
+ normalizedDir = path76.normalize(args2.working_directory);
72989
+ const pathParts = normalizedDir.split(path76.sep);
72521
72990
  if (pathParts.includes("..")) {
72522
72991
  return {
72523
72992
  success: false,
@@ -72527,10 +72996,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
72527
72996
  ]
72528
72997
  };
72529
72998
  }
72530
- const resolvedDir = path75.resolve(normalizedDir);
72999
+ const resolvedDir = path76.resolve(normalizedDir);
72531
73000
  try {
72532
73001
  const realPath = fs63.realpathSync(resolvedDir);
72533
- const planPath = path75.join(realPath, ".swarm", "plan.json");
73002
+ const planPath = path76.join(realPath, ".swarm", "plan.json");
72534
73003
  if (!fs63.existsSync(planPath)) {
72535
73004
  return {
72536
73005
  success: false,
@@ -72562,8 +73031,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
72562
73031
  }
72563
73032
  if (args2.status === "in_progress") {
72564
73033
  try {
72565
- const evidencePath = path75.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
72566
- 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 });
72567
73036
  const fd = fs63.openSync(evidencePath, "wx");
72568
73037
  let writeOk = false;
72569
73038
  try {
@@ -72588,7 +73057,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
72588
73057
  recoverTaskStateFromDelegations(args2.task_id);
72589
73058
  let phaseRequiresReviewer = true;
72590
73059
  try {
72591
- const planPath = path75.join(directory, ".swarm", "plan.json");
73060
+ const planPath = path76.join(directory, ".swarm", "plan.json");
72592
73061
  const planRaw = fs63.readFileSync(planPath, "utf-8");
72593
73062
  const plan = JSON.parse(planRaw);
72594
73063
  const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
@@ -72688,7 +73157,7 @@ init_tool();
72688
73157
  init_utils2();
72689
73158
  init_create_tool();
72690
73159
  import fs64 from "fs";
72691
- import path76 from "path";
73160
+ import path77 from "path";
72692
73161
  function normalizeVerdict(verdict) {
72693
73162
  switch (verdict) {
72694
73163
  case "APPROVED":
@@ -72735,7 +73204,7 @@ async function executeWriteDriftEvidence(args2, directory) {
72735
73204
  entries: [evidenceEntry]
72736
73205
  };
72737
73206
  const filename = "drift-verifier.json";
72738
- const relativePath = path76.join("evidence", String(phase), filename);
73207
+ const relativePath = path77.join("evidence", String(phase), filename);
72739
73208
  let validatedPath;
72740
73209
  try {
72741
73210
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -72746,10 +73215,10 @@ async function executeWriteDriftEvidence(args2, directory) {
72746
73215
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
72747
73216
  }, null, 2);
72748
73217
  }
72749
- const evidenceDir = path76.dirname(validatedPath);
73218
+ const evidenceDir = path77.dirname(validatedPath);
72750
73219
  try {
72751
73220
  await fs64.promises.mkdir(evidenceDir, { recursive: true });
72752
- const tempPath = path76.join(evidenceDir, `.${filename}.tmp`);
73221
+ const tempPath = path77.join(evidenceDir, `.${filename}.tmp`);
72753
73222
  await fs64.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
72754
73223
  await fs64.promises.rename(tempPath, validatedPath);
72755
73224
  return JSON.stringify({
@@ -72840,7 +73309,7 @@ var OpenCodeSwarm = async (ctx) => {
72840
73309
  swarmState.opencodeClient = ctx.client;
72841
73310
  await loadSnapshot(ctx.directory);
72842
73311
  initTelemetry(ctx.directory);
72843
- const agents = getAgentConfigs(config3);
73312
+ const agents = getAgentConfigs(config3, ctx.directory);
72844
73313
  const agentDefinitions = createAgents(config3);
72845
73314
  swarmState.curatorInitAgentNames = Object.keys(agents).filter((k) => k === "curator_init" || k.endsWith("_curator_init"));
72846
73315
  swarmState.curatorPhaseAgentNames = Object.keys(agents).filter((k) => k === "curator_phase" || k.endsWith("_curator_phase"));
@@ -72952,7 +73421,7 @@ var OpenCodeSwarm = async (ctx) => {
72952
73421
  const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
72953
73422
  preflightTriggerManager = new PTM(automationConfig);
72954
73423
  const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
72955
- const swarmDir = path77.resolve(ctx.directory, ".swarm");
73424
+ const swarmDir = path78.resolve(ctx.directory, ".swarm");
72956
73425
  statusArtifact = new ASA(swarmDir);
72957
73426
  statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
72958
73427
  if (automationConfig.capabilities?.evidence_auto_summaries === true) {
@@ -73058,9 +73527,9 @@ var OpenCodeSwarm = async (ctx) => {
73058
73527
  completion_verify,
73059
73528
  complexity_hotspots,
73060
73529
  curator_analyze,
73061
- knowledgeAdd,
73062
- knowledgeRecall,
73063
- knowledgeRemove,
73530
+ knowledge_add,
73531
+ knowledge_recall,
73532
+ knowledge_remove,
73064
73533
  co_change_analyzer,
73065
73534
  detect_domains,
73066
73535
  doc_extract,
@@ -73455,6 +73924,24 @@ var OpenCodeSwarm = async (ctx) => {
73455
73924
  taskSession.pendingAdvisoryMessages ??= [];
73456
73925
  taskSession.pendingAdvisoryMessages.push(`[PIPELINE] ${baseAgentName} delegation complete for task ${taskSession.currentTaskId ?? "unknown"}. ` + `Resume the QA gate pipeline \u2014 check your task pipeline steps for the next required action. ` + `Do not stop here.`);
73457
73926
  }
73927
+ if (baseAgentName === "critic_sounding_board") {
73928
+ const rawResponse = typeof output.output === "string" ? output.output : "";
73929
+ const parsed = parseSoundingBoardResponse(rawResponse);
73930
+ taskSession.pendingAdvisoryMessages ??= [];
73931
+ if (parsed) {
73932
+ let verdictMsg = `[SOUNDING_BOARD] Verdict: ${parsed.verdict}. ${parsed.reasoning}`;
73933
+ if (parsed.improvedQuestion)
73934
+ verdictMsg += ` Rephrase to: ${parsed.improvedQuestion}`;
73935
+ if (parsed.answer)
73936
+ verdictMsg += ` Answer: ${parsed.answer}`;
73937
+ if (parsed.warning)
73938
+ verdictMsg += ` WARNING: ${parsed.warning}`;
73939
+ taskSession.pendingAdvisoryMessages.push(verdictMsg);
73940
+ taskSession.lastDelegationReason = "critic_consultation";
73941
+ } else {
73942
+ taskSession.pendingAdvisoryMessages.push(`[SOUNDING_BOARD] WARNING: Could not parse a structured verdict from critic_sounding_board response (${rawResponse.length} chars). Treat as APPROVED and proceed, but review the raw response for manual guidance.`);
73943
+ }
73944
+ }
73458
73945
  }
73459
73946
  if (_dbg)
73460
73947
  console.error(`[DIAG] Task handoff DONE session=${sessionId} activeAgent=${swarmState.activeAgent.get(sessionId)}`);