opencode-swarm 6.44.1 → 6.44.3

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))
@@ -37330,10 +37238,10 @@ function detectAdditionalLinter(cwd) {
37330
37238
  function findBinInAncestors(startDir, binName) {
37331
37239
  let dir = startDir;
37332
37240
  while (true) {
37333
- const candidate = path19.join(dir, "node_modules", ".bin", binName);
37241
+ const candidate = path18.join(dir, "node_modules", ".bin", binName);
37334
37242
  if (fs9.existsSync(candidate))
37335
37243
  return candidate;
37336
- const parent = path19.dirname(dir);
37244
+ const parent = path18.dirname(dir);
37337
37245
  if (parent === dir)
37338
37246
  break;
37339
37247
  dir = parent;
@@ -37342,10 +37250,10 @@ function findBinInAncestors(startDir, binName) {
37342
37250
  }
37343
37251
  function findBinInEnvPath(binName) {
37344
37252
  const searchPath = process.env.PATH ?? "";
37345
- for (const dir of searchPath.split(path19.delimiter)) {
37253
+ for (const dir of searchPath.split(path18.delimiter)) {
37346
37254
  if (!dir)
37347
37255
  continue;
37348
- const candidate = path19.join(dir, binName);
37256
+ const candidate = path18.join(dir, binName);
37349
37257
  if (fs9.existsSync(candidate))
37350
37258
  return candidate;
37351
37259
  }
@@ -37358,13 +37266,13 @@ async function detectAvailableLinter(directory) {
37358
37266
  return null;
37359
37267
  const projectDir = directory;
37360
37268
  const isWindows = process.platform === "win32";
37361
- const biomeBin = isWindows ? path19.join(projectDir, "node_modules", ".bin", "biome.EXE") : path19.join(projectDir, "node_modules", ".bin", "biome");
37362
- const eslintBin = isWindows ? path19.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path19.join(projectDir, "node_modules", ".bin", "eslint");
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");
37363
37271
  const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
37364
37272
  if (localResult)
37365
37273
  return localResult;
37366
- const biomeAncestor = findBinInAncestors(path19.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
37367
- const eslintAncestor = findBinInAncestors(path19.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
37274
+ const biomeAncestor = findBinInAncestors(path18.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
37275
+ const eslintAncestor = findBinInAncestors(path18.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
37368
37276
  if (biomeAncestor || eslintAncestor) {
37369
37277
  return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
37370
37278
  }
@@ -37572,7 +37480,7 @@ For Rust: rustup component add clippy`
37572
37480
 
37573
37481
  // src/tools/secretscan.ts
37574
37482
  import * as fs10 from "fs";
37575
- import * as path20 from "path";
37483
+ import * as path19 from "path";
37576
37484
  var MAX_FILE_PATH_LENGTH = 500;
37577
37485
  var MAX_FILE_SIZE_BYTES = 512 * 1024;
37578
37486
  var MAX_FILES_SCANNED = 1000;
@@ -37799,7 +37707,7 @@ function isGlobOrPathPattern(pattern) {
37799
37707
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
37800
37708
  }
37801
37709
  function loadSecretScanIgnore(scanDir) {
37802
- const ignorePath = path20.join(scanDir, ".secretscanignore");
37710
+ const ignorePath = path19.join(scanDir, ".secretscanignore");
37803
37711
  try {
37804
37712
  if (!fs10.existsSync(ignorePath))
37805
37713
  return [];
@@ -37822,7 +37730,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
37822
37730
  if (exactNames.has(entry))
37823
37731
  return true;
37824
37732
  for (const pattern of globPatterns) {
37825
- if (path20.matchesGlob(relPath, pattern))
37733
+ if (path19.matchesGlob(relPath, pattern))
37826
37734
  return true;
37827
37735
  }
37828
37736
  return false;
@@ -37843,7 +37751,7 @@ function validateDirectoryInput(dir) {
37843
37751
  return null;
37844
37752
  }
37845
37753
  function isBinaryFile(filePath, buffer) {
37846
- const ext = path20.extname(filePath).toLowerCase();
37754
+ const ext = path19.extname(filePath).toLowerCase();
37847
37755
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
37848
37756
  return true;
37849
37757
  }
@@ -37980,9 +37888,9 @@ function isSymlinkLoop(realPath, visited) {
37980
37888
  return false;
37981
37889
  }
37982
37890
  function isPathWithinScope(realPath, scanDir) {
37983
- const resolvedScanDir = path20.resolve(scanDir);
37984
- const resolvedRealPath = path20.resolve(realPath);
37985
- 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}\\`);
37986
37894
  }
37987
37895
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
37988
37896
  skippedDirs: 0,
@@ -38008,8 +37916,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
38008
37916
  return a.localeCompare(b);
38009
37917
  });
38010
37918
  for (const entry of entries) {
38011
- const fullPath = path20.join(dir, entry);
38012
- const relPath = path20.relative(scanDir, fullPath).replace(/\\/g, "/");
37919
+ const fullPath = path19.join(dir, entry);
37920
+ const relPath = path19.relative(scanDir, fullPath).replace(/\\/g, "/");
38013
37921
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
38014
37922
  stats.skippedDirs++;
38015
37923
  continue;
@@ -38044,7 +37952,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
38044
37952
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
38045
37953
  files.push(...subFiles);
38046
37954
  } else if (lstat.isFile()) {
38047
- const ext = path20.extname(fullPath).toLowerCase();
37955
+ const ext = path19.extname(fullPath).toLowerCase();
38048
37956
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
38049
37957
  files.push(fullPath);
38050
37958
  } else {
@@ -38110,7 +38018,14 @@ var secretscan = createSwarmTool({
38110
38018
  }
38111
38019
  }
38112
38020
  try {
38113
- 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
+ })();
38114
38029
  if (!fs10.existsSync(scanDir)) {
38115
38030
  const errorResult = {
38116
38031
  error: "directory not found",
@@ -38261,11 +38176,11 @@ async function runSecretscan(directory) {
38261
38176
 
38262
38177
  // src/tools/test-runner.ts
38263
38178
  import * as fs12 from "fs";
38264
- import * as path22 from "path";
38179
+ import * as path21 from "path";
38265
38180
 
38266
38181
  // src/tools/resolve-working-directory.ts
38267
38182
  import * as fs11 from "fs";
38268
- import * as path21 from "path";
38183
+ import * as path20 from "path";
38269
38184
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
38270
38185
  if (workingDirectory == null || workingDirectory === "") {
38271
38186
  return { success: true, directory: fallbackDirectory };
@@ -38285,15 +38200,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
38285
38200
  };
38286
38201
  }
38287
38202
  }
38288
- const normalizedDir = path21.normalize(workingDirectory);
38289
- const pathParts = normalizedDir.split(path21.sep);
38203
+ const normalizedDir = path20.normalize(workingDirectory);
38204
+ const pathParts = normalizedDir.split(path20.sep);
38290
38205
  if (pathParts.includes("..")) {
38291
38206
  return {
38292
38207
  success: false,
38293
38208
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
38294
38209
  };
38295
38210
  }
38296
- const resolvedDir = path21.resolve(normalizedDir);
38211
+ const resolvedDir = path20.resolve(normalizedDir);
38297
38212
  try {
38298
38213
  const realPath = fs11.realpathSync(resolvedDir);
38299
38214
  return { success: true, directory: realPath };
@@ -38376,14 +38291,14 @@ function hasDevDependency(devDeps, ...patterns) {
38376
38291
  return hasPackageJsonDependency(devDeps, ...patterns);
38377
38292
  }
38378
38293
  function detectGoTest(cwd) {
38379
- return fs12.existsSync(path22.join(cwd, "go.mod")) && isCommandAvailable("go");
38294
+ return fs12.existsSync(path21.join(cwd, "go.mod")) && isCommandAvailable("go");
38380
38295
  }
38381
38296
  function detectJavaMaven(cwd) {
38382
- return fs12.existsSync(path22.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
38297
+ return fs12.existsSync(path21.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
38383
38298
  }
38384
38299
  function detectGradle(cwd) {
38385
- const hasBuildFile = fs12.existsSync(path22.join(cwd, "build.gradle")) || fs12.existsSync(path22.join(cwd, "build.gradle.kts"));
38386
- 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"));
38387
38302
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
38388
38303
  }
38389
38304
  function detectDotnetTest(cwd) {
@@ -38396,30 +38311,30 @@ function detectDotnetTest(cwd) {
38396
38311
  }
38397
38312
  }
38398
38313
  function detectCTest(cwd) {
38399
- const hasSource = fs12.existsSync(path22.join(cwd, "CMakeLists.txt"));
38400
- 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"));
38401
38316
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
38402
38317
  }
38403
38318
  function detectSwiftTest(cwd) {
38404
- return fs12.existsSync(path22.join(cwd, "Package.swift")) && isCommandAvailable("swift");
38319
+ return fs12.existsSync(path21.join(cwd, "Package.swift")) && isCommandAvailable("swift");
38405
38320
  }
38406
38321
  function detectDartTest(cwd) {
38407
- 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"));
38408
38323
  }
38409
38324
  function detectRSpec(cwd) {
38410
- const hasRSpecFile = fs12.existsSync(path22.join(cwd, ".rspec"));
38411
- const hasGemfile = fs12.existsSync(path22.join(cwd, "Gemfile"));
38412
- 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"));
38413
38328
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
38414
38329
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
38415
38330
  }
38416
38331
  function detectMinitest(cwd) {
38417
- 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");
38418
38333
  }
38419
38334
  async function detectTestFramework(cwd) {
38420
38335
  const baseDir = cwd;
38421
38336
  try {
38422
- const packageJsonPath = path22.join(baseDir, "package.json");
38337
+ const packageJsonPath = path21.join(baseDir, "package.json");
38423
38338
  if (fs12.existsSync(packageJsonPath)) {
38424
38339
  const content = fs12.readFileSync(packageJsonPath, "utf-8");
38425
38340
  const pkg = JSON.parse(content);
@@ -38440,16 +38355,16 @@ async function detectTestFramework(cwd) {
38440
38355
  return "jest";
38441
38356
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
38442
38357
  return "mocha";
38443
- 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"))) {
38444
38359
  if (scripts.test?.includes("bun"))
38445
38360
  return "bun";
38446
38361
  }
38447
38362
  }
38448
38363
  } catch {}
38449
38364
  try {
38450
- const pyprojectTomlPath = path22.join(baseDir, "pyproject.toml");
38451
- const setupCfgPath = path22.join(baseDir, "setup.cfg");
38452
- 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");
38453
38368
  if (fs12.existsSync(pyprojectTomlPath)) {
38454
38369
  const content = fs12.readFileSync(pyprojectTomlPath, "utf-8");
38455
38370
  if (content.includes("[tool.pytest"))
@@ -38469,7 +38384,7 @@ async function detectTestFramework(cwd) {
38469
38384
  }
38470
38385
  } catch {}
38471
38386
  try {
38472
- const cargoTomlPath = path22.join(baseDir, "Cargo.toml");
38387
+ const cargoTomlPath = path21.join(baseDir, "Cargo.toml");
38473
38388
  if (fs12.existsSync(cargoTomlPath)) {
38474
38389
  const content = fs12.readFileSync(cargoTomlPath, "utf-8");
38475
38390
  if (content.includes("[dev-dependencies]")) {
@@ -38480,9 +38395,9 @@ async function detectTestFramework(cwd) {
38480
38395
  }
38481
38396
  } catch {}
38482
38397
  try {
38483
- const pesterConfigPath = path22.join(baseDir, "pester.config.ps1");
38484
- const pesterConfigJsonPath = path22.join(baseDir, "pester.config.ps1.json");
38485
- 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");
38486
38401
  if (fs12.existsSync(pesterConfigPath) || fs12.existsSync(pesterConfigJsonPath) || fs12.existsSync(pesterPs1Path)) {
38487
38402
  return "pester";
38488
38403
  }
@@ -38534,8 +38449,8 @@ function getTestFilesFromConvention(sourceFiles) {
38534
38449
  const testFiles = [];
38535
38450
  for (const file3 of sourceFiles) {
38536
38451
  const normalizedPath = file3.replace(/\\/g, "/");
38537
- const basename4 = path22.basename(file3);
38538
- const dirname10 = path22.dirname(file3);
38452
+ const basename4 = path21.basename(file3);
38453
+ const dirname10 = path21.dirname(file3);
38539
38454
  if (hasCompoundTestExtension(basename4) || basename4.includes(".spec.") || basename4.includes(".test.") || normalizedPath.includes("/__tests__/") || normalizedPath.includes("/tests/") || normalizedPath.includes("/test/")) {
38540
38455
  if (!testFiles.includes(file3)) {
38541
38456
  testFiles.push(file3);
@@ -38544,13 +38459,13 @@ function getTestFilesFromConvention(sourceFiles) {
38544
38459
  }
38545
38460
  for (const _pattern of TEST_PATTERNS) {
38546
38461
  const nameWithoutExt = basename4.replace(/\.[^.]+$/, "");
38547
- const ext = path22.extname(basename4);
38462
+ const ext = path21.extname(basename4);
38548
38463
  const possibleTestFiles = [
38549
- path22.join(dirname10, `${nameWithoutExt}.spec${ext}`),
38550
- path22.join(dirname10, `${nameWithoutExt}.test${ext}`),
38551
- path22.join(dirname10, "__tests__", `${nameWithoutExt}${ext}`),
38552
- path22.join(dirname10, "tests", `${nameWithoutExt}${ext}`),
38553
- path22.join(dirname10, "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}`)
38554
38469
  ];
38555
38470
  for (const testFile of possibleTestFiles) {
38556
38471
  if (fs12.existsSync(testFile) && !testFiles.includes(testFile)) {
@@ -38570,7 +38485,7 @@ async function getTestFilesFromGraph(sourceFiles) {
38570
38485
  for (const testFile of candidateTestFiles) {
38571
38486
  try {
38572
38487
  const content = fs12.readFileSync(testFile, "utf-8");
38573
- const testDir = path22.dirname(testFile);
38488
+ const testDir = path21.dirname(testFile);
38574
38489
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
38575
38490
  let match;
38576
38491
  match = importRegex.exec(content);
@@ -38578,8 +38493,8 @@ async function getTestFilesFromGraph(sourceFiles) {
38578
38493
  const importPath = match[1];
38579
38494
  let resolvedImport;
38580
38495
  if (importPath.startsWith(".")) {
38581
- resolvedImport = path22.resolve(testDir, importPath);
38582
- const existingExt = path22.extname(resolvedImport);
38496
+ resolvedImport = path21.resolve(testDir, importPath);
38497
+ const existingExt = path21.extname(resolvedImport);
38583
38498
  if (!existingExt) {
38584
38499
  for (const extToTry of [
38585
38500
  ".ts",
@@ -38599,12 +38514,12 @@ async function getTestFilesFromGraph(sourceFiles) {
38599
38514
  } else {
38600
38515
  continue;
38601
38516
  }
38602
- const importBasename = path22.basename(resolvedImport, path22.extname(resolvedImport));
38603
- const importDir = path22.dirname(resolvedImport);
38517
+ const importBasename = path21.basename(resolvedImport, path21.extname(resolvedImport));
38518
+ const importDir = path21.dirname(resolvedImport);
38604
38519
  for (const sourceFile of sourceFiles) {
38605
- const sourceDir = path22.dirname(sourceFile);
38606
- const sourceBasename = path22.basename(sourceFile, path22.extname(sourceFile));
38607
- 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");
38608
38523
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
38609
38524
  if (!testFiles.includes(testFile)) {
38610
38525
  testFiles.push(testFile);
@@ -38619,8 +38534,8 @@ async function getTestFilesFromGraph(sourceFiles) {
38619
38534
  while (match !== null) {
38620
38535
  const importPath = match[1];
38621
38536
  if (importPath.startsWith(".")) {
38622
- let resolvedImport = path22.resolve(testDir, importPath);
38623
- const existingExt = path22.extname(resolvedImport);
38537
+ let resolvedImport = path21.resolve(testDir, importPath);
38538
+ const existingExt = path21.extname(resolvedImport);
38624
38539
  if (!existingExt) {
38625
38540
  for (const extToTry of [
38626
38541
  ".ts",
@@ -38637,12 +38552,12 @@ async function getTestFilesFromGraph(sourceFiles) {
38637
38552
  }
38638
38553
  }
38639
38554
  }
38640
- const importDir = path22.dirname(resolvedImport);
38641
- const importBasename = path22.basename(resolvedImport, path22.extname(resolvedImport));
38555
+ const importDir = path21.dirname(resolvedImport);
38556
+ const importBasename = path21.basename(resolvedImport, path21.extname(resolvedImport));
38642
38557
  for (const sourceFile of sourceFiles) {
38643
- const sourceDir = path22.dirname(sourceFile);
38644
- const sourceBasename = path22.basename(sourceFile, path22.extname(sourceFile));
38645
- 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");
38646
38561
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
38647
38562
  if (!testFiles.includes(testFile)) {
38648
38563
  testFiles.push(testFile);
@@ -38727,8 +38642,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
38727
38642
  return ["mvn", "test"];
38728
38643
  case "gradle": {
38729
38644
  const isWindows = process.platform === "win32";
38730
- const hasGradlewBat = fs12.existsSync(path22.join(baseDir, "gradlew.bat"));
38731
- 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"));
38732
38647
  if (hasGradlewBat && isWindows)
38733
38648
  return ["gradlew.bat", "test"];
38734
38649
  if (hasGradlew)
@@ -38745,7 +38660,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
38745
38660
  "cmake-build-release",
38746
38661
  "out"
38747
38662
  ];
38748
- 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";
38749
38664
  return ["ctest", "--test-dir", actualBuildDir];
38750
38665
  }
38751
38666
  case "swift-test":
@@ -39287,7 +39202,7 @@ var test_runner = createSwarmTool({
39287
39202
  let effectiveScope = scope;
39288
39203
  if (scope === "all") {} else if (scope === "convention") {
39289
39204
  const sourceFiles = args.files.filter((f) => {
39290
- const ext = path22.extname(f).toLowerCase();
39205
+ const ext = path21.extname(f).toLowerCase();
39291
39206
  return SOURCE_EXTENSIONS.has(ext);
39292
39207
  });
39293
39208
  if (sourceFiles.length === 0) {
@@ -39303,7 +39218,7 @@ var test_runner = createSwarmTool({
39303
39218
  testFiles = getTestFilesFromConvention(sourceFiles);
39304
39219
  } else if (scope === "graph") {
39305
39220
  const sourceFiles = args.files.filter((f) => {
39306
- const ext = path22.extname(f).toLowerCase();
39221
+ const ext = path21.extname(f).toLowerCase();
39307
39222
  return SOURCE_EXTENSIONS.has(ext);
39308
39223
  });
39309
39224
  if (sourceFiles.length === 0) {
@@ -39374,8 +39289,8 @@ function validateDirectoryPath(dir) {
39374
39289
  if (dir.includes("..")) {
39375
39290
  throw new Error("Directory path must not contain path traversal sequences");
39376
39291
  }
39377
- const normalized = path23.normalize(dir);
39378
- 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);
39379
39294
  return absolutePath;
39380
39295
  }
39381
39296
  function validateTimeout(timeoutMs, defaultValue) {
@@ -39398,7 +39313,7 @@ function validateTimeout(timeoutMs, defaultValue) {
39398
39313
  }
39399
39314
  function getPackageVersion(dir) {
39400
39315
  try {
39401
- const packagePath = path23.join(dir, "package.json");
39316
+ const packagePath = path22.join(dir, "package.json");
39402
39317
  if (fs13.existsSync(packagePath)) {
39403
39318
  const content = fs13.readFileSync(packagePath, "utf-8");
39404
39319
  const pkg = JSON.parse(content);
@@ -39409,7 +39324,7 @@ function getPackageVersion(dir) {
39409
39324
  }
39410
39325
  function getChangelogVersion(dir) {
39411
39326
  try {
39412
- const changelogPath = path23.join(dir, "CHANGELOG.md");
39327
+ const changelogPath = path22.join(dir, "CHANGELOG.md");
39413
39328
  if (fs13.existsSync(changelogPath)) {
39414
39329
  const content = fs13.readFileSync(changelogPath, "utf-8");
39415
39330
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
@@ -39423,7 +39338,7 @@ function getChangelogVersion(dir) {
39423
39338
  function getVersionFileVersion(dir) {
39424
39339
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
39425
39340
  for (const file3 of possibleFiles) {
39426
- const filePath = path23.join(dir, file3);
39341
+ const filePath = path22.join(dir, file3);
39427
39342
  if (fs13.existsSync(filePath)) {
39428
39343
  try {
39429
39344
  const content = fs13.readFileSync(filePath, "utf-8").trim();
@@ -39918,6 +39833,144 @@ async function handlePreflightCommand(directory, _args) {
39918
39833
  const report = await runPreflight(directory, 0);
39919
39834
  return formatPreflightMarkdown(report);
39920
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
+
39921
39974
  // src/commands/promote.ts
39922
39975
  async function handlePromoteCommand(directory, args) {
39923
39976
  let category;
@@ -39940,11 +39993,7 @@ async function handlePromoteCommand(directory, args) {
39940
39993
  return `Usage: /swarm promote "<lesson text>" or /swarm promote --from-swarm <id>`;
39941
39994
  }
39942
39995
  if (lessonText) {
39943
- const validation = validateLesson(lessonText, [], {
39944
- category: category || "process",
39945
- scope: "global",
39946
- confidence: 1
39947
- });
39996
+ const validation = validateLesson2(lessonText);
39948
39997
  if (!validation.valid) {
39949
39998
  return `Lesson rejected by validator: ${validation.reason}`;
39950
39999
  }
@@ -39970,7 +40019,7 @@ async function handlePromoteCommand(directory, args) {
39970
40019
  }
39971
40020
 
39972
40021
  // src/commands/reset.ts
39973
- import * as fs14 from "fs";
40022
+ import * as fs15 from "fs";
39974
40023
 
39975
40024
  // src/background/manager.ts
39976
40025
  init_utils();
@@ -40671,8 +40720,8 @@ async function handleResetCommand(directory, args) {
40671
40720
  for (const filename of filesToReset) {
40672
40721
  try {
40673
40722
  const resolvedPath = validateSwarmPath(directory, filename);
40674
- if (fs14.existsSync(resolvedPath)) {
40675
- fs14.unlinkSync(resolvedPath);
40723
+ if (fs15.existsSync(resolvedPath)) {
40724
+ fs15.unlinkSync(resolvedPath);
40676
40725
  results.push(`- \u2705 Deleted ${filename}`);
40677
40726
  } else {
40678
40727
  results.push(`- \u23ED\uFE0F ${filename} not found (skipped)`);
@@ -40689,8 +40738,8 @@ async function handleResetCommand(directory, args) {
40689
40738
  }
40690
40739
  try {
40691
40740
  const summariesPath = validateSwarmPath(directory, "summaries");
40692
- if (fs14.existsSync(summariesPath)) {
40693
- fs14.rmSync(summariesPath, { recursive: true, force: true });
40741
+ if (fs15.existsSync(summariesPath)) {
40742
+ fs15.rmSync(summariesPath, { recursive: true, force: true });
40694
40743
  results.push("- \u2705 Deleted summaries/ directory");
40695
40744
  } else {
40696
40745
  results.push("- \u23ED\uFE0F summaries/ not found (skipped)");
@@ -40710,14 +40759,14 @@ async function handleResetCommand(directory, args) {
40710
40759
 
40711
40760
  // src/commands/reset-session.ts
40712
40761
  init_utils2();
40713
- import * as fs15 from "fs";
40762
+ import * as fs16 from "fs";
40714
40763
  import * as path24 from "path";
40715
40764
  async function handleResetSessionCommand(directory, _args) {
40716
40765
  const results = [];
40717
40766
  try {
40718
40767
  const statePath = validateSwarmPath(directory, "session/state.json");
40719
- if (fs15.existsSync(statePath)) {
40720
- fs15.unlinkSync(statePath);
40768
+ if (fs16.existsSync(statePath)) {
40769
+ fs16.unlinkSync(statePath);
40721
40770
  results.push("\u2705 Deleted .swarm/session/state.json");
40722
40771
  } else {
40723
40772
  results.push("\u23ED\uFE0F state.json not found (already clean)");
@@ -40727,14 +40776,14 @@ async function handleResetSessionCommand(directory, _args) {
40727
40776
  }
40728
40777
  try {
40729
40778
  const sessionDir = path24.dirname(validateSwarmPath(directory, "session/state.json"));
40730
- if (fs15.existsSync(sessionDir)) {
40731
- const files = fs15.readdirSync(sessionDir);
40779
+ if (fs16.existsSync(sessionDir)) {
40780
+ const files = fs16.readdirSync(sessionDir);
40732
40781
  const otherFiles = files.filter((f) => f !== "state.json");
40733
40782
  let deletedCount = 0;
40734
40783
  for (const file3 of otherFiles) {
40735
40784
  const filePath = path24.join(sessionDir, file3);
40736
- if (fs15.lstatSync(filePath).isFile()) {
40737
- fs15.unlinkSync(filePath);
40785
+ if (fs16.lstatSync(filePath).isFile()) {
40786
+ fs16.unlinkSync(filePath);
40738
40787
  deletedCount++;
40739
40788
  }
40740
40789
  }
@@ -40839,18 +40888,18 @@ ${error93 instanceof Error ? error93.message : String(error93)}`;
40839
40888
 
40840
40889
  // src/commands/rollback.ts
40841
40890
  init_utils2();
40842
- import * as fs16 from "fs";
40891
+ import * as fs17 from "fs";
40843
40892
  import * as path26 from "path";
40844
40893
  async function handleRollbackCommand(directory, args) {
40845
40894
  const phaseArg = args[0];
40846
40895
  if (!phaseArg) {
40847
40896
  const manifestPath2 = validateSwarmPath(directory, "checkpoints/manifest.json");
40848
- if (!fs16.existsSync(manifestPath2)) {
40897
+ if (!fs17.existsSync(manifestPath2)) {
40849
40898
  return "No checkpoints found. Use `/swarm checkpoint` to create checkpoints.";
40850
40899
  }
40851
40900
  let manifest2;
40852
40901
  try {
40853
- manifest2 = JSON.parse(fs16.readFileSync(manifestPath2, "utf-8"));
40902
+ manifest2 = JSON.parse(fs17.readFileSync(manifestPath2, "utf-8"));
40854
40903
  } catch {
40855
40904
  return "Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.";
40856
40905
  }
@@ -40872,12 +40921,12 @@ async function handleRollbackCommand(directory, args) {
40872
40921
  return "Error: Phase number must be a positive integer.";
40873
40922
  }
40874
40923
  const manifestPath = validateSwarmPath(directory, "checkpoints/manifest.json");
40875
- if (!fs16.existsSync(manifestPath)) {
40924
+ if (!fs17.existsSync(manifestPath)) {
40876
40925
  return `Error: No checkpoints found. Cannot rollback to phase ${targetPhase}.`;
40877
40926
  }
40878
40927
  let manifest;
40879
40928
  try {
40880
- manifest = JSON.parse(fs16.readFileSync(manifestPath, "utf-8"));
40929
+ manifest = JSON.parse(fs17.readFileSync(manifestPath, "utf-8"));
40881
40930
  } catch {
40882
40931
  return `Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.`;
40883
40932
  }
@@ -40887,10 +40936,10 @@ async function handleRollbackCommand(directory, args) {
40887
40936
  return `Error: Checkpoint for phase ${targetPhase} not found. Available phases: ${available}`;
40888
40937
  }
40889
40938
  const checkpointDir = validateSwarmPath(directory, `checkpoints/phase-${targetPhase}`);
40890
- if (!fs16.existsSync(checkpointDir)) {
40939
+ if (!fs17.existsSync(checkpointDir)) {
40891
40940
  return `Error: Checkpoint directory for phase ${targetPhase} does not exist.`;
40892
40941
  }
40893
- const checkpointFiles = fs16.readdirSync(checkpointDir);
40942
+ const checkpointFiles = fs17.readdirSync(checkpointDir);
40894
40943
  if (checkpointFiles.length === 0) {
40895
40944
  return `Error: Checkpoint for phase ${targetPhase} is empty. Cannot rollback.`;
40896
40945
  }
@@ -40901,7 +40950,7 @@ async function handleRollbackCommand(directory, args) {
40901
40950
  const src = path26.join(checkpointDir, file3);
40902
40951
  const dest = path26.join(swarmDir, file3);
40903
40952
  try {
40904
- fs16.cpSync(src, dest, { recursive: true, force: true });
40953
+ fs17.cpSync(src, dest, { recursive: true, force: true });
40905
40954
  successes.push(file3);
40906
40955
  } catch (error93) {
40907
40956
  failures.push({ file: file3, error: error93.message });
@@ -40918,7 +40967,7 @@ async function handleRollbackCommand(directory, args) {
40918
40967
  timestamp: new Date().toISOString()
40919
40968
  };
40920
40969
  try {
40921
- fs16.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
40970
+ fs17.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
40922
40971
  `);
40923
40972
  } catch (error93) {
40924
40973
  console.error("Failed to write rollback event:", error93 instanceof Error ? error93.message : String(error93));
@@ -40961,11 +41010,11 @@ async function handleSimulateCommand(directory, args) {
40961
41010
  ];
40962
41011
  const report = reportLines.filter(Boolean).join(`
40963
41012
  `);
40964
- const fs17 = await import("fs/promises");
41013
+ const fs18 = await import("fs/promises");
40965
41014
  const path27 = await import("path");
40966
41015
  const reportPath = path27.join(directory, ".swarm", "simulate-report.md");
40967
- await fs17.mkdir(path27.dirname(reportPath), { recursive: true });
40968
- await fs17.writeFile(reportPath, report, "utf-8");
41016
+ await fs18.mkdir(path27.dirname(reportPath), { recursive: true });
41017
+ await fs18.writeFile(reportPath, report, "utf-8");
40969
41018
  return `${darkMatterPairs.length} hidden coupling pairs detected`;
40970
41019
  }
40971
41020
 
@@ -41447,18 +41496,18 @@ function resolveCommand(tokens) {
41447
41496
  }
41448
41497
 
41449
41498
  // src/cli/index.ts
41450
- 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");
41451
41500
  var OPENCODE_CONFIG_PATH = path27.join(CONFIG_DIR, "opencode.json");
41452
41501
  var PLUGIN_CONFIG_PATH = path27.join(CONFIG_DIR, "opencode-swarm.json");
41453
41502
  var PROMPTS_DIR = path27.join(CONFIG_DIR, "opencode-swarm");
41454
41503
  function ensureDir(dir) {
41455
- if (!fs17.existsSync(dir)) {
41456
- fs17.mkdirSync(dir, { recursive: true });
41504
+ if (!fs18.existsSync(dir)) {
41505
+ fs18.mkdirSync(dir, { recursive: true });
41457
41506
  }
41458
41507
  }
41459
41508
  function loadJson(filepath) {
41460
41509
  try {
41461
- const content = fs17.readFileSync(filepath, "utf-8");
41510
+ const content = fs18.readFileSync(filepath, "utf-8");
41462
41511
  const stripped = content.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (match, comment) => comment ? "" : match).replace(/,(\s*[}\]])/g, "$1");
41463
41512
  return JSON.parse(stripped);
41464
41513
  } catch {
@@ -41466,7 +41515,7 @@ function loadJson(filepath) {
41466
41515
  }
41467
41516
  }
41468
41517
  function saveJson(filepath, data) {
41469
- fs17.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
41518
+ fs18.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
41470
41519
  `, "utf-8");
41471
41520
  }
41472
41521
  async function install() {
@@ -41499,7 +41548,7 @@ async function install() {
41499
41548
  saveJson(OPENCODE_CONFIG_PATH, opencodeConfig);
41500
41549
  console.log("\u2713 Added opencode-swarm to OpenCode plugins");
41501
41550
  console.log("\u2713 Disabled default OpenCode agents (explore, general)");
41502
- if (!fs17.existsSync(PLUGIN_CONFIG_PATH)) {
41551
+ if (!fs18.existsSync(PLUGIN_CONFIG_PATH)) {
41503
41552
  const defaultConfig = {
41504
41553
  agents: {
41505
41554
  coder: { model: "opencode/minimax-m2.5-free" },
@@ -41542,7 +41591,7 @@ async function uninstall() {
41542
41591
  `);
41543
41592
  const opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
41544
41593
  if (!opencodeConfig) {
41545
- if (fs17.existsSync(OPENCODE_CONFIG_PATH)) {
41594
+ if (fs18.existsSync(OPENCODE_CONFIG_PATH)) {
41546
41595
  console.log(`\u2717 Could not parse opencode config at: ${OPENCODE_CONFIG_PATH}`);
41547
41596
  return 1;
41548
41597
  } else {
@@ -41574,13 +41623,13 @@ async function uninstall() {
41574
41623
  console.log("\u2713 Re-enabled default OpenCode agents (explore, general)");
41575
41624
  if (process.argv.includes("--clean")) {
41576
41625
  let cleaned = false;
41577
- if (fs17.existsSync(PLUGIN_CONFIG_PATH)) {
41578
- fs17.unlinkSync(PLUGIN_CONFIG_PATH);
41626
+ if (fs18.existsSync(PLUGIN_CONFIG_PATH)) {
41627
+ fs18.unlinkSync(PLUGIN_CONFIG_PATH);
41579
41628
  console.log(`\u2713 Removed plugin config: ${PLUGIN_CONFIG_PATH}`);
41580
41629
  cleaned = true;
41581
41630
  }
41582
- if (fs17.existsSync(PROMPTS_DIR)) {
41583
- fs17.rmSync(PROMPTS_DIR, { recursive: true });
41631
+ if (fs18.existsSync(PROMPTS_DIR)) {
41632
+ fs18.rmSync(PROMPTS_DIR, { recursive: true });
41584
41633
  console.log(`\u2713 Removed custom prompts: ${PROMPTS_DIR}`);
41585
41634
  cleaned = true;
41586
41635
  }