opencode-swarm 7.12.0 → 7.13.1

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
@@ -33,7 +33,7 @@ var package_default;
33
33
  var init_package = __esm(() => {
34
34
  package_default = {
35
35
  name: "opencode-swarm",
36
- version: "7.12.0",
36
+ version: "7.13.1",
37
37
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
38
38
  main: "dist/index.js",
39
39
  types: "dist/index.d.ts",
@@ -57533,6 +57533,14 @@ var init_write_retro2 = __esm(() => {
57533
57533
  init_write_retro();
57534
57534
  });
57535
57535
 
57536
+ // src/commands/command-names.ts
57537
+ var COMMAND_NAMES, COMMAND_NAME_SET;
57538
+ var init_command_names = __esm(() => {
57539
+ init_registry();
57540
+ COMMAND_NAMES = Object.freeze(Object.keys(COMMAND_REGISTRY));
57541
+ COMMAND_NAME_SET = new Set(COMMAND_NAMES);
57542
+ });
57543
+
57536
57544
  // src/commands/index.ts
57537
57545
  var exports_commands = {};
57538
57546
  __export(exports_commands, {
@@ -57580,7 +57588,9 @@ __export(exports_commands, {
57580
57588
  createSwarmCommandHandler: () => createSwarmCommandHandler,
57581
57589
  buildHelpText: () => buildHelpText,
57582
57590
  VALID_COMMANDS: () => VALID_COMMANDS,
57583
- COMMAND_REGISTRY: () => COMMAND_REGISTRY
57591
+ COMMAND_REGISTRY: () => COMMAND_REGISTRY,
57592
+ COMMAND_NAME_SET: () => COMMAND_NAME_SET,
57593
+ COMMAND_NAMES: () => COMMAND_NAMES
57584
57594
  });
57585
57595
  import fs30 from "node:fs";
57586
57596
  import path46 from "node:path";
@@ -57760,6 +57770,7 @@ var init_commands = __esm(() => {
57760
57770
  init_benchmark();
57761
57771
  init_checkpoint2();
57762
57772
  init_close();
57773
+ init_command_names();
57763
57774
  init_config2();
57764
57775
  init_council();
57765
57776
  init_curate();
@@ -58017,11 +58028,19 @@ var init_registry = __esm(() => {
58017
58028
  category: "core",
58018
58029
  clashesWithNativeCcCommand: "/status"
58019
58030
  },
58031
+ "show-plan": {
58032
+ handler: (ctx) => handlePlanCommand(ctx.directory, ctx.args),
58033
+ description: "Show current plan (optionally filter by phase number)",
58034
+ category: "core",
58035
+ args: "[phase-number]"
58036
+ },
58020
58037
  plan: {
58021
58038
  handler: (ctx) => handlePlanCommand(ctx.directory, ctx.args),
58022
- description: "Show plan (optionally filter by phase number)",
58039
+ description: "Show current plan (deprecated alias for /swarm show-plan)",
58023
58040
  category: "core",
58024
- clashesWithNativeCcCommand: "/plan"
58041
+ clashesWithNativeCcCommand: "/plan",
58042
+ aliasOf: "show-plan",
58043
+ deprecated: true
58025
58044
  },
58026
58045
  agents: {
58027
58046
  handler: (ctx) => Promise.resolve(handleAgentsCommand(ctx.agents, undefined)),
@@ -58191,13 +58210,22 @@ var init_registry = __esm(() => {
58191
58210
  args: "--threshold <number>, --min-commits <number>",
58192
58211
  category: "diagnostics"
58193
58212
  },
58194
- close: {
58213
+ finalize: {
58195
58214
  handler: (ctx) => handleCloseCommand(ctx.directory, ctx.args),
58196
- description: "Use /swarm close to close the swarm project and archive evidence",
58215
+ description: "Use /swarm finalize to finalize the swarm project and archive evidence",
58197
58216
  details: "Idempotent 4-stage terminal finalization: (1) finalize writes retrospectives for in-progress phases, (2) archive creates timestamped bundle of swarm artifacts and evidence, (3) clean removes active-state files for a clean slate, (4) align performs safe git ff-only to main. Resets agent sessions and delegation chains. Reads .swarm/close-lessons.md for explicit lessons and runs curation.",
58198
58217
  args: "--prune-branches",
58199
58218
  category: "core"
58200
58219
  },
58220
+ close: {
58221
+ handler: (ctx) => handleCloseCommand(ctx.directory, ctx.args),
58222
+ description: "Use /swarm close (deprecated alias) to finalize and archive swarm state",
58223
+ details: "Deprecated alias for /swarm finalize. Preserved for backward compatibility.",
58224
+ args: "--prune-branches",
58225
+ category: "core",
58226
+ aliasOf: "finalize",
58227
+ deprecated: true
58228
+ },
58201
58229
  simulate: {
58202
58230
  handler: (ctx) => handleSimulateCommand(ctx.directory, ctx.args),
58203
58231
  description: "Dry-run hidden coupling analysis with configurable thresholds",
@@ -58231,9 +58259,9 @@ var init_registry = __esm(() => {
58231
58259
  },
58232
58260
  council: {
58233
58261
  handler: (ctx) => handleCouncilCommand(ctx.directory, ctx.args),
58234
- description: "Enter architect MODE: COUNCIL — multi-model deliberation [question] [--spec-review]",
58235
- args: "<question> [--spec-review]",
58236
- details: "Triggers the architect to convene a three-agent General Council: Generalist (reviewer model), Skeptic (critic model), and Domain Expert (SME model). " + "The architect first runs 1–3 targeted web searches and passes a compiled RESEARCH CONTEXT " + "to all three agents before dispatching them in parallel. Agents deliberate using the NSED peer-review protocol (Round 1 independent analysis, Round 2 MAINTAIN/CONCEDE/NUANCE for disagreements). The architect synthesizes the final answer directly from convene_general_council output. --spec-review switches to single-pass advisory mode for spec review. Requires council.general.enabled: true and a search API key in opencode-swarm.json.",
58262
+ description: "Enter architect MODE: COUNCIL — multi-model deliberation [question] [--preset <name>] [--spec-review]",
58263
+ args: "<question> [--preset <name>] [--spec-review]",
58264
+ details: "Triggers the architect to convene a three-agent General Council: Generalist (reviewer model), Skeptic (critic model), and Domain Expert (SME model). Use --preset <name> to choose a named member preset from council.general.presets. " + "The architect first runs 1–3 targeted web searches and passes a compiled RESEARCH CONTEXT " + "to all three agents before dispatching them in parallel. Agents deliberate using the NSED peer-review protocol (Round 1 independent analysis, Round 2 MAINTAIN/CONCEDE/NUANCE for disagreements). The architect synthesizes the final answer directly from convene_general_council output. --spec-review switches to single-pass advisory mode for spec review. Requires council.general.enabled: true and a search API key in opencode-swarm.json.",
58237
58265
  category: "agent"
58238
58266
  },
58239
58267
  "pr-review": {
@@ -58553,7 +58581,7 @@ function buildSlashCommandsList() {
58553
58581
  "history",
58554
58582
  "agents",
58555
58583
  "config",
58556
- "plan",
58584
+ "show-plan",
58557
58585
  "benchmark",
58558
58586
  "export",
58559
58587
  "retrieve"
@@ -58569,7 +58597,7 @@ function buildSlashCommandsList() {
58569
58597
  ];
58570
58598
  const COMMANDS_BY_CATEGORY = {
58571
58599
  "Session Lifecycle": [
58572
- "close",
58600
+ "finalize",
58573
58601
  "reset",
58574
58602
  "reset-session",
58575
58603
  "handoff",
@@ -58579,7 +58607,7 @@ function buildSlashCommandsList() {
58579
58607
  "specify",
58580
58608
  "clarify",
58581
58609
  "analyze",
58582
- "plan",
58610
+ "show-plan",
58583
58611
  "sync-plan",
58584
58612
  "acknowledge-spec-drift",
58585
58613
  "council"
@@ -58734,7 +58762,7 @@ All swarm commands are invoked as /swarm <subcommand>.
58734
58762
  NEVER invoke a bare slash command that shares a name with a swarm subcommand.
58735
58763
 
58736
58764
  CRITICAL CONFLICTS — bare CC command = catastrophic:
58737
- /plan (CC) → Blocks all execution. /swarm plan → Reads .swarm/plan.md. USE THIS.
58765
+ /plan (CC) → Blocks all execution. /swarm show-plan → Reads .swarm/plan.md. USE THIS.
58738
58766
  /reset (CC) → WIPES conversation context. /swarm reset → Clears .swarm (--confirm). USE THIS.
58739
58767
  /checkpoint (CC) → Reverts your work. /swarm checkpoint → Project snapshots. USE THIS.
58740
58768
 
@@ -59692,7 +59720,7 @@ GREENFIELD EXEMPTION: If the work is purely greenfield (new project, no existing
59692
59720
 
59693
59721
  ### MODE: COUNCIL
59694
59722
 
59695
- Activates when: user invokes \`/swarm council <question>\` (optionally with \`--spec-review\`).
59723
+ Activates when: user invokes \`/swarm council <question>\` (optionally with \`--preset <name>\` and/or \`--spec-review\`).
59696
59724
 
59697
59725
  Purpose: convene a fixed three-agent multi-model General Council (generalist / skeptic / domain expert) for an advisory deliberation. The architect runs a curated web research pass upfront, dispatches the three agents in parallel with the gathered RESEARCH CONTEXT, routes any disagreements back for one targeted reconciliation round, and synthesizes the final user-facing answer directly.
59698
59726
 
@@ -68701,12 +68729,12 @@ ${content.substring(endIndex + 1)}`;
68701
68729
  // src/commands/conflict-registry.ts
68702
68730
  var CLAUDE_CODE_CONFLICTS = [
68703
68731
  {
68704
- swarmCommand: "plan",
68732
+ swarmCommand: "show-plan",
68705
68733
  ccCommand: "/plan",
68706
68734
  severity: "CRITICAL",
68707
68735
  ccBehavior: "Enters Claude Code plan mode — Claude proposes all actions before executing them",
68708
68736
  swarmBehavior: "Displays the current .swarm/plan.md task list",
68709
- disambiguationNote: "Use /swarm plan to read the swarm task plan. NEVER invoke the bare /plan command — it enters Claude Code plan mode and blocks execution."
68737
+ disambiguationNote: "Use /swarm show-plan to read the swarm task plan. NEVER invoke the bare /plan command — it enters Claude Code plan mode and blocks execution."
68710
68738
  },
68711
68739
  {
68712
68740
  swarmCommand: "reset",
@@ -81869,10 +81897,6 @@ function writeCouncilEvidence(workingDir, synthesis) {
81869
81897
  }
81870
81898
  }
81871
81899
 
81872
- // src/council/council-service.ts
81873
- import fs65 from "node:fs";
81874
- import path87 from "node:path";
81875
-
81876
81900
  // src/council/types.ts
81877
81901
  var COUNCIL_DEFAULTS = {
81878
81902
  enabled: false,
@@ -81997,7 +82021,7 @@ function buildUnifiedFeedback(taskId, verdict, vetoedBy, requiredFixes, advisory
81997
82021
  return lines.join(`
81998
82022
  `);
81999
82023
  }
82000
- function synthesizePhaseCouncilAdvisory(phaseNumber, phaseSummary, verdicts, roundNumber, config3 = {}, workingDir) {
82024
+ function synthesizePhaseCouncilAdvisory(phaseNumber, phaseSummary, verdicts, roundNumber, config3 = {}, _workingDir) {
82001
82025
  const cfg = { ...COUNCIL_DEFAULTS, ...config3 };
82002
82026
  const timestamp = new Date().toISOString();
82003
82027
  const scope = "phase";
@@ -82030,47 +82054,6 @@ function synthesizePhaseCouncilAdvisory(phaseNumber, phaseSummary, verdicts, rou
82030
82054
  const allCriteriaMet = allUnmetIds.size === 0 && verdicts.length > 0;
82031
82055
  const unifiedFeedbackMd = buildPhaseCouncilFeedback(phaseNumber, phaseSummary, overallVerdict, rejectingMembers, requiredFixes, advisoryFindings, unresolvedConflicts, roundNumber, cfg.maxRounds);
82032
82056
  const evidencePath = `.swarm/evidence/${phaseNumber}/phase-council.json`;
82033
- const baseDir = workingDir ?? process.cwd();
82034
- const evidenceDir = path87.join(baseDir, ".swarm", "evidence", String(phaseNumber));
82035
- fs65.mkdirSync(evidenceDir, { recursive: true });
82036
- const evidenceFile = path87.join(evidenceDir, "phase-council.json");
82037
- const evidenceBundle = {
82038
- entries: [
82039
- {
82040
- type: "phase-council",
82041
- phase_number: phaseNumber,
82042
- scope: "phase",
82043
- timestamp,
82044
- verdict: overallVerdict,
82045
- quorumSize,
82046
- phaseSummary,
82047
- requiredFixes: requiredFixes.map((f) => ({
82048
- severity: f.severity,
82049
- category: f.category,
82050
- location: f.location,
82051
- detail: f.detail,
82052
- evidence: f.evidence
82053
- })),
82054
- advisoryNotes,
82055
- advisoryFindings: advisoryFindings.map((f) => ({
82056
- severity: f.severity,
82057
- category: f.category,
82058
- location: f.location,
82059
- detail: f.detail,
82060
- evidence: f.evidence
82061
- })),
82062
- roundNumber,
82063
- allCriteriaMet
82064
- }
82065
- ]
82066
- };
82067
- try {
82068
- const tempFile = `${evidenceFile}.tmp-${Date.now()}`;
82069
- fs65.writeFileSync(tempFile, JSON.stringify(evidenceBundle, null, 2), "utf-8");
82070
- fs65.renameSync(tempFile, evidenceFile);
82071
- } catch (writeErr) {
82072
- console.warn(`[phase-council] Failed to write phase-council evidence to ${evidenceFile}: ${writeErr instanceof Error ? writeErr.message : String(writeErr)}`);
82073
- }
82074
82057
  return {
82075
82058
  phaseNumber,
82076
82059
  scope,
@@ -82302,8 +82285,8 @@ var submit_council_verdicts = createSwarmTool({
82302
82285
  // src/tools/convene-general-council.ts
82303
82286
  init_zod();
82304
82287
  init_loader();
82305
- import * as fs66 from "node:fs";
82306
- import * as path88 from "node:path";
82288
+ import * as fs65 from "node:fs";
82289
+ import * as path87 from "node:path";
82307
82290
 
82308
82291
  // src/council/general-council-advisory.ts
82309
82292
  var ADVISORY_HEADER = "[general_council] (advisory; not blocking)";
@@ -82731,13 +82714,13 @@ var convene_general_council = createSwarmTool({
82731
82714
  const round1 = input.round1Responses;
82732
82715
  const round2 = input.round2Responses ?? [];
82733
82716
  const result = synthesizeGeneralCouncil(input.question, input.mode, round1, round2);
82734
- const evidenceDir = path88.join(workingDir, ".swarm", "council", "general");
82717
+ const evidenceDir = path87.join(workingDir, ".swarm", "council", "general");
82735
82718
  const safeTimestamp = result.timestamp.replace(/[:.]/g, "-");
82736
82719
  const evidenceFile = `${safeTimestamp}-${input.mode}.json`;
82737
- const evidencePath = path88.join(evidenceDir, evidenceFile);
82720
+ const evidencePath = path87.join(evidenceDir, evidenceFile);
82738
82721
  try {
82739
- await fs66.promises.mkdir(evidenceDir, { recursive: true });
82740
- await fs66.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
82722
+ await fs65.promises.mkdir(evidenceDir, { recursive: true });
82723
+ await fs65.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
82741
82724
  } catch (err2) {
82742
82725
  const message = err2 instanceof Error ? err2.message : String(err2);
82743
82726
  console.warn(`[convene_general_council] Failed to write evidence to ${evidencePath}: ${message}`);
@@ -82978,8 +82961,8 @@ init_scope_persistence();
82978
82961
  init_state();
82979
82962
  init_task_id();
82980
82963
  init_create_tool();
82981
- import * as fs67 from "node:fs";
82982
- import * as path89 from "node:path";
82964
+ import * as fs66 from "node:fs";
82965
+ import * as path88 from "node:path";
82983
82966
  function validateTaskIdFormat2(taskId) {
82984
82967
  return validateTaskIdFormat(taskId);
82985
82968
  }
@@ -83053,8 +83036,8 @@ async function executeDeclareScope(args2, fallbackDir) {
83053
83036
  };
83054
83037
  }
83055
83038
  }
83056
- normalizedDir = path89.normalize(args2.working_directory);
83057
- const pathParts = normalizedDir.split(path89.sep);
83039
+ normalizedDir = path88.normalize(args2.working_directory);
83040
+ const pathParts = normalizedDir.split(path88.sep);
83058
83041
  if (pathParts.includes("..")) {
83059
83042
  return {
83060
83043
  success: false,
@@ -83064,11 +83047,11 @@ async function executeDeclareScope(args2, fallbackDir) {
83064
83047
  ]
83065
83048
  };
83066
83049
  }
83067
- const resolvedDir = path89.resolve(normalizedDir);
83050
+ const resolvedDir = path88.resolve(normalizedDir);
83068
83051
  try {
83069
- const realPath = fs67.realpathSync(resolvedDir);
83070
- const planPath2 = path89.join(realPath, ".swarm", "plan.json");
83071
- if (!fs67.existsSync(planPath2)) {
83052
+ const realPath = fs66.realpathSync(resolvedDir);
83053
+ const planPath2 = path88.join(realPath, ".swarm", "plan.json");
83054
+ if (!fs66.existsSync(planPath2)) {
83072
83055
  return {
83073
83056
  success: false,
83074
83057
  message: `Invalid working_directory: plan not found in "${realPath}"`,
@@ -83091,8 +83074,8 @@ async function executeDeclareScope(args2, fallbackDir) {
83091
83074
  console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
83092
83075
  }
83093
83076
  const directory = normalizedDir || fallbackDir;
83094
- const planPath = path89.resolve(directory, ".swarm", "plan.json");
83095
- if (!fs67.existsSync(planPath)) {
83077
+ const planPath = path88.resolve(directory, ".swarm", "plan.json");
83078
+ if (!fs66.existsSync(planPath)) {
83096
83079
  return {
83097
83080
  success: false,
83098
83081
  message: "No plan found",
@@ -83101,7 +83084,7 @@ async function executeDeclareScope(args2, fallbackDir) {
83101
83084
  }
83102
83085
  let planContent;
83103
83086
  try {
83104
- planContent = JSON.parse(fs67.readFileSync(planPath, "utf-8"));
83087
+ planContent = JSON.parse(fs66.readFileSync(planPath, "utf-8"));
83105
83088
  } catch {
83106
83089
  return {
83107
83090
  success: false,
@@ -83131,8 +83114,8 @@ async function executeDeclareScope(args2, fallbackDir) {
83131
83114
  const normalizeErrors = [];
83132
83115
  const dir = normalizedDir || fallbackDir || process.cwd();
83133
83116
  const mergedFiles = rawMergedFiles.map((file3) => {
83134
- if (path89.isAbsolute(file3)) {
83135
- const relativePath = path89.relative(dir, file3).replace(/\\/g, "/");
83117
+ if (path88.isAbsolute(file3)) {
83118
+ const relativePath = path88.relative(dir, file3).replace(/\\/g, "/");
83136
83119
  if (relativePath.startsWith("..")) {
83137
83120
  normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
83138
83121
  return file3;
@@ -83192,8 +83175,8 @@ var declare_scope = createSwarmTool({
83192
83175
  // src/tools/diff.ts
83193
83176
  init_zod();
83194
83177
  import * as child_process7 from "node:child_process";
83195
- import * as fs68 from "node:fs";
83196
- import * as path90 from "node:path";
83178
+ import * as fs67 from "node:fs";
83179
+ import * as path89 from "node:path";
83197
83180
  init_create_tool();
83198
83181
  var MAX_DIFF_LINES = 500;
83199
83182
  var DIFF_TIMEOUT_MS = 30000;
@@ -83222,20 +83205,20 @@ function validateBase(base) {
83222
83205
  function validatePaths(paths) {
83223
83206
  if (!paths)
83224
83207
  return null;
83225
- for (const path91 of paths) {
83226
- if (!path91 || path91.length === 0) {
83208
+ for (const path90 of paths) {
83209
+ if (!path90 || path90.length === 0) {
83227
83210
  return "empty path not allowed";
83228
83211
  }
83229
- if (path91.length > MAX_PATH_LENGTH) {
83212
+ if (path90.length > MAX_PATH_LENGTH) {
83230
83213
  return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
83231
83214
  }
83232
- if (SHELL_METACHARACTERS2.test(path91)) {
83215
+ if (SHELL_METACHARACTERS2.test(path90)) {
83233
83216
  return "path contains shell metacharacters";
83234
83217
  }
83235
- if (path91.startsWith("-")) {
83218
+ if (path90.startsWith("-")) {
83236
83219
  return 'path cannot start with "-" (option-like arguments not allowed)';
83237
83220
  }
83238
- if (CONTROL_CHAR_PATTERN2.test(path91)) {
83221
+ if (CONTROL_CHAR_PATTERN2.test(path90)) {
83239
83222
  return "path contains control characters";
83240
83223
  }
83241
83224
  }
@@ -83343,8 +83326,8 @@ var diff = createSwarmTool({
83343
83326
  if (parts2.length >= 3) {
83344
83327
  const additions = parseInt(parts2[0], 10) || 0;
83345
83328
  const deletions = parseInt(parts2[1], 10) || 0;
83346
- const path91 = parts2[2];
83347
- files.push({ path: path91, additions, deletions });
83329
+ const path90 = parts2[2];
83330
+ files.push({ path: path90, additions, deletions });
83348
83331
  }
83349
83332
  }
83350
83333
  const contractChanges = [];
@@ -83384,7 +83367,7 @@ var diff = createSwarmTool({
83384
83367
  } else if (base === "unstaged") {
83385
83368
  const oldRef = `:${file3.path}`;
83386
83369
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
83387
- newContent = fs68.readFileSync(path90.join(directory, file3.path), "utf-8");
83370
+ newContent = fs67.readFileSync(path89.join(directory, file3.path), "utf-8");
83388
83371
  } else {
83389
83372
  const oldRef = `${base}:${file3.path}`;
83390
83373
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
@@ -83458,8 +83441,8 @@ var diff = createSwarmTool({
83458
83441
  // src/tools/diff-summary.ts
83459
83442
  init_zod();
83460
83443
  import * as child_process8 from "node:child_process";
83461
- import * as fs69 from "node:fs";
83462
- import * as path91 from "node:path";
83444
+ import * as fs68 from "node:fs";
83445
+ import * as path90 from "node:path";
83463
83446
  init_create_tool();
83464
83447
  var diff_summary = createSwarmTool({
83465
83448
  description: "Generate a filtered semantic diff summary from AST analysis. Returns SemanticDiffSummary with optional filtering by classification or riskLevel.",
@@ -83507,7 +83490,7 @@ var diff_summary = createSwarmTool({
83507
83490
  }
83508
83491
  try {
83509
83492
  let oldContent;
83510
- const newContent = fs69.readFileSync(path91.join(workingDir, filePath), "utf-8");
83493
+ const newContent = fs68.readFileSync(path90.join(workingDir, filePath), "utf-8");
83511
83494
  if (fileExistsInHead) {
83512
83495
  oldContent = child_process8.execFileSync("git", ["show", `HEAD:${filePath}`], {
83513
83496
  encoding: "utf-8",
@@ -83735,8 +83718,8 @@ Use these as DOMAIN values when delegating to @sme.`;
83735
83718
  init_zod();
83736
83719
  init_create_tool();
83737
83720
  init_path_security();
83738
- import * as fs70 from "node:fs";
83739
- import * as path92 from "node:path";
83721
+ import * as fs69 from "node:fs";
83722
+ import * as path91 from "node:path";
83740
83723
  var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
83741
83724
  var MAX_EVIDENCE_FILES = 1000;
83742
83725
  var EVIDENCE_DIR3 = ".swarm/evidence";
@@ -83763,9 +83746,9 @@ function validateRequiredTypes(input) {
83763
83746
  return null;
83764
83747
  }
83765
83748
  function isPathWithinSwarm2(filePath, cwd) {
83766
- const normalizedCwd = path92.resolve(cwd);
83767
- const swarmPath = path92.join(normalizedCwd, ".swarm");
83768
- const normalizedPath = path92.resolve(filePath);
83749
+ const normalizedCwd = path91.resolve(cwd);
83750
+ const swarmPath = path91.join(normalizedCwd, ".swarm");
83751
+ const normalizedPath = path91.resolve(filePath);
83769
83752
  return normalizedPath.startsWith(swarmPath);
83770
83753
  }
83771
83754
  function parseCompletedTasks(planContent) {
@@ -83781,12 +83764,12 @@ function parseCompletedTasks(planContent) {
83781
83764
  }
83782
83765
  function readEvidenceFiles(evidenceDir, _cwd) {
83783
83766
  const evidence = [];
83784
- if (!fs70.existsSync(evidenceDir) || !fs70.statSync(evidenceDir).isDirectory()) {
83767
+ if (!fs69.existsSync(evidenceDir) || !fs69.statSync(evidenceDir).isDirectory()) {
83785
83768
  return evidence;
83786
83769
  }
83787
83770
  let files;
83788
83771
  try {
83789
- files = fs70.readdirSync(evidenceDir);
83772
+ files = fs69.readdirSync(evidenceDir);
83790
83773
  } catch {
83791
83774
  return evidence;
83792
83775
  }
@@ -83795,14 +83778,14 @@ function readEvidenceFiles(evidenceDir, _cwd) {
83795
83778
  if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
83796
83779
  continue;
83797
83780
  }
83798
- const filePath = path92.join(evidenceDir, filename);
83781
+ const filePath = path91.join(evidenceDir, filename);
83799
83782
  try {
83800
- const resolvedPath = path92.resolve(filePath);
83801
- const evidenceDirResolved = path92.resolve(evidenceDir);
83783
+ const resolvedPath = path91.resolve(filePath);
83784
+ const evidenceDirResolved = path91.resolve(evidenceDir);
83802
83785
  if (!resolvedPath.startsWith(evidenceDirResolved)) {
83803
83786
  continue;
83804
83787
  }
83805
- const stat7 = fs70.lstatSync(filePath);
83788
+ const stat7 = fs69.lstatSync(filePath);
83806
83789
  if (!stat7.isFile()) {
83807
83790
  continue;
83808
83791
  }
@@ -83811,7 +83794,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
83811
83794
  }
83812
83795
  let fileStat;
83813
83796
  try {
83814
- fileStat = fs70.statSync(filePath);
83797
+ fileStat = fs69.statSync(filePath);
83815
83798
  if (fileStat.size > MAX_FILE_SIZE_BYTES6) {
83816
83799
  continue;
83817
83800
  }
@@ -83820,7 +83803,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
83820
83803
  }
83821
83804
  let content;
83822
83805
  try {
83823
- content = fs70.readFileSync(filePath, "utf-8");
83806
+ content = fs69.readFileSync(filePath, "utf-8");
83824
83807
  } catch {
83825
83808
  continue;
83826
83809
  }
@@ -83916,7 +83899,7 @@ var evidence_check = createSwarmTool({
83916
83899
  return JSON.stringify(errorResult, null, 2);
83917
83900
  }
83918
83901
  const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
83919
- const planPath = path92.join(cwd, PLAN_FILE);
83902
+ const planPath = path91.join(cwd, PLAN_FILE);
83920
83903
  if (!isPathWithinSwarm2(planPath, cwd)) {
83921
83904
  const errorResult = {
83922
83905
  error: "plan file path validation failed",
@@ -83930,7 +83913,7 @@ var evidence_check = createSwarmTool({
83930
83913
  }
83931
83914
  let planContent;
83932
83915
  try {
83933
- planContent = fs70.readFileSync(planPath, "utf-8");
83916
+ planContent = fs69.readFileSync(planPath, "utf-8");
83934
83917
  } catch {
83935
83918
  const result2 = {
83936
83919
  message: "No completed tasks found in plan.",
@@ -83948,7 +83931,7 @@ var evidence_check = createSwarmTool({
83948
83931
  };
83949
83932
  return JSON.stringify(result2, null, 2);
83950
83933
  }
83951
- const evidenceDir = path92.join(cwd, EVIDENCE_DIR3);
83934
+ const evidenceDir = path91.join(cwd, EVIDENCE_DIR3);
83952
83935
  const evidence = readEvidenceFiles(evidenceDir, cwd);
83953
83936
  const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
83954
83937
  const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
@@ -83965,8 +83948,8 @@ var evidence_check = createSwarmTool({
83965
83948
  // src/tools/file-extractor.ts
83966
83949
  init_zod();
83967
83950
  init_create_tool();
83968
- import * as fs71 from "node:fs";
83969
- import * as path93 from "node:path";
83951
+ import * as fs70 from "node:fs";
83952
+ import * as path92 from "node:path";
83970
83953
  var EXT_MAP = {
83971
83954
  python: ".py",
83972
83955
  py: ".py",
@@ -84028,8 +84011,8 @@ var extract_code_blocks = createSwarmTool({
84028
84011
  execute: async (args2, directory) => {
84029
84012
  const { content, output_dir, prefix } = args2;
84030
84013
  const targetDir = output_dir || directory;
84031
- if (!fs71.existsSync(targetDir)) {
84032
- fs71.mkdirSync(targetDir, { recursive: true });
84014
+ if (!fs70.existsSync(targetDir)) {
84015
+ fs70.mkdirSync(targetDir, { recursive: true });
84033
84016
  }
84034
84017
  if (!content) {
84035
84018
  return "Error: content is required";
@@ -84047,16 +84030,16 @@ var extract_code_blocks = createSwarmTool({
84047
84030
  if (prefix) {
84048
84031
  filename = `${prefix}_${filename}`;
84049
84032
  }
84050
- let filepath = path93.join(targetDir, filename);
84051
- const base = path93.basename(filepath, path93.extname(filepath));
84052
- const ext = path93.extname(filepath);
84033
+ let filepath = path92.join(targetDir, filename);
84034
+ const base = path92.basename(filepath, path92.extname(filepath));
84035
+ const ext = path92.extname(filepath);
84053
84036
  let counter = 1;
84054
- while (fs71.existsSync(filepath)) {
84055
- filepath = path93.join(targetDir, `${base}_${counter}${ext}`);
84037
+ while (fs70.existsSync(filepath)) {
84038
+ filepath = path92.join(targetDir, `${base}_${counter}${ext}`);
84056
84039
  counter++;
84057
84040
  }
84058
84041
  try {
84059
- fs71.writeFileSync(filepath, code.trim(), "utf-8");
84042
+ fs70.writeFileSync(filepath, code.trim(), "utf-8");
84060
84043
  savedFiles.push(filepath);
84061
84044
  } catch (error93) {
84062
84045
  errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
@@ -84309,8 +84292,8 @@ var gitingest = createSwarmTool({
84309
84292
  init_zod();
84310
84293
  init_create_tool();
84311
84294
  init_path_security();
84312
- import * as fs72 from "node:fs";
84313
- import * as path94 from "node:path";
84295
+ import * as fs71 from "node:fs";
84296
+ import * as path93 from "node:path";
84314
84297
  var MAX_FILE_PATH_LENGTH2 = 500;
84315
84298
  var MAX_SYMBOL_LENGTH = 256;
84316
84299
  var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
@@ -84358,7 +84341,7 @@ function validateSymbolInput(symbol3) {
84358
84341
  return null;
84359
84342
  }
84360
84343
  function isBinaryFile2(filePath, buffer) {
84361
- const ext = path94.extname(filePath).toLowerCase();
84344
+ const ext = path93.extname(filePath).toLowerCase();
84362
84345
  if (ext === ".json" || ext === ".md" || ext === ".txt") {
84363
84346
  return false;
84364
84347
  }
@@ -84382,15 +84365,15 @@ function parseImports(content, targetFile, targetSymbol) {
84382
84365
  const imports = [];
84383
84366
  let _resolvedTarget;
84384
84367
  try {
84385
- _resolvedTarget = path94.resolve(targetFile);
84368
+ _resolvedTarget = path93.resolve(targetFile);
84386
84369
  } catch {
84387
84370
  _resolvedTarget = targetFile;
84388
84371
  }
84389
- const targetBasename = path94.basename(targetFile, path94.extname(targetFile));
84372
+ const targetBasename = path93.basename(targetFile, path93.extname(targetFile));
84390
84373
  const targetWithExt = targetFile;
84391
84374
  const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
84392
- const normalizedTargetWithExt = path94.normalize(targetWithExt).replace(/\\/g, "/");
84393
- const normalizedTargetWithoutExt = path94.normalize(targetWithoutExt).replace(/\\/g, "/");
84375
+ const normalizedTargetWithExt = path93.normalize(targetWithExt).replace(/\\/g, "/");
84376
+ const normalizedTargetWithoutExt = path93.normalize(targetWithoutExt).replace(/\\/g, "/");
84394
84377
  const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
84395
84378
  for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
84396
84379
  const modulePath = match[1] || match[2] || match[3];
@@ -84413,9 +84396,9 @@ function parseImports(content, targetFile, targetSymbol) {
84413
84396
  }
84414
84397
  const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
84415
84398
  let isMatch = false;
84416
- const _targetDir = path94.dirname(targetFile);
84417
- const targetExt = path94.extname(targetFile);
84418
- const targetBasenameNoExt = path94.basename(targetFile, targetExt);
84399
+ const _targetDir = path93.dirname(targetFile);
84400
+ const targetExt = path93.extname(targetFile);
84401
+ const targetBasenameNoExt = path93.basename(targetFile, targetExt);
84419
84402
  const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
84420
84403
  const moduleName = modulePath.split(/[/\\]/).pop() || "";
84421
84404
  const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
@@ -84472,7 +84455,7 @@ var SKIP_DIRECTORIES4 = new Set([
84472
84455
  function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
84473
84456
  let entries;
84474
84457
  try {
84475
- entries = fs72.readdirSync(dir);
84458
+ entries = fs71.readdirSync(dir);
84476
84459
  } catch (e) {
84477
84460
  stats.fileErrors.push({
84478
84461
  path: dir,
@@ -84483,13 +84466,13 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
84483
84466
  entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
84484
84467
  for (const entry of entries) {
84485
84468
  if (SKIP_DIRECTORIES4.has(entry)) {
84486
- stats.skippedDirs.push(path94.join(dir, entry));
84469
+ stats.skippedDirs.push(path93.join(dir, entry));
84487
84470
  continue;
84488
84471
  }
84489
- const fullPath = path94.join(dir, entry);
84472
+ const fullPath = path93.join(dir, entry);
84490
84473
  let stat7;
84491
84474
  try {
84492
- stat7 = fs72.statSync(fullPath);
84475
+ stat7 = fs71.statSync(fullPath);
84493
84476
  } catch (e) {
84494
84477
  stats.fileErrors.push({
84495
84478
  path: fullPath,
@@ -84500,7 +84483,7 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
84500
84483
  if (stat7.isDirectory()) {
84501
84484
  findSourceFiles2(fullPath, files, stats);
84502
84485
  } else if (stat7.isFile()) {
84503
- const ext = path94.extname(fullPath).toLowerCase();
84486
+ const ext = path93.extname(fullPath).toLowerCase();
84504
84487
  if (SUPPORTED_EXTENSIONS3.includes(ext)) {
84505
84488
  files.push(fullPath);
84506
84489
  }
@@ -84557,8 +84540,8 @@ var imports = createSwarmTool({
84557
84540
  return JSON.stringify(errorResult, null, 2);
84558
84541
  }
84559
84542
  try {
84560
- const targetFile = path94.resolve(file3);
84561
- if (!fs72.existsSync(targetFile)) {
84543
+ const targetFile = path93.resolve(file3);
84544
+ if (!fs71.existsSync(targetFile)) {
84562
84545
  const errorResult = {
84563
84546
  error: `target file not found: ${file3}`,
84564
84547
  target: file3,
@@ -84568,7 +84551,7 @@ var imports = createSwarmTool({
84568
84551
  };
84569
84552
  return JSON.stringify(errorResult, null, 2);
84570
84553
  }
84571
- const targetStat = fs72.statSync(targetFile);
84554
+ const targetStat = fs71.statSync(targetFile);
84572
84555
  if (!targetStat.isFile()) {
84573
84556
  const errorResult = {
84574
84557
  error: "target must be a file, not a directory",
@@ -84579,7 +84562,7 @@ var imports = createSwarmTool({
84579
84562
  };
84580
84563
  return JSON.stringify(errorResult, null, 2);
84581
84564
  }
84582
- const baseDir = path94.dirname(targetFile);
84565
+ const baseDir = path93.dirname(targetFile);
84583
84566
  const scanStats = {
84584
84567
  skippedDirs: [],
84585
84568
  skippedFiles: 0,
@@ -84594,12 +84577,12 @@ var imports = createSwarmTool({
84594
84577
  if (consumers.length >= MAX_CONSUMERS)
84595
84578
  break;
84596
84579
  try {
84597
- const stat7 = fs72.statSync(filePath);
84580
+ const stat7 = fs71.statSync(filePath);
84598
84581
  if (stat7.size > MAX_FILE_SIZE_BYTES7) {
84599
84582
  skippedFileCount++;
84600
84583
  continue;
84601
84584
  }
84602
- const buffer = fs72.readFileSync(filePath);
84585
+ const buffer = fs71.readFileSync(filePath);
84603
84586
  if (isBinaryFile2(filePath, buffer)) {
84604
84587
  skippedFileCount++;
84605
84588
  continue;
@@ -85175,30 +85158,30 @@ init_config();
85175
85158
  init_schema();
85176
85159
  init_qa_gate_profile();
85177
85160
  init_manager2();
85178
- import * as fs75 from "node:fs";
85179
- import * as path97 from "node:path";
85161
+ import * as fs74 from "node:fs";
85162
+ import * as path96 from "node:path";
85180
85163
 
85181
85164
  // src/full-auto/phase-approval.ts
85182
85165
  init_utils2();
85183
85166
  init_logger();
85184
85167
  init_state2();
85185
- import * as fs73 from "node:fs";
85186
- import * as path95 from "node:path";
85168
+ import * as fs72 from "node:fs";
85169
+ import * as path94 from "node:path";
85187
85170
  var APPROVAL_TTL_MS = 24 * 60 * 60 * 1000;
85188
85171
  function readEvidenceDir(directory, phase) {
85189
85172
  try {
85190
- const dirPath = validateSwarmPath(directory, path95.posix.join("evidence", String(phase)));
85191
- if (!fs73.existsSync(dirPath))
85173
+ const dirPath = validateSwarmPath(directory, path94.posix.join("evidence", String(phase)));
85174
+ if (!fs72.existsSync(dirPath))
85192
85175
  return [];
85193
- const entries = fs73.readdirSync(dirPath);
85194
- return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path95.join(dirPath, e));
85176
+ const entries = fs72.readdirSync(dirPath);
85177
+ return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path94.join(dirPath, e));
85195
85178
  } catch {
85196
85179
  return [];
85197
85180
  }
85198
85181
  }
85199
85182
  function parseEvidence(filePath) {
85200
85183
  try {
85201
- const raw = fs73.readFileSync(filePath, "utf-8");
85184
+ const raw = fs72.readFileSync(filePath, "utf-8");
85202
85185
  const parsed = JSON.parse(raw);
85203
85186
  return parsed;
85204
85187
  } catch (error93) {
@@ -85287,9 +85270,9 @@ function verifyFullAutoPhaseApproval(directory, sessionID, phase, config3) {
85287
85270
  function phaseIsExplicitlyNonCode(directory, phase) {
85288
85271
  try {
85289
85272
  const planPath = validateSwarmPath(directory, "plan.json");
85290
- if (!fs73.existsSync(planPath))
85273
+ if (!fs72.existsSync(planPath))
85291
85274
  return false;
85292
- const raw = fs73.readFileSync(planPath, "utf-8");
85275
+ const raw = fs72.readFileSync(planPath, "utf-8");
85293
85276
  const plan = JSON.parse(raw);
85294
85277
  const phases = Array.isArray(plan.phases) ? plan.phases : [];
85295
85278
  const entry = phases.find((p) => p.id === phase || p.phase === phase);
@@ -85329,20 +85312,20 @@ init_file_locks();
85329
85312
  init_plan_schema();
85330
85313
  init_ledger();
85331
85314
  init_manager();
85332
- import * as fs74 from "node:fs";
85333
- import * as path96 from "node:path";
85315
+ import * as fs73 from "node:fs";
85316
+ import * as path95 from "node:path";
85334
85317
  async function writeCheckpoint(directory) {
85335
85318
  try {
85336
85319
  const plan = await loadPlan(directory);
85337
85320
  if (!plan)
85338
85321
  return;
85339
- const swarmDir = path96.join(directory, ".swarm");
85340
- fs74.mkdirSync(swarmDir, { recursive: true });
85341
- const jsonPath = path96.join(swarmDir, "SWARM_PLAN.json");
85342
- const mdPath = path96.join(swarmDir, "SWARM_PLAN.md");
85343
- fs74.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
85322
+ const swarmDir = path95.join(directory, ".swarm");
85323
+ fs73.mkdirSync(swarmDir, { recursive: true });
85324
+ const jsonPath = path95.join(swarmDir, "SWARM_PLAN.json");
85325
+ const mdPath = path95.join(swarmDir, "SWARM_PLAN.md");
85326
+ fs73.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
85344
85327
  const md = derivePlanMarkdown(plan);
85345
- fs74.writeFileSync(mdPath, md, "utf8");
85328
+ fs73.writeFileSync(mdPath, md, "utf8");
85346
85329
  } catch (error93) {
85347
85330
  console.warn(`[checkpoint] Failed to write SWARM_PLAN checkpoint: ${error93 instanceof Error ? error93.message : String(error93)}`);
85348
85331
  }
@@ -85574,8 +85557,8 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
85574
85557
  let driftCheckEnabled = true;
85575
85558
  let driftHasSpecMd = false;
85576
85559
  try {
85577
- const specMdPath = path97.join(dir, ".swarm", "spec.md");
85578
- driftHasSpecMd = fs75.existsSync(specMdPath);
85560
+ const specMdPath = path96.join(dir, ".swarm", "spec.md");
85561
+ driftHasSpecMd = fs74.existsSync(specMdPath);
85579
85562
  const gatePlan = await loadPlan(dir);
85580
85563
  if (gatePlan) {
85581
85564
  const gatePlanId = derivePlanId(gatePlan);
@@ -85596,9 +85579,9 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
85596
85579
  } else {
85597
85580
  let phaseType;
85598
85581
  try {
85599
- const planPath = path97.join(dir, ".swarm", "plan.json");
85600
- if (fs75.existsSync(planPath)) {
85601
- const planRaw = fs75.readFileSync(planPath, "utf-8");
85582
+ const planPath = path96.join(dir, ".swarm", "plan.json");
85583
+ if (fs74.existsSync(planPath)) {
85584
+ const planRaw = fs74.readFileSync(planPath, "utf-8");
85602
85585
  const plan = JSON.parse(planRaw);
85603
85586
  const targetPhase = plan.phases?.find((p) => p.id === phase);
85604
85587
  phaseType = targetPhase?.type;
@@ -85609,11 +85592,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
85609
85592
  warnings.push(`Phase ${phase} is annotated as 'non-code'. Drift verification was skipped per phase type annotation.`);
85610
85593
  } else {
85611
85594
  try {
85612
- const driftEvidencePath = path97.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
85595
+ const driftEvidencePath = path96.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
85613
85596
  let driftVerdictFound = false;
85614
85597
  let driftVerdictApproved = false;
85615
85598
  try {
85616
- const driftEvidenceContent = fs75.readFileSync(driftEvidencePath, "utf-8");
85599
+ const driftEvidenceContent = fs74.readFileSync(driftEvidencePath, "utf-8");
85617
85600
  const driftEvidence = JSON.parse(driftEvidenceContent);
85618
85601
  const entries = driftEvidence.entries ?? [];
85619
85602
  for (const entry of entries) {
@@ -85647,9 +85630,9 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
85647
85630
  let incompleteTaskCount = 0;
85648
85631
  let planParseable = false;
85649
85632
  try {
85650
- const planPath = path97.join(dir, ".swarm", "plan.json");
85651
- if (fs75.existsSync(planPath)) {
85652
- const planRaw = fs75.readFileSync(planPath, "utf-8");
85633
+ const planPath = path96.join(dir, ".swarm", "plan.json");
85634
+ if (fs74.existsSync(planPath)) {
85635
+ const planRaw = fs74.readFileSync(planPath, "utf-8");
85653
85636
  const plan = JSON.parse(planRaw);
85654
85637
  planParseable = true;
85655
85638
  const planPhase = plan.phases?.find((p) => p.id === phase);
@@ -85714,11 +85697,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
85714
85697
  const overrides = session2?.qaGateSessionOverrides ?? {};
85715
85698
  const effective = getEffectiveGates(profile, overrides);
85716
85699
  if (effective.hallucination_guard === true) {
85717
- const hgPath = path97.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
85700
+ const hgPath = path96.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
85718
85701
  let hgVerdictFound = false;
85719
85702
  let hgVerdictApproved = false;
85720
85703
  try {
85721
- const hgContent = fs75.readFileSync(hgPath, "utf-8");
85704
+ const hgContent = fs74.readFileSync(hgPath, "utf-8");
85722
85705
  const hgBundle = JSON.parse(hgContent);
85723
85706
  for (const entry of hgBundle.entries ?? []) {
85724
85707
  if (typeof entry.type === "string" && entry.type.includes("hallucination") && typeof entry.verdict === "string") {
@@ -85786,11 +85769,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
85786
85769
  const overrides = session2?.qaGateSessionOverrides ?? {};
85787
85770
  const effective = getEffectiveGates(profile, overrides);
85788
85771
  if (effective.mutation_test === true) {
85789
- const mgPath = path97.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
85772
+ const mgPath = path96.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
85790
85773
  let mgVerdictFound = false;
85791
85774
  let mgVerdict;
85792
85775
  try {
85793
- const mgContent = fs75.readFileSync(mgPath, "utf-8");
85776
+ const mgContent = fs74.readFileSync(mgPath, "utf-8");
85794
85777
  const mgBundle = JSON.parse(mgContent);
85795
85778
  for (const entry of mgBundle.entries ?? []) {
85796
85779
  if (typeof entry.type === "string" && entry.type === "mutation-gate" && typeof entry.verdict === "string") {
@@ -85860,14 +85843,14 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
85860
85843
  const effective = getEffectiveGates(profile, overrides);
85861
85844
  if (effective.council_mode === true) {
85862
85845
  councilModeEnabled = true;
85863
- const pcPath = path97.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
85846
+ const pcPath = path96.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
85864
85847
  let pcVerdictFound = false;
85865
85848
  let _pcVerdict;
85866
85849
  let pcQuorumSize;
85867
85850
  let pcTimestamp;
85868
85851
  let pcPhaseNumber;
85869
85852
  try {
85870
- const pcContent = fs75.readFileSync(pcPath, "utf-8");
85853
+ const pcContent = fs74.readFileSync(pcPath, "utf-8");
85871
85854
  const pcBundle = JSON.parse(pcContent);
85872
85855
  for (const entry of pcBundle.entries ?? []) {
85873
85856
  if (typeof entry.type === "string" && entry.type === "phase-council" && typeof entry.verdict === "string") {
@@ -86068,11 +86051,11 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
86068
86051
  const effective = getEffectiveGates(profile, overrides);
86069
86052
  if (effective.final_council === true) {
86070
86053
  finalCouncilEnabled = true;
86071
- const fcPath = path97.join(dir, ".swarm", "evidence", "final-council.json");
86054
+ const fcPath = path96.join(dir, ".swarm", "evidence", "final-council.json");
86072
86055
  let fcVerdictFound = false;
86073
86056
  let _fcVerdict;
86074
86057
  try {
86075
- const fcContent = fs75.readFileSync(fcPath, "utf-8");
86058
+ const fcContent = fs74.readFileSync(fcPath, "utf-8");
86076
86059
  const fcBundle = JSON.parse(fcContent);
86077
86060
  for (const entry of fcBundle.entries ?? []) {
86078
86061
  if (typeof entry.type === "string" && entry.type === "final-council" && typeof entry.verdict === "string") {
@@ -86200,7 +86183,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
86200
86183
  }
86201
86184
  if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
86202
86185
  try {
86203
- const projectName = path97.basename(dir);
86186
+ const projectName = path96.basename(dir);
86204
86187
  const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
86205
86188
  if (curationResult) {
86206
86189
  const sessionState = swarmState.agentSessions.get(sessionID);
@@ -86280,7 +86263,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
86280
86263
  let phaseRequiredAgents;
86281
86264
  try {
86282
86265
  const planPath = validateSwarmPath(dir, "plan.json");
86283
- const planRaw = fs75.readFileSync(planPath, "utf-8");
86266
+ const planRaw = fs74.readFileSync(planPath, "utf-8");
86284
86267
  const plan = JSON.parse(planRaw);
86285
86268
  const phaseObj = plan.phases.find((p) => p.id === phase);
86286
86269
  phaseRequiredAgents = phaseObj?.required_agents;
@@ -86295,7 +86278,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
86295
86278
  if (agentsMissing.length > 0) {
86296
86279
  try {
86297
86280
  const planPath = validateSwarmPath(dir, "plan.json");
86298
- const planRaw = fs75.readFileSync(planPath, "utf-8");
86281
+ const planRaw = fs74.readFileSync(planPath, "utf-8");
86299
86282
  const plan = JSON.parse(planRaw);
86300
86283
  const targetPhase = plan.phases.find((p) => p.id === phase);
86301
86284
  if (targetPhase && targetPhase.tasks.length > 0 && targetPhase.tasks.every((t) => t.status === "completed")) {
@@ -86335,7 +86318,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
86335
86318
  if (phaseCompleteConfig.regression_sweep?.enforce) {
86336
86319
  try {
86337
86320
  const planPath = validateSwarmPath(dir, "plan.json");
86338
- const planRaw = fs75.readFileSync(planPath, "utf-8");
86321
+ const planRaw = fs74.readFileSync(planPath, "utf-8");
86339
86322
  const plan = JSON.parse(planRaw);
86340
86323
  const targetPhase = plan.phases.find((p) => p.id === phase);
86341
86324
  if (targetPhase) {
@@ -86389,7 +86372,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
86389
86372
  }
86390
86373
  try {
86391
86374
  const eventsPath = validateSwarmPath(dir, "events.jsonl");
86392
- fs75.appendFileSync(eventsPath, `${JSON.stringify(event)}
86375
+ fs74.appendFileSync(eventsPath, `${JSON.stringify(event)}
86393
86376
  `, "utf-8");
86394
86377
  } catch (writeError) {
86395
86378
  warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
@@ -86464,12 +86447,12 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
86464
86447
  warnings.push(`Warning: failed to update plan.json phase status`);
86465
86448
  try {
86466
86449
  const planPath = validateSwarmPath(dir, "plan.json");
86467
- const planRaw = fs75.readFileSync(planPath, "utf-8");
86450
+ const planRaw = fs74.readFileSync(planPath, "utf-8");
86468
86451
  const plan2 = JSON.parse(planRaw);
86469
86452
  const phaseObj = plan2.phases.find((p) => p.id === phase);
86470
86453
  if (phaseObj) {
86471
86454
  phaseObj.status = "complete";
86472
- fs75.writeFileSync(planPath, JSON.stringify(plan2, null, 2), "utf-8");
86455
+ fs74.writeFileSync(planPath, JSON.stringify(plan2, null, 2), "utf-8");
86473
86456
  }
86474
86457
  } catch {}
86475
86458
  } else if (plan) {
@@ -86506,12 +86489,12 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
86506
86489
  warnings.push(`Warning: failed to update plan.json phase status`);
86507
86490
  try {
86508
86491
  const planPath = validateSwarmPath(dir, "plan.json");
86509
- const planRaw = fs75.readFileSync(planPath, "utf-8");
86492
+ const planRaw = fs74.readFileSync(planPath, "utf-8");
86510
86493
  const plan = JSON.parse(planRaw);
86511
86494
  const phaseObj = plan.phases.find((p) => p.id === phase);
86512
86495
  if (phaseObj) {
86513
86496
  phaseObj.status = "complete";
86514
- fs75.writeFileSync(planPath, JSON.stringify(plan, null, 2), "utf-8");
86497
+ fs74.writeFileSync(planPath, JSON.stringify(plan, null, 2), "utf-8");
86515
86498
  }
86516
86499
  } catch {}
86517
86500
  }
@@ -86569,8 +86552,8 @@ init_discovery();
86569
86552
  init_utils();
86570
86553
  init_bun_compat();
86571
86554
  init_create_tool();
86572
- import * as fs76 from "node:fs";
86573
- import * as path98 from "node:path";
86555
+ import * as fs75 from "node:fs";
86556
+ import * as path97 from "node:path";
86574
86557
  var MAX_OUTPUT_BYTES5 = 52428800;
86575
86558
  var AUDIT_TIMEOUT_MS = 120000;
86576
86559
  function isValidEcosystem(value) {
@@ -86598,31 +86581,31 @@ function validateArgs3(args2) {
86598
86581
  function detectEcosystems(directory) {
86599
86582
  const ecosystems = [];
86600
86583
  const cwd = directory;
86601
- if (fs76.existsSync(path98.join(cwd, "package.json"))) {
86584
+ if (fs75.existsSync(path97.join(cwd, "package.json"))) {
86602
86585
  ecosystems.push("npm");
86603
86586
  }
86604
- if (fs76.existsSync(path98.join(cwd, "pyproject.toml")) || fs76.existsSync(path98.join(cwd, "requirements.txt"))) {
86587
+ if (fs75.existsSync(path97.join(cwd, "pyproject.toml")) || fs75.existsSync(path97.join(cwd, "requirements.txt"))) {
86605
86588
  ecosystems.push("pip");
86606
86589
  }
86607
- if (fs76.existsSync(path98.join(cwd, "Cargo.toml"))) {
86590
+ if (fs75.existsSync(path97.join(cwd, "Cargo.toml"))) {
86608
86591
  ecosystems.push("cargo");
86609
86592
  }
86610
- if (fs76.existsSync(path98.join(cwd, "go.mod"))) {
86593
+ if (fs75.existsSync(path97.join(cwd, "go.mod"))) {
86611
86594
  ecosystems.push("go");
86612
86595
  }
86613
86596
  try {
86614
- const files = fs76.readdirSync(cwd);
86597
+ const files = fs75.readdirSync(cwd);
86615
86598
  if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
86616
86599
  ecosystems.push("dotnet");
86617
86600
  }
86618
86601
  } catch {}
86619
- if (fs76.existsSync(path98.join(cwd, "Gemfile")) || fs76.existsSync(path98.join(cwd, "Gemfile.lock"))) {
86602
+ if (fs75.existsSync(path97.join(cwd, "Gemfile")) || fs75.existsSync(path97.join(cwd, "Gemfile.lock"))) {
86620
86603
  ecosystems.push("ruby");
86621
86604
  }
86622
- if (fs76.existsSync(path98.join(cwd, "pubspec.yaml"))) {
86605
+ if (fs75.existsSync(path97.join(cwd, "pubspec.yaml"))) {
86623
86606
  ecosystems.push("dart");
86624
86607
  }
86625
- if (fs76.existsSync(path98.join(cwd, "composer.lock"))) {
86608
+ if (fs75.existsSync(path97.join(cwd, "composer.lock"))) {
86626
86609
  ecosystems.push("composer");
86627
86610
  }
86628
86611
  return ecosystems;
@@ -87757,8 +87740,8 @@ var pkg_audit = createSwarmTool({
87757
87740
  // src/tools/placeholder-scan.ts
87758
87741
  init_zod();
87759
87742
  init_manager2();
87760
- import * as fs77 from "node:fs";
87761
- import * as path99 from "node:path";
87743
+ import * as fs76 from "node:fs";
87744
+ import * as path98 from "node:path";
87762
87745
  init_utils();
87763
87746
  init_create_tool();
87764
87747
  var MAX_FILE_SIZE = 1024 * 1024;
@@ -87881,7 +87864,7 @@ function isScaffoldFile(filePath) {
87881
87864
  if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
87882
87865
  return true;
87883
87866
  }
87884
- const filename = path99.basename(filePath);
87867
+ const filename = path98.basename(filePath);
87885
87868
  if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
87886
87869
  return true;
87887
87870
  }
@@ -87898,7 +87881,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
87898
87881
  if (regex.test(normalizedPath)) {
87899
87882
  return true;
87900
87883
  }
87901
- const filename = path99.basename(filePath);
87884
+ const filename = path98.basename(filePath);
87902
87885
  const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
87903
87886
  if (filenameRegex.test(filename)) {
87904
87887
  return true;
@@ -87907,7 +87890,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
87907
87890
  return false;
87908
87891
  }
87909
87892
  function isParserSupported(filePath) {
87910
- const ext = path99.extname(filePath).toLowerCase();
87893
+ const ext = path98.extname(filePath).toLowerCase();
87911
87894
  return SUPPORTED_PARSER_EXTENSIONS.has(ext);
87912
87895
  }
87913
87896
  function isPlanFile(filePath) {
@@ -88154,28 +88137,28 @@ async function placeholderScan(input, directory) {
88154
88137
  let filesScanned = 0;
88155
88138
  const filesWithFindings = new Set;
88156
88139
  for (const filePath of changed_files) {
88157
- const fullPath = path99.isAbsolute(filePath) ? filePath : path99.resolve(directory, filePath);
88158
- const resolvedDirectory = path99.resolve(directory);
88159
- if (!fullPath.startsWith(resolvedDirectory + path99.sep) && fullPath !== resolvedDirectory) {
88140
+ const fullPath = path98.isAbsolute(filePath) ? filePath : path98.resolve(directory, filePath);
88141
+ const resolvedDirectory = path98.resolve(directory);
88142
+ if (!fullPath.startsWith(resolvedDirectory + path98.sep) && fullPath !== resolvedDirectory) {
88160
88143
  continue;
88161
88144
  }
88162
- if (!fs77.existsSync(fullPath)) {
88145
+ if (!fs76.existsSync(fullPath)) {
88163
88146
  continue;
88164
88147
  }
88165
88148
  if (isAllowedByGlobs(filePath, allow_globs)) {
88166
88149
  continue;
88167
88150
  }
88168
- const relativeFilePath = path99.relative(directory, fullPath).replace(/\\/g, "/");
88151
+ const relativeFilePath = path98.relative(directory, fullPath).replace(/\\/g, "/");
88169
88152
  if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
88170
88153
  continue;
88171
88154
  }
88172
88155
  let content;
88173
88156
  try {
88174
- const stat7 = fs77.statSync(fullPath);
88157
+ const stat7 = fs76.statSync(fullPath);
88175
88158
  if (stat7.size > MAX_FILE_SIZE) {
88176
88159
  continue;
88177
88160
  }
88178
- content = fs77.readFileSync(fullPath, "utf-8");
88161
+ content = fs76.readFileSync(fullPath, "utf-8");
88179
88162
  } catch {
88180
88163
  continue;
88181
88164
  }
@@ -88236,8 +88219,8 @@ var placeholder_scan = createSwarmTool({
88236
88219
  }
88237
88220
  });
88238
88221
  // src/tools/pre-check-batch.ts
88239
- import * as fs81 from "node:fs";
88240
- import * as path103 from "node:path";
88222
+ import * as fs80 from "node:fs";
88223
+ import * as path102 from "node:path";
88241
88224
  init_zod();
88242
88225
  init_manager2();
88243
88226
  init_utils();
@@ -88377,8 +88360,8 @@ var _internals30 = {
88377
88360
  init_zod();
88378
88361
  init_manager2();
88379
88362
  init_detector();
88380
- import * as fs80 from "node:fs";
88381
- import * as path102 from "node:path";
88363
+ import * as fs79 from "node:fs";
88364
+ import * as path101 from "node:path";
88382
88365
  import { extname as extname18 } from "node:path";
88383
88366
 
88384
88367
  // src/sast/rules/c.ts
@@ -89093,8 +89076,8 @@ function executeRulesSync(filePath, content, language) {
89093
89076
 
89094
89077
  // src/sast/semgrep.ts
89095
89078
  import * as child_process9 from "node:child_process";
89096
- import * as fs78 from "node:fs";
89097
- import * as path100 from "node:path";
89079
+ import * as fs77 from "node:fs";
89080
+ import * as path99 from "node:path";
89098
89081
  var semgrepAvailableCache = null;
89099
89082
  var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
89100
89083
  var DEFAULT_TIMEOUT_MS3 = 30000;
@@ -89281,14 +89264,14 @@ async function runSemgrep(options) {
89281
89264
  }
89282
89265
  function getRulesDirectory(projectRoot) {
89283
89266
  if (projectRoot) {
89284
- return path100.resolve(projectRoot, DEFAULT_RULES_DIR);
89267
+ return path99.resolve(projectRoot, DEFAULT_RULES_DIR);
89285
89268
  }
89286
89269
  return DEFAULT_RULES_DIR;
89287
89270
  }
89288
89271
  function hasBundledRules(projectRoot) {
89289
89272
  const rulesDir = getRulesDirectory(projectRoot);
89290
89273
  try {
89291
- return fs78.existsSync(rulesDir);
89274
+ return fs77.existsSync(rulesDir);
89292
89275
  } catch {
89293
89276
  return false;
89294
89277
  }
@@ -89301,25 +89284,25 @@ init_create_tool();
89301
89284
  // src/tools/sast-baseline.ts
89302
89285
  init_utils2();
89303
89286
  import * as crypto9 from "node:crypto";
89304
- import * as fs79 from "node:fs";
89305
- import * as path101 from "node:path";
89287
+ import * as fs78 from "node:fs";
89288
+ import * as path100 from "node:path";
89306
89289
  var BASELINE_SCHEMA_VERSION = "1.0.0";
89307
89290
  var MAX_BASELINE_FINDINGS = 2000;
89308
89291
  var MAX_BASELINE_BYTES = 2 * 1048576;
89309
89292
  var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
89310
89293
  function normalizeFindingPath(directory, file3) {
89311
- const resolved = path101.isAbsolute(file3) ? file3 : path101.resolve(directory, file3);
89312
- const rel = path101.relative(path101.resolve(directory), resolved);
89294
+ const resolved = path100.isAbsolute(file3) ? file3 : path100.resolve(directory, file3);
89295
+ const rel = path100.relative(path100.resolve(directory), resolved);
89313
89296
  return rel.replace(/\\/g, "/");
89314
89297
  }
89315
89298
  function baselineRelPath(phase) {
89316
- return path101.join("evidence", String(phase), "sast-baseline.json");
89299
+ return path100.join("evidence", String(phase), "sast-baseline.json");
89317
89300
  }
89318
89301
  function tempRelPath(phase) {
89319
- return path101.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
89302
+ return path100.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
89320
89303
  }
89321
89304
  function lockRelPath(phase) {
89322
- return path101.join("evidence", String(phase), "sast-baseline.json.lock");
89305
+ return path100.join("evidence", String(phase), "sast-baseline.json.lock");
89323
89306
  }
89324
89307
  function getLine(lines, idx) {
89325
89308
  if (idx < 0 || idx >= lines.length)
@@ -89336,7 +89319,7 @@ function fingerprintFinding(finding, directory, occurrenceIndex) {
89336
89319
  }
89337
89320
  const lineNum = finding.location.line;
89338
89321
  try {
89339
- const content = fs79.readFileSync(finding.location.file, "utf-8");
89322
+ const content = fs78.readFileSync(finding.location.file, "utf-8");
89340
89323
  const lines = content.split(`
89341
89324
  `);
89342
89325
  const idx = lineNum - 1;
@@ -89367,7 +89350,7 @@ function assignOccurrenceIndices(findings, directory) {
89367
89350
  try {
89368
89351
  if (relFile.startsWith(".."))
89369
89352
  throw new Error("escapes workspace");
89370
- const content = fs79.readFileSync(finding.location.file, "utf-8");
89353
+ const content = fs78.readFileSync(finding.location.file, "utf-8");
89371
89354
  const lines = content.split(`
89372
89355
  `);
89373
89356
  const idx = lineNum - 1;
@@ -89396,11 +89379,11 @@ function assignOccurrenceIndices(findings, directory) {
89396
89379
  async function acquireLock(lockPath) {
89397
89380
  for (let attempt = 0;attempt <= LOCK_RETRY_DELAYS_MS.length; attempt++) {
89398
89381
  try {
89399
- const fd = fs79.openSync(lockPath, "wx");
89400
- fs79.closeSync(fd);
89382
+ const fd = fs78.openSync(lockPath, "wx");
89383
+ fs78.closeSync(fd);
89401
89384
  return () => {
89402
89385
  try {
89403
- fs79.unlinkSync(lockPath);
89386
+ fs78.unlinkSync(lockPath);
89404
89387
  } catch {}
89405
89388
  };
89406
89389
  } catch {
@@ -89440,13 +89423,13 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
89440
89423
  message: e instanceof Error ? e.message : "Path validation failed"
89441
89424
  };
89442
89425
  }
89443
- fs79.mkdirSync(path101.dirname(baselinePath), { recursive: true });
89444
- fs79.mkdirSync(path101.dirname(tempPath), { recursive: true });
89426
+ fs78.mkdirSync(path100.dirname(baselinePath), { recursive: true });
89427
+ fs78.mkdirSync(path100.dirname(tempPath), { recursive: true });
89445
89428
  const releaseLock = await acquireLock(lockPath);
89446
89429
  try {
89447
89430
  let existing = null;
89448
89431
  try {
89449
- const raw = fs79.readFileSync(baselinePath, "utf-8");
89432
+ const raw = fs78.readFileSync(baselinePath, "utf-8");
89450
89433
  const parsed = JSON.parse(raw);
89451
89434
  if (parsed.schema_version === BASELINE_SCHEMA_VERSION) {
89452
89435
  existing = parsed;
@@ -89506,8 +89489,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
89506
89489
  message: `Baseline would exceed size cap (${json4.length} bytes > ${MAX_BASELINE_BYTES})`
89507
89490
  };
89508
89491
  }
89509
- fs79.writeFileSync(tempPath, json4, "utf-8");
89510
- fs79.renameSync(tempPath, baselinePath);
89492
+ fs78.writeFileSync(tempPath, json4, "utf-8");
89493
+ fs78.renameSync(tempPath, baselinePath);
89511
89494
  return {
89512
89495
  status: "merged",
89513
89496
  path: baselinePath,
@@ -89538,8 +89521,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
89538
89521
  message: `Baseline would exceed size cap (${json3.length} bytes > ${MAX_BASELINE_BYTES})`
89539
89522
  };
89540
89523
  }
89541
- fs79.writeFileSync(tempPath, json3, "utf-8");
89542
- fs79.renameSync(tempPath, baselinePath);
89524
+ fs78.writeFileSync(tempPath, json3, "utf-8");
89525
+ fs78.renameSync(tempPath, baselinePath);
89543
89526
  return {
89544
89527
  status: "written",
89545
89528
  path: baselinePath,
@@ -89564,7 +89547,7 @@ function loadBaseline(directory, phase) {
89564
89547
  };
89565
89548
  }
89566
89549
  try {
89567
- const raw = fs79.readFileSync(baselinePath, "utf-8");
89550
+ const raw = fs78.readFileSync(baselinePath, "utf-8");
89568
89551
  const parsed = JSON.parse(raw);
89569
89552
  if (parsed.schema_version !== BASELINE_SCHEMA_VERSION) {
89570
89553
  return {
@@ -89612,17 +89595,17 @@ var SEVERITY_ORDER = {
89612
89595
  };
89613
89596
  function shouldSkipFile(filePath) {
89614
89597
  try {
89615
- const stats = fs80.statSync(filePath);
89598
+ const stats = fs79.statSync(filePath);
89616
89599
  if (stats.size > MAX_FILE_SIZE_BYTES8) {
89617
89600
  return { skip: true, reason: "file too large" };
89618
89601
  }
89619
89602
  if (stats.size === 0) {
89620
89603
  return { skip: true, reason: "empty file" };
89621
89604
  }
89622
- const fd = fs80.openSync(filePath, "r");
89605
+ const fd = fs79.openSync(filePath, "r");
89623
89606
  const buffer = Buffer.alloc(8192);
89624
- const bytesRead = fs80.readSync(fd, buffer, 0, 8192, 0);
89625
- fs80.closeSync(fd);
89607
+ const bytesRead = fs79.readSync(fd, buffer, 0, 8192, 0);
89608
+ fs79.closeSync(fd);
89626
89609
  if (bytesRead > 0) {
89627
89610
  let nullCount = 0;
89628
89611
  for (let i2 = 0;i2 < bytesRead; i2++) {
@@ -89661,7 +89644,7 @@ function countBySeverity(findings) {
89661
89644
  }
89662
89645
  function scanFileWithTierA(filePath, language) {
89663
89646
  try {
89664
- const content = fs80.readFileSync(filePath, "utf-8");
89647
+ const content = fs79.readFileSync(filePath, "utf-8");
89665
89648
  const findings = executeRulesSync(filePath, content, language);
89666
89649
  return findings.map((f) => ({
89667
89650
  rule_id: f.rule_id,
@@ -89714,13 +89697,13 @@ async function sastScan(input, directory, config3) {
89714
89697
  _filesSkipped++;
89715
89698
  continue;
89716
89699
  }
89717
- const resolvedPath = path102.isAbsolute(filePath) ? filePath : path102.resolve(directory, filePath);
89718
- const resolvedDirectory = path102.resolve(directory);
89719
- if (!resolvedPath.startsWith(resolvedDirectory + path102.sep) && resolvedPath !== resolvedDirectory) {
89700
+ const resolvedPath = path101.isAbsolute(filePath) ? filePath : path101.resolve(directory, filePath);
89701
+ const resolvedDirectory = path101.resolve(directory);
89702
+ if (!resolvedPath.startsWith(resolvedDirectory + path101.sep) && resolvedPath !== resolvedDirectory) {
89720
89703
  _filesSkipped++;
89721
89704
  continue;
89722
89705
  }
89723
- if (!fs80.existsSync(resolvedPath)) {
89706
+ if (!fs79.existsSync(resolvedPath)) {
89724
89707
  _filesSkipped++;
89725
89708
  continue;
89726
89709
  }
@@ -90031,18 +90014,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
90031
90014
  let resolved;
90032
90015
  const isWinAbs = isWindowsAbsolutePath(inputPath);
90033
90016
  if (isWinAbs) {
90034
- resolved = path103.win32.resolve(inputPath);
90035
- } else if (path103.isAbsolute(inputPath)) {
90036
- resolved = path103.resolve(inputPath);
90017
+ resolved = path102.win32.resolve(inputPath);
90018
+ } else if (path102.isAbsolute(inputPath)) {
90019
+ resolved = path102.resolve(inputPath);
90037
90020
  } else {
90038
- resolved = path103.resolve(baseDir, inputPath);
90021
+ resolved = path102.resolve(baseDir, inputPath);
90039
90022
  }
90040
- const workspaceResolved = path103.resolve(workspaceDir);
90023
+ const workspaceResolved = path102.resolve(workspaceDir);
90041
90024
  let relative22;
90042
90025
  if (isWinAbs) {
90043
- relative22 = path103.win32.relative(workspaceResolved, resolved);
90026
+ relative22 = path102.win32.relative(workspaceResolved, resolved);
90044
90027
  } else {
90045
- relative22 = path103.relative(workspaceResolved, resolved);
90028
+ relative22 = path102.relative(workspaceResolved, resolved);
90046
90029
  }
90047
90030
  if (relative22.startsWith("..")) {
90048
90031
  return "path traversal detected";
@@ -90107,7 +90090,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
90107
90090
  if (typeof file3 !== "string") {
90108
90091
  continue;
90109
90092
  }
90110
- const resolvedPath = path103.resolve(file3);
90093
+ const resolvedPath = path102.resolve(file3);
90111
90094
  const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
90112
90095
  if (validationError) {
90113
90096
  continue;
@@ -90264,7 +90247,7 @@ async function runSecretscanWithFiles(files, directory) {
90264
90247
  skippedFiles++;
90265
90248
  continue;
90266
90249
  }
90267
- const resolvedPath = path103.resolve(file3);
90250
+ const resolvedPath = path102.resolve(file3);
90268
90251
  const validationError = validatePath(resolvedPath, directory, directory);
90269
90252
  if (validationError) {
90270
90253
  skippedFiles++;
@@ -90282,14 +90265,14 @@ async function runSecretscanWithFiles(files, directory) {
90282
90265
  };
90283
90266
  }
90284
90267
  for (const file3 of validatedFiles) {
90285
- const ext = path103.extname(file3).toLowerCase();
90268
+ const ext = path102.extname(file3).toLowerCase();
90286
90269
  if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
90287
90270
  skippedFiles++;
90288
90271
  continue;
90289
90272
  }
90290
90273
  let stat7;
90291
90274
  try {
90292
- stat7 = fs81.statSync(file3);
90275
+ stat7 = fs80.statSync(file3);
90293
90276
  } catch {
90294
90277
  skippedFiles++;
90295
90278
  continue;
@@ -90300,7 +90283,7 @@ async function runSecretscanWithFiles(files, directory) {
90300
90283
  }
90301
90284
  let content;
90302
90285
  try {
90303
- const buffer = fs81.readFileSync(file3);
90286
+ const buffer = fs80.readFileSync(file3);
90304
90287
  if (buffer.includes(0)) {
90305
90288
  skippedFiles++;
90306
90289
  continue;
@@ -90501,7 +90484,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
90501
90484
  const preexistingFindings = [];
90502
90485
  for (const finding of findings) {
90503
90486
  const filePath = finding.location.file;
90504
- const normalised = path103.relative(directory, filePath).replace(/\\/g, "/");
90487
+ const normalised = path102.relative(directory, filePath).replace(/\\/g, "/");
90505
90488
  const changedLines = changedLineRanges.get(normalised);
90506
90489
  if (changedLines?.has(finding.location.line)) {
90507
90490
  newFindings.push(finding);
@@ -90552,7 +90535,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
90552
90535
  warn(`pre_check_batch: Invalid file path: ${file3}`);
90553
90536
  continue;
90554
90537
  }
90555
- changedFiles.push(path103.resolve(directory, file3));
90538
+ changedFiles.push(path102.resolve(directory, file3));
90556
90539
  }
90557
90540
  if (changedFiles.length === 0) {
90558
90541
  warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
@@ -90753,7 +90736,7 @@ var pre_check_batch = createSwarmTool({
90753
90736
  };
90754
90737
  return JSON.stringify(errorResult, null, 2);
90755
90738
  }
90756
- const resolvedDirectory = path103.resolve(typedArgs.directory);
90739
+ const resolvedDirectory = path102.resolve(typedArgs.directory);
90757
90740
  const workspaceAnchor = resolvedDirectory;
90758
90741
  const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
90759
90742
  if (dirError) {
@@ -90794,7 +90777,7 @@ var pre_check_batch = createSwarmTool({
90794
90777
  });
90795
90778
  // src/tools/repo-map.ts
90796
90779
  init_zod();
90797
- import * as path104 from "node:path";
90780
+ import * as path103 from "node:path";
90798
90781
  init_path_security();
90799
90782
  init_create_tool();
90800
90783
  var VALID_ACTIONS = [
@@ -90819,7 +90802,7 @@ function validateFile(p) {
90819
90802
  return "file contains control characters";
90820
90803
  if (containsPathTraversal(p))
90821
90804
  return "file contains path traversal";
90822
- if (path104.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
90805
+ if (path103.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
90823
90806
  return "file must be a workspace-relative path, not absolute";
90824
90807
  }
90825
90808
  return null;
@@ -90842,8 +90825,8 @@ function ok(action, payload) {
90842
90825
  }
90843
90826
  function toRelativeGraphPath(input, workspaceRoot) {
90844
90827
  const normalized = input.replace(/\\/g, "/");
90845
- if (path104.isAbsolute(normalized)) {
90846
- const rel = path104.relative(workspaceRoot, normalized).replace(/\\/g, "/");
90828
+ if (path103.isAbsolute(normalized)) {
90829
+ const rel = path103.relative(workspaceRoot, normalized).replace(/\\/g, "/");
90847
90830
  return normalizeGraphPath2(rel);
90848
90831
  }
90849
90832
  return normalizeGraphPath2(normalized);
@@ -90987,8 +90970,8 @@ var repo_map = createSwarmTool({
90987
90970
  // src/tools/req-coverage.ts
90988
90971
  init_zod();
90989
90972
  init_create_tool();
90990
- import * as fs82 from "node:fs";
90991
- import * as path105 from "node:path";
90973
+ import * as fs81 from "node:fs";
90974
+ import * as path104 from "node:path";
90992
90975
  var SPEC_FILE = ".swarm/spec.md";
90993
90976
  var EVIDENCE_DIR4 = ".swarm/evidence";
90994
90977
  var OBLIGATION_KEYWORDS = ["MUST", "SHOULD", "SHALL"];
@@ -91047,19 +91030,19 @@ function extractObligationAndText(id, lineText) {
91047
91030
  var PHASE_TASK_ID_REGEX = /^\d+\.\d+(\.\d+)*$/;
91048
91031
  function readTouchedFiles(evidenceDir, phase, cwd) {
91049
91032
  const touchedFiles = new Set;
91050
- if (!fs82.existsSync(evidenceDir) || !fs82.statSync(evidenceDir).isDirectory()) {
91033
+ if (!fs81.existsSync(evidenceDir) || !fs81.statSync(evidenceDir).isDirectory()) {
91051
91034
  return [];
91052
91035
  }
91053
91036
  let entries;
91054
91037
  try {
91055
- entries = fs82.readdirSync(evidenceDir);
91038
+ entries = fs81.readdirSync(evidenceDir);
91056
91039
  } catch {
91057
91040
  return [];
91058
91041
  }
91059
91042
  for (const entry of entries) {
91060
- const entryPath = path105.join(evidenceDir, entry);
91043
+ const entryPath = path104.join(evidenceDir, entry);
91061
91044
  try {
91062
- const stat7 = fs82.statSync(entryPath);
91045
+ const stat7 = fs81.statSync(entryPath);
91063
91046
  if (!stat7.isDirectory()) {
91064
91047
  continue;
91065
91048
  }
@@ -91073,14 +91056,14 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
91073
91056
  if (entryPhase !== String(phase)) {
91074
91057
  continue;
91075
91058
  }
91076
- const evidenceFilePath = path105.join(entryPath, "evidence.json");
91059
+ const evidenceFilePath = path104.join(entryPath, "evidence.json");
91077
91060
  try {
91078
- const resolvedPath = path105.resolve(evidenceFilePath);
91079
- const evidenceDirResolved = path105.resolve(evidenceDir);
91080
- if (!resolvedPath.startsWith(evidenceDirResolved + path105.sep)) {
91061
+ const resolvedPath = path104.resolve(evidenceFilePath);
91062
+ const evidenceDirResolved = path104.resolve(evidenceDir);
91063
+ if (!resolvedPath.startsWith(evidenceDirResolved + path104.sep)) {
91081
91064
  continue;
91082
91065
  }
91083
- const stat7 = fs82.lstatSync(evidenceFilePath);
91066
+ const stat7 = fs81.lstatSync(evidenceFilePath);
91084
91067
  if (!stat7.isFile()) {
91085
91068
  continue;
91086
91069
  }
@@ -91092,7 +91075,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
91092
91075
  }
91093
91076
  let content;
91094
91077
  try {
91095
- content = fs82.readFileSync(evidenceFilePath, "utf-8");
91078
+ content = fs81.readFileSync(evidenceFilePath, "utf-8");
91096
91079
  } catch {
91097
91080
  continue;
91098
91081
  }
@@ -91111,7 +91094,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
91111
91094
  if (Array.isArray(diffEntry.files_changed)) {
91112
91095
  for (const file3 of diffEntry.files_changed) {
91113
91096
  if (typeof file3 === "string") {
91114
- touchedFiles.add(path105.resolve(cwd, file3));
91097
+ touchedFiles.add(path104.resolve(cwd, file3));
91115
91098
  }
91116
91099
  }
91117
91100
  }
@@ -91124,12 +91107,12 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
91124
91107
  }
91125
91108
  function searchFileForKeywords(filePath, keywords, cwd) {
91126
91109
  try {
91127
- const resolvedPath = path105.resolve(filePath);
91128
- const cwdResolved = path105.resolve(cwd);
91110
+ const resolvedPath = path104.resolve(filePath);
91111
+ const cwdResolved = path104.resolve(cwd);
91129
91112
  if (!resolvedPath.startsWith(cwdResolved)) {
91130
91113
  return false;
91131
91114
  }
91132
- const content = fs82.readFileSync(resolvedPath, "utf-8");
91115
+ const content = fs81.readFileSync(resolvedPath, "utf-8");
91133
91116
  for (const keyword of keywords) {
91134
91117
  const regex = new RegExp(`\\b${keyword}\\b`, "i");
91135
91118
  if (regex.test(content)) {
@@ -91259,10 +91242,10 @@ var req_coverage = createSwarmTool({
91259
91242
  }, null, 2);
91260
91243
  }
91261
91244
  const cwd = inputDirectory || directory;
91262
- const specPath = path105.join(cwd, SPEC_FILE);
91245
+ const specPath = path104.join(cwd, SPEC_FILE);
91263
91246
  let specContent;
91264
91247
  try {
91265
- specContent = fs82.readFileSync(specPath, "utf-8");
91248
+ specContent = fs81.readFileSync(specPath, "utf-8");
91266
91249
  } catch (readError) {
91267
91250
  return JSON.stringify({
91268
91251
  success: false,
@@ -91286,7 +91269,7 @@ var req_coverage = createSwarmTool({
91286
91269
  message: "No FR requirements found in spec.md"
91287
91270
  }, null, 2);
91288
91271
  }
91289
- const evidenceDir = path105.join(cwd, EVIDENCE_DIR4);
91272
+ const evidenceDir = path104.join(cwd, EVIDENCE_DIR4);
91290
91273
  const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
91291
91274
  const analyzedRequirements = [];
91292
91275
  let coveredCount = 0;
@@ -91312,12 +91295,12 @@ var req_coverage = createSwarmTool({
91312
91295
  requirements: analyzedRequirements
91313
91296
  };
91314
91297
  const reportFilename = `req-coverage-phase-${phase}.json`;
91315
- const reportPath = path105.join(evidenceDir, reportFilename);
91298
+ const reportPath = path104.join(evidenceDir, reportFilename);
91316
91299
  try {
91317
- if (!fs82.existsSync(evidenceDir)) {
91318
- fs82.mkdirSync(evidenceDir, { recursive: true });
91300
+ if (!fs81.existsSync(evidenceDir)) {
91301
+ fs81.mkdirSync(evidenceDir, { recursive: true });
91319
91302
  }
91320
- fs82.writeFileSync(reportPath, JSON.stringify(result, null, 2), "utf-8");
91303
+ fs81.writeFileSync(reportPath, JSON.stringify(result, null, 2), "utf-8");
91321
91304
  } catch (writeError) {
91322
91305
  console.warn(`Failed to write coverage report: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
91323
91306
  }
@@ -91399,8 +91382,8 @@ init_plan_schema();
91399
91382
  init_qa_gate_profile();
91400
91383
  init_file_locks();
91401
91384
  import * as crypto10 from "node:crypto";
91402
- import * as fs83 from "node:fs";
91403
- import * as path106 from "node:path";
91385
+ import * as fs82 from "node:fs";
91386
+ import * as path105 from "node:path";
91404
91387
  init_ledger();
91405
91388
  init_manager();
91406
91389
  init_state();
@@ -91478,17 +91461,17 @@ async function executeSavePlan(args2, fallbackDir) {
91478
91461
  };
91479
91462
  }
91480
91463
  if (args2.working_directory && fallbackDir) {
91481
- const resolvedTarget = path106.resolve(args2.working_directory);
91482
- const resolvedRoot = path106.resolve(fallbackDir);
91464
+ const resolvedTarget = path105.resolve(args2.working_directory);
91465
+ const resolvedRoot = path105.resolve(fallbackDir);
91483
91466
  let fallbackExists = false;
91484
91467
  try {
91485
- fs83.accessSync(resolvedRoot, fs83.constants.F_OK);
91468
+ fs82.accessSync(resolvedRoot, fs82.constants.F_OK);
91486
91469
  fallbackExists = true;
91487
91470
  } catch {
91488
91471
  fallbackExists = false;
91489
91472
  }
91490
91473
  if (fallbackExists) {
91491
- const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path106.sep);
91474
+ const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path105.sep);
91492
91475
  if (isSubdirectory) {
91493
91476
  return {
91494
91477
  success: false,
@@ -91504,11 +91487,11 @@ async function executeSavePlan(args2, fallbackDir) {
91504
91487
  let specMtime;
91505
91488
  let specHash;
91506
91489
  if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
91507
- const specPath = path106.join(targetWorkspace, ".swarm", "spec.md");
91490
+ const specPath = path105.join(targetWorkspace, ".swarm", "spec.md");
91508
91491
  try {
91509
- const stat7 = await fs83.promises.stat(specPath);
91492
+ const stat7 = await fs82.promises.stat(specPath);
91510
91493
  specMtime = stat7.mtime.toISOString();
91511
- const content = await fs83.promises.readFile(specPath, "utf8");
91494
+ const content = await fs82.promises.readFile(specPath, "utf8");
91512
91495
  specHash = crypto10.createHash("sha256").update(content).digest("hex");
91513
91496
  } catch {
91514
91497
  return {
@@ -91520,10 +91503,10 @@ async function executeSavePlan(args2, fallbackDir) {
91520
91503
  }
91521
91504
  }
91522
91505
  if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
91523
- const contextPath = path106.join(targetWorkspace, ".swarm", "context.md");
91506
+ const contextPath = path105.join(targetWorkspace, ".swarm", "context.md");
91524
91507
  let contextContent = "";
91525
91508
  try {
91526
- contextContent = await fs83.promises.readFile(contextPath, "utf8");
91509
+ contextContent = await fs82.promises.readFile(contextPath, "utf8");
91527
91510
  } catch {}
91528
91511
  const hasPendingSection = contextContent.includes("## Pending QA Gate Selection");
91529
91512
  if (!hasPendingSection) {
@@ -91673,14 +91656,14 @@ async function executeSavePlan(args2, fallbackDir) {
91673
91656
  }
91674
91657
  await writeCheckpoint(dir).catch(() => {});
91675
91658
  try {
91676
- const markerPath = path106.join(dir, ".swarm", ".plan-write-marker");
91659
+ const markerPath = path105.join(dir, ".swarm", ".plan-write-marker");
91677
91660
  const marker = JSON.stringify({
91678
91661
  source: "save_plan",
91679
91662
  timestamp: new Date().toISOString(),
91680
91663
  phases_count: plan.phases.length,
91681
91664
  tasks_count: tasksCount
91682
91665
  });
91683
- await fs83.promises.writeFile(markerPath, marker, "utf8");
91666
+ await fs82.promises.writeFile(markerPath, marker, "utf8");
91684
91667
  } catch {}
91685
91668
  const warnings = [];
91686
91669
  let criticReviewFound = false;
@@ -91696,7 +91679,7 @@ async function executeSavePlan(args2, fallbackDir) {
91696
91679
  return {
91697
91680
  success: true,
91698
91681
  message: "Plan saved successfully",
91699
- plan_path: path106.join(dir, ".swarm", "plan.json"),
91682
+ plan_path: path105.join(dir, ".swarm", "plan.json"),
91700
91683
  phases_count: plan.phases.length,
91701
91684
  tasks_count: tasksCount,
91702
91685
  ...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
@@ -91748,8 +91731,8 @@ var save_plan = createSwarmTool({
91748
91731
  // src/tools/sbom-generate.ts
91749
91732
  init_zod();
91750
91733
  init_manager2();
91751
- import * as fs84 from "node:fs";
91752
- import * as path107 from "node:path";
91734
+ import * as fs83 from "node:fs";
91735
+ import * as path106 from "node:path";
91753
91736
 
91754
91737
  // src/sbom/detectors/index.ts
91755
91738
  init_utils();
@@ -92597,9 +92580,9 @@ function findManifestFiles(rootDir) {
92597
92580
  const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
92598
92581
  function searchDir(dir) {
92599
92582
  try {
92600
- const entries = fs84.readdirSync(dir, { withFileTypes: true });
92583
+ const entries = fs83.readdirSync(dir, { withFileTypes: true });
92601
92584
  for (const entry of entries) {
92602
- const fullPath = path107.join(dir, entry.name);
92585
+ const fullPath = path106.join(dir, entry.name);
92603
92586
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
92604
92587
  continue;
92605
92588
  }
@@ -92608,7 +92591,7 @@ function findManifestFiles(rootDir) {
92608
92591
  } else if (entry.isFile()) {
92609
92592
  for (const pattern of patterns) {
92610
92593
  if (simpleGlobToRegex(pattern).test(entry.name)) {
92611
- manifestFiles.push(path107.relative(rootDir, fullPath));
92594
+ manifestFiles.push(path106.relative(rootDir, fullPath));
92612
92595
  break;
92613
92596
  }
92614
92597
  }
@@ -92624,13 +92607,13 @@ function findManifestFilesInDirs(directories, workingDir) {
92624
92607
  const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
92625
92608
  for (const dir of directories) {
92626
92609
  try {
92627
- const entries = fs84.readdirSync(dir, { withFileTypes: true });
92610
+ const entries = fs83.readdirSync(dir, { withFileTypes: true });
92628
92611
  for (const entry of entries) {
92629
- const fullPath = path107.join(dir, entry.name);
92612
+ const fullPath = path106.join(dir, entry.name);
92630
92613
  if (entry.isFile()) {
92631
92614
  for (const pattern of patterns) {
92632
92615
  if (simpleGlobToRegex(pattern).test(entry.name)) {
92633
- found.push(path107.relative(workingDir, fullPath));
92616
+ found.push(path106.relative(workingDir, fullPath));
92634
92617
  break;
92635
92618
  }
92636
92619
  }
@@ -92643,11 +92626,11 @@ function findManifestFilesInDirs(directories, workingDir) {
92643
92626
  function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
92644
92627
  const dirs = new Set;
92645
92628
  for (const file3 of changedFiles) {
92646
- let currentDir = path107.dirname(file3);
92629
+ let currentDir = path106.dirname(file3);
92647
92630
  while (true) {
92648
- if (currentDir && currentDir !== "." && currentDir !== path107.sep) {
92649
- dirs.add(path107.join(workingDir, currentDir));
92650
- const parent = path107.dirname(currentDir);
92631
+ if (currentDir && currentDir !== "." && currentDir !== path106.sep) {
92632
+ dirs.add(path106.join(workingDir, currentDir));
92633
+ const parent = path106.dirname(currentDir);
92651
92634
  if (parent === currentDir)
92652
92635
  break;
92653
92636
  currentDir = parent;
@@ -92661,7 +92644,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
92661
92644
  }
92662
92645
  function ensureOutputDir(outputDir) {
92663
92646
  try {
92664
- fs84.mkdirSync(outputDir, { recursive: true });
92647
+ fs83.mkdirSync(outputDir, { recursive: true });
92665
92648
  } catch (error93) {
92666
92649
  if (!error93 || error93.code !== "EEXIST") {
92667
92650
  throw error93;
@@ -92731,7 +92714,7 @@ var sbom_generate = createSwarmTool({
92731
92714
  const changedFiles = obj.changed_files;
92732
92715
  const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
92733
92716
  const workingDir = directory;
92734
- const outputDir = path107.isAbsolute(relativeOutputDir) ? relativeOutputDir : path107.join(workingDir, relativeOutputDir);
92717
+ const outputDir = path106.isAbsolute(relativeOutputDir) ? relativeOutputDir : path106.join(workingDir, relativeOutputDir);
92735
92718
  let manifestFiles = [];
92736
92719
  if (scope === "all") {
92737
92720
  manifestFiles = findManifestFiles(workingDir);
@@ -92754,11 +92737,11 @@ var sbom_generate = createSwarmTool({
92754
92737
  const processedFiles = [];
92755
92738
  for (const manifestFile of manifestFiles) {
92756
92739
  try {
92757
- const fullPath = path107.isAbsolute(manifestFile) ? manifestFile : path107.join(workingDir, manifestFile);
92758
- if (!fs84.existsSync(fullPath)) {
92740
+ const fullPath = path106.isAbsolute(manifestFile) ? manifestFile : path106.join(workingDir, manifestFile);
92741
+ if (!fs83.existsSync(fullPath)) {
92759
92742
  continue;
92760
92743
  }
92761
- const content = fs84.readFileSync(fullPath, "utf-8");
92744
+ const content = fs83.readFileSync(fullPath, "utf-8");
92762
92745
  const components = detectComponents(manifestFile, content);
92763
92746
  processedFiles.push(manifestFile);
92764
92747
  if (components.length > 0) {
@@ -92771,8 +92754,8 @@ var sbom_generate = createSwarmTool({
92771
92754
  const bom = generateCycloneDX(allComponents);
92772
92755
  const bomJson = serializeCycloneDX(bom);
92773
92756
  const filename = generateSbomFilename();
92774
- const outputPath = path107.join(outputDir, filename);
92775
- fs84.writeFileSync(outputPath, bomJson, "utf-8");
92757
+ const outputPath = path106.join(outputDir, filename);
92758
+ fs83.writeFileSync(outputPath, bomJson, "utf-8");
92776
92759
  const verdict = processedFiles.length > 0 ? "pass" : "pass";
92777
92760
  try {
92778
92761
  const timestamp = new Date().toISOString();
@@ -92814,8 +92797,8 @@ var sbom_generate = createSwarmTool({
92814
92797
  // src/tools/schema-drift.ts
92815
92798
  init_zod();
92816
92799
  init_create_tool();
92817
- import * as fs85 from "node:fs";
92818
- import * as path108 from "node:path";
92800
+ import * as fs84 from "node:fs";
92801
+ import * as path107 from "node:path";
92819
92802
  var SPEC_CANDIDATES = [
92820
92803
  "openapi.json",
92821
92804
  "openapi.yaml",
@@ -92847,28 +92830,28 @@ function normalizePath4(p) {
92847
92830
  }
92848
92831
  function discoverSpecFile(cwd, specFileArg) {
92849
92832
  if (specFileArg) {
92850
- const resolvedPath = path108.resolve(cwd, specFileArg);
92851
- const normalizedCwd = cwd.endsWith(path108.sep) ? cwd : cwd + path108.sep;
92833
+ const resolvedPath = path107.resolve(cwd, specFileArg);
92834
+ const normalizedCwd = cwd.endsWith(path107.sep) ? cwd : cwd + path107.sep;
92852
92835
  if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
92853
92836
  throw new Error("Invalid spec_file: path traversal detected");
92854
92837
  }
92855
- const ext = path108.extname(resolvedPath).toLowerCase();
92838
+ const ext = path107.extname(resolvedPath).toLowerCase();
92856
92839
  if (!ALLOWED_EXTENSIONS.includes(ext)) {
92857
92840
  throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
92858
92841
  }
92859
- const stats = fs85.statSync(resolvedPath);
92842
+ const stats = fs84.statSync(resolvedPath);
92860
92843
  if (stats.size > MAX_SPEC_SIZE) {
92861
92844
  throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
92862
92845
  }
92863
- if (!fs85.existsSync(resolvedPath)) {
92846
+ if (!fs84.existsSync(resolvedPath)) {
92864
92847
  throw new Error(`Spec file not found: ${resolvedPath}`);
92865
92848
  }
92866
92849
  return resolvedPath;
92867
92850
  }
92868
92851
  for (const candidate of SPEC_CANDIDATES) {
92869
- const candidatePath = path108.resolve(cwd, candidate);
92870
- if (fs85.existsSync(candidatePath)) {
92871
- const stats = fs85.statSync(candidatePath);
92852
+ const candidatePath = path107.resolve(cwd, candidate);
92853
+ if (fs84.existsSync(candidatePath)) {
92854
+ const stats = fs84.statSync(candidatePath);
92872
92855
  if (stats.size <= MAX_SPEC_SIZE) {
92873
92856
  return candidatePath;
92874
92857
  }
@@ -92877,8 +92860,8 @@ function discoverSpecFile(cwd, specFileArg) {
92877
92860
  return null;
92878
92861
  }
92879
92862
  function parseSpec(specFile) {
92880
- const content = fs85.readFileSync(specFile, "utf-8");
92881
- const ext = path108.extname(specFile).toLowerCase();
92863
+ const content = fs84.readFileSync(specFile, "utf-8");
92864
+ const ext = path107.extname(specFile).toLowerCase();
92882
92865
  if (ext === ".json") {
92883
92866
  return parseJsonSpec(content);
92884
92867
  }
@@ -92949,12 +92932,12 @@ function extractRoutes(cwd) {
92949
92932
  function walkDir(dir) {
92950
92933
  let entries;
92951
92934
  try {
92952
- entries = fs85.readdirSync(dir, { withFileTypes: true });
92935
+ entries = fs84.readdirSync(dir, { withFileTypes: true });
92953
92936
  } catch {
92954
92937
  return;
92955
92938
  }
92956
92939
  for (const entry of entries) {
92957
- const fullPath = path108.join(dir, entry.name);
92940
+ const fullPath = path107.join(dir, entry.name);
92958
92941
  if (entry.isSymbolicLink()) {
92959
92942
  continue;
92960
92943
  }
@@ -92964,7 +92947,7 @@ function extractRoutes(cwd) {
92964
92947
  }
92965
92948
  walkDir(fullPath);
92966
92949
  } else if (entry.isFile()) {
92967
- const ext = path108.extname(entry.name).toLowerCase();
92950
+ const ext = path107.extname(entry.name).toLowerCase();
92968
92951
  const baseName = entry.name.toLowerCase();
92969
92952
  if (![".ts", ".js", ".mjs"].includes(ext)) {
92970
92953
  continue;
@@ -92982,7 +92965,7 @@ function extractRoutes(cwd) {
92982
92965
  }
92983
92966
  function extractRoutesFromFile(filePath) {
92984
92967
  const routes = [];
92985
- const content = fs85.readFileSync(filePath, "utf-8");
92968
+ const content = fs84.readFileSync(filePath, "utf-8");
92986
92969
  const lines = content.split(/\r?\n/);
92987
92970
  const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
92988
92971
  const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
@@ -93131,8 +93114,8 @@ init_zod();
93131
93114
  init_bun_compat();
93132
93115
  init_path_security();
93133
93116
  init_create_tool();
93134
- import * as fs86 from "node:fs";
93135
- import * as path109 from "node:path";
93117
+ import * as fs85 from "node:fs";
93118
+ import * as path108 from "node:path";
93136
93119
  var DEFAULT_MAX_RESULTS = 100;
93137
93120
  var DEFAULT_MAX_LINES = 200;
93138
93121
  var REGEX_TIMEOUT_MS = 5000;
@@ -93168,11 +93151,11 @@ function containsWindowsAttacks3(str) {
93168
93151
  }
93169
93152
  function isPathInWorkspace3(filePath, workspace) {
93170
93153
  try {
93171
- const resolvedPath = path109.resolve(workspace, filePath);
93172
- const realWorkspace = fs86.realpathSync(workspace);
93173
- const realResolvedPath = fs86.realpathSync(resolvedPath);
93174
- const relativePath = path109.relative(realWorkspace, realResolvedPath);
93175
- if (relativePath.startsWith("..") || path109.isAbsolute(relativePath)) {
93154
+ const resolvedPath = path108.resolve(workspace, filePath);
93155
+ const realWorkspace = fs85.realpathSync(workspace);
93156
+ const realResolvedPath = fs85.realpathSync(resolvedPath);
93157
+ const relativePath = path108.relative(realWorkspace, realResolvedPath);
93158
+ if (relativePath.startsWith("..") || path108.isAbsolute(relativePath)) {
93176
93159
  return false;
93177
93160
  }
93178
93161
  return true;
@@ -93185,12 +93168,12 @@ function validatePathForRead2(filePath, workspace) {
93185
93168
  }
93186
93169
  function findRgInEnvPath() {
93187
93170
  const searchPath = process.env.PATH ?? "";
93188
- for (const dir of searchPath.split(path109.delimiter)) {
93171
+ for (const dir of searchPath.split(path108.delimiter)) {
93189
93172
  if (!dir)
93190
93173
  continue;
93191
93174
  const isWindows = process.platform === "win32";
93192
- const candidate = path109.join(dir, isWindows ? "rg.exe" : "rg");
93193
- if (fs86.existsSync(candidate))
93175
+ const candidate = path108.join(dir, isWindows ? "rg.exe" : "rg");
93176
+ if (fs85.existsSync(candidate))
93194
93177
  return candidate;
93195
93178
  }
93196
93179
  return null;
@@ -93317,10 +93300,10 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
93317
93300
  return files;
93318
93301
  }
93319
93302
  try {
93320
- const entries = fs86.readdirSync(dir, { withFileTypes: true });
93303
+ const entries = fs85.readdirSync(dir, { withFileTypes: true });
93321
93304
  for (const entry of entries) {
93322
- const fullPath = path109.join(dir, entry.name);
93323
- const relativePath = path109.relative(workspace, fullPath);
93305
+ const fullPath = path108.join(dir, entry.name);
93306
+ const relativePath = path108.relative(workspace, fullPath);
93324
93307
  if (!validatePathForRead2(fullPath, workspace)) {
93325
93308
  continue;
93326
93309
  }
@@ -93361,13 +93344,13 @@ async function fallbackSearch(opts) {
93361
93344
  const matches = [];
93362
93345
  let total = 0;
93363
93346
  for (const file3 of files) {
93364
- const fullPath = path109.join(opts.workspace, file3);
93347
+ const fullPath = path108.join(opts.workspace, file3);
93365
93348
  if (!validatePathForRead2(fullPath, opts.workspace)) {
93366
93349
  continue;
93367
93350
  }
93368
93351
  let stats;
93369
93352
  try {
93370
- stats = fs86.statSync(fullPath);
93353
+ stats = fs85.statSync(fullPath);
93371
93354
  if (stats.size > MAX_FILE_SIZE_BYTES10) {
93372
93355
  continue;
93373
93356
  }
@@ -93376,7 +93359,7 @@ async function fallbackSearch(opts) {
93376
93359
  }
93377
93360
  let content;
93378
93361
  try {
93379
- content = fs86.readFileSync(fullPath, "utf-8");
93362
+ content = fs85.readFileSync(fullPath, "utf-8");
93380
93363
  } catch {
93381
93364
  continue;
93382
93365
  }
@@ -93488,7 +93471,7 @@ var search = createSwarmTool({
93488
93471
  message: "Exclude pattern contains invalid Windows-specific sequence"
93489
93472
  }, null, 2);
93490
93473
  }
93491
- if (!fs86.existsSync(directory)) {
93474
+ if (!fs85.existsSync(directory)) {
93492
93475
  return JSON.stringify({
93493
93476
  error: true,
93494
93477
  type: "unknown",
@@ -93668,7 +93651,7 @@ init_schema();
93668
93651
  init_knowledge_store();
93669
93652
  import { existsSync as existsSync64 } from "node:fs";
93670
93653
  import { mkdir as mkdir17, rename as rename6, writeFile as writeFile14 } from "node:fs/promises";
93671
- import * as path111 from "node:path";
93654
+ import * as path110 from "node:path";
93672
93655
 
93673
93656
  // src/hooks/skill-improver-llm-factory.ts
93674
93657
  init_state();
@@ -93784,7 +93767,7 @@ init_skill_generator();
93784
93767
  var import_proper_lockfile7 = __toESM(require_proper_lockfile(), 1);
93785
93768
  import { existsSync as existsSync63 } from "node:fs";
93786
93769
  import { mkdir as mkdir16, readFile as readFile15, rename as rename5, writeFile as writeFile13 } from "node:fs/promises";
93787
- import * as path110 from "node:path";
93770
+ import * as path109 from "node:path";
93788
93771
  var LOCK_ACQUIRE_TIMEOUT_MS = 1e4;
93789
93772
  var LOCK_RETRY_OPTS = {
93790
93773
  retries: {
@@ -93812,7 +93795,7 @@ async function acquireLock2(dir) {
93812
93795
  }
93813
93796
  }
93814
93797
  function resolveQuotaPath(directory) {
93815
- return path110.join(directory, ".swarm", "skill-improver-quota.json");
93798
+ return path109.join(directory, ".swarm", "skill-improver-quota.json");
93816
93799
  }
93817
93800
  function todayKey(window2, now = new Date) {
93818
93801
  if (window2 === "utc") {
@@ -93838,7 +93821,7 @@ async function readState(filePath) {
93838
93821
  }
93839
93822
  }
93840
93823
  async function writeState(filePath, state) {
93841
- await mkdir16(path110.dirname(filePath), { recursive: true });
93824
+ await mkdir16(path109.dirname(filePath), { recursive: true });
93842
93825
  const tmp = `${filePath}.tmp-${process.pid}`;
93843
93826
  await writeFile13(tmp, JSON.stringify(state, null, 2), "utf-8");
93844
93827
  await rename5(tmp, filePath);
@@ -93861,10 +93844,10 @@ async function getQuotaState(directory, opts) {
93861
93844
  }
93862
93845
  async function reserveQuota(directory, opts) {
93863
93846
  const filePath = resolveQuotaPath(directory);
93864
- await mkdir16(path110.dirname(filePath), { recursive: true });
93847
+ await mkdir16(path109.dirname(filePath), { recursive: true });
93865
93848
  let release = null;
93866
93849
  try {
93867
- release = await acquireLock2(path110.dirname(filePath));
93850
+ release = await acquireLock2(path109.dirname(filePath));
93868
93851
  const state = await getQuotaState(directory, opts);
93869
93852
  if (state.calls_used + opts.nCalls > opts.maxCalls) {
93870
93853
  return {
@@ -93891,10 +93874,10 @@ async function reserveQuota(directory, opts) {
93891
93874
  }
93892
93875
  async function releaseQuota(directory, opts) {
93893
93876
  const filePath = resolveQuotaPath(directory);
93894
- await mkdir16(path110.dirname(filePath), { recursive: true });
93877
+ await mkdir16(path109.dirname(filePath), { recursive: true });
93895
93878
  let release = null;
93896
93879
  try {
93897
- release = await acquireLock2(path110.dirname(filePath));
93880
+ release = await acquireLock2(path109.dirname(filePath));
93898
93881
  const state = await getQuotaState(directory, opts);
93899
93882
  const next = {
93900
93883
  ...state,
@@ -93917,7 +93900,7 @@ function timestampSlug(d) {
93917
93900
  return d.toISOString().replace(/[:.]/g, "-");
93918
93901
  }
93919
93902
  async function atomicWrite4(p, content) {
93920
- await mkdir17(path111.dirname(p), { recursive: true });
93903
+ await mkdir17(path110.dirname(p), { recursive: true });
93921
93904
  const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
93922
93905
  await writeFile14(tmp, content, "utf-8");
93923
93906
  await rename6(tmp, p);
@@ -94117,8 +94100,8 @@ async function runSkillImprover(req) {
94117
94100
  sourceKnowledgeIds: w.sourceKnowledgeIds
94118
94101
  }));
94119
94102
  }
94120
- const proposalDir = path111.join(req.directory, ".swarm", "skill-improver", "proposals");
94121
- const proposalFile = path111.join(proposalDir, `${timestampSlug(now)}.md`);
94103
+ const proposalDir = path110.join(req.directory, ".swarm", "skill-improver", "proposals");
94104
+ const proposalFile = path110.join(proposalDir, `${timestampSlug(now)}.md`);
94122
94105
  const finalBody = source === "llm" ? buildLLMProposalFrame({
94123
94106
  body: body2,
94124
94107
  targets,
@@ -94211,7 +94194,7 @@ init_config();
94211
94194
  init_schema();
94212
94195
  init_create_tool();
94213
94196
  import { mkdir as mkdir18, rename as rename7, writeFile as writeFile15 } from "node:fs/promises";
94214
- import * as path112 from "node:path";
94197
+ import * as path111 from "node:path";
94215
94198
  var MAX_SPEC_BYTES = 256 * 1024;
94216
94199
  var spec_write = createSwarmTool({
94217
94200
  description: "Write the canonical project spec to .swarm/spec.md. Atomic write, size-bounded (256 KiB), heading-required. Honors spec_writer.allow_spec_write.",
@@ -94252,14 +94235,14 @@ var spec_write = createSwarmTool({
94252
94235
  reason: 'spec must contain at least one top-level "# Heading"'
94253
94236
  }, null, 2);
94254
94237
  }
94255
- const target = path112.join(directory, ".swarm", "spec.md");
94256
- await mkdir18(path112.dirname(target), { recursive: true });
94238
+ const target = path111.join(directory, ".swarm", "spec.md");
94239
+ await mkdir18(path111.dirname(target), { recursive: true });
94257
94240
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
94258
94241
  let finalContent = content;
94259
94242
  if (mode === "append") {
94260
94243
  try {
94261
- const fs87 = await import("node:fs/promises");
94262
- const prior = await fs87.readFile(target, "utf-8");
94244
+ const fs86 = await import("node:fs/promises");
94245
+ const prior = await fs86.readFile(target, "utf-8");
94263
94246
  finalContent = `${prior.replace(/\s+$/, "")}
94264
94247
 
94265
94248
  ${content}
@@ -94280,6 +94263,15 @@ ${content}
94280
94263
  // src/tools/submit-phase-council-verdicts.ts
94281
94264
  init_zod();
94282
94265
  init_loader();
94266
+ import {
94267
+ existsSync as existsSync65,
94268
+ mkdirSync as mkdirSync28,
94269
+ readFileSync as readFileSync55,
94270
+ renameSync as renameSync18,
94271
+ unlinkSync as unlinkSync14,
94272
+ writeFileSync as writeFileSync22
94273
+ } from "node:fs";
94274
+ import path112 from "node:path";
94283
94275
  init_create_tool();
94284
94276
  init_resolve_working_directory();
94285
94277
  var VerdictSchema2 = exports_external.object({
@@ -94382,6 +94374,12 @@ var submit_phase_council_verdicts = createSwarmTool({
94382
94374
  }, null, 2);
94383
94375
  }
94384
94376
  const synthesis = synthesizePhaseCouncilAdvisory(input.phaseNumber, input.phaseSummary, input.verdicts, input.roundNumber ?? 1, config3.council, workingDir);
94377
+ const existingMutationGapFinding = input.verdicts.some((verdict) => verdict.findings.some((finding) => finding.category === "mutation_gap"));
94378
+ const mutationGapFinding = existingMutationGapFinding ? null : getPhaseMutationGapFinding(input.phaseNumber, workingDir);
94379
+ if (mutationGapFinding) {
94380
+ addMutationGapFindingToSynthesis(synthesis, mutationGapFinding);
94381
+ }
94382
+ writePhaseCouncilEvidence(workingDir, synthesis);
94385
94383
  return JSON.stringify({
94386
94384
  success: true,
94387
94385
  overallVerdict: synthesis.overallVerdict,
@@ -94392,6 +94390,7 @@ var submit_phase_council_verdicts = createSwarmTool({
94392
94390
  advisoryFindingsCount: synthesis.advisoryFindings?.length ?? 0,
94393
94391
  unresolvedConflictsCount: synthesis.unresolvedConflicts?.length ?? 0,
94394
94392
  advisoryNotes: synthesis.advisoryNotes ?? [],
94393
+ mutationGapEmitted: mutationGapFinding !== null,
94395
94394
  membersVoted,
94396
94395
  membersAbsent,
94397
94396
  quorumSize: membersVoted.length,
@@ -94401,11 +94400,132 @@ var submit_phase_council_verdicts = createSwarmTool({
94401
94400
  }, null, 2);
94402
94401
  }
94403
94402
  });
94403
+ function getPhaseMutationGapFinding(phaseNumber, workingDir) {
94404
+ const mutationGatePath = path112.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
94405
+ try {
94406
+ const raw = readFileSync55(mutationGatePath, "utf-8");
94407
+ const parsed = JSON.parse(raw);
94408
+ const gateEntry = (parsed.entries ?? []).find((entry) => entry?.type === "mutation-gate");
94409
+ if (!gateEntry) {
94410
+ return {
94411
+ severity: "HIGH",
94412
+ category: "mutation_gap",
94413
+ location: `.swarm/evidence/${phaseNumber}/mutation-gate.json`,
94414
+ detail: "Mutation gate evidence is missing a mutation-gate entry for this phase.",
94415
+ evidence: 'Expected entries[].type="mutation-gate" with verdict in mutation-gate.json.'
94416
+ };
94417
+ }
94418
+ if (gateEntry.verdict === "skip") {
94419
+ return {
94420
+ severity: "MEDIUM",
94421
+ category: "mutation_gap",
94422
+ location: `.swarm/evidence/${phaseNumber}/mutation-gate.json`,
94423
+ detail: "Mutation testing was skipped for this phase; coverage is unverified.",
94424
+ evidence: 'mutation-gate.json recorded verdict="skip". Run mutation_test and write_mutation_evidence.'
94425
+ };
94426
+ }
94427
+ if (gateEntry.verdict === "warn") {
94428
+ return {
94429
+ severity: "LOW",
94430
+ category: "mutation_gap",
94431
+ location: `.swarm/evidence/${phaseNumber}/mutation-gate.json`,
94432
+ detail: "Mutation gate reported WARN; mutation coverage may be insufficient.",
94433
+ evidence: 'mutation-gate.json recorded verdict="warn" indicating below-pass mutation quality.'
94434
+ };
94435
+ }
94436
+ if (gateEntry.verdict === "fail") {
94437
+ return {
94438
+ severity: "HIGH",
94439
+ category: "mutation_gap",
94440
+ location: `.swarm/evidence/${phaseNumber}/mutation-gate.json`,
94441
+ detail: "Mutation gate reported FAIL; mutation testing quality is below the required threshold.",
94442
+ evidence: 'mutation-gate.json recorded verdict="fail" indicating insufficient mutation kill rate.'
94443
+ };
94444
+ }
94445
+ return null;
94446
+ } catch (error93) {
94447
+ if (error93.code === "ENOENT") {
94448
+ return {
94449
+ severity: "HIGH",
94450
+ category: "mutation_gap",
94451
+ location: `.swarm/evidence/${phaseNumber}/mutation-gate.json`,
94452
+ detail: "Mutation gate evidence file is missing for this phase, so mutation coverage cannot be verified.",
94453
+ evidence: "No .swarm/evidence/{phase}/mutation-gate.json was found at council synthesis time."
94454
+ };
94455
+ }
94456
+ return {
94457
+ severity: "MEDIUM",
94458
+ category: "mutation_gap",
94459
+ location: `.swarm/evidence/${phaseNumber}/mutation-gate.json`,
94460
+ detail: "Mutation gate evidence could not be read, so mutation coverage cannot be verified.",
94461
+ evidence: error93 instanceof Error ? error93.message : String(error93)
94462
+ };
94463
+ }
94464
+ }
94465
+ function writePhaseCouncilEvidence(workingDir, synthesis) {
94466
+ const evidenceDir = path112.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
94467
+ mkdirSync28(evidenceDir, { recursive: true });
94468
+ const evidenceFile = path112.join(evidenceDir, "phase-council.json");
94469
+ const evidenceBundle = {
94470
+ entries: [
94471
+ {
94472
+ type: "phase-council",
94473
+ phase_number: synthesis.phaseNumber,
94474
+ scope: "phase",
94475
+ timestamp: synthesis.timestamp,
94476
+ verdict: synthesis.overallVerdict,
94477
+ quorumSize: synthesis.quorumSize,
94478
+ phaseSummary: synthesis.phaseSummary ?? "",
94479
+ requiredFixes: synthesis.requiredFixes.map((finding) => ({
94480
+ severity: finding.severity,
94481
+ category: finding.category,
94482
+ location: finding.location,
94483
+ detail: finding.detail,
94484
+ evidence: finding.evidence
94485
+ })),
94486
+ advisoryNotes: synthesis.advisoryNotes,
94487
+ advisoryFindings: synthesis.advisoryFindings.map((finding) => ({
94488
+ severity: finding.severity,
94489
+ category: finding.category,
94490
+ location: finding.location,
94491
+ detail: finding.detail,
94492
+ evidence: finding.evidence
94493
+ })),
94494
+ roundNumber: synthesis.roundNumber,
94495
+ allCriteriaMet: synthesis.allCriteriaMet
94496
+ }
94497
+ ]
94498
+ };
94499
+ const tempFile = `${evidenceFile}.tmp-${Date.now()}`;
94500
+ try {
94501
+ writeFileSync22(tempFile, JSON.stringify(evidenceBundle, null, 2), "utf-8");
94502
+ renameSync18(tempFile, evidenceFile);
94503
+ } finally {
94504
+ if (existsSync65(tempFile)) {
94505
+ unlinkSync14(tempFile);
94506
+ }
94507
+ }
94508
+ }
94509
+ function addMutationGapFindingToSynthesis(synthesis, finding) {
94510
+ if (finding.severity === "HIGH" || finding.severity === "MEDIUM") {
94511
+ synthesis.requiredFixes.push(finding);
94512
+ } else {
94513
+ synthesis.advisoryFindings.push(finding);
94514
+ }
94515
+ synthesis.unifiedFeedbackMd += formatMutationGapFeedback(finding);
94516
+ }
94517
+ function formatMutationGapFeedback(finding) {
94518
+ return `
94519
+
94520
+ ### Mutation Coverage Gap
94521
+ - **[${finding.severity}]** \`${finding.location}\` (${finding.category}) — ${finding.detail}
94522
+ _Evidence:_ ${finding.evidence}`;
94523
+ }
94404
94524
  // src/tools/suggest-patch.ts
94405
94525
  init_zod();
94406
94526
  init_path_security();
94407
94527
  init_create_tool();
94408
- import * as fs87 from "node:fs";
94528
+ import * as fs86 from "node:fs";
94409
94529
  import * as path113 from "node:path";
94410
94530
  var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
94411
94531
  function containsWindowsAttacks4(str) {
@@ -94421,11 +94541,11 @@ function containsWindowsAttacks4(str) {
94421
94541
  function isPathInWorkspace4(filePath, workspace) {
94422
94542
  try {
94423
94543
  const resolvedPath = path113.resolve(workspace, filePath);
94424
- if (!fs87.existsSync(resolvedPath)) {
94544
+ if (!fs86.existsSync(resolvedPath)) {
94425
94545
  return true;
94426
94546
  }
94427
- const realWorkspace = fs87.realpathSync(workspace);
94428
- const realResolvedPath = fs87.realpathSync(resolvedPath);
94547
+ const realWorkspace = fs86.realpathSync(workspace);
94548
+ const realResolvedPath = fs86.realpathSync(resolvedPath);
94429
94549
  const relativePath = path113.relative(realWorkspace, realResolvedPath);
94430
94550
  if (relativePath.startsWith("..") || path113.isAbsolute(relativePath)) {
94431
94551
  return false;
@@ -94599,7 +94719,7 @@ var suggestPatch = createSwarmTool({
94599
94719
  message: "changes cannot be empty"
94600
94720
  }, null, 2);
94601
94721
  }
94602
- if (!fs87.existsSync(directory)) {
94722
+ if (!fs86.existsSync(directory)) {
94603
94723
  return JSON.stringify({
94604
94724
  success: false,
94605
94725
  error: true,
@@ -94636,7 +94756,7 @@ var suggestPatch = createSwarmTool({
94636
94756
  continue;
94637
94757
  }
94638
94758
  const fullPath = path113.resolve(directory, change.file);
94639
- if (!fs87.existsSync(fullPath)) {
94759
+ if (!fs86.existsSync(fullPath)) {
94640
94760
  errors5.push({
94641
94761
  success: false,
94642
94762
  error: true,
@@ -94650,7 +94770,7 @@ var suggestPatch = createSwarmTool({
94650
94770
  }
94651
94771
  let content;
94652
94772
  try {
94653
- content = fs87.readFileSync(fullPath, "utf-8");
94773
+ content = fs86.readFileSync(fullPath, "utf-8");
94654
94774
  } catch (err3) {
94655
94775
  errors5.push({
94656
94776
  success: false,
@@ -94897,7 +95017,7 @@ var generate_mutants = createSwarmTool({
94897
95017
  // src/tools/lint-spec.ts
94898
95018
  init_spec_schema();
94899
95019
  init_create_tool();
94900
- import * as fs88 from "node:fs";
95020
+ import * as fs87 from "node:fs";
94901
95021
  import * as path114 from "node:path";
94902
95022
  var SPEC_FILE_NAME = "spec.md";
94903
95023
  var SWARM_DIR2 = ".swarm";
@@ -94952,7 +95072,7 @@ var lint_spec = createSwarmTool({
94952
95072
  const errors5 = [];
94953
95073
  const warnings = [];
94954
95074
  const specPath = path114.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
94955
- if (!fs88.existsSync(specPath)) {
95075
+ if (!fs87.existsSync(specPath)) {
94956
95076
  const result2 = {
94957
95077
  valid: false,
94958
95078
  specMtime: null,
@@ -94971,12 +95091,12 @@ var lint_spec = createSwarmTool({
94971
95091
  }
94972
95092
  let specMtime = null;
94973
95093
  try {
94974
- const stats = fs88.statSync(specPath);
95094
+ const stats = fs87.statSync(specPath);
94975
95095
  specMtime = stats.mtime.toISOString();
94976
95096
  } catch {}
94977
95097
  let content;
94978
95098
  try {
94979
- content = fs88.readFileSync(specPath, "utf-8");
95099
+ content = fs87.readFileSync(specPath, "utf-8");
94980
95100
  } catch (e) {
94981
95101
  const result2 = {
94982
95102
  valid: false,
@@ -95021,12 +95141,12 @@ var lint_spec = createSwarmTool({
95021
95141
  });
95022
95142
  // src/tools/mutation-test.ts
95023
95143
  init_zod();
95024
- import * as fs89 from "node:fs";
95144
+ import * as fs88 from "node:fs";
95025
95145
  import * as path116 from "node:path";
95026
95146
 
95027
95147
  // src/mutation/engine.ts
95028
95148
  import { spawnSync as spawnSync3 } from "node:child_process";
95029
- import { unlinkSync as unlinkSync14, writeFileSync as writeFileSync22 } from "node:fs";
95149
+ import { unlinkSync as unlinkSync15, writeFileSync as writeFileSync23 } from "node:fs";
95030
95150
  import * as path115 from "node:path";
95031
95151
 
95032
95152
  // src/mutation/equivalence.ts
@@ -95169,7 +95289,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
95169
95289
  const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
95170
95290
  patchFile = path115.join(workingDir, `.mutation_patch_${safeId2}.diff`);
95171
95291
  try {
95172
- writeFileSync22(patchFile, patch.patch);
95292
+ writeFileSync23(patchFile, patch.patch);
95173
95293
  } catch (writeErr) {
95174
95294
  error93 = `Failed to write patch file: ${writeErr}`;
95175
95295
  outcome = "error";
@@ -95265,7 +95385,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
95265
95385
  revertError = new Error(`Failed to revert mutation ${patch.id}: ${revertErr}. Working tree may be dirty.`);
95266
95386
  }
95267
95387
  try {
95268
- unlinkSync14(patchFile);
95388
+ unlinkSync15(patchFile);
95269
95389
  } catch (_unlinkErr) {}
95270
95390
  }
95271
95391
  }
@@ -95567,7 +95687,7 @@ var mutation_test = createSwarmTool({
95567
95687
  for (const filePath of uniquePaths) {
95568
95688
  try {
95569
95689
  const resolvedPath = path116.resolve(cwd, filePath);
95570
- sourceFiles.set(filePath, fs89.readFileSync(resolvedPath, "utf-8"));
95690
+ sourceFiles.set(filePath, fs88.readFileSync(resolvedPath, "utf-8"));
95571
95691
  } catch {}
95572
95692
  }
95573
95693
  const report = await executeMutationSuite(typedArgs.patches, typedArgs.test_command, typedArgs.files, cwd, undefined, undefined, sourceFiles.size > 0 ? sourceFiles : undefined);
@@ -95585,7 +95705,7 @@ var mutation_test = createSwarmTool({
95585
95705
  init_zod();
95586
95706
  init_manager2();
95587
95707
  init_detector();
95588
- import * as fs90 from "node:fs";
95708
+ import * as fs89 from "node:fs";
95589
95709
  import * as path117 from "node:path";
95590
95710
  init_create_tool();
95591
95711
  var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
@@ -95695,7 +95815,7 @@ async function syntaxCheck(input, directory, config3) {
95695
95815
  }
95696
95816
  let content;
95697
95817
  try {
95698
- content = fs90.readFileSync(fullPath, "utf8");
95818
+ content = fs89.readFileSync(fullPath, "utf8");
95699
95819
  } catch {
95700
95820
  result.skipped_reason = "file_read_error";
95701
95821
  skippedCount++;
@@ -95806,7 +95926,7 @@ init_zod();
95806
95926
  init_utils();
95807
95927
  init_create_tool();
95808
95928
  init_path_security();
95809
- import * as fs91 from "node:fs";
95929
+ import * as fs90 from "node:fs";
95810
95930
  import * as path118 from "node:path";
95811
95931
  var MAX_TEXT_LENGTH = 200;
95812
95932
  var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
@@ -95897,7 +96017,7 @@ function isSupportedExtension(filePath) {
95897
96017
  function findSourceFiles3(dir, files = []) {
95898
96018
  let entries;
95899
96019
  try {
95900
- entries = fs91.readdirSync(dir);
96020
+ entries = fs90.readdirSync(dir);
95901
96021
  } catch {
95902
96022
  return files;
95903
96023
  }
@@ -95909,7 +96029,7 @@ function findSourceFiles3(dir, files = []) {
95909
96029
  const fullPath = path118.join(dir, entry);
95910
96030
  let stat7;
95911
96031
  try {
95912
- stat7 = fs91.statSync(fullPath);
96032
+ stat7 = fs90.statSync(fullPath);
95913
96033
  } catch {
95914
96034
  continue;
95915
96035
  }
@@ -96002,7 +96122,7 @@ var todo_extract = createSwarmTool({
96002
96122
  return JSON.stringify(errorResult, null, 2);
96003
96123
  }
96004
96124
  const scanPath = resolvedPath;
96005
- if (!fs91.existsSync(scanPath)) {
96125
+ if (!fs90.existsSync(scanPath)) {
96006
96126
  const errorResult = {
96007
96127
  error: `path not found: ${pathsInput}`,
96008
96128
  total: 0,
@@ -96012,7 +96132,7 @@ var todo_extract = createSwarmTool({
96012
96132
  return JSON.stringify(errorResult, null, 2);
96013
96133
  }
96014
96134
  const filesToScan = [];
96015
- const stat7 = fs91.statSync(scanPath);
96135
+ const stat7 = fs90.statSync(scanPath);
96016
96136
  if (stat7.isFile()) {
96017
96137
  if (isSupportedExtension(scanPath)) {
96018
96138
  filesToScan.push(scanPath);
@@ -96031,11 +96151,11 @@ var todo_extract = createSwarmTool({
96031
96151
  const allEntries = [];
96032
96152
  for (const filePath of filesToScan) {
96033
96153
  try {
96034
- const fileStat = fs91.statSync(filePath);
96154
+ const fileStat = fs90.statSync(filePath);
96035
96155
  if (fileStat.size > MAX_FILE_SIZE_BYTES11) {
96036
96156
  continue;
96037
96157
  }
96038
- const content = fs91.readFileSync(filePath, "utf-8");
96158
+ const content = fs90.readFileSync(filePath, "utf-8");
96039
96159
  const entries = parseTodoComments(content, filePath, tagsSet);
96040
96160
  allEntries.push(...entries);
96041
96161
  } catch {}
@@ -96066,17 +96186,17 @@ init_loader();
96066
96186
  init_schema();
96067
96187
  init_qa_gate_profile();
96068
96188
  init_gate_evidence();
96069
- import * as fs94 from "node:fs";
96189
+ import * as fs93 from "node:fs";
96070
96190
  import * as path121 from "node:path";
96071
96191
 
96072
96192
  // src/hooks/diff-scope.ts
96073
96193
  init_bun_compat();
96074
- import * as fs93 from "node:fs";
96194
+ import * as fs92 from "node:fs";
96075
96195
  import * as path120 from "node:path";
96076
96196
 
96077
96197
  // src/utils/gitignore-warning.ts
96078
96198
  init_bun_compat();
96079
- import * as fs92 from "node:fs";
96199
+ import * as fs91 from "node:fs";
96080
96200
  import * as path119 from "node:path";
96081
96201
  var _internals36 = { bunSpawn };
96082
96202
  var _swarmGitExcludedChecked = false;
@@ -96154,13 +96274,13 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
96154
96274
  const excludePath = path119.isAbsolute(excludeRelPath) ? excludeRelPath : path119.join(directory, excludeRelPath);
96155
96275
  if (checkIgnoreExitCode !== 0) {
96156
96276
  try {
96157
- fs92.mkdirSync(path119.dirname(excludePath), { recursive: true });
96277
+ fs91.mkdirSync(path119.dirname(excludePath), { recursive: true });
96158
96278
  let existing = "";
96159
96279
  try {
96160
- existing = fs92.readFileSync(excludePath, "utf8");
96280
+ existing = fs91.readFileSync(excludePath, "utf8");
96161
96281
  } catch {}
96162
96282
  if (!fileCoversSwarm(existing)) {
96163
- fs92.appendFileSync(excludePath, `
96283
+ fs91.appendFileSync(excludePath, `
96164
96284
  # opencode-swarm local runtime state
96165
96285
  .swarm/
96166
96286
  `, "utf8");
@@ -96199,9 +96319,9 @@ var _internals37 = { bunSpawn };
96199
96319
  function getDeclaredScope(taskId, directory) {
96200
96320
  try {
96201
96321
  const planPath = path120.join(directory, ".swarm", "plan.json");
96202
- if (!fs93.existsSync(planPath))
96322
+ if (!fs92.existsSync(planPath))
96203
96323
  return null;
96204
- const raw = fs93.readFileSync(planPath, "utf-8");
96324
+ const raw = fs92.readFileSync(planPath, "utf-8");
96205
96325
  const plan = JSON.parse(raw);
96206
96326
  for (const phase of plan.phases ?? []) {
96207
96327
  for (const task of phase.tasks ?? []) {
@@ -96350,7 +96470,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
96350
96470
  const resolvedDir2 = workingDirectory;
96351
96471
  try {
96352
96472
  const planPath = path121.join(resolvedDir2, ".swarm", "plan.json");
96353
- const planRaw = fs94.readFileSync(planPath, "utf-8");
96473
+ const planRaw = fs93.readFileSync(planPath, "utf-8");
96354
96474
  const plan = JSON.parse(planRaw);
96355
96475
  for (const planPhase of plan.phases ?? []) {
96356
96476
  for (const task of planPhase.tasks ?? []) {
@@ -96417,7 +96537,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
96417
96537
  try {
96418
96538
  const resolvedDir2 = workingDirectory;
96419
96539
  const planPath = path121.join(resolvedDir2, ".swarm", "plan.json");
96420
- const planRaw = fs94.readFileSync(planPath, "utf-8");
96540
+ const planRaw = fs93.readFileSync(planPath, "utf-8");
96421
96541
  const plan = JSON.parse(planRaw);
96422
96542
  for (const planPhase of plan.phases ?? []) {
96423
96543
  for (const task of planPhase.tasks ?? []) {
@@ -96614,9 +96734,9 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
96614
96734
  }
96615
96735
  const resolvedDir = path121.resolve(normalizedDir);
96616
96736
  try {
96617
- const realPath = fs94.realpathSync(resolvedDir);
96737
+ const realPath = fs93.realpathSync(resolvedDir);
96618
96738
  const planPath = path121.join(realPath, ".swarm", "plan.json");
96619
- if (!fs94.existsSync(planPath)) {
96739
+ if (!fs93.existsSync(planPath)) {
96620
96740
  return {
96621
96741
  success: false,
96622
96742
  message: `Invalid working_directory: plan not found in "${realPath}"`,
@@ -96648,21 +96768,21 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
96648
96768
  if (args2.status === "in_progress") {
96649
96769
  try {
96650
96770
  const evidencePath = path121.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
96651
- fs94.mkdirSync(path121.dirname(evidencePath), { recursive: true });
96652
- const fd = fs94.openSync(evidencePath, "wx");
96771
+ fs93.mkdirSync(path121.dirname(evidencePath), { recursive: true });
96772
+ const fd = fs93.openSync(evidencePath, "wx");
96653
96773
  let writeOk = false;
96654
96774
  try {
96655
- fs94.writeSync(fd, JSON.stringify({
96775
+ fs93.writeSync(fd, JSON.stringify({
96656
96776
  taskId: args2.task_id,
96657
96777
  required_gates: ["reviewer", "test_engineer"],
96658
96778
  gates: {}
96659
96779
  }, null, 2));
96660
96780
  writeOk = true;
96661
96781
  } finally {
96662
- fs94.closeSync(fd);
96782
+ fs93.closeSync(fd);
96663
96783
  if (!writeOk) {
96664
96784
  try {
96665
- fs94.unlinkSync(evidencePath);
96785
+ fs93.unlinkSync(evidencePath);
96666
96786
  } catch {}
96667
96787
  }
96668
96788
  }
@@ -96673,7 +96793,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
96673
96793
  let phaseRequiresReviewer = true;
96674
96794
  try {
96675
96795
  const planPath = path121.join(directory, ".swarm", "plan.json");
96676
- const planRaw = fs94.readFileSync(planPath, "utf-8");
96796
+ const planRaw = fs93.readFileSync(planPath, "utf-8");
96677
96797
  const plan = JSON.parse(planRaw);
96678
96798
  const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
96679
96799
  if (taskPhase?.required_agents && !taskPhase.required_agents.includes("reviewer")) {
@@ -96983,7 +97103,7 @@ init_utils2();
96983
97103
  init_ledger();
96984
97104
  init_manager();
96985
97105
  init_create_tool();
96986
- import fs95 from "node:fs";
97106
+ import fs94 from "node:fs";
96987
97107
  import path122 from "node:path";
96988
97108
  function normalizeVerdict(verdict) {
96989
97109
  switch (verdict) {
@@ -97045,10 +97165,10 @@ async function executeWriteDriftEvidence(args2, directory) {
97045
97165
  }
97046
97166
  const evidenceDir = path122.dirname(validatedPath);
97047
97167
  try {
97048
- await fs95.promises.mkdir(evidenceDir, { recursive: true });
97168
+ await fs94.promises.mkdir(evidenceDir, { recursive: true });
97049
97169
  const tempPath = path122.join(evidenceDir, `.${filename}.tmp`);
97050
- await fs95.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
97051
- await fs95.promises.rename(tempPath, validatedPath);
97170
+ await fs94.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
97171
+ await fs94.promises.rename(tempPath, validatedPath);
97052
97172
  let snapshotInfo;
97053
97173
  let snapshotError;
97054
97174
  let qaProfileLocked;
@@ -97143,7 +97263,7 @@ init_zod();
97143
97263
  init_utils2();
97144
97264
  init_manager();
97145
97265
  init_create_tool();
97146
- import fs96 from "node:fs";
97266
+ import fs95 from "node:fs";
97147
97267
  import path123 from "node:path";
97148
97268
  function normalizeVerdict2(verdict) {
97149
97269
  switch (verdict) {
@@ -97208,10 +97328,10 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
97208
97328
  }
97209
97329
  const evidenceDir = path123.dirname(validatedPath);
97210
97330
  try {
97211
- await fs96.promises.mkdir(evidenceDir, { recursive: true });
97331
+ await fs95.promises.mkdir(evidenceDir, { recursive: true });
97212
97332
  const tempPath = path123.join(evidenceDir, `.${filename}.tmp`);
97213
- await fs96.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
97214
- await fs96.promises.rename(tempPath, validatedPath);
97333
+ await fs95.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
97334
+ await fs95.promises.rename(tempPath, validatedPath);
97215
97335
  return JSON.stringify({
97216
97336
  success: true,
97217
97337
  phase,
@@ -97255,7 +97375,7 @@ var write_final_council_evidence = createSwarmTool({
97255
97375
  init_zod();
97256
97376
  init_utils2();
97257
97377
  init_create_tool();
97258
- import fs97 from "node:fs";
97378
+ import fs96 from "node:fs";
97259
97379
  import path124 from "node:path";
97260
97380
  function normalizeVerdict3(verdict) {
97261
97381
  switch (verdict) {
@@ -97317,10 +97437,10 @@ async function executeWriteHallucinationEvidence(args2, directory) {
97317
97437
  }
97318
97438
  const evidenceDir = path124.dirname(validatedPath);
97319
97439
  try {
97320
- await fs97.promises.mkdir(evidenceDir, { recursive: true });
97440
+ await fs96.promises.mkdir(evidenceDir, { recursive: true });
97321
97441
  const tempPath = path124.join(evidenceDir, `.${filename}.tmp`);
97322
- await fs97.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
97323
- await fs97.promises.rename(tempPath, validatedPath);
97442
+ await fs96.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
97443
+ await fs96.promises.rename(tempPath, validatedPath);
97324
97444
  return JSON.stringify({
97325
97445
  success: true,
97326
97446
  phase,
@@ -97366,7 +97486,7 @@ var write_hallucination_evidence = createSwarmTool({
97366
97486
  init_zod();
97367
97487
  init_utils2();
97368
97488
  init_create_tool();
97369
- import fs98 from "node:fs";
97489
+ import fs97 from "node:fs";
97370
97490
  import path125 from "node:path";
97371
97491
  function normalizeVerdict4(verdict) {
97372
97492
  switch (verdict) {
@@ -97454,10 +97574,10 @@ async function executeWriteMutationEvidence(args2, directory) {
97454
97574
  }
97455
97575
  const evidenceDir = path125.dirname(validatedPath);
97456
97576
  try {
97457
- await fs98.promises.mkdir(evidenceDir, { recursive: true });
97577
+ await fs97.promises.mkdir(evidenceDir, { recursive: true });
97458
97578
  const tempPath = path125.join(evidenceDir, `.${filename}.tmp`);
97459
- await fs98.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
97460
- await fs98.promises.rename(tempPath, validatedPath);
97579
+ await fs97.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
97580
+ await fs97.promises.rename(tempPath, validatedPath);
97461
97581
  return JSON.stringify({
97462
97582
  success: true,
97463
97583
  phase,
@@ -97943,15 +98063,19 @@ async function initializeOpenCodeSwarm(ctx) {
97943
98063
  ...opencodeConfig.command || {},
97944
98064
  swarm: {
97945
98065
  template: "/swarm $ARGUMENTS",
97946
- description: "Swarm management commands: /swarm [status|plan|agents|history|config|evidence|handoff|archive|diagnose|diagnosis|preflight|sync-plan|benchmark|export|reset|rollback|retrieve|clarify|analyze|specify|brainstorm|council|pr-review|issue|qa-gates|dark-matter|knowledge|curate|turbo|full-auto|write-retro|reset-session|simulate|promote|checkpoint|acknowledge-spec-drift|doctor-tools|close]"
98066
+ description: "Swarm management commands: /swarm [status|show-plan|plan|agents|history|config|help|evidence|handoff|archive|diagnose|diagnosis|preflight|sync-plan|benchmark|export|reset|rollback|retrieve|clarify|analyze|specify|brainstorm|council|pr-review|issue|qa-gates|dark-matter|knowledge|curate|turbo|full-auto|write-retro|reset-session|simulate|promote|checkpoint|acknowledge-spec-drift|doctor tools|finalize|close]"
97947
98067
  },
97948
98068
  "swarm-status": {
97949
98069
  template: "/swarm status",
97950
98070
  description: "Use /swarm status to show current swarm status and active phase"
97951
98071
  },
98072
+ "swarm-show-plan": {
98073
+ template: "/swarm show-plan $ARGUMENTS",
98074
+ description: "Use /swarm show-plan to view or filter the current execution plan"
98075
+ },
97952
98076
  "swarm-plan": {
97953
98077
  template: "/swarm plan $ARGUMENTS",
97954
- description: "Use /swarm plan to view or filter the current execution plan"
98078
+ description: "Deprecated alias for /swarm show-plan"
97955
98079
  },
97956
98080
  "swarm-agents": {
97957
98081
  template: "/swarm agents",
@@ -98031,7 +98155,7 @@ async function initializeOpenCodeSwarm(ctx) {
98031
98155
  },
98032
98156
  "swarm-council": {
98033
98157
  template: "/swarm council $ARGUMENTS",
98034
- description: "Use /swarm council <question> to convene a multi-model General Council deliberation (generalist / skeptic / domain expert) [--spec-review]"
98158
+ description: "Use /swarm council <question> to convene a multi-model General Council deliberation (generalist / skeptic / domain expert) [--preset <name>] [--spec-review]"
98035
98159
  },
98036
98160
  "swarm-pr-review": {
98037
98161
  template: "/swarm pr-review $ARGUMENTS",
@@ -98093,9 +98217,13 @@ async function initializeOpenCodeSwarm(ctx) {
98093
98217
  template: "/swarm evidence summary",
98094
98218
  description: "Use /swarm evidence summary to generate evidence summaries"
98095
98219
  },
98220
+ "swarm-finalize": {
98221
+ template: "/swarm finalize",
98222
+ description: "Use /swarm finalize to archive the swarm project and close active state"
98223
+ },
98096
98224
  "swarm-close": {
98097
98225
  template: "/swarm close",
98098
- description: "Use /swarm close to close the swarm project and archive state"
98226
+ description: "Deprecated alias for /swarm finalize"
98099
98227
  },
98100
98228
  "swarm-acknowledge-spec-drift": {
98101
98229
  template: "/swarm acknowledge-spec-drift",