opencode-swarm 6.33.1 → 6.33.2

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
@@ -14146,7 +14146,7 @@ var init_zod = __esm(() => {
14146
14146
  });
14147
14147
 
14148
14148
  // src/config/evidence-schema.ts
14149
- var EVIDENCE_MAX_JSON_BYTES, EVIDENCE_MAX_PATCH_BYTES, EVIDENCE_MAX_TASK_BYTES, EvidenceTypeSchema, EvidenceVerdictSchema, BaseEvidenceSchema, ReviewEvidenceSchema, TestEvidenceSchema, DiffEvidenceSchema, ApprovalEvidenceSchema, NoteEvidenceSchema, RetrospectiveEvidenceSchema, SyntaxEvidenceSchema, PlaceholderEvidenceSchema, SastEvidenceSchema, SbomEvidenceSchema, BuildEvidenceSchema, QualityBudgetEvidenceSchema, EvidenceSchema, EvidenceBundleSchema;
14149
+ var EVIDENCE_MAX_JSON_BYTES, EVIDENCE_MAX_PATCH_BYTES, EVIDENCE_MAX_TASK_BYTES, EvidenceTypeSchema, EvidenceVerdictSchema, BaseEvidenceSchema, ReviewEvidenceSchema, TestEvidenceSchema, DiffEvidenceSchema, ApprovalEvidenceSchema, NoteEvidenceSchema, RetrospectiveEvidenceSchema, SyntaxEvidenceSchema, PlaceholderEvidenceSchema, SastEvidenceSchema, SbomEvidenceSchema, BuildEvidenceSchema, QualityBudgetEvidenceSchema, SecretscanEvidenceSchema, EvidenceSchema, EvidenceBundleSchema;
14150
14150
  var init_evidence_schema = __esm(() => {
14151
14151
  init_zod();
14152
14152
  EVIDENCE_MAX_JSON_BYTES = 500 * 1024;
@@ -14164,7 +14164,8 @@ var init_evidence_schema = __esm(() => {
14164
14164
  "sast",
14165
14165
  "sbom",
14166
14166
  "build",
14167
- "quality_budget"
14167
+ "quality_budget",
14168
+ "secretscan"
14168
14169
  ]);
14169
14170
  EvidenceVerdictSchema = exports_external.enum([
14170
14171
  "pass",
@@ -14245,7 +14246,14 @@ var init_evidence_schema = __esm(() => {
14245
14246
  approach: exports_external.string().min(1),
14246
14247
  result: exports_external.enum(["success", "failure", "partial"]),
14247
14248
  abandoned_reason: exports_external.string().optional()
14248
- })).max(10).default([])
14249
+ })).max(10).default([]),
14250
+ error_taxonomy: exports_external.array(exports_external.enum([
14251
+ "planning_error",
14252
+ "interface_mismatch",
14253
+ "logic_error",
14254
+ "scope_creep",
14255
+ "gate_evasion"
14256
+ ])).default([])
14249
14257
  });
14250
14258
  SyntaxEvidenceSchema = BaseEvidenceSchema.extend({
14251
14259
  type: exports_external.literal("syntax"),
@@ -14356,6 +14364,13 @@ var init_evidence_schema = __esm(() => {
14356
14364
  })).default([]),
14357
14365
  files_analyzed: exports_external.array(exports_external.string())
14358
14366
  });
14367
+ SecretscanEvidenceSchema = BaseEvidenceSchema.extend({
14368
+ type: exports_external.literal("secretscan"),
14369
+ findings_count: exports_external.number().int().min(0).default(0),
14370
+ scan_directory: exports_external.string().optional(),
14371
+ files_scanned: exports_external.number().int().min(0).default(0),
14372
+ skipped_files: exports_external.number().int().min(0).default(0)
14373
+ });
14359
14374
  EvidenceSchema = exports_external.discriminatedUnion("type", [
14360
14375
  ReviewEvidenceSchema,
14361
14376
  TestEvidenceSchema,
@@ -14368,7 +14383,8 @@ var init_evidence_schema = __esm(() => {
14368
14383
  SastEvidenceSchema,
14369
14384
  SbomEvidenceSchema,
14370
14385
  BuildEvidenceSchema,
14371
- QualityBudgetEvidenceSchema
14386
+ QualityBudgetEvidenceSchema,
14387
+ SecretscanEvidenceSchema
14372
14388
  ]);
14373
14389
  EvidenceBundleSchema = exports_external.object({
14374
14390
  schema_version: exports_external.literal("1.0.0"),
@@ -14458,7 +14474,8 @@ var init_schema = __esm(() => {
14458
14474
  AgentOverrideConfigSchema = exports_external.object({
14459
14475
  model: exports_external.string().optional(),
14460
14476
  temperature: exports_external.number().min(0).max(2).optional(),
14461
- disabled: exports_external.boolean().optional()
14477
+ disabled: exports_external.boolean().optional(),
14478
+ fallback_models: exports_external.array(exports_external.string()).max(3).optional()
14462
14479
  });
14463
14480
  SwarmConfigSchema = exports_external.object({
14464
14481
  name: exports_external.string().optional(),
@@ -14799,6 +14816,7 @@ var init_schema = __esm(() => {
14799
14816
  warning_threshold: exports_external.number().min(0.1).max(0.9).default(0.75),
14800
14817
  idle_timeout_minutes: exports_external.number().min(5).max(240).default(60),
14801
14818
  no_op_warning_threshold: exports_external.number().min(1).max(100).default(15),
14819
+ max_coder_revisions: exports_external.number().int().min(1).max(20).default(5),
14802
14820
  qa_gates: exports_external.object({
14803
14821
  required_tools: exports_external.array(exports_external.string().min(1)).default([
14804
14822
  "diff",
@@ -15400,6 +15418,9 @@ import * as path4 from "path";
15400
15418
  function isValidEvidenceType(type) {
15401
15419
  return VALID_EVIDENCE_TYPES.includes(type);
15402
15420
  }
15421
+ function isSecretscanEvidence(evidence) {
15422
+ return evidence.type === "secretscan";
15423
+ }
15403
15424
  function sanitizeTaskId(taskId) {
15404
15425
  if (!taskId || taskId.length === 0) {
15405
15426
  throw new Error("Invalid task ID: empty string");
@@ -15652,11 +15673,12 @@ var init_manager = __esm(() => {
15652
15673
  "sast",
15653
15674
  "sbom",
15654
15675
  "build",
15655
- "quality_budget"
15676
+ "quality_budget",
15677
+ "secretscan"
15656
15678
  ];
15657
15679
  TASK_ID_REGEX = /^\d+\.\d+(\.\d+)*$/;
15658
15680
  RETRO_TASK_ID_REGEX = /^retro-\d+$/;
15659
- INTERNAL_TOOL_ID_REGEX = /^(?:sast_scan|quality_budget|syntax_check|placeholder_scan|sbom_generate|build)$/;
15681
+ INTERNAL_TOOL_ID_REGEX = /^(?:sast_scan|quality_budget|syntax_check|placeholder_scan|sbom_generate|build|secretscan)$/;
15660
15682
  LEGACY_TASK_COMPLEXITY_MAP = {
15661
15683
  low: "simple",
15662
15684
  medium: "moderate",
@@ -36250,7 +36272,7 @@ __export(exports_gate_evidence, {
36250
36272
  deriveRequiredGates: () => deriveRequiredGates,
36251
36273
  DEFAULT_REQUIRED_GATES: () => DEFAULT_REQUIRED_GATES
36252
36274
  });
36253
- import { mkdirSync as mkdirSync9, readFileSync as readFileSync14, renameSync as renameSync8, unlinkSync as unlinkSync5 } from "fs";
36275
+ import { mkdirSync as mkdirSync9, readFileSync as readFileSync14, renameSync as renameSync9, unlinkSync as unlinkSync5 } from "fs";
36254
36276
  import * as path30 from "path";
36255
36277
  function isValidTaskId2(taskId) {
36256
36278
  if (!taskId)
@@ -36315,7 +36337,7 @@ async function atomicWrite(targetPath, content) {
36315
36337
  const tempPath = `${targetPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
36316
36338
  try {
36317
36339
  await Bun.write(tempPath, content);
36318
- renameSync8(tempPath, targetPath);
36340
+ renameSync9(tempPath, targetPath);
36319
36341
  } finally {
36320
36342
  try {
36321
36343
  unlinkSync5(tempPath);
@@ -37910,11 +37932,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
37910
37932
  throw toThrow;
37911
37933
  }, "quit_");
37912
37934
  var scriptDirectory = "";
37913
- function locateFile(path47) {
37935
+ function locateFile(path48) {
37914
37936
  if (Module["locateFile"]) {
37915
- return Module["locateFile"](path47, scriptDirectory);
37937
+ return Module["locateFile"](path48, scriptDirectory);
37916
37938
  }
37917
- return scriptDirectory + path47;
37939
+ return scriptDirectory + path48;
37918
37940
  }
37919
37941
  __name(locateFile, "locateFile");
37920
37942
  var readAsync, readBinary;
@@ -39662,7 +39684,7 @@ var init_runtime = __esm(() => {
39662
39684
  });
39663
39685
 
39664
39686
  // src/index.ts
39665
- import * as path57 from "path";
39687
+ import * as path58 from "path";
39666
39688
 
39667
39689
  // src/agents/index.ts
39668
39690
  init_config();
@@ -39729,6 +39751,10 @@ function startAgentSession(sessionId, agentName, staleDurationMs = 7200000, dire
39729
39751
  scopeViolationDetected: false,
39730
39752
  modifiedFilesThisCoderTask: [],
39731
39753
  turboMode: false,
39754
+ model_fallback_index: 0,
39755
+ modelFallbackExhausted: false,
39756
+ coderRevisions: 0,
39757
+ revisionLimitHit: false,
39732
39758
  loopDetectionWindow: [],
39733
39759
  pendingAdvisoryMessages: []
39734
39760
  };
@@ -39837,6 +39863,12 @@ function ensureAgentSession(sessionId, agentName, directory) {
39837
39863
  if (session.turboMode === undefined) {
39838
39864
  session.turboMode = false;
39839
39865
  }
39866
+ if (session.model_fallback_index === undefined) {
39867
+ session.model_fallback_index = 0;
39868
+ }
39869
+ if (session.modelFallbackExhausted === undefined) {
39870
+ session.modelFallbackExhausted = false;
39871
+ }
39840
39872
  if (session.loopDetectionWindow === undefined) {
39841
39873
  session.loopDetectionWindow = [];
39842
39874
  }
@@ -44112,14 +44144,18 @@ async function readCuratorSummary(directory) {
44112
44144
  }
44113
44145
  return parsed;
44114
44146
  } catch {
44115
- console.warn("Failed to parse curator-summary.json: invalid JSON");
44147
+ if (process.env.DEBUG_SWARM) {
44148
+ console.warn("Failed to parse curator-summary.json: invalid JSON");
44149
+ }
44116
44150
  return null;
44117
44151
  }
44118
44152
  }
44119
44153
  async function writeCuratorSummary(directory, summary) {
44120
44154
  const resolvedPath = validateSwarmPath(directory, "curator-summary.json");
44121
44155
  fs7.mkdirSync(path12.dirname(resolvedPath), { recursive: true });
44122
- await Bun.write(resolvedPath, JSON.stringify(summary, null, 2));
44156
+ const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
44157
+ await Bun.write(tempPath, JSON.stringify(summary, null, 2));
44158
+ fs7.renameSync(tempPath, resolvedPath);
44123
44159
  }
44124
44160
  function normalizeAgentName(name2) {
44125
44161
  return name2.toLowerCase().replace(/^(mega|paid|local|lowtier|modelrelay)_/, "");
@@ -44143,7 +44179,9 @@ function filterPhaseEvents(eventsJsonl, phase, sinceTimestamp) {
44143
44179
  }
44144
44180
  }
44145
44181
  } catch {
44146
- console.warn("filterPhaseEvents: skipping malformed line");
44182
+ if (process.env.DEBUG_SWARM) {
44183
+ console.warn("filterPhaseEvents: skipping malformed line");
44184
+ }
44147
44185
  }
44148
44186
  }
44149
44187
  return filtered;
@@ -46473,7 +46511,7 @@ async function handleExportCommand(directory, _args) {
46473
46511
  // src/commands/handoff.ts
46474
46512
  init_utils2();
46475
46513
  import crypto3 from "crypto";
46476
- import { renameSync as renameSync5 } from "fs";
46514
+ import { renameSync as renameSync6 } from "fs";
46477
46515
 
46478
46516
  // src/services/handoff-service.ts
46479
46517
  init_utils2();
@@ -46774,7 +46812,7 @@ function formatHandoffMarkdown(data) {
46774
46812
 
46775
46813
  // src/session/snapshot-writer.ts
46776
46814
  init_utils2();
46777
- import { mkdirSync as mkdirSync7, renameSync as renameSync4 } from "fs";
46815
+ import { mkdirSync as mkdirSync7, renameSync as renameSync5 } from "fs";
46778
46816
  import * as path19 from "path";
46779
46817
  var pendingWrite = null;
46780
46818
  var lastWritePromise = Promise.resolve();
@@ -46839,7 +46877,11 @@ function serializeAgentSession(s) {
46839
46877
  taskWorkflowStates: Object.fromEntries(s.taskWorkflowStates ?? new Map),
46840
46878
  ...s.scopeViolationDetected !== undefined && {
46841
46879
  scopeViolationDetected: s.scopeViolationDetected
46842
- }
46880
+ },
46881
+ model_fallback_index: s.model_fallback_index ?? 0,
46882
+ modelFallbackExhausted: s.modelFallbackExhausted ?? false,
46883
+ coderRevisions: s.coderRevisions ?? 0,
46884
+ revisionLimitHit: s.revisionLimitHit ?? false
46843
46885
  };
46844
46886
  }
46845
46887
  async function writeSnapshot(directory, state) {
@@ -46861,9 +46903,11 @@ async function writeSnapshot(directory, state) {
46861
46903
  mkdirSync7(dir, { recursive: true });
46862
46904
  const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
46863
46905
  await Bun.write(tempPath, content);
46864
- renameSync4(tempPath, resolvedPath);
46906
+ renameSync5(tempPath, resolvedPath);
46865
46907
  } catch (error93) {
46866
- console.warn("[snapshot-writer] write failed:", error93 instanceof Error ? error93.message : String(error93));
46908
+ if (process.env.DEBUG_SWARM) {
46909
+ console.warn("[snapshot-writer] write failed:", error93 instanceof Error ? error93.message : String(error93));
46910
+ }
46867
46911
  }
46868
46912
  }
46869
46913
  function createSnapshotWriterHook(directory) {
@@ -46893,7 +46937,7 @@ async function handleHandoffCommand(directory, _args) {
46893
46937
  const resolvedPath = validateSwarmPath(directory, "handoff.md");
46894
46938
  const tempPath = `${resolvedPath}.tmp.${crypto3.randomUUID()}`;
46895
46939
  await Bun.write(tempPath, markdown);
46896
- renameSync5(tempPath, resolvedPath);
46940
+ renameSync6(tempPath, resolvedPath);
46897
46941
  await writeSnapshot(directory, swarmState);
46898
46942
  await flushPendingSnapshot(directory);
46899
46943
  return `## Handoff Brief Written
@@ -47639,7 +47683,7 @@ async function handleResetSessionCommand(directory, _args) {
47639
47683
  // src/summaries/manager.ts
47640
47684
  init_utils2();
47641
47685
  init_utils();
47642
- import { mkdirSync as mkdirSync8, readdirSync as readdirSync7, renameSync as renameSync6, rmSync as rmSync3, statSync as statSync7 } from "fs";
47686
+ import { mkdirSync as mkdirSync8, readdirSync as readdirSync7, renameSync as renameSync7, rmSync as rmSync3, statSync as statSync7 } from "fs";
47643
47687
  import * as path26 from "path";
47644
47688
  var SUMMARY_ID_REGEX = /^S\d+$/;
47645
47689
  function sanitizeSummaryId(id) {
@@ -47683,7 +47727,7 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
47683
47727
  const tempPath = path26.join(summaryDir, `${sanitizedId}.json.tmp.${Date.now()}.${process.pid}`);
47684
47728
  try {
47685
47729
  await Bun.write(tempPath, entryJson);
47686
- renameSync6(tempPath, summaryPath);
47730
+ renameSync7(tempPath, summaryPath);
47687
47731
  } catch (error93) {
47688
47732
  try {
47689
47733
  rmSync3(tempPath, { force: true });
@@ -48863,8 +48907,46 @@ async function executeWriteRetro(args2, directory) {
48863
48907
  top_rejection_reasons: args2.top_rejection_reasons ?? [],
48864
48908
  lessons_learned: (args2.lessons_learned ?? []).slice(0, 5),
48865
48909
  user_directives: [],
48866
- approaches_tried: []
48910
+ approaches_tried: [],
48911
+ error_taxonomy: []
48867
48912
  };
48913
+ const taxonomy = [];
48914
+ try {
48915
+ for (const taskSuffix of ["1", "2", "3", "4", "5"]) {
48916
+ const phaseTaskId = `${phase}.${taskSuffix}`;
48917
+ const result = await loadEvidence(directory, phaseTaskId);
48918
+ if (result.status !== "found")
48919
+ continue;
48920
+ const bundle = result.bundle;
48921
+ for (const entry of bundle.entries) {
48922
+ const e = entry;
48923
+ if (e.type === "review" && e.verdict === "fail") {
48924
+ const reasonParts = [];
48925
+ if (typeof e.summary === "string")
48926
+ reasonParts.push(e.summary);
48927
+ if (Array.isArray(e.issues)) {
48928
+ for (const iss of e.issues) {
48929
+ if (typeof iss.message === "string")
48930
+ reasonParts.push(iss.message);
48931
+ }
48932
+ }
48933
+ const reason = reasonParts.join(" ");
48934
+ if (/signature|type|contract|interface/i.test(reason)) {
48935
+ taxonomy.push("interface_mismatch");
48936
+ } else {
48937
+ taxonomy.push("logic_error");
48938
+ }
48939
+ } else if (e.type === "test" && e.verdict === "fail") {
48940
+ taxonomy.push("logic_error");
48941
+ } else if (e.agent === "scope_guard" && e.verdict === "fail") {
48942
+ taxonomy.push("scope_creep");
48943
+ } else if (e.agent === "loop_detector" && e.verdict === "fail") {
48944
+ taxonomy.push("gate_evasion");
48945
+ }
48946
+ }
48947
+ }
48948
+ } catch {}
48949
+ retroEntry.error_taxonomy = [...new Set(taxonomy)];
48868
48950
  try {
48869
48951
  await saveEvidence(directory, taskId, retroEntry);
48870
48952
  return JSON.stringify({
@@ -49187,7 +49269,7 @@ init_constants();
49187
49269
  init_schema();
49188
49270
 
49189
49271
  // src/hooks/agent-activity.ts
49190
- import { renameSync as renameSync7, unlinkSync as unlinkSync4 } from "fs";
49272
+ import { renameSync as renameSync8, unlinkSync as unlinkSync4 } from "fs";
49191
49273
  init_utils();
49192
49274
  init_utils2();
49193
49275
  function createAgentActivityHooks(config3, directory) {
@@ -49261,7 +49343,7 @@ async function doFlush(directory) {
49261
49343
  const tempPath = `${path29}.tmp`;
49262
49344
  try {
49263
49345
  await Bun.write(tempPath, updated);
49264
- renameSync7(tempPath, path29);
49346
+ renameSync8(tempPath, path29);
49265
49347
  } catch (writeError) {
49266
49348
  try {
49267
49349
  unlinkSync4(tempPath);
@@ -49895,6 +49977,7 @@ function detectLoop(sessionId, toolName, args2) {
49895
49977
 
49896
49978
  // src/hooks/guardrails.ts
49897
49979
  var storedInputArgs = new Map;
49980
+ var TRANSIENT_MODEL_ERROR_PATTERN = /rate.?limit|429|503|timeout|overloaded|model.?not.?found|temporarily unavailable|server error/i;
49898
49981
  function getStoredInputArgs(callID) {
49899
49982
  return storedInputArgs.get(callID);
49900
49983
  }
@@ -50072,6 +50155,9 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
50072
50155
  const coderSession = swarmState.agentSessions.get(input.sessionID);
50073
50156
  if (coderSession) {
50074
50157
  coderSession.modifiedFilesThisCoderTask = [];
50158
+ if (!coderSession.revisionLimitHit) {
50159
+ coderSession.coderRevisions = 0;
50160
+ }
50075
50161
  }
50076
50162
  }
50077
50163
  }
@@ -50080,7 +50166,7 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
50080
50166
  const loopResult = detectLoop(input.sessionID, input.tool, loopArgs);
50081
50167
  if (loopResult.count >= 5) {
50082
50168
  throw new Error(`CIRCUIT BREAKER: Delegation loop detected (${loopResult.count} identical patterns). Session paused. Ask the user for guidance.`);
50083
- } else if (loopResult.count === 3) {
50169
+ } else if (loopResult.count >= 3 && loopResult.count < 5) {
50084
50170
  const agentName2 = typeof loopArgs?.subagent_type === "string" ? loopArgs.subagent_type : "agent";
50085
50171
  const loopSession = swarmState.agentSessions.get(input.sessionID);
50086
50172
  if (loopSession) {
@@ -50411,6 +50497,16 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
50411
50497
  }
50412
50498
  if (delegation.isDelegation && delegation.targetAgent === "coder" && session.lastCoderDelegationTaskId) {
50413
50499
  session.currentTaskId = session.lastCoderDelegationTaskId;
50500
+ if (!session.revisionLimitHit) {
50501
+ session.coderRevisions++;
50502
+ const maxRevisions = cfg.max_coder_revisions ?? 5;
50503
+ if (session.coderRevisions >= maxRevisions) {
50504
+ session.revisionLimitHit = true;
50505
+ session.pendingAdvisoryMessages ??= [];
50506
+ session.pendingAdvisoryMessages.push(`CODER REVISION LIMIT: Agent has been revised ${session.coderRevisions} times ` + `(max: ${maxRevisions}) for task ${session.currentTaskId ?? "unknown"}. ` + `Escalate to user or consider a fundamentally different approach.`);
50507
+ swarmState.pendingEvents++;
50508
+ }
50509
+ }
50414
50510
  session.partialGateWarningsIssuedForTask?.delete(session.currentTaskId);
50415
50511
  if (session.declaredCoderScope !== null) {
50416
50512
  const undeclaredFiles = session.modifiedFilesThisCoderTask.map((f) => f.replace(/[\r\n\t]/g, "_")).filter((f) => !isInDeclaredScope(f, session.declaredCoderScope));
@@ -50442,9 +50538,26 @@ function createGuardrailsHooks(directory, directoryOrConfig, config3) {
50442
50538
  const hasError = output.output === null || output.output === undefined;
50443
50539
  if (hasError) {
50444
50540
  window2.consecutiveErrors++;
50541
+ if (session) {
50542
+ const outputStr = typeof output.output === "string" ? output.output : "";
50543
+ const errorContent = output.error ?? outputStr;
50544
+ if (typeof errorContent === "string" && TRANSIENT_MODEL_ERROR_PATTERN.test(errorContent) && !session.modelFallbackExhausted) {
50545
+ session.model_fallback_index++;
50546
+ session.modelFallbackExhausted = true;
50547
+ session.pendingAdvisoryMessages ??= [];
50548
+ session.pendingAdvisoryMessages.push(`MODEL FALLBACK: Transient model error detected (attempt ${session.model_fallback_index}). ` + `The agent model may be rate-limited, overloaded, or temporarily unavailable. ` + `Consider retrying with a fallback model or waiting before retrying.`);
50549
+ swarmState.pendingEvents++;
50550
+ }
50551
+ }
50445
50552
  } else {
50446
50553
  window2.consecutiveErrors = 0;
50447
50554
  window2.lastSuccessTimeMs = Date.now();
50555
+ if (session) {
50556
+ if (session.model_fallback_index > 0) {
50557
+ session.model_fallback_index = 0;
50558
+ session.modelFallbackExhausted = false;
50559
+ }
50560
+ }
50448
50561
  }
50449
50562
  },
50450
50563
  messagesTransform: async (_input, output) => {
@@ -50740,7 +50853,7 @@ function extractPlanTaskId(text) {
50740
50853
  function getSeedTaskId(session) {
50741
50854
  return session.currentTaskId ?? session.lastCoderDelegationTaskId;
50742
50855
  }
50743
- function getEvidenceTaskId(session, directory) {
50856
+ async function getEvidenceTaskId(session, directory) {
50744
50857
  const primary = session.currentTaskId ?? session.lastCoderDelegationTaskId;
50745
50858
  if (primary)
50746
50859
  return primary;
@@ -50757,7 +50870,7 @@ function getEvidenceTaskId(session, directory) {
50757
50870
  if (!resolvedPlanPath.startsWith(resolvedDirectory + path31.sep) && resolvedPlanPath !== resolvedDirectory) {
50758
50871
  return null;
50759
50872
  }
50760
- const planContent = fs19.readFileSync(resolvedPlanPath, "utf-8");
50873
+ const planContent = await fs19.promises.readFile(resolvedPlanPath, "utf-8");
50761
50874
  const plan = JSON.parse(planContent);
50762
50875
  if (!plan || !Array.isArray(plan.phases)) {
50763
50876
  return null;
@@ -50877,7 +50990,7 @@ function createDelegationGateHook(config3, directory) {
50877
50990
  }
50878
50991
  if (typeof subagentType === "string") {
50879
50992
  const rawTaskId = directArgs?.task_id;
50880
- const evidenceTaskId = typeof rawTaskId === "string" && rawTaskId.length <= 20 && /^\d+\.\d+$/.test(rawTaskId.trim()) ? rawTaskId.trim() : getEvidenceTaskId(session, directory);
50993
+ const evidenceTaskId = typeof rawTaskId === "string" && rawTaskId.length <= 20 && /^\d+\.\d+$/.test(rawTaskId.trim()) ? rawTaskId.trim() : await getEvidenceTaskId(session, directory);
50881
50994
  if (evidenceTaskId) {
50882
50995
  try {
50883
50996
  const turbo = hasActiveTurboMode();
@@ -50997,7 +51110,7 @@ function createDelegationGateHook(config3, directory) {
50997
51110
  }
50998
51111
  {
50999
51112
  const rawTaskId = directArgs?.task_id;
51000
- const evidenceTaskId = typeof rawTaskId === "string" && rawTaskId.length <= 20 && /^\d+\.\d+$/.test(rawTaskId.trim()) ? rawTaskId.trim() : getEvidenceTaskId(session, directory);
51113
+ const evidenceTaskId = typeof rawTaskId === "string" && rawTaskId.length <= 20 && /^\d+\.\d+$/.test(rawTaskId.trim()) ? rawTaskId.trim() : await getEvidenceTaskId(session, directory);
51001
51114
  if (evidenceTaskId) {
51002
51115
  try {
51003
51116
  const turbo = hasActiveTurboMode();
@@ -51094,7 +51207,7 @@ ${trimComment}${after}`;
51094
51207
  const currentTaskId = planTaskId ?? taskIdFromLine;
51095
51208
  const coderDelegationPattern = /(?:^|\n)\s*(?:\w+_)?coder\s*\n\s*TASK:/i;
51096
51209
  const isCoderDelegation = coderDelegationPattern.test(text);
51097
- const priorCoderTaskId = sessionID ? ensureAgentSession(sessionID).lastCoderDelegationTaskId ?? null : null;
51210
+ const priorCoderTaskId = sessionID ? swarmState.agentSessions.get(sessionID)?.lastCoderDelegationTaskId ?? null : null;
51098
51211
  if (sessionID && isCoderDelegation && currentTaskId) {
51099
51212
  const session = ensureAgentSession(sessionID);
51100
51213
  session.lastCoderDelegationTaskId = currentTaskId;
@@ -54872,7 +54985,11 @@ function deserializeAgentSession(s) {
54872
54985
  lastScopeViolation: null,
54873
54986
  scopeViolationDetected: s.scopeViolationDetected,
54874
54987
  modifiedFilesThisCoderTask: [],
54875
- pendingAdvisoryMessages: s.pendingAdvisoryMessages ?? []
54988
+ pendingAdvisoryMessages: s.pendingAdvisoryMessages ?? [],
54989
+ model_fallback_index: s.model_fallback_index ?? 0,
54990
+ modelFallbackExhausted: s.modelFallbackExhausted ?? false,
54991
+ coderRevisions: s.coderRevisions ?? 0,
54992
+ revisionLimitHit: s.revisionLimitHit ?? false
54876
54993
  };
54877
54994
  }
54878
54995
  async function readSnapshot(directory) {
@@ -55115,6 +55232,7 @@ var build_check = createSwarmTool({
55115
55232
  });
55116
55233
  // src/tools/check-gate-status.ts
55117
55234
  init_dist();
55235
+ init_manager();
55118
55236
  init_create_tool();
55119
55237
  import * as fs27 from "fs";
55120
55238
  import * as path39 from "path";
@@ -55238,13 +55356,37 @@ var check_gate_status = createSwarmTool({
55238
55356
  missingGates.push(requiredGate);
55239
55357
  }
55240
55358
  }
55241
- const status = missingGates.length === 0 ? "all_passed" : "incomplete";
55359
+ let status = missingGates.length === 0 ? "all_passed" : "incomplete";
55242
55360
  let message;
55243
55361
  if (status === "all_passed") {
55244
55362
  message = `All required gates have passed for task "${taskIdInput}".`;
55245
55363
  } else {
55246
55364
  message = `Task "${taskIdInput}" is incomplete. Missing gates: ${missingGates.join(", ")}.`;
55247
55365
  }
55366
+ let secretscanVerdict = "not_run";
55367
+ try {
55368
+ const evidenceResult = await loadEvidence(directory, taskIdInput);
55369
+ if (evidenceResult.status === "found") {
55370
+ const secretscanEntries = evidenceResult.bundle.entries.filter((entry) => entry.type === "secretscan");
55371
+ if (secretscanEntries.length > 0) {
55372
+ const lastSecretscan = secretscanEntries[secretscanEntries.length - 1];
55373
+ if (isSecretscanEvidence(lastSecretscan)) {
55374
+ if (lastSecretscan.verdict === "fail" || lastSecretscan.verdict === "rejected") {
55375
+ secretscanVerdict = "fail";
55376
+ missingGates.push("secretscan (BLOCKED \u2014 secrets detected)");
55377
+ if (status === "all_passed") {
55378
+ status = "incomplete";
55379
+ }
55380
+ message = `BLOCKED: Secretscan found secrets in prior scan. ${message}`;
55381
+ } else if (lastSecretscan.verdict === "pass" || lastSecretscan.verdict === "approved" || lastSecretscan.verdict === "info") {
55382
+ secretscanVerdict = "pass";
55383
+ }
55384
+ }
55385
+ } else {
55386
+ message += " Advisory: No secretscan evidence found for this task. Consider running secretscan.";
55387
+ }
55388
+ }
55389
+ } catch {}
55248
55390
  const todoScan = evidenceData.todo_scan;
55249
55391
  const result = {
55250
55392
  taskId: taskIdInput,
@@ -55254,7 +55396,8 @@ var check_gate_status = createSwarmTool({
55254
55396
  missing_gates: missingGates,
55255
55397
  gates: gatesMap,
55256
55398
  message,
55257
- todo_scan: todoScan ?? null
55399
+ todo_scan: todoScan ?? null,
55400
+ secretscan_verdict: secretscanVerdict
55258
55401
  };
55259
55402
  return JSON.stringify(result, null, 2);
55260
55403
  }
@@ -55980,6 +56123,391 @@ var diff = createSwarmTool({
55980
56123
  }
55981
56124
  }
55982
56125
  });
56126
+ // src/tools/doc-scan.ts
56127
+ init_dist();
56128
+ init_schema();
56129
+ import * as crypto4 from "crypto";
56130
+ import * as fs30 from "fs";
56131
+ import { mkdir as mkdir5, readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
56132
+ import * as path42 from "path";
56133
+ init_create_tool();
56134
+ var SKIP_DIRECTORIES2 = new Set([
56135
+ "node_modules",
56136
+ ".git",
56137
+ ".swarm",
56138
+ "dist",
56139
+ "build",
56140
+ ".next",
56141
+ "vendor"
56142
+ ]);
56143
+ var SKIP_PATTERNS = [/\.test\./, /\.spec\./, /\.d\.ts$/];
56144
+ var MAX_SUMMARY_LENGTH = 200;
56145
+ var MAX_INDEXED_FILES = 100;
56146
+ var READ_LINES_LIMIT = 30;
56147
+ var MIN_LESSON_LENGTH = 15;
56148
+ var MAX_CONSTRAINTS_PER_DOC = 5;
56149
+ var MAX_CONSTRAINT_LENGTH = 200;
56150
+ var RELEVANCE_THRESHOLD = 0.1;
56151
+ var DEDUP_THRESHOLD = 0.6;
56152
+ function normalizeSeparators(filePath) {
56153
+ return filePath.replace(/\\/g, "/");
56154
+ }
56155
+ function matchesDocPattern(filePath, patterns) {
56156
+ const normalizedPath = normalizeSeparators(filePath);
56157
+ const basename5 = path42.basename(filePath);
56158
+ for (const pattern of patterns) {
56159
+ if (!pattern.includes("/") && !pattern.includes("\\")) {
56160
+ if (basename5 === pattern) {
56161
+ return true;
56162
+ }
56163
+ continue;
56164
+ }
56165
+ if (pattern.startsWith("**/")) {
56166
+ const filenamePattern = pattern.slice(3);
56167
+ if (basename5 === filenamePattern) {
56168
+ return true;
56169
+ }
56170
+ continue;
56171
+ }
56172
+ const patternNormalized = normalizeSeparators(pattern);
56173
+ const dirPrefix = patternNormalized.replace(/\/\*\*.*$/, "").replace(/\/\*.*$/, "");
56174
+ if (normalizedPath.startsWith(dirPrefix + "/") || normalizedPath === dirPrefix) {
56175
+ return true;
56176
+ }
56177
+ }
56178
+ return false;
56179
+ }
56180
+ function extractTitleAndSummary(content, filename) {
56181
+ const lines = content.split(`
56182
+ `);
56183
+ let title = filename;
56184
+ let summary = "";
56185
+ let foundTitle = false;
56186
+ const potentialSummaryLines = [];
56187
+ for (let i2 = 0;i2 < lines.length && i2 < READ_LINES_LIMIT; i2++) {
56188
+ const line = lines[i2].trim();
56189
+ if (!foundTitle && line.startsWith("# ")) {
56190
+ title = line.slice(2).trim();
56191
+ foundTitle = true;
56192
+ continue;
56193
+ }
56194
+ if (line && !line.startsWith("#")) {
56195
+ potentialSummaryLines.push(line);
56196
+ }
56197
+ }
56198
+ for (const line of potentialSummaryLines) {
56199
+ summary += (summary ? " " : "") + line;
56200
+ if (summary.length >= MAX_SUMMARY_LENGTH) {
56201
+ break;
56202
+ }
56203
+ }
56204
+ if (summary.length > MAX_SUMMARY_LENGTH) {
56205
+ summary = summary.slice(0, MAX_SUMMARY_LENGTH - 3) + "...";
56206
+ }
56207
+ return { title, summary };
56208
+ }
56209
+ function stripMarkdown(text) {
56210
+ return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*\u2022]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
56211
+ }
56212
+ async function scanDocIndex(directory) {
56213
+ const manifestPath = path42.join(directory, ".swarm", "doc-manifest.json");
56214
+ const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
56215
+ const extraPatterns = [
56216
+ "ARCHITECTURE.md",
56217
+ "CLAUDE.md",
56218
+ "AGENTS.md",
56219
+ ".github/*.md",
56220
+ "doc/**/*.md"
56221
+ ];
56222
+ const allPatterns = [...defaultPatterns, ...extraPatterns];
56223
+ try {
56224
+ const manifestContent = await readFile6(manifestPath, "utf-8");
56225
+ const existingManifest = JSON.parse(manifestContent);
56226
+ if (existingManifest.schema_version === 1 && existingManifest.files) {
56227
+ let cacheValid = true;
56228
+ for (const file3 of existingManifest.files) {
56229
+ try {
56230
+ const fullPath = path42.join(directory, file3.path);
56231
+ const stat2 = fs30.statSync(fullPath);
56232
+ if (stat2.mtimeMs > new Date(existingManifest.scanned_at).getTime()) {
56233
+ cacheValid = false;
56234
+ break;
56235
+ }
56236
+ } catch {
56237
+ cacheValid = false;
56238
+ break;
56239
+ }
56240
+ }
56241
+ if (cacheValid) {
56242
+ return { manifest: existingManifest, cached: true };
56243
+ }
56244
+ }
56245
+ } catch {}
56246
+ const discoveredFiles = [];
56247
+ let rawEntries;
56248
+ try {
56249
+ rawEntries = fs30.readdirSync(directory, { recursive: true });
56250
+ } catch {
56251
+ const manifest2 = {
56252
+ schema_version: 1,
56253
+ scanned_at: new Date().toISOString(),
56254
+ files: []
56255
+ };
56256
+ return { manifest: manifest2, cached: false };
56257
+ }
56258
+ const entries = rawEntries.filter((e) => typeof e === "string");
56259
+ for (const entry of entries) {
56260
+ const fullPath = path42.join(directory, entry);
56261
+ let stat2;
56262
+ try {
56263
+ stat2 = fs30.statSync(fullPath);
56264
+ } catch {
56265
+ continue;
56266
+ }
56267
+ if (!stat2.isFile())
56268
+ continue;
56269
+ const pathParts = normalizeSeparators(entry).split("/");
56270
+ let skipThisFile = false;
56271
+ for (const part of pathParts) {
56272
+ if (SKIP_DIRECTORIES2.has(part)) {
56273
+ skipThisFile = true;
56274
+ break;
56275
+ }
56276
+ }
56277
+ if (skipThisFile)
56278
+ continue;
56279
+ for (const pattern of SKIP_PATTERNS) {
56280
+ if (pattern.test(entry)) {
56281
+ skipThisFile = true;
56282
+ break;
56283
+ }
56284
+ }
56285
+ if (skipThisFile)
56286
+ continue;
56287
+ if (!matchesDocPattern(entry, allPatterns)) {
56288
+ continue;
56289
+ }
56290
+ let content;
56291
+ try {
56292
+ content = fs30.readFileSync(fullPath, "utf-8");
56293
+ } catch {
56294
+ continue;
56295
+ }
56296
+ const { title, summary } = extractTitleAndSummary(content, path42.basename(entry));
56297
+ const lineCount = content.split(`
56298
+ `).length;
56299
+ discoveredFiles.push({
56300
+ path: entry,
56301
+ title,
56302
+ summary,
56303
+ lines: lineCount,
56304
+ mtime: stat2.mtimeMs
56305
+ });
56306
+ }
56307
+ discoveredFiles.sort((a, b) => a.path.toLowerCase().localeCompare(b.path.toLowerCase()));
56308
+ let truncated = false;
56309
+ if (discoveredFiles.length > MAX_INDEXED_FILES) {
56310
+ discoveredFiles.splice(MAX_INDEXED_FILES);
56311
+ truncated = true;
56312
+ }
56313
+ if (truncated && discoveredFiles.length > 0) {
56314
+ discoveredFiles[0].summary = `[Warning: ${MAX_INDEXED_FILES}+ docs found, listing first ${MAX_INDEXED_FILES}] ` + discoveredFiles[0].summary;
56315
+ }
56316
+ const manifest = {
56317
+ schema_version: 1,
56318
+ scanned_at: new Date().toISOString(),
56319
+ files: discoveredFiles
56320
+ };
56321
+ try {
56322
+ await mkdir5(path42.dirname(manifestPath), { recursive: true });
56323
+ await writeFile5(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
56324
+ } catch {}
56325
+ return { manifest, cached: false };
56326
+ }
56327
+ var CONSTRAINT_PATTERNS = [
56328
+ /\bMUST\b/,
56329
+ /\bMUST NOT\b/,
56330
+ /\bSHOULD\b/,
56331
+ /\bSHOULD NOT\b/,
56332
+ /\bDO NOT\b/,
56333
+ /\bALWAYS\b/,
56334
+ /\bNEVER\b/,
56335
+ /\bREQUIRED\b/
56336
+ ];
56337
+ var ACTION_WORDS = /\b(must|should|don't|avoid|ensure|use|follow)\b/i;
56338
+ function isConstraintLine(line) {
56339
+ const upperLine = line.toUpperCase();
56340
+ for (const pattern of CONSTRAINT_PATTERNS) {
56341
+ if (pattern.test(upperLine)) {
56342
+ return true;
56343
+ }
56344
+ }
56345
+ if (/^\s*[-*\u2022]/.test(line) && ACTION_WORDS.test(line)) {
56346
+ return true;
56347
+ }
56348
+ return false;
56349
+ }
56350
+ function extractConstraintsFromContent(content) {
56351
+ const lines = content.split(`
56352
+ `);
56353
+ const constraints = [];
56354
+ for (const line of lines) {
56355
+ if (constraints.length >= MAX_CONSTRAINTS_PER_DOC) {
56356
+ break;
56357
+ }
56358
+ const trimmed = line.trim();
56359
+ if (!trimmed)
56360
+ continue;
56361
+ if (isConstraintLine(trimmed)) {
56362
+ const cleaned = stripMarkdown(trimmed);
56363
+ const len = cleaned.length;
56364
+ if (len >= MIN_LESSON_LENGTH && len <= MAX_CONSTRAINT_LENGTH) {
56365
+ constraints.push(cleaned);
56366
+ }
56367
+ }
56368
+ }
56369
+ return constraints;
56370
+ }
56371
+ async function extractDocConstraints(directory, taskFiles, taskDescription) {
56372
+ const manifestPath = path42.join(directory, ".swarm", "doc-manifest.json");
56373
+ let manifest;
56374
+ try {
56375
+ const content = await readFile6(manifestPath, "utf-8");
56376
+ manifest = JSON.parse(content);
56377
+ } catch {
56378
+ const result = await scanDocIndex(directory);
56379
+ manifest = result.manifest;
56380
+ }
56381
+ const knowledgePath = resolveSwarmKnowledgePath(directory);
56382
+ const existingEntries = await readKnowledge(knowledgePath);
56383
+ const taskContext = [...taskFiles, taskDescription].join(" ");
56384
+ const taskBigrams = wordBigrams(normalize2(taskContext));
56385
+ let extractedCount = 0;
56386
+ let skippedCount = 0;
56387
+ const details = [];
56388
+ for (const docFile of manifest.files) {
56389
+ const docContext = `${docFile.path} ${docFile.title} ${docFile.summary}`;
56390
+ const docBigrams = wordBigrams(normalize2(docContext));
56391
+ const score = jaccardBigram(taskBigrams, docBigrams);
56392
+ if (score <= RELEVANCE_THRESHOLD) {
56393
+ skippedCount++;
56394
+ continue;
56395
+ }
56396
+ let fullContent;
56397
+ try {
56398
+ fullContent = await readFile6(path42.join(directory, docFile.path), "utf-8");
56399
+ } catch {
56400
+ skippedCount++;
56401
+ continue;
56402
+ }
56403
+ const constraints = extractConstraintsFromContent(fullContent);
56404
+ if (constraints.length === 0) {
56405
+ skippedCount++;
56406
+ continue;
56407
+ }
56408
+ const docDetails = {
56409
+ path: docFile.path,
56410
+ score,
56411
+ constraints: []
56412
+ };
56413
+ for (const constraint of constraints) {
56414
+ const duplicate = findNearDuplicate(constraint, existingEntries, DEDUP_THRESHOLD);
56415
+ if (!duplicate) {
56416
+ const entry = {
56417
+ id: crypto4.randomUUID(),
56418
+ tier: "swarm",
56419
+ lesson: constraint,
56420
+ category: "architecture",
56421
+ tags: ["doc-scan", path42.basename(docFile.path)],
56422
+ scope: "global",
56423
+ confidence: 0.5,
56424
+ status: "candidate",
56425
+ confirmed_by: [],
56426
+ project_name: "",
56427
+ retrieval_outcomes: {
56428
+ applied_count: 0,
56429
+ succeeded_after_count: 0,
56430
+ failed_after_count: 0
56431
+ },
56432
+ schema_version: 1,
56433
+ created_at: new Date().toISOString(),
56434
+ updated_at: new Date().toISOString(),
56435
+ auto_generated: true,
56436
+ hive_eligible: false
56437
+ };
56438
+ await appendKnowledge(knowledgePath, entry);
56439
+ existingEntries.push(entry);
56440
+ extractedCount++;
56441
+ docDetails.constraints.push(constraint);
56442
+ }
56443
+ }
56444
+ if (docDetails.constraints.length > 0) {
56445
+ details.push(docDetails);
56446
+ } else {
56447
+ skippedCount++;
56448
+ }
56449
+ }
56450
+ return { extracted: extractedCount, skipped: skippedCount, details };
56451
+ }
56452
+ var doc_scan = createSwarmTool({
56453
+ description: "Scan project documentation files and build an index manifest. Caches results in .swarm/doc-manifest.json for fast subsequent scans.",
56454
+ args: {
56455
+ force: tool.schema.boolean().optional().describe("Force re-scan even if cache is valid")
56456
+ },
56457
+ execute: async (args2, directory) => {
56458
+ let force = false;
56459
+ try {
56460
+ if (args2 && typeof args2 === "object") {
56461
+ const obj = args2;
56462
+ if (obj.force === true)
56463
+ force = true;
56464
+ }
56465
+ } catch {}
56466
+ if (force) {
56467
+ const manifestPath = path42.join(directory, ".swarm", "doc-manifest.json");
56468
+ try {
56469
+ fs30.unlinkSync(manifestPath);
56470
+ } catch {}
56471
+ }
56472
+ const { manifest, cached: cached3 } = await scanDocIndex(directory);
56473
+ return JSON.stringify({
56474
+ success: true,
56475
+ files_count: manifest.files.length,
56476
+ cached: cached3,
56477
+ manifest
56478
+ }, null, 2);
56479
+ }
56480
+ });
56481
+ var doc_extract = createSwarmTool({
56482
+ description: "Extract actionable constraints from project documentation relevant to the current task. Scans docs via doc-manifest, scores relevance via Jaccard bigram similarity, and stores non-duplicate constraints in .swarm/knowledge.jsonl.",
56483
+ args: {
56484
+ task_files: tool.schema.array(tool.schema.string()).describe("List of file paths involved in the current task"),
56485
+ task_description: tool.schema.string().describe("Description of the current task")
56486
+ },
56487
+ execute: async (args2, directory) => {
56488
+ let taskFiles = [];
56489
+ let taskDescription = "";
56490
+ try {
56491
+ if (args2 && typeof args2 === "object") {
56492
+ const obj = args2;
56493
+ if (Array.isArray(obj.task_files)) {
56494
+ taskFiles = obj.task_files.filter((f) => typeof f === "string");
56495
+ }
56496
+ if (typeof obj.task_description === "string") {
56497
+ taskDescription = obj.task_description;
56498
+ }
56499
+ }
56500
+ } catch {}
56501
+ if (taskFiles.length === 0 && !taskDescription) {
56502
+ return JSON.stringify({
56503
+ success: false,
56504
+ error: "task_files or task_description is required"
56505
+ });
56506
+ }
56507
+ const result = await extractDocConstraints(directory, taskFiles, taskDescription);
56508
+ return JSON.stringify({ success: true, ...result }, null, 2);
56509
+ }
56510
+ });
55983
56511
  // src/tools/domain-detector.ts
55984
56512
  init_tool();
55985
56513
  var DOMAIN_PATTERNS = {
@@ -56163,8 +56691,8 @@ Use these as DOMAIN values when delegating to @sme.`;
56163
56691
  // src/tools/evidence-check.ts
56164
56692
  init_dist();
56165
56693
  init_create_tool();
56166
- import * as fs30 from "fs";
56167
- import * as path42 from "path";
56694
+ import * as fs31 from "fs";
56695
+ import * as path43 from "path";
56168
56696
  var MAX_FILE_SIZE_BYTES3 = 1024 * 1024;
56169
56697
  var MAX_EVIDENCE_FILES = 1000;
56170
56698
  var EVIDENCE_DIR2 = ".swarm/evidence";
@@ -56194,9 +56722,9 @@ function validateRequiredTypes(input) {
56194
56722
  return null;
56195
56723
  }
56196
56724
  function isPathWithinSwarm2(filePath, cwd) {
56197
- const normalizedCwd = path42.resolve(cwd);
56198
- const swarmPath = path42.join(normalizedCwd, ".swarm");
56199
- const normalizedPath = path42.resolve(filePath);
56725
+ const normalizedCwd = path43.resolve(cwd);
56726
+ const swarmPath = path43.join(normalizedCwd, ".swarm");
56727
+ const normalizedPath = path43.resolve(filePath);
56200
56728
  return normalizedPath.startsWith(swarmPath);
56201
56729
  }
56202
56730
  function parseCompletedTasks(planContent) {
@@ -56212,12 +56740,12 @@ function parseCompletedTasks(planContent) {
56212
56740
  }
56213
56741
  function readEvidenceFiles(evidenceDir, _cwd) {
56214
56742
  const evidence = [];
56215
- if (!fs30.existsSync(evidenceDir) || !fs30.statSync(evidenceDir).isDirectory()) {
56743
+ if (!fs31.existsSync(evidenceDir) || !fs31.statSync(evidenceDir).isDirectory()) {
56216
56744
  return evidence;
56217
56745
  }
56218
56746
  let files;
56219
56747
  try {
56220
- files = fs30.readdirSync(evidenceDir);
56748
+ files = fs31.readdirSync(evidenceDir);
56221
56749
  } catch {
56222
56750
  return evidence;
56223
56751
  }
@@ -56226,14 +56754,14 @@ function readEvidenceFiles(evidenceDir, _cwd) {
56226
56754
  if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
56227
56755
  continue;
56228
56756
  }
56229
- const filePath = path42.join(evidenceDir, filename);
56757
+ const filePath = path43.join(evidenceDir, filename);
56230
56758
  try {
56231
- const resolvedPath = path42.resolve(filePath);
56232
- const evidenceDirResolved = path42.resolve(evidenceDir);
56759
+ const resolvedPath = path43.resolve(filePath);
56760
+ const evidenceDirResolved = path43.resolve(evidenceDir);
56233
56761
  if (!resolvedPath.startsWith(evidenceDirResolved)) {
56234
56762
  continue;
56235
56763
  }
56236
- const stat2 = fs30.lstatSync(filePath);
56764
+ const stat2 = fs31.lstatSync(filePath);
56237
56765
  if (!stat2.isFile()) {
56238
56766
  continue;
56239
56767
  }
@@ -56242,7 +56770,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
56242
56770
  }
56243
56771
  let fileStat;
56244
56772
  try {
56245
- fileStat = fs30.statSync(filePath);
56773
+ fileStat = fs31.statSync(filePath);
56246
56774
  if (fileStat.size > MAX_FILE_SIZE_BYTES3) {
56247
56775
  continue;
56248
56776
  }
@@ -56251,7 +56779,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
56251
56779
  }
56252
56780
  let content;
56253
56781
  try {
56254
- content = fs30.readFileSync(filePath, "utf-8");
56782
+ content = fs31.readFileSync(filePath, "utf-8");
56255
56783
  } catch {
56256
56784
  continue;
56257
56785
  }
@@ -56347,7 +56875,7 @@ var evidence_check = createSwarmTool({
56347
56875
  return JSON.stringify(errorResult, null, 2);
56348
56876
  }
56349
56877
  const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
56350
- const planPath = path42.join(cwd, PLAN_FILE);
56878
+ const planPath = path43.join(cwd, PLAN_FILE);
56351
56879
  if (!isPathWithinSwarm2(planPath, cwd)) {
56352
56880
  const errorResult = {
56353
56881
  error: "plan file path validation failed",
@@ -56361,7 +56889,7 @@ var evidence_check = createSwarmTool({
56361
56889
  }
56362
56890
  let planContent;
56363
56891
  try {
56364
- planContent = fs30.readFileSync(planPath, "utf-8");
56892
+ planContent = fs31.readFileSync(planPath, "utf-8");
56365
56893
  } catch {
56366
56894
  const result2 = {
56367
56895
  message: "No completed tasks found in plan.",
@@ -56379,7 +56907,7 @@ var evidence_check = createSwarmTool({
56379
56907
  };
56380
56908
  return JSON.stringify(result2, null, 2);
56381
56909
  }
56382
- const evidenceDir = path42.join(cwd, EVIDENCE_DIR2);
56910
+ const evidenceDir = path43.join(cwd, EVIDENCE_DIR2);
56383
56911
  const evidence = readEvidenceFiles(evidenceDir, cwd);
56384
56912
  const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
56385
56913
  const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
@@ -56396,8 +56924,8 @@ var evidence_check = createSwarmTool({
56396
56924
  // src/tools/file-extractor.ts
56397
56925
  init_tool();
56398
56926
  init_create_tool();
56399
- import * as fs31 from "fs";
56400
- import * as path43 from "path";
56927
+ import * as fs32 from "fs";
56928
+ import * as path44 from "path";
56401
56929
  var EXT_MAP = {
56402
56930
  python: ".py",
56403
56931
  py: ".py",
@@ -56459,8 +56987,8 @@ var extract_code_blocks = createSwarmTool({
56459
56987
  execute: async (args2, directory) => {
56460
56988
  const { content, output_dir, prefix } = args2;
56461
56989
  const targetDir = output_dir || directory;
56462
- if (!fs31.existsSync(targetDir)) {
56463
- fs31.mkdirSync(targetDir, { recursive: true });
56990
+ if (!fs32.existsSync(targetDir)) {
56991
+ fs32.mkdirSync(targetDir, { recursive: true });
56464
56992
  }
56465
56993
  if (!content) {
56466
56994
  return "Error: content is required";
@@ -56478,16 +57006,16 @@ var extract_code_blocks = createSwarmTool({
56478
57006
  if (prefix) {
56479
57007
  filename = `${prefix}_${filename}`;
56480
57008
  }
56481
- let filepath = path43.join(targetDir, filename);
56482
- const base = path43.basename(filepath, path43.extname(filepath));
56483
- const ext = path43.extname(filepath);
57009
+ let filepath = path44.join(targetDir, filename);
57010
+ const base = path44.basename(filepath, path44.extname(filepath));
57011
+ const ext = path44.extname(filepath);
56484
57012
  let counter = 1;
56485
- while (fs31.existsSync(filepath)) {
56486
- filepath = path43.join(targetDir, `${base}_${counter}${ext}`);
57013
+ while (fs32.existsSync(filepath)) {
57014
+ filepath = path44.join(targetDir, `${base}_${counter}${ext}`);
56487
57015
  counter++;
56488
57016
  }
56489
57017
  try {
56490
- fs31.writeFileSync(filepath, code.trim(), "utf-8");
57018
+ fs32.writeFileSync(filepath, code.trim(), "utf-8");
56491
57019
  savedFiles.push(filepath);
56492
57020
  } catch (error93) {
56493
57021
  errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
@@ -56603,8 +57131,8 @@ var gitingest = createSwarmTool({
56603
57131
  // src/tools/imports.ts
56604
57132
  init_dist();
56605
57133
  init_create_tool();
56606
- import * as fs32 from "fs";
56607
- import * as path44 from "path";
57134
+ import * as fs33 from "fs";
57135
+ import * as path45 from "path";
56608
57136
  var MAX_FILE_PATH_LENGTH2 = 500;
56609
57137
  var MAX_SYMBOL_LENGTH = 256;
56610
57138
  var MAX_FILE_SIZE_BYTES4 = 1024 * 1024;
@@ -56658,7 +57186,7 @@ function validateSymbolInput(symbol3) {
56658
57186
  return null;
56659
57187
  }
56660
57188
  function isBinaryFile2(filePath, buffer) {
56661
- const ext = path44.extname(filePath).toLowerCase();
57189
+ const ext = path45.extname(filePath).toLowerCase();
56662
57190
  if (ext === ".json" || ext === ".md" || ext === ".txt") {
56663
57191
  return false;
56664
57192
  }
@@ -56682,15 +57210,15 @@ function parseImports(content, targetFile, targetSymbol) {
56682
57210
  const imports = [];
56683
57211
  let _resolvedTarget;
56684
57212
  try {
56685
- _resolvedTarget = path44.resolve(targetFile);
57213
+ _resolvedTarget = path45.resolve(targetFile);
56686
57214
  } catch {
56687
57215
  _resolvedTarget = targetFile;
56688
57216
  }
56689
- const targetBasename = path44.basename(targetFile, path44.extname(targetFile));
57217
+ const targetBasename = path45.basename(targetFile, path45.extname(targetFile));
56690
57218
  const targetWithExt = targetFile;
56691
57219
  const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
56692
- const normalizedTargetWithExt = path44.normalize(targetWithExt).replace(/\\/g, "/");
56693
- const normalizedTargetWithoutExt = path44.normalize(targetWithoutExt).replace(/\\/g, "/");
57220
+ const normalizedTargetWithExt = path45.normalize(targetWithExt).replace(/\\/g, "/");
57221
+ const normalizedTargetWithoutExt = path45.normalize(targetWithoutExt).replace(/\\/g, "/");
56694
57222
  const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
56695
57223
  for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
56696
57224
  const modulePath = match[1] || match[2] || match[3];
@@ -56713,9 +57241,9 @@ function parseImports(content, targetFile, targetSymbol) {
56713
57241
  }
56714
57242
  const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
56715
57243
  let isMatch = false;
56716
- const _targetDir = path44.dirname(targetFile);
56717
- const targetExt = path44.extname(targetFile);
56718
- const targetBasenameNoExt = path44.basename(targetFile, targetExt);
57244
+ const _targetDir = path45.dirname(targetFile);
57245
+ const targetExt = path45.extname(targetFile);
57246
+ const targetBasenameNoExt = path45.basename(targetFile, targetExt);
56719
57247
  const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
56720
57248
  const moduleName = modulePath.split(/[/\\]/).pop() || "";
56721
57249
  const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
@@ -56755,7 +57283,7 @@ function parseImports(content, targetFile, targetSymbol) {
56755
57283
  }
56756
57284
  return imports;
56757
57285
  }
56758
- var SKIP_DIRECTORIES2 = new Set([
57286
+ var SKIP_DIRECTORIES3 = new Set([
56759
57287
  "node_modules",
56760
57288
  ".git",
56761
57289
  "dist",
@@ -56772,7 +57300,7 @@ var SKIP_DIRECTORIES2 = new Set([
56772
57300
  function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
56773
57301
  let entries;
56774
57302
  try {
56775
- entries = fs32.readdirSync(dir);
57303
+ entries = fs33.readdirSync(dir);
56776
57304
  } catch (e) {
56777
57305
  stats.fileErrors.push({
56778
57306
  path: dir,
@@ -56782,14 +57310,14 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
56782
57310
  }
56783
57311
  entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
56784
57312
  for (const entry of entries) {
56785
- if (SKIP_DIRECTORIES2.has(entry)) {
56786
- stats.skippedDirs.push(path44.join(dir, entry));
57313
+ if (SKIP_DIRECTORIES3.has(entry)) {
57314
+ stats.skippedDirs.push(path45.join(dir, entry));
56787
57315
  continue;
56788
57316
  }
56789
- const fullPath = path44.join(dir, entry);
57317
+ const fullPath = path45.join(dir, entry);
56790
57318
  let stat2;
56791
57319
  try {
56792
- stat2 = fs32.statSync(fullPath);
57320
+ stat2 = fs33.statSync(fullPath);
56793
57321
  } catch (e) {
56794
57322
  stats.fileErrors.push({
56795
57323
  path: fullPath,
@@ -56800,7 +57328,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
56800
57328
  if (stat2.isDirectory()) {
56801
57329
  findSourceFiles(fullPath, files, stats);
56802
57330
  } else if (stat2.isFile()) {
56803
- const ext = path44.extname(fullPath).toLowerCase();
57331
+ const ext = path45.extname(fullPath).toLowerCase();
56804
57332
  if (SUPPORTED_EXTENSIONS.includes(ext)) {
56805
57333
  files.push(fullPath);
56806
57334
  }
@@ -56857,8 +57385,8 @@ var imports = createSwarmTool({
56857
57385
  return JSON.stringify(errorResult, null, 2);
56858
57386
  }
56859
57387
  try {
56860
- const targetFile = path44.resolve(file3);
56861
- if (!fs32.existsSync(targetFile)) {
57388
+ const targetFile = path45.resolve(file3);
57389
+ if (!fs33.existsSync(targetFile)) {
56862
57390
  const errorResult = {
56863
57391
  error: `target file not found: ${file3}`,
56864
57392
  target: file3,
@@ -56868,7 +57396,7 @@ var imports = createSwarmTool({
56868
57396
  };
56869
57397
  return JSON.stringify(errorResult, null, 2);
56870
57398
  }
56871
- const targetStat = fs32.statSync(targetFile);
57399
+ const targetStat = fs33.statSync(targetFile);
56872
57400
  if (!targetStat.isFile()) {
56873
57401
  const errorResult = {
56874
57402
  error: "target must be a file, not a directory",
@@ -56879,7 +57407,7 @@ var imports = createSwarmTool({
56879
57407
  };
56880
57408
  return JSON.stringify(errorResult, null, 2);
56881
57409
  }
56882
- const baseDir = path44.dirname(targetFile);
57410
+ const baseDir = path45.dirname(targetFile);
56883
57411
  const scanStats = {
56884
57412
  skippedDirs: [],
56885
57413
  skippedFiles: 0,
@@ -56894,12 +57422,12 @@ var imports = createSwarmTool({
56894
57422
  if (consumers.length >= MAX_CONSUMERS)
56895
57423
  break;
56896
57424
  try {
56897
- const stat2 = fs32.statSync(filePath);
57425
+ const stat2 = fs33.statSync(filePath);
56898
57426
  if (stat2.size > MAX_FILE_SIZE_BYTES4) {
56899
57427
  skippedFileCount++;
56900
57428
  continue;
56901
57429
  }
56902
- const buffer = fs32.readFileSync(filePath);
57430
+ const buffer = fs33.readFileSync(filePath);
56903
57431
  if (isBinaryFile2(filePath, buffer)) {
56904
57432
  skippedFileCount++;
56905
57433
  continue;
@@ -57448,8 +57976,8 @@ init_dist();
57448
57976
  init_config();
57449
57977
  init_schema();
57450
57978
  init_manager();
57451
- import * as fs33 from "fs";
57452
- import * as path45 from "path";
57979
+ import * as fs34 from "fs";
57980
+ import * as path46 from "path";
57453
57981
  init_utils2();
57454
57982
  init_create_tool();
57455
57983
  function safeWarn(message, error93) {
@@ -57668,7 +58196,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
57668
58196
  };
57669
58197
  if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
57670
58198
  try {
57671
- const projectName = path45.basename(dir);
58199
+ const projectName = path46.basename(dir);
57672
58200
  await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
57673
58201
  } catch (error93) {
57674
58202
  safeWarn("[phase_complete] Failed to curate lessons from retrospective:", error93);
@@ -57708,7 +58236,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
57708
58236
  if (agentsMissing.length > 0) {
57709
58237
  try {
57710
58238
  const planPath = validateSwarmPath(dir, "plan.json");
57711
- const planRaw = fs33.readFileSync(planPath, "utf-8");
58239
+ const planRaw = fs34.readFileSync(planPath, "utf-8");
57712
58240
  const plan = JSON.parse(planRaw);
57713
58241
  const targetPhase = plan.phases.find((p) => p.id === phase);
57714
58242
  if (targetPhase && targetPhase.tasks.length > 0 && targetPhase.tasks.every((t) => t.status === "completed")) {
@@ -57739,7 +58267,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
57739
58267
  if (phaseCompleteConfig.regression_sweep?.enforce) {
57740
58268
  try {
57741
58269
  const planPath = validateSwarmPath(dir, "plan.json");
57742
- const planRaw = fs33.readFileSync(planPath, "utf-8");
58270
+ const planRaw = fs34.readFileSync(planPath, "utf-8");
57743
58271
  const plan = JSON.parse(planRaw);
57744
58272
  const targetPhase = plan.phases.find((p) => p.id === phase);
57745
58273
  if (targetPhase) {
@@ -57777,7 +58305,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
57777
58305
  };
57778
58306
  try {
57779
58307
  const eventsPath = validateSwarmPath(dir, "events.jsonl");
57780
- fs33.appendFileSync(eventsPath, `${JSON.stringify(event)}
58308
+ fs34.appendFileSync(eventsPath, `${JSON.stringify(event)}
57781
58309
  `, "utf-8");
57782
58310
  } catch (writeError) {
57783
58311
  warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
@@ -57796,12 +58324,12 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
57796
58324
  }
57797
58325
  try {
57798
58326
  const planPath = validateSwarmPath(dir, "plan.json");
57799
- const planJson = fs33.readFileSync(planPath, "utf-8");
58327
+ const planJson = fs34.readFileSync(planPath, "utf-8");
57800
58328
  const plan = JSON.parse(planJson);
57801
58329
  const phaseObj = plan.phases.find((p) => p.id === phase);
57802
58330
  if (phaseObj) {
57803
58331
  phaseObj.status = "completed";
57804
- fs33.writeFileSync(planPath, `${JSON.stringify(plan, null, 2)}
58332
+ fs34.writeFileSync(planPath, `${JSON.stringify(plan, null, 2)}
57805
58333
  `, "utf-8");
57806
58334
  }
57807
58335
  } catch (error93) {
@@ -57855,8 +58383,8 @@ init_dist();
57855
58383
  init_discovery();
57856
58384
  init_utils();
57857
58385
  init_create_tool();
57858
- import * as fs34 from "fs";
57859
- import * as path46 from "path";
58386
+ import * as fs35 from "fs";
58387
+ import * as path47 from "path";
57860
58388
  var MAX_OUTPUT_BYTES5 = 52428800;
57861
58389
  var AUDIT_TIMEOUT_MS = 120000;
57862
58390
  function isValidEcosystem(value) {
@@ -57874,28 +58402,28 @@ function validateArgs3(args2) {
57874
58402
  function detectEcosystems(directory) {
57875
58403
  const ecosystems = [];
57876
58404
  const cwd = directory;
57877
- if (fs34.existsSync(path46.join(cwd, "package.json"))) {
58405
+ if (fs35.existsSync(path47.join(cwd, "package.json"))) {
57878
58406
  ecosystems.push("npm");
57879
58407
  }
57880
- if (fs34.existsSync(path46.join(cwd, "pyproject.toml")) || fs34.existsSync(path46.join(cwd, "requirements.txt"))) {
58408
+ if (fs35.existsSync(path47.join(cwd, "pyproject.toml")) || fs35.existsSync(path47.join(cwd, "requirements.txt"))) {
57881
58409
  ecosystems.push("pip");
57882
58410
  }
57883
- if (fs34.existsSync(path46.join(cwd, "Cargo.toml"))) {
58411
+ if (fs35.existsSync(path47.join(cwd, "Cargo.toml"))) {
57884
58412
  ecosystems.push("cargo");
57885
58413
  }
57886
- if (fs34.existsSync(path46.join(cwd, "go.mod"))) {
58414
+ if (fs35.existsSync(path47.join(cwd, "go.mod"))) {
57887
58415
  ecosystems.push("go");
57888
58416
  }
57889
58417
  try {
57890
- const files = fs34.readdirSync(cwd);
58418
+ const files = fs35.readdirSync(cwd);
57891
58419
  if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
57892
58420
  ecosystems.push("dotnet");
57893
58421
  }
57894
58422
  } catch {}
57895
- if (fs34.existsSync(path46.join(cwd, "Gemfile")) || fs34.existsSync(path46.join(cwd, "Gemfile.lock"))) {
58423
+ if (fs35.existsSync(path47.join(cwd, "Gemfile")) || fs35.existsSync(path47.join(cwd, "Gemfile.lock"))) {
57896
58424
  ecosystems.push("ruby");
57897
58425
  }
57898
- if (fs34.existsSync(path46.join(cwd, "pubspec.yaml"))) {
58426
+ if (fs35.existsSync(path47.join(cwd, "pubspec.yaml"))) {
57899
58427
  ecosystems.push("dart");
57900
58428
  }
57901
58429
  return ecosystems;
@@ -58957,8 +59485,8 @@ var SUPPORTED_PARSER_EXTENSIONS = new Set([
58957
59485
  ]);
58958
59486
  // src/tools/pre-check-batch.ts
58959
59487
  init_dist();
58960
- import * as fs37 from "fs";
58961
- import * as path49 from "path";
59488
+ import * as fs38 from "fs";
59489
+ import * as path50 from "path";
58962
59490
 
58963
59491
  // node_modules/yocto-queue/index.js
58964
59492
  class Node2 {
@@ -59103,8 +59631,8 @@ function pLimit(concurrency) {
59103
59631
  },
59104
59632
  map: {
59105
59633
  async value(iterable, function_) {
59106
- const promises3 = Array.from(iterable, (value, index) => this(function_, value, index));
59107
- return Promise.all(promises3);
59634
+ const promises4 = Array.from(iterable, (value, index) => this(function_, value, index));
59635
+ return Promise.all(promises4);
59108
59636
  }
59109
59637
  }
59110
59638
  });
@@ -59117,6 +59645,7 @@ function validateConcurrency(concurrency) {
59117
59645
  }
59118
59646
 
59119
59647
  // src/tools/pre-check-batch.ts
59648
+ init_manager();
59120
59649
  init_utils();
59121
59650
  init_create_tool();
59122
59651
  init_lint();
@@ -59125,8 +59654,8 @@ init_lint();
59125
59654
  init_manager();
59126
59655
 
59127
59656
  // src/quality/metrics.ts
59128
- import * as fs35 from "fs";
59129
- import * as path47 from "path";
59657
+ import * as fs36 from "fs";
59658
+ import * as path48 from "path";
59130
59659
  var MAX_FILE_SIZE_BYTES5 = 256 * 1024;
59131
59660
  var MIN_DUPLICATION_LINES = 10;
59132
59661
  function estimateCyclomaticComplexity(content) {
@@ -59164,11 +59693,11 @@ function estimateCyclomaticComplexity(content) {
59164
59693
  }
59165
59694
  function getComplexityForFile2(filePath) {
59166
59695
  try {
59167
- const stat2 = fs35.statSync(filePath);
59696
+ const stat2 = fs36.statSync(filePath);
59168
59697
  if (stat2.size > MAX_FILE_SIZE_BYTES5) {
59169
59698
  return null;
59170
59699
  }
59171
- const content = fs35.readFileSync(filePath, "utf-8");
59700
+ const content = fs36.readFileSync(filePath, "utf-8");
59172
59701
  return estimateCyclomaticComplexity(content);
59173
59702
  } catch {
59174
59703
  return null;
@@ -59178,8 +59707,8 @@ async function computeComplexityDelta(files, workingDir) {
59178
59707
  let totalComplexity = 0;
59179
59708
  const analyzedFiles = [];
59180
59709
  for (const file3 of files) {
59181
- const fullPath = path47.isAbsolute(file3) ? file3 : path47.join(workingDir, file3);
59182
- if (!fs35.existsSync(fullPath)) {
59710
+ const fullPath = path48.isAbsolute(file3) ? file3 : path48.join(workingDir, file3);
59711
+ if (!fs36.existsSync(fullPath)) {
59183
59712
  continue;
59184
59713
  }
59185
59714
  const complexity = getComplexityForFile2(fullPath);
@@ -59300,8 +59829,8 @@ function countGoExports(content) {
59300
59829
  }
59301
59830
  function getExportCountForFile(filePath) {
59302
59831
  try {
59303
- const content = fs35.readFileSync(filePath, "utf-8");
59304
- const ext = path47.extname(filePath).toLowerCase();
59832
+ const content = fs36.readFileSync(filePath, "utf-8");
59833
+ const ext = path48.extname(filePath).toLowerCase();
59305
59834
  switch (ext) {
59306
59835
  case ".ts":
59307
59836
  case ".tsx":
@@ -59327,8 +59856,8 @@ async function computePublicApiDelta(files, workingDir) {
59327
59856
  let totalExports = 0;
59328
59857
  const analyzedFiles = [];
59329
59858
  for (const file3 of files) {
59330
- const fullPath = path47.isAbsolute(file3) ? file3 : path47.join(workingDir, file3);
59331
- if (!fs35.existsSync(fullPath)) {
59859
+ const fullPath = path48.isAbsolute(file3) ? file3 : path48.join(workingDir, file3);
59860
+ if (!fs36.existsSync(fullPath)) {
59332
59861
  continue;
59333
59862
  }
59334
59863
  const exports = getExportCountForFile(fullPath);
@@ -59361,16 +59890,16 @@ async function computeDuplicationRatio(files, workingDir) {
59361
59890
  let duplicateLines = 0;
59362
59891
  const analyzedFiles = [];
59363
59892
  for (const file3 of files) {
59364
- const fullPath = path47.isAbsolute(file3) ? file3 : path47.join(workingDir, file3);
59365
- if (!fs35.existsSync(fullPath)) {
59893
+ const fullPath = path48.isAbsolute(file3) ? file3 : path48.join(workingDir, file3);
59894
+ if (!fs36.existsSync(fullPath)) {
59366
59895
  continue;
59367
59896
  }
59368
59897
  try {
59369
- const stat2 = fs35.statSync(fullPath);
59898
+ const stat2 = fs36.statSync(fullPath);
59370
59899
  if (stat2.size > MAX_FILE_SIZE_BYTES5) {
59371
59900
  continue;
59372
59901
  }
59373
- const content = fs35.readFileSync(fullPath, "utf-8");
59902
+ const content = fs36.readFileSync(fullPath, "utf-8");
59374
59903
  const lines = content.split(`
59375
59904
  `).filter((line) => line.trim().length > 0);
59376
59905
  if (lines.length < MIN_DUPLICATION_LINES) {
@@ -59394,8 +59923,8 @@ function countCodeLines(content) {
59394
59923
  return lines.length;
59395
59924
  }
59396
59925
  function isTestFile(filePath) {
59397
- const basename8 = path47.basename(filePath);
59398
- const _ext = path47.extname(filePath).toLowerCase();
59926
+ const basename9 = path48.basename(filePath);
59927
+ const _ext = path48.extname(filePath).toLowerCase();
59399
59928
  const testPatterns = [
59400
59929
  ".test.",
59401
59930
  ".spec.",
@@ -59410,7 +59939,7 @@ function isTestFile(filePath) {
59410
59939
  ".spec.jsx"
59411
59940
  ];
59412
59941
  for (const pattern of testPatterns) {
59413
- if (basename8.includes(pattern)) {
59942
+ if (basename9.includes(pattern)) {
59414
59943
  return true;
59415
59944
  }
59416
59945
  }
@@ -59476,8 +60005,8 @@ function matchGlobSegment(globSegments, pathSegments) {
59476
60005
  }
59477
60006
  return gIndex === globSegments.length && pIndex === pathSegments.length;
59478
60007
  }
59479
- function matchesGlobSegment(path48, glob) {
59480
- const normalizedPath = path48.replace(/\\/g, "/");
60008
+ function matchesGlobSegment(path49, glob) {
60009
+ const normalizedPath = path49.replace(/\\/g, "/");
59481
60010
  const normalizedGlob = glob.replace(/\\/g, "/");
59482
60011
  if (normalizedPath.includes("//")) {
59483
60012
  return false;
@@ -59508,8 +60037,8 @@ function simpleGlobToRegex2(glob) {
59508
60037
  function hasGlobstar(glob) {
59509
60038
  return glob.includes("**");
59510
60039
  }
59511
- function globMatches(path48, glob) {
59512
- const normalizedPath = path48.replace(/\\/g, "/");
60040
+ function globMatches(path49, glob) {
60041
+ const normalizedPath = path49.replace(/\\/g, "/");
59513
60042
  if (!glob || glob === "") {
59514
60043
  if (normalizedPath.includes("//")) {
59515
60044
  return false;
@@ -59545,31 +60074,31 @@ function shouldExcludeFile(filePath, excludeGlobs) {
59545
60074
  async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
59546
60075
  let testLines = 0;
59547
60076
  let codeLines = 0;
59548
- const srcDir = path47.join(workingDir, "src");
59549
- if (fs35.existsSync(srcDir)) {
60077
+ const srcDir = path48.join(workingDir, "src");
60078
+ if (fs36.existsSync(srcDir)) {
59550
60079
  await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
59551
60080
  codeLines += lines;
59552
60081
  });
59553
60082
  }
59554
60083
  const possibleSrcDirs = ["lib", "app", "source", "core"];
59555
60084
  for (const dir of possibleSrcDirs) {
59556
- const dirPath = path47.join(workingDir, dir);
59557
- if (fs35.existsSync(dirPath)) {
60085
+ const dirPath = path48.join(workingDir, dir);
60086
+ if (fs36.existsSync(dirPath)) {
59558
60087
  await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
59559
60088
  codeLines += lines;
59560
60089
  });
59561
60090
  }
59562
60091
  }
59563
- const testsDir = path47.join(workingDir, "tests");
59564
- if (fs35.existsSync(testsDir)) {
60092
+ const testsDir = path48.join(workingDir, "tests");
60093
+ if (fs36.existsSync(testsDir)) {
59565
60094
  await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
59566
60095
  testLines += lines;
59567
60096
  });
59568
60097
  }
59569
60098
  const possibleTestDirs = ["test", "__tests__", "specs"];
59570
60099
  for (const dir of possibleTestDirs) {
59571
- const dirPath = path47.join(workingDir, dir);
59572
- if (fs35.existsSync(dirPath) && dirPath !== testsDir) {
60100
+ const dirPath = path48.join(workingDir, dir);
60101
+ if (fs36.existsSync(dirPath) && dirPath !== testsDir) {
59573
60102
  await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
59574
60103
  testLines += lines;
59575
60104
  });
@@ -59581,9 +60110,9 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
59581
60110
  }
59582
60111
  async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTestScan, callback) {
59583
60112
  try {
59584
- const entries = fs35.readdirSync(dirPath, { withFileTypes: true });
60113
+ const entries = fs36.readdirSync(dirPath, { withFileTypes: true });
59585
60114
  for (const entry of entries) {
59586
- const fullPath = path47.join(dirPath, entry.name);
60115
+ const fullPath = path48.join(dirPath, entry.name);
59587
60116
  if (entry.isDirectory()) {
59588
60117
  if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
59589
60118
  continue;
@@ -59591,7 +60120,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
59591
60120
  await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
59592
60121
  } else if (entry.isFile()) {
59593
60122
  const relativePath = fullPath.replace(`${dirPath}/`, "");
59594
- const ext = path47.extname(entry.name).toLowerCase();
60123
+ const ext = path48.extname(entry.name).toLowerCase();
59595
60124
  const validExts = [
59596
60125
  ".ts",
59597
60126
  ".tsx",
@@ -59627,7 +60156,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
59627
60156
  continue;
59628
60157
  }
59629
60158
  try {
59630
- const content = fs35.readFileSync(fullPath, "utf-8");
60159
+ const content = fs36.readFileSync(fullPath, "utf-8");
59631
60160
  const lines = countCodeLines(content);
59632
60161
  callback(lines);
59633
60162
  } catch {}
@@ -59841,8 +60370,8 @@ async function qualityBudget(input, directory) {
59841
60370
  init_dist();
59842
60371
  init_manager();
59843
60372
  init_detector();
59844
- import * as fs36 from "fs";
59845
- import * as path48 from "path";
60373
+ import * as fs37 from "fs";
60374
+ import * as path49 from "path";
59846
60375
  import { extname as extname9 } from "path";
59847
60376
 
59848
60377
  // src/sast/rules/c.ts
@@ -60709,17 +61238,17 @@ var SEVERITY_ORDER = {
60709
61238
  };
60710
61239
  function shouldSkipFile(filePath) {
60711
61240
  try {
60712
- const stats = fs36.statSync(filePath);
61241
+ const stats = fs37.statSync(filePath);
60713
61242
  if (stats.size > MAX_FILE_SIZE_BYTES6) {
60714
61243
  return { skip: true, reason: "file too large" };
60715
61244
  }
60716
61245
  if (stats.size === 0) {
60717
61246
  return { skip: true, reason: "empty file" };
60718
61247
  }
60719
- const fd = fs36.openSync(filePath, "r");
61248
+ const fd = fs37.openSync(filePath, "r");
60720
61249
  const buffer = Buffer.alloc(8192);
60721
- const bytesRead = fs36.readSync(fd, buffer, 0, 8192, 0);
60722
- fs36.closeSync(fd);
61250
+ const bytesRead = fs37.readSync(fd, buffer, 0, 8192, 0);
61251
+ fs37.closeSync(fd);
60723
61252
  if (bytesRead > 0) {
60724
61253
  let nullCount = 0;
60725
61254
  for (let i2 = 0;i2 < bytesRead; i2++) {
@@ -60758,7 +61287,7 @@ function countBySeverity(findings) {
60758
61287
  }
60759
61288
  function scanFileWithTierA(filePath, language) {
60760
61289
  try {
60761
- const content = fs36.readFileSync(filePath, "utf-8");
61290
+ const content = fs37.readFileSync(filePath, "utf-8");
60762
61291
  const findings = executeRulesSync(filePath, content, language);
60763
61292
  return findings.map((f) => ({
60764
61293
  rule_id: f.rule_id,
@@ -60805,8 +61334,8 @@ async function sastScan(input, directory, config3) {
60805
61334
  _filesSkipped++;
60806
61335
  continue;
60807
61336
  }
60808
- const resolvedPath = path48.isAbsolute(filePath) ? filePath : path48.resolve(directory, filePath);
60809
- if (!fs36.existsSync(resolvedPath)) {
61337
+ const resolvedPath = path49.isAbsolute(filePath) ? filePath : path49.resolve(directory, filePath);
61338
+ if (!fs37.existsSync(resolvedPath)) {
60810
61339
  _filesSkipped++;
60811
61340
  continue;
60812
61341
  }
@@ -61004,18 +61533,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
61004
61533
  let resolved;
61005
61534
  const isWinAbs = isWindowsAbsolutePath(inputPath);
61006
61535
  if (isWinAbs) {
61007
- resolved = path49.win32.resolve(inputPath);
61008
- } else if (path49.isAbsolute(inputPath)) {
61009
- resolved = path49.resolve(inputPath);
61536
+ resolved = path50.win32.resolve(inputPath);
61537
+ } else if (path50.isAbsolute(inputPath)) {
61538
+ resolved = path50.resolve(inputPath);
61010
61539
  } else {
61011
- resolved = path49.resolve(baseDir, inputPath);
61540
+ resolved = path50.resolve(baseDir, inputPath);
61012
61541
  }
61013
- const workspaceResolved = path49.resolve(workspaceDir);
61542
+ const workspaceResolved = path50.resolve(workspaceDir);
61014
61543
  let relative6;
61015
61544
  if (isWinAbs) {
61016
- relative6 = path49.win32.relative(workspaceResolved, resolved);
61545
+ relative6 = path50.win32.relative(workspaceResolved, resolved);
61017
61546
  } else {
61018
- relative6 = path49.relative(workspaceResolved, resolved);
61547
+ relative6 = path50.relative(workspaceResolved, resolved);
61019
61548
  }
61020
61549
  if (relative6.startsWith("..")) {
61021
61550
  return "path traversal detected";
@@ -61076,13 +61605,13 @@ async function runLintWrapped(files, directory, _config) {
61076
61605
  }
61077
61606
  async function runLintOnFiles(linter, files, workspaceDir) {
61078
61607
  const isWindows = process.platform === "win32";
61079
- const binDir = path49.join(workspaceDir, "node_modules", ".bin");
61608
+ const binDir = path50.join(workspaceDir, "node_modules", ".bin");
61080
61609
  const validatedFiles = [];
61081
61610
  for (const file3 of files) {
61082
61611
  if (typeof file3 !== "string") {
61083
61612
  continue;
61084
61613
  }
61085
- const resolvedPath = path49.resolve(file3);
61614
+ const resolvedPath = path50.resolve(file3);
61086
61615
  const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
61087
61616
  if (validationError) {
61088
61617
  continue;
@@ -61100,10 +61629,10 @@ async function runLintOnFiles(linter, files, workspaceDir) {
61100
61629
  }
61101
61630
  let command;
61102
61631
  if (linter === "biome") {
61103
- const biomeBin = isWindows ? path49.join(binDir, "biome.EXE") : path49.join(binDir, "biome");
61632
+ const biomeBin = isWindows ? path50.join(binDir, "biome.EXE") : path50.join(binDir, "biome");
61104
61633
  command = [biomeBin, "check", ...validatedFiles];
61105
61634
  } else {
61106
- const eslintBin = isWindows ? path49.join(binDir, "eslint.cmd") : path49.join(binDir, "eslint");
61635
+ const eslintBin = isWindows ? path50.join(binDir, "eslint.cmd") : path50.join(binDir, "eslint");
61107
61636
  command = [eslintBin, ...validatedFiles];
61108
61637
  }
61109
61638
  try {
@@ -61240,7 +61769,7 @@ async function runSecretscanWithFiles(files, directory) {
61240
61769
  skippedFiles++;
61241
61770
  continue;
61242
61771
  }
61243
- const resolvedPath = path49.resolve(file3);
61772
+ const resolvedPath = path50.resolve(file3);
61244
61773
  const validationError = validatePath(resolvedPath, directory, directory);
61245
61774
  if (validationError) {
61246
61775
  skippedFiles++;
@@ -61258,14 +61787,14 @@ async function runSecretscanWithFiles(files, directory) {
61258
61787
  };
61259
61788
  }
61260
61789
  for (const file3 of validatedFiles) {
61261
- const ext = path49.extname(file3).toLowerCase();
61790
+ const ext = path50.extname(file3).toLowerCase();
61262
61791
  if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
61263
61792
  skippedFiles++;
61264
61793
  continue;
61265
61794
  }
61266
61795
  let stat2;
61267
61796
  try {
61268
- stat2 = fs37.statSync(file3);
61797
+ stat2 = fs38.statSync(file3);
61269
61798
  } catch {
61270
61799
  skippedFiles++;
61271
61800
  continue;
@@ -61276,7 +61805,7 @@ async function runSecretscanWithFiles(files, directory) {
61276
61805
  }
61277
61806
  let content;
61278
61807
  try {
61279
- const buffer = fs37.readFileSync(file3);
61808
+ const buffer = fs38.readFileSync(file3);
61280
61809
  if (buffer.includes(0)) {
61281
61810
  skippedFiles++;
61282
61811
  continue;
@@ -61417,7 +61946,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
61417
61946
  warn(`pre_check_batch: Invalid file path: ${file3}`);
61418
61947
  continue;
61419
61948
  }
61420
- changedFiles.push(path49.resolve(directory, file3));
61949
+ changedFiles.push(path50.resolve(directory, file3));
61421
61950
  }
61422
61951
  if (changedFiles.length === 0) {
61423
61952
  warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
@@ -61464,6 +61993,26 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
61464
61993
  gatesPassed = false;
61465
61994
  warn(`pre_check_batch: Secretscan error - GATE FAILED: ${secretscanResult.error}`);
61466
61995
  }
61996
+ if (secretscanResult.ran && secretscanResult.result) {
61997
+ try {
61998
+ const scanResult = secretscanResult.result;
61999
+ const secretscanEvidence = {
62000
+ task_id: "secretscan",
62001
+ type: "secretscan",
62002
+ timestamp: new Date().toISOString(),
62003
+ agent: "pre_check_batch",
62004
+ verdict: scanResult.count > 0 ? "fail" : "pass",
62005
+ summary: `Secretscan: ${scanResult.count} finding(s), ${scanResult.files_scanned ?? 0} files scanned, ${scanResult.skipped_files ?? 0} skipped`,
62006
+ findings_count: scanResult.count,
62007
+ scan_directory: scanResult.scan_dir,
62008
+ files_scanned: scanResult.files_scanned,
62009
+ skipped_files: scanResult.skipped_files
62010
+ };
62011
+ await saveEvidence(directory, "secretscan", secretscanEvidence);
62012
+ } catch (e) {
62013
+ warn(`Failed to persist secretscan evidence: ${e instanceof Error ? e.message : String(e)}`);
62014
+ }
62015
+ }
61467
62016
  if (sastScanResult.ran && sastScanResult.result) {
61468
62017
  if (sastScanResult.result.verdict === "fail") {
61469
62018
  gatesPassed = false;
@@ -61568,7 +62117,7 @@ var pre_check_batch = createSwarmTool({
61568
62117
  };
61569
62118
  return JSON.stringify(errorResult, null, 2);
61570
62119
  }
61571
- const resolvedDirectory = path49.resolve(typedArgs.directory);
62120
+ const resolvedDirectory = path50.resolve(typedArgs.directory);
61572
62121
  const workspaceAnchor = resolvedDirectory;
61573
62122
  const dirError = validateDirectory3(resolvedDirectory, workspaceAnchor);
61574
62123
  if (dirError) {
@@ -61676,8 +62225,8 @@ ${paginatedContent}`;
61676
62225
  init_tool();
61677
62226
  init_manager2();
61678
62227
  init_create_tool();
61679
- import * as fs38 from "fs";
61680
- import * as path50 from "path";
62228
+ import * as fs39 from "fs";
62229
+ import * as path51 from "path";
61681
62230
  function detectPlaceholderContent(args2) {
61682
62231
  const issues = [];
61683
62232
  const placeholderPattern = /^\[\w[\w\s]*\]$/;
@@ -61781,19 +62330,19 @@ async function executeSavePlan(args2, fallbackDir) {
61781
62330
  try {
61782
62331
  await savePlan(dir, plan);
61783
62332
  try {
61784
- const markerPath = path50.join(dir, ".swarm", ".plan-write-marker");
62333
+ const markerPath = path51.join(dir, ".swarm", ".plan-write-marker");
61785
62334
  const marker = JSON.stringify({
61786
62335
  source: "save_plan",
61787
62336
  timestamp: new Date().toISOString(),
61788
62337
  phases_count: plan.phases.length,
61789
62338
  tasks_count: tasksCount
61790
62339
  });
61791
- await fs38.promises.writeFile(markerPath, marker, "utf8");
62340
+ await fs39.promises.writeFile(markerPath, marker, "utf8");
61792
62341
  } catch {}
61793
62342
  return {
61794
62343
  success: true,
61795
62344
  message: "Plan saved successfully",
61796
- plan_path: path50.join(dir, ".swarm", "plan.json"),
62345
+ plan_path: path51.join(dir, ".swarm", "plan.json"),
61797
62346
  phases_count: plan.phases.length,
61798
62347
  tasks_count: tasksCount
61799
62348
  };
@@ -61831,8 +62380,8 @@ var save_plan = createSwarmTool({
61831
62380
  // src/tools/sbom-generate.ts
61832
62381
  init_dist();
61833
62382
  init_manager();
61834
- import * as fs39 from "fs";
61835
- import * as path51 from "path";
62383
+ import * as fs40 from "fs";
62384
+ import * as path52 from "path";
61836
62385
 
61837
62386
  // src/sbom/detectors/index.ts
61838
62387
  init_utils();
@@ -62678,9 +63227,9 @@ function findManifestFiles(rootDir) {
62678
63227
  const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
62679
63228
  function searchDir(dir) {
62680
63229
  try {
62681
- const entries = fs39.readdirSync(dir, { withFileTypes: true });
63230
+ const entries = fs40.readdirSync(dir, { withFileTypes: true });
62682
63231
  for (const entry of entries) {
62683
- const fullPath = path51.join(dir, entry.name);
63232
+ const fullPath = path52.join(dir, entry.name);
62684
63233
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
62685
63234
  continue;
62686
63235
  }
@@ -62689,7 +63238,7 @@ function findManifestFiles(rootDir) {
62689
63238
  } else if (entry.isFile()) {
62690
63239
  for (const pattern of patterns) {
62691
63240
  if (simpleGlobToRegex(pattern).test(entry.name)) {
62692
- manifestFiles.push(path51.relative(rootDir, fullPath));
63241
+ manifestFiles.push(path52.relative(rootDir, fullPath));
62693
63242
  break;
62694
63243
  }
62695
63244
  }
@@ -62705,13 +63254,13 @@ function findManifestFilesInDirs(directories, workingDir) {
62705
63254
  const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
62706
63255
  for (const dir of directories) {
62707
63256
  try {
62708
- const entries = fs39.readdirSync(dir, { withFileTypes: true });
63257
+ const entries = fs40.readdirSync(dir, { withFileTypes: true });
62709
63258
  for (const entry of entries) {
62710
- const fullPath = path51.join(dir, entry.name);
63259
+ const fullPath = path52.join(dir, entry.name);
62711
63260
  if (entry.isFile()) {
62712
63261
  for (const pattern of patterns) {
62713
63262
  if (simpleGlobToRegex(pattern).test(entry.name)) {
62714
- found.push(path51.relative(workingDir, fullPath));
63263
+ found.push(path52.relative(workingDir, fullPath));
62715
63264
  break;
62716
63265
  }
62717
63266
  }
@@ -62724,11 +63273,11 @@ function findManifestFilesInDirs(directories, workingDir) {
62724
63273
  function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
62725
63274
  const dirs = new Set;
62726
63275
  for (const file3 of changedFiles) {
62727
- let currentDir = path51.dirname(file3);
63276
+ let currentDir = path52.dirname(file3);
62728
63277
  while (true) {
62729
- if (currentDir && currentDir !== "." && currentDir !== path51.sep) {
62730
- dirs.add(path51.join(workingDir, currentDir));
62731
- const parent = path51.dirname(currentDir);
63278
+ if (currentDir && currentDir !== "." && currentDir !== path52.sep) {
63279
+ dirs.add(path52.join(workingDir, currentDir));
63280
+ const parent = path52.dirname(currentDir);
62732
63281
  if (parent === currentDir)
62733
63282
  break;
62734
63283
  currentDir = parent;
@@ -62742,7 +63291,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
62742
63291
  }
62743
63292
  function ensureOutputDir(outputDir) {
62744
63293
  try {
62745
- fs39.mkdirSync(outputDir, { recursive: true });
63294
+ fs40.mkdirSync(outputDir, { recursive: true });
62746
63295
  } catch (error93) {
62747
63296
  if (!error93 || error93.code !== "EEXIST") {
62748
63297
  throw error93;
@@ -62812,7 +63361,7 @@ var sbom_generate = createSwarmTool({
62812
63361
  const changedFiles = obj.changed_files;
62813
63362
  const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
62814
63363
  const workingDir = directory;
62815
- const outputDir = path51.isAbsolute(relativeOutputDir) ? relativeOutputDir : path51.join(workingDir, relativeOutputDir);
63364
+ const outputDir = path52.isAbsolute(relativeOutputDir) ? relativeOutputDir : path52.join(workingDir, relativeOutputDir);
62816
63365
  let manifestFiles = [];
62817
63366
  if (scope === "all") {
62818
63367
  manifestFiles = findManifestFiles(workingDir);
@@ -62835,11 +63384,11 @@ var sbom_generate = createSwarmTool({
62835
63384
  const processedFiles = [];
62836
63385
  for (const manifestFile of manifestFiles) {
62837
63386
  try {
62838
- const fullPath = path51.isAbsolute(manifestFile) ? manifestFile : path51.join(workingDir, manifestFile);
62839
- if (!fs39.existsSync(fullPath)) {
63387
+ const fullPath = path52.isAbsolute(manifestFile) ? manifestFile : path52.join(workingDir, manifestFile);
63388
+ if (!fs40.existsSync(fullPath)) {
62840
63389
  continue;
62841
63390
  }
62842
- const content = fs39.readFileSync(fullPath, "utf-8");
63391
+ const content = fs40.readFileSync(fullPath, "utf-8");
62843
63392
  const components = detectComponents(manifestFile, content);
62844
63393
  processedFiles.push(manifestFile);
62845
63394
  if (components.length > 0) {
@@ -62852,8 +63401,8 @@ var sbom_generate = createSwarmTool({
62852
63401
  const bom = generateCycloneDX(allComponents);
62853
63402
  const bomJson = serializeCycloneDX(bom);
62854
63403
  const filename = generateSbomFilename();
62855
- const outputPath = path51.join(outputDir, filename);
62856
- fs39.writeFileSync(outputPath, bomJson, "utf-8");
63404
+ const outputPath = path52.join(outputDir, filename);
63405
+ fs40.writeFileSync(outputPath, bomJson, "utf-8");
62857
63406
  const verdict = processedFiles.length > 0 ? "pass" : "pass";
62858
63407
  try {
62859
63408
  const timestamp = new Date().toISOString();
@@ -62895,8 +63444,8 @@ var sbom_generate = createSwarmTool({
62895
63444
  // src/tools/schema-drift.ts
62896
63445
  init_dist();
62897
63446
  init_create_tool();
62898
- import * as fs40 from "fs";
62899
- import * as path52 from "path";
63447
+ import * as fs41 from "fs";
63448
+ import * as path53 from "path";
62900
63449
  var SPEC_CANDIDATES = [
62901
63450
  "openapi.json",
62902
63451
  "openapi.yaml",
@@ -62928,28 +63477,28 @@ function normalizePath2(p) {
62928
63477
  }
62929
63478
  function discoverSpecFile(cwd, specFileArg) {
62930
63479
  if (specFileArg) {
62931
- const resolvedPath = path52.resolve(cwd, specFileArg);
62932
- const normalizedCwd = cwd.endsWith(path52.sep) ? cwd : cwd + path52.sep;
63480
+ const resolvedPath = path53.resolve(cwd, specFileArg);
63481
+ const normalizedCwd = cwd.endsWith(path53.sep) ? cwd : cwd + path53.sep;
62933
63482
  if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
62934
63483
  throw new Error("Invalid spec_file: path traversal detected");
62935
63484
  }
62936
- const ext = path52.extname(resolvedPath).toLowerCase();
63485
+ const ext = path53.extname(resolvedPath).toLowerCase();
62937
63486
  if (!ALLOWED_EXTENSIONS.includes(ext)) {
62938
63487
  throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
62939
63488
  }
62940
- const stats = fs40.statSync(resolvedPath);
63489
+ const stats = fs41.statSync(resolvedPath);
62941
63490
  if (stats.size > MAX_SPEC_SIZE) {
62942
63491
  throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
62943
63492
  }
62944
- if (!fs40.existsSync(resolvedPath)) {
63493
+ if (!fs41.existsSync(resolvedPath)) {
62945
63494
  throw new Error(`Spec file not found: ${resolvedPath}`);
62946
63495
  }
62947
63496
  return resolvedPath;
62948
63497
  }
62949
63498
  for (const candidate of SPEC_CANDIDATES) {
62950
- const candidatePath = path52.resolve(cwd, candidate);
62951
- if (fs40.existsSync(candidatePath)) {
62952
- const stats = fs40.statSync(candidatePath);
63499
+ const candidatePath = path53.resolve(cwd, candidate);
63500
+ if (fs41.existsSync(candidatePath)) {
63501
+ const stats = fs41.statSync(candidatePath);
62953
63502
  if (stats.size <= MAX_SPEC_SIZE) {
62954
63503
  return candidatePath;
62955
63504
  }
@@ -62958,8 +63507,8 @@ function discoverSpecFile(cwd, specFileArg) {
62958
63507
  return null;
62959
63508
  }
62960
63509
  function parseSpec(specFile) {
62961
- const content = fs40.readFileSync(specFile, "utf-8");
62962
- const ext = path52.extname(specFile).toLowerCase();
63510
+ const content = fs41.readFileSync(specFile, "utf-8");
63511
+ const ext = path53.extname(specFile).toLowerCase();
62963
63512
  if (ext === ".json") {
62964
63513
  return parseJsonSpec(content);
62965
63514
  }
@@ -63030,12 +63579,12 @@ function extractRoutes(cwd) {
63030
63579
  function walkDir(dir) {
63031
63580
  let entries;
63032
63581
  try {
63033
- entries = fs40.readdirSync(dir, { withFileTypes: true });
63582
+ entries = fs41.readdirSync(dir, { withFileTypes: true });
63034
63583
  } catch {
63035
63584
  return;
63036
63585
  }
63037
63586
  for (const entry of entries) {
63038
- const fullPath = path52.join(dir, entry.name);
63587
+ const fullPath = path53.join(dir, entry.name);
63039
63588
  if (entry.isSymbolicLink()) {
63040
63589
  continue;
63041
63590
  }
@@ -63045,7 +63594,7 @@ function extractRoutes(cwd) {
63045
63594
  }
63046
63595
  walkDir(fullPath);
63047
63596
  } else if (entry.isFile()) {
63048
- const ext = path52.extname(entry.name).toLowerCase();
63597
+ const ext = path53.extname(entry.name).toLowerCase();
63049
63598
  const baseName = entry.name.toLowerCase();
63050
63599
  if (![".ts", ".js", ".mjs"].includes(ext)) {
63051
63600
  continue;
@@ -63063,7 +63612,7 @@ function extractRoutes(cwd) {
63063
63612
  }
63064
63613
  function extractRoutesFromFile(filePath) {
63065
63614
  const routes = [];
63066
- const content = fs40.readFileSync(filePath, "utf-8");
63615
+ const content = fs41.readFileSync(filePath, "utf-8");
63067
63616
  const lines = content.split(/\r?\n/);
63068
63617
  const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
63069
63618
  const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
@@ -63214,8 +63763,8 @@ init_secretscan();
63214
63763
  // src/tools/symbols.ts
63215
63764
  init_tool();
63216
63765
  init_create_tool();
63217
- import * as fs41 from "fs";
63218
- import * as path53 from "path";
63766
+ import * as fs42 from "fs";
63767
+ import * as path54 from "path";
63219
63768
  var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
63220
63769
  var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
63221
63770
  function containsControlCharacters(str) {
@@ -63244,11 +63793,11 @@ function containsWindowsAttacks(str) {
63244
63793
  }
63245
63794
  function isPathInWorkspace(filePath, workspace) {
63246
63795
  try {
63247
- const resolvedPath = path53.resolve(workspace, filePath);
63248
- const realWorkspace = fs41.realpathSync(workspace);
63249
- const realResolvedPath = fs41.realpathSync(resolvedPath);
63250
- const relativePath = path53.relative(realWorkspace, realResolvedPath);
63251
- if (relativePath.startsWith("..") || path53.isAbsolute(relativePath)) {
63796
+ const resolvedPath = path54.resolve(workspace, filePath);
63797
+ const realWorkspace = fs42.realpathSync(workspace);
63798
+ const realResolvedPath = fs42.realpathSync(resolvedPath);
63799
+ const relativePath = path54.relative(realWorkspace, realResolvedPath);
63800
+ if (relativePath.startsWith("..") || path54.isAbsolute(relativePath)) {
63252
63801
  return false;
63253
63802
  }
63254
63803
  return true;
@@ -63260,17 +63809,17 @@ function validatePathForRead(filePath, workspace) {
63260
63809
  return isPathInWorkspace(filePath, workspace);
63261
63810
  }
63262
63811
  function extractTSSymbols(filePath, cwd) {
63263
- const fullPath = path53.join(cwd, filePath);
63812
+ const fullPath = path54.join(cwd, filePath);
63264
63813
  if (!validatePathForRead(fullPath, cwd)) {
63265
63814
  return [];
63266
63815
  }
63267
63816
  let content;
63268
63817
  try {
63269
- const stats = fs41.statSync(fullPath);
63818
+ const stats = fs42.statSync(fullPath);
63270
63819
  if (stats.size > MAX_FILE_SIZE_BYTES7) {
63271
63820
  throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
63272
63821
  }
63273
- content = fs41.readFileSync(fullPath, "utf-8");
63822
+ content = fs42.readFileSync(fullPath, "utf-8");
63274
63823
  } catch {
63275
63824
  return [];
63276
63825
  }
@@ -63412,17 +63961,17 @@ function extractTSSymbols(filePath, cwd) {
63412
63961
  });
63413
63962
  }
63414
63963
  function extractPythonSymbols(filePath, cwd) {
63415
- const fullPath = path53.join(cwd, filePath);
63964
+ const fullPath = path54.join(cwd, filePath);
63416
63965
  if (!validatePathForRead(fullPath, cwd)) {
63417
63966
  return [];
63418
63967
  }
63419
63968
  let content;
63420
63969
  try {
63421
- const stats = fs41.statSync(fullPath);
63970
+ const stats = fs42.statSync(fullPath);
63422
63971
  if (stats.size > MAX_FILE_SIZE_BYTES7) {
63423
63972
  throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
63424
63973
  }
63425
- content = fs41.readFileSync(fullPath, "utf-8");
63974
+ content = fs42.readFileSync(fullPath, "utf-8");
63426
63975
  } catch {
63427
63976
  return [];
63428
63977
  }
@@ -63495,7 +64044,7 @@ var symbols = createSwarmTool({
63495
64044
  }, null, 2);
63496
64045
  }
63497
64046
  const cwd = directory;
63498
- const ext = path53.extname(file3);
64047
+ const ext = path54.extname(file3);
63499
64048
  if (containsControlCharacters(file3)) {
63500
64049
  return JSON.stringify({
63501
64050
  file: file3,
@@ -63566,8 +64115,8 @@ init_test_runner();
63566
64115
  init_dist();
63567
64116
  init_utils();
63568
64117
  init_create_tool();
63569
- import * as fs42 from "fs";
63570
- import * as path54 from "path";
64118
+ import * as fs43 from "fs";
64119
+ import * as path55 from "path";
63571
64120
  var MAX_TEXT_LENGTH = 200;
63572
64121
  var MAX_FILE_SIZE_BYTES8 = 1024 * 1024;
63573
64122
  var SUPPORTED_EXTENSIONS2 = new Set([
@@ -63589,7 +64138,7 @@ var SUPPORTED_EXTENSIONS2 = new Set([
63589
64138
  ".swift",
63590
64139
  ".kt"
63591
64140
  ]);
63592
- var SKIP_DIRECTORIES3 = new Set([
64141
+ var SKIP_DIRECTORIES4 = new Set([
63593
64142
  "node_modules",
63594
64143
  "dist",
63595
64144
  "build",
@@ -63638,9 +64187,9 @@ function validatePathsInput(paths, cwd) {
63638
64187
  return { error: "paths contains path traversal", resolvedPath: null };
63639
64188
  }
63640
64189
  try {
63641
- const resolvedPath = path54.resolve(paths);
63642
- const normalizedCwd = path54.resolve(cwd);
63643
- const normalizedResolved = path54.resolve(resolvedPath);
64190
+ const resolvedPath = path55.resolve(paths);
64191
+ const normalizedCwd = path55.resolve(cwd);
64192
+ const normalizedResolved = path55.resolve(resolvedPath);
63644
64193
  if (!normalizedResolved.startsWith(normalizedCwd)) {
63645
64194
  return {
63646
64195
  error: "paths must be within the current working directory",
@@ -63656,25 +64205,25 @@ function validatePathsInput(paths, cwd) {
63656
64205
  }
63657
64206
  }
63658
64207
  function isSupportedExtension(filePath) {
63659
- const ext = path54.extname(filePath).toLowerCase();
64208
+ const ext = path55.extname(filePath).toLowerCase();
63660
64209
  return SUPPORTED_EXTENSIONS2.has(ext);
63661
64210
  }
63662
64211
  function findSourceFiles2(dir, files = []) {
63663
64212
  let entries;
63664
64213
  try {
63665
- entries = fs42.readdirSync(dir);
64214
+ entries = fs43.readdirSync(dir);
63666
64215
  } catch {
63667
64216
  return files;
63668
64217
  }
63669
64218
  entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
63670
64219
  for (const entry of entries) {
63671
- if (SKIP_DIRECTORIES3.has(entry)) {
64220
+ if (SKIP_DIRECTORIES4.has(entry)) {
63672
64221
  continue;
63673
64222
  }
63674
- const fullPath = path54.join(dir, entry);
64223
+ const fullPath = path55.join(dir, entry);
63675
64224
  let stat2;
63676
64225
  try {
63677
- stat2 = fs42.statSync(fullPath);
64226
+ stat2 = fs43.statSync(fullPath);
63678
64227
  } catch {
63679
64228
  continue;
63680
64229
  }
@@ -63767,7 +64316,7 @@ var todo_extract = createSwarmTool({
63767
64316
  return JSON.stringify(errorResult, null, 2);
63768
64317
  }
63769
64318
  const scanPath = resolvedPath;
63770
- if (!fs42.existsSync(scanPath)) {
64319
+ if (!fs43.existsSync(scanPath)) {
63771
64320
  const errorResult = {
63772
64321
  error: `path not found: ${pathsInput}`,
63773
64322
  total: 0,
@@ -63777,13 +64326,13 @@ var todo_extract = createSwarmTool({
63777
64326
  return JSON.stringify(errorResult, null, 2);
63778
64327
  }
63779
64328
  const filesToScan = [];
63780
- const stat2 = fs42.statSync(scanPath);
64329
+ const stat2 = fs43.statSync(scanPath);
63781
64330
  if (stat2.isFile()) {
63782
64331
  if (isSupportedExtension(scanPath)) {
63783
64332
  filesToScan.push(scanPath);
63784
64333
  } else {
63785
64334
  const errorResult = {
63786
- error: `unsupported file extension: ${path54.extname(scanPath)}`,
64335
+ error: `unsupported file extension: ${path55.extname(scanPath)}`,
63787
64336
  total: 0,
63788
64337
  byPriority: { high: 0, medium: 0, low: 0 },
63789
64338
  entries: []
@@ -63796,11 +64345,11 @@ var todo_extract = createSwarmTool({
63796
64345
  const allEntries = [];
63797
64346
  for (const filePath of filesToScan) {
63798
64347
  try {
63799
- const fileStat = fs42.statSync(filePath);
64348
+ const fileStat = fs43.statSync(filePath);
63800
64349
  if (fileStat.size > MAX_FILE_SIZE_BYTES8) {
63801
64350
  continue;
63802
64351
  }
63803
- const content = fs42.readFileSync(filePath, "utf-8");
64352
+ const content = fs43.readFileSync(filePath, "utf-8");
63804
64353
  const entries = parseTodoComments(content, filePath, tagsSet);
63805
64354
  allEntries.push(...entries);
63806
64355
  } catch {}
@@ -63828,18 +64377,18 @@ var todo_extract = createSwarmTool({
63828
64377
  // src/tools/update-task-status.ts
63829
64378
  init_tool();
63830
64379
  init_schema();
63831
- import * as fs44 from "fs";
63832
- import * as path56 from "path";
64380
+ import * as fs45 from "fs";
64381
+ import * as path57 from "path";
63833
64382
 
63834
64383
  // src/hooks/diff-scope.ts
63835
- import * as fs43 from "fs";
63836
- import * as path55 from "path";
64384
+ import * as fs44 from "fs";
64385
+ import * as path56 from "path";
63837
64386
  function getDeclaredScope(taskId, directory) {
63838
64387
  try {
63839
- const planPath = path55.join(directory, ".swarm", "plan.json");
63840
- if (!fs43.existsSync(planPath))
64388
+ const planPath = path56.join(directory, ".swarm", "plan.json");
64389
+ if (!fs44.existsSync(planPath))
63841
64390
  return null;
63842
- const raw = fs43.readFileSync(planPath, "utf-8");
64391
+ const raw = fs44.readFileSync(planPath, "utf-8");
63843
64392
  const plan = JSON.parse(raw);
63844
64393
  for (const phase of plan.phases ?? []) {
63845
64394
  for (const task of phase.tasks ?? []) {
@@ -63951,7 +64500,7 @@ var TIER_3_PATTERNS = [
63951
64500
  ];
63952
64501
  function matchesTier3Pattern(files) {
63953
64502
  for (const file3 of files) {
63954
- const fileName = path56.basename(file3);
64503
+ const fileName = path57.basename(file3);
63955
64504
  for (const pattern of TIER_3_PATTERNS) {
63956
64505
  if (pattern.test(fileName)) {
63957
64506
  return true;
@@ -63973,8 +64522,8 @@ function checkReviewerGate(taskId, workingDirectory) {
63973
64522
  if (hasActiveTurboMode2()) {
63974
64523
  const resolvedDir2 = workingDirectory;
63975
64524
  try {
63976
- const planPath = path56.join(resolvedDir2, ".swarm", "plan.json");
63977
- const planRaw = fs44.readFileSync(planPath, "utf-8");
64525
+ const planPath = path57.join(resolvedDir2, ".swarm", "plan.json");
64526
+ const planRaw = fs45.readFileSync(planPath, "utf-8");
63978
64527
  const plan = JSON.parse(planRaw);
63979
64528
  for (const planPhase of plan.phases ?? []) {
63980
64529
  for (const task of planPhase.tasks ?? []) {
@@ -63993,8 +64542,8 @@ function checkReviewerGate(taskId, workingDirectory) {
63993
64542
  }
63994
64543
  const resolvedDir = workingDirectory;
63995
64544
  try {
63996
- const evidencePath = path56.join(resolvedDir, ".swarm", "evidence", `${taskId}.json`);
63997
- const raw = fs44.readFileSync(evidencePath, "utf-8");
64545
+ const evidencePath = path57.join(resolvedDir, ".swarm", "evidence", `${taskId}.json`);
64546
+ const raw = fs45.readFileSync(evidencePath, "utf-8");
63998
64547
  const evidence = JSON.parse(raw);
63999
64548
  if (evidence?.required_gates && Array.isArray(evidence.required_gates) && evidence?.gates) {
64000
64549
  const allGatesMet = evidence.required_gates.every((gate) => evidence.gates[gate] != null);
@@ -64034,8 +64583,8 @@ function checkReviewerGate(taskId, workingDirectory) {
64034
64583
  }
64035
64584
  try {
64036
64585
  const resolvedDir2 = workingDirectory;
64037
- const planPath = path56.join(resolvedDir2, ".swarm", "plan.json");
64038
- const planRaw = fs44.readFileSync(planPath, "utf-8");
64586
+ const planPath = path57.join(resolvedDir2, ".swarm", "plan.json");
64587
+ const planRaw = fs45.readFileSync(planPath, "utf-8");
64039
64588
  const plan = JSON.parse(planRaw);
64040
64589
  for (const planPhase of plan.phases ?? []) {
64041
64590
  for (const task of planPhase.tasks ?? []) {
@@ -64216,8 +64765,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
64216
64765
  };
64217
64766
  }
64218
64767
  }
64219
- normalizedDir = path56.normalize(args2.working_directory);
64220
- const pathParts = normalizedDir.split(path56.sep);
64768
+ normalizedDir = path57.normalize(args2.working_directory);
64769
+ const pathParts = normalizedDir.split(path57.sep);
64221
64770
  if (pathParts.includes("..")) {
64222
64771
  return {
64223
64772
  success: false,
@@ -64227,11 +64776,11 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
64227
64776
  ]
64228
64777
  };
64229
64778
  }
64230
- const resolvedDir = path56.resolve(normalizedDir);
64779
+ const resolvedDir = path57.resolve(normalizedDir);
64231
64780
  try {
64232
- const realPath = fs44.realpathSync(resolvedDir);
64233
- const planPath = path56.join(realPath, ".swarm", "plan.json");
64234
- if (!fs44.existsSync(planPath)) {
64781
+ const realPath = fs45.realpathSync(resolvedDir);
64782
+ const planPath = path57.join(realPath, ".swarm", "plan.json");
64783
+ if (!fs45.existsSync(planPath)) {
64235
64784
  return {
64236
64785
  success: false,
64237
64786
  message: `Invalid working_directory: plan not found in "${realPath}"`,
@@ -64453,7 +65002,7 @@ var OpenCodeSwarm = async (ctx) => {
64453
65002
  const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
64454
65003
  preflightTriggerManager = new PTM(automationConfig);
64455
65004
  const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
64456
- const swarmDir = path57.resolve(ctx.directory, ".swarm");
65005
+ const swarmDir = path58.resolve(ctx.directory, ".swarm");
64457
65006
  statusArtifact = new ASA(swarmDir);
64458
65007
  statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
64459
65008
  if (automationConfig.capabilities?.evidence_auto_summaries === true) {
@@ -64745,7 +65294,9 @@ var OpenCodeSwarm = async (ctx) => {
64745
65294
  await safeHook(activityHooks.toolBefore)(input, output);
64746
65295
  },
64747
65296
  "tool.execute.after": async (input, output) => {
64748
- console.debug("[hook-chain] toolAfter start sessionID=%s agent=%s tool=%s", input.sessionID, input.agent, input.tool?.name);
65297
+ if (process.env.DEBUG_SWARM) {
65298
+ console.debug("[hook-chain] toolAfter start sessionID=%s agent=%s tool=%s", input.sessionID, input.agent, input.tool?.name);
65299
+ }
64749
65300
  await activityHooks.toolAfter(input, output);
64750
65301
  await guardrailsHooks.toolAfter(input, output);
64751
65302
  await safeHook(delegationLedgerHook.toolAfter)(input, output);
@@ -64805,7 +65356,9 @@ var OpenCodeSwarm = async (ctx) => {
64805
65356
  deleteStoredInputArgs(input.callID);
64806
65357
  },
64807
65358
  "chat.message": safeHook(async (input, output) => {
64808
- console.debug("[session] chat.message sessionID=%s agent=%s", input.sessionID, input.agent);
65359
+ if (process.env.DEBUG_SWARM) {
65360
+ console.debug("[session] chat.message sessionID=%s agent=%s", input.sessionID, input.agent);
65361
+ }
64809
65362
  await delegationHandler(input, output);
64810
65363
  }),
64811
65364
  automation: automationManager