opencode-swarm 6.44.0 → 6.44.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -5,43 +5,25 @@ var __getProtoOf = Object.getPrototypeOf;
5
5
  var __defProp = Object.defineProperty;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- function __accessProp(key) {
9
- return this[key];
10
- }
11
- var __toESMCache_node;
12
- var __toESMCache_esm;
13
8
  var __toESM = (mod, isNodeMode, target) => {
14
- var canCache = mod != null && typeof mod === "object";
15
- if (canCache) {
16
- var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
17
- var cached = cache.get(mod);
18
- if (cached)
19
- return cached;
20
- }
21
9
  target = mod != null ? __create(__getProtoOf(mod)) : {};
22
10
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
23
11
  for (let key of __getOwnPropNames(mod))
24
12
  if (!__hasOwnProp.call(to, key))
25
13
  __defProp(to, key, {
26
- get: __accessProp.bind(mod, key),
14
+ get: () => mod[key],
27
15
  enumerable: true
28
16
  });
29
- if (canCache)
30
- cache.set(mod, to);
31
17
  return to;
32
18
  };
33
19
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
34
- var __returnValue = (v) => v;
35
- function __exportSetter(name, newValue) {
36
- this[name] = __returnValue.bind(null, newValue);
37
- }
38
20
  var __export = (target, all) => {
39
21
  for (var name in all)
40
22
  __defProp(target, name, {
41
23
  get: all[name],
42
24
  enumerable: true,
43
25
  configurable: true,
44
- set: __exportSetter.bind(all, name)
26
+ set: (newValue) => all[name] = () => newValue
45
27
  });
46
28
  };
47
29
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
@@ -17005,13 +16987,13 @@ __export(exports_config_doctor, {
17005
16987
  import * as crypto3 from "crypto";
17006
16988
  import * as fs7 from "fs";
17007
16989
  import * as os4 from "os";
17008
- import * as path16 from "path";
16990
+ import * as path15 from "path";
17009
16991
  function getUserConfigDir3() {
17010
- return process.env.XDG_CONFIG_HOME || path16.join(os4.homedir(), ".config");
16992
+ return process.env.XDG_CONFIG_HOME || path15.join(os4.homedir(), ".config");
17011
16993
  }
17012
16994
  function getConfigPaths(directory) {
17013
- const userConfigPath = path16.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
17014
- const projectConfigPath = path16.join(directory, ".opencode", "opencode-swarm.json");
16995
+ const userConfigPath = path15.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
16996
+ const projectConfigPath = path15.join(directory, ".opencode", "opencode-swarm.json");
17015
16997
  return { userConfigPath, projectConfigPath };
17016
16998
  }
17017
16999
  function computeHash(content) {
@@ -17036,9 +17018,9 @@ function isValidConfigPath(configPath, directory) {
17036
17018
  const normalizedUser = userConfigPath.replace(/\\/g, "/");
17037
17019
  const normalizedProject = projectConfigPath.replace(/\\/g, "/");
17038
17020
  try {
17039
- const resolvedConfig = path16.resolve(configPath);
17040
- const resolvedUser = path16.resolve(normalizedUser);
17041
- const resolvedProject = path16.resolve(normalizedProject);
17021
+ const resolvedConfig = path15.resolve(configPath);
17022
+ const resolvedUser = path15.resolve(normalizedUser);
17023
+ const resolvedProject = path15.resolve(normalizedProject);
17042
17024
  return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
17043
17025
  } catch {
17044
17026
  return false;
@@ -17078,12 +17060,12 @@ function createConfigBackup(directory) {
17078
17060
  };
17079
17061
  }
17080
17062
  function writeBackupArtifact(directory, backup) {
17081
- const swarmDir = path16.join(directory, ".swarm");
17063
+ const swarmDir = path15.join(directory, ".swarm");
17082
17064
  if (!fs7.existsSync(swarmDir)) {
17083
17065
  fs7.mkdirSync(swarmDir, { recursive: true });
17084
17066
  }
17085
17067
  const backupFilename = `config-backup-${backup.createdAt}.json`;
17086
- const backupPath = path16.join(swarmDir, backupFilename);
17068
+ const backupPath = path15.join(swarmDir, backupFilename);
17087
17069
  const artifact = {
17088
17070
  createdAt: backup.createdAt,
17089
17071
  configPath: backup.configPath,
@@ -17113,7 +17095,7 @@ function restoreFromBackup(backupPath, directory) {
17113
17095
  return null;
17114
17096
  }
17115
17097
  const targetPath = artifact.configPath;
17116
- const targetDir = path16.dirname(targetPath);
17098
+ const targetDir = path15.dirname(targetPath);
17117
17099
  if (!fs7.existsSync(targetDir)) {
17118
17100
  fs7.mkdirSync(targetDir, { recursive: true });
17119
17101
  }
@@ -17144,9 +17126,9 @@ function readConfigFromFile(directory) {
17144
17126
  return null;
17145
17127
  }
17146
17128
  }
17147
- function validateConfigKey(path17, value, _config) {
17129
+ function validateConfigKey(path16, value, _config) {
17148
17130
  const findings = [];
17149
- switch (path17) {
17131
+ switch (path16) {
17150
17132
  case "agents": {
17151
17133
  if (value !== undefined) {
17152
17134
  findings.push({
@@ -17393,27 +17375,27 @@ function validateConfigKey(path17, value, _config) {
17393
17375
  }
17394
17376
  return findings;
17395
17377
  }
17396
- function walkConfigAndValidate(obj, path17, config3, findings) {
17378
+ function walkConfigAndValidate(obj, path16, config3, findings) {
17397
17379
  if (obj === null || obj === undefined) {
17398
17380
  return;
17399
17381
  }
17400
- if (path17 && typeof obj === "object" && !Array.isArray(obj)) {
17401
- const keyFindings = validateConfigKey(path17, obj, config3);
17382
+ if (path16 && typeof obj === "object" && !Array.isArray(obj)) {
17383
+ const keyFindings = validateConfigKey(path16, obj, config3);
17402
17384
  findings.push(...keyFindings);
17403
17385
  }
17404
17386
  if (typeof obj !== "object") {
17405
- const keyFindings = validateConfigKey(path17, obj, config3);
17387
+ const keyFindings = validateConfigKey(path16, obj, config3);
17406
17388
  findings.push(...keyFindings);
17407
17389
  return;
17408
17390
  }
17409
17391
  if (Array.isArray(obj)) {
17410
17392
  obj.forEach((item, index) => {
17411
- walkConfigAndValidate(item, `${path17}[${index}]`, config3, findings);
17393
+ walkConfigAndValidate(item, `${path16}[${index}]`, config3, findings);
17412
17394
  });
17413
17395
  return;
17414
17396
  }
17415
17397
  for (const [key, value] of Object.entries(obj)) {
17416
- const newPath = path17 ? `${path17}.${key}` : key;
17398
+ const newPath = path16 ? `${path16}.${key}` : key;
17417
17399
  walkConfigAndValidate(value, newPath, config3, findings);
17418
17400
  }
17419
17401
  }
@@ -17533,7 +17515,7 @@ function applySafeAutoFixes(directory, result) {
17533
17515
  }
17534
17516
  }
17535
17517
  if (appliedFixes.length > 0) {
17536
- const configDir = path16.dirname(configPath);
17518
+ const configDir = path15.dirname(configPath);
17537
17519
  if (!fs7.existsSync(configDir)) {
17538
17520
  fs7.mkdirSync(configDir, { recursive: true });
17539
17521
  }
@@ -17543,12 +17525,12 @@ function applySafeAutoFixes(directory, result) {
17543
17525
  return { appliedFixes, updatedConfigPath };
17544
17526
  }
17545
17527
  function writeDoctorArtifact(directory, result) {
17546
- const swarmDir = path16.join(directory, ".swarm");
17528
+ const swarmDir = path15.join(directory, ".swarm");
17547
17529
  if (!fs7.existsSync(swarmDir)) {
17548
17530
  fs7.mkdirSync(swarmDir, { recursive: true });
17549
17531
  }
17550
17532
  const artifactFilename = "config-doctor.json";
17551
- const artifactPath = path16.join(swarmDir, artifactFilename);
17533
+ const artifactPath = path15.join(swarmDir, artifactFilename);
17552
17534
  const guiOutput = {
17553
17535
  timestamp: result.timestamp,
17554
17536
  summary: result.summary,
@@ -17909,8 +17891,8 @@ var init_evidence_summary_service = __esm(() => {
17909
17891
  });
17910
17892
 
17911
17893
  // src/cli/index.ts
17912
- import * as fs17 from "fs";
17913
- import * as os5 from "os";
17894
+ import * as fs18 from "fs";
17895
+ import * as os6 from "os";
17914
17896
  import * as path27 from "path";
17915
17897
 
17916
17898
  // src/commands/agents.ts
@@ -19241,7 +19223,7 @@ async function handleBenchmarkCommand(directory, args) {
19241
19223
  init_zod();
19242
19224
 
19243
19225
  // src/tools/checkpoint.ts
19244
- import { spawnSync } from "child_process";
19226
+ import * as child_process from "child_process";
19245
19227
  import * as fs3 from "fs";
19246
19228
  import * as path4 from "path";
19247
19229
 
@@ -31668,7 +31650,7 @@ function writeCheckpointLog(log2, directory) {
31668
31650
  fs3.renameSync(tempPath, logPath);
31669
31651
  }
31670
31652
  function gitExec(args) {
31671
- const result = spawnSync("git", args, {
31653
+ const result = child_process.spawnSync("git", args, {
31672
31654
  encoding: "utf-8",
31673
31655
  timeout: GIT_TIMEOUT_MS,
31674
31656
  stdio: ["pipe", "pipe", "pipe"]
@@ -32765,6 +32747,12 @@ async function flushPendingSnapshot(directory) {
32765
32747
  init_evidence_schema();
32766
32748
  init_manager();
32767
32749
  async function executeWriteRetro(args, directory) {
32750
+ if (/^(CON|PRN|AUX|NUL|COM[0-9]|LPT[0-9])(:|$)/i.test(directory)) {
32751
+ return JSON.stringify({
32752
+ success: false,
32753
+ message: "Invalid directory: reserved device name"
32754
+ }, null, 2);
32755
+ }
32768
32756
  const phase = args.phase;
32769
32757
  if (!Number.isInteger(phase) || phase < 1) {
32770
32758
  return JSON.stringify({
@@ -33249,9 +33237,6 @@ async function handleConfigCommand(directory, _args) {
33249
33237
  `);
33250
33238
  }
33251
33239
 
33252
- // src/hooks/hive-promoter.ts
33253
- import path12 from "path";
33254
-
33255
33240
  // src/background/event-bus.ts
33256
33241
  init_utils();
33257
33242
 
@@ -33473,86 +33458,6 @@ async function checkHivePromotions(swarmEntries, config3) {
33473
33458
  total_hive_entries: hiveEntries.length
33474
33459
  };
33475
33460
  }
33476
- async function promoteToHive(directory, lesson, category) {
33477
- const trimmedLesson = lesson.trim();
33478
- const hiveEntries = await readKnowledge(resolveHiveKnowledgePath());
33479
- const validationResult = validateLesson(trimmedLesson, hiveEntries.map((e) => e.lesson), {
33480
- category: category || "process",
33481
- scope: "global",
33482
- confidence: 1
33483
- });
33484
- if (validationResult.severity === "error") {
33485
- throw new Error(`Lesson rejected by validator: ${validationResult.reason}`);
33486
- }
33487
- if (findNearDuplicate(trimmedLesson, hiveEntries, 0.6)) {
33488
- return `Lesson already exists in hive (near-duplicate).`;
33489
- }
33490
- const newHiveEntry = {
33491
- id: crypto.randomUUID(),
33492
- tier: "hive",
33493
- lesson: trimmedLesson,
33494
- category: category || "process",
33495
- tags: [],
33496
- scope: "global",
33497
- confidence: 1,
33498
- status: "promoted",
33499
- confirmed_by: [],
33500
- retrieval_outcomes: {
33501
- applied_count: 0,
33502
- succeeded_after_count: 0,
33503
- failed_after_count: 0
33504
- },
33505
- schema_version: 1,
33506
- created_at: new Date().toISOString(),
33507
- updated_at: new Date().toISOString(),
33508
- source_project: path12.basename(directory) || "unknown",
33509
- encounter_score: 1
33510
- };
33511
- await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
33512
- return `Promoted to hive: "${trimmedLesson.slice(0, 50)}${trimmedLesson.length > 50 ? "..." : ""}" (confidence: 1.0, source: manual)`;
33513
- }
33514
- async function promoteFromSwarm(directory, lessonId) {
33515
- const swarmEntries = await readKnowledge(resolveSwarmKnowledgePath(directory));
33516
- const swarmEntry = swarmEntries.find((e) => e.id === lessonId);
33517
- if (!swarmEntry) {
33518
- throw new Error(`Lesson ${lessonId} not found in .swarm/knowledge.jsonl`);
33519
- }
33520
- const hiveEntries = await readKnowledge(resolveHiveKnowledgePath());
33521
- const validationResult = validateLesson(swarmEntry.lesson, hiveEntries.map((e) => e.lesson), {
33522
- category: swarmEntry.category,
33523
- scope: swarmEntry.scope,
33524
- confidence: swarmEntry.confidence
33525
- });
33526
- if (validationResult.severity === "error") {
33527
- throw new Error(`Lesson rejected by validator: ${validationResult.reason}`);
33528
- }
33529
- if (findNearDuplicate(swarmEntry.lesson, hiveEntries, 0.6)) {
33530
- return `Lesson already exists in hive (near-duplicate).`;
33531
- }
33532
- const newHiveEntry = {
33533
- id: crypto.randomUUID(),
33534
- tier: "hive",
33535
- lesson: swarmEntry.lesson,
33536
- category: swarmEntry.category,
33537
- tags: swarmEntry.tags,
33538
- scope: swarmEntry.scope,
33539
- confidence: 1,
33540
- status: "promoted",
33541
- confirmed_by: [],
33542
- retrieval_outcomes: {
33543
- applied_count: 0,
33544
- succeeded_after_count: 0,
33545
- failed_after_count: 0
33546
- },
33547
- schema_version: 1,
33548
- created_at: new Date().toISOString(),
33549
- updated_at: new Date().toISOString(),
33550
- source_project: swarmEntry.project_name,
33551
- encounter_score: 1
33552
- };
33553
- await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
33554
- return `Promoted lesson ${lessonId} from swarm to hive: "${swarmEntry.lesson.slice(0, 50)}${swarmEntry.lesson.length > 50 ? "..." : ""}"`;
33555
- }
33556
33461
 
33557
33462
  // src/commands/curate.ts
33558
33463
  async function handleCurateCommand(directory, _args) {
@@ -33583,16 +33488,16 @@ function formatCurationSummary(summary) {
33583
33488
  }
33584
33489
 
33585
33490
  // src/commands/dark-matter.ts
33586
- import path14 from "path";
33491
+ import path13 from "path";
33587
33492
 
33588
33493
  // src/tools/co-change-analyzer.ts
33589
- import * as child_process from "child_process";
33494
+ import * as child_process2 from "child_process";
33590
33495
  import { randomUUID } from "crypto";
33591
33496
  import { readdir, readFile as readFile2, stat } from "fs/promises";
33592
- import * as path13 from "path";
33497
+ import * as path12 from "path";
33593
33498
  import { promisify } from "util";
33594
33499
  function getExecFileAsync() {
33595
- return promisify(child_process.execFile);
33500
+ return promisify(child_process2.execFile);
33596
33501
  }
33597
33502
  async function parseGitLog(directory, maxCommits) {
33598
33503
  const commitMap = new Map;
@@ -33691,7 +33596,7 @@ async function scanSourceFiles(dir) {
33691
33596
  try {
33692
33597
  const entries = await readdir(dir, { withFileTypes: true });
33693
33598
  for (const entry of entries) {
33694
- const fullPath = path13.join(dir, entry.name);
33599
+ const fullPath = path12.join(dir, entry.name);
33695
33600
  if (entry.isDirectory()) {
33696
33601
  if (skipDirs.has(entry.name)) {
33697
33602
  continue;
@@ -33699,7 +33604,7 @@ async function scanSourceFiles(dir) {
33699
33604
  const subFiles = await scanSourceFiles(fullPath);
33700
33605
  results.push(...subFiles);
33701
33606
  } else if (entry.isFile()) {
33702
- const ext = path13.extname(entry.name);
33607
+ const ext = path12.extname(entry.name);
33703
33608
  if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
33704
33609
  results.push(fullPath);
33705
33610
  }
@@ -33721,8 +33626,8 @@ async function getStaticEdges(directory) {
33721
33626
  continue;
33722
33627
  }
33723
33628
  try {
33724
- const sourceDir = path13.dirname(sourceFile);
33725
- const resolvedPath = path13.resolve(sourceDir, importPath);
33629
+ const sourceDir = path12.dirname(sourceFile);
33630
+ const resolvedPath = path12.resolve(sourceDir, importPath);
33726
33631
  const extensions = [
33727
33632
  "",
33728
33633
  ".ts",
@@ -33747,8 +33652,8 @@ async function getStaticEdges(directory) {
33747
33652
  if (!targetFile) {
33748
33653
  continue;
33749
33654
  }
33750
- const relSource = path13.relative(directory, sourceFile).replace(/\\/g, "/");
33751
- const relTarget = path13.relative(directory, targetFile).replace(/\\/g, "/");
33655
+ const relSource = path12.relative(directory, sourceFile).replace(/\\/g, "/");
33656
+ const relTarget = path12.relative(directory, targetFile).replace(/\\/g, "/");
33752
33657
  const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
33753
33658
  edges.add(key);
33754
33659
  } catch {}
@@ -33760,7 +33665,7 @@ async function getStaticEdges(directory) {
33760
33665
  function isTestImplementationPair(fileA, fileB) {
33761
33666
  const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
33762
33667
  const getBaseName = (filePath) => {
33763
- const base = path13.basename(filePath);
33668
+ const base = path12.basename(filePath);
33764
33669
  for (const pattern of testPatterns) {
33765
33670
  if (base.endsWith(pattern)) {
33766
33671
  return base.slice(0, -pattern.length);
@@ -33770,16 +33675,16 @@ function isTestImplementationPair(fileA, fileB) {
33770
33675
  };
33771
33676
  const baseA = getBaseName(fileA);
33772
33677
  const baseB = getBaseName(fileB);
33773
- return baseA === baseB && baseA !== path13.basename(fileA) && baseA !== path13.basename(fileB);
33678
+ return baseA === baseB && baseA !== path12.basename(fileA) && baseA !== path12.basename(fileB);
33774
33679
  }
33775
33680
  function hasSharedPrefix(fileA, fileB) {
33776
- const dirA = path13.dirname(fileA);
33777
- const dirB = path13.dirname(fileB);
33681
+ const dirA = path12.dirname(fileA);
33682
+ const dirB = path12.dirname(fileB);
33778
33683
  if (dirA !== dirB) {
33779
33684
  return false;
33780
33685
  }
33781
- const baseA = path13.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
33782
- const baseB = path13.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
33686
+ const baseA = path12.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
33687
+ const baseB = path12.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
33783
33688
  if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
33784
33689
  return true;
33785
33690
  }
@@ -33833,8 +33738,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
33833
33738
  const entries = [];
33834
33739
  const now = new Date().toISOString();
33835
33740
  for (const pair of pairs.slice(0, 10)) {
33836
- const baseA = path13.basename(pair.fileA);
33837
- const baseB = path13.basename(pair.fileB);
33741
+ const baseA = path12.basename(pair.fileA);
33742
+ const baseB = path12.basename(pair.fileB);
33838
33743
  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.`;
33839
33744
  if (lesson.length > 280) {
33840
33745
  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.`;
@@ -33944,7 +33849,7 @@ async function handleDarkMatterCommand(directory, args) {
33944
33849
  const output = formatDarkMatterOutput(pairs);
33945
33850
  if (pairs.length > 0) {
33946
33851
  try {
33947
- const projectName = path14.basename(path14.resolve(directory));
33852
+ const projectName = path13.basename(path13.resolve(directory));
33948
33853
  const entries = darkMatterToKnowledgeEntries(pairs, projectName);
33949
33854
  if (entries.length > 0) {
33950
33855
  const knowledgePath = resolveSwarmKnowledgePath(directory);
@@ -33964,9 +33869,9 @@ async function handleDarkMatterCommand(directory, args) {
33964
33869
  }
33965
33870
 
33966
33871
  // src/services/diagnose-service.ts
33967
- import { execSync } from "child_process";
33872
+ import * as child_process3 from "child_process";
33968
33873
  import { existsSync as existsSync5, readdirSync as readdirSync2, readFileSync as readFileSync5, statSync as statSync3 } from "fs";
33969
- import path15 from "path";
33874
+ import path14 from "path";
33970
33875
  import { fileURLToPath } from "url";
33971
33876
  init_manager();
33972
33877
  init_utils2();
@@ -34209,7 +34114,10 @@ async function checkGitRepository(directory) {
34209
34114
  detail: "Invalid directory \u2014 cannot check git status"
34210
34115
  };
34211
34116
  }
34212
- execSync("git rev-parse --git-dir", { cwd: directory, stdio: "pipe" });
34117
+ child_process3.execSync("git rev-parse --git-dir", {
34118
+ cwd: directory,
34119
+ stdio: "pipe"
34120
+ });
34213
34121
  return {
34214
34122
  name: "Git Repository",
34215
34123
  status: "\u2705",
@@ -34263,7 +34171,7 @@ async function checkSpecStaleness(directory, plan) {
34263
34171
  };
34264
34172
  }
34265
34173
  async function checkConfigParseability(directory) {
34266
- const configPath = path15.join(directory, ".opencode/opencode-swarm.json");
34174
+ const configPath = path14.join(directory, ".opencode/opencode-swarm.json");
34267
34175
  if (!existsSync5(configPath)) {
34268
34176
  return {
34269
34177
  name: "Config Parseability",
@@ -34310,15 +34218,15 @@ async function checkGrammarWasmFiles() {
34310
34218
  "tree-sitter-ini.wasm",
34311
34219
  "tree-sitter-regex.wasm"
34312
34220
  ];
34313
- const thisDir = path15.dirname(fileURLToPath(import.meta.url));
34221
+ const thisDir = path14.dirname(fileURLToPath(import.meta.url));
34314
34222
  const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/services");
34315
- const grammarDir = isSource ? path15.join(thisDir, "..", "lang", "grammars") : path15.join(thisDir, "lang", "grammars");
34223
+ const grammarDir = isSource ? path14.join(thisDir, "..", "lang", "grammars") : path14.join(thisDir, "lang", "grammars");
34316
34224
  const missing = [];
34317
- if (!existsSync5(path15.join(grammarDir, "tree-sitter.wasm"))) {
34225
+ if (!existsSync5(path14.join(grammarDir, "tree-sitter.wasm"))) {
34318
34226
  missing.push("tree-sitter.wasm (core runtime)");
34319
34227
  }
34320
34228
  for (const file3 of grammarFiles) {
34321
- if (!existsSync5(path15.join(grammarDir, file3))) {
34229
+ if (!existsSync5(path14.join(grammarDir, file3))) {
34322
34230
  missing.push(file3);
34323
34231
  }
34324
34232
  }
@@ -34336,7 +34244,7 @@ async function checkGrammarWasmFiles() {
34336
34244
  };
34337
34245
  }
34338
34246
  async function checkCheckpointManifest(directory) {
34339
- const manifestPath = path15.join(directory, ".swarm/checkpoints.json");
34247
+ const manifestPath = path14.join(directory, ".swarm/checkpoints.json");
34340
34248
  if (!existsSync5(manifestPath)) {
34341
34249
  return {
34342
34250
  name: "Checkpoint Manifest",
@@ -34388,7 +34296,7 @@ async function checkCheckpointManifest(directory) {
34388
34296
  }
34389
34297
  }
34390
34298
  async function checkEventStreamIntegrity(directory) {
34391
- const eventsPath = path15.join(directory, ".swarm/events.jsonl");
34299
+ const eventsPath = path14.join(directory, ".swarm/events.jsonl");
34392
34300
  if (!existsSync5(eventsPath)) {
34393
34301
  return {
34394
34302
  name: "Event Stream",
@@ -34429,7 +34337,7 @@ async function checkEventStreamIntegrity(directory) {
34429
34337
  }
34430
34338
  }
34431
34339
  async function checkSteeringDirectives(directory) {
34432
- const eventsPath = path15.join(directory, ".swarm/events.jsonl");
34340
+ const eventsPath = path14.join(directory, ".swarm/events.jsonl");
34433
34341
  if (!existsSync5(eventsPath)) {
34434
34342
  return {
34435
34343
  name: "Steering Directives",
@@ -34485,7 +34393,7 @@ async function checkCurator(directory) {
34485
34393
  detail: "Disabled (enable via curator.enabled)"
34486
34394
  };
34487
34395
  }
34488
- const summaryPath = path15.join(directory, ".swarm/curator-summary.json");
34396
+ const summaryPath = path14.join(directory, ".swarm/curator-summary.json");
34489
34397
  if (!existsSync5(summaryPath)) {
34490
34398
  return {
34491
34399
  name: "Curator",
@@ -35382,10 +35290,10 @@ async function handleHistoryCommand(directory, _args) {
35382
35290
  import { randomUUID as randomUUID2 } from "crypto";
35383
35291
  import { existsSync as existsSync7, readFileSync as readFileSync7 } from "fs";
35384
35292
  import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
35385
- import * as path17 from "path";
35293
+ import * as path16 from "path";
35386
35294
  async function migrateContextToKnowledge(directory, config3) {
35387
- const sentinelPath = path17.join(directory, ".swarm", ".knowledge-migrated");
35388
- const contextPath = path17.join(directory, ".swarm", "context.md");
35295
+ const sentinelPath = path16.join(directory, ".swarm", ".knowledge-migrated");
35296
+ const contextPath = path16.join(directory, ".swarm", "context.md");
35389
35297
  const knowledgePath = resolveSwarmKnowledgePath(directory);
35390
35298
  if (existsSync7(sentinelPath)) {
35391
35299
  return {
@@ -35581,7 +35489,7 @@ function truncateLesson(text) {
35581
35489
  return `${text.slice(0, 277)}...`;
35582
35490
  }
35583
35491
  function inferProjectName(directory) {
35584
- const packageJsonPath = path17.join(directory, "package.json");
35492
+ const packageJsonPath = path16.join(directory, "package.json");
35585
35493
  if (existsSync7(packageJsonPath)) {
35586
35494
  try {
35587
35495
  const pkg = JSON.parse(readFileSync7(packageJsonPath, "utf-8"));
@@ -35590,7 +35498,7 @@ function inferProjectName(directory) {
35590
35498
  }
35591
35499
  } catch {}
35592
35500
  }
35593
- return path17.basename(directory);
35501
+ return path16.basename(directory);
35594
35502
  }
35595
35503
  async function writeSentinel(sentinelPath, migrated, dropped) {
35596
35504
  const sentinel = {
@@ -35602,7 +35510,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
35602
35510
  schema_version: 1,
35603
35511
  migration_tool: "knowledge-migrator.ts"
35604
35512
  };
35605
- await mkdir3(path17.dirname(sentinelPath), { recursive: true });
35513
+ await mkdir3(path16.dirname(sentinelPath), { recursive: true });
35606
35514
  await writeFile3(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
35607
35515
  }
35608
35516
 
@@ -35839,15 +35747,15 @@ async function handlePlanCommand(directory, args) {
35839
35747
  init_manager();
35840
35748
  init_manager2();
35841
35749
  import * as fs13 from "fs";
35842
- import * as path23 from "path";
35750
+ import * as path22 from "path";
35843
35751
 
35844
35752
  // src/tools/lint.ts
35845
35753
  import * as fs9 from "fs";
35846
- import * as path19 from "path";
35754
+ import * as path18 from "path";
35847
35755
 
35848
35756
  // src/build/discovery.ts
35849
35757
  import * as fs8 from "fs";
35850
- import * as path18 from "path";
35758
+ import * as path17 from "path";
35851
35759
 
35852
35760
  // src/lang/detector.ts
35853
35761
  import { access, readdir as readdir2 } from "fs/promises";
@@ -36944,11 +36852,11 @@ function findBuildFiles(workingDir, patterns) {
36944
36852
  const regex = simpleGlobToRegex(pattern);
36945
36853
  const matches = files.filter((f) => regex.test(f));
36946
36854
  if (matches.length > 0) {
36947
- return path18.join(dir, matches[0]);
36855
+ return path17.join(dir, matches[0]);
36948
36856
  }
36949
36857
  } catch {}
36950
36858
  } else {
36951
- const filePath = path18.join(workingDir, pattern);
36859
+ const filePath = path17.join(workingDir, pattern);
36952
36860
  if (fs8.existsSync(filePath)) {
36953
36861
  return filePath;
36954
36862
  }
@@ -36957,7 +36865,7 @@ function findBuildFiles(workingDir, patterns) {
36957
36865
  return null;
36958
36866
  }
36959
36867
  function getRepoDefinedScripts(workingDir, scripts) {
36960
- const packageJsonPath = path18.join(workingDir, "package.json");
36868
+ const packageJsonPath = path17.join(workingDir, "package.json");
36961
36869
  if (!fs8.existsSync(packageJsonPath)) {
36962
36870
  return [];
36963
36871
  }
@@ -36998,7 +36906,7 @@ function findAllBuildFiles(workingDir) {
36998
36906
  const regex = simpleGlobToRegex(pattern);
36999
36907
  findFilesRecursive(workingDir, regex, allBuildFiles);
37000
36908
  } else {
37001
- const filePath = path18.join(workingDir, pattern);
36909
+ const filePath = path17.join(workingDir, pattern);
37002
36910
  if (fs8.existsSync(filePath)) {
37003
36911
  allBuildFiles.add(filePath);
37004
36912
  }
@@ -37011,7 +36919,7 @@ function findFilesRecursive(dir, regex, results) {
37011
36919
  try {
37012
36920
  const entries = fs8.readdirSync(dir, { withFileTypes: true });
37013
36921
  for (const entry of entries) {
37014
- const fullPath = path18.join(dir, entry.name);
36922
+ const fullPath = path17.join(dir, entry.name);
37015
36923
  if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
37016
36924
  findFilesRecursive(fullPath, regex, results);
37017
36925
  } else if (entry.isFile() && regex.test(entry.name)) {
@@ -37034,7 +36942,7 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
37034
36942
  let foundCommand = false;
37035
36943
  for (const cmd of sortedCommands) {
37036
36944
  if (cmd.detectFile) {
37037
- const detectFilePath = path18.join(workingDir, cmd.detectFile);
36945
+ const detectFilePath = path17.join(workingDir, cmd.detectFile);
37038
36946
  if (!fs8.existsSync(detectFilePath)) {
37039
36947
  continue;
37040
36948
  }
@@ -37182,9 +37090,9 @@ function validateArgs(args) {
37182
37090
  }
37183
37091
  function getLinterCommand(linter, mode, projectDir) {
37184
37092
  const isWindows = process.platform === "win32";
37185
- const binDir = path19.join(projectDir, "node_modules", ".bin");
37186
- const biomeBin = isWindows ? path19.join(binDir, "biome.EXE") : path19.join(binDir, "biome");
37187
- const eslintBin = isWindows ? path19.join(binDir, "eslint.cmd") : path19.join(binDir, "eslint");
37093
+ const binDir = path18.join(projectDir, "node_modules", ".bin");
37094
+ const biomeBin = isWindows ? path18.join(binDir, "biome.EXE") : path18.join(binDir, "biome");
37095
+ const eslintBin = isWindows ? path18.join(binDir, "eslint.cmd") : path18.join(binDir, "eslint");
37188
37096
  switch (linter) {
37189
37097
  case "biome":
37190
37098
  if (mode === "fix") {
@@ -37200,7 +37108,7 @@ function getLinterCommand(linter, mode, projectDir) {
37200
37108
  }
37201
37109
  function getAdditionalLinterCommand(linter, mode, cwd) {
37202
37110
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
37203
- const gradlew = fs9.existsSync(path19.join(cwd, gradlewName)) ? path19.join(cwd, gradlewName) : null;
37111
+ const gradlew = fs9.existsSync(path18.join(cwd, gradlewName)) ? path18.join(cwd, gradlewName) : null;
37204
37112
  switch (linter) {
37205
37113
  case "ruff":
37206
37114
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -37234,10 +37142,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
37234
37142
  }
37235
37143
  }
37236
37144
  function detectRuff(cwd) {
37237
- if (fs9.existsSync(path19.join(cwd, "ruff.toml")))
37145
+ if (fs9.existsSync(path18.join(cwd, "ruff.toml")))
37238
37146
  return isCommandAvailable("ruff");
37239
37147
  try {
37240
- const pyproject = path19.join(cwd, "pyproject.toml");
37148
+ const pyproject = path18.join(cwd, "pyproject.toml");
37241
37149
  if (fs9.existsSync(pyproject)) {
37242
37150
  const content = fs9.readFileSync(pyproject, "utf-8");
37243
37151
  if (content.includes("[tool.ruff]"))
@@ -37247,19 +37155,19 @@ function detectRuff(cwd) {
37247
37155
  return false;
37248
37156
  }
37249
37157
  function detectClippy(cwd) {
37250
- return fs9.existsSync(path19.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
37158
+ return fs9.existsSync(path18.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
37251
37159
  }
37252
37160
  function detectGolangciLint(cwd) {
37253
- return fs9.existsSync(path19.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
37161
+ return fs9.existsSync(path18.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
37254
37162
  }
37255
37163
  function detectCheckstyle(cwd) {
37256
- const hasMaven = fs9.existsSync(path19.join(cwd, "pom.xml"));
37257
- const hasGradle = fs9.existsSync(path19.join(cwd, "build.gradle")) || fs9.existsSync(path19.join(cwd, "build.gradle.kts"));
37258
- const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs9.existsSync(path19.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
37164
+ const hasMaven = fs9.existsSync(path18.join(cwd, "pom.xml"));
37165
+ const hasGradle = fs9.existsSync(path18.join(cwd, "build.gradle")) || fs9.existsSync(path18.join(cwd, "build.gradle.kts"));
37166
+ const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs9.existsSync(path18.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
37259
37167
  return (hasMaven || hasGradle) && hasBinary;
37260
37168
  }
37261
37169
  function detectKtlint(cwd) {
37262
- const hasKotlin = fs9.existsSync(path19.join(cwd, "build.gradle.kts")) || fs9.existsSync(path19.join(cwd, "build.gradle")) || (() => {
37170
+ const hasKotlin = fs9.existsSync(path18.join(cwd, "build.gradle.kts")) || fs9.existsSync(path18.join(cwd, "build.gradle")) || (() => {
37263
37171
  try {
37264
37172
  return fs9.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
37265
37173
  } catch {
@@ -37278,11 +37186,11 @@ function detectDotnetFormat(cwd) {
37278
37186
  }
37279
37187
  }
37280
37188
  function detectCppcheck(cwd) {
37281
- if (fs9.existsSync(path19.join(cwd, "CMakeLists.txt"))) {
37189
+ if (fs9.existsSync(path18.join(cwd, "CMakeLists.txt"))) {
37282
37190
  return isCommandAvailable("cppcheck");
37283
37191
  }
37284
37192
  try {
37285
- const dirsToCheck = [cwd, path19.join(cwd, "src")];
37193
+ const dirsToCheck = [cwd, path18.join(cwd, "src")];
37286
37194
  const hasCpp = dirsToCheck.some((dir) => {
37287
37195
  try {
37288
37196
  return fs9.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
@@ -37296,13 +37204,13 @@ function detectCppcheck(cwd) {
37296
37204
  }
37297
37205
  }
37298
37206
  function detectSwiftlint(cwd) {
37299
- return fs9.existsSync(path19.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
37207
+ return fs9.existsSync(path18.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
37300
37208
  }
37301
37209
  function detectDartAnalyze(cwd) {
37302
- return fs9.existsSync(path19.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
37210
+ return fs9.existsSync(path18.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
37303
37211
  }
37304
37212
  function detectRubocop(cwd) {
37305
- 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"));
37213
+ 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"));
37306
37214
  }
37307
37215
  function detectAdditionalLinter(cwd) {
37308
37216
  if (detectRuff(cwd))
@@ -37327,17 +37235,53 @@ function detectAdditionalLinter(cwd) {
37327
37235
  return "rubocop";
37328
37236
  return null;
37329
37237
  }
37238
+ function findBinInAncestors(startDir, binName) {
37239
+ let dir = startDir;
37240
+ while (true) {
37241
+ const candidate = path18.join(dir, "node_modules", ".bin", binName);
37242
+ if (fs9.existsSync(candidate))
37243
+ return candidate;
37244
+ const parent = path18.dirname(dir);
37245
+ if (parent === dir)
37246
+ break;
37247
+ dir = parent;
37248
+ }
37249
+ return null;
37250
+ }
37251
+ function findBinInEnvPath(binName) {
37252
+ const searchPath = process.env.PATH ?? "";
37253
+ for (const dir of searchPath.split(path18.delimiter)) {
37254
+ if (!dir)
37255
+ continue;
37256
+ const candidate = path18.join(dir, binName);
37257
+ if (fs9.existsSync(candidate))
37258
+ return candidate;
37259
+ }
37260
+ return null;
37261
+ }
37330
37262
  async function detectAvailableLinter(directory) {
37331
- const _DETECT_TIMEOUT = 2000;
37332
37263
  if (!directory)
37333
37264
  return null;
37334
37265
  if (!fs9.existsSync(directory))
37335
37266
  return null;
37336
37267
  const projectDir = directory;
37337
37268
  const isWindows = process.platform === "win32";
37338
- const biomeBin = isWindows ? path19.join(projectDir, "node_modules", ".bin", "biome.EXE") : path19.join(projectDir, "node_modules", ".bin", "biome");
37339
- const eslintBin = isWindows ? path19.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path19.join(projectDir, "node_modules", ".bin", "eslint");
37340
- return _detectAvailableLinter(projectDir, biomeBin, eslintBin);
37269
+ const biomeBin = isWindows ? path18.join(projectDir, "node_modules", ".bin", "biome.EXE") : path18.join(projectDir, "node_modules", ".bin", "biome");
37270
+ const eslintBin = isWindows ? path18.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path18.join(projectDir, "node_modules", ".bin", "eslint");
37271
+ const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
37272
+ if (localResult)
37273
+ return localResult;
37274
+ const biomeAncestor = findBinInAncestors(path18.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
37275
+ const eslintAncestor = findBinInAncestors(path18.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
37276
+ if (biomeAncestor || eslintAncestor) {
37277
+ return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
37278
+ }
37279
+ const pathBiome = findBinInEnvPath(isWindows ? "biome.EXE" : "biome");
37280
+ const pathEslint = findBinInEnvPath(isWindows ? "eslint.cmd" : "eslint");
37281
+ if (pathBiome || pathEslint) {
37282
+ return _detectAvailableLinter(projectDir, pathBiome ?? biomeBin, pathEslint ?? eslintBin);
37283
+ }
37284
+ return null;
37341
37285
  }
37342
37286
  async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
37343
37287
  const DETECT_TIMEOUT = 2000;
@@ -37536,7 +37480,7 @@ For Rust: rustup component add clippy`
37536
37480
 
37537
37481
  // src/tools/secretscan.ts
37538
37482
  import * as fs10 from "fs";
37539
- import * as path20 from "path";
37483
+ import * as path19 from "path";
37540
37484
  var MAX_FILE_PATH_LENGTH = 500;
37541
37485
  var MAX_FILE_SIZE_BYTES = 512 * 1024;
37542
37486
  var MAX_FILES_SCANNED = 1000;
@@ -37763,7 +37707,7 @@ function isGlobOrPathPattern(pattern) {
37763
37707
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
37764
37708
  }
37765
37709
  function loadSecretScanIgnore(scanDir) {
37766
- const ignorePath = path20.join(scanDir, ".secretscanignore");
37710
+ const ignorePath = path19.join(scanDir, ".secretscanignore");
37767
37711
  try {
37768
37712
  if (!fs10.existsSync(ignorePath))
37769
37713
  return [];
@@ -37786,7 +37730,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
37786
37730
  if (exactNames.has(entry))
37787
37731
  return true;
37788
37732
  for (const pattern of globPatterns) {
37789
- if (path20.matchesGlob(relPath, pattern))
37733
+ if (path19.matchesGlob(relPath, pattern))
37790
37734
  return true;
37791
37735
  }
37792
37736
  return false;
@@ -37807,7 +37751,7 @@ function validateDirectoryInput(dir) {
37807
37751
  return null;
37808
37752
  }
37809
37753
  function isBinaryFile(filePath, buffer) {
37810
- const ext = path20.extname(filePath).toLowerCase();
37754
+ const ext = path19.extname(filePath).toLowerCase();
37811
37755
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
37812
37756
  return true;
37813
37757
  }
@@ -37944,9 +37888,9 @@ function isSymlinkLoop(realPath, visited) {
37944
37888
  return false;
37945
37889
  }
37946
37890
  function isPathWithinScope(realPath, scanDir) {
37947
- const resolvedScanDir = path20.resolve(scanDir);
37948
- const resolvedRealPath = path20.resolve(realPath);
37949
- return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path20.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
37891
+ const resolvedScanDir = path19.resolve(scanDir);
37892
+ const resolvedRealPath = path19.resolve(realPath);
37893
+ return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path19.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
37950
37894
  }
37951
37895
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
37952
37896
  skippedDirs: 0,
@@ -37972,8 +37916,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
37972
37916
  return a.localeCompare(b);
37973
37917
  });
37974
37918
  for (const entry of entries) {
37975
- const fullPath = path20.join(dir, entry);
37976
- const relPath = path20.relative(scanDir, fullPath).replace(/\\/g, "/");
37919
+ const fullPath = path19.join(dir, entry);
37920
+ const relPath = path19.relative(scanDir, fullPath).replace(/\\/g, "/");
37977
37921
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
37978
37922
  stats.skippedDirs++;
37979
37923
  continue;
@@ -38008,7 +37952,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
38008
37952
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
38009
37953
  files.push(...subFiles);
38010
37954
  } else if (lstat.isFile()) {
38011
- const ext = path20.extname(fullPath).toLowerCase();
37955
+ const ext = path19.extname(fullPath).toLowerCase();
38012
37956
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
38013
37957
  files.push(fullPath);
38014
37958
  } else {
@@ -38074,7 +38018,14 @@ var secretscan = createSwarmTool({
38074
38018
  }
38075
38019
  }
38076
38020
  try {
38077
- const scanDir = path20.resolve(directory);
38021
+ const _scanDirRaw = path19.resolve(directory);
38022
+ const scanDir = (() => {
38023
+ try {
38024
+ return fs10.realpathSync(_scanDirRaw);
38025
+ } catch {
38026
+ return _scanDirRaw;
38027
+ }
38028
+ })();
38078
38029
  if (!fs10.existsSync(scanDir)) {
38079
38030
  const errorResult = {
38080
38031
  error: "directory not found",
@@ -38225,11 +38176,11 @@ async function runSecretscan(directory) {
38225
38176
 
38226
38177
  // src/tools/test-runner.ts
38227
38178
  import * as fs12 from "fs";
38228
- import * as path22 from "path";
38179
+ import * as path21 from "path";
38229
38180
 
38230
38181
  // src/tools/resolve-working-directory.ts
38231
38182
  import * as fs11 from "fs";
38232
- import * as path21 from "path";
38183
+ import * as path20 from "path";
38233
38184
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
38234
38185
  if (workingDirectory == null || workingDirectory === "") {
38235
38186
  return { success: true, directory: fallbackDirectory };
@@ -38249,15 +38200,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
38249
38200
  };
38250
38201
  }
38251
38202
  }
38252
- const normalizedDir = path21.normalize(workingDirectory);
38253
- const pathParts = normalizedDir.split(path21.sep);
38203
+ const normalizedDir = path20.normalize(workingDirectory);
38204
+ const pathParts = normalizedDir.split(path20.sep);
38254
38205
  if (pathParts.includes("..")) {
38255
38206
  return {
38256
38207
  success: false,
38257
38208
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
38258
38209
  };
38259
38210
  }
38260
- const resolvedDir = path21.resolve(normalizedDir);
38211
+ const resolvedDir = path20.resolve(normalizedDir);
38261
38212
  try {
38262
38213
  const realPath = fs11.realpathSync(resolvedDir);
38263
38214
  return { success: true, directory: realPath };
@@ -38340,14 +38291,14 @@ function hasDevDependency(devDeps, ...patterns) {
38340
38291
  return hasPackageJsonDependency(devDeps, ...patterns);
38341
38292
  }
38342
38293
  function detectGoTest(cwd) {
38343
- return fs12.existsSync(path22.join(cwd, "go.mod")) && isCommandAvailable("go");
38294
+ return fs12.existsSync(path21.join(cwd, "go.mod")) && isCommandAvailable("go");
38344
38295
  }
38345
38296
  function detectJavaMaven(cwd) {
38346
- return fs12.existsSync(path22.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
38297
+ return fs12.existsSync(path21.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
38347
38298
  }
38348
38299
  function detectGradle(cwd) {
38349
- const hasBuildFile = fs12.existsSync(path22.join(cwd, "build.gradle")) || fs12.existsSync(path22.join(cwd, "build.gradle.kts"));
38350
- const hasGradlew = fs12.existsSync(path22.join(cwd, "gradlew")) || fs12.existsSync(path22.join(cwd, "gradlew.bat"));
38300
+ const hasBuildFile = fs12.existsSync(path21.join(cwd, "build.gradle")) || fs12.existsSync(path21.join(cwd, "build.gradle.kts"));
38301
+ const hasGradlew = fs12.existsSync(path21.join(cwd, "gradlew")) || fs12.existsSync(path21.join(cwd, "gradlew.bat"));
38351
38302
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
38352
38303
  }
38353
38304
  function detectDotnetTest(cwd) {
@@ -38360,30 +38311,30 @@ function detectDotnetTest(cwd) {
38360
38311
  }
38361
38312
  }
38362
38313
  function detectCTest(cwd) {
38363
- const hasSource = fs12.existsSync(path22.join(cwd, "CMakeLists.txt"));
38364
- const hasBuildCache = fs12.existsSync(path22.join(cwd, "CMakeCache.txt")) || fs12.existsSync(path22.join(cwd, "build", "CMakeCache.txt"));
38314
+ const hasSource = fs12.existsSync(path21.join(cwd, "CMakeLists.txt"));
38315
+ const hasBuildCache = fs12.existsSync(path21.join(cwd, "CMakeCache.txt")) || fs12.existsSync(path21.join(cwd, "build", "CMakeCache.txt"));
38365
38316
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
38366
38317
  }
38367
38318
  function detectSwiftTest(cwd) {
38368
- return fs12.existsSync(path22.join(cwd, "Package.swift")) && isCommandAvailable("swift");
38319
+ return fs12.existsSync(path21.join(cwd, "Package.swift")) && isCommandAvailable("swift");
38369
38320
  }
38370
38321
  function detectDartTest(cwd) {
38371
- return fs12.existsSync(path22.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
38322
+ return fs12.existsSync(path21.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
38372
38323
  }
38373
38324
  function detectRSpec(cwd) {
38374
- const hasRSpecFile = fs12.existsSync(path22.join(cwd, ".rspec"));
38375
- const hasGemfile = fs12.existsSync(path22.join(cwd, "Gemfile"));
38376
- const hasSpecDir = fs12.existsSync(path22.join(cwd, "spec"));
38325
+ const hasRSpecFile = fs12.existsSync(path21.join(cwd, ".rspec"));
38326
+ const hasGemfile = fs12.existsSync(path21.join(cwd, "Gemfile"));
38327
+ const hasSpecDir = fs12.existsSync(path21.join(cwd, "spec"));
38377
38328
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
38378
38329
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
38379
38330
  }
38380
38331
  function detectMinitest(cwd) {
38381
- return fs12.existsSync(path22.join(cwd, "test")) && (fs12.existsSync(path22.join(cwd, "Gemfile")) || fs12.existsSync(path22.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
38332
+ return fs12.existsSync(path21.join(cwd, "test")) && (fs12.existsSync(path21.join(cwd, "Gemfile")) || fs12.existsSync(path21.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
38382
38333
  }
38383
38334
  async function detectTestFramework(cwd) {
38384
38335
  const baseDir = cwd;
38385
38336
  try {
38386
- const packageJsonPath = path22.join(baseDir, "package.json");
38337
+ const packageJsonPath = path21.join(baseDir, "package.json");
38387
38338
  if (fs12.existsSync(packageJsonPath)) {
38388
38339
  const content = fs12.readFileSync(packageJsonPath, "utf-8");
38389
38340
  const pkg = JSON.parse(content);
@@ -38404,16 +38355,16 @@ async function detectTestFramework(cwd) {
38404
38355
  return "jest";
38405
38356
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
38406
38357
  return "mocha";
38407
- if (fs12.existsSync(path22.join(baseDir, "bun.lockb")) || fs12.existsSync(path22.join(baseDir, "bun.lock"))) {
38358
+ if (fs12.existsSync(path21.join(baseDir, "bun.lockb")) || fs12.existsSync(path21.join(baseDir, "bun.lock"))) {
38408
38359
  if (scripts.test?.includes("bun"))
38409
38360
  return "bun";
38410
38361
  }
38411
38362
  }
38412
38363
  } catch {}
38413
38364
  try {
38414
- const pyprojectTomlPath = path22.join(baseDir, "pyproject.toml");
38415
- const setupCfgPath = path22.join(baseDir, "setup.cfg");
38416
- const requirementsTxtPath = path22.join(baseDir, "requirements.txt");
38365
+ const pyprojectTomlPath = path21.join(baseDir, "pyproject.toml");
38366
+ const setupCfgPath = path21.join(baseDir, "setup.cfg");
38367
+ const requirementsTxtPath = path21.join(baseDir, "requirements.txt");
38417
38368
  if (fs12.existsSync(pyprojectTomlPath)) {
38418
38369
  const content = fs12.readFileSync(pyprojectTomlPath, "utf-8");
38419
38370
  if (content.includes("[tool.pytest"))
@@ -38433,7 +38384,7 @@ async function detectTestFramework(cwd) {
38433
38384
  }
38434
38385
  } catch {}
38435
38386
  try {
38436
- const cargoTomlPath = path22.join(baseDir, "Cargo.toml");
38387
+ const cargoTomlPath = path21.join(baseDir, "Cargo.toml");
38437
38388
  if (fs12.existsSync(cargoTomlPath)) {
38438
38389
  const content = fs12.readFileSync(cargoTomlPath, "utf-8");
38439
38390
  if (content.includes("[dev-dependencies]")) {
@@ -38444,9 +38395,9 @@ async function detectTestFramework(cwd) {
38444
38395
  }
38445
38396
  } catch {}
38446
38397
  try {
38447
- const pesterConfigPath = path22.join(baseDir, "pester.config.ps1");
38448
- const pesterConfigJsonPath = path22.join(baseDir, "pester.config.ps1.json");
38449
- const pesterPs1Path = path22.join(baseDir, "tests.ps1");
38398
+ const pesterConfigPath = path21.join(baseDir, "pester.config.ps1");
38399
+ const pesterConfigJsonPath = path21.join(baseDir, "pester.config.ps1.json");
38400
+ const pesterPs1Path = path21.join(baseDir, "tests.ps1");
38450
38401
  if (fs12.existsSync(pesterConfigPath) || fs12.existsSync(pesterConfigJsonPath) || fs12.existsSync(pesterPs1Path)) {
38451
38402
  return "pester";
38452
38403
  }
@@ -38498,8 +38449,8 @@ function getTestFilesFromConvention(sourceFiles) {
38498
38449
  const testFiles = [];
38499
38450
  for (const file3 of sourceFiles) {
38500
38451
  const normalizedPath = file3.replace(/\\/g, "/");
38501
- const basename4 = path22.basename(file3);
38502
- const dirname9 = path22.dirname(file3);
38452
+ const basename4 = path21.basename(file3);
38453
+ const dirname10 = path21.dirname(file3);
38503
38454
  if (hasCompoundTestExtension(basename4) || basename4.includes(".spec.") || basename4.includes(".test.") || normalizedPath.includes("/__tests__/") || normalizedPath.includes("/tests/") || normalizedPath.includes("/test/")) {
38504
38455
  if (!testFiles.includes(file3)) {
38505
38456
  testFiles.push(file3);
@@ -38508,13 +38459,13 @@ function getTestFilesFromConvention(sourceFiles) {
38508
38459
  }
38509
38460
  for (const _pattern of TEST_PATTERNS) {
38510
38461
  const nameWithoutExt = basename4.replace(/\.[^.]+$/, "");
38511
- const ext = path22.extname(basename4);
38462
+ const ext = path21.extname(basename4);
38512
38463
  const possibleTestFiles = [
38513
- path22.join(dirname9, `${nameWithoutExt}.spec${ext}`),
38514
- path22.join(dirname9, `${nameWithoutExt}.test${ext}`),
38515
- path22.join(dirname9, "__tests__", `${nameWithoutExt}${ext}`),
38516
- path22.join(dirname9, "tests", `${nameWithoutExt}${ext}`),
38517
- path22.join(dirname9, "test", `${nameWithoutExt}${ext}`)
38464
+ path21.join(dirname10, `${nameWithoutExt}.spec${ext}`),
38465
+ path21.join(dirname10, `${nameWithoutExt}.test${ext}`),
38466
+ path21.join(dirname10, "__tests__", `${nameWithoutExt}${ext}`),
38467
+ path21.join(dirname10, "tests", `${nameWithoutExt}${ext}`),
38468
+ path21.join(dirname10, "test", `${nameWithoutExt}${ext}`)
38518
38469
  ];
38519
38470
  for (const testFile of possibleTestFiles) {
38520
38471
  if (fs12.existsSync(testFile) && !testFiles.includes(testFile)) {
@@ -38534,7 +38485,7 @@ async function getTestFilesFromGraph(sourceFiles) {
38534
38485
  for (const testFile of candidateTestFiles) {
38535
38486
  try {
38536
38487
  const content = fs12.readFileSync(testFile, "utf-8");
38537
- const testDir = path22.dirname(testFile);
38488
+ const testDir = path21.dirname(testFile);
38538
38489
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
38539
38490
  let match;
38540
38491
  match = importRegex.exec(content);
@@ -38542,8 +38493,8 @@ async function getTestFilesFromGraph(sourceFiles) {
38542
38493
  const importPath = match[1];
38543
38494
  let resolvedImport;
38544
38495
  if (importPath.startsWith(".")) {
38545
- resolvedImport = path22.resolve(testDir, importPath);
38546
- const existingExt = path22.extname(resolvedImport);
38496
+ resolvedImport = path21.resolve(testDir, importPath);
38497
+ const existingExt = path21.extname(resolvedImport);
38547
38498
  if (!existingExt) {
38548
38499
  for (const extToTry of [
38549
38500
  ".ts",
@@ -38563,12 +38514,12 @@ async function getTestFilesFromGraph(sourceFiles) {
38563
38514
  } else {
38564
38515
  continue;
38565
38516
  }
38566
- const importBasename = path22.basename(resolvedImport, path22.extname(resolvedImport));
38567
- const importDir = path22.dirname(resolvedImport);
38517
+ const importBasename = path21.basename(resolvedImport, path21.extname(resolvedImport));
38518
+ const importDir = path21.dirname(resolvedImport);
38568
38519
  for (const sourceFile of sourceFiles) {
38569
- const sourceDir = path22.dirname(sourceFile);
38570
- const sourceBasename = path22.basename(sourceFile, path22.extname(sourceFile));
38571
- const isRelatedDir = importDir === sourceDir || importDir === path22.join(sourceDir, "__tests__") || importDir === path22.join(sourceDir, "tests") || importDir === path22.join(sourceDir, "test");
38520
+ const sourceDir = path21.dirname(sourceFile);
38521
+ const sourceBasename = path21.basename(sourceFile, path21.extname(sourceFile));
38522
+ const isRelatedDir = importDir === sourceDir || importDir === path21.join(sourceDir, "__tests__") || importDir === path21.join(sourceDir, "tests") || importDir === path21.join(sourceDir, "test");
38572
38523
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
38573
38524
  if (!testFiles.includes(testFile)) {
38574
38525
  testFiles.push(testFile);
@@ -38583,8 +38534,8 @@ async function getTestFilesFromGraph(sourceFiles) {
38583
38534
  while (match !== null) {
38584
38535
  const importPath = match[1];
38585
38536
  if (importPath.startsWith(".")) {
38586
- let resolvedImport = path22.resolve(testDir, importPath);
38587
- const existingExt = path22.extname(resolvedImport);
38537
+ let resolvedImport = path21.resolve(testDir, importPath);
38538
+ const existingExt = path21.extname(resolvedImport);
38588
38539
  if (!existingExt) {
38589
38540
  for (const extToTry of [
38590
38541
  ".ts",
@@ -38601,12 +38552,12 @@ async function getTestFilesFromGraph(sourceFiles) {
38601
38552
  }
38602
38553
  }
38603
38554
  }
38604
- const importDir = path22.dirname(resolvedImport);
38605
- const importBasename = path22.basename(resolvedImport, path22.extname(resolvedImport));
38555
+ const importDir = path21.dirname(resolvedImport);
38556
+ const importBasename = path21.basename(resolvedImport, path21.extname(resolvedImport));
38606
38557
  for (const sourceFile of sourceFiles) {
38607
- const sourceDir = path22.dirname(sourceFile);
38608
- const sourceBasename = path22.basename(sourceFile, path22.extname(sourceFile));
38609
- const isRelatedDir = importDir === sourceDir || importDir === path22.join(sourceDir, "__tests__") || importDir === path22.join(sourceDir, "tests") || importDir === path22.join(sourceDir, "test");
38558
+ const sourceDir = path21.dirname(sourceFile);
38559
+ const sourceBasename = path21.basename(sourceFile, path21.extname(sourceFile));
38560
+ const isRelatedDir = importDir === sourceDir || importDir === path21.join(sourceDir, "__tests__") || importDir === path21.join(sourceDir, "tests") || importDir === path21.join(sourceDir, "test");
38610
38561
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
38611
38562
  if (!testFiles.includes(testFile)) {
38612
38563
  testFiles.push(testFile);
@@ -38691,8 +38642,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
38691
38642
  return ["mvn", "test"];
38692
38643
  case "gradle": {
38693
38644
  const isWindows = process.platform === "win32";
38694
- const hasGradlewBat = fs12.existsSync(path22.join(baseDir, "gradlew.bat"));
38695
- const hasGradlew = fs12.existsSync(path22.join(baseDir, "gradlew"));
38645
+ const hasGradlewBat = fs12.existsSync(path21.join(baseDir, "gradlew.bat"));
38646
+ const hasGradlew = fs12.existsSync(path21.join(baseDir, "gradlew"));
38696
38647
  if (hasGradlewBat && isWindows)
38697
38648
  return ["gradlew.bat", "test"];
38698
38649
  if (hasGradlew)
@@ -38709,7 +38660,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
38709
38660
  "cmake-build-release",
38710
38661
  "out"
38711
38662
  ];
38712
- const actualBuildDir = buildDirCandidates.find((d) => fs12.existsSync(path22.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
38663
+ const actualBuildDir = buildDirCandidates.find((d) => fs12.existsSync(path21.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
38713
38664
  return ["ctest", "--test-dir", actualBuildDir];
38714
38665
  }
38715
38666
  case "swift-test":
@@ -39251,7 +39202,7 @@ var test_runner = createSwarmTool({
39251
39202
  let effectiveScope = scope;
39252
39203
  if (scope === "all") {} else if (scope === "convention") {
39253
39204
  const sourceFiles = args.files.filter((f) => {
39254
- const ext = path22.extname(f).toLowerCase();
39205
+ const ext = path21.extname(f).toLowerCase();
39255
39206
  return SOURCE_EXTENSIONS.has(ext);
39256
39207
  });
39257
39208
  if (sourceFiles.length === 0) {
@@ -39267,7 +39218,7 @@ var test_runner = createSwarmTool({
39267
39218
  testFiles = getTestFilesFromConvention(sourceFiles);
39268
39219
  } else if (scope === "graph") {
39269
39220
  const sourceFiles = args.files.filter((f) => {
39270
- const ext = path22.extname(f).toLowerCase();
39221
+ const ext = path21.extname(f).toLowerCase();
39271
39222
  return SOURCE_EXTENSIONS.has(ext);
39272
39223
  });
39273
39224
  if (sourceFiles.length === 0) {
@@ -39338,8 +39289,8 @@ function validateDirectoryPath(dir) {
39338
39289
  if (dir.includes("..")) {
39339
39290
  throw new Error("Directory path must not contain path traversal sequences");
39340
39291
  }
39341
- const normalized = path23.normalize(dir);
39342
- const absolutePath = path23.isAbsolute(normalized) ? normalized : path23.resolve(normalized);
39292
+ const normalized = path22.normalize(dir);
39293
+ const absolutePath = path22.isAbsolute(normalized) ? normalized : path22.resolve(normalized);
39343
39294
  return absolutePath;
39344
39295
  }
39345
39296
  function validateTimeout(timeoutMs, defaultValue) {
@@ -39362,7 +39313,7 @@ function validateTimeout(timeoutMs, defaultValue) {
39362
39313
  }
39363
39314
  function getPackageVersion(dir) {
39364
39315
  try {
39365
- const packagePath = path23.join(dir, "package.json");
39316
+ const packagePath = path22.join(dir, "package.json");
39366
39317
  if (fs13.existsSync(packagePath)) {
39367
39318
  const content = fs13.readFileSync(packagePath, "utf-8");
39368
39319
  const pkg = JSON.parse(content);
@@ -39373,7 +39324,7 @@ function getPackageVersion(dir) {
39373
39324
  }
39374
39325
  function getChangelogVersion(dir) {
39375
39326
  try {
39376
- const changelogPath = path23.join(dir, "CHANGELOG.md");
39327
+ const changelogPath = path22.join(dir, "CHANGELOG.md");
39377
39328
  if (fs13.existsSync(changelogPath)) {
39378
39329
  const content = fs13.readFileSync(changelogPath, "utf-8");
39379
39330
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
@@ -39387,7 +39338,7 @@ function getChangelogVersion(dir) {
39387
39338
  function getVersionFileVersion(dir) {
39388
39339
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
39389
39340
  for (const file3 of possibleFiles) {
39390
- const filePath = path23.join(dir, file3);
39341
+ const filePath = path22.join(dir, file3);
39391
39342
  if (fs13.existsSync(filePath)) {
39392
39343
  try {
39393
39344
  const content = fs13.readFileSync(filePath, "utf-8").trim();
@@ -39882,6 +39833,144 @@ async function handlePreflightCommand(directory, _args) {
39882
39833
  const report = await runPreflight(directory, 0);
39883
39834
  return formatPreflightMarkdown(report);
39884
39835
  }
39836
+ // src/knowledge/hive-promoter.ts
39837
+ import * as fs14 from "fs";
39838
+ import * as os5 from "os";
39839
+ import * as path23 from "path";
39840
+ var DANGEROUS_PATTERNS = [
39841
+ [/rm\s+-rf/, "rm\\s+-rf"],
39842
+ [/:\s*!\s*\|/, ":\\s*!\\s*\\|"],
39843
+ [/\|\s*sh\b/, "\\|\\s*sh\\b"],
39844
+ [/`[^`]*`/, "`[^`]*`"],
39845
+ [/\$\(/, "\\$\\("],
39846
+ [/;\s*rm\s+\//, ";\\s*rm\\s+\\/"],
39847
+ [/>\s*\/dev\//, ">\\s*\\/dev\\/"],
39848
+ [/\bmkfs\b/, "\\bmkfs\\b"],
39849
+ [/\bdd\s+if=/, "\\bdd\\s+if="],
39850
+ [/chmod\s+[0-7]*7[0-7]{2}/, "chmod\\s+[0-7]*7[0-7]\\{2\\}"],
39851
+ [/\bchown\s+-R\b/, "\\bchown\\s+-R\\b"],
39852
+ [/(?<!\.)\beval\s*\(/, "(?<!\\.)\\beval\\s*\\("],
39853
+ [/(?<!\.)\bexec\s*\(/, "(?<!\\.)\\bexec\\s*\\("]
39854
+ ];
39855
+ var SHELL_COMMAND_START = /^(grep|find|ls|cat|sed|awk|curl|wget|ssh|scp|git|mv|cp|mkdir|touch|echo|printf|python|python3|node|bash|sh|zsh|apt|yum|brew)\s/;
39856
+ function validateLesson2(text) {
39857
+ if (!text || !text.trim()) {
39858
+ return { valid: false, reason: "Lesson text cannot be empty" };
39859
+ }
39860
+ for (const [pattern, patternSource] of DANGEROUS_PATTERNS) {
39861
+ if (pattern.test(text)) {
39862
+ return {
39863
+ valid: false,
39864
+ reason: `Dangerous pattern detected: ${patternSource}`
39865
+ };
39866
+ }
39867
+ }
39868
+ const trimmed = text.trim();
39869
+ if (SHELL_COMMAND_START.test(trimmed)) {
39870
+ const lastChar = trimmed[trimmed.length - 1];
39871
+ if (![".", "!", "?", ";"].includes(lastChar)) {
39872
+ return {
39873
+ valid: false,
39874
+ reason: "Lesson appears to contain raw shell commands"
39875
+ };
39876
+ }
39877
+ }
39878
+ return { valid: true };
39879
+ }
39880
+ function getHiveFilePath() {
39881
+ const platform = process.platform;
39882
+ const home = os5.homedir();
39883
+ let dataDir;
39884
+ if (platform === "win32") {
39885
+ dataDir = path23.join(process.env.LOCALAPPDATA || path23.join(home, "AppData", "Local"), "opencode-swarm", "Data");
39886
+ } else if (platform === "darwin") {
39887
+ dataDir = path23.join(home, "Library", "Application Support", "opencode-swarm");
39888
+ } else {
39889
+ dataDir = path23.join(process.env.XDG_DATA_HOME || path23.join(home, ".local", "share"), "opencode-swarm");
39890
+ }
39891
+ return path23.join(dataDir, "hive-knowledge.jsonl");
39892
+ }
39893
+ async function promoteToHive(_directory, lesson, category) {
39894
+ const trimmed = (lesson ?? "").trim();
39895
+ if (!trimmed) {
39896
+ throw new Error("Lesson text required");
39897
+ }
39898
+ const validation = validateLesson2(trimmed);
39899
+ if (!validation.valid) {
39900
+ throw new Error(`Lesson rejected by validator: ${validation.reason}`);
39901
+ }
39902
+ const hivePath = getHiveFilePath();
39903
+ const hiveDir = path23.dirname(hivePath);
39904
+ if (!fs14.existsSync(hiveDir)) {
39905
+ fs14.mkdirSync(hiveDir, { recursive: true });
39906
+ }
39907
+ const now = new Date;
39908
+ const entry = {
39909
+ id: `hive-manual-${now.getTime()}`,
39910
+ lesson: trimmed,
39911
+ category: category || "process",
39912
+ scope_tag: "global",
39913
+ confidence: 1,
39914
+ status: "promoted",
39915
+ promotion_source: "manual",
39916
+ promotedAt: now.toISOString(),
39917
+ retrievalOutcomes: { applied: 0, succeededAfter: 0, failedAfter: 0 }
39918
+ };
39919
+ fs14.appendFileSync(hivePath, `${JSON.stringify(entry)}
39920
+ `, "utf-8");
39921
+ const preview = `${trimmed.slice(0, 50)}${trimmed.length > 50 ? "..." : ""}`;
39922
+ return `Promoted to hive: "${preview}" (confidence: 1.0, source: manual)`;
39923
+ }
39924
+ async function promoteFromSwarm(directory, lessonId) {
39925
+ const knowledgePath = path23.join(directory, ".swarm", "knowledge.jsonl");
39926
+ const entries = [];
39927
+ if (fs14.existsSync(knowledgePath)) {
39928
+ const content = fs14.readFileSync(knowledgePath, "utf-8");
39929
+ for (const line of content.split(`
39930
+ `)) {
39931
+ const t = line.trim();
39932
+ if (!t)
39933
+ continue;
39934
+ try {
39935
+ entries.push(JSON.parse(t));
39936
+ } catch {}
39937
+ }
39938
+ }
39939
+ const swarmEntry = entries.find((e) => e.id === lessonId);
39940
+ if (!swarmEntry) {
39941
+ throw new Error(`Lesson ${lessonId} not found in .swarm/knowledge.jsonl`);
39942
+ }
39943
+ const lessonText = typeof swarmEntry.lesson === "string" ? swarmEntry.lesson.trim() : "";
39944
+ if (!lessonText) {
39945
+ throw new Error("Lesson text required");
39946
+ }
39947
+ const validation = validateLesson2(lessonText);
39948
+ if (!validation.valid) {
39949
+ throw new Error(`Lesson rejected by validator: ${validation.reason}`);
39950
+ }
39951
+ const hivePath = getHiveFilePath();
39952
+ const hiveDir = path23.dirname(hivePath);
39953
+ if (!fs14.existsSync(hiveDir)) {
39954
+ fs14.mkdirSync(hiveDir, { recursive: true });
39955
+ }
39956
+ const now = new Date;
39957
+ const hiveEntry = {
39958
+ id: `hive-manual-${now.getTime()}`,
39959
+ lesson: lessonText,
39960
+ category: typeof swarmEntry.category === "string" ? swarmEntry.category : "process",
39961
+ scope_tag: typeof swarmEntry.scope === "string" ? swarmEntry.scope : "global",
39962
+ confidence: 1,
39963
+ status: "promoted",
39964
+ promotion_source: "manual",
39965
+ promotedAt: now.toISOString(),
39966
+ retrievalOutcomes: { applied: 0, succeededAfter: 0, failedAfter: 0 }
39967
+ };
39968
+ fs14.appendFileSync(hivePath, `${JSON.stringify(hiveEntry)}
39969
+ `, "utf-8");
39970
+ const preview = `${lessonText.slice(0, 50)}${lessonText.length > 50 ? "..." : ""}`;
39971
+ return `Promoted to hive: "${preview}" (confidence: 1.0, source: manual)`;
39972
+ }
39973
+
39885
39974
  // src/commands/promote.ts
39886
39975
  async function handlePromoteCommand(directory, args) {
39887
39976
  let category;
@@ -39904,11 +39993,7 @@ async function handlePromoteCommand(directory, args) {
39904
39993
  return `Usage: /swarm promote "<lesson text>" or /swarm promote --from-swarm <id>`;
39905
39994
  }
39906
39995
  if (lessonText) {
39907
- const validation = validateLesson(lessonText, [], {
39908
- category: category || "process",
39909
- scope: "global",
39910
- confidence: 1
39911
- });
39996
+ const validation = validateLesson2(lessonText);
39912
39997
  if (!validation.valid) {
39913
39998
  return `Lesson rejected by validator: ${validation.reason}`;
39914
39999
  }
@@ -39934,7 +40019,7 @@ async function handlePromoteCommand(directory, args) {
39934
40019
  }
39935
40020
 
39936
40021
  // src/commands/reset.ts
39937
- import * as fs14 from "fs";
40022
+ import * as fs15 from "fs";
39938
40023
 
39939
40024
  // src/background/manager.ts
39940
40025
  init_utils();
@@ -40635,8 +40720,8 @@ async function handleResetCommand(directory, args) {
40635
40720
  for (const filename of filesToReset) {
40636
40721
  try {
40637
40722
  const resolvedPath = validateSwarmPath(directory, filename);
40638
- if (fs14.existsSync(resolvedPath)) {
40639
- fs14.unlinkSync(resolvedPath);
40723
+ if (fs15.existsSync(resolvedPath)) {
40724
+ fs15.unlinkSync(resolvedPath);
40640
40725
  results.push(`- \u2705 Deleted ${filename}`);
40641
40726
  } else {
40642
40727
  results.push(`- \u23ED\uFE0F ${filename} not found (skipped)`);
@@ -40653,8 +40738,8 @@ async function handleResetCommand(directory, args) {
40653
40738
  }
40654
40739
  try {
40655
40740
  const summariesPath = validateSwarmPath(directory, "summaries");
40656
- if (fs14.existsSync(summariesPath)) {
40657
- fs14.rmSync(summariesPath, { recursive: true, force: true });
40741
+ if (fs15.existsSync(summariesPath)) {
40742
+ fs15.rmSync(summariesPath, { recursive: true, force: true });
40658
40743
  results.push("- \u2705 Deleted summaries/ directory");
40659
40744
  } else {
40660
40745
  results.push("- \u23ED\uFE0F summaries/ not found (skipped)");
@@ -40674,14 +40759,14 @@ async function handleResetCommand(directory, args) {
40674
40759
 
40675
40760
  // src/commands/reset-session.ts
40676
40761
  init_utils2();
40677
- import * as fs15 from "fs";
40762
+ import * as fs16 from "fs";
40678
40763
  import * as path24 from "path";
40679
40764
  async function handleResetSessionCommand(directory, _args) {
40680
40765
  const results = [];
40681
40766
  try {
40682
40767
  const statePath = validateSwarmPath(directory, "session/state.json");
40683
- if (fs15.existsSync(statePath)) {
40684
- fs15.unlinkSync(statePath);
40768
+ if (fs16.existsSync(statePath)) {
40769
+ fs16.unlinkSync(statePath);
40685
40770
  results.push("\u2705 Deleted .swarm/session/state.json");
40686
40771
  } else {
40687
40772
  results.push("\u23ED\uFE0F state.json not found (already clean)");
@@ -40691,14 +40776,14 @@ async function handleResetSessionCommand(directory, _args) {
40691
40776
  }
40692
40777
  try {
40693
40778
  const sessionDir = path24.dirname(validateSwarmPath(directory, "session/state.json"));
40694
- if (fs15.existsSync(sessionDir)) {
40695
- const files = fs15.readdirSync(sessionDir);
40779
+ if (fs16.existsSync(sessionDir)) {
40780
+ const files = fs16.readdirSync(sessionDir);
40696
40781
  const otherFiles = files.filter((f) => f !== "state.json");
40697
40782
  let deletedCount = 0;
40698
40783
  for (const file3 of otherFiles) {
40699
40784
  const filePath = path24.join(sessionDir, file3);
40700
- if (fs15.lstatSync(filePath).isFile()) {
40701
- fs15.unlinkSync(filePath);
40785
+ if (fs16.lstatSync(filePath).isFile()) {
40786
+ fs16.unlinkSync(filePath);
40702
40787
  deletedCount++;
40703
40788
  }
40704
40789
  }
@@ -40803,18 +40888,18 @@ ${error93 instanceof Error ? error93.message : String(error93)}`;
40803
40888
 
40804
40889
  // src/commands/rollback.ts
40805
40890
  init_utils2();
40806
- import * as fs16 from "fs";
40891
+ import * as fs17 from "fs";
40807
40892
  import * as path26 from "path";
40808
40893
  async function handleRollbackCommand(directory, args) {
40809
40894
  const phaseArg = args[0];
40810
40895
  if (!phaseArg) {
40811
40896
  const manifestPath2 = validateSwarmPath(directory, "checkpoints/manifest.json");
40812
- if (!fs16.existsSync(manifestPath2)) {
40897
+ if (!fs17.existsSync(manifestPath2)) {
40813
40898
  return "No checkpoints found. Use `/swarm checkpoint` to create checkpoints.";
40814
40899
  }
40815
40900
  let manifest2;
40816
40901
  try {
40817
- manifest2 = JSON.parse(fs16.readFileSync(manifestPath2, "utf-8"));
40902
+ manifest2 = JSON.parse(fs17.readFileSync(manifestPath2, "utf-8"));
40818
40903
  } catch {
40819
40904
  return "Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.";
40820
40905
  }
@@ -40836,12 +40921,12 @@ async function handleRollbackCommand(directory, args) {
40836
40921
  return "Error: Phase number must be a positive integer.";
40837
40922
  }
40838
40923
  const manifestPath = validateSwarmPath(directory, "checkpoints/manifest.json");
40839
- if (!fs16.existsSync(manifestPath)) {
40924
+ if (!fs17.existsSync(manifestPath)) {
40840
40925
  return `Error: No checkpoints found. Cannot rollback to phase ${targetPhase}.`;
40841
40926
  }
40842
40927
  let manifest;
40843
40928
  try {
40844
- manifest = JSON.parse(fs16.readFileSync(manifestPath, "utf-8"));
40929
+ manifest = JSON.parse(fs17.readFileSync(manifestPath, "utf-8"));
40845
40930
  } catch {
40846
40931
  return `Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.`;
40847
40932
  }
@@ -40851,10 +40936,10 @@ async function handleRollbackCommand(directory, args) {
40851
40936
  return `Error: Checkpoint for phase ${targetPhase} not found. Available phases: ${available}`;
40852
40937
  }
40853
40938
  const checkpointDir = validateSwarmPath(directory, `checkpoints/phase-${targetPhase}`);
40854
- if (!fs16.existsSync(checkpointDir)) {
40939
+ if (!fs17.existsSync(checkpointDir)) {
40855
40940
  return `Error: Checkpoint directory for phase ${targetPhase} does not exist.`;
40856
40941
  }
40857
- const checkpointFiles = fs16.readdirSync(checkpointDir);
40942
+ const checkpointFiles = fs17.readdirSync(checkpointDir);
40858
40943
  if (checkpointFiles.length === 0) {
40859
40944
  return `Error: Checkpoint for phase ${targetPhase} is empty. Cannot rollback.`;
40860
40945
  }
@@ -40865,7 +40950,7 @@ async function handleRollbackCommand(directory, args) {
40865
40950
  const src = path26.join(checkpointDir, file3);
40866
40951
  const dest = path26.join(swarmDir, file3);
40867
40952
  try {
40868
- fs16.cpSync(src, dest, { recursive: true, force: true });
40953
+ fs17.cpSync(src, dest, { recursive: true, force: true });
40869
40954
  successes.push(file3);
40870
40955
  } catch (error93) {
40871
40956
  failures.push({ file: file3, error: error93.message });
@@ -40882,7 +40967,7 @@ async function handleRollbackCommand(directory, args) {
40882
40967
  timestamp: new Date().toISOString()
40883
40968
  };
40884
40969
  try {
40885
- fs16.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
40970
+ fs17.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
40886
40971
  `);
40887
40972
  } catch (error93) {
40888
40973
  console.error("Failed to write rollback event:", error93 instanceof Error ? error93.message : String(error93));
@@ -40925,11 +41010,11 @@ async function handleSimulateCommand(directory, args) {
40925
41010
  ];
40926
41011
  const report = reportLines.filter(Boolean).join(`
40927
41012
  `);
40928
- const fs17 = await import("fs/promises");
41013
+ const fs18 = await import("fs/promises");
40929
41014
  const path27 = await import("path");
40930
41015
  const reportPath = path27.join(directory, ".swarm", "simulate-report.md");
40931
- await fs17.mkdir(path27.dirname(reportPath), { recursive: true });
40932
- await fs17.writeFile(reportPath, report, "utf-8");
41016
+ await fs18.mkdir(path27.dirname(reportPath), { recursive: true });
41017
+ await fs18.writeFile(reportPath, report, "utf-8");
40933
41018
  return `${darkMatterPairs.length} hidden coupling pairs detected`;
40934
41019
  }
40935
41020
 
@@ -41411,18 +41496,18 @@ function resolveCommand(tokens) {
41411
41496
  }
41412
41497
 
41413
41498
  // src/cli/index.ts
41414
- var CONFIG_DIR = path27.join(process.env.XDG_CONFIG_HOME || path27.join(os5.homedir(), ".config"), "opencode");
41499
+ var CONFIG_DIR = path27.join(process.env.XDG_CONFIG_HOME || path27.join(os6.homedir(), ".config"), "opencode");
41415
41500
  var OPENCODE_CONFIG_PATH = path27.join(CONFIG_DIR, "opencode.json");
41416
41501
  var PLUGIN_CONFIG_PATH = path27.join(CONFIG_DIR, "opencode-swarm.json");
41417
41502
  var PROMPTS_DIR = path27.join(CONFIG_DIR, "opencode-swarm");
41418
41503
  function ensureDir(dir) {
41419
- if (!fs17.existsSync(dir)) {
41420
- fs17.mkdirSync(dir, { recursive: true });
41504
+ if (!fs18.existsSync(dir)) {
41505
+ fs18.mkdirSync(dir, { recursive: true });
41421
41506
  }
41422
41507
  }
41423
41508
  function loadJson(filepath) {
41424
41509
  try {
41425
- const content = fs17.readFileSync(filepath, "utf-8");
41510
+ const content = fs18.readFileSync(filepath, "utf-8");
41426
41511
  const stripped = content.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (match, comment) => comment ? "" : match).replace(/,(\s*[}\]])/g, "$1");
41427
41512
  return JSON.parse(stripped);
41428
41513
  } catch {
@@ -41430,7 +41515,7 @@ function loadJson(filepath) {
41430
41515
  }
41431
41516
  }
41432
41517
  function saveJson(filepath, data) {
41433
- fs17.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
41518
+ fs18.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
41434
41519
  `, "utf-8");
41435
41520
  }
41436
41521
  async function install() {
@@ -41463,7 +41548,7 @@ async function install() {
41463
41548
  saveJson(OPENCODE_CONFIG_PATH, opencodeConfig);
41464
41549
  console.log("\u2713 Added opencode-swarm to OpenCode plugins");
41465
41550
  console.log("\u2713 Disabled default OpenCode agents (explore, general)");
41466
- if (!fs17.existsSync(PLUGIN_CONFIG_PATH)) {
41551
+ if (!fs18.existsSync(PLUGIN_CONFIG_PATH)) {
41467
41552
  const defaultConfig = {
41468
41553
  agents: {
41469
41554
  coder: { model: "opencode/minimax-m2.5-free" },
@@ -41506,7 +41591,7 @@ async function uninstall() {
41506
41591
  `);
41507
41592
  const opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
41508
41593
  if (!opencodeConfig) {
41509
- if (fs17.existsSync(OPENCODE_CONFIG_PATH)) {
41594
+ if (fs18.existsSync(OPENCODE_CONFIG_PATH)) {
41510
41595
  console.log(`\u2717 Could not parse opencode config at: ${OPENCODE_CONFIG_PATH}`);
41511
41596
  return 1;
41512
41597
  } else {
@@ -41538,13 +41623,13 @@ async function uninstall() {
41538
41623
  console.log("\u2713 Re-enabled default OpenCode agents (explore, general)");
41539
41624
  if (process.argv.includes("--clean")) {
41540
41625
  let cleaned = false;
41541
- if (fs17.existsSync(PLUGIN_CONFIG_PATH)) {
41542
- fs17.unlinkSync(PLUGIN_CONFIG_PATH);
41626
+ if (fs18.existsSync(PLUGIN_CONFIG_PATH)) {
41627
+ fs18.unlinkSync(PLUGIN_CONFIG_PATH);
41543
41628
  console.log(`\u2713 Removed plugin config: ${PLUGIN_CONFIG_PATH}`);
41544
41629
  cleaned = true;
41545
41630
  }
41546
- if (fs17.existsSync(PROMPTS_DIR)) {
41547
- fs17.rmSync(PROMPTS_DIR, { recursive: true });
41631
+ if (fs18.existsSync(PROMPTS_DIR)) {
41632
+ fs18.rmSync(PROMPTS_DIR, { recursive: true });
41548
41633
  console.log(`\u2713 Removed custom prompts: ${PROMPTS_DIR}`);
41549
41634
  cleaned = true;
41550
41635
  }