opencode-swarm 6.45.1 → 6.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -16987,13 +16987,13 @@ __export(exports_config_doctor, {
16987
16987
  import * as crypto3 from "crypto";
16988
16988
  import * as fs7 from "fs";
16989
16989
  import * as os4 from "os";
16990
- import * as path15 from "path";
16990
+ import * as path16 from "path";
16991
16991
  function getUserConfigDir3() {
16992
- return process.env.XDG_CONFIG_HOME || path15.join(os4.homedir(), ".config");
16992
+ return process.env.XDG_CONFIG_HOME || path16.join(os4.homedir(), ".config");
16993
16993
  }
16994
16994
  function getConfigPaths(directory) {
16995
- const userConfigPath = path15.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
16996
- const projectConfigPath = path15.join(directory, ".opencode", "opencode-swarm.json");
16995
+ const userConfigPath = path16.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
16996
+ const projectConfigPath = path16.join(directory, ".opencode", "opencode-swarm.json");
16997
16997
  return { userConfigPath, projectConfigPath };
16998
16998
  }
16999
16999
  function computeHash(content) {
@@ -17018,9 +17018,9 @@ function isValidConfigPath(configPath, directory) {
17018
17018
  const normalizedUser = userConfigPath.replace(/\\/g, "/");
17019
17019
  const normalizedProject = projectConfigPath.replace(/\\/g, "/");
17020
17020
  try {
17021
- const resolvedConfig = path15.resolve(configPath);
17022
- const resolvedUser = path15.resolve(normalizedUser);
17023
- const resolvedProject = path15.resolve(normalizedProject);
17021
+ const resolvedConfig = path16.resolve(configPath);
17022
+ const resolvedUser = path16.resolve(normalizedUser);
17023
+ const resolvedProject = path16.resolve(normalizedProject);
17024
17024
  return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
17025
17025
  } catch {
17026
17026
  return false;
@@ -17060,12 +17060,12 @@ function createConfigBackup(directory) {
17060
17060
  };
17061
17061
  }
17062
17062
  function writeBackupArtifact(directory, backup) {
17063
- const swarmDir = path15.join(directory, ".swarm");
17063
+ const swarmDir = path16.join(directory, ".swarm");
17064
17064
  if (!fs7.existsSync(swarmDir)) {
17065
17065
  fs7.mkdirSync(swarmDir, { recursive: true });
17066
17066
  }
17067
17067
  const backupFilename = `config-backup-${backup.createdAt}.json`;
17068
- const backupPath = path15.join(swarmDir, backupFilename);
17068
+ const backupPath = path16.join(swarmDir, backupFilename);
17069
17069
  const artifact = {
17070
17070
  createdAt: backup.createdAt,
17071
17071
  configPath: backup.configPath,
@@ -17095,7 +17095,7 @@ function restoreFromBackup(backupPath, directory) {
17095
17095
  return null;
17096
17096
  }
17097
17097
  const targetPath = artifact.configPath;
17098
- const targetDir = path15.dirname(targetPath);
17098
+ const targetDir = path16.dirname(targetPath);
17099
17099
  if (!fs7.existsSync(targetDir)) {
17100
17100
  fs7.mkdirSync(targetDir, { recursive: true });
17101
17101
  }
@@ -17126,9 +17126,9 @@ function readConfigFromFile(directory) {
17126
17126
  return null;
17127
17127
  }
17128
17128
  }
17129
- function validateConfigKey(path16, value, _config) {
17129
+ function validateConfigKey(path17, value, _config) {
17130
17130
  const findings = [];
17131
- switch (path16) {
17131
+ switch (path17) {
17132
17132
  case "agents": {
17133
17133
  if (value !== undefined) {
17134
17134
  findings.push({
@@ -17375,27 +17375,27 @@ function validateConfigKey(path16, value, _config) {
17375
17375
  }
17376
17376
  return findings;
17377
17377
  }
17378
- function walkConfigAndValidate(obj, path16, config3, findings) {
17378
+ function walkConfigAndValidate(obj, path17, config3, findings) {
17379
17379
  if (obj === null || obj === undefined) {
17380
17380
  return;
17381
17381
  }
17382
- if (path16 && typeof obj === "object" && !Array.isArray(obj)) {
17383
- const keyFindings = validateConfigKey(path16, obj, config3);
17382
+ if (path17 && typeof obj === "object" && !Array.isArray(obj)) {
17383
+ const keyFindings = validateConfigKey(path17, obj, config3);
17384
17384
  findings.push(...keyFindings);
17385
17385
  }
17386
17386
  if (typeof obj !== "object") {
17387
- const keyFindings = validateConfigKey(path16, obj, config3);
17387
+ const keyFindings = validateConfigKey(path17, obj, config3);
17388
17388
  findings.push(...keyFindings);
17389
17389
  return;
17390
17390
  }
17391
17391
  if (Array.isArray(obj)) {
17392
17392
  obj.forEach((item, index) => {
17393
- walkConfigAndValidate(item, `${path16}[${index}]`, config3, findings);
17393
+ walkConfigAndValidate(item, `${path17}[${index}]`, config3, findings);
17394
17394
  });
17395
17395
  return;
17396
17396
  }
17397
17397
  for (const [key, value] of Object.entries(obj)) {
17398
- const newPath = path16 ? `${path16}.${key}` : key;
17398
+ const newPath = path17 ? `${path17}.${key}` : key;
17399
17399
  walkConfigAndValidate(value, newPath, config3, findings);
17400
17400
  }
17401
17401
  }
@@ -17515,7 +17515,7 @@ function applySafeAutoFixes(directory, result) {
17515
17515
  }
17516
17516
  }
17517
17517
  if (appliedFixes.length > 0) {
17518
- const configDir = path15.dirname(configPath);
17518
+ const configDir = path16.dirname(configPath);
17519
17519
  if (!fs7.existsSync(configDir)) {
17520
17520
  fs7.mkdirSync(configDir, { recursive: true });
17521
17521
  }
@@ -17525,12 +17525,12 @@ function applySafeAutoFixes(directory, result) {
17525
17525
  return { appliedFixes, updatedConfigPath };
17526
17526
  }
17527
17527
  function writeDoctorArtifact(directory, result) {
17528
- const swarmDir = path15.join(directory, ".swarm");
17528
+ const swarmDir = path16.join(directory, ".swarm");
17529
17529
  if (!fs7.existsSync(swarmDir)) {
17530
17530
  fs7.mkdirSync(swarmDir, { recursive: true });
17531
17531
  }
17532
17532
  const artifactFilename = "config-doctor.json";
17533
- const artifactPath = path15.join(swarmDir, artifactFilename);
17533
+ const artifactPath = path16.join(swarmDir, artifactFilename);
17534
17534
  const guiOutput = {
17535
17535
  timestamp: result.timestamp,
17536
17536
  summary: result.summary,
@@ -17893,7 +17893,7 @@ var init_evidence_summary_service = __esm(() => {
17893
17893
  // src/cli/index.ts
17894
17894
  import * as fs18 from "fs";
17895
17895
  import * as os6 from "os";
17896
- import * as path27 from "path";
17896
+ import * as path28 from "path";
17897
17897
 
17898
17898
  // src/commands/agents.ts
17899
17899
  function handleAgentsCommand(agents, guardrails) {
@@ -18649,6 +18649,17 @@ var CompactionConfigSchema = exports_external.object({
18649
18649
  emergencyThreshold: exports_external.number().min(1).max(99).default(80),
18650
18650
  preserveLastNTurns: exports_external.number().int().min(1).default(5)
18651
18651
  });
18652
+ var AgentAuthorityRuleSchema = exports_external.object({
18653
+ readOnly: exports_external.boolean().optional(),
18654
+ blockedExact: exports_external.array(exports_external.string()).optional(),
18655
+ blockedPrefix: exports_external.array(exports_external.string()).optional(),
18656
+ allowedPrefix: exports_external.array(exports_external.string()).optional(),
18657
+ blockedZones: exports_external.array(exports_external.enum(["production", "test", "config", "generated", "docs", "build"])).optional()
18658
+ });
18659
+ var AuthorityConfigSchema = exports_external.object({
18660
+ enabled: exports_external.boolean().default(true),
18661
+ rules: exports_external.record(exports_external.string(), AgentAuthorityRuleSchema).default({})
18662
+ });
18652
18663
  var PluginConfigSchema = exports_external.object({
18653
18664
  agents: exports_external.record(exports_external.string(), AgentOverrideConfigSchema).optional(),
18654
18665
  swarms: exports_external.record(exports_external.string(), SwarmConfigSchema).optional(),
@@ -18665,6 +18676,7 @@ var PluginConfigSchema = exports_external.object({
18665
18676
  watchdog: WatchdogConfigSchema.optional(),
18666
18677
  self_review: SelfReviewConfigSchema.optional(),
18667
18678
  tool_filter: ToolFilterConfigSchema.optional(),
18679
+ authority: AuthorityConfigSchema.optional(),
18668
18680
  plan_cursor: PlanCursorConfigSchema.optional(),
18669
18681
  evidence: EvidenceConfigSchema.optional(),
18670
18682
  summaries: SummaryConfigSchema.optional(),
@@ -31993,7 +32005,9 @@ async function handleClarifyCommand(_directory, args) {
31993
32005
  }
31994
32006
 
31995
32007
  // src/commands/close.ts
32008
+ import { execFileSync } from "child_process";
31996
32009
  import { promises as fs6 } from "fs";
32010
+ import path11 from "path";
31997
32011
  init_manager();
31998
32012
 
31999
32013
  // src/hooks/knowledge-store.ts
@@ -33105,87 +33119,183 @@ var write_retro = createSwarmTool({
33105
33119
  });
33106
33120
 
33107
33121
  // src/commands/close.ts
33108
- async function handleCloseCommand(directory, _args) {
33122
+ async function handleCloseCommand(directory, args) {
33109
33123
  const planPath = validateSwarmPath(directory, "plan.json");
33110
- let planData;
33124
+ let planExists = false;
33125
+ let planData = {
33126
+ title: path11.basename(directory) || "Ad-hoc session",
33127
+ phases: []
33128
+ };
33111
33129
  try {
33112
33130
  const content = await fs6.readFile(planPath, "utf-8");
33113
33131
  planData = JSON.parse(content);
33132
+ planExists = true;
33114
33133
  } catch (error93) {
33115
- return `\u274C Failed to read plan.json: ${error93 instanceof Error ? error93.message : String(error93)}`;
33134
+ if (error93?.code !== "ENOENT") {
33135
+ return `\u274C Failed to read plan.json: ${error93 instanceof Error ? error93.message : String(error93)}`;
33136
+ }
33137
+ const swarmDirExists = await fs6.access(path11.join(directory, ".swarm")).then(() => true).catch(() => false);
33138
+ if (!swarmDirExists) {
33139
+ return `\u274C No .swarm/ directory found in ${directory}. Run /swarm close from the project root, or run /swarm plan first.`;
33140
+ }
33116
33141
  }
33117
33142
  const phases = planData.phases ?? [];
33118
33143
  const inProgressPhases = phases.filter((p) => p.status === "in_progress");
33119
- const allDone = phases.every((p) => p.status === "complete" || p.status === "completed" || p.status === "blocked" || p.status === "closed");
33120
- if (allDone) {
33121
- const closedCount = phases.filter((p) => p.status === "closed").length;
33122
- const blockedCount = phases.filter((p) => p.status === "blocked").length;
33123
- const completeCount = phases.filter((p) => p.status === "complete" || p.status === "completed").length;
33124
- return `\u2139\uFE0F Swarm already closed. ${completeCount} phases complete, ${closedCount} phases closed, ${blockedCount} phases blocked. No action taken.`;
33144
+ let planAlreadyDone = false;
33145
+ if (planExists) {
33146
+ planAlreadyDone = phases.length > 0 && phases.every((p) => p.status === "complete" || p.status === "completed" || p.status === "blocked" || p.status === "closed");
33125
33147
  }
33126
33148
  const config3 = KnowledgeConfigSchema.parse({});
33127
33149
  const projectName = planData.title ?? "Unknown Project";
33128
33150
  const closedPhases = [];
33129
33151
  const closedTasks = [];
33130
33152
  const warnings = [];
33131
- for (const phase of inProgressPhases) {
33132
- closedPhases.push(phase.id);
33133
- const retroResult = await executeWriteRetro({
33134
- phase: phase.id,
33135
- summary: "Phase closed via /swarm close",
33136
- task_count: Math.max(1, (phase.tasks ?? []).length),
33137
- task_complexity: "simple",
33138
- total_tool_calls: 0,
33139
- coder_revisions: 0,
33140
- reviewer_rejections: 0,
33141
- test_failures: 0,
33142
- security_findings: 0,
33143
- integration_issues: 0
33144
- }, directory);
33145
- try {
33146
- const parsed = JSON.parse(retroResult);
33147
- if (parsed.success !== true) {
33148
- warnings.push(`Retrospective write failed for phase ${phase.id}`);
33153
+ if (!planAlreadyDone) {
33154
+ for (const phase of inProgressPhases) {
33155
+ closedPhases.push(phase.id);
33156
+ let retroResult;
33157
+ try {
33158
+ retroResult = await executeWriteRetro({
33159
+ phase: phase.id,
33160
+ summary: "Phase closed via /swarm close",
33161
+ task_count: Math.max(1, (phase.tasks ?? []).length),
33162
+ task_complexity: "simple",
33163
+ total_tool_calls: 0,
33164
+ coder_revisions: 0,
33165
+ reviewer_rejections: 0,
33166
+ test_failures: 0,
33167
+ security_findings: 0,
33168
+ integration_issues: 0
33169
+ }, directory);
33170
+ } catch (retroError) {
33171
+ warnings.push(`Retrospective write threw for phase ${phase.id}: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
33172
+ }
33173
+ if (retroResult !== undefined) {
33174
+ try {
33175
+ const parsed = JSON.parse(retroResult);
33176
+ if (parsed.success !== true) {
33177
+ warnings.push(`Retrospective write failed for phase ${phase.id}`);
33178
+ }
33179
+ } catch {}
33149
33180
  }
33150
- } catch {}
33151
- for (const task of phase.tasks ?? []) {
33152
- if (task.status !== "completed" && task.status !== "complete") {
33153
- closedTasks.push(task.id);
33181
+ for (const task of phase.tasks ?? []) {
33182
+ if (task.status !== "completed" && task.status !== "complete") {
33183
+ closedTasks.push(task.id);
33184
+ }
33154
33185
  }
33155
33186
  }
33156
33187
  }
33188
+ const lessonsFilePath = path11.join(directory, ".swarm", "close-lessons.md");
33189
+ let explicitLessons = [];
33157
33190
  try {
33158
- await curateAndStoreSwarm([], projectName, { phase_number: 0 }, directory, config3);
33191
+ const lessonsText = await fs6.readFile(lessonsFilePath, "utf-8");
33192
+ explicitLessons = lessonsText.split(`
33193
+ `).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
33194
+ } catch {}
33195
+ let curationSucceeded = false;
33196
+ try {
33197
+ await curateAndStoreSwarm(explicitLessons, projectName, { phase_number: 0 }, directory, config3);
33198
+ curationSucceeded = true;
33159
33199
  } catch (error93) {
33160
33200
  console.warn("[close-command] curateAndStoreSwarm error:", error93);
33161
33201
  }
33162
- for (const phase of phases) {
33163
- if (phase.status !== "complete" && phase.status !== "completed") {
33164
- phase.status = "closed";
33165
- if (!closedPhases.includes(phase.id)) {
33166
- closedPhases.push(phase.id);
33202
+ if (curationSucceeded && explicitLessons.length > 0) {
33203
+ await fs6.unlink(lessonsFilePath).catch(() => {});
33204
+ }
33205
+ if (planExists && !planAlreadyDone) {
33206
+ for (const phase of phases) {
33207
+ if (phase.status !== "complete" && phase.status !== "completed") {
33208
+ phase.status = "closed";
33209
+ if (!closedPhases.includes(phase.id)) {
33210
+ closedPhases.push(phase.id);
33211
+ }
33167
33212
  }
33168
- }
33169
- for (const task of phase.tasks ?? []) {
33170
- if (task.status !== "completed" && task.status !== "complete") {
33171
- task.status = "closed";
33172
- if (!closedTasks.includes(task.id)) {
33173
- closedTasks.push(task.id);
33213
+ for (const task of phase.tasks ?? []) {
33214
+ if (task.status !== "completed" && task.status !== "complete") {
33215
+ task.status = "closed";
33216
+ if (!closedTasks.includes(task.id)) {
33217
+ closedTasks.push(task.id);
33218
+ }
33174
33219
  }
33175
33220
  }
33176
33221
  }
33222
+ try {
33223
+ await fs6.writeFile(planPath, JSON.stringify(planData, null, 2), "utf-8");
33224
+ } catch (error93) {
33225
+ console.warn("[close-command] Failed to write plan.json:", error93);
33226
+ }
33177
33227
  }
33178
33228
  try {
33179
- await fs6.writeFile(planPath, JSON.stringify(planData, null, 2), "utf-8");
33229
+ await archiveEvidence(directory, 30, 10);
33180
33230
  } catch (error93) {
33181
- console.warn("[close-command] Failed to write plan.json:", error93);
33231
+ console.warn("[close-command] archiveEvidence error:", error93);
33182
33232
  }
33233
+ const swarmDir = path11.join(directory, ".swarm");
33234
+ let configBackupsRemoved = 0;
33183
33235
  try {
33184
- await archiveEvidence(directory, 30, 10);
33236
+ const swarmFiles = await fs6.readdir(swarmDir);
33237
+ const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
33238
+ for (const backup of configBackups) {
33239
+ try {
33240
+ await fs6.unlink(path11.join(swarmDir, backup));
33241
+ configBackupsRemoved++;
33242
+ } catch {}
33243
+ }
33244
+ } catch {}
33245
+ const contextPath = path11.join(directory, ".swarm", "context.md");
33246
+ const contextContent = [
33247
+ "# Context",
33248
+ "",
33249
+ "## Status",
33250
+ `Session closed after: ${projectName}`,
33251
+ `Closed: ${new Date().toISOString()}`,
33252
+ "No active plan. Next session starts fresh.",
33253
+ ""
33254
+ ].join(`
33255
+ `);
33256
+ try {
33257
+ await fs6.writeFile(contextPath, contextContent, "utf-8");
33185
33258
  } catch (error93) {
33186
- console.warn("[close-command] archiveEvidence error:", error93);
33259
+ console.warn("[close-command] Failed to write context.md:", error93);
33260
+ }
33261
+ const pruneBranches = args.includes("--prune-branches");
33262
+ const prunedBranches = [];
33263
+ const pruneErrors = [];
33264
+ if (pruneBranches) {
33265
+ try {
33266
+ const branchOutput = execFileSync("git", ["branch", "-vv"], {
33267
+ cwd: directory,
33268
+ encoding: "utf-8",
33269
+ stdio: ["pipe", "pipe", "pipe"]
33270
+ });
33271
+ const goneBranches = branchOutput.split(`
33272
+ `).filter((line) => line.includes(": gone]")).map((line) => line.trim().replace(/^[*+]\s+/, "").split(/\s+/)[0]).filter(Boolean);
33273
+ for (const branch of goneBranches) {
33274
+ try {
33275
+ execFileSync("git", ["branch", "-d", branch], {
33276
+ cwd: directory,
33277
+ encoding: "utf-8",
33278
+ stdio: ["pipe", "pipe", "pipe"]
33279
+ });
33280
+ prunedBranches.push(branch);
33281
+ } catch {
33282
+ pruneErrors.push(branch);
33283
+ }
33284
+ }
33285
+ } catch {}
33187
33286
  }
33188
33287
  const closeSummaryPath = validateSwarmPath(directory, "close-summary.md");
33288
+ const actionsPerformed = [
33289
+ ...!planAlreadyDone && inProgressPhases.length > 0 ? ["- Wrote retrospectives for in-progress phases"] : [],
33290
+ "- Archived evidence bundles",
33291
+ "- Reset context.md for next session",
33292
+ ...configBackupsRemoved > 0 ? [`- Removed ${configBackupsRemoved} stale config backup file(s)`] : [],
33293
+ ...prunedBranches.length > 0 ? [
33294
+ `- Pruned ${prunedBranches.length} stale local git branch(es): ${prunedBranches.join(", ")}`
33295
+ ] : [],
33296
+ "- Cleared agent sessions and delegation chains",
33297
+ ...planExists && !planAlreadyDone ? ["- Set non-completed phases/tasks to closed status"] : []
33298
+ ];
33189
33299
  const summaryContent = [
33190
33300
  "# Swarm Close Summary",
33191
33301
  "",
@@ -33193,18 +33303,15 @@ async function handleCloseCommand(directory, _args) {
33193
33303
  `**Closed:** ${new Date().toISOString()}`,
33194
33304
  "",
33195
33305
  `## Phases Closed: ${closedPhases.length}`,
33196
- closedPhases.map((id) => `- Phase ${id}`).join(`
33197
- `),
33306
+ !planExists ? "_No plan \u2014 ad-hoc session_" : closedPhases.length > 0 ? closedPhases.map((id) => `- Phase ${id}`).join(`
33307
+ `) : "_No phases to close_",
33198
33308
  "",
33199
33309
  `## Tasks Closed: ${closedTasks.length}`,
33200
33310
  closedTasks.length > 0 ? closedTasks.map((id) => `- ${id}`).join(`
33201
33311
  `) : "_No incomplete tasks_",
33202
33312
  "",
33203
33313
  "## Actions Performed",
33204
- "- Wrote retrospectives for in-progress phases",
33205
- "- Archived evidence bundles",
33206
- "- Cleared agent sessions and delegation chains",
33207
- "- Set non-completed phases/tasks to closed status"
33314
+ ...actionsPerformed
33208
33315
  ].join(`
33209
33316
  `);
33210
33317
  try {
@@ -33220,20 +33327,26 @@ async function handleCloseCommand(directory, _args) {
33220
33327
  await writeCheckpoint(directory).catch(() => {});
33221
33328
  swarmState.agentSessions.clear();
33222
33329
  swarmState.delegationChains.clear();
33330
+ if (pruneErrors.length > 0) {
33331
+ warnings.push(`Could not prune ${pruneErrors.length} branch(es) (unmerged or checked out): ${pruneErrors.join(", ")}`);
33332
+ }
33223
33333
  const warningMsg = warnings.length > 0 ? ` Warnings: ${warnings.join("; ")}.` : "";
33334
+ if (planAlreadyDone) {
33335
+ return `\u2705 Session closed. Plan was already in a terminal state \u2014 cleanup steps applied.${warningMsg}`;
33336
+ }
33224
33337
  return `\u2705 Swarm closed successfully. ${closedPhases.length} phase(s) closed, ${closedTasks.length} incomplete task(s) marked closed.${warningMsg}`;
33225
33338
  }
33226
33339
 
33227
33340
  // src/commands/config.ts
33228
33341
  import * as os3 from "os";
33229
- import * as path11 from "path";
33342
+ import * as path12 from "path";
33230
33343
  function getUserConfigDir2() {
33231
- return process.env.XDG_CONFIG_HOME || path11.join(os3.homedir(), ".config");
33344
+ return process.env.XDG_CONFIG_HOME || path12.join(os3.homedir(), ".config");
33232
33345
  }
33233
33346
  async function handleConfigCommand(directory, _args) {
33234
33347
  const config3 = loadPluginConfig(directory);
33235
- const userConfigPath = path11.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
33236
- const projectConfigPath = path11.join(directory, ".opencode", "opencode-swarm.json");
33348
+ const userConfigPath = path12.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
33349
+ const projectConfigPath = path12.join(directory, ".opencode", "opencode-swarm.json");
33237
33350
  const lines = [
33238
33351
  "## Swarm Configuration",
33239
33352
  "",
@@ -33501,13 +33614,13 @@ function formatCurationSummary(summary) {
33501
33614
  }
33502
33615
 
33503
33616
  // src/commands/dark-matter.ts
33504
- import path13 from "path";
33617
+ import path14 from "path";
33505
33618
 
33506
33619
  // src/tools/co-change-analyzer.ts
33507
33620
  import * as child_process2 from "child_process";
33508
33621
  import { randomUUID } from "crypto";
33509
33622
  import { readdir, readFile as readFile2, stat } from "fs/promises";
33510
- import * as path12 from "path";
33623
+ import * as path13 from "path";
33511
33624
  import { promisify } from "util";
33512
33625
  function getExecFileAsync() {
33513
33626
  return promisify(child_process2.execFile);
@@ -33609,7 +33722,7 @@ async function scanSourceFiles(dir) {
33609
33722
  try {
33610
33723
  const entries = await readdir(dir, { withFileTypes: true });
33611
33724
  for (const entry of entries) {
33612
- const fullPath = path12.join(dir, entry.name);
33725
+ const fullPath = path13.join(dir, entry.name);
33613
33726
  if (entry.isDirectory()) {
33614
33727
  if (skipDirs.has(entry.name)) {
33615
33728
  continue;
@@ -33617,7 +33730,7 @@ async function scanSourceFiles(dir) {
33617
33730
  const subFiles = await scanSourceFiles(fullPath);
33618
33731
  results.push(...subFiles);
33619
33732
  } else if (entry.isFile()) {
33620
- const ext = path12.extname(entry.name);
33733
+ const ext = path13.extname(entry.name);
33621
33734
  if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
33622
33735
  results.push(fullPath);
33623
33736
  }
@@ -33639,8 +33752,8 @@ async function getStaticEdges(directory) {
33639
33752
  continue;
33640
33753
  }
33641
33754
  try {
33642
- const sourceDir = path12.dirname(sourceFile);
33643
- const resolvedPath = path12.resolve(sourceDir, importPath);
33755
+ const sourceDir = path13.dirname(sourceFile);
33756
+ const resolvedPath = path13.resolve(sourceDir, importPath);
33644
33757
  const extensions = [
33645
33758
  "",
33646
33759
  ".ts",
@@ -33665,8 +33778,8 @@ async function getStaticEdges(directory) {
33665
33778
  if (!targetFile) {
33666
33779
  continue;
33667
33780
  }
33668
- const relSource = path12.relative(directory, sourceFile).replace(/\\/g, "/");
33669
- const relTarget = path12.relative(directory, targetFile).replace(/\\/g, "/");
33781
+ const relSource = path13.relative(directory, sourceFile).replace(/\\/g, "/");
33782
+ const relTarget = path13.relative(directory, targetFile).replace(/\\/g, "/");
33670
33783
  const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
33671
33784
  edges.add(key);
33672
33785
  } catch {}
@@ -33678,7 +33791,7 @@ async function getStaticEdges(directory) {
33678
33791
  function isTestImplementationPair(fileA, fileB) {
33679
33792
  const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
33680
33793
  const getBaseName = (filePath) => {
33681
- const base = path12.basename(filePath);
33794
+ const base = path13.basename(filePath);
33682
33795
  for (const pattern of testPatterns) {
33683
33796
  if (base.endsWith(pattern)) {
33684
33797
  return base.slice(0, -pattern.length);
@@ -33688,16 +33801,16 @@ function isTestImplementationPair(fileA, fileB) {
33688
33801
  };
33689
33802
  const baseA = getBaseName(fileA);
33690
33803
  const baseB = getBaseName(fileB);
33691
- return baseA === baseB && baseA !== path12.basename(fileA) && baseA !== path12.basename(fileB);
33804
+ return baseA === baseB && baseA !== path13.basename(fileA) && baseA !== path13.basename(fileB);
33692
33805
  }
33693
33806
  function hasSharedPrefix(fileA, fileB) {
33694
- const dirA = path12.dirname(fileA);
33695
- const dirB = path12.dirname(fileB);
33807
+ const dirA = path13.dirname(fileA);
33808
+ const dirB = path13.dirname(fileB);
33696
33809
  if (dirA !== dirB) {
33697
33810
  return false;
33698
33811
  }
33699
- const baseA = path12.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
33700
- const baseB = path12.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
33812
+ const baseA = path13.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
33813
+ const baseB = path13.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
33701
33814
  if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
33702
33815
  return true;
33703
33816
  }
@@ -33751,8 +33864,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
33751
33864
  const entries = [];
33752
33865
  const now = new Date().toISOString();
33753
33866
  for (const pair of pairs.slice(0, 10)) {
33754
- const baseA = path12.basename(pair.fileA);
33755
- const baseB = path12.basename(pair.fileB);
33867
+ const baseA = path13.basename(pair.fileA);
33868
+ const baseB = path13.basename(pair.fileB);
33756
33869
  let lesson = `Files ${pair.fileA} and ${pair.fileB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
33757
33870
  if (lesson.length > 280) {
33758
33871
  lesson = `Files ${baseA} and ${baseB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
@@ -33862,7 +33975,7 @@ async function handleDarkMatterCommand(directory, args) {
33862
33975
  const output = formatDarkMatterOutput(pairs);
33863
33976
  if (pairs.length > 0) {
33864
33977
  try {
33865
- const projectName = path13.basename(path13.resolve(directory));
33978
+ const projectName = path14.basename(path14.resolve(directory));
33866
33979
  const entries = darkMatterToKnowledgeEntries(pairs, projectName);
33867
33980
  if (entries.length > 0) {
33868
33981
  const knowledgePath = resolveSwarmKnowledgePath(directory);
@@ -33884,7 +33997,7 @@ async function handleDarkMatterCommand(directory, args) {
33884
33997
  // src/services/diagnose-service.ts
33885
33998
  import * as child_process3 from "child_process";
33886
33999
  import { existsSync as existsSync5, readdirSync as readdirSync2, readFileSync as readFileSync5, statSync as statSync3 } from "fs";
33887
- import path14 from "path";
34000
+ import path15 from "path";
33888
34001
  import { fileURLToPath } from "url";
33889
34002
  init_manager();
33890
34003
  init_utils2();
@@ -34184,7 +34297,7 @@ async function checkSpecStaleness(directory, plan) {
34184
34297
  };
34185
34298
  }
34186
34299
  async function checkConfigParseability(directory) {
34187
- const configPath = path14.join(directory, ".opencode/opencode-swarm.json");
34300
+ const configPath = path15.join(directory, ".opencode/opencode-swarm.json");
34188
34301
  if (!existsSync5(configPath)) {
34189
34302
  return {
34190
34303
  name: "Config Parseability",
@@ -34231,15 +34344,15 @@ async function checkGrammarWasmFiles() {
34231
34344
  "tree-sitter-ini.wasm",
34232
34345
  "tree-sitter-regex.wasm"
34233
34346
  ];
34234
- const thisDir = path14.dirname(fileURLToPath(import.meta.url));
34347
+ const thisDir = path15.dirname(fileURLToPath(import.meta.url));
34235
34348
  const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/services");
34236
- const grammarDir = isSource ? path14.join(thisDir, "..", "lang", "grammars") : path14.join(thisDir, "lang", "grammars");
34349
+ const grammarDir = isSource ? path15.join(thisDir, "..", "lang", "grammars") : path15.join(thisDir, "lang", "grammars");
34237
34350
  const missing = [];
34238
- if (!existsSync5(path14.join(grammarDir, "tree-sitter.wasm"))) {
34351
+ if (!existsSync5(path15.join(grammarDir, "tree-sitter.wasm"))) {
34239
34352
  missing.push("tree-sitter.wasm (core runtime)");
34240
34353
  }
34241
34354
  for (const file3 of grammarFiles) {
34242
- if (!existsSync5(path14.join(grammarDir, file3))) {
34355
+ if (!existsSync5(path15.join(grammarDir, file3))) {
34243
34356
  missing.push(file3);
34244
34357
  }
34245
34358
  }
@@ -34257,7 +34370,7 @@ async function checkGrammarWasmFiles() {
34257
34370
  };
34258
34371
  }
34259
34372
  async function checkCheckpointManifest(directory) {
34260
- const manifestPath = path14.join(directory, ".swarm/checkpoints.json");
34373
+ const manifestPath = path15.join(directory, ".swarm/checkpoints.json");
34261
34374
  if (!existsSync5(manifestPath)) {
34262
34375
  return {
34263
34376
  name: "Checkpoint Manifest",
@@ -34309,7 +34422,7 @@ async function checkCheckpointManifest(directory) {
34309
34422
  }
34310
34423
  }
34311
34424
  async function checkEventStreamIntegrity(directory) {
34312
- const eventsPath = path14.join(directory, ".swarm/events.jsonl");
34425
+ const eventsPath = path15.join(directory, ".swarm/events.jsonl");
34313
34426
  if (!existsSync5(eventsPath)) {
34314
34427
  return {
34315
34428
  name: "Event Stream",
@@ -34350,7 +34463,7 @@ async function checkEventStreamIntegrity(directory) {
34350
34463
  }
34351
34464
  }
34352
34465
  async function checkSteeringDirectives(directory) {
34353
- const eventsPath = path14.join(directory, ".swarm/events.jsonl");
34466
+ const eventsPath = path15.join(directory, ".swarm/events.jsonl");
34354
34467
  if (!existsSync5(eventsPath)) {
34355
34468
  return {
34356
34469
  name: "Steering Directives",
@@ -34406,7 +34519,7 @@ async function checkCurator(directory) {
34406
34519
  detail: "Disabled (enable via curator.enabled)"
34407
34520
  };
34408
34521
  }
34409
- const summaryPath = path14.join(directory, ".swarm/curator-summary.json");
34522
+ const summaryPath = path15.join(directory, ".swarm/curator-summary.json");
34410
34523
  if (!existsSync5(summaryPath)) {
34411
34524
  return {
34412
34525
  name: "Curator",
@@ -35303,10 +35416,10 @@ async function handleHistoryCommand(directory, _args) {
35303
35416
  import { randomUUID as randomUUID2 } from "crypto";
35304
35417
  import { existsSync as existsSync7, readFileSync as readFileSync7 } from "fs";
35305
35418
  import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
35306
- import * as path16 from "path";
35419
+ import * as path17 from "path";
35307
35420
  async function migrateContextToKnowledge(directory, config3) {
35308
- const sentinelPath = path16.join(directory, ".swarm", ".knowledge-migrated");
35309
- const contextPath = path16.join(directory, ".swarm", "context.md");
35421
+ const sentinelPath = path17.join(directory, ".swarm", ".knowledge-migrated");
35422
+ const contextPath = path17.join(directory, ".swarm", "context.md");
35310
35423
  const knowledgePath = resolveSwarmKnowledgePath(directory);
35311
35424
  if (existsSync7(sentinelPath)) {
35312
35425
  return {
@@ -35502,7 +35615,7 @@ function truncateLesson(text) {
35502
35615
  return `${text.slice(0, 277)}...`;
35503
35616
  }
35504
35617
  function inferProjectName(directory) {
35505
- const packageJsonPath = path16.join(directory, "package.json");
35618
+ const packageJsonPath = path17.join(directory, "package.json");
35506
35619
  if (existsSync7(packageJsonPath)) {
35507
35620
  try {
35508
35621
  const pkg = JSON.parse(readFileSync7(packageJsonPath, "utf-8"));
@@ -35511,7 +35624,7 @@ function inferProjectName(directory) {
35511
35624
  }
35512
35625
  } catch {}
35513
35626
  }
35514
- return path16.basename(directory);
35627
+ return path17.basename(directory);
35515
35628
  }
35516
35629
  async function writeSentinel(sentinelPath, migrated, dropped) {
35517
35630
  const sentinel = {
@@ -35523,7 +35636,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
35523
35636
  schema_version: 1,
35524
35637
  migration_tool: "knowledge-migrator.ts"
35525
35638
  };
35526
- await mkdir3(path16.dirname(sentinelPath), { recursive: true });
35639
+ await mkdir3(path17.dirname(sentinelPath), { recursive: true });
35527
35640
  await writeFile3(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
35528
35641
  }
35529
35642
 
@@ -35760,15 +35873,15 @@ async function handlePlanCommand(directory, args) {
35760
35873
  init_manager();
35761
35874
  init_manager2();
35762
35875
  import * as fs13 from "fs";
35763
- import * as path22 from "path";
35876
+ import * as path23 from "path";
35764
35877
 
35765
35878
  // src/tools/lint.ts
35766
35879
  import * as fs9 from "fs";
35767
- import * as path18 from "path";
35880
+ import * as path19 from "path";
35768
35881
 
35769
35882
  // src/build/discovery.ts
35770
35883
  import * as fs8 from "fs";
35771
- import * as path17 from "path";
35884
+ import * as path18 from "path";
35772
35885
 
35773
35886
  // src/lang/detector.ts
35774
35887
  import { access, readdir as readdir2 } from "fs/promises";
@@ -36865,11 +36978,11 @@ function findBuildFiles(workingDir, patterns) {
36865
36978
  const regex = simpleGlobToRegex(pattern);
36866
36979
  const matches = files.filter((f) => regex.test(f));
36867
36980
  if (matches.length > 0) {
36868
- return path17.join(dir, matches[0]);
36981
+ return path18.join(dir, matches[0]);
36869
36982
  }
36870
36983
  } catch {}
36871
36984
  } else {
36872
- const filePath = path17.join(workingDir, pattern);
36985
+ const filePath = path18.join(workingDir, pattern);
36873
36986
  if (fs8.existsSync(filePath)) {
36874
36987
  return filePath;
36875
36988
  }
@@ -36878,7 +36991,7 @@ function findBuildFiles(workingDir, patterns) {
36878
36991
  return null;
36879
36992
  }
36880
36993
  function getRepoDefinedScripts(workingDir, scripts) {
36881
- const packageJsonPath = path17.join(workingDir, "package.json");
36994
+ const packageJsonPath = path18.join(workingDir, "package.json");
36882
36995
  if (!fs8.existsSync(packageJsonPath)) {
36883
36996
  return [];
36884
36997
  }
@@ -36919,7 +37032,7 @@ function findAllBuildFiles(workingDir) {
36919
37032
  const regex = simpleGlobToRegex(pattern);
36920
37033
  findFilesRecursive(workingDir, regex, allBuildFiles);
36921
37034
  } else {
36922
- const filePath = path17.join(workingDir, pattern);
37035
+ const filePath = path18.join(workingDir, pattern);
36923
37036
  if (fs8.existsSync(filePath)) {
36924
37037
  allBuildFiles.add(filePath);
36925
37038
  }
@@ -36932,7 +37045,7 @@ function findFilesRecursive(dir, regex, results) {
36932
37045
  try {
36933
37046
  const entries = fs8.readdirSync(dir, { withFileTypes: true });
36934
37047
  for (const entry of entries) {
36935
- const fullPath = path17.join(dir, entry.name);
37048
+ const fullPath = path18.join(dir, entry.name);
36936
37049
  if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
36937
37050
  findFilesRecursive(fullPath, regex, results);
36938
37051
  } else if (entry.isFile() && regex.test(entry.name)) {
@@ -36955,7 +37068,7 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
36955
37068
  let foundCommand = false;
36956
37069
  for (const cmd of sortedCommands) {
36957
37070
  if (cmd.detectFile) {
36958
- const detectFilePath = path17.join(workingDir, cmd.detectFile);
37071
+ const detectFilePath = path18.join(workingDir, cmd.detectFile);
36959
37072
  if (!fs8.existsSync(detectFilePath)) {
36960
37073
  continue;
36961
37074
  }
@@ -37103,9 +37216,9 @@ function validateArgs(args) {
37103
37216
  }
37104
37217
  function getLinterCommand(linter, mode, projectDir) {
37105
37218
  const isWindows = process.platform === "win32";
37106
- const binDir = path18.join(projectDir, "node_modules", ".bin");
37107
- const biomeBin = isWindows ? path18.join(binDir, "biome.EXE") : path18.join(binDir, "biome");
37108
- const eslintBin = isWindows ? path18.join(binDir, "eslint.cmd") : path18.join(binDir, "eslint");
37219
+ const binDir = path19.join(projectDir, "node_modules", ".bin");
37220
+ const biomeBin = isWindows ? path19.join(binDir, "biome.EXE") : path19.join(binDir, "biome");
37221
+ const eslintBin = isWindows ? path19.join(binDir, "eslint.cmd") : path19.join(binDir, "eslint");
37109
37222
  switch (linter) {
37110
37223
  case "biome":
37111
37224
  if (mode === "fix") {
@@ -37121,7 +37234,7 @@ function getLinterCommand(linter, mode, projectDir) {
37121
37234
  }
37122
37235
  function getAdditionalLinterCommand(linter, mode, cwd) {
37123
37236
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
37124
- const gradlew = fs9.existsSync(path18.join(cwd, gradlewName)) ? path18.join(cwd, gradlewName) : null;
37237
+ const gradlew = fs9.existsSync(path19.join(cwd, gradlewName)) ? path19.join(cwd, gradlewName) : null;
37125
37238
  switch (linter) {
37126
37239
  case "ruff":
37127
37240
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -37155,10 +37268,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
37155
37268
  }
37156
37269
  }
37157
37270
  function detectRuff(cwd) {
37158
- if (fs9.existsSync(path18.join(cwd, "ruff.toml")))
37271
+ if (fs9.existsSync(path19.join(cwd, "ruff.toml")))
37159
37272
  return isCommandAvailable("ruff");
37160
37273
  try {
37161
- const pyproject = path18.join(cwd, "pyproject.toml");
37274
+ const pyproject = path19.join(cwd, "pyproject.toml");
37162
37275
  if (fs9.existsSync(pyproject)) {
37163
37276
  const content = fs9.readFileSync(pyproject, "utf-8");
37164
37277
  if (content.includes("[tool.ruff]"))
@@ -37168,19 +37281,19 @@ function detectRuff(cwd) {
37168
37281
  return false;
37169
37282
  }
37170
37283
  function detectClippy(cwd) {
37171
- return fs9.existsSync(path18.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
37284
+ return fs9.existsSync(path19.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
37172
37285
  }
37173
37286
  function detectGolangciLint(cwd) {
37174
- return fs9.existsSync(path18.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
37287
+ return fs9.existsSync(path19.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
37175
37288
  }
37176
37289
  function detectCheckstyle(cwd) {
37177
- const hasMaven = fs9.existsSync(path18.join(cwd, "pom.xml"));
37178
- const hasGradle = fs9.existsSync(path18.join(cwd, "build.gradle")) || fs9.existsSync(path18.join(cwd, "build.gradle.kts"));
37179
- const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs9.existsSync(path18.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
37290
+ const hasMaven = fs9.existsSync(path19.join(cwd, "pom.xml"));
37291
+ const hasGradle = fs9.existsSync(path19.join(cwd, "build.gradle")) || fs9.existsSync(path19.join(cwd, "build.gradle.kts"));
37292
+ const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs9.existsSync(path19.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
37180
37293
  return (hasMaven || hasGradle) && hasBinary;
37181
37294
  }
37182
37295
  function detectKtlint(cwd) {
37183
- const hasKotlin = fs9.existsSync(path18.join(cwd, "build.gradle.kts")) || fs9.existsSync(path18.join(cwd, "build.gradle")) || (() => {
37296
+ const hasKotlin = fs9.existsSync(path19.join(cwd, "build.gradle.kts")) || fs9.existsSync(path19.join(cwd, "build.gradle")) || (() => {
37184
37297
  try {
37185
37298
  return fs9.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
37186
37299
  } catch {
@@ -37199,11 +37312,11 @@ function detectDotnetFormat(cwd) {
37199
37312
  }
37200
37313
  }
37201
37314
  function detectCppcheck(cwd) {
37202
- if (fs9.existsSync(path18.join(cwd, "CMakeLists.txt"))) {
37315
+ if (fs9.existsSync(path19.join(cwd, "CMakeLists.txt"))) {
37203
37316
  return isCommandAvailable("cppcheck");
37204
37317
  }
37205
37318
  try {
37206
- const dirsToCheck = [cwd, path18.join(cwd, "src")];
37319
+ const dirsToCheck = [cwd, path19.join(cwd, "src")];
37207
37320
  const hasCpp = dirsToCheck.some((dir) => {
37208
37321
  try {
37209
37322
  return fs9.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
@@ -37217,13 +37330,13 @@ function detectCppcheck(cwd) {
37217
37330
  }
37218
37331
  }
37219
37332
  function detectSwiftlint(cwd) {
37220
- return fs9.existsSync(path18.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
37333
+ return fs9.existsSync(path19.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
37221
37334
  }
37222
37335
  function detectDartAnalyze(cwd) {
37223
- return fs9.existsSync(path18.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
37336
+ return fs9.existsSync(path19.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
37224
37337
  }
37225
37338
  function detectRubocop(cwd) {
37226
- return (fs9.existsSync(path18.join(cwd, "Gemfile")) || fs9.existsSync(path18.join(cwd, "gems.rb")) || fs9.existsSync(path18.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
37339
+ return (fs9.existsSync(path19.join(cwd, "Gemfile")) || fs9.existsSync(path19.join(cwd, "gems.rb")) || fs9.existsSync(path19.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
37227
37340
  }
37228
37341
  function detectAdditionalLinter(cwd) {
37229
37342
  if (detectRuff(cwd))
@@ -37251,10 +37364,10 @@ function detectAdditionalLinter(cwd) {
37251
37364
  function findBinInAncestors(startDir, binName) {
37252
37365
  let dir = startDir;
37253
37366
  while (true) {
37254
- const candidate = path18.join(dir, "node_modules", ".bin", binName);
37367
+ const candidate = path19.join(dir, "node_modules", ".bin", binName);
37255
37368
  if (fs9.existsSync(candidate))
37256
37369
  return candidate;
37257
- const parent = path18.dirname(dir);
37370
+ const parent = path19.dirname(dir);
37258
37371
  if (parent === dir)
37259
37372
  break;
37260
37373
  dir = parent;
@@ -37263,10 +37376,10 @@ function findBinInAncestors(startDir, binName) {
37263
37376
  }
37264
37377
  function findBinInEnvPath(binName) {
37265
37378
  const searchPath = process.env.PATH ?? "";
37266
- for (const dir of searchPath.split(path18.delimiter)) {
37379
+ for (const dir of searchPath.split(path19.delimiter)) {
37267
37380
  if (!dir)
37268
37381
  continue;
37269
- const candidate = path18.join(dir, binName);
37382
+ const candidate = path19.join(dir, binName);
37270
37383
  if (fs9.existsSync(candidate))
37271
37384
  return candidate;
37272
37385
  }
@@ -37279,13 +37392,13 @@ async function detectAvailableLinter(directory) {
37279
37392
  return null;
37280
37393
  const projectDir = directory;
37281
37394
  const isWindows = process.platform === "win32";
37282
- const biomeBin = isWindows ? path18.join(projectDir, "node_modules", ".bin", "biome.EXE") : path18.join(projectDir, "node_modules", ".bin", "biome");
37283
- const eslintBin = isWindows ? path18.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path18.join(projectDir, "node_modules", ".bin", "eslint");
37395
+ const biomeBin = isWindows ? path19.join(projectDir, "node_modules", ".bin", "biome.EXE") : path19.join(projectDir, "node_modules", ".bin", "biome");
37396
+ const eslintBin = isWindows ? path19.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path19.join(projectDir, "node_modules", ".bin", "eslint");
37284
37397
  const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
37285
37398
  if (localResult)
37286
37399
  return localResult;
37287
- const biomeAncestor = findBinInAncestors(path18.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
37288
- const eslintAncestor = findBinInAncestors(path18.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
37400
+ const biomeAncestor = findBinInAncestors(path19.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
37401
+ const eslintAncestor = findBinInAncestors(path19.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
37289
37402
  if (biomeAncestor || eslintAncestor) {
37290
37403
  return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
37291
37404
  }
@@ -37493,7 +37606,7 @@ For Rust: rustup component add clippy`
37493
37606
 
37494
37607
  // src/tools/secretscan.ts
37495
37608
  import * as fs10 from "fs";
37496
- import * as path19 from "path";
37609
+ import * as path20 from "path";
37497
37610
  var MAX_FILE_PATH_LENGTH = 500;
37498
37611
  var MAX_FILE_SIZE_BYTES = 512 * 1024;
37499
37612
  var MAX_FILES_SCANNED = 1000;
@@ -37720,7 +37833,7 @@ function isGlobOrPathPattern(pattern) {
37720
37833
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
37721
37834
  }
37722
37835
  function loadSecretScanIgnore(scanDir) {
37723
- const ignorePath = path19.join(scanDir, ".secretscanignore");
37836
+ const ignorePath = path20.join(scanDir, ".secretscanignore");
37724
37837
  try {
37725
37838
  if (!fs10.existsSync(ignorePath))
37726
37839
  return [];
@@ -37743,7 +37856,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
37743
37856
  if (exactNames.has(entry))
37744
37857
  return true;
37745
37858
  for (const pattern of globPatterns) {
37746
- if (path19.matchesGlob(relPath, pattern))
37859
+ if (path20.matchesGlob(relPath, pattern))
37747
37860
  return true;
37748
37861
  }
37749
37862
  return false;
@@ -37764,7 +37877,7 @@ function validateDirectoryInput(dir) {
37764
37877
  return null;
37765
37878
  }
37766
37879
  function isBinaryFile(filePath, buffer) {
37767
- const ext = path19.extname(filePath).toLowerCase();
37880
+ const ext = path20.extname(filePath).toLowerCase();
37768
37881
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
37769
37882
  return true;
37770
37883
  }
@@ -37901,9 +38014,9 @@ function isSymlinkLoop(realPath, visited) {
37901
38014
  return false;
37902
38015
  }
37903
38016
  function isPathWithinScope(realPath, scanDir) {
37904
- const resolvedScanDir = path19.resolve(scanDir);
37905
- const resolvedRealPath = path19.resolve(realPath);
37906
- return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path19.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
38017
+ const resolvedScanDir = path20.resolve(scanDir);
38018
+ const resolvedRealPath = path20.resolve(realPath);
38019
+ return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path20.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
37907
38020
  }
37908
38021
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
37909
38022
  skippedDirs: 0,
@@ -37929,8 +38042,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
37929
38042
  return a.localeCompare(b);
37930
38043
  });
37931
38044
  for (const entry of entries) {
37932
- const fullPath = path19.join(dir, entry);
37933
- const relPath = path19.relative(scanDir, fullPath).replace(/\\/g, "/");
38045
+ const fullPath = path20.join(dir, entry);
38046
+ const relPath = path20.relative(scanDir, fullPath).replace(/\\/g, "/");
37934
38047
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
37935
38048
  stats.skippedDirs++;
37936
38049
  continue;
@@ -37965,7 +38078,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
37965
38078
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
37966
38079
  files.push(...subFiles);
37967
38080
  } else if (lstat.isFile()) {
37968
- const ext = path19.extname(fullPath).toLowerCase();
38081
+ const ext = path20.extname(fullPath).toLowerCase();
37969
38082
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
37970
38083
  files.push(fullPath);
37971
38084
  } else {
@@ -38031,7 +38144,7 @@ var secretscan = createSwarmTool({
38031
38144
  }
38032
38145
  }
38033
38146
  try {
38034
- const _scanDirRaw = path19.resolve(directory);
38147
+ const _scanDirRaw = path20.resolve(directory);
38035
38148
  const scanDir = (() => {
38036
38149
  try {
38037
38150
  return fs10.realpathSync(_scanDirRaw);
@@ -38189,11 +38302,11 @@ async function runSecretscan(directory) {
38189
38302
 
38190
38303
  // src/tools/test-runner.ts
38191
38304
  import * as fs12 from "fs";
38192
- import * as path21 from "path";
38305
+ import * as path22 from "path";
38193
38306
 
38194
38307
  // src/tools/resolve-working-directory.ts
38195
38308
  import * as fs11 from "fs";
38196
- import * as path20 from "path";
38309
+ import * as path21 from "path";
38197
38310
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
38198
38311
  if (workingDirectory == null || workingDirectory === "") {
38199
38312
  return { success: true, directory: fallbackDirectory };
@@ -38213,15 +38326,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
38213
38326
  };
38214
38327
  }
38215
38328
  }
38216
- const normalizedDir = path20.normalize(workingDirectory);
38217
- const pathParts = normalizedDir.split(path20.sep);
38329
+ const normalizedDir = path21.normalize(workingDirectory);
38330
+ const pathParts = normalizedDir.split(path21.sep);
38218
38331
  if (pathParts.includes("..")) {
38219
38332
  return {
38220
38333
  success: false,
38221
38334
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
38222
38335
  };
38223
38336
  }
38224
- const resolvedDir = path20.resolve(normalizedDir);
38337
+ const resolvedDir = path21.resolve(normalizedDir);
38225
38338
  try {
38226
38339
  const realPath = fs11.realpathSync(resolvedDir);
38227
38340
  return { success: true, directory: realPath };
@@ -38304,14 +38417,14 @@ function hasDevDependency(devDeps, ...patterns) {
38304
38417
  return hasPackageJsonDependency(devDeps, ...patterns);
38305
38418
  }
38306
38419
  function detectGoTest(cwd) {
38307
- return fs12.existsSync(path21.join(cwd, "go.mod")) && isCommandAvailable("go");
38420
+ return fs12.existsSync(path22.join(cwd, "go.mod")) && isCommandAvailable("go");
38308
38421
  }
38309
38422
  function detectJavaMaven(cwd) {
38310
- return fs12.existsSync(path21.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
38423
+ return fs12.existsSync(path22.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
38311
38424
  }
38312
38425
  function detectGradle(cwd) {
38313
- const hasBuildFile = fs12.existsSync(path21.join(cwd, "build.gradle")) || fs12.existsSync(path21.join(cwd, "build.gradle.kts"));
38314
- const hasGradlew = fs12.existsSync(path21.join(cwd, "gradlew")) || fs12.existsSync(path21.join(cwd, "gradlew.bat"));
38426
+ const hasBuildFile = fs12.existsSync(path22.join(cwd, "build.gradle")) || fs12.existsSync(path22.join(cwd, "build.gradle.kts"));
38427
+ const hasGradlew = fs12.existsSync(path22.join(cwd, "gradlew")) || fs12.existsSync(path22.join(cwd, "gradlew.bat"));
38315
38428
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
38316
38429
  }
38317
38430
  function detectDotnetTest(cwd) {
@@ -38324,30 +38437,30 @@ function detectDotnetTest(cwd) {
38324
38437
  }
38325
38438
  }
38326
38439
  function detectCTest(cwd) {
38327
- const hasSource = fs12.existsSync(path21.join(cwd, "CMakeLists.txt"));
38328
- const hasBuildCache = fs12.existsSync(path21.join(cwd, "CMakeCache.txt")) || fs12.existsSync(path21.join(cwd, "build", "CMakeCache.txt"));
38440
+ const hasSource = fs12.existsSync(path22.join(cwd, "CMakeLists.txt"));
38441
+ const hasBuildCache = fs12.existsSync(path22.join(cwd, "CMakeCache.txt")) || fs12.existsSync(path22.join(cwd, "build", "CMakeCache.txt"));
38329
38442
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
38330
38443
  }
38331
38444
  function detectSwiftTest(cwd) {
38332
- return fs12.existsSync(path21.join(cwd, "Package.swift")) && isCommandAvailable("swift");
38445
+ return fs12.existsSync(path22.join(cwd, "Package.swift")) && isCommandAvailable("swift");
38333
38446
  }
38334
38447
  function detectDartTest(cwd) {
38335
- return fs12.existsSync(path21.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
38448
+ return fs12.existsSync(path22.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
38336
38449
  }
38337
38450
  function detectRSpec(cwd) {
38338
- const hasRSpecFile = fs12.existsSync(path21.join(cwd, ".rspec"));
38339
- const hasGemfile = fs12.existsSync(path21.join(cwd, "Gemfile"));
38340
- const hasSpecDir = fs12.existsSync(path21.join(cwd, "spec"));
38451
+ const hasRSpecFile = fs12.existsSync(path22.join(cwd, ".rspec"));
38452
+ const hasGemfile = fs12.existsSync(path22.join(cwd, "Gemfile"));
38453
+ const hasSpecDir = fs12.existsSync(path22.join(cwd, "spec"));
38341
38454
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
38342
38455
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
38343
38456
  }
38344
38457
  function detectMinitest(cwd) {
38345
- return fs12.existsSync(path21.join(cwd, "test")) && (fs12.existsSync(path21.join(cwd, "Gemfile")) || fs12.existsSync(path21.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
38458
+ return fs12.existsSync(path22.join(cwd, "test")) && (fs12.existsSync(path22.join(cwd, "Gemfile")) || fs12.existsSync(path22.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
38346
38459
  }
38347
38460
  async function detectTestFramework(cwd) {
38348
38461
  const baseDir = cwd;
38349
38462
  try {
38350
- const packageJsonPath = path21.join(baseDir, "package.json");
38463
+ const packageJsonPath = path22.join(baseDir, "package.json");
38351
38464
  if (fs12.existsSync(packageJsonPath)) {
38352
38465
  const content = fs12.readFileSync(packageJsonPath, "utf-8");
38353
38466
  const pkg = JSON.parse(content);
@@ -38368,16 +38481,16 @@ async function detectTestFramework(cwd) {
38368
38481
  return "jest";
38369
38482
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
38370
38483
  return "mocha";
38371
- if (fs12.existsSync(path21.join(baseDir, "bun.lockb")) || fs12.existsSync(path21.join(baseDir, "bun.lock"))) {
38484
+ if (fs12.existsSync(path22.join(baseDir, "bun.lockb")) || fs12.existsSync(path22.join(baseDir, "bun.lock"))) {
38372
38485
  if (scripts.test?.includes("bun"))
38373
38486
  return "bun";
38374
38487
  }
38375
38488
  }
38376
38489
  } catch {}
38377
38490
  try {
38378
- const pyprojectTomlPath = path21.join(baseDir, "pyproject.toml");
38379
- const setupCfgPath = path21.join(baseDir, "setup.cfg");
38380
- const requirementsTxtPath = path21.join(baseDir, "requirements.txt");
38491
+ const pyprojectTomlPath = path22.join(baseDir, "pyproject.toml");
38492
+ const setupCfgPath = path22.join(baseDir, "setup.cfg");
38493
+ const requirementsTxtPath = path22.join(baseDir, "requirements.txt");
38381
38494
  if (fs12.existsSync(pyprojectTomlPath)) {
38382
38495
  const content = fs12.readFileSync(pyprojectTomlPath, "utf-8");
38383
38496
  if (content.includes("[tool.pytest"))
@@ -38397,7 +38510,7 @@ async function detectTestFramework(cwd) {
38397
38510
  }
38398
38511
  } catch {}
38399
38512
  try {
38400
- const cargoTomlPath = path21.join(baseDir, "Cargo.toml");
38513
+ const cargoTomlPath = path22.join(baseDir, "Cargo.toml");
38401
38514
  if (fs12.existsSync(cargoTomlPath)) {
38402
38515
  const content = fs12.readFileSync(cargoTomlPath, "utf-8");
38403
38516
  if (content.includes("[dev-dependencies]")) {
@@ -38408,9 +38521,9 @@ async function detectTestFramework(cwd) {
38408
38521
  }
38409
38522
  } catch {}
38410
38523
  try {
38411
- const pesterConfigPath = path21.join(baseDir, "pester.config.ps1");
38412
- const pesterConfigJsonPath = path21.join(baseDir, "pester.config.ps1.json");
38413
- const pesterPs1Path = path21.join(baseDir, "tests.ps1");
38524
+ const pesterConfigPath = path22.join(baseDir, "pester.config.ps1");
38525
+ const pesterConfigJsonPath = path22.join(baseDir, "pester.config.ps1.json");
38526
+ const pesterPs1Path = path22.join(baseDir, "tests.ps1");
38414
38527
  if (fs12.existsSync(pesterConfigPath) || fs12.existsSync(pesterConfigJsonPath) || fs12.existsSync(pesterPs1Path)) {
38415
38528
  return "pester";
38416
38529
  }
@@ -38462,8 +38575,8 @@ function getTestFilesFromConvention(sourceFiles) {
38462
38575
  const testFiles = [];
38463
38576
  for (const file3 of sourceFiles) {
38464
38577
  const normalizedPath = file3.replace(/\\/g, "/");
38465
- const basename4 = path21.basename(file3);
38466
- const dirname10 = path21.dirname(file3);
38578
+ const basename4 = path22.basename(file3);
38579
+ const dirname10 = path22.dirname(file3);
38467
38580
  if (hasCompoundTestExtension(basename4) || basename4.includes(".spec.") || basename4.includes(".test.") || normalizedPath.includes("/__tests__/") || normalizedPath.includes("/tests/") || normalizedPath.includes("/test/")) {
38468
38581
  if (!testFiles.includes(file3)) {
38469
38582
  testFiles.push(file3);
@@ -38472,13 +38585,13 @@ function getTestFilesFromConvention(sourceFiles) {
38472
38585
  }
38473
38586
  for (const _pattern of TEST_PATTERNS) {
38474
38587
  const nameWithoutExt = basename4.replace(/\.[^.]+$/, "");
38475
- const ext = path21.extname(basename4);
38588
+ const ext = path22.extname(basename4);
38476
38589
  const possibleTestFiles = [
38477
- path21.join(dirname10, `${nameWithoutExt}.spec${ext}`),
38478
- path21.join(dirname10, `${nameWithoutExt}.test${ext}`),
38479
- path21.join(dirname10, "__tests__", `${nameWithoutExt}${ext}`),
38480
- path21.join(dirname10, "tests", `${nameWithoutExt}${ext}`),
38481
- path21.join(dirname10, "test", `${nameWithoutExt}${ext}`)
38590
+ path22.join(dirname10, `${nameWithoutExt}.spec${ext}`),
38591
+ path22.join(dirname10, `${nameWithoutExt}.test${ext}`),
38592
+ path22.join(dirname10, "__tests__", `${nameWithoutExt}${ext}`),
38593
+ path22.join(dirname10, "tests", `${nameWithoutExt}${ext}`),
38594
+ path22.join(dirname10, "test", `${nameWithoutExt}${ext}`)
38482
38595
  ];
38483
38596
  for (const testFile of possibleTestFiles) {
38484
38597
  if (fs12.existsSync(testFile) && !testFiles.includes(testFile)) {
@@ -38498,7 +38611,7 @@ async function getTestFilesFromGraph(sourceFiles) {
38498
38611
  for (const testFile of candidateTestFiles) {
38499
38612
  try {
38500
38613
  const content = fs12.readFileSync(testFile, "utf-8");
38501
- const testDir = path21.dirname(testFile);
38614
+ const testDir = path22.dirname(testFile);
38502
38615
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
38503
38616
  let match;
38504
38617
  match = importRegex.exec(content);
@@ -38506,8 +38619,8 @@ async function getTestFilesFromGraph(sourceFiles) {
38506
38619
  const importPath = match[1];
38507
38620
  let resolvedImport;
38508
38621
  if (importPath.startsWith(".")) {
38509
- resolvedImport = path21.resolve(testDir, importPath);
38510
- const existingExt = path21.extname(resolvedImport);
38622
+ resolvedImport = path22.resolve(testDir, importPath);
38623
+ const existingExt = path22.extname(resolvedImport);
38511
38624
  if (!existingExt) {
38512
38625
  for (const extToTry of [
38513
38626
  ".ts",
@@ -38527,12 +38640,12 @@ async function getTestFilesFromGraph(sourceFiles) {
38527
38640
  } else {
38528
38641
  continue;
38529
38642
  }
38530
- const importBasename = path21.basename(resolvedImport, path21.extname(resolvedImport));
38531
- const importDir = path21.dirname(resolvedImport);
38643
+ const importBasename = path22.basename(resolvedImport, path22.extname(resolvedImport));
38644
+ const importDir = path22.dirname(resolvedImport);
38532
38645
  for (const sourceFile of sourceFiles) {
38533
- const sourceDir = path21.dirname(sourceFile);
38534
- const sourceBasename = path21.basename(sourceFile, path21.extname(sourceFile));
38535
- const isRelatedDir = importDir === sourceDir || importDir === path21.join(sourceDir, "__tests__") || importDir === path21.join(sourceDir, "tests") || importDir === path21.join(sourceDir, "test");
38646
+ const sourceDir = path22.dirname(sourceFile);
38647
+ const sourceBasename = path22.basename(sourceFile, path22.extname(sourceFile));
38648
+ const isRelatedDir = importDir === sourceDir || importDir === path22.join(sourceDir, "__tests__") || importDir === path22.join(sourceDir, "tests") || importDir === path22.join(sourceDir, "test");
38536
38649
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
38537
38650
  if (!testFiles.includes(testFile)) {
38538
38651
  testFiles.push(testFile);
@@ -38547,8 +38660,8 @@ async function getTestFilesFromGraph(sourceFiles) {
38547
38660
  while (match !== null) {
38548
38661
  const importPath = match[1];
38549
38662
  if (importPath.startsWith(".")) {
38550
- let resolvedImport = path21.resolve(testDir, importPath);
38551
- const existingExt = path21.extname(resolvedImport);
38663
+ let resolvedImport = path22.resolve(testDir, importPath);
38664
+ const existingExt = path22.extname(resolvedImport);
38552
38665
  if (!existingExt) {
38553
38666
  for (const extToTry of [
38554
38667
  ".ts",
@@ -38565,12 +38678,12 @@ async function getTestFilesFromGraph(sourceFiles) {
38565
38678
  }
38566
38679
  }
38567
38680
  }
38568
- const importDir = path21.dirname(resolvedImport);
38569
- const importBasename = path21.basename(resolvedImport, path21.extname(resolvedImport));
38681
+ const importDir = path22.dirname(resolvedImport);
38682
+ const importBasename = path22.basename(resolvedImport, path22.extname(resolvedImport));
38570
38683
  for (const sourceFile of sourceFiles) {
38571
- const sourceDir = path21.dirname(sourceFile);
38572
- const sourceBasename = path21.basename(sourceFile, path21.extname(sourceFile));
38573
- const isRelatedDir = importDir === sourceDir || importDir === path21.join(sourceDir, "__tests__") || importDir === path21.join(sourceDir, "tests") || importDir === path21.join(sourceDir, "test");
38684
+ const sourceDir = path22.dirname(sourceFile);
38685
+ const sourceBasename = path22.basename(sourceFile, path22.extname(sourceFile));
38686
+ const isRelatedDir = importDir === sourceDir || importDir === path22.join(sourceDir, "__tests__") || importDir === path22.join(sourceDir, "tests") || importDir === path22.join(sourceDir, "test");
38574
38687
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
38575
38688
  if (!testFiles.includes(testFile)) {
38576
38689
  testFiles.push(testFile);
@@ -38655,8 +38768,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
38655
38768
  return ["mvn", "test"];
38656
38769
  case "gradle": {
38657
38770
  const isWindows = process.platform === "win32";
38658
- const hasGradlewBat = fs12.existsSync(path21.join(baseDir, "gradlew.bat"));
38659
- const hasGradlew = fs12.existsSync(path21.join(baseDir, "gradlew"));
38771
+ const hasGradlewBat = fs12.existsSync(path22.join(baseDir, "gradlew.bat"));
38772
+ const hasGradlew = fs12.existsSync(path22.join(baseDir, "gradlew"));
38660
38773
  if (hasGradlewBat && isWindows)
38661
38774
  return ["gradlew.bat", "test"];
38662
38775
  if (hasGradlew)
@@ -38673,7 +38786,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
38673
38786
  "cmake-build-release",
38674
38787
  "out"
38675
38788
  ];
38676
- const actualBuildDir = buildDirCandidates.find((d) => fs12.existsSync(path21.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
38789
+ const actualBuildDir = buildDirCandidates.find((d) => fs12.existsSync(path22.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
38677
38790
  return ["ctest", "--test-dir", actualBuildDir];
38678
38791
  }
38679
38792
  case "swift-test":
@@ -39215,7 +39328,7 @@ var test_runner = createSwarmTool({
39215
39328
  let effectiveScope = scope;
39216
39329
  if (scope === "all") {} else if (scope === "convention") {
39217
39330
  const sourceFiles = args.files.filter((f) => {
39218
- const ext = path21.extname(f).toLowerCase();
39331
+ const ext = path22.extname(f).toLowerCase();
39219
39332
  return SOURCE_EXTENSIONS.has(ext);
39220
39333
  });
39221
39334
  if (sourceFiles.length === 0) {
@@ -39231,7 +39344,7 @@ var test_runner = createSwarmTool({
39231
39344
  testFiles = getTestFilesFromConvention(sourceFiles);
39232
39345
  } else if (scope === "graph") {
39233
39346
  const sourceFiles = args.files.filter((f) => {
39234
- const ext = path21.extname(f).toLowerCase();
39347
+ const ext = path22.extname(f).toLowerCase();
39235
39348
  return SOURCE_EXTENSIONS.has(ext);
39236
39349
  });
39237
39350
  if (sourceFiles.length === 0) {
@@ -39302,8 +39415,8 @@ function validateDirectoryPath(dir) {
39302
39415
  if (dir.includes("..")) {
39303
39416
  throw new Error("Directory path must not contain path traversal sequences");
39304
39417
  }
39305
- const normalized = path22.normalize(dir);
39306
- const absolutePath = path22.isAbsolute(normalized) ? normalized : path22.resolve(normalized);
39418
+ const normalized = path23.normalize(dir);
39419
+ const absolutePath = path23.isAbsolute(normalized) ? normalized : path23.resolve(normalized);
39307
39420
  return absolutePath;
39308
39421
  }
39309
39422
  function validateTimeout(timeoutMs, defaultValue) {
@@ -39326,7 +39439,7 @@ function validateTimeout(timeoutMs, defaultValue) {
39326
39439
  }
39327
39440
  function getPackageVersion(dir) {
39328
39441
  try {
39329
- const packagePath = path22.join(dir, "package.json");
39442
+ const packagePath = path23.join(dir, "package.json");
39330
39443
  if (fs13.existsSync(packagePath)) {
39331
39444
  const content = fs13.readFileSync(packagePath, "utf-8");
39332
39445
  const pkg = JSON.parse(content);
@@ -39337,7 +39450,7 @@ function getPackageVersion(dir) {
39337
39450
  }
39338
39451
  function getChangelogVersion(dir) {
39339
39452
  try {
39340
- const changelogPath = path22.join(dir, "CHANGELOG.md");
39453
+ const changelogPath = path23.join(dir, "CHANGELOG.md");
39341
39454
  if (fs13.existsSync(changelogPath)) {
39342
39455
  const content = fs13.readFileSync(changelogPath, "utf-8");
39343
39456
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
@@ -39351,7 +39464,7 @@ function getChangelogVersion(dir) {
39351
39464
  function getVersionFileVersion(dir) {
39352
39465
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
39353
39466
  for (const file3 of possibleFiles) {
39354
- const filePath = path22.join(dir, file3);
39467
+ const filePath = path23.join(dir, file3);
39355
39468
  if (fs13.existsSync(filePath)) {
39356
39469
  try {
39357
39470
  const content = fs13.readFileSync(filePath, "utf-8").trim();
@@ -39849,7 +39962,7 @@ async function handlePreflightCommand(directory, _args) {
39849
39962
  // src/knowledge/hive-promoter.ts
39850
39963
  import * as fs14 from "fs";
39851
39964
  import * as os5 from "os";
39852
- import * as path23 from "path";
39965
+ import * as path24 from "path";
39853
39966
  var DANGEROUS_PATTERNS = [
39854
39967
  [/rm\s+-rf/, "rm\\s+-rf"],
39855
39968
  [/:\s*!\s*\|/, ":\\s*!\\s*\\|"],
@@ -39895,13 +40008,13 @@ function getHiveFilePath() {
39895
40008
  const home = os5.homedir();
39896
40009
  let dataDir;
39897
40010
  if (platform === "win32") {
39898
- dataDir = path23.join(process.env.LOCALAPPDATA || path23.join(home, "AppData", "Local"), "opencode-swarm", "Data");
40011
+ dataDir = path24.join(process.env.LOCALAPPDATA || path24.join(home, "AppData", "Local"), "opencode-swarm", "Data");
39899
40012
  } else if (platform === "darwin") {
39900
- dataDir = path23.join(home, "Library", "Application Support", "opencode-swarm");
40013
+ dataDir = path24.join(home, "Library", "Application Support", "opencode-swarm");
39901
40014
  } else {
39902
- dataDir = path23.join(process.env.XDG_DATA_HOME || path23.join(home, ".local", "share"), "opencode-swarm");
40015
+ dataDir = path24.join(process.env.XDG_DATA_HOME || path24.join(home, ".local", "share"), "opencode-swarm");
39903
40016
  }
39904
- return path23.join(dataDir, "hive-knowledge.jsonl");
40017
+ return path24.join(dataDir, "hive-knowledge.jsonl");
39905
40018
  }
39906
40019
  async function promoteToHive(_directory, lesson, category) {
39907
40020
  const trimmed = (lesson ?? "").trim();
@@ -39913,7 +40026,7 @@ async function promoteToHive(_directory, lesson, category) {
39913
40026
  throw new Error(`Lesson rejected by validator: ${validation.reason}`);
39914
40027
  }
39915
40028
  const hivePath = getHiveFilePath();
39916
- const hiveDir = path23.dirname(hivePath);
40029
+ const hiveDir = path24.dirname(hivePath);
39917
40030
  if (!fs14.existsSync(hiveDir)) {
39918
40031
  fs14.mkdirSync(hiveDir, { recursive: true });
39919
40032
  }
@@ -39935,7 +40048,7 @@ async function promoteToHive(_directory, lesson, category) {
39935
40048
  return `Promoted to hive: "${preview}" (confidence: 1.0, source: manual)`;
39936
40049
  }
39937
40050
  async function promoteFromSwarm(directory, lessonId) {
39938
- const knowledgePath = path23.join(directory, ".swarm", "knowledge.jsonl");
40051
+ const knowledgePath = path24.join(directory, ".swarm", "knowledge.jsonl");
39939
40052
  const entries = [];
39940
40053
  if (fs14.existsSync(knowledgePath)) {
39941
40054
  const content = fs14.readFileSync(knowledgePath, "utf-8");
@@ -39962,7 +40075,7 @@ async function promoteFromSwarm(directory, lessonId) {
39962
40075
  throw new Error(`Lesson rejected by validator: ${validation.reason}`);
39963
40076
  }
39964
40077
  const hivePath = getHiveFilePath();
39965
- const hiveDir = path23.dirname(hivePath);
40078
+ const hiveDir = path24.dirname(hivePath);
39966
40079
  if (!fs14.existsSync(hiveDir)) {
39967
40080
  fs14.mkdirSync(hiveDir, { recursive: true });
39968
40081
  }
@@ -40773,7 +40886,7 @@ async function handleResetCommand(directory, args) {
40773
40886
  // src/commands/reset-session.ts
40774
40887
  init_utils2();
40775
40888
  import * as fs16 from "fs";
40776
- import * as path24 from "path";
40889
+ import * as path25 from "path";
40777
40890
  async function handleResetSessionCommand(directory, _args) {
40778
40891
  const results = [];
40779
40892
  try {
@@ -40788,13 +40901,13 @@ async function handleResetSessionCommand(directory, _args) {
40788
40901
  results.push("\u274C Failed to delete state.json");
40789
40902
  }
40790
40903
  try {
40791
- const sessionDir = path24.dirname(validateSwarmPath(directory, "session/state.json"));
40904
+ const sessionDir = path25.dirname(validateSwarmPath(directory, "session/state.json"));
40792
40905
  if (fs16.existsSync(sessionDir)) {
40793
40906
  const files = fs16.readdirSync(sessionDir);
40794
40907
  const otherFiles = files.filter((f) => f !== "state.json");
40795
40908
  let deletedCount = 0;
40796
40909
  for (const file3 of otherFiles) {
40797
- const filePath = path24.join(sessionDir, file3);
40910
+ const filePath = path25.join(sessionDir, file3);
40798
40911
  if (fs16.lstatSync(filePath).isFile()) {
40799
40912
  fs16.unlinkSync(filePath);
40800
40913
  deletedCount++;
@@ -40824,7 +40937,7 @@ async function handleResetSessionCommand(directory, _args) {
40824
40937
  // src/summaries/manager.ts
40825
40938
  init_utils2();
40826
40939
  init_utils();
40827
- import * as path25 from "path";
40940
+ import * as path26 from "path";
40828
40941
  var SUMMARY_ID_REGEX = /^S\d+$/;
40829
40942
  function sanitizeSummaryId(id) {
40830
40943
  if (!id || id.length === 0) {
@@ -40848,7 +40961,7 @@ function sanitizeSummaryId(id) {
40848
40961
  }
40849
40962
  async function loadFullOutput(directory, id) {
40850
40963
  const sanitizedId = sanitizeSummaryId(id);
40851
- const relativePath = path25.join("summaries", `${sanitizedId}.json`);
40964
+ const relativePath = path26.join("summaries", `${sanitizedId}.json`);
40852
40965
  validateSwarmPath(directory, relativePath);
40853
40966
  const content = await readSwarmFileAsync(directory, relativePath);
40854
40967
  if (content === null) {
@@ -40902,7 +41015,7 @@ ${error93 instanceof Error ? error93.message : String(error93)}`;
40902
41015
  // src/commands/rollback.ts
40903
41016
  init_utils2();
40904
41017
  import * as fs17 from "fs";
40905
- import * as path26 from "path";
41018
+ import * as path27 from "path";
40906
41019
  async function handleRollbackCommand(directory, args) {
40907
41020
  const phaseArg = args[0];
40908
41021
  if (!phaseArg) {
@@ -40960,8 +41073,8 @@ async function handleRollbackCommand(directory, args) {
40960
41073
  const successes = [];
40961
41074
  const failures = [];
40962
41075
  for (const file3 of checkpointFiles) {
40963
- const src = path26.join(checkpointDir, file3);
40964
- const dest = path26.join(swarmDir, file3);
41076
+ const src = path27.join(checkpointDir, file3);
41077
+ const dest = path27.join(swarmDir, file3);
40965
41078
  try {
40966
41079
  fs17.cpSync(src, dest, { recursive: true, force: true });
40967
41080
  successes.push(file3);
@@ -41024,9 +41137,9 @@ async function handleSimulateCommand(directory, args) {
41024
41137
  const report = reportLines.filter(Boolean).join(`
41025
41138
  `);
41026
41139
  const fs18 = await import("fs/promises");
41027
- const path27 = await import("path");
41028
- const reportPath = path27.join(directory, ".swarm", "simulate-report.md");
41029
- await fs18.mkdir(path27.dirname(reportPath), { recursive: true });
41140
+ const path28 = await import("path");
41141
+ const reportPath = path28.join(directory, ".swarm", "simulate-report.md");
41142
+ await fs18.mkdir(path28.dirname(reportPath), { recursive: true });
41030
41143
  await fs18.writeFile(reportPath, report, "utf-8");
41031
41144
  return `${darkMatterPairs.length} hidden coupling pairs detected`;
41032
41145
  }
@@ -41509,10 +41622,10 @@ function resolveCommand(tokens) {
41509
41622
  }
41510
41623
 
41511
41624
  // src/cli/index.ts
41512
- var CONFIG_DIR = path27.join(process.env.XDG_CONFIG_HOME || path27.join(os6.homedir(), ".config"), "opencode");
41513
- var OPENCODE_CONFIG_PATH = path27.join(CONFIG_DIR, "opencode.json");
41514
- var PLUGIN_CONFIG_PATH = path27.join(CONFIG_DIR, "opencode-swarm.json");
41515
- var PROMPTS_DIR = path27.join(CONFIG_DIR, "opencode-swarm");
41625
+ var CONFIG_DIR = path28.join(process.env.XDG_CONFIG_HOME || path28.join(os6.homedir(), ".config"), "opencode");
41626
+ var OPENCODE_CONFIG_PATH = path28.join(CONFIG_DIR, "opencode.json");
41627
+ var PLUGIN_CONFIG_PATH = path28.join(CONFIG_DIR, "opencode-swarm.json");
41628
+ var PROMPTS_DIR = path28.join(CONFIG_DIR, "opencode-swarm");
41516
41629
  function ensureDir(dir) {
41517
41630
  if (!fs18.existsSync(dir)) {
41518
41631
  fs18.mkdirSync(dir, { recursive: true });
@@ -41536,7 +41649,7 @@ async function install() {
41536
41649
  `);
41537
41650
  ensureDir(CONFIG_DIR);
41538
41651
  ensureDir(PROMPTS_DIR);
41539
- const LEGACY_CONFIG_PATH = path27.join(CONFIG_DIR, "config.json");
41652
+ const LEGACY_CONFIG_PATH = path28.join(CONFIG_DIR, "config.json");
41540
41653
  let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
41541
41654
  if (!opencodeConfig) {
41542
41655
  const legacyConfig = loadJson(LEGACY_CONFIG_PATH);