opencode-swarm 6.86.3 → 6.86.6

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
@@ -14230,11 +14230,17 @@ async function readLedgerEvents(directory) {
14230
14230
  const lines = content.trim().split(`
14231
14231
  `).filter((line) => line.trim() !== "");
14232
14232
  const events = [];
14233
+ let skippedCount = 0;
14233
14234
  for (const line of lines) {
14234
14235
  try {
14235
14236
  const event = JSON.parse(line);
14236
14237
  events.push(event);
14237
- } catch {}
14238
+ } catch {
14239
+ skippedCount++;
14240
+ }
14241
+ }
14242
+ if (skippedCount > 0) {
14243
+ console.warn(`[ledger] Skipped ${skippedCount} malformed line(s) in plan-ledger.jsonl`);
14238
14244
  }
14239
14245
  events.sort((a, b) => a.seq - b.seq);
14240
14246
  return events;
@@ -14331,10 +14337,13 @@ async function takeSnapshotEvent(directory, plan, options) {
14331
14337
  }, { planHashAfter: options?.planHashAfter });
14332
14338
  }
14333
14339
  async function replayFromLedger(directory, _options) {
14334
- const events = await readLedgerEvents(directory);
14340
+ const { events, truncated, badSuffix } = await readLedgerEventsWithIntegrity(directory);
14335
14341
  if (events.length === 0) {
14336
14342
  return null;
14337
14343
  }
14344
+ if (truncated && badSuffix !== null) {
14345
+ await quarantineLedgerSuffix(directory, badSuffix);
14346
+ }
14338
14347
  const targetPlanId = events[0].plan_id;
14339
14348
  const relevantEvents = events.filter((e) => e.plan_id === targetPlanId);
14340
14349
  {
@@ -14455,6 +14464,46 @@ function applyEventToPlan(plan, event) {
14455
14464
  throw new Error(`applyEventToPlan: unhandled event type "${event.event_type}" at seq ${event.seq}`);
14456
14465
  }
14457
14466
  }
14467
+ async function readLedgerEventsWithIntegrity(directory) {
14468
+ const ledgerPath = getLedgerPath(directory);
14469
+ if (!fs.existsSync(ledgerPath)) {
14470
+ return { events: [], truncated: false, badSuffix: null };
14471
+ }
14472
+ try {
14473
+ const content = fs.readFileSync(ledgerPath, "utf8");
14474
+ const lines = content.split(`
14475
+ `);
14476
+ const events = [];
14477
+ let truncated = false;
14478
+ let badSuffix = null;
14479
+ for (let i = 0;i < lines.length; i++) {
14480
+ const line = lines[i];
14481
+ if (line.trim() === "") {
14482
+ continue;
14483
+ }
14484
+ try {
14485
+ const event = JSON.parse(line);
14486
+ events.push(event);
14487
+ } catch {
14488
+ truncated = true;
14489
+ badSuffix = lines.slice(i).join(`
14490
+ `);
14491
+ break;
14492
+ }
14493
+ }
14494
+ events.sort((a, b) => a.seq - b.seq);
14495
+ return { events, truncated, badSuffix };
14496
+ } catch {
14497
+ return { events: [], truncated: false, badSuffix: null };
14498
+ }
14499
+ }
14500
+ async function quarantineLedgerSuffix(directory, badSuffix) {
14501
+ try {
14502
+ const quarantinePath = path2.join(directory, ".swarm", "plan-ledger.quarantine");
14503
+ fs.writeFileSync(quarantinePath, badSuffix, "utf8");
14504
+ console.warn(`[ledger] Corrupted suffix quarantined to ${path2.relative(directory, quarantinePath)}`);
14505
+ } catch {}
14506
+ }
14458
14507
  async function loadLastApprovedPlan(directory, expectedPlanId) {
14459
14508
  const events = await readLedgerEvents(directory);
14460
14509
  if (events.length === 0) {
@@ -17619,15 +17668,15 @@ __export(exports_config_doctor, {
17619
17668
  applySafeAutoFixes: () => applySafeAutoFixes
17620
17669
  });
17621
17670
  import * as crypto3 from "crypto";
17622
- import * as fs9 from "fs";
17671
+ import * as fs8 from "fs";
17623
17672
  import * as os5 from "os";
17624
- import * as path19 from "path";
17673
+ import * as path18 from "path";
17625
17674
  function getUserConfigDir3() {
17626
- return process.env.XDG_CONFIG_HOME || path19.join(os5.homedir(), ".config");
17675
+ return process.env.XDG_CONFIG_HOME || path18.join(os5.homedir(), ".config");
17627
17676
  }
17628
17677
  function getConfigPaths(directory) {
17629
- const userConfigPath = path19.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
17630
- const projectConfigPath = path19.join(directory, ".opencode", "opencode-swarm.json");
17678
+ const userConfigPath = path18.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
17679
+ const projectConfigPath = path18.join(directory, ".opencode", "opencode-swarm.json");
17631
17680
  return { userConfigPath, projectConfigPath };
17632
17681
  }
17633
17682
  function computeHash(content) {
@@ -17652,9 +17701,9 @@ function isValidConfigPath(configPath, directory) {
17652
17701
  const normalizedUser = userConfigPath.replace(/\\/g, "/");
17653
17702
  const normalizedProject = projectConfigPath.replace(/\\/g, "/");
17654
17703
  try {
17655
- const resolvedConfig = path19.resolve(configPath);
17656
- const resolvedUser = path19.resolve(normalizedUser);
17657
- const resolvedProject = path19.resolve(normalizedProject);
17704
+ const resolvedConfig = path18.resolve(configPath);
17705
+ const resolvedUser = path18.resolve(normalizedUser);
17706
+ const resolvedProject = path18.resolve(normalizedProject);
17658
17707
  return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
17659
17708
  } catch {
17660
17709
  return false;
@@ -17664,19 +17713,19 @@ function createConfigBackup(directory) {
17664
17713
  const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
17665
17714
  let configPath = projectConfigPath;
17666
17715
  let content = null;
17667
- if (fs9.existsSync(projectConfigPath)) {
17716
+ if (fs8.existsSync(projectConfigPath)) {
17668
17717
  try {
17669
- content = fs9.readFileSync(projectConfigPath, "utf-8");
17718
+ content = fs8.readFileSync(projectConfigPath, "utf-8");
17670
17719
  } catch (error93) {
17671
17720
  log("[ConfigDoctor] project config read failed", {
17672
17721
  error: error93 instanceof Error ? error93.message : String(error93)
17673
17722
  });
17674
17723
  }
17675
17724
  }
17676
- if (content === null && fs9.existsSync(userConfigPath)) {
17725
+ if (content === null && fs8.existsSync(userConfigPath)) {
17677
17726
  configPath = userConfigPath;
17678
17727
  try {
17679
- content = fs9.readFileSync(userConfigPath, "utf-8");
17728
+ content = fs8.readFileSync(userConfigPath, "utf-8");
17680
17729
  } catch (error93) {
17681
17730
  log("[ConfigDoctor] user config read failed", {
17682
17731
  error: error93 instanceof Error ? error93.message : String(error93)
@@ -17694,12 +17743,12 @@ function createConfigBackup(directory) {
17694
17743
  };
17695
17744
  }
17696
17745
  function writeBackupArtifact(directory, backup) {
17697
- const swarmDir = path19.join(directory, ".swarm");
17698
- if (!fs9.existsSync(swarmDir)) {
17699
- fs9.mkdirSync(swarmDir, { recursive: true });
17746
+ const swarmDir = path18.join(directory, ".swarm");
17747
+ if (!fs8.existsSync(swarmDir)) {
17748
+ fs8.mkdirSync(swarmDir, { recursive: true });
17700
17749
  }
17701
17750
  const backupFilename = `config-backup-${backup.createdAt}.json`;
17702
- const backupPath = path19.join(swarmDir, backupFilename);
17751
+ const backupPath = path18.join(swarmDir, backupFilename);
17703
17752
  const artifact = {
17704
17753
  createdAt: backup.createdAt,
17705
17754
  configPath: backup.configPath,
@@ -17707,15 +17756,15 @@ function writeBackupArtifact(directory, backup) {
17707
17756
  content: backup.content,
17708
17757
  preview: backup.content.substring(0, 500) + (backup.content.length > 500 ? "..." : "")
17709
17758
  };
17710
- fs9.writeFileSync(backupPath, JSON.stringify(artifact, null, 2), "utf-8");
17759
+ fs8.writeFileSync(backupPath, JSON.stringify(artifact, null, 2), "utf-8");
17711
17760
  return backupPath;
17712
17761
  }
17713
17762
  function restoreFromBackup(backupPath, directory) {
17714
- if (!fs9.existsSync(backupPath)) {
17763
+ if (!fs8.existsSync(backupPath)) {
17715
17764
  return null;
17716
17765
  }
17717
17766
  try {
17718
- const artifact = JSON.parse(fs9.readFileSync(backupPath, "utf-8"));
17767
+ const artifact = JSON.parse(fs8.readFileSync(backupPath, "utf-8"));
17719
17768
  if (!artifact.content || !artifact.configPath || !artifact.contentHash) {
17720
17769
  return null;
17721
17770
  }
@@ -17729,11 +17778,11 @@ function restoreFromBackup(backupPath, directory) {
17729
17778
  return null;
17730
17779
  }
17731
17780
  const targetPath = artifact.configPath;
17732
- const targetDir = path19.dirname(targetPath);
17733
- if (!fs9.existsSync(targetDir)) {
17734
- fs9.mkdirSync(targetDir, { recursive: true });
17781
+ const targetDir = path18.dirname(targetPath);
17782
+ if (!fs8.existsSync(targetDir)) {
17783
+ fs8.mkdirSync(targetDir, { recursive: true });
17735
17784
  }
17736
- fs9.writeFileSync(targetPath, artifact.content, "utf-8");
17785
+ fs8.writeFileSync(targetPath, artifact.content, "utf-8");
17737
17786
  return targetPath;
17738
17787
  } catch {
17739
17788
  return null;
@@ -17743,12 +17792,12 @@ function readConfigFromFile(directory) {
17743
17792
  const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
17744
17793
  let configPath = projectConfigPath;
17745
17794
  let configContent = null;
17746
- if (fs9.existsSync(projectConfigPath)) {
17795
+ if (fs8.existsSync(projectConfigPath)) {
17747
17796
  configPath = projectConfigPath;
17748
- configContent = fs9.readFileSync(projectConfigPath, "utf-8");
17749
- } else if (fs9.existsSync(userConfigPath)) {
17797
+ configContent = fs8.readFileSync(projectConfigPath, "utf-8");
17798
+ } else if (fs8.existsSync(userConfigPath)) {
17750
17799
  configPath = userConfigPath;
17751
- configContent = fs9.readFileSync(userConfigPath, "utf-8");
17800
+ configContent = fs8.readFileSync(userConfigPath, "utf-8");
17752
17801
  }
17753
17802
  if (configContent === null) {
17754
17803
  return null;
@@ -17760,9 +17809,9 @@ function readConfigFromFile(directory) {
17760
17809
  return null;
17761
17810
  }
17762
17811
  }
17763
- function validateConfigKey(path20, value, _config) {
17812
+ function validateConfigKey(path19, value, _config) {
17764
17813
  const findings = [];
17765
- switch (path20) {
17814
+ switch (path19) {
17766
17815
  case "agents": {
17767
17816
  if (value !== undefined) {
17768
17817
  findings.push({
@@ -18009,27 +18058,27 @@ function validateConfigKey(path20, value, _config) {
18009
18058
  }
18010
18059
  return findings;
18011
18060
  }
18012
- function walkConfigAndValidate(obj, path20, config3, findings) {
18061
+ function walkConfigAndValidate(obj, path19, config3, findings) {
18013
18062
  if (obj === null || obj === undefined) {
18014
18063
  return;
18015
18064
  }
18016
- if (path20 && typeof obj === "object" && !Array.isArray(obj)) {
18017
- const keyFindings = validateConfigKey(path20, obj, config3);
18065
+ if (path19 && typeof obj === "object" && !Array.isArray(obj)) {
18066
+ const keyFindings = validateConfigKey(path19, obj, config3);
18018
18067
  findings.push(...keyFindings);
18019
18068
  }
18020
18069
  if (typeof obj !== "object") {
18021
- const keyFindings = validateConfigKey(path20, obj, config3);
18070
+ const keyFindings = validateConfigKey(path19, obj, config3);
18022
18071
  findings.push(...keyFindings);
18023
18072
  return;
18024
18073
  }
18025
18074
  if (Array.isArray(obj)) {
18026
18075
  obj.forEach((item, index) => {
18027
- walkConfigAndValidate(item, `${path20}[${index}]`, config3, findings);
18076
+ walkConfigAndValidate(item, `${path19}[${index}]`, config3, findings);
18028
18077
  });
18029
18078
  return;
18030
18079
  }
18031
18080
  for (const [key, value] of Object.entries(obj)) {
18032
- const newPath = path20 ? `${path20}.${key}` : key;
18081
+ const newPath = path19 ? `${path19}.${key}` : key;
18033
18082
  walkConfigAndValidate(value, newPath, config3, findings);
18034
18083
  }
18035
18084
  }
@@ -18044,9 +18093,9 @@ function runConfigDoctor(config3, directory) {
18044
18093
  const hasAutoFixableIssues = findings.some((f) => f.autoFixable && f.proposedFix?.risk === "low");
18045
18094
  const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
18046
18095
  let configSource = "defaults";
18047
- if (fs9.existsSync(projectConfigPath)) {
18096
+ if (fs8.existsSync(projectConfigPath)) {
18048
18097
  configSource = projectConfigPath;
18049
- } else if (fs9.existsSync(userConfigPath)) {
18098
+ } else if (fs8.existsSync(userConfigPath)) {
18050
18099
  configSource = userConfigPath;
18051
18100
  }
18052
18101
  return {
@@ -18075,12 +18124,12 @@ function applySafeAutoFixes(directory, result) {
18075
18124
  const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
18076
18125
  let configPath = projectConfigPath;
18077
18126
  let configContent;
18078
- if (fs9.existsSync(projectConfigPath)) {
18127
+ if (fs8.existsSync(projectConfigPath)) {
18079
18128
  configPath = projectConfigPath;
18080
- configContent = fs9.readFileSync(projectConfigPath, "utf-8");
18081
- } else if (fs9.existsSync(userConfigPath)) {
18129
+ configContent = fs8.readFileSync(projectConfigPath, "utf-8");
18130
+ } else if (fs8.existsSync(userConfigPath)) {
18082
18131
  configPath = userConfigPath;
18083
- configContent = fs9.readFileSync(userConfigPath, "utf-8");
18132
+ configContent = fs8.readFileSync(userConfigPath, "utf-8");
18084
18133
  } else {
18085
18134
  return { appliedFixes, updatedConfigPath: null };
18086
18135
  }
@@ -18149,22 +18198,22 @@ function applySafeAutoFixes(directory, result) {
18149
18198
  }
18150
18199
  }
18151
18200
  if (appliedFixes.length > 0) {
18152
- const configDir = path19.dirname(configPath);
18153
- if (!fs9.existsSync(configDir)) {
18154
- fs9.mkdirSync(configDir, { recursive: true });
18201
+ const configDir = path18.dirname(configPath);
18202
+ if (!fs8.existsSync(configDir)) {
18203
+ fs8.mkdirSync(configDir, { recursive: true });
18155
18204
  }
18156
- fs9.writeFileSync(configPath, JSON.stringify(config3, null, 2), "utf-8");
18205
+ fs8.writeFileSync(configPath, JSON.stringify(config3, null, 2), "utf-8");
18157
18206
  updatedConfigPath = configPath;
18158
18207
  }
18159
18208
  return { appliedFixes, updatedConfigPath };
18160
18209
  }
18161
18210
  function writeDoctorArtifact(directory, result) {
18162
- const swarmDir = path19.join(directory, ".swarm");
18163
- if (!fs9.existsSync(swarmDir)) {
18164
- fs9.mkdirSync(swarmDir, { recursive: true });
18211
+ const swarmDir = path18.join(directory, ".swarm");
18212
+ if (!fs8.existsSync(swarmDir)) {
18213
+ fs8.mkdirSync(swarmDir, { recursive: true });
18165
18214
  }
18166
18215
  const artifactFilename = "config-doctor.json";
18167
- const artifactPath = path19.join(swarmDir, artifactFilename);
18216
+ const artifactPath = path18.join(swarmDir, artifactFilename);
18168
18217
  const guiOutput = {
18169
18218
  timestamp: result.timestamp,
18170
18219
  summary: result.summary,
@@ -18185,7 +18234,7 @@ function writeDoctorArtifact(directory, result) {
18185
18234
  } : null
18186
18235
  }))
18187
18236
  };
18188
- fs9.writeFileSync(artifactPath, JSON.stringify(guiOutput, null, 2), "utf-8");
18237
+ fs8.writeFileSync(artifactPath, JSON.stringify(guiOutput, null, 2), "utf-8");
18189
18238
  return artifactPath;
18190
18239
  }
18191
18240
  function shouldRunOnStartup(automationConfig) {
@@ -18525,9 +18574,78 @@ var init_evidence_summary_service = __esm(() => {
18525
18574
  });
18526
18575
 
18527
18576
  // src/cli/index.ts
18528
- import * as fs22 from "fs";
18577
+ import * as fs21 from "fs";
18529
18578
  import * as os6 from "os";
18530
- import * as path33 from "path";
18579
+ import * as path32 from "path";
18580
+ // package.json
18581
+ var package_default = {
18582
+ name: "opencode-swarm",
18583
+ version: "6.86.6",
18584
+ description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
18585
+ main: "dist/index.js",
18586
+ types: "dist/index.d.ts",
18587
+ bin: {
18588
+ "opencode-swarm": "./dist/cli/index.js"
18589
+ },
18590
+ type: "module",
18591
+ engines: {
18592
+ bun: ">=1.0.0"
18593
+ },
18594
+ license: "MIT",
18595
+ repository: {
18596
+ type: "git",
18597
+ url: "https://github.com/zaxbysauce/opencode-swarm.git"
18598
+ },
18599
+ publishConfig: {
18600
+ access: "public",
18601
+ registry: "https://registry.npmjs.org/"
18602
+ },
18603
+ keywords: [
18604
+ "opencode",
18605
+ "opencode-plugin",
18606
+ "ai",
18607
+ "agents",
18608
+ "orchestration",
18609
+ "swarm",
18610
+ "multi-agent",
18611
+ "llm"
18612
+ ],
18613
+ files: [
18614
+ "dist",
18615
+ "dist/lang/grammars",
18616
+ "README.md",
18617
+ "LICENSE"
18618
+ ],
18619
+ scripts: {
18620
+ clean: `bun -e "require('fs').rmSync('dist',{recursive:true,force:true})"`,
18621
+ build: "bun run clean && bun run scripts/copy-grammars.ts && bun build src/index.ts --outdir dist --target bun --format esm && bun build src/cli/index.ts --outdir dist/cli --target bun --format esm && bun run scripts/copy-grammars.ts --to-dist && tsc --emitDeclarationOnly",
18622
+ typecheck: "tsc --noEmit",
18623
+ test: "bun test",
18624
+ lint: "biome lint .",
18625
+ format: "biome format . --write",
18626
+ check: "biome check --write .",
18627
+ dev: "bun run build && opencode",
18628
+ prepublishOnly: "bun run build"
18629
+ },
18630
+ dependencies: {
18631
+ "@opencode-ai/plugin": "^1.1.53",
18632
+ "@opencode-ai/sdk": "^1.1.53",
18633
+ "@vscode/tree-sitter-wasm": "^0.3.0",
18634
+ "p-limit": "^7.3.0",
18635
+ picomatch: "^4.0.4",
18636
+ "proper-lockfile": "^4.1.2",
18637
+ "quick-lru": "^7.3.0",
18638
+ "web-tree-sitter": "^0.25.0",
18639
+ zod: "^4.1.8"
18640
+ },
18641
+ devDependencies: {
18642
+ "@biomejs/biome": "2.3.14",
18643
+ "@types/picomatch": "^4.0.3",
18644
+ "bun-types": "1.3.8",
18645
+ "js-yaml": "^4.1.1",
18646
+ typescript: "^5.7.3"
18647
+ }
18648
+ };
18531
18649
 
18532
18650
  // src/commands/acknowledge-spec-drift.ts
18533
18651
  init_utils2();
@@ -18604,71 +18722,6 @@ ${warnings.map((w) => ` - ${w}`).join(`
18604
18722
  return baseMessage + warningMessage + cautionMessage;
18605
18723
  }
18606
18724
 
18607
- // src/commands/agents.ts
18608
- function handleAgentsCommand(agents, guardrails) {
18609
- const entries = Object.entries(agents);
18610
- if (entries.length === 0) {
18611
- return "No agents registered.";
18612
- }
18613
- const lines = [`## Registered Agents (${entries.length} total)`, ""];
18614
- for (const [key, agent] of entries) {
18615
- const model = agent.config.model || "default";
18616
- const temp = agent.config.temperature !== undefined ? agent.config.temperature.toString() : "default";
18617
- const tools = agent.config.tools || {};
18618
- const isReadOnly = tools.write === false || tools.edit === false;
18619
- const access = isReadOnly ? "\uD83D\uDD12 read-only" : "\u270F\uFE0F read-write";
18620
- const desc = agent.description || agent.config.description || "";
18621
- const hasCustomProfile = guardrails?.profiles?.[key] !== undefined;
18622
- const profileIndicator = hasCustomProfile ? " | \u26A1 custom limits" : "";
18623
- lines.push(`- **${key}** | model: \`${model}\` | temp: ${temp} | ${access}${profileIndicator}`);
18624
- if (desc) {
18625
- lines.push(` ${desc}`);
18626
- }
18627
- }
18628
- if (guardrails?.profiles && Object.keys(guardrails.profiles).length > 0) {
18629
- lines.push("", "### Guardrail Profiles", "");
18630
- for (const [profileName, profile] of Object.entries(guardrails.profiles)) {
18631
- const overrides = [];
18632
- if (profile.max_tool_calls !== undefined) {
18633
- overrides.push(`max_tool_calls=${profile.max_tool_calls}`);
18634
- }
18635
- if (profile.max_duration_minutes !== undefined) {
18636
- overrides.push(`max_duration_minutes=${profile.max_duration_minutes}`);
18637
- }
18638
- if (profile.max_repetitions !== undefined) {
18639
- overrides.push(`max_repetitions=${profile.max_repetitions}`);
18640
- }
18641
- if (profile.max_consecutive_errors !== undefined) {
18642
- overrides.push(`max_consecutive_errors=${profile.max_consecutive_errors}`);
18643
- }
18644
- if (profile.warning_threshold !== undefined) {
18645
- overrides.push(`warning_threshold=${profile.warning_threshold}`);
18646
- }
18647
- const overrideStr = overrides.length > 0 ? overrides.join(", ") : "no overrides";
18648
- lines.push(`- **${profileName}**: ${overrideStr}`);
18649
- }
18650
- }
18651
- return lines.join(`
18652
- `);
18653
- }
18654
-
18655
- // src/commands/analyze.ts
18656
- async function handleAnalyzeCommand(_directory, args) {
18657
- const description = args.join(" ").trim();
18658
- if (description) {
18659
- return `[MODE: ANALYZE] ${description}`;
18660
- }
18661
- return "[MODE: ANALYZE] Please analyze the spec against the plan using MODE: ANALYZE.";
18662
- }
18663
-
18664
- // src/config/loader.ts
18665
- import * as fs2 from "fs";
18666
- import * as os2 from "os";
18667
- import * as path4 from "path";
18668
-
18669
- // src/config/schema.ts
18670
- init_zod();
18671
-
18672
18725
  // src/tools/tool-names.ts
18673
18726
  var TOOL_NAMES = [
18674
18727
  "diff",
@@ -18981,6 +19034,57 @@ for (const [agentName, tools] of Object.entries(AGENT_TOOL_MAP)) {
18981
19034
  }
18982
19035
 
18983
19036
  // src/config/schema.ts
19037
+ init_zod();
19038
+ var KNOWN_SWARM_PREFIXES = [
19039
+ "paid",
19040
+ "local",
19041
+ "cloud",
19042
+ "enterprise",
19043
+ "mega",
19044
+ "default",
19045
+ "custom",
19046
+ "team",
19047
+ "project",
19048
+ "swarm",
19049
+ "synthetic"
19050
+ ];
19051
+ var SEPARATORS = ["_", "-", " "];
19052
+ function stripKnownSwarmPrefix(agentName) {
19053
+ if (!agentName)
19054
+ return agentName;
19055
+ const normalized = agentName.toLowerCase();
19056
+ let stripped = normalized;
19057
+ let previous = "";
19058
+ while (stripped !== previous) {
19059
+ previous = stripped;
19060
+ for (const prefix of KNOWN_SWARM_PREFIXES) {
19061
+ for (const sep2 of SEPARATORS) {
19062
+ const prefixWithSep = prefix + sep2;
19063
+ if (stripped.startsWith(prefixWithSep)) {
19064
+ stripped = stripped.slice(prefixWithSep.length);
19065
+ break;
19066
+ }
19067
+ }
19068
+ if (stripped !== previous)
19069
+ break;
19070
+ }
19071
+ }
19072
+ if (ALL_AGENT_NAMES.includes(stripped)) {
19073
+ return stripped;
19074
+ }
19075
+ for (const agent of ALL_AGENT_NAMES) {
19076
+ for (const sep2 of SEPARATORS) {
19077
+ const suffix = sep2 + agent;
19078
+ if (normalized.endsWith(suffix)) {
19079
+ return agent;
19080
+ }
19081
+ }
19082
+ if (normalized === agent) {
19083
+ return agent;
19084
+ }
19085
+ }
19086
+ return agentName;
19087
+ }
18984
19088
  var AgentOverrideConfigSchema = exports_external.object({
18985
19089
  model: exports_external.string().optional(),
18986
19090
  variant: exports_external.string().min(1).optional(),
@@ -19585,6 +19689,7 @@ var PluginConfigSchema = exports_external.object({
19585
19689
  council: CouncilConfigSchema.optional(),
19586
19690
  parallelization: ParallelizationConfigSchema.optional(),
19587
19691
  turbo_mode: exports_external.boolean().default(false).optional(),
19692
+ quiet: exports_external.boolean().default(false).optional(),
19588
19693
  full_auto: exports_external.object({
19589
19694
  enabled: exports_external.boolean().default(false),
19590
19695
  critic_model: exports_external.string().optional(),
@@ -19599,7 +19704,78 @@ var PluginConfigSchema = exports_external.object({
19599
19704
  })
19600
19705
  });
19601
19706
 
19707
+ // src/commands/agents.ts
19708
+ function handleAgentsCommand(agents, guardrails) {
19709
+ const entries = Object.entries(agents);
19710
+ if (entries.length === 0) {
19711
+ return "No agents registered.";
19712
+ }
19713
+ const allAgentKeys = entries.map(([key]) => key);
19714
+ const registeredBaseNames = allAgentKeys.map((key) => stripKnownSwarmPrefix(key)).filter((stripped) => ALL_SUBAGENT_NAMES.includes(stripped));
19715
+ const unregistered = ALL_SUBAGENT_NAMES.filter((name) => !registeredBaseNames.includes(name));
19716
+ const hasUnregistered = unregistered.length > 0;
19717
+ const headerLabel = hasUnregistered ? `${entries.length} registered + ${unregistered.length} unregistered` : `${entries.length} total`;
19718
+ const lines = [`## Registered Agents (${headerLabel})`, ""];
19719
+ for (const [key, agent] of entries) {
19720
+ const model = agent.config.model || "default";
19721
+ const temp = agent.config.temperature !== undefined ? agent.config.temperature.toString() : "default";
19722
+ const tools = agent.config.tools || {};
19723
+ const isReadOnly = tools.write === false || tools.edit === false;
19724
+ const access = isReadOnly ? "\uD83D\uDD12 read-only" : "\u270F\uFE0F read-write";
19725
+ const desc = agent.description || agent.config.description || "";
19726
+ const hasCustomProfile = guardrails?.profiles?.[key] !== undefined;
19727
+ const profileIndicator = hasCustomProfile ? " | \u26A1 custom limits" : "";
19728
+ lines.push(`- **${key}** | model: \`${model}\` | temp: ${temp} | ${access}${profileIndicator}`);
19729
+ if (desc) {
19730
+ lines.push(` ${desc}`);
19731
+ }
19732
+ }
19733
+ if (hasUnregistered) {
19734
+ lines.push("", "### Unregistered Subagents");
19735
+ for (const name of unregistered) {
19736
+ lines.push(`- **${name}** (requires configuration)`);
19737
+ }
19738
+ }
19739
+ if (guardrails?.profiles && Object.keys(guardrails.profiles).length > 0) {
19740
+ lines.push("", "### Guardrail Profiles", "");
19741
+ for (const [profileName, profile] of Object.entries(guardrails.profiles)) {
19742
+ const overrides = [];
19743
+ if (profile.max_tool_calls !== undefined) {
19744
+ overrides.push(`max_tool_calls=${profile.max_tool_calls}`);
19745
+ }
19746
+ if (profile.max_duration_minutes !== undefined) {
19747
+ overrides.push(`max_duration_minutes=${profile.max_duration_minutes}`);
19748
+ }
19749
+ if (profile.max_repetitions !== undefined) {
19750
+ overrides.push(`max_repetitions=${profile.max_repetitions}`);
19751
+ }
19752
+ if (profile.max_consecutive_errors !== undefined) {
19753
+ overrides.push(`max_consecutive_errors=${profile.max_consecutive_errors}`);
19754
+ }
19755
+ if (profile.warning_threshold !== undefined) {
19756
+ overrides.push(`warning_threshold=${profile.warning_threshold}`);
19757
+ }
19758
+ const overrideStr = overrides.length > 0 ? overrides.join(", ") : "no overrides";
19759
+ lines.push(`- **${profileName}**: ${overrideStr}`);
19760
+ }
19761
+ }
19762
+ return lines.join(`
19763
+ `);
19764
+ }
19765
+
19766
+ // src/commands/analyze.ts
19767
+ async function handleAnalyzeCommand(_directory, args) {
19768
+ const description = args.join(" ").trim();
19769
+ if (description) {
19770
+ return `[MODE: ANALYZE] ${description}`;
19771
+ }
19772
+ return "[MODE: ANALYZE] Please analyze the spec against the plan using MODE: ANALYZE.";
19773
+ }
19774
+
19602
19775
  // src/config/loader.ts
19776
+ import * as fs2 from "fs";
19777
+ import * as os2 from "os";
19778
+ import * as path4 from "path";
19603
19779
  var CONFIG_FILENAME = "opencode-swarm.json";
19604
19780
  var MAX_CONFIG_FILE_BYTES = 102400;
19605
19781
  function getUserConfigDir() {
@@ -20292,6 +20468,9 @@ var DeltaSpecSchema = exports_external.union([
20292
20468
  SwarmSpecSchema,
20293
20469
  SpecDeltaSchema
20294
20470
  ]);
20471
+ // src/services/warning-buffer.ts
20472
+ var deferredWarnings = [];
20473
+
20295
20474
  // src/agents/index.ts
20296
20475
  var warnedAgents = new Set;
20297
20476
 
@@ -33621,8 +33800,8 @@ async function handleClarifyCommand(_directory, args) {
33621
33800
 
33622
33801
  // src/commands/close.ts
33623
33802
  import { execFileSync } from "child_process";
33624
- import { promises as fs8 } from "fs";
33625
- import path13 from "path";
33803
+ import { promises as fs7 } from "fs";
33804
+ import path12 from "path";
33626
33805
  init_manager2();
33627
33806
 
33628
33807
  // src/git/branch.ts
@@ -34311,31 +34490,10 @@ async function runAutoPromotion(directory, config3) {
34311
34490
  // src/commands/close.ts
34312
34491
  init_utils2();
34313
34492
 
34314
- // src/plan/checkpoint.ts
34315
- init_plan_schema();
34316
- init_ledger();
34317
- init_manager();
34318
- import * as fs7 from "fs";
34319
- import * as path11 from "path";
34320
- async function writeCheckpoint(directory) {
34321
- try {
34322
- const plan = await loadPlan(directory);
34323
- if (!plan)
34324
- return;
34325
- const jsonPath = path11.join(directory, "SWARM_PLAN.json");
34326
- const mdPath = path11.join(directory, "SWARM_PLAN.md");
34327
- fs7.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
34328
- const md = derivePlanMarkdown(plan);
34329
- fs7.writeFileSync(mdPath, md, "utf8");
34330
- } catch (error93) {
34331
- console.warn(`[checkpoint] Failed to write SWARM_PLAN checkpoint: ${error93 instanceof Error ? error93.message : String(error93)}`);
34332
- }
34333
- }
34334
-
34335
34493
  // src/session/snapshot-writer.ts
34336
34494
  init_utils2();
34337
34495
  import { mkdirSync as mkdirSync7, renameSync as renameSync5 } from "fs";
34338
- import * as path12 from "path";
34496
+ import * as path11 from "path";
34339
34497
  init_utils();
34340
34498
  var _writeInFlight = Promise.resolve();
34341
34499
  function serializeAgentSession(s) {
@@ -34426,7 +34584,7 @@ async function writeSnapshot(directory, state) {
34426
34584
  }
34427
34585
  const content = JSON.stringify(snapshot, null, 2);
34428
34586
  const resolvedPath = validateSwarmPath(directory, "session/state.json");
34429
- const dir = path12.dirname(resolvedPath);
34587
+ const dir = path11.dirname(resolvedPath);
34430
34588
  mkdirSync7(dir, { recursive: true });
34431
34589
  const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
34432
34590
  await Bun.write(tempPath, content);
@@ -34819,21 +34977,21 @@ var ACTIVE_STATE_TO_CLEAN = [
34819
34977
  ];
34820
34978
  async function handleCloseCommand(directory, args) {
34821
34979
  const planPath = validateSwarmPath(directory, "plan.json");
34822
- const swarmDir = path13.join(directory, ".swarm");
34980
+ const swarmDir = path12.join(directory, ".swarm");
34823
34981
  let planExists = false;
34824
34982
  let planData = {
34825
- title: path13.basename(directory) || "Ad-hoc session",
34983
+ title: path12.basename(directory) || "Ad-hoc session",
34826
34984
  phases: []
34827
34985
  };
34828
34986
  try {
34829
- const content = await fs8.readFile(planPath, "utf-8");
34987
+ const content = await fs7.readFile(planPath, "utf-8");
34830
34988
  planData = JSON.parse(content);
34831
34989
  planExists = true;
34832
34990
  } catch (error93) {
34833
34991
  if (error93?.code !== "ENOENT") {
34834
34992
  return `\u274C Failed to read plan.json: ${error93 instanceof Error ? error93.message : String(error93)}`;
34835
34993
  }
34836
- const swarmDirExists = await fs8.access(swarmDir).then(() => true).catch(() => false);
34994
+ const swarmDirExists = await fs7.access(swarmDir).then(() => true).catch(() => false);
34837
34995
  if (!swarmDirExists) {
34838
34996
  return `\u274C No .swarm/ directory found in ${directory}. Run /swarm close from the project root, or run /swarm plan first.`;
34839
34997
  }
@@ -34927,10 +35085,10 @@ async function handleCloseCommand(directory, args) {
34927
35085
  warnings.push(`Session retrospective write threw: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
34928
35086
  }
34929
35087
  }
34930
- const lessonsFilePath = path13.join(swarmDir, "close-lessons.md");
35088
+ const lessonsFilePath = path12.join(swarmDir, "close-lessons.md");
34931
35089
  let explicitLessons = [];
34932
35090
  try {
34933
- const lessonsText = await fs8.readFile(lessonsFilePath, "utf-8");
35091
+ const lessonsText = await fs7.readFile(lessonsFilePath, "utf-8");
34934
35092
  explicitLessons = lessonsText.split(`
34935
35093
  `).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
34936
35094
  } catch {}
@@ -34944,7 +35102,7 @@ async function handleCloseCommand(directory, args) {
34944
35102
  console.warn("[close-command] curateAndStoreSwarm error:", error93);
34945
35103
  }
34946
35104
  if (curationSucceeded && explicitLessons.length > 0) {
34947
- await fs8.unlink(lessonsFilePath).catch(() => {});
35105
+ await fs7.unlink(lessonsFilePath).catch(() => {});
34948
35106
  }
34949
35107
  if (planExists && !planAlreadyDone) {
34950
35108
  for (const phase of phases) {
@@ -34964,7 +35122,7 @@ async function handleCloseCommand(directory, args) {
34964
35122
  }
34965
35123
  }
34966
35124
  try {
34967
- await fs8.writeFile(planPath, JSON.stringify(planData, null, 2), "utf-8");
35125
+ await fs7.writeFile(planPath, JSON.stringify(planData, null, 2), "utf-8");
34968
35126
  } catch (error93) {
34969
35127
  const msg = error93 instanceof Error ? error93.message : String(error93);
34970
35128
  warnings.push(`Failed to persist terminal plan.json state: ${msg}`);
@@ -34973,53 +35131,53 @@ async function handleCloseCommand(directory, args) {
34973
35131
  }
34974
35132
  const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
34975
35133
  const suffix = Math.random().toString(36).slice(2, 8);
34976
- const archiveDir = path13.join(swarmDir, "archive", `swarm-${timestamp}-${suffix}`);
35134
+ const archiveDir = path12.join(swarmDir, "archive", `swarm-${timestamp}-${suffix}`);
34977
35135
  let archiveResult = "";
34978
35136
  let archivedFileCount = 0;
34979
35137
  const archivedActiveStateFiles = new Set;
34980
35138
  try {
34981
- await fs8.mkdir(archiveDir, { recursive: true });
35139
+ await fs7.mkdir(archiveDir, { recursive: true });
34982
35140
  for (const artifact of ARCHIVE_ARTIFACTS) {
34983
- const srcPath = path13.join(swarmDir, artifact);
34984
- const destPath = path13.join(archiveDir, artifact);
35141
+ const srcPath = path12.join(swarmDir, artifact);
35142
+ const destPath = path12.join(archiveDir, artifact);
34985
35143
  try {
34986
- await fs8.copyFile(srcPath, destPath);
35144
+ await fs7.copyFile(srcPath, destPath);
34987
35145
  archivedFileCount++;
34988
35146
  if (ACTIVE_STATE_TO_CLEAN.includes(artifact)) {
34989
35147
  archivedActiveStateFiles.add(artifact);
34990
35148
  }
34991
35149
  } catch {}
34992
35150
  }
34993
- const evidenceDir = path13.join(swarmDir, "evidence");
34994
- const archiveEvidenceDir = path13.join(archiveDir, "evidence");
35151
+ const evidenceDir = path12.join(swarmDir, "evidence");
35152
+ const archiveEvidenceDir = path12.join(archiveDir, "evidence");
34995
35153
  try {
34996
- const evidenceEntries = await fs8.readdir(evidenceDir);
35154
+ const evidenceEntries = await fs7.readdir(evidenceDir);
34997
35155
  if (evidenceEntries.length > 0) {
34998
- await fs8.mkdir(archiveEvidenceDir, { recursive: true });
35156
+ await fs7.mkdir(archiveEvidenceDir, { recursive: true });
34999
35157
  for (const entry of evidenceEntries) {
35000
- const srcEntry = path13.join(evidenceDir, entry);
35001
- const destEntry = path13.join(archiveEvidenceDir, entry);
35158
+ const srcEntry = path12.join(evidenceDir, entry);
35159
+ const destEntry = path12.join(archiveEvidenceDir, entry);
35002
35160
  try {
35003
- const stat = await fs8.stat(srcEntry);
35161
+ const stat = await fs7.stat(srcEntry);
35004
35162
  if (stat.isDirectory()) {
35005
- await fs8.mkdir(destEntry, { recursive: true });
35006
- const subEntries = await fs8.readdir(srcEntry);
35163
+ await fs7.mkdir(destEntry, { recursive: true });
35164
+ const subEntries = await fs7.readdir(srcEntry);
35007
35165
  for (const sub of subEntries) {
35008
- await fs8.copyFile(path13.join(srcEntry, sub), path13.join(destEntry, sub)).catch(() => {});
35166
+ await fs7.copyFile(path12.join(srcEntry, sub), path12.join(destEntry, sub)).catch(() => {});
35009
35167
  }
35010
35168
  } else {
35011
- await fs8.copyFile(srcEntry, destEntry);
35169
+ await fs7.copyFile(srcEntry, destEntry);
35012
35170
  }
35013
35171
  archivedFileCount++;
35014
35172
  } catch {}
35015
35173
  }
35016
35174
  }
35017
35175
  } catch {}
35018
- const sessionStatePath = path13.join(swarmDir, "session", "state.json");
35176
+ const sessionStatePath = path12.join(swarmDir, "session", "state.json");
35019
35177
  try {
35020
- const archiveSessionDir = path13.join(archiveDir, "session");
35021
- await fs8.mkdir(archiveSessionDir, { recursive: true });
35022
- await fs8.copyFile(sessionStatePath, path13.join(archiveSessionDir, "state.json"));
35178
+ const archiveSessionDir = path12.join(archiveDir, "session");
35179
+ await fs7.mkdir(archiveSessionDir, { recursive: true });
35180
+ await fs7.copyFile(sessionStatePath, path12.join(archiveSessionDir, "state.json"));
35023
35181
  archivedFileCount++;
35024
35182
  } catch {}
35025
35183
  archiveResult = `Archived ${archivedFileCount} artifact(s) to .swarm/archive/swarm-${timestamp}/`;
@@ -35042,9 +35200,9 @@ async function handleCloseCommand(directory, args) {
35042
35200
  warnings.push(`Preserved ${artifact} because it was not successfully archived.`);
35043
35201
  continue;
35044
35202
  }
35045
- const filePath = path13.join(swarmDir, artifact);
35203
+ const filePath = path12.join(swarmDir, artifact);
35046
35204
  try {
35047
- await fs8.unlink(filePath);
35205
+ await fs7.unlink(filePath);
35048
35206
  cleanedFiles.push(artifact);
35049
35207
  } catch {}
35050
35208
  }
@@ -35052,23 +35210,42 @@ async function handleCloseCommand(directory, args) {
35052
35210
  warnings.push("Skipped active-state cleanup because no active-state files were archived. Files preserved to prevent data loss.");
35053
35211
  }
35054
35212
  try {
35055
- const swarmFiles = await fs8.readdir(swarmDir);
35213
+ const swarmFiles = await fs7.readdir(swarmDir);
35056
35214
  const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
35057
35215
  for (const backup of configBackups) {
35058
35216
  try {
35059
- await fs8.unlink(path13.join(swarmDir, backup));
35217
+ await fs7.unlink(path12.join(swarmDir, backup));
35060
35218
  configBackupsRemoved++;
35061
35219
  } catch {}
35062
35220
  }
35063
35221
  const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
35064
35222
  for (const sibling of ledgerSiblings) {
35065
35223
  try {
35066
- await fs8.unlink(path13.join(swarmDir, sibling));
35224
+ await fs7.unlink(path12.join(swarmDir, sibling));
35067
35225
  } catch {}
35068
35226
  }
35069
35227
  } catch {}
35228
+ let swarmPlanFilesRemoved = 0;
35229
+ const swarmPlanJsonPath = path12.join(directory, "SWARM_PLAN.json");
35230
+ const swarmPlanMdPath = path12.join(directory, "SWARM_PLAN.md");
35231
+ try {
35232
+ await fs7.unlink(swarmPlanJsonPath);
35233
+ swarmPlanFilesRemoved++;
35234
+ } catch (err) {
35235
+ if (err?.code !== "ENOENT") {
35236
+ warnings.push(`Failed to remove SWARM_PLAN.json: ${err instanceof Error ? err.message : String(err)}`);
35237
+ }
35238
+ }
35239
+ try {
35240
+ await fs7.unlink(swarmPlanMdPath);
35241
+ swarmPlanFilesRemoved++;
35242
+ } catch (err) {
35243
+ if (err?.code !== "ENOENT") {
35244
+ warnings.push(`Failed to remove SWARM_PLAN.md: ${err instanceof Error ? err.message : String(err)}`);
35245
+ }
35246
+ }
35070
35247
  clearAllScopes(directory);
35071
- const contextPath = path13.join(swarmDir, "context.md");
35248
+ const contextPath = path12.join(swarmDir, "context.md");
35072
35249
  const contextContent = [
35073
35250
  "# Context",
35074
35251
  "",
@@ -35081,7 +35258,7 @@ async function handleCloseCommand(directory, args) {
35081
35258
  ].join(`
35082
35259
  `);
35083
35260
  try {
35084
- await fs8.writeFile(contextPath, contextContent, "utf-8");
35261
+ await fs7.writeFile(contextPath, contextContent, "utf-8");
35085
35262
  } catch (error93) {
35086
35263
  const msg = error93 instanceof Error ? error93.message : String(error93);
35087
35264
  warnings.push(`Failed to reset context.md: ${msg}`);
@@ -35183,6 +35360,9 @@ async function handleCloseCommand(directory, args) {
35183
35360
  ] : [],
35184
35361
  "- Reset context.md for next session",
35185
35362
  ...configBackupsRemoved > 0 ? [`- Removed ${configBackupsRemoved} stale config backup file(s)`] : [],
35363
+ ...swarmPlanFilesRemoved > 0 ? [
35364
+ `- Removed ${swarmPlanFilesRemoved} root-level SWARM_PLAN checkpoint artifact(s)`
35365
+ ] : [],
35186
35366
  ...prunedBranches.length > 0 ? [
35187
35367
  `- Pruned ${prunedBranches.length} stale local git branch(es): ${prunedBranches.join(", ")}`
35188
35368
  ] : [],
@@ -35212,7 +35392,7 @@ async function handleCloseCommand(directory, args) {
35212
35392
  ].join(`
35213
35393
  `);
35214
35394
  try {
35215
- await fs8.writeFile(closeSummaryPath, summaryContent, "utf-8");
35395
+ await fs7.writeFile(closeSummaryPath, summaryContent, "utf-8");
35216
35396
  } catch (error93) {
35217
35397
  const msg = error93 instanceof Error ? error93.message : String(error93);
35218
35398
  warnings.push(`Failed to write close-summary.md: ${msg}`);
@@ -35225,7 +35405,6 @@ async function handleCloseCommand(directory, args) {
35225
35405
  warnings.push(`flushPendingSnapshot failed: ${msg}`);
35226
35406
  console.warn("[close-command] flushPendingSnapshot error:", error93);
35227
35407
  }
35228
- await writeCheckpoint(directory).catch(() => {});
35229
35408
  const preservedClient = swarmState.opencodeClient;
35230
35409
  const preservedFullAutoFlag = swarmState.fullAutoEnabledInConfig;
35231
35410
  const preservedCuratorInitNames = swarmState.curatorInitAgentNames;
@@ -35269,14 +35448,14 @@ ${otherWarnings.map((w) => `- ${w}`).join(`
35269
35448
 
35270
35449
  // src/commands/config.ts
35271
35450
  import * as os4 from "os";
35272
- import * as path14 from "path";
35451
+ import * as path13 from "path";
35273
35452
  function getUserConfigDir2() {
35274
- return process.env.XDG_CONFIG_HOME || path14.join(os4.homedir(), ".config");
35453
+ return process.env.XDG_CONFIG_HOME || path13.join(os4.homedir(), ".config");
35275
35454
  }
35276
35455
  async function handleConfigCommand(directory, _args) {
35277
35456
  const config3 = loadPluginConfig(directory);
35278
- const userConfigPath = path14.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
35279
- const projectConfigPath = path14.join(directory, ".opencode", "opencode-swarm.json");
35457
+ const userConfigPath = path13.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
35458
+ const projectConfigPath = path13.join(directory, ".opencode", "opencode-swarm.json");
35280
35459
  const lines = [
35281
35460
  "## Swarm Configuration",
35282
35461
  "",
@@ -35362,7 +35541,7 @@ async function handleCouncilCommand(_directory, args) {
35362
35541
  }
35363
35542
 
35364
35543
  // src/hooks/hive-promoter.ts
35365
- import path15 from "path";
35544
+ import path14 from "path";
35366
35545
 
35367
35546
  // src/background/event-bus.ts
35368
35547
  init_utils();
@@ -35617,7 +35796,7 @@ async function promoteToHive(directory, lesson, category) {
35617
35796
  schema_version: 1,
35618
35797
  created_at: new Date().toISOString(),
35619
35798
  updated_at: new Date().toISOString(),
35620
- source_project: path15.basename(directory) || "unknown",
35799
+ source_project: path14.basename(directory) || "unknown",
35621
35800
  encounter_score: 1
35622
35801
  };
35623
35802
  await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
@@ -35695,14 +35874,14 @@ function formatCurationSummary(summary) {
35695
35874
  }
35696
35875
 
35697
35876
  // src/commands/dark-matter.ts
35698
- import path17 from "path";
35877
+ import path16 from "path";
35699
35878
 
35700
35879
  // src/tools/co-change-analyzer.ts
35701
35880
  init_zod();
35702
35881
  import * as child_process3 from "child_process";
35703
35882
  import { randomUUID } from "crypto";
35704
35883
  import { readdir, readFile as readFile3, stat } from "fs/promises";
35705
- import * as path16 from "path";
35884
+ import * as path15 from "path";
35706
35885
  import { promisify } from "util";
35707
35886
  function getExecFileAsync() {
35708
35887
  return promisify(child_process3.execFile);
@@ -35804,7 +35983,7 @@ async function scanSourceFiles(dir) {
35804
35983
  try {
35805
35984
  const entries = await readdir(dir, { withFileTypes: true });
35806
35985
  for (const entry of entries) {
35807
- const fullPath = path16.join(dir, entry.name);
35986
+ const fullPath = path15.join(dir, entry.name);
35808
35987
  if (entry.isDirectory()) {
35809
35988
  if (skipDirs.has(entry.name)) {
35810
35989
  continue;
@@ -35812,7 +35991,7 @@ async function scanSourceFiles(dir) {
35812
35991
  const subFiles = await scanSourceFiles(fullPath);
35813
35992
  results.push(...subFiles);
35814
35993
  } else if (entry.isFile()) {
35815
- const ext = path16.extname(entry.name);
35994
+ const ext = path15.extname(entry.name);
35816
35995
  if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
35817
35996
  results.push(fullPath);
35818
35997
  }
@@ -35834,8 +36013,8 @@ async function getStaticEdges(directory) {
35834
36013
  continue;
35835
36014
  }
35836
36015
  try {
35837
- const sourceDir = path16.dirname(sourceFile);
35838
- const resolvedPath = path16.resolve(sourceDir, importPath);
36016
+ const sourceDir = path15.dirname(sourceFile);
36017
+ const resolvedPath = path15.resolve(sourceDir, importPath);
35839
36018
  const extensions = [
35840
36019
  "",
35841
36020
  ".ts",
@@ -35860,8 +36039,8 @@ async function getStaticEdges(directory) {
35860
36039
  if (!targetFile) {
35861
36040
  continue;
35862
36041
  }
35863
- const relSource = path16.relative(directory, sourceFile).replace(/\\/g, "/");
35864
- const relTarget = path16.relative(directory, targetFile).replace(/\\/g, "/");
36042
+ const relSource = path15.relative(directory, sourceFile).replace(/\\/g, "/");
36043
+ const relTarget = path15.relative(directory, targetFile).replace(/\\/g, "/");
35865
36044
  const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
35866
36045
  edges.add(key);
35867
36046
  } catch {}
@@ -35873,7 +36052,7 @@ async function getStaticEdges(directory) {
35873
36052
  function isTestImplementationPair(fileA, fileB) {
35874
36053
  const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
35875
36054
  const getBaseName = (filePath) => {
35876
- const base = path16.basename(filePath);
36055
+ const base = path15.basename(filePath);
35877
36056
  for (const pattern of testPatterns) {
35878
36057
  if (base.endsWith(pattern)) {
35879
36058
  return base.slice(0, -pattern.length);
@@ -35883,16 +36062,16 @@ function isTestImplementationPair(fileA, fileB) {
35883
36062
  };
35884
36063
  const baseA = getBaseName(fileA);
35885
36064
  const baseB = getBaseName(fileB);
35886
- return baseA === baseB && baseA !== path16.basename(fileA) && baseA !== path16.basename(fileB);
36065
+ return baseA === baseB && baseA !== path15.basename(fileA) && baseA !== path15.basename(fileB);
35887
36066
  }
35888
36067
  function hasSharedPrefix(fileA, fileB) {
35889
- const dirA = path16.dirname(fileA);
35890
- const dirB = path16.dirname(fileB);
36068
+ const dirA = path15.dirname(fileA);
36069
+ const dirB = path15.dirname(fileB);
35891
36070
  if (dirA !== dirB) {
35892
36071
  return false;
35893
36072
  }
35894
- const baseA = path16.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
35895
- const baseB = path16.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
36073
+ const baseA = path15.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
36074
+ const baseB = path15.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
35896
36075
  if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
35897
36076
  return true;
35898
36077
  }
@@ -35946,8 +36125,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
35946
36125
  const entries = [];
35947
36126
  const now = new Date().toISOString();
35948
36127
  for (const pair of pairs.slice(0, 10)) {
35949
- const baseA = path16.basename(pair.fileA);
35950
- const baseB = path16.basename(pair.fileB);
36128
+ const baseA = path15.basename(pair.fileA);
36129
+ const baseB = path15.basename(pair.fileB);
35951
36130
  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.`;
35952
36131
  if (lesson.length > 280) {
35953
36132
  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.`;
@@ -36057,7 +36236,7 @@ async function handleDarkMatterCommand(directory, args) {
36057
36236
  const output = formatDarkMatterOutput(pairs);
36058
36237
  if (pairs.length > 0) {
36059
36238
  try {
36060
- const projectName = path17.basename(path17.resolve(directory));
36239
+ const projectName = path16.basename(path16.resolve(directory));
36061
36240
  const entries = darkMatterToKnowledgeEntries(pairs, projectName);
36062
36241
  if (entries.length > 0) {
36063
36242
  const knowledgePath = resolveSwarmKnowledgePath(directory);
@@ -36078,12 +36257,13 @@ async function handleDarkMatterCommand(directory, args) {
36078
36257
 
36079
36258
  // src/services/diagnose-service.ts
36080
36259
  import * as child_process4 from "child_process";
36081
- import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync5 } from "fs";
36082
- import path18 from "path";
36260
+ import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as readFileSync5, statSync as statSync5 } from "fs";
36261
+ import path17 from "path";
36083
36262
  import { fileURLToPath } from "url";
36084
36263
  init_manager2();
36085
36264
  init_utils2();
36086
36265
  init_manager();
36266
+ var { version: version3 } = package_default;
36087
36267
  function validateTaskDag(plan) {
36088
36268
  const allTaskIds = new Set;
36089
36269
  for (const phase of plan.phases) {
@@ -36379,7 +36559,7 @@ async function checkSpecStaleness(directory, plan) {
36379
36559
  };
36380
36560
  }
36381
36561
  async function checkConfigParseability(directory) {
36382
- const configPath = path18.join(directory, ".opencode/opencode-swarm.json");
36562
+ const configPath = path17.join(directory, ".opencode/opencode-swarm.json");
36383
36563
  if (!existsSync8(configPath)) {
36384
36564
  return {
36385
36565
  name: "Config Parseability",
@@ -36388,7 +36568,7 @@ async function checkConfigParseability(directory) {
36388
36568
  };
36389
36569
  }
36390
36570
  try {
36391
- const content = readFileSync6(configPath, "utf-8");
36571
+ const content = readFileSync5(configPath, "utf-8");
36392
36572
  JSON.parse(content);
36393
36573
  return {
36394
36574
  name: "Config Parseability",
@@ -36408,7 +36588,7 @@ function resolveGrammarDir(thisDir) {
36408
36588
  const normalized = thisDir.replace(/\\/g, "/");
36409
36589
  const isSource = normalized.endsWith("/src/services");
36410
36590
  const isCliBundle = normalized.endsWith("/cli");
36411
- return isSource || isCliBundle ? path18.join(thisDir, "..", "lang", "grammars") : path18.join(thisDir, "lang", "grammars");
36591
+ return isSource || isCliBundle ? path17.join(thisDir, "..", "lang", "grammars") : path17.join(thisDir, "lang", "grammars");
36412
36592
  }
36413
36593
  async function checkGrammarWasmFiles() {
36414
36594
  const grammarFiles = [
@@ -36432,14 +36612,14 @@ async function checkGrammarWasmFiles() {
36432
36612
  "tree-sitter-ini.wasm",
36433
36613
  "tree-sitter-regex.wasm"
36434
36614
  ];
36435
- const thisDir = path18.dirname(fileURLToPath(import.meta.url));
36615
+ const thisDir = path17.dirname(fileURLToPath(import.meta.url));
36436
36616
  const grammarDir = resolveGrammarDir(thisDir);
36437
36617
  const missing = [];
36438
- if (!existsSync8(path18.join(grammarDir, "tree-sitter.wasm"))) {
36618
+ if (!existsSync8(path17.join(grammarDir, "tree-sitter.wasm"))) {
36439
36619
  missing.push("tree-sitter.wasm (core runtime)");
36440
36620
  }
36441
36621
  for (const file3 of grammarFiles) {
36442
- if (!existsSync8(path18.join(grammarDir, file3))) {
36622
+ if (!existsSync8(path17.join(grammarDir, file3))) {
36443
36623
  missing.push(file3);
36444
36624
  }
36445
36625
  }
@@ -36457,7 +36637,7 @@ async function checkGrammarWasmFiles() {
36457
36637
  };
36458
36638
  }
36459
36639
  async function checkCheckpointManifest(directory) {
36460
- const manifestPath = path18.join(directory, ".swarm/checkpoints.json");
36640
+ const manifestPath = path17.join(directory, ".swarm/checkpoints.json");
36461
36641
  if (!existsSync8(manifestPath)) {
36462
36642
  return {
36463
36643
  name: "Checkpoint Manifest",
@@ -36466,7 +36646,7 @@ async function checkCheckpointManifest(directory) {
36466
36646
  };
36467
36647
  }
36468
36648
  try {
36469
- const content = readFileSync6(manifestPath, "utf-8");
36649
+ const content = readFileSync5(manifestPath, "utf-8");
36470
36650
  const parsed = JSON.parse(content);
36471
36651
  if (!parsed.checkpoints || !Array.isArray(parsed.checkpoints)) {
36472
36652
  return {
@@ -36509,7 +36689,7 @@ async function checkCheckpointManifest(directory) {
36509
36689
  }
36510
36690
  }
36511
36691
  async function checkEventStreamIntegrity(directory) {
36512
- const eventsPath = path18.join(directory, ".swarm/events.jsonl");
36692
+ const eventsPath = path17.join(directory, ".swarm/events.jsonl");
36513
36693
  if (!existsSync8(eventsPath)) {
36514
36694
  return {
36515
36695
  name: "Event Stream",
@@ -36518,7 +36698,7 @@ async function checkEventStreamIntegrity(directory) {
36518
36698
  };
36519
36699
  }
36520
36700
  try {
36521
- const content = readFileSync6(eventsPath, "utf-8");
36701
+ const content = readFileSync5(eventsPath, "utf-8");
36522
36702
  const lines = content.split(`
36523
36703
  `).filter((line) => line.trim() !== "");
36524
36704
  let malformedCount = 0;
@@ -36550,7 +36730,7 @@ async function checkEventStreamIntegrity(directory) {
36550
36730
  }
36551
36731
  }
36552
36732
  async function checkSteeringDirectives(directory) {
36553
- const eventsPath = path18.join(directory, ".swarm/events.jsonl");
36733
+ const eventsPath = path17.join(directory, ".swarm/events.jsonl");
36554
36734
  if (!existsSync8(eventsPath)) {
36555
36735
  return {
36556
36736
  name: "Steering Directives",
@@ -36559,7 +36739,7 @@ async function checkSteeringDirectives(directory) {
36559
36739
  };
36560
36740
  }
36561
36741
  try {
36562
- const content = readFileSync6(eventsPath, "utf-8");
36742
+ const content = readFileSync5(eventsPath, "utf-8");
36563
36743
  const lines = content.split(`
36564
36744
  `).filter((line) => line.trim() !== "");
36565
36745
  const directivesIssued = [];
@@ -36606,7 +36786,7 @@ async function checkCurator(directory) {
36606
36786
  detail: "Disabled (enable via curator.enabled)"
36607
36787
  };
36608
36788
  }
36609
- const summaryPath = path18.join(directory, ".swarm/curator-summary.json");
36789
+ const summaryPath = path17.join(directory, ".swarm/curator-summary.json");
36610
36790
  if (!existsSync8(summaryPath)) {
36611
36791
  return {
36612
36792
  name: "Curator",
@@ -36615,7 +36795,7 @@ async function checkCurator(directory) {
36615
36795
  };
36616
36796
  }
36617
36797
  try {
36618
- const content = readFileSync6(summaryPath, "utf-8");
36798
+ const content = readFileSync5(summaryPath, "utf-8");
36619
36799
  const parsed = JSON.parse(content);
36620
36800
  if (typeof parsed.schema_version !== "number" || parsed.schema_version !== 1) {
36621
36801
  return {
@@ -36650,6 +36830,11 @@ async function checkCurator(directory) {
36650
36830
  }
36651
36831
  async function getDiagnoseData(directory) {
36652
36832
  const checks5 = [];
36833
+ checks5.push({
36834
+ name: "Version",
36835
+ status: "\u2705",
36836
+ detail: version3
36837
+ });
36653
36838
  const plan = await loadPlanJsonOnly(directory);
36654
36839
  if (plan) {
36655
36840
  checks5.push({
@@ -36754,7 +36939,7 @@ async function getDiagnoseData(directory) {
36754
36939
  checks5.push(await checkSteeringDirectives(directory));
36755
36940
  checks5.push(await checkCurator(directory));
36756
36941
  try {
36757
- const evidenceDir = path18.join(directory, ".swarm", "evidence");
36942
+ const evidenceDir = path17.join(directory, ".swarm", "evidence");
36758
36943
  const snapshotFiles = existsSync8(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
36759
36944
  if (snapshotFiles.length > 0) {
36760
36945
  const latest = snapshotFiles.sort().pop();
@@ -36777,6 +36962,13 @@ async function getDiagnoseData(directory) {
36777
36962
  detail: "No snapshots yet (snapshots written on next session start)"
36778
36963
  });
36779
36964
  }
36965
+ if (deferredWarnings.length > 0) {
36966
+ checks5.push({
36967
+ name: "Deferred Warnings",
36968
+ status: "\u26A0\uFE0F",
36969
+ detail: `${deferredWarnings.length} warning(s) deferred from init (run with verbose logs for details)`
36970
+ });
36971
+ }
36780
36972
  const passCount = checks5.filter((c) => c.status === "\u2705").length;
36781
36973
  const totalCount = checks5.length;
36782
36974
  const allPassed = passCount === totalCount;
@@ -36795,6 +36987,14 @@ function formatDiagnoseMarkdown(diagnose) {
36795
36987
  "",
36796
36988
  `**Result**: ${diagnose.allPassed ? "\u2705 All checks passed" : `\u26A0\uFE0F ${diagnose.passCount}/${diagnose.totalCount} checks passed`}`
36797
36989
  ];
36990
+ if (deferredWarnings.length > 0) {
36991
+ lines.push("");
36992
+ lines.push("## Deferred Warnings");
36993
+ lines.push("");
36994
+ for (const warning of deferredWarnings) {
36995
+ lines.push(`- ${warning}`);
36996
+ }
36997
+ }
36798
36998
  return lines.join(`
36799
36999
  `);
36800
37000
  }
@@ -36806,16 +37006,16 @@ async function handleDiagnoseCommand(directory, _args) {
36806
37006
  init_config_doctor();
36807
37007
 
36808
37008
  // src/services/tool-doctor.ts
36809
- import * as fs11 from "fs";
36810
- import * as path21 from "path";
36811
-
36812
- // src/build/discovery.ts
36813
37009
  import * as fs10 from "fs";
36814
37010
  import * as path20 from "path";
36815
37011
 
37012
+ // src/build/discovery.ts
37013
+ import * as fs9 from "fs";
37014
+ import * as path19 from "path";
37015
+
36816
37016
  // src/lang/detector.ts
36817
37017
  import { access as access2, readdir as readdir2 } from "fs/promises";
36818
- import { extname as extname2, join as join16 } from "path";
37018
+ import { extname as extname2, join as join15 } from "path";
36819
37019
 
36820
37020
  // src/lang/profiles.ts
36821
37021
  class LanguageRegistry {
@@ -37795,7 +37995,7 @@ async function detectProjectLanguages(projectDir) {
37795
37995
  if (detectFile.includes("*") || detectFile.includes("?"))
37796
37996
  continue;
37797
37997
  try {
37798
- await access2(join16(dir, detectFile));
37998
+ await access2(join15(dir, detectFile));
37799
37999
  detected.add(profile.id);
37800
38000
  break;
37801
38001
  } catch {}
@@ -37816,7 +38016,7 @@ async function detectProjectLanguages(projectDir) {
37816
38016
  const topEntries = await readdir2(projectDir, { withFileTypes: true });
37817
38017
  for (const entry of topEntries) {
37818
38018
  if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
37819
- await scanDir(join16(projectDir, entry.name));
38019
+ await scanDir(join15(projectDir, entry.name));
37820
38020
  }
37821
38021
  }
37822
38022
  } catch {}
@@ -37971,16 +38171,16 @@ function findBuildFiles(workingDir, patterns) {
37971
38171
  if (pattern.includes("*")) {
37972
38172
  const dir = workingDir;
37973
38173
  try {
37974
- const files = fs10.readdirSync(dir);
38174
+ const files = fs9.readdirSync(dir);
37975
38175
  const regex = simpleGlobToRegex(pattern);
37976
38176
  const matches = files.filter((f) => regex.test(f));
37977
38177
  if (matches.length > 0) {
37978
- return path20.join(dir, matches[0]);
38178
+ return path19.join(dir, matches[0]);
37979
38179
  }
37980
38180
  } catch {}
37981
38181
  } else {
37982
- const filePath = path20.join(workingDir, pattern);
37983
- if (fs10.existsSync(filePath)) {
38182
+ const filePath = path19.join(workingDir, pattern);
38183
+ if (fs9.existsSync(filePath)) {
37984
38184
  return filePath;
37985
38185
  }
37986
38186
  }
@@ -37988,12 +38188,12 @@ function findBuildFiles(workingDir, patterns) {
37988
38188
  return null;
37989
38189
  }
37990
38190
  function getRepoDefinedScripts(workingDir, scripts) {
37991
- const packageJsonPath = path20.join(workingDir, "package.json");
37992
- if (!fs10.existsSync(packageJsonPath)) {
38191
+ const packageJsonPath = path19.join(workingDir, "package.json");
38192
+ if (!fs9.existsSync(packageJsonPath)) {
37993
38193
  return [];
37994
38194
  }
37995
38195
  try {
37996
- const content = fs10.readFileSync(packageJsonPath, "utf-8");
38196
+ const content = fs9.readFileSync(packageJsonPath, "utf-8");
37997
38197
  const pkg = JSON.parse(content);
37998
38198
  if (!pkg.scripts || typeof pkg.scripts !== "object") {
37999
38199
  return [];
@@ -38029,8 +38229,8 @@ function findAllBuildFiles(workingDir) {
38029
38229
  const regex = simpleGlobToRegex(pattern);
38030
38230
  findFilesRecursive(workingDir, regex, allBuildFiles);
38031
38231
  } else {
38032
- const filePath = path20.join(workingDir, pattern);
38033
- if (fs10.existsSync(filePath)) {
38232
+ const filePath = path19.join(workingDir, pattern);
38233
+ if (fs9.existsSync(filePath)) {
38034
38234
  allBuildFiles.add(filePath);
38035
38235
  }
38036
38236
  }
@@ -38040,9 +38240,9 @@ function findAllBuildFiles(workingDir) {
38040
38240
  }
38041
38241
  function findFilesRecursive(dir, regex, results) {
38042
38242
  try {
38043
- const entries = fs10.readdirSync(dir, { withFileTypes: true });
38243
+ const entries = fs9.readdirSync(dir, { withFileTypes: true });
38044
38244
  for (const entry of entries) {
38045
- const fullPath = path20.join(dir, entry.name);
38245
+ const fullPath = path19.join(dir, entry.name);
38046
38246
  if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
38047
38247
  findFilesRecursive(fullPath, regex, results);
38048
38248
  } else if (entry.isFile() && regex.test(entry.name)) {
@@ -38065,8 +38265,8 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
38065
38265
  let foundCommand = false;
38066
38266
  for (const cmd of sortedCommands) {
38067
38267
  if (cmd.detectFile) {
38068
- const detectFilePath = path20.join(workingDir, cmd.detectFile);
38069
- if (!fs10.existsSync(detectFilePath)) {
38268
+ const detectFilePath = path19.join(workingDir, cmd.detectFile);
38269
+ if (!fs9.existsSync(detectFilePath)) {
38070
38270
  continue;
38071
38271
  }
38072
38272
  }
@@ -38189,7 +38389,7 @@ var BINARY_CHECKLIST = [
38189
38389
  function extractRegisteredToolKeys(indexPath) {
38190
38390
  const registeredKeys = new Set;
38191
38391
  try {
38192
- const content = fs11.readFileSync(indexPath, "utf-8");
38392
+ const content = fs10.readFileSync(indexPath, "utf-8");
38193
38393
  const toolBlockMatch = content.match(/tool:\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}/s);
38194
38394
  if (!toolBlockMatch) {
38195
38395
  return registeredKeys;
@@ -38240,9 +38440,9 @@ function checkBinaryReadiness() {
38240
38440
  }
38241
38441
  function runToolDoctor(_directory, pluginRoot) {
38242
38442
  const findings = [];
38243
- const resolvedPluginRoot = pluginRoot ?? path21.resolve(import.meta.dir, "..", "..");
38244
- const indexPath = path21.join(resolvedPluginRoot, "src", "index.ts");
38245
- if (!fs11.existsSync(indexPath)) {
38443
+ const resolvedPluginRoot = pluginRoot ?? path20.resolve(import.meta.dir, "..", "..");
38444
+ const indexPath = path20.join(resolvedPluginRoot, "src", "index.ts");
38445
+ if (!fs10.existsSync(indexPath)) {
38246
38446
  return {
38247
38447
  findings: [
38248
38448
  {
@@ -39162,12 +39362,12 @@ async function handleHistoryCommand(directory, _args) {
39162
39362
  }
39163
39363
  // src/hooks/knowledge-migrator.ts
39164
39364
  import { randomUUID as randomUUID2 } from "crypto";
39165
- import { existsSync as existsSync12, readFileSync as readFileSync10 } from "fs";
39365
+ import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
39166
39366
  import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
39167
- import * as path22 from "path";
39367
+ import * as path21 from "path";
39168
39368
  async function migrateContextToKnowledge(directory, config3) {
39169
- const sentinelPath = path22.join(directory, ".swarm", ".knowledge-migrated");
39170
- const contextPath = path22.join(directory, ".swarm", "context.md");
39369
+ const sentinelPath = path21.join(directory, ".swarm", ".knowledge-migrated");
39370
+ const contextPath = path21.join(directory, ".swarm", "context.md");
39171
39371
  const knowledgePath = resolveSwarmKnowledgePath(directory);
39172
39372
  if (existsSync12(sentinelPath)) {
39173
39373
  return {
@@ -39363,16 +39563,16 @@ function truncateLesson(text) {
39363
39563
  return `${text.slice(0, 277)}...`;
39364
39564
  }
39365
39565
  function inferProjectName(directory) {
39366
- const packageJsonPath = path22.join(directory, "package.json");
39566
+ const packageJsonPath = path21.join(directory, "package.json");
39367
39567
  if (existsSync12(packageJsonPath)) {
39368
39568
  try {
39369
- const pkg = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
39569
+ const pkg = JSON.parse(readFileSync9(packageJsonPath, "utf-8"));
39370
39570
  if (pkg.name && typeof pkg.name === "string") {
39371
39571
  return pkg.name;
39372
39572
  }
39373
39573
  } catch {}
39374
39574
  }
39375
- return path22.basename(directory);
39575
+ return path21.basename(directory);
39376
39576
  }
39377
39577
  async function writeSentinel(sentinelPath, migrated, dropped) {
39378
39578
  const sentinel = {
@@ -39384,7 +39584,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
39384
39584
  schema_version: 1,
39385
39585
  migration_tool: "knowledge-migrator.ts"
39386
39586
  };
39387
- await mkdir3(path22.dirname(sentinelPath), { recursive: true });
39587
+ await mkdir3(path21.dirname(sentinelPath), { recursive: true });
39388
39588
  await writeFile4(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
39389
39589
  }
39390
39590
 
@@ -39620,13 +39820,13 @@ async function handlePlanCommand(directory, args) {
39620
39820
  // src/services/preflight-service.ts
39621
39821
  init_manager2();
39622
39822
  init_manager();
39623
- import * as fs18 from "fs";
39624
- import * as path29 from "path";
39823
+ import * as fs17 from "fs";
39824
+ import * as path28 from "path";
39625
39825
 
39626
39826
  // src/tools/lint.ts
39627
39827
  init_zod();
39628
- import * as fs12 from "fs";
39629
- import * as path23 from "path";
39828
+ import * as fs11 from "fs";
39829
+ import * as path22 from "path";
39630
39830
  init_utils();
39631
39831
 
39632
39832
  // src/utils/path-security.ts
@@ -39672,9 +39872,9 @@ function validateArgs(args) {
39672
39872
  }
39673
39873
  function getLinterCommand(linter, mode, projectDir) {
39674
39874
  const isWindows = process.platform === "win32";
39675
- const binDir = path23.join(projectDir, "node_modules", ".bin");
39676
- const biomeBin = isWindows ? path23.join(binDir, "biome.EXE") : path23.join(binDir, "biome");
39677
- const eslintBin = isWindows ? path23.join(binDir, "eslint.cmd") : path23.join(binDir, "eslint");
39875
+ const binDir = path22.join(projectDir, "node_modules", ".bin");
39876
+ const biomeBin = isWindows ? path22.join(binDir, "biome.EXE") : path22.join(binDir, "biome");
39877
+ const eslintBin = isWindows ? path22.join(binDir, "eslint.cmd") : path22.join(binDir, "eslint");
39678
39878
  switch (linter) {
39679
39879
  case "biome":
39680
39880
  if (mode === "fix") {
@@ -39690,7 +39890,7 @@ function getLinterCommand(linter, mode, projectDir) {
39690
39890
  }
39691
39891
  function getAdditionalLinterCommand(linter, mode, cwd) {
39692
39892
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
39693
- const gradlew = fs12.existsSync(path23.join(cwd, gradlewName)) ? path23.join(cwd, gradlewName) : null;
39893
+ const gradlew = fs11.existsSync(path22.join(cwd, gradlewName)) ? path22.join(cwd, gradlewName) : null;
39694
39894
  switch (linter) {
39695
39895
  case "ruff":
39696
39896
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -39724,12 +39924,12 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
39724
39924
  }
39725
39925
  }
39726
39926
  function detectRuff(cwd) {
39727
- if (fs12.existsSync(path23.join(cwd, "ruff.toml")))
39927
+ if (fs11.existsSync(path22.join(cwd, "ruff.toml")))
39728
39928
  return isCommandAvailable("ruff");
39729
39929
  try {
39730
- const pyproject = path23.join(cwd, "pyproject.toml");
39731
- if (fs12.existsSync(pyproject)) {
39732
- const content = fs12.readFileSync(pyproject, "utf-8");
39930
+ const pyproject = path22.join(cwd, "pyproject.toml");
39931
+ if (fs11.existsSync(pyproject)) {
39932
+ const content = fs11.readFileSync(pyproject, "utf-8");
39733
39933
  if (content.includes("[tool.ruff]"))
39734
39934
  return isCommandAvailable("ruff");
39735
39935
  }
@@ -39737,21 +39937,21 @@ function detectRuff(cwd) {
39737
39937
  return false;
39738
39938
  }
39739
39939
  function detectClippy(cwd) {
39740
- return fs12.existsSync(path23.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
39940
+ return fs11.existsSync(path22.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
39741
39941
  }
39742
39942
  function detectGolangciLint(cwd) {
39743
- return fs12.existsSync(path23.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
39943
+ return fs11.existsSync(path22.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
39744
39944
  }
39745
39945
  function detectCheckstyle(cwd) {
39746
- const hasMaven = fs12.existsSync(path23.join(cwd, "pom.xml"));
39747
- const hasGradle = fs12.existsSync(path23.join(cwd, "build.gradle")) || fs12.existsSync(path23.join(cwd, "build.gradle.kts"));
39748
- const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs12.existsSync(path23.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
39946
+ const hasMaven = fs11.existsSync(path22.join(cwd, "pom.xml"));
39947
+ const hasGradle = fs11.existsSync(path22.join(cwd, "build.gradle")) || fs11.existsSync(path22.join(cwd, "build.gradle.kts"));
39948
+ const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs11.existsSync(path22.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
39749
39949
  return (hasMaven || hasGradle) && hasBinary;
39750
39950
  }
39751
39951
  function detectKtlint(cwd) {
39752
- const hasKotlin = fs12.existsSync(path23.join(cwd, "build.gradle.kts")) || fs12.existsSync(path23.join(cwd, "build.gradle")) || (() => {
39952
+ const hasKotlin = fs11.existsSync(path22.join(cwd, "build.gradle.kts")) || fs11.existsSync(path22.join(cwd, "build.gradle")) || (() => {
39753
39953
  try {
39754
- return fs12.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
39954
+ return fs11.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
39755
39955
  } catch {
39756
39956
  return false;
39757
39957
  }
@@ -39760,7 +39960,7 @@ function detectKtlint(cwd) {
39760
39960
  }
39761
39961
  function detectDotnetFormat(cwd) {
39762
39962
  try {
39763
- const files = fs12.readdirSync(cwd);
39963
+ const files = fs11.readdirSync(cwd);
39764
39964
  const hasCsproj = files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"));
39765
39965
  return hasCsproj && isCommandAvailable("dotnet");
39766
39966
  } catch {
@@ -39768,14 +39968,14 @@ function detectDotnetFormat(cwd) {
39768
39968
  }
39769
39969
  }
39770
39970
  function detectCppcheck(cwd) {
39771
- if (fs12.existsSync(path23.join(cwd, "CMakeLists.txt"))) {
39971
+ if (fs11.existsSync(path22.join(cwd, "CMakeLists.txt"))) {
39772
39972
  return isCommandAvailable("cppcheck");
39773
39973
  }
39774
39974
  try {
39775
- const dirsToCheck = [cwd, path23.join(cwd, "src")];
39975
+ const dirsToCheck = [cwd, path22.join(cwd, "src")];
39776
39976
  const hasCpp = dirsToCheck.some((dir) => {
39777
39977
  try {
39778
- return fs12.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
39978
+ return fs11.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
39779
39979
  } catch {
39780
39980
  return false;
39781
39981
  }
@@ -39786,13 +39986,13 @@ function detectCppcheck(cwd) {
39786
39986
  }
39787
39987
  }
39788
39988
  function detectSwiftlint(cwd) {
39789
- return fs12.existsSync(path23.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
39989
+ return fs11.existsSync(path22.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
39790
39990
  }
39791
39991
  function detectDartAnalyze(cwd) {
39792
- return fs12.existsSync(path23.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
39992
+ return fs11.existsSync(path22.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
39793
39993
  }
39794
39994
  function detectRubocop(cwd) {
39795
- return (fs12.existsSync(path23.join(cwd, "Gemfile")) || fs12.existsSync(path23.join(cwd, "gems.rb")) || fs12.existsSync(path23.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
39995
+ return (fs11.existsSync(path22.join(cwd, "Gemfile")) || fs11.existsSync(path22.join(cwd, "gems.rb")) || fs11.existsSync(path22.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
39796
39996
  }
39797
39997
  function detectAdditionalLinter(cwd) {
39798
39998
  if (detectRuff(cwd))
@@ -39820,10 +40020,10 @@ function detectAdditionalLinter(cwd) {
39820
40020
  function findBinInAncestors(startDir, binName) {
39821
40021
  let dir = startDir;
39822
40022
  while (true) {
39823
- const candidate = path23.join(dir, "node_modules", ".bin", binName);
39824
- if (fs12.existsSync(candidate))
40023
+ const candidate = path22.join(dir, "node_modules", ".bin", binName);
40024
+ if (fs11.existsSync(candidate))
39825
40025
  return candidate;
39826
- const parent = path23.dirname(dir);
40026
+ const parent = path22.dirname(dir);
39827
40027
  if (parent === dir)
39828
40028
  break;
39829
40029
  dir = parent;
@@ -39832,11 +40032,11 @@ function findBinInAncestors(startDir, binName) {
39832
40032
  }
39833
40033
  function findBinInEnvPath(binName) {
39834
40034
  const searchPath = process.env.PATH ?? "";
39835
- for (const dir of searchPath.split(path23.delimiter)) {
40035
+ for (const dir of searchPath.split(path22.delimiter)) {
39836
40036
  if (!dir)
39837
40037
  continue;
39838
- const candidate = path23.join(dir, binName);
39839
- if (fs12.existsSync(candidate))
40038
+ const candidate = path22.join(dir, binName);
40039
+ if (fs11.existsSync(candidate))
39840
40040
  return candidate;
39841
40041
  }
39842
40042
  return null;
@@ -39844,17 +40044,17 @@ function findBinInEnvPath(binName) {
39844
40044
  async function detectAvailableLinter(directory) {
39845
40045
  if (!directory)
39846
40046
  return null;
39847
- if (!fs12.existsSync(directory))
40047
+ if (!fs11.existsSync(directory))
39848
40048
  return null;
39849
40049
  const projectDir = directory;
39850
40050
  const isWindows = process.platform === "win32";
39851
- const biomeBin = isWindows ? path23.join(projectDir, "node_modules", ".bin", "biome.EXE") : path23.join(projectDir, "node_modules", ".bin", "biome");
39852
- const eslintBin = isWindows ? path23.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path23.join(projectDir, "node_modules", ".bin", "eslint");
40051
+ const biomeBin = isWindows ? path22.join(projectDir, "node_modules", ".bin", "biome.EXE") : path22.join(projectDir, "node_modules", ".bin", "biome");
40052
+ const eslintBin = isWindows ? path22.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path22.join(projectDir, "node_modules", ".bin", "eslint");
39853
40053
  const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
39854
40054
  if (localResult)
39855
40055
  return localResult;
39856
- const biomeAncestor = findBinInAncestors(path23.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
39857
- const eslintAncestor = findBinInAncestors(path23.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
40056
+ const biomeAncestor = findBinInAncestors(path22.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
40057
+ const eslintAncestor = findBinInAncestors(path22.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
39858
40058
  if (biomeAncestor || eslintAncestor) {
39859
40059
  return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
39860
40060
  }
@@ -39877,7 +40077,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
39877
40077
  const result = await Promise.race([biomeExit, timeout]);
39878
40078
  if (result === "timeout") {
39879
40079
  biomeProc.kill();
39880
- } else if (biomeProc.exitCode === 0 && fs12.existsSync(biomeBin)) {
40080
+ } else if (biomeProc.exitCode === 0 && fs11.existsSync(biomeBin)) {
39881
40081
  return "biome";
39882
40082
  }
39883
40083
  } catch {}
@@ -39891,7 +40091,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
39891
40091
  const result = await Promise.race([eslintExit, timeout]);
39892
40092
  if (result === "timeout") {
39893
40093
  eslintProc.kill();
39894
- } else if (eslintProc.exitCode === 0 && fs12.existsSync(eslintBin)) {
40094
+ } else if (eslintProc.exitCode === 0 && fs11.existsSync(eslintBin)) {
39895
40095
  return "eslint";
39896
40096
  }
39897
40097
  } catch {}
@@ -40062,8 +40262,8 @@ For Rust: rustup component add clippy`
40062
40262
 
40063
40263
  // src/tools/secretscan.ts
40064
40264
  init_zod();
40065
- import * as fs13 from "fs";
40066
- import * as path24 from "path";
40265
+ import * as fs12 from "fs";
40266
+ import * as path23 from "path";
40067
40267
  var MAX_FILE_PATH_LENGTH = 500;
40068
40268
  var MAX_FILE_SIZE_BYTES = 512 * 1024;
40069
40269
  var MAX_FILES_SCANNED = 1000;
@@ -40290,11 +40490,11 @@ function isGlobOrPathPattern(pattern) {
40290
40490
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
40291
40491
  }
40292
40492
  function loadSecretScanIgnore(scanDir) {
40293
- const ignorePath = path24.join(scanDir, ".secretscanignore");
40493
+ const ignorePath = path23.join(scanDir, ".secretscanignore");
40294
40494
  try {
40295
- if (!fs13.existsSync(ignorePath))
40495
+ if (!fs12.existsSync(ignorePath))
40296
40496
  return [];
40297
- const content = fs13.readFileSync(ignorePath, "utf8");
40497
+ const content = fs12.readFileSync(ignorePath, "utf8");
40298
40498
  const patterns = [];
40299
40499
  for (const rawLine of content.split(/\r?\n/)) {
40300
40500
  const line = rawLine.trim();
@@ -40313,7 +40513,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
40313
40513
  if (exactNames.has(entry))
40314
40514
  return true;
40315
40515
  for (const pattern of globPatterns) {
40316
- if (path24.matchesGlob(relPath, pattern))
40516
+ if (path23.matchesGlob(relPath, pattern))
40317
40517
  return true;
40318
40518
  }
40319
40519
  return false;
@@ -40334,7 +40534,7 @@ function validateDirectoryInput(dir) {
40334
40534
  return null;
40335
40535
  }
40336
40536
  function isBinaryFile(filePath, buffer) {
40337
- const ext = path24.extname(filePath).toLowerCase();
40537
+ const ext = path23.extname(filePath).toLowerCase();
40338
40538
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
40339
40539
  return true;
40340
40540
  }
@@ -40409,11 +40609,11 @@ function createRedactedContext(line, findings) {
40409
40609
  result += line.slice(lastEnd);
40410
40610
  return result;
40411
40611
  }
40412
- var O_NOFOLLOW = process.platform !== "win32" ? fs13.constants.O_NOFOLLOW : undefined;
40612
+ var O_NOFOLLOW = process.platform !== "win32" ? fs12.constants.O_NOFOLLOW : undefined;
40413
40613
  function scanFileForSecrets(filePath) {
40414
40614
  const findings = [];
40415
40615
  try {
40416
- const lstat = fs13.lstatSync(filePath);
40616
+ const lstat = fs12.lstatSync(filePath);
40417
40617
  if (lstat.isSymbolicLink()) {
40418
40618
  return findings;
40419
40619
  }
@@ -40422,14 +40622,14 @@ function scanFileForSecrets(filePath) {
40422
40622
  }
40423
40623
  let buffer;
40424
40624
  if (O_NOFOLLOW !== undefined) {
40425
- const fd = fs13.openSync(filePath, "r", O_NOFOLLOW);
40625
+ const fd = fs12.openSync(filePath, "r", O_NOFOLLOW);
40426
40626
  try {
40427
- buffer = fs13.readFileSync(fd);
40627
+ buffer = fs12.readFileSync(fd);
40428
40628
  } finally {
40429
- fs13.closeSync(fd);
40629
+ fs12.closeSync(fd);
40430
40630
  }
40431
40631
  } else {
40432
- buffer = fs13.readFileSync(filePath);
40632
+ buffer = fs12.readFileSync(filePath);
40433
40633
  }
40434
40634
  if (isBinaryFile(filePath, buffer)) {
40435
40635
  return findings;
@@ -40471,9 +40671,9 @@ function isSymlinkLoop(realPath, visited) {
40471
40671
  return false;
40472
40672
  }
40473
40673
  function isPathWithinScope(realPath, scanDir) {
40474
- const resolvedScanDir = path24.resolve(scanDir);
40475
- const resolvedRealPath = path24.resolve(realPath);
40476
- return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path24.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
40674
+ const resolvedScanDir = path23.resolve(scanDir);
40675
+ const resolvedRealPath = path23.resolve(realPath);
40676
+ return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path23.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
40477
40677
  }
40478
40678
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
40479
40679
  skippedDirs: 0,
@@ -40484,7 +40684,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
40484
40684
  const files = [];
40485
40685
  let entries;
40486
40686
  try {
40487
- entries = fs13.readdirSync(dir);
40687
+ entries = fs12.readdirSync(dir);
40488
40688
  } catch {
40489
40689
  stats.fileErrors++;
40490
40690
  return files;
@@ -40499,15 +40699,15 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
40499
40699
  return a.localeCompare(b);
40500
40700
  });
40501
40701
  for (const entry of entries) {
40502
- const fullPath = path24.join(dir, entry);
40503
- const relPath = path24.relative(scanDir, fullPath).replace(/\\/g, "/");
40702
+ const fullPath = path23.join(dir, entry);
40703
+ const relPath = path23.relative(scanDir, fullPath).replace(/\\/g, "/");
40504
40704
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
40505
40705
  stats.skippedDirs++;
40506
40706
  continue;
40507
40707
  }
40508
40708
  let lstat;
40509
40709
  try {
40510
- lstat = fs13.lstatSync(fullPath);
40710
+ lstat = fs12.lstatSync(fullPath);
40511
40711
  } catch {
40512
40712
  stats.fileErrors++;
40513
40713
  continue;
@@ -40519,7 +40719,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
40519
40719
  if (lstat.isDirectory()) {
40520
40720
  let realPath;
40521
40721
  try {
40522
- realPath = fs13.realpathSync(fullPath);
40722
+ realPath = fs12.realpathSync(fullPath);
40523
40723
  } catch {
40524
40724
  stats.fileErrors++;
40525
40725
  continue;
@@ -40535,7 +40735,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
40535
40735
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
40536
40736
  files.push(...subFiles);
40537
40737
  } else if (lstat.isFile()) {
40538
- const ext = path24.extname(fullPath).toLowerCase();
40738
+ const ext = path23.extname(fullPath).toLowerCase();
40539
40739
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
40540
40740
  files.push(fullPath);
40541
40741
  } else {
@@ -40601,15 +40801,15 @@ var secretscan = createSwarmTool({
40601
40801
  }
40602
40802
  }
40603
40803
  try {
40604
- const _scanDirRaw = path24.resolve(directory);
40804
+ const _scanDirRaw = path23.resolve(directory);
40605
40805
  const scanDir = (() => {
40606
40806
  try {
40607
- return fs13.realpathSync(_scanDirRaw);
40807
+ return fs12.realpathSync(_scanDirRaw);
40608
40808
  } catch {
40609
40809
  return _scanDirRaw;
40610
40810
  }
40611
40811
  })();
40612
- if (!fs13.existsSync(scanDir)) {
40812
+ if (!fs12.existsSync(scanDir)) {
40613
40813
  const errorResult = {
40614
40814
  error: "directory not found",
40615
40815
  scan_dir: directory,
@@ -40620,7 +40820,7 @@ var secretscan = createSwarmTool({
40620
40820
  };
40621
40821
  return JSON.stringify(errorResult, null, 2);
40622
40822
  }
40623
- const dirStat = fs13.statSync(scanDir);
40823
+ const dirStat = fs12.statSync(scanDir);
40624
40824
  if (!dirStat.isDirectory()) {
40625
40825
  const errorResult = {
40626
40826
  error: "target must be a directory, not a file",
@@ -40671,7 +40871,7 @@ var secretscan = createSwarmTool({
40671
40871
  break;
40672
40872
  const fileFindings = scanFileForSecrets(filePath);
40673
40873
  try {
40674
- const stat2 = fs13.statSync(filePath);
40874
+ const stat2 = fs12.statSync(filePath);
40675
40875
  if (stat2.size > MAX_FILE_SIZE_BYTES) {
40676
40876
  skippedFiles++;
40677
40877
  continue;
@@ -40760,12 +40960,12 @@ async function runSecretscan(directory) {
40760
40960
 
40761
40961
  // src/tools/test-runner.ts
40762
40962
  init_zod();
40763
- import * as fs17 from "fs";
40764
- import * as path28 from "path";
40963
+ import * as fs16 from "fs";
40964
+ import * as path27 from "path";
40765
40965
 
40766
40966
  // src/test-impact/analyzer.ts
40767
- import fs14 from "fs";
40768
- import path25 from "path";
40967
+ import fs13 from "fs";
40968
+ import path24 from "path";
40769
40969
  var IMPORT_REGEX_ES = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
40770
40970
  var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
40771
40971
  var IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
@@ -40776,7 +40976,7 @@ function normalizePath(p) {
40776
40976
  function isCacheStale(impactMap, generatedAtMs) {
40777
40977
  for (const sourcePath of Object.keys(impactMap)) {
40778
40978
  try {
40779
- const stat2 = fs14.statSync(sourcePath);
40979
+ const stat2 = fs13.statSync(sourcePath);
40780
40980
  if (stat2.mtimeMs > generatedAtMs) {
40781
40981
  return true;
40782
40982
  }
@@ -40790,15 +40990,15 @@ function resolveRelativeImport(fromDir, importPath) {
40790
40990
  if (!importPath.startsWith(".")) {
40791
40991
  return null;
40792
40992
  }
40793
- const resolved = path25.resolve(fromDir, importPath);
40794
- if (path25.extname(resolved)) {
40795
- if (fs14.existsSync(resolved) && fs14.statSync(resolved).isFile()) {
40993
+ const resolved = path24.resolve(fromDir, importPath);
40994
+ if (path24.extname(resolved)) {
40995
+ if (fs13.existsSync(resolved) && fs13.statSync(resolved).isFile()) {
40796
40996
  return normalizePath(resolved);
40797
40997
  }
40798
40998
  } else {
40799
40999
  for (const ext of EXTENSIONS_TO_TRY) {
40800
41000
  const withExt = resolved + ext;
40801
- if (fs14.existsSync(withExt) && fs14.statSync(withExt).isFile()) {
41001
+ if (fs13.existsSync(withExt) && fs13.statSync(withExt).isFile()) {
40802
41002
  return normalizePath(withExt);
40803
41003
  }
40804
41004
  }
@@ -40817,13 +41017,13 @@ function findTestFilesSync(cwd) {
40817
41017
  function walk(dir, visitedInodes) {
40818
41018
  let entries;
40819
41019
  try {
40820
- entries = fs14.readdirSync(dir, { withFileTypes: true });
41020
+ entries = fs13.readdirSync(dir, { withFileTypes: true });
40821
41021
  } catch {
40822
41022
  return;
40823
41023
  }
40824
41024
  let dirInode;
40825
41025
  try {
40826
- dirInode = fs14.statSync(dir).ino;
41026
+ dirInode = fs13.statSync(dir).ino;
40827
41027
  } catch {
40828
41028
  return;
40829
41029
  }
@@ -40836,12 +41036,12 @@ function findTestFilesSync(cwd) {
40836
41036
  for (const entry of entries) {
40837
41037
  if (entry.isDirectory()) {
40838
41038
  if (!skipDirs.has(entry.name)) {
40839
- walk(path25.join(dir, entry.name), visitedInodes);
41039
+ walk(path24.join(dir, entry.name), visitedInodes);
40840
41040
  }
40841
41041
  } else if (entry.isFile()) {
40842
41042
  const name = entry.name;
40843
41043
  if (/\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name)) {
40844
- testFiles.push(normalizePath(path25.join(dir, entry.name)));
41044
+ testFiles.push(normalizePath(path24.join(dir, entry.name)));
40845
41045
  }
40846
41046
  }
40847
41047
  }
@@ -40871,7 +41071,7 @@ async function buildImpactMapInternal(cwd) {
40871
41071
  for (const testFile of testFiles) {
40872
41072
  let content;
40873
41073
  try {
40874
- content = fs14.readFileSync(testFile, "utf-8");
41074
+ content = fs13.readFileSync(testFile, "utf-8");
40875
41075
  } catch {
40876
41076
  continue;
40877
41077
  }
@@ -40879,7 +41079,7 @@ async function buildImpactMapInternal(cwd) {
40879
41079
  continue;
40880
41080
  }
40881
41081
  const imports = extractImports(content);
40882
- const testDir = path25.dirname(testFile);
41082
+ const testDir = path24.dirname(testFile);
40883
41083
  for (const importPath of imports) {
40884
41084
  const resolvedSource = resolveRelativeImport(testDir, importPath);
40885
41085
  if (resolvedSource === null) {
@@ -40901,10 +41101,10 @@ async function buildImpactMap(cwd) {
40901
41101
  return impactMap;
40902
41102
  }
40903
41103
  async function loadImpactMap(cwd) {
40904
- const cachePath = path25.join(cwd, ".swarm", "cache", "impact-map.json");
40905
- if (fs14.existsSync(cachePath)) {
41104
+ const cachePath = path24.join(cwd, ".swarm", "cache", "impact-map.json");
41105
+ if (fs13.existsSync(cachePath)) {
40906
41106
  try {
40907
- const content = fs14.readFileSync(cachePath, "utf-8");
41107
+ const content = fs13.readFileSync(cachePath, "utf-8");
40908
41108
  const data = JSON.parse(content);
40909
41109
  const map3 = data.map;
40910
41110
  const generatedAt = new Date(data.generatedAt).getTime();
@@ -40916,17 +41116,17 @@ async function loadImpactMap(cwd) {
40916
41116
  return buildImpactMap(cwd);
40917
41117
  }
40918
41118
  async function saveImpactMap(cwd, impactMap) {
40919
- const cacheDir = path25.join(cwd, ".swarm", "cache");
40920
- const cachePath = path25.join(cacheDir, "impact-map.json");
40921
- if (!fs14.existsSync(cacheDir)) {
40922
- fs14.mkdirSync(cacheDir, { recursive: true });
41119
+ const cacheDir = path24.join(cwd, ".swarm", "cache");
41120
+ const cachePath = path24.join(cacheDir, "impact-map.json");
41121
+ if (!fs13.existsSync(cacheDir)) {
41122
+ fs13.mkdirSync(cacheDir, { recursive: true });
40923
41123
  }
40924
41124
  const data = {
40925
41125
  generatedAt: new Date().toISOString(),
40926
41126
  fileCount: Object.keys(impactMap).length,
40927
41127
  map: impactMap
40928
41128
  };
40929
- fs14.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf-8");
41129
+ fs13.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf-8");
40930
41130
  }
40931
41131
  async function analyzeImpact(changedFiles, cwd) {
40932
41132
  if (!Array.isArray(changedFiles)) {
@@ -40943,7 +41143,7 @@ async function analyzeImpact(changedFiles, cwd) {
40943
41143
  const impactedTestsSet = new Set;
40944
41144
  const untestedFiles = [];
40945
41145
  for (const changedFile of validFiles) {
40946
- const normalizedChanged = normalizePath(path25.resolve(changedFile));
41146
+ const normalizedChanged = normalizePath(path24.resolve(changedFile));
40947
41147
  const tests = impactMap[normalizedChanged];
40948
41148
  if (tests && tests.length > 0) {
40949
41149
  for (const test of tests) {
@@ -41189,14 +41389,14 @@ function detectFlakyTests(allHistory) {
41189
41389
  }
41190
41390
 
41191
41391
  // src/test-impact/history-store.ts
41192
- import fs15 from "fs";
41193
- import path26 from "path";
41392
+ import fs14 from "fs";
41393
+ import path25 from "path";
41194
41394
  var MAX_HISTORY_PER_TEST = 20;
41195
41395
  var MAX_ERROR_LENGTH = 500;
41196
41396
  var MAX_STACK_LENGTH = 200;
41197
41397
  var MAX_CHANGED_FILES = 50;
41198
41398
  function getHistoryPath(workingDir) {
41199
- return path26.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
41399
+ return path25.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
41200
41400
  }
41201
41401
  function sanitizeErrorMessage(errorMessage) {
41202
41402
  if (errorMessage === undefined) {
@@ -41256,9 +41456,9 @@ function appendTestRun(record3, workingDir) {
41256
41456
  changedFiles: sanitizeChangedFiles(record3.changedFiles || [])
41257
41457
  };
41258
41458
  const historyPath = getHistoryPath(workingDir);
41259
- const historyDir = path26.dirname(historyPath);
41260
- if (!fs15.existsSync(historyDir)) {
41261
- fs15.mkdirSync(historyDir, { recursive: true });
41459
+ const historyDir = path25.dirname(historyPath);
41460
+ if (!fs14.existsSync(historyDir)) {
41461
+ fs14.mkdirSync(historyDir, { recursive: true });
41262
41462
  }
41263
41463
  const existingRecords = readAllRecords(historyPath);
41264
41464
  existingRecords.push(sanitizedRecord);
@@ -41283,24 +41483,24 @@ function appendTestRun(record3, workingDir) {
41283
41483
  `)}
41284
41484
  `;
41285
41485
  const tempPath = `${historyPath}.tmp`;
41286
- fs15.writeFileSync(tempPath, content, "utf-8");
41287
- fs15.renameSync(tempPath, historyPath);
41486
+ fs14.writeFileSync(tempPath, content, "utf-8");
41487
+ fs14.renameSync(tempPath, historyPath);
41288
41488
  } catch (err) {
41289
41489
  try {
41290
41490
  const tempPath = `${historyPath}.tmp`;
41291
- if (fs15.existsSync(tempPath)) {
41292
- fs15.unlinkSync(tempPath);
41491
+ if (fs14.existsSync(tempPath)) {
41492
+ fs14.unlinkSync(tempPath);
41293
41493
  }
41294
41494
  } catch {}
41295
41495
  throw new Error(`Failed to write test history: ${err instanceof Error ? err.message : String(err)}`);
41296
41496
  }
41297
41497
  }
41298
41498
  function readAllRecords(historyPath) {
41299
- if (!fs15.existsSync(historyPath)) {
41499
+ if (!fs14.existsSync(historyPath)) {
41300
41500
  return [];
41301
41501
  }
41302
41502
  try {
41303
- const content = fs15.readFileSync(historyPath, "utf-8");
41503
+ const content = fs14.readFileSync(historyPath, "utf-8");
41304
41504
  const lines = content.split(`
41305
41505
  `);
41306
41506
  const records = [];
@@ -41329,8 +41529,8 @@ function getAllHistory(workingDir) {
41329
41529
  }
41330
41530
 
41331
41531
  // src/tools/resolve-working-directory.ts
41332
- import * as fs16 from "fs";
41333
- import * as path27 from "path";
41532
+ import * as fs15 from "fs";
41533
+ import * as path26 from "path";
41334
41534
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
41335
41535
  if (workingDirectory == null || workingDirectory === "") {
41336
41536
  return { success: true, directory: fallbackDirectory };
@@ -41350,18 +41550,18 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
41350
41550
  };
41351
41551
  }
41352
41552
  }
41353
- const normalizedDir = path27.normalize(workingDirectory);
41354
- const pathParts = normalizedDir.split(path27.sep);
41553
+ const normalizedDir = path26.normalize(workingDirectory);
41554
+ const pathParts = normalizedDir.split(path26.sep);
41355
41555
  if (pathParts.includes("..")) {
41356
41556
  return {
41357
41557
  success: false,
41358
41558
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
41359
41559
  };
41360
41560
  }
41361
- const resolvedDir = path27.resolve(normalizedDir);
41561
+ const resolvedDir = path26.resolve(normalizedDir);
41362
41562
  let statResult;
41363
41563
  try {
41364
- statResult = fs16.statSync(resolvedDir);
41564
+ statResult = fs15.statSync(resolvedDir);
41365
41565
  } catch {
41366
41566
  return {
41367
41567
  success: false,
@@ -41374,17 +41574,17 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
41374
41574
  message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
41375
41575
  };
41376
41576
  }
41377
- const resolvedFallback = path27.resolve(fallbackDirectory);
41577
+ const resolvedFallback = path26.resolve(fallbackDirectory);
41378
41578
  let fallbackExists = false;
41379
41579
  try {
41380
- fs16.statSync(resolvedFallback);
41580
+ fs15.statSync(resolvedFallback);
41381
41581
  fallbackExists = true;
41382
41582
  } catch {
41383
41583
  fallbackExists = false;
41384
41584
  }
41385
41585
  if (workingDirectory != null && workingDirectory !== "") {
41386
41586
  if (fallbackExists) {
41387
- const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path27.sep);
41587
+ const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path26.sep);
41388
41588
  if (isSubdirectory) {
41389
41589
  return {
41390
41590
  success: false,
@@ -41474,19 +41674,19 @@ function hasDevDependency(devDeps, ...patterns) {
41474
41674
  return hasPackageJsonDependency(devDeps, ...patterns);
41475
41675
  }
41476
41676
  function detectGoTest(cwd) {
41477
- return fs17.existsSync(path28.join(cwd, "go.mod")) && isCommandAvailable("go");
41677
+ return fs16.existsSync(path27.join(cwd, "go.mod")) && isCommandAvailable("go");
41478
41678
  }
41479
41679
  function detectJavaMaven(cwd) {
41480
- return fs17.existsSync(path28.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
41680
+ return fs16.existsSync(path27.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
41481
41681
  }
41482
41682
  function detectGradle(cwd) {
41483
- const hasBuildFile = fs17.existsSync(path28.join(cwd, "build.gradle")) || fs17.existsSync(path28.join(cwd, "build.gradle.kts"));
41484
- const hasGradlew = fs17.existsSync(path28.join(cwd, "gradlew")) || fs17.existsSync(path28.join(cwd, "gradlew.bat"));
41683
+ const hasBuildFile = fs16.existsSync(path27.join(cwd, "build.gradle")) || fs16.existsSync(path27.join(cwd, "build.gradle.kts"));
41684
+ const hasGradlew = fs16.existsSync(path27.join(cwd, "gradlew")) || fs16.existsSync(path27.join(cwd, "gradlew.bat"));
41485
41685
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
41486
41686
  }
41487
41687
  function detectDotnetTest(cwd) {
41488
41688
  try {
41489
- const files = fs17.readdirSync(cwd);
41689
+ const files = fs16.readdirSync(cwd);
41490
41690
  const hasCsproj = files.some((f) => f.endsWith(".csproj"));
41491
41691
  return hasCsproj && isCommandAvailable("dotnet");
41492
41692
  } catch {
@@ -41494,32 +41694,32 @@ function detectDotnetTest(cwd) {
41494
41694
  }
41495
41695
  }
41496
41696
  function detectCTest(cwd) {
41497
- const hasSource = fs17.existsSync(path28.join(cwd, "CMakeLists.txt"));
41498
- const hasBuildCache = fs17.existsSync(path28.join(cwd, "CMakeCache.txt")) || fs17.existsSync(path28.join(cwd, "build", "CMakeCache.txt"));
41697
+ const hasSource = fs16.existsSync(path27.join(cwd, "CMakeLists.txt"));
41698
+ const hasBuildCache = fs16.existsSync(path27.join(cwd, "CMakeCache.txt")) || fs16.existsSync(path27.join(cwd, "build", "CMakeCache.txt"));
41499
41699
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
41500
41700
  }
41501
41701
  function detectSwiftTest(cwd) {
41502
- return fs17.existsSync(path28.join(cwd, "Package.swift")) && isCommandAvailable("swift");
41702
+ return fs16.existsSync(path27.join(cwd, "Package.swift")) && isCommandAvailable("swift");
41503
41703
  }
41504
41704
  function detectDartTest(cwd) {
41505
- return fs17.existsSync(path28.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
41705
+ return fs16.existsSync(path27.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
41506
41706
  }
41507
41707
  function detectRSpec(cwd) {
41508
- const hasRSpecFile = fs17.existsSync(path28.join(cwd, ".rspec"));
41509
- const hasGemfile = fs17.existsSync(path28.join(cwd, "Gemfile"));
41510
- const hasSpecDir = fs17.existsSync(path28.join(cwd, "spec"));
41708
+ const hasRSpecFile = fs16.existsSync(path27.join(cwd, ".rspec"));
41709
+ const hasGemfile = fs16.existsSync(path27.join(cwd, "Gemfile"));
41710
+ const hasSpecDir = fs16.existsSync(path27.join(cwd, "spec"));
41511
41711
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
41512
41712
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
41513
41713
  }
41514
41714
  function detectMinitest(cwd) {
41515
- return fs17.existsSync(path28.join(cwd, "test")) && (fs17.existsSync(path28.join(cwd, "Gemfile")) || fs17.existsSync(path28.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
41715
+ return fs16.existsSync(path27.join(cwd, "test")) && (fs16.existsSync(path27.join(cwd, "Gemfile")) || fs16.existsSync(path27.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
41516
41716
  }
41517
41717
  async function detectTestFramework(cwd) {
41518
41718
  const baseDir = cwd;
41519
41719
  try {
41520
- const packageJsonPath = path28.join(baseDir, "package.json");
41521
- if (fs17.existsSync(packageJsonPath)) {
41522
- const content = fs17.readFileSync(packageJsonPath, "utf-8");
41720
+ const packageJsonPath = path27.join(baseDir, "package.json");
41721
+ if (fs16.existsSync(packageJsonPath)) {
41722
+ const content = fs16.readFileSync(packageJsonPath, "utf-8");
41523
41723
  const pkg = JSON.parse(content);
41524
41724
  const _deps = pkg.dependencies || {};
41525
41725
  const devDeps = pkg.devDependencies || {};
@@ -41538,38 +41738,38 @@ async function detectTestFramework(cwd) {
41538
41738
  return "jest";
41539
41739
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
41540
41740
  return "mocha";
41541
- if (fs17.existsSync(path28.join(baseDir, "bun.lockb")) || fs17.existsSync(path28.join(baseDir, "bun.lock"))) {
41741
+ if (fs16.existsSync(path27.join(baseDir, "bun.lockb")) || fs16.existsSync(path27.join(baseDir, "bun.lock"))) {
41542
41742
  if (scripts.test?.includes("bun"))
41543
41743
  return "bun";
41544
41744
  }
41545
41745
  }
41546
41746
  } catch {}
41547
41747
  try {
41548
- const pyprojectTomlPath = path28.join(baseDir, "pyproject.toml");
41549
- const setupCfgPath = path28.join(baseDir, "setup.cfg");
41550
- const requirementsTxtPath = path28.join(baseDir, "requirements.txt");
41551
- if (fs17.existsSync(pyprojectTomlPath)) {
41552
- const content = fs17.readFileSync(pyprojectTomlPath, "utf-8");
41748
+ const pyprojectTomlPath = path27.join(baseDir, "pyproject.toml");
41749
+ const setupCfgPath = path27.join(baseDir, "setup.cfg");
41750
+ const requirementsTxtPath = path27.join(baseDir, "requirements.txt");
41751
+ if (fs16.existsSync(pyprojectTomlPath)) {
41752
+ const content = fs16.readFileSync(pyprojectTomlPath, "utf-8");
41553
41753
  if (content.includes("[tool.pytest"))
41554
41754
  return "pytest";
41555
41755
  if (content.includes("pytest"))
41556
41756
  return "pytest";
41557
41757
  }
41558
- if (fs17.existsSync(setupCfgPath)) {
41559
- const content = fs17.readFileSync(setupCfgPath, "utf-8");
41758
+ if (fs16.existsSync(setupCfgPath)) {
41759
+ const content = fs16.readFileSync(setupCfgPath, "utf-8");
41560
41760
  if (content.includes("[pytest]"))
41561
41761
  return "pytest";
41562
41762
  }
41563
- if (fs17.existsSync(requirementsTxtPath)) {
41564
- const content = fs17.readFileSync(requirementsTxtPath, "utf-8");
41763
+ if (fs16.existsSync(requirementsTxtPath)) {
41764
+ const content = fs16.readFileSync(requirementsTxtPath, "utf-8");
41565
41765
  if (content.includes("pytest"))
41566
41766
  return "pytest";
41567
41767
  }
41568
41768
  } catch {}
41569
41769
  try {
41570
- const cargoTomlPath = path28.join(baseDir, "Cargo.toml");
41571
- if (fs17.existsSync(cargoTomlPath)) {
41572
- const content = fs17.readFileSync(cargoTomlPath, "utf-8");
41770
+ const cargoTomlPath = path27.join(baseDir, "Cargo.toml");
41771
+ if (fs16.existsSync(cargoTomlPath)) {
41772
+ const content = fs16.readFileSync(cargoTomlPath, "utf-8");
41573
41773
  if (content.includes("[dev-dependencies]")) {
41574
41774
  if (content.includes("tokio") || content.includes("mockall") || content.includes("pretty_assertions")) {
41575
41775
  return "cargo";
@@ -41578,10 +41778,10 @@ async function detectTestFramework(cwd) {
41578
41778
  }
41579
41779
  } catch {}
41580
41780
  try {
41581
- const pesterConfigPath = path28.join(baseDir, "pester.config.ps1");
41582
- const pesterConfigJsonPath = path28.join(baseDir, "pester.config.ps1.json");
41583
- const pesterPs1Path = path28.join(baseDir, "tests.ps1");
41584
- if (fs17.existsSync(pesterConfigPath) || fs17.existsSync(pesterConfigJsonPath) || fs17.existsSync(pesterPs1Path)) {
41781
+ const pesterConfigPath = path27.join(baseDir, "pester.config.ps1");
41782
+ const pesterConfigJsonPath = path27.join(baseDir, "pester.config.ps1.json");
41783
+ const pesterPs1Path = path27.join(baseDir, "tests.ps1");
41784
+ if (fs16.existsSync(pesterConfigPath) || fs16.existsSync(pesterConfigJsonPath) || fs16.existsSync(pesterPs1Path)) {
41585
41785
  return "pester";
41586
41786
  }
41587
41787
  } catch {}
@@ -41623,12 +41823,12 @@ function isTestDirectoryPath(normalizedPath) {
41623
41823
  return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
41624
41824
  }
41625
41825
  function resolveWorkspacePath(file3, workingDir) {
41626
- return path28.isAbsolute(file3) ? path28.resolve(file3) : path28.resolve(workingDir, file3);
41826
+ return path27.isAbsolute(file3) ? path27.resolve(file3) : path27.resolve(workingDir, file3);
41627
41827
  }
41628
41828
  function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
41629
41829
  if (!preferRelative)
41630
41830
  return absolutePath;
41631
- return path28.relative(workingDir, absolutePath);
41831
+ return path27.relative(workingDir, absolutePath);
41632
41832
  }
41633
41833
  function dedupePush(target, value) {
41634
41834
  if (!target.includes(value)) {
@@ -41665,18 +41865,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
41665
41865
  }
41666
41866
  }
41667
41867
  function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
41668
- const relativeDir = path28.dirname(relativePath);
41868
+ const relativeDir = path27.dirname(relativePath);
41669
41869
  const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
41670
41870
  const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
41671
- const rootDir = path28.join(workingDir, dirName);
41672
- return nestedRelativeDir ? [rootDir, path28.join(rootDir, nestedRelativeDir)] : [rootDir];
41871
+ const rootDir = path27.join(workingDir, dirName);
41872
+ return nestedRelativeDir ? [rootDir, path27.join(rootDir, nestedRelativeDir)] : [rootDir];
41673
41873
  });
41674
41874
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
41675
41875
  if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
41676
- directories.push(path28.join(workingDir, "src/test/java", path28.dirname(normalizedRelativePath.slice("src/main/java/".length))));
41876
+ directories.push(path27.join(workingDir, "src/test/java", path27.dirname(normalizedRelativePath.slice("src/main/java/".length))));
41677
41877
  }
41678
41878
  if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
41679
- directories.push(path28.join(workingDir, "src/test/kotlin", path28.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
41879
+ directories.push(path27.join(workingDir, "src/test/kotlin", path27.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
41680
41880
  }
41681
41881
  return [...new Set(directories)];
41682
41882
  }
@@ -41704,23 +41904,23 @@ function isLanguageSpecificTestFile(basename4) {
41704
41904
  }
41705
41905
  function isConventionTestFilePath(filePath) {
41706
41906
  const normalizedPath = filePath.replace(/\\/g, "/");
41707
- const basename4 = path28.basename(filePath);
41907
+ const basename4 = path27.basename(filePath);
41708
41908
  return hasCompoundTestExtension(basename4) || basename4.includes(".spec.") || basename4.includes(".test.") || isLanguageSpecificTestFile(basename4) || isTestDirectoryPath(normalizedPath);
41709
41909
  }
41710
41910
  function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
41711
41911
  const testFiles = [];
41712
41912
  for (const file3 of sourceFiles) {
41713
41913
  const absoluteFile = resolveWorkspacePath(file3, workingDir);
41714
- const relativeFile = path28.relative(workingDir, absoluteFile);
41715
- const basename4 = path28.basename(absoluteFile);
41716
- const dirname11 = path28.dirname(absoluteFile);
41717
- const preferRelativeOutput = !path28.isAbsolute(file3);
41914
+ const relativeFile = path27.relative(workingDir, absoluteFile);
41915
+ const basename4 = path27.basename(absoluteFile);
41916
+ const dirname11 = path27.dirname(absoluteFile);
41917
+ const preferRelativeOutput = !path27.isAbsolute(file3);
41718
41918
  if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
41719
41919
  dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
41720
41920
  continue;
41721
41921
  }
41722
41922
  const nameWithoutExt = basename4.replace(/\.[^.]+$/, "");
41723
- const ext = path28.extname(basename4);
41923
+ const ext = path27.extname(basename4);
41724
41924
  const genericTestNames = [
41725
41925
  `${nameWithoutExt}.spec${ext}`,
41726
41926
  `${nameWithoutExt}.test${ext}`
@@ -41729,7 +41929,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
41729
41929
  const colocatedCandidates = [
41730
41930
  ...genericTestNames,
41731
41931
  ...languageSpecificTestNames
41732
- ].map((candidateName) => path28.join(dirname11, candidateName));
41932
+ ].map((candidateName) => path27.join(dirname11, candidateName));
41733
41933
  const testDirectoryNames = [
41734
41934
  basename4,
41735
41935
  ...genericTestNames,
@@ -41738,11 +41938,11 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
41738
41938
  const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
41739
41939
  const possibleTestFiles = [
41740
41940
  ...colocatedCandidates,
41741
- ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path28.join(dirname11, dirName, candidateName))),
41742
- ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path28.join(candidateDir, candidateName)))
41941
+ ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path27.join(dirname11, dirName, candidateName))),
41942
+ ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path27.join(candidateDir, candidateName)))
41743
41943
  ];
41744
41944
  for (const testFile of possibleTestFiles) {
41745
- if (fs17.existsSync(testFile)) {
41945
+ if (fs16.existsSync(testFile)) {
41746
41946
  dedupePush(testFiles, toWorkspaceOutputPath(testFile, workingDir, preferRelativeOutput));
41747
41947
  }
41748
41948
  }
@@ -41759,8 +41959,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
41759
41959
  for (const testFile of candidateTestFiles) {
41760
41960
  try {
41761
41961
  const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
41762
- const content = fs17.readFileSync(absoluteTestFile, "utf-8");
41763
- const testDir = path28.dirname(absoluteTestFile);
41962
+ const content = fs16.readFileSync(absoluteTestFile, "utf-8");
41963
+ const testDir = path27.dirname(absoluteTestFile);
41764
41964
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
41765
41965
  let match;
41766
41966
  match = importRegex.exec(content);
@@ -41768,8 +41968,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
41768
41968
  const importPath = match[1];
41769
41969
  let resolvedImport;
41770
41970
  if (importPath.startsWith(".")) {
41771
- resolvedImport = path28.resolve(testDir, importPath);
41772
- const existingExt = path28.extname(resolvedImport);
41971
+ resolvedImport = path27.resolve(testDir, importPath);
41972
+ const existingExt = path27.extname(resolvedImport);
41773
41973
  if (!existingExt) {
41774
41974
  for (const extToTry of [
41775
41975
  ".ts",
@@ -41780,7 +41980,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
41780
41980
  ".cjs"
41781
41981
  ]) {
41782
41982
  const withExt = resolvedImport + extToTry;
41783
- if (absoluteSourceFiles.includes(withExt) || fs17.existsSync(withExt)) {
41983
+ if (absoluteSourceFiles.includes(withExt) || fs16.existsSync(withExt)) {
41784
41984
  resolvedImport = withExt;
41785
41985
  break;
41786
41986
  }
@@ -41789,12 +41989,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
41789
41989
  } else {
41790
41990
  continue;
41791
41991
  }
41792
- const importBasename = path28.basename(resolvedImport, path28.extname(resolvedImport));
41793
- const importDir = path28.dirname(resolvedImport);
41992
+ const importBasename = path27.basename(resolvedImport, path27.extname(resolvedImport));
41993
+ const importDir = path27.dirname(resolvedImport);
41794
41994
  for (const sourceFile of absoluteSourceFiles) {
41795
- const sourceDir = path28.dirname(sourceFile);
41796
- const sourceBasename = path28.basename(sourceFile, path28.extname(sourceFile));
41797
- const isRelatedDir = importDir === sourceDir || importDir === path28.join(sourceDir, "__tests__") || importDir === path28.join(sourceDir, "tests") || importDir === path28.join(sourceDir, "test") || importDir === path28.join(sourceDir, "spec");
41995
+ const sourceDir = path27.dirname(sourceFile);
41996
+ const sourceBasename = path27.basename(sourceFile, path27.extname(sourceFile));
41997
+ const isRelatedDir = importDir === sourceDir || importDir === path27.join(sourceDir, "__tests__") || importDir === path27.join(sourceDir, "tests") || importDir === path27.join(sourceDir, "test") || importDir === path27.join(sourceDir, "spec");
41798
41998
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
41799
41999
  dedupePush(testFiles, testFile);
41800
42000
  break;
@@ -41807,8 +42007,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
41807
42007
  while (match !== null) {
41808
42008
  const importPath = match[1];
41809
42009
  if (importPath.startsWith(".")) {
41810
- let resolvedImport = path28.resolve(testDir, importPath);
41811
- const existingExt = path28.extname(resolvedImport);
42010
+ let resolvedImport = path27.resolve(testDir, importPath);
42011
+ const existingExt = path27.extname(resolvedImport);
41812
42012
  if (!existingExt) {
41813
42013
  for (const extToTry of [
41814
42014
  ".ts",
@@ -41819,18 +42019,18 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
41819
42019
  ".cjs"
41820
42020
  ]) {
41821
42021
  const withExt = resolvedImport + extToTry;
41822
- if (absoluteSourceFiles.includes(withExt) || fs17.existsSync(withExt)) {
42022
+ if (absoluteSourceFiles.includes(withExt) || fs16.existsSync(withExt)) {
41823
42023
  resolvedImport = withExt;
41824
42024
  break;
41825
42025
  }
41826
42026
  }
41827
42027
  }
41828
- const importDir = path28.dirname(resolvedImport);
41829
- const importBasename = path28.basename(resolvedImport, path28.extname(resolvedImport));
42028
+ const importDir = path27.dirname(resolvedImport);
42029
+ const importBasename = path27.basename(resolvedImport, path27.extname(resolvedImport));
41830
42030
  for (const sourceFile of absoluteSourceFiles) {
41831
- const sourceDir = path28.dirname(sourceFile);
41832
- const sourceBasename = path28.basename(sourceFile, path28.extname(sourceFile));
41833
- const isRelatedDir = importDir === sourceDir || importDir === path28.join(sourceDir, "__tests__") || importDir === path28.join(sourceDir, "tests") || importDir === path28.join(sourceDir, "test") || importDir === path28.join(sourceDir, "spec");
42031
+ const sourceDir = path27.dirname(sourceFile);
42032
+ const sourceBasename = path27.basename(sourceFile, path27.extname(sourceFile));
42033
+ const isRelatedDir = importDir === sourceDir || importDir === path27.join(sourceDir, "__tests__") || importDir === path27.join(sourceDir, "tests") || importDir === path27.join(sourceDir, "test") || importDir === path27.join(sourceDir, "spec");
41834
42034
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
41835
42035
  dedupePush(testFiles, testFile);
41836
42036
  break;
@@ -41933,8 +42133,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
41933
42133
  return ["mvn", "test"];
41934
42134
  case "gradle": {
41935
42135
  const isWindows = process.platform === "win32";
41936
- const hasGradlewBat = fs17.existsSync(path28.join(baseDir, "gradlew.bat"));
41937
- const hasGradlew = fs17.existsSync(path28.join(baseDir, "gradlew"));
42136
+ const hasGradlewBat = fs16.existsSync(path27.join(baseDir, "gradlew.bat"));
42137
+ const hasGradlew = fs16.existsSync(path27.join(baseDir, "gradlew"));
41938
42138
  if (hasGradlewBat && isWindows)
41939
42139
  return ["gradlew.bat", "test"];
41940
42140
  if (hasGradlew)
@@ -41951,7 +42151,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
41951
42151
  "cmake-build-release",
41952
42152
  "out"
41953
42153
  ];
41954
- const actualBuildDir = buildDirCandidates.find((d) => fs17.existsSync(path28.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
42154
+ const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(path27.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
41955
42155
  return ["ctest", "--test-dir", actualBuildDir];
41956
42156
  }
41957
42157
  case "swift-test":
@@ -42579,7 +42779,7 @@ var test_runner = createSwarmTool({
42579
42779
  const sourceFiles = args.files.filter((file3) => {
42580
42780
  if (directTestFiles.includes(file3))
42581
42781
  return false;
42582
- const ext = path28.extname(file3).toLowerCase();
42782
+ const ext = path27.extname(file3).toLowerCase();
42583
42783
  return SOURCE_EXTENSIONS.has(ext);
42584
42784
  });
42585
42785
  const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
@@ -42614,7 +42814,7 @@ var test_runner = createSwarmTool({
42614
42814
  if (isConventionTestFilePath(f)) {
42615
42815
  return false;
42616
42816
  }
42617
- const ext = path28.extname(f).toLowerCase();
42817
+ const ext = path27.extname(f).toLowerCase();
42618
42818
  return SOURCE_EXTENSIONS.has(ext);
42619
42819
  });
42620
42820
  if (sourceFiles.length === 0) {
@@ -42641,7 +42841,7 @@ var test_runner = createSwarmTool({
42641
42841
  if (isConventionTestFilePath(f)) {
42642
42842
  return false;
42643
42843
  }
42644
- const ext = path28.extname(f).toLowerCase();
42844
+ const ext = path27.extname(f).toLowerCase();
42645
42845
  return SOURCE_EXTENSIONS.has(ext);
42646
42846
  });
42647
42847
  if (sourceFiles.length === 0) {
@@ -42659,8 +42859,8 @@ var test_runner = createSwarmTool({
42659
42859
  const impactResult = await analyzeImpact(sourceFiles, workingDir);
42660
42860
  if (impactResult.impactedTests.length > 0) {
42661
42861
  testFiles = impactResult.impactedTests.map((absPath) => {
42662
- const relativePath = path28.relative(workingDir, absPath);
42663
- return path28.isAbsolute(relativePath) ? absPath : relativePath;
42862
+ const relativePath = path27.relative(workingDir, absPath);
42863
+ return path27.isAbsolute(relativePath) ? absPath : relativePath;
42664
42864
  });
42665
42865
  } else {
42666
42866
  graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
@@ -42753,8 +42953,8 @@ function validateDirectoryPath(dir) {
42753
42953
  if (dir.includes("..")) {
42754
42954
  throw new Error("Directory path must not contain path traversal sequences");
42755
42955
  }
42756
- const normalized = path29.normalize(dir);
42757
- const absolutePath = path29.isAbsolute(normalized) ? normalized : path29.resolve(normalized);
42956
+ const normalized = path28.normalize(dir);
42957
+ const absolutePath = path28.isAbsolute(normalized) ? normalized : path28.resolve(normalized);
42758
42958
  return absolutePath;
42759
42959
  }
42760
42960
  function validateTimeout(timeoutMs, defaultValue) {
@@ -42777,9 +42977,9 @@ function validateTimeout(timeoutMs, defaultValue) {
42777
42977
  }
42778
42978
  function getPackageVersion(dir) {
42779
42979
  try {
42780
- const packagePath = path29.join(dir, "package.json");
42781
- if (fs18.existsSync(packagePath)) {
42782
- const content = fs18.readFileSync(packagePath, "utf-8");
42980
+ const packagePath = path28.join(dir, "package.json");
42981
+ if (fs17.existsSync(packagePath)) {
42982
+ const content = fs17.readFileSync(packagePath, "utf-8");
42783
42983
  const pkg = JSON.parse(content);
42784
42984
  return pkg.version ?? null;
42785
42985
  }
@@ -42788,9 +42988,9 @@ function getPackageVersion(dir) {
42788
42988
  }
42789
42989
  function getChangelogVersion(dir) {
42790
42990
  try {
42791
- const changelogPath = path29.join(dir, "CHANGELOG.md");
42792
- if (fs18.existsSync(changelogPath)) {
42793
- const content = fs18.readFileSync(changelogPath, "utf-8");
42991
+ const changelogPath = path28.join(dir, "CHANGELOG.md");
42992
+ if (fs17.existsSync(changelogPath)) {
42993
+ const content = fs17.readFileSync(changelogPath, "utf-8");
42794
42994
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
42795
42995
  if (match) {
42796
42996
  return match[1];
@@ -42802,10 +43002,10 @@ function getChangelogVersion(dir) {
42802
43002
  function getVersionFileVersion(dir) {
42803
43003
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
42804
43004
  for (const file3 of possibleFiles) {
42805
- const filePath = path29.join(dir, file3);
42806
- if (fs18.existsSync(filePath)) {
43005
+ const filePath = path28.join(dir, file3);
43006
+ if (fs17.existsSync(filePath)) {
42807
43007
  try {
42808
- const content = fs18.readFileSync(filePath, "utf-8").trim();
43008
+ const content = fs17.readFileSync(filePath, "utf-8").trim();
42809
43009
  const match = content.match(/(\d+\.\d+\.\d+)/);
42810
43010
  if (match) {
42811
43011
  return match[1];
@@ -43129,8 +43329,8 @@ async function runEvidenceCheck(dir) {
43129
43329
  async function runRequirementCoverageCheck(dir, currentPhase) {
43130
43330
  const startTime = Date.now();
43131
43331
  try {
43132
- const specPath = path29.join(dir, ".swarm", "spec.md");
43133
- if (!fs18.existsSync(specPath)) {
43332
+ const specPath = path28.join(dir, ".swarm", "spec.md");
43333
+ if (!fs17.existsSync(specPath)) {
43134
43334
  return {
43135
43335
  type: "req_coverage",
43136
43336
  status: "skip",
@@ -43511,7 +43711,7 @@ async function handleQaGatesCommand(directory, args, sessionID) {
43511
43711
  }
43512
43712
 
43513
43713
  // src/commands/reset.ts
43514
- import * as fs19 from "fs";
43714
+ import * as fs18 from "fs";
43515
43715
 
43516
43716
  // src/background/manager.ts
43517
43717
  init_utils();
@@ -44212,8 +44412,8 @@ async function handleResetCommand(directory, args) {
44212
44412
  for (const filename of filesToReset) {
44213
44413
  try {
44214
44414
  const resolvedPath = validateSwarmPath(directory, filename);
44215
- if (fs19.existsSync(resolvedPath)) {
44216
- fs19.unlinkSync(resolvedPath);
44415
+ if (fs18.existsSync(resolvedPath)) {
44416
+ fs18.unlinkSync(resolvedPath);
44217
44417
  results.push(`- \u2705 Deleted ${filename}`);
44218
44418
  } else {
44219
44419
  results.push(`- \u23ED\uFE0F ${filename} not found (skipped)`);
@@ -44230,8 +44430,8 @@ async function handleResetCommand(directory, args) {
44230
44430
  }
44231
44431
  try {
44232
44432
  const summariesPath = validateSwarmPath(directory, "summaries");
44233
- if (fs19.existsSync(summariesPath)) {
44234
- fs19.rmSync(summariesPath, { recursive: true, force: true });
44433
+ if (fs18.existsSync(summariesPath)) {
44434
+ fs18.rmSync(summariesPath, { recursive: true, force: true });
44235
44435
  results.push("- \u2705 Deleted summaries/ directory");
44236
44436
  } else {
44237
44437
  results.push("- \u23ED\uFE0F summaries/ not found (skipped)");
@@ -44251,14 +44451,14 @@ async function handleResetCommand(directory, args) {
44251
44451
 
44252
44452
  // src/commands/reset-session.ts
44253
44453
  init_utils2();
44254
- import * as fs20 from "fs";
44255
- import * as path30 from "path";
44454
+ import * as fs19 from "fs";
44455
+ import * as path29 from "path";
44256
44456
  async function handleResetSessionCommand(directory, _args) {
44257
44457
  const results = [];
44258
44458
  try {
44259
44459
  const statePath = validateSwarmPath(directory, "session/state.json");
44260
- if (fs20.existsSync(statePath)) {
44261
- fs20.unlinkSync(statePath);
44460
+ if (fs19.existsSync(statePath)) {
44461
+ fs19.unlinkSync(statePath);
44262
44462
  results.push("\u2705 Deleted .swarm/session/state.json");
44263
44463
  } else {
44264
44464
  results.push("\u23ED\uFE0F state.json not found (already clean)");
@@ -44267,15 +44467,15 @@ async function handleResetSessionCommand(directory, _args) {
44267
44467
  results.push("\u274C Failed to delete state.json");
44268
44468
  }
44269
44469
  try {
44270
- const sessionDir = path30.dirname(validateSwarmPath(directory, "session/state.json"));
44271
- if (fs20.existsSync(sessionDir)) {
44272
- const files = fs20.readdirSync(sessionDir);
44470
+ const sessionDir = path29.dirname(validateSwarmPath(directory, "session/state.json"));
44471
+ if (fs19.existsSync(sessionDir)) {
44472
+ const files = fs19.readdirSync(sessionDir);
44273
44473
  const otherFiles = files.filter((f) => f !== "state.json");
44274
44474
  let deletedCount = 0;
44275
44475
  for (const file3 of otherFiles) {
44276
- const filePath = path30.join(sessionDir, file3);
44277
- if (fs20.lstatSync(filePath).isFile()) {
44278
- fs20.unlinkSync(filePath);
44476
+ const filePath = path29.join(sessionDir, file3);
44477
+ if (fs19.lstatSync(filePath).isFile()) {
44478
+ fs19.unlinkSync(filePath);
44279
44479
  deletedCount++;
44280
44480
  }
44281
44481
  }
@@ -44303,7 +44503,7 @@ async function handleResetSessionCommand(directory, _args) {
44303
44503
  // src/summaries/manager.ts
44304
44504
  init_utils2();
44305
44505
  init_utils();
44306
- import * as path31 from "path";
44506
+ import * as path30 from "path";
44307
44507
  var SUMMARY_ID_REGEX = /^S\d+$/;
44308
44508
  function sanitizeSummaryId(id) {
44309
44509
  if (!id || id.length === 0) {
@@ -44327,7 +44527,7 @@ function sanitizeSummaryId(id) {
44327
44527
  }
44328
44528
  async function loadFullOutput(directory, id) {
44329
44529
  const sanitizedId = sanitizeSummaryId(id);
44330
- const relativePath = path31.join("summaries", `${sanitizedId}.json`);
44530
+ const relativePath = path30.join("summaries", `${sanitizedId}.json`);
44331
44531
  validateSwarmPath(directory, relativePath);
44332
44532
  const content = await readSwarmFileAsync(directory, relativePath);
44333
44533
  if (content === null) {
@@ -44379,19 +44579,21 @@ ${error93 instanceof Error ? error93.message : String(error93)}`;
44379
44579
  }
44380
44580
 
44381
44581
  // src/commands/rollback.ts
44582
+ init_plan_schema();
44382
44583
  init_utils2();
44383
- import * as fs21 from "fs";
44384
- import * as path32 from "path";
44584
+ init_ledger();
44585
+ import * as fs20 from "fs";
44586
+ import * as path31 from "path";
44385
44587
  async function handleRollbackCommand(directory, args) {
44386
44588
  const phaseArg = args[0];
44387
44589
  if (!phaseArg) {
44388
44590
  const manifestPath2 = validateSwarmPath(directory, "checkpoints/manifest.json");
44389
- if (!fs21.existsSync(manifestPath2)) {
44591
+ if (!fs20.existsSync(manifestPath2)) {
44390
44592
  return "No checkpoints found. Use `/swarm checkpoint` to create checkpoints.";
44391
44593
  }
44392
44594
  let manifest2;
44393
44595
  try {
44394
- manifest2 = JSON.parse(fs21.readFileSync(manifestPath2, "utf-8"));
44596
+ manifest2 = JSON.parse(fs20.readFileSync(manifestPath2, "utf-8"));
44395
44597
  } catch {
44396
44598
  return "Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.";
44397
44599
  }
@@ -44413,12 +44615,12 @@ async function handleRollbackCommand(directory, args) {
44413
44615
  return "Error: Phase number must be a positive integer.";
44414
44616
  }
44415
44617
  const manifestPath = validateSwarmPath(directory, "checkpoints/manifest.json");
44416
- if (!fs21.existsSync(manifestPath)) {
44618
+ if (!fs20.existsSync(manifestPath)) {
44417
44619
  return `Error: No checkpoints found. Cannot rollback to phase ${targetPhase}.`;
44418
44620
  }
44419
44621
  let manifest;
44420
44622
  try {
44421
- manifest = JSON.parse(fs21.readFileSync(manifestPath, "utf-8"));
44623
+ manifest = JSON.parse(fs20.readFileSync(manifestPath, "utf-8"));
44422
44624
  } catch {
44423
44625
  return `Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.`;
44424
44626
  }
@@ -44428,28 +44630,69 @@ async function handleRollbackCommand(directory, args) {
44428
44630
  return `Error: Checkpoint for phase ${targetPhase} not found. Available phases: ${available}`;
44429
44631
  }
44430
44632
  const checkpointDir = validateSwarmPath(directory, `checkpoints/phase-${targetPhase}`);
44431
- if (!fs21.existsSync(checkpointDir)) {
44633
+ if (!fs20.existsSync(checkpointDir)) {
44432
44634
  return `Error: Checkpoint directory for phase ${targetPhase} does not exist.`;
44433
44635
  }
44434
- const checkpointFiles = fs21.readdirSync(checkpointDir);
44636
+ const checkpointFiles = fs20.readdirSync(checkpointDir);
44435
44637
  if (checkpointFiles.length === 0) {
44436
44638
  return `Error: Checkpoint for phase ${targetPhase} is empty. Cannot rollback.`;
44437
44639
  }
44438
44640
  const swarmDir = validateSwarmPath(directory, "");
44641
+ const EXCLUDE_FILES = new Set([
44642
+ "plan-ledger.jsonl",
44643
+ "plan-ledger.quarantine"
44644
+ ]);
44439
44645
  const successes = [];
44440
44646
  const failures = [];
44441
44647
  for (const file3 of checkpointFiles) {
44442
- const src = path32.join(checkpointDir, file3);
44443
- const dest = path32.join(swarmDir, file3);
44648
+ if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
44649
+ continue;
44650
+ }
44651
+ const src = path31.join(checkpointDir, file3);
44652
+ const dest = path31.join(swarmDir, file3);
44444
44653
  try {
44445
- fs21.cpSync(src, dest, { recursive: true, force: true });
44654
+ fs20.cpSync(src, dest, { recursive: true, force: true });
44446
44655
  successes.push(file3);
44447
44656
  } catch (error93) {
44448
44657
  failures.push({ file: file3, error: error93.message });
44449
44658
  }
44450
44659
  }
44451
44660
  if (failures.length > 0) {
44452
- return `Rollback partially completed. Successfully restored ${successes.length} files: ${successes.join(", ") || "none"}. Failed on ${failures.length} files: ${failures.map((f) => f.file).join(", ")}. Check permissions and disk space.`;
44661
+ return [
44662
+ `Rollback partially completed. Successfully restored ${successes.length} files.`,
44663
+ `Failed on ${failures.length} files:`,
44664
+ ...failures.map((f) => ` - ${f.file}: ${f.error}`),
44665
+ "",
44666
+ "Some files could not be restored. The .swarm/ directory may be in an inconsistent state.",
44667
+ "Check permissions and disk space, then retry the rollback."
44668
+ ].join(`
44669
+ `);
44670
+ }
44671
+ const existingLedgerPath = path31.join(swarmDir, "plan-ledger.jsonl");
44672
+ if (fs20.existsSync(existingLedgerPath)) {
44673
+ fs20.unlinkSync(existingLedgerPath);
44674
+ }
44675
+ try {
44676
+ const planJsonPath = path31.join(swarmDir, "plan.json");
44677
+ if (fs20.existsSync(planJsonPath)) {
44678
+ const planRaw = fs20.readFileSync(planJsonPath, "utf-8");
44679
+ const plan = PlanSchema.parse(JSON.parse(planRaw));
44680
+ const planId = `${plan.swarm}-${plan.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
44681
+ const planHash = computePlanHash(plan);
44682
+ await initLedger(directory, planId, planHash, plan);
44683
+ await appendLedgerEvent(directory, {
44684
+ event_type: "plan_rebuilt",
44685
+ source: "rollback",
44686
+ plan_id: planId
44687
+ });
44688
+ }
44689
+ } catch (initError) {
44690
+ return [
44691
+ `Rollback restored files but failed to initialize ledger: ${initError instanceof Error ? initError.message : String(initError)}`,
44692
+ "The .swarm/plan.json has been restored but the ledger may be out of sync.",
44693
+ "Run /swarm reset-session to reinitialize the ledger."
44694
+ ].join(`
44695
+ `);
44453
44696
  }
44454
44697
  const eventsPath = validateSwarmPath(directory, "events.jsonl");
44455
44698
  const rollbackEvent = {
@@ -44459,7 +44702,7 @@ async function handleRollbackCommand(directory, args) {
44459
44702
  timestamp: new Date().toISOString()
44460
44703
  };
44461
44704
  try {
44462
- fs21.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
44705
+ fs20.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
44463
44706
  `);
44464
44707
  } catch (error93) {
44465
44708
  console.error("Failed to write rollback event:", error93 instanceof Error ? error93.message : String(error93));
@@ -44502,11 +44745,11 @@ async function handleSimulateCommand(directory, args) {
44502
44745
  ];
44503
44746
  const report = reportLines.filter(Boolean).join(`
44504
44747
  `);
44505
- const fs22 = await import("fs/promises");
44506
- const path33 = await import("path");
44507
- const reportPath = path33.join(directory, ".swarm", "simulate-report.md");
44508
- await fs22.mkdir(path33.dirname(reportPath), { recursive: true });
44509
- await fs22.writeFile(reportPath, report, "utf-8");
44748
+ const fs21 = await import("fs/promises");
44749
+ const path32 = await import("path");
44750
+ const reportPath = path32.join(directory, ".swarm", "simulate-report.md");
44751
+ await fs21.mkdir(path32.dirname(reportPath), { recursive: true });
44752
+ await fs21.writeFile(reportPath, report, "utf-8");
44510
44753
  return `${darkMatterPairs.length} hidden coupling pairs detected`;
44511
44754
  }
44512
44755
 
@@ -45039,19 +45282,20 @@ function resolveCommand(tokens) {
45039
45282
  }
45040
45283
 
45041
45284
  // src/cli/index.ts
45042
- var CONFIG_DIR = path33.join(process.env.XDG_CONFIG_HOME || path33.join(os6.homedir(), ".config"), "opencode");
45043
- var OPENCODE_CONFIG_PATH = path33.join(CONFIG_DIR, "opencode.json");
45044
- var PLUGIN_CONFIG_PATH = path33.join(CONFIG_DIR, "opencode-swarm.json");
45045
- var PROMPTS_DIR = path33.join(CONFIG_DIR, "opencode-swarm");
45046
- var OPENCODE_PLUGIN_CACHE_PATH = path33.join(process.env.XDG_CACHE_HOME || path33.join(os6.homedir(), ".cache"), "opencode", "packages", "opencode-swarm@latest");
45285
+ var { version: version4 } = package_default;
45286
+ var CONFIG_DIR = path32.join(process.env.XDG_CONFIG_HOME || path32.join(os6.homedir(), ".config"), "opencode");
45287
+ var OPENCODE_CONFIG_PATH = path32.join(CONFIG_DIR, "opencode.json");
45288
+ var PLUGIN_CONFIG_PATH = path32.join(CONFIG_DIR, "opencode-swarm.json");
45289
+ var PROMPTS_DIR = path32.join(CONFIG_DIR, "opencode-swarm");
45290
+ var OPENCODE_PLUGIN_CACHE_PATH = path32.join(process.env.XDG_CACHE_HOME || path32.join(os6.homedir(), ".cache"), "opencode", "packages", "opencode-swarm@latest");
45047
45291
  function ensureDir(dir) {
45048
- if (!fs22.existsSync(dir)) {
45049
- fs22.mkdirSync(dir, { recursive: true });
45292
+ if (!fs21.existsSync(dir)) {
45293
+ fs21.mkdirSync(dir, { recursive: true });
45050
45294
  }
45051
45295
  }
45052
45296
  function loadJson(filepath) {
45053
45297
  try {
45054
- const content = fs22.readFileSync(filepath, "utf-8");
45298
+ const content = fs21.readFileSync(filepath, "utf-8");
45055
45299
  const stripped = content.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (match, comment) => comment ? "" : match).replace(/,(\s*[}\]])/g, "$1");
45056
45300
  return JSON.parse(stripped);
45057
45301
  } catch {
@@ -45059,15 +45303,31 @@ function loadJson(filepath) {
45059
45303
  }
45060
45304
  }
45061
45305
  function saveJson(filepath, data) {
45062
- fs22.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
45306
+ fs21.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
45063
45307
  `, "utf-8");
45064
45308
  }
45309
+ function writeProjectConfigIfMissing(cwd) {
45310
+ try {
45311
+ const opencodeDir = path32.join(cwd, ".opencode");
45312
+ const projectConfigPath = path32.join(opencodeDir, "opencode-swarm.json");
45313
+ if (fs21.existsSync(projectConfigPath)) {
45314
+ return;
45315
+ }
45316
+ ensureDir(opencodeDir);
45317
+ const starterConfig = { agents: {} };
45318
+ saveJson(projectConfigPath, starterConfig);
45319
+ console.log("\u2713 Created project config at:", projectConfigPath);
45320
+ } catch (error93) {
45321
+ console.warn("\u26A0 Could not create project config \u2014 installation will continue:");
45322
+ console.warn(` ${error93 instanceof Error ? error93.message : String(error93)}`);
45323
+ }
45324
+ }
45065
45325
  async function install() {
45066
45326
  console.log(`\uD83D\uDC1D Installing OpenCode Swarm...
45067
45327
  `);
45068
45328
  ensureDir(CONFIG_DIR);
45069
45329
  ensureDir(PROMPTS_DIR);
45070
- const LEGACY_CONFIG_PATH = path33.join(CONFIG_DIR, "config.json");
45330
+ const LEGACY_CONFIG_PATH = path32.join(CONFIG_DIR, "config.json");
45071
45331
  let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
45072
45332
  if (!opencodeConfig) {
45073
45333
  const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
@@ -45099,15 +45359,15 @@ async function install() {
45099
45359
  console.log("\u2713 Added opencode-swarm to OpenCode plugins");
45100
45360
  console.log("\u2713 Disabled default OpenCode agents (explore, general)");
45101
45361
  try {
45102
- if (fs22.existsSync(OPENCODE_PLUGIN_CACHE_PATH)) {
45103
- fs22.rmSync(OPENCODE_PLUGIN_CACHE_PATH, { recursive: true, force: true });
45362
+ if (fs21.existsSync(OPENCODE_PLUGIN_CACHE_PATH)) {
45363
+ fs21.rmSync(OPENCODE_PLUGIN_CACHE_PATH, { recursive: true, force: true });
45104
45364
  console.log("\u2713 Cleared opencode plugin cache (next start will fetch latest)");
45105
45365
  }
45106
45366
  } catch {
45107
45367
  console.warn("\u26A0 Could not clear opencode plugin cache \u2014 you may need to delete it manually:");
45108
45368
  console.warn(` ${OPENCODE_PLUGIN_CACHE_PATH}`);
45109
45369
  }
45110
- if (!fs22.existsSync(PLUGIN_CONFIG_PATH)) {
45370
+ if (!fs21.existsSync(PLUGIN_CONFIG_PATH)) {
45111
45371
  const defaultConfig = {
45112
45372
  agents: {
45113
45373
  coder: {
@@ -45182,6 +45442,7 @@ async function install() {
45182
45442
  } else {
45183
45443
  console.log("\u2713 Plugin config already exists at:", PLUGIN_CONFIG_PATH);
45184
45444
  }
45445
+ writeProjectConfigIfMissing(process.cwd());
45185
45446
  console.log(`
45186
45447
  \uD83D\uDCC1 Configuration files:`);
45187
45448
  console.log(` OpenCode config: ${OPENCODE_CONFIG_PATH}`);
@@ -45210,7 +45471,7 @@ async function uninstall() {
45210
45471
  `);
45211
45472
  const opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
45212
45473
  if (!opencodeConfig) {
45213
- if (fs22.existsSync(OPENCODE_CONFIG_PATH)) {
45474
+ if (fs21.existsSync(OPENCODE_CONFIG_PATH)) {
45214
45475
  console.log(`\u2717 Could not parse opencode config at: ${OPENCODE_CONFIG_PATH}`);
45215
45476
  return 1;
45216
45477
  } else {
@@ -45242,13 +45503,13 @@ async function uninstall() {
45242
45503
  console.log("\u2713 Re-enabled default OpenCode agents (explore, general)");
45243
45504
  if (process.argv.includes("--clean")) {
45244
45505
  let cleaned = false;
45245
- if (fs22.existsSync(PLUGIN_CONFIG_PATH)) {
45246
- fs22.unlinkSync(PLUGIN_CONFIG_PATH);
45506
+ if (fs21.existsSync(PLUGIN_CONFIG_PATH)) {
45507
+ fs21.unlinkSync(PLUGIN_CONFIG_PATH);
45247
45508
  console.log(`\u2713 Removed plugin config: ${PLUGIN_CONFIG_PATH}`);
45248
45509
  cleaned = true;
45249
45510
  }
45250
- if (fs22.existsSync(PROMPTS_DIR)) {
45251
- fs22.rmSync(PROMPTS_DIR, { recursive: true });
45511
+ if (fs21.existsSync(PROMPTS_DIR)) {
45512
+ fs21.rmSync(PROMPTS_DIR, { recursive: true });
45252
45513
  console.log(`\u2713 Removed custom prompts: ${PROMPTS_DIR}`);
45253
45514
  cleaned = true;
45254
45515
  }
@@ -45311,6 +45572,10 @@ Examples:
45311
45572
  }
45312
45573
  async function main() {
45313
45574
  const args = process.argv.slice(2);
45575
+ if (args.includes("-v") || args.includes("--version")) {
45576
+ console.log(`opencode-swarm ${version4}`);
45577
+ process.exit(0);
45578
+ }
45314
45579
  if (args.includes("-h") || args.includes("--help")) {
45315
45580
  printHelp();
45316
45581
  process.exit(0);