opencode-swarm 7.58.1 → 7.59.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -69,7 +69,7 @@ var package_default;
69
69
  var init_package = __esm(() => {
70
70
  package_default = {
71
71
  name: "opencode-swarm",
72
- version: "7.58.1",
72
+ version: "7.59.1",
73
73
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
74
74
  main: "dist/index.js",
75
75
  types: "dist/index.d.ts",
@@ -1044,7 +1044,9 @@ var init_constants = __esm(() => {
1044
1044
  phase_critic: true,
1045
1045
  integrated_diff_required: true,
1046
1046
  allow_docs_only_without_reviewer: false,
1047
- worktree_isolation: false
1047
+ worktree_isolation: false,
1048
+ merge_strategy: "merge",
1049
+ worktree_dir: undefined
1048
1050
  };
1049
1051
  });
1050
1052
 
@@ -15917,9 +15919,9 @@ var init_schema = __esm(() => {
15917
15919
  phase_critic: exports_external.boolean().default(true),
15918
15920
  integrated_diff_required: exports_external.boolean().default(true),
15919
15921
  allow_docs_only_without_reviewer: exports_external.boolean().default(false),
15920
- worktree_isolation: exports_external.boolean().default(false).refine((val) => val === false, {
15921
- message: "worktree_isolation: true is not yet implemented. Use false (the default) for in-repo parallel execution. Full worktree isolation will be available in a future release."
15922
- })
15922
+ worktree_isolation: exports_external.boolean().default(false),
15923
+ merge_strategy: exports_external.enum(["merge", "rebase", "cherry-pick"]).default("merge").optional(),
15924
+ worktree_dir: exports_external.string().optional()
15923
15925
  });
15924
15926
  StandardTurboConfigSchema = exports_external.object({
15925
15927
  strategy: exports_external.literal("standard"),
@@ -57803,7 +57805,7 @@ var init_knowledge_validator = __esm(() => {
57803
57805
  /\bmkfs\b/,
57804
57806
  /\bdd\s+if=/,
57805
57807
  /:\(\)\s*\{/,
57806
- /\bchmod\s+-R\s+777\b/,
57808
+ /\bchmod\s+-R\s+777\b/i,
57807
57809
  /\bdeltree\b/,
57808
57810
  /\brmdir\s+\/s\b/,
57809
57811
  /\bkill\s+-9\b/,
@@ -92851,7 +92853,7 @@ async function readMergedKnowledge(directory, config3, context, opts) {
92851
92853
  const retractionRecords = await readRetractionRecords(directory);
92852
92854
  const suppressedLessons = new Set(retractionRecords.map((record3) => record3.normalized_lesson).filter((value) => typeof value === "string" && value.length > 0));
92853
92855
  const scopeFilter = config3.scope_filter ?? ["global"];
92854
- const filtered = merged.filter((entry) => (opts?.skipScopeFilter || scopeFilter.some((pattern) => (entry.scope ?? "global") === pattern)) && NORMAL_RETRIEVAL_STATUSES.has(entry.status) && !suppressedLessons.has(normalize4(entry.lesson)));
92856
+ const filtered = merged.filter((entry) => (opts?.skipScopeFilter || scopeFilter.some((pattern) => (entry.scope ?? "global") === pattern)) && entry.status !== QUARANTINED_STATUS && !suppressedLessons.has(normalize4(entry.lesson)));
92855
92857
  const ranked = filtered.map((entry) => {
92856
92858
  let categoryScore = 0;
92857
92859
  if (context?.currentPhase) {
@@ -93023,12 +93025,11 @@ function scoreDirectiveAgainstContext(entry, ctx) {
93023
93025
  score += 0.1;
93024
93026
  return { triggerHit, actionHit, agentHit, score: Math.min(1, score) };
93025
93027
  }
93026
- var JACCARD_THRESHOLD2 = 0.6, HIVE_TIER_BOOST = 0.05, SAME_PROJECT_PENALTY = -0.05, NORMAL_RETRIEVAL_STATUSES;
93028
+ var JACCARD_THRESHOLD2 = 0.6, HIVE_TIER_BOOST = 0.05, SAME_PROJECT_PENALTY = -0.05, QUARANTINED_STATUS = "quarantined";
93027
93029
  var init_knowledge_reader = __esm(() => {
93028
93030
  init_task_file();
93029
93031
  init_logger();
93030
93032
  init_knowledge_store();
93031
- NORMAL_RETRIEVAL_STATUSES = new Set(["established", "promoted"]);
93032
93033
  });
93033
93034
 
93034
93035
  // src/hooks/search-knowledge.ts
@@ -93081,6 +93082,8 @@ async function searchKnowledge(params) {
93081
93082
  });
93082
93083
  const counterRollups = await readKnowledgeCounterRollups(directory);
93083
93084
  candidates = candidates.filter((e) => {
93085
+ if (e.status === "archived")
93086
+ return false;
93084
93087
  if (e.status === "quarantined")
93085
93088
  return false;
93086
93089
  if (tier === "hive" && e.tier !== "hive")
@@ -93513,10 +93516,10 @@ var init_curator_drift = __esm(() => {
93513
93516
  var exports_design_doc_drift = {};
93514
93517
  __export(exports_design_doc_drift, {
93515
93518
  runDesignDocDriftCheck: () => runDesignDocDriftCheck,
93516
- _internals: () => _internals67
93519
+ _internals: () => _internals69
93517
93520
  });
93518
93521
  import * as fs109 from "node:fs";
93519
- import * as path148 from "node:path";
93522
+ import * as path149 from "node:path";
93520
93523
  function mtimeMsOrNull(absPath) {
93521
93524
  try {
93522
93525
  return fs109.statSync(absPath).mtimeMs;
@@ -93527,35 +93530,35 @@ function mtimeMsOrNull(absPath) {
93527
93530
  function resolveAnchorWithin(directory, anchor) {
93528
93531
  if (!anchor || typeof anchor !== "string")
93529
93532
  return null;
93530
- const root = path148.resolve(directory);
93531
- const resolved = path148.resolve(root, anchor);
93532
- const rel = path148.relative(root, resolved);
93533
- if (rel.startsWith("..") || path148.isAbsolute(rel))
93533
+ const root = path149.resolve(directory);
93534
+ const resolved = path149.resolve(root, anchor);
93535
+ const rel = path149.relative(root, resolved);
93536
+ if (rel.startsWith("..") || path149.isAbsolute(rel))
93534
93537
  return null;
93535
93538
  return resolved;
93536
93539
  }
93537
93540
  async function runDesignDocDriftCheck(directory, phase, outDir) {
93538
93541
  try {
93539
- const root = path148.resolve(directory);
93540
- const outAbs = path148.resolve(root, outDir);
93541
- const outRel = path148.relative(root, outAbs);
93542
- if (outRel.startsWith("..") || path148.isAbsolute(outRel)) {
93542
+ const root = path149.resolve(directory);
93543
+ const outAbs = path149.resolve(root, outDir);
93544
+ const outRel = path149.relative(root, outAbs);
93545
+ if (outRel.startsWith("..") || path149.isAbsolute(outRel)) {
93543
93546
  return null;
93544
93547
  }
93545
93548
  const docMtimes = new Map;
93546
93549
  const checkedDocs = [];
93547
93550
  const missingDocs = [];
93548
93551
  for (const [docName, relFile] of Object.entries(DESIGN_DOC_FILES)) {
93549
- const abs = path148.join(outAbs, relFile);
93552
+ const abs = path149.join(outAbs, relFile);
93550
93553
  const mtime = mtimeMsOrNull(abs);
93551
93554
  docMtimes.set(docName, mtime);
93552
93555
  if (mtime === null) {
93553
- missingDocs.push(path148.join(outDir, relFile));
93556
+ missingDocs.push(path149.join(outDir, relFile));
93554
93557
  } else {
93555
- checkedDocs.push(path148.join(outDir, relFile));
93558
+ checkedDocs.push(path149.join(outDir, relFile));
93556
93559
  }
93557
93560
  }
93558
- const traceabilityAbs = path148.join(outAbs, TRACEABILITY_REL);
93561
+ const traceabilityAbs = path149.join(outAbs, TRACEABILITY_REL);
93559
93562
  let registry3 = null;
93560
93563
  try {
93561
93564
  const stat9 = await fs109.promises.stat(traceabilityAbs);
@@ -93568,7 +93571,7 @@ async function runDesignDocDriftCheck(directory, phase, outDir) {
93568
93571
  registry3 = null;
93569
93572
  }
93570
93573
  const noDocs = checkedDocs.length === 0 || registry3 === null;
93571
- const specMtime = mtimeMsOrNull(path148.join(root, ".swarm", "spec.md"));
93574
+ const specMtime = mtimeMsOrNull(path149.join(root, ".swarm", "spec.md"));
93572
93575
  const staleSections = [];
93573
93576
  if (!noDocs && Array.isArray(registry3?.sections)) {
93574
93577
  for (const section of registry3.sections) {
@@ -93624,7 +93627,7 @@ async function runDesignDocDriftCheck(directory, phase, outDir) {
93624
93627
  };
93625
93628
  const filename = `${DOC_DRIFT_REPORT_PREFIX}${phase}.json`;
93626
93629
  const filePath = validateSwarmPath(directory, filename);
93627
- await fs109.promises.mkdir(path148.dirname(filePath), { recursive: true });
93630
+ await fs109.promises.mkdir(path149.dirname(filePath), { recursive: true });
93628
93631
  await fs109.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
93629
93632
  getGlobalEventBus().publish("curator.docdrift.completed", {
93630
93633
  phase,
@@ -93645,7 +93648,7 @@ async function runDesignDocDriftCheck(directory, phase, outDir) {
93645
93648
  return null;
93646
93649
  }
93647
93650
  }
93648
- var DOC_DRIFT_REPORT_PREFIX = "doc-drift-phase-", MAX_TRACEABILITY_BYTES, DESIGN_DOC_FILES, TRACEABILITY_REL, _internals67;
93651
+ var DOC_DRIFT_REPORT_PREFIX = "doc-drift-phase-", MAX_TRACEABILITY_BYTES, DESIGN_DOC_FILES, TRACEABILITY_REL, _internals69;
93649
93652
  var init_design_doc_drift = __esm(() => {
93650
93653
  init_event_bus();
93651
93654
  init_logger();
@@ -93655,11 +93658,11 @@ var init_design_doc_drift = __esm(() => {
93655
93658
  domain: "domain.md",
93656
93659
  "technical-spec": "technical-spec.md",
93657
93660
  "behavior-spec": "behavior-spec.md",
93658
- "reference-impl": path148.join("reference", "reference-impl.md"),
93659
- "idiom-notes": path148.join("reference", "idiom-notes.md")
93661
+ "reference-impl": path149.join("reference", "reference-impl.md"),
93662
+ "idiom-notes": path149.join("reference", "idiom-notes.md")
93660
93663
  };
93661
- TRACEABILITY_REL = path148.join("reference", "traceability.json");
93662
- _internals67 = {
93664
+ TRACEABILITY_REL = path149.join("reference", "traceability.json");
93665
+ _internals69 = {
93663
93666
  mtimeMsOrNull,
93664
93667
  resolveAnchorWithin,
93665
93668
  DESIGN_DOC_FILES
@@ -93670,11 +93673,11 @@ var init_design_doc_drift = __esm(() => {
93670
93673
  var exports_project_context = {};
93671
93674
  __export(exports_project_context, {
93672
93675
  buildProjectContext: () => buildProjectContext,
93673
- _internals: () => _internals78,
93676
+ _internals: () => _internals80,
93674
93677
  LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
93675
93678
  });
93676
93679
  import * as fs133 from "node:fs";
93677
- import * as path177 from "node:path";
93680
+ import * as path178 from "node:path";
93678
93681
  function detectFileExists2(directory, pattern) {
93679
93682
  if (pattern.includes("*") || pattern.includes("?")) {
93680
93683
  try {
@@ -93686,7 +93689,7 @@ function detectFileExists2(directory, pattern) {
93686
93689
  }
93687
93690
  }
93688
93691
  try {
93689
- fs133.accessSync(path177.join(directory, pattern));
93692
+ fs133.accessSync(path178.join(directory, pattern));
93690
93693
  return true;
93691
93694
  } catch {
93692
93695
  return false;
@@ -93695,7 +93698,7 @@ function detectFileExists2(directory, pattern) {
93695
93698
  function selectTestCommandFromScriptsTest(backend, directory) {
93696
93699
  let pkgRaw;
93697
93700
  try {
93698
- pkgRaw = fs133.readFileSync(path177.join(directory, "package.json"), "utf-8");
93701
+ pkgRaw = fs133.readFileSync(path178.join(directory, "package.json"), "utf-8");
93699
93702
  } catch {
93700
93703
  return null;
93701
93704
  }
@@ -93754,7 +93757,7 @@ function selectLintCommand(backend, directory) {
93754
93757
  return null;
93755
93758
  }
93756
93759
  async function buildProjectContext(directory) {
93757
- const backend = await _internals78.pickBackend(directory);
93760
+ const backend = await _internals80.pickBackend(directory);
93758
93761
  if (!backend)
93759
93762
  return null;
93760
93763
  const ctx = emptyProjectContext();
@@ -93793,17 +93796,17 @@ async function buildProjectContext(directory) {
93793
93796
  if (backend.prompts.reviewerChecklist.length > 0) {
93794
93797
  ctx.REVIEWER_CHECKLIST = bulletList(backend.prompts.reviewerChecklist);
93795
93798
  }
93796
- const profiles = _internals78.pickedProfiles(directory);
93799
+ const profiles = _internals80.pickedProfiles(directory);
93797
93800
  if (profiles.length > 1) {
93798
93801
  ctx.PROJECT_CONTEXT_SECONDARY_LANGUAGES = profiles.slice(1).map((p) => p.id).join(", ");
93799
93802
  }
93800
93803
  return ctx;
93801
93804
  }
93802
- var LANG_BACKEND_DETECTION_TIMEOUT_MS = 300, _internals78;
93805
+ var LANG_BACKEND_DETECTION_TIMEOUT_MS = 300, _internals80;
93803
93806
  var init_project_context = __esm(() => {
93804
93807
  init_dispatch();
93805
93808
  init_framework_detector();
93806
- _internals78 = {
93809
+ _internals80 = {
93807
93810
  pickBackend,
93808
93811
  pickedProfiles
93809
93812
  };
@@ -93813,7 +93816,7 @@ var init_project_context = __esm(() => {
93813
93816
  init_package();
93814
93817
  init_agents2();
93815
93818
  init_critic();
93816
- import * as path178 from "node:path";
93819
+ import * as path179 from "node:path";
93817
93820
  import { fileURLToPath as fileURLToPath5 } from "node:url";
93818
93821
 
93819
93822
  // src/background/index.ts
@@ -116503,7 +116506,468 @@ init_state2();
116503
116506
  init_file_locks();
116504
116507
  init_manager();
116505
116508
  init_state();
116509
+
116510
+ // src/turbo/lean/merge-back.ts
116511
+ init_bun_compat();
116512
+
116513
+ // src/turbo/lean/worktree.ts
116514
+ init_bun_compat();
116515
+ import * as os14 from "node:os";
116516
+ import * as path137 from "node:path";
116517
+ var _internals62 = {
116518
+ bunSpawn,
116519
+ platform: process.platform,
116520
+ sleep: (ms) => new Promise((resolve50) => setTimeout(resolve50, ms)),
116521
+ osTmpdir: () => os14.tmpdir(),
116522
+ getCoreLongPaths: async (directory) => {
116523
+ const result = await runGit(["config", "core.longpaths"], directory);
116524
+ if (result.exitCode !== 0) {
116525
+ return;
116526
+ }
116527
+ const value = result.stdout.trim().toLowerCase();
116528
+ return value === "" ? undefined : value;
116529
+ }
116530
+ };
116531
+ var WORKTREE_TIMEOUT_MS = 30000;
116532
+ var WIN_PATH_BUDGET = 250;
116533
+ async function runGit(args2, cwd, timeoutMs = WORKTREE_TIMEOUT_MS) {
116534
+ const proc = _internals62.bunSpawn(["git", ...args2], {
116535
+ cwd,
116536
+ timeout: timeoutMs,
116537
+ stdin: "ignore",
116538
+ stdout: "pipe",
116539
+ stderr: "pipe",
116540
+ env: { ...process.env, LC_ALL: "C" }
116541
+ });
116542
+ try {
116543
+ const exitCode = await proc.exited;
116544
+ const stdout = await proc.stdout.text();
116545
+ const stderr = await proc.stderr.text();
116546
+ return { exitCode, stdout, stderr };
116547
+ } finally {
116548
+ try {
116549
+ proc.kill();
116550
+ } catch {}
116551
+ }
116552
+ }
116553
+ async function checkPathBudget(worktreeRoot, directory) {
116554
+ if (_internals62.platform !== "win32") {
116555
+ return { ok: true };
116556
+ }
116557
+ let longPaths;
116558
+ try {
116559
+ longPaths = await _internals62.getCoreLongPaths(directory);
116560
+ } catch {}
116561
+ if (longPaths === "true") {
116562
+ return { ok: true };
116563
+ }
116564
+ const proc = _internals62.bunSpawn(["git", "ls-files"], {
116565
+ cwd: directory,
116566
+ timeout: WORKTREE_TIMEOUT_MS,
116567
+ stdin: "ignore",
116568
+ stdout: "pipe",
116569
+ stderr: "ignore",
116570
+ env: { ...process.env, LC_ALL: "C" }
116571
+ });
116572
+ try {
116573
+ const exitCode = await proc.exited;
116574
+ const stdout = await proc.stdout.text();
116575
+ if (exitCode !== 0 || stdout.trim().length === 0) {
116576
+ return { ok: true };
116577
+ }
116578
+ const files = stdout.split(/\r?\n/);
116579
+ let longest = 0;
116580
+ for (const file3 of files) {
116581
+ if (file3.length > longest) {
116582
+ longest = file3.length;
116583
+ }
116584
+ }
116585
+ const totalPathLength = worktreeRoot.length + 1 + longest;
116586
+ if (totalPathLength >= WIN_PATH_BUDGET) {
116587
+ return {
116588
+ ok: false,
116589
+ error: `Total path budget exceeded: worktree root "${worktreeRoot}" (${worktreeRoot.length} chars) + longest file "${files.find((f) => f.length === longest)}" (${longest} chars) = ${totalPathLength} chars (budget: ${WIN_PATH_BUDGET})`,
116590
+ suggestion: "Set config.worktree_dir to a shorter absolute path, or let the auto-shorten feature relocate the worktree to the system temp directory."
116591
+ };
116592
+ }
116593
+ return { ok: true };
116594
+ } finally {
116595
+ try {
116596
+ proc.kill();
116597
+ } catch {}
116598
+ }
116599
+ }
116600
+ function shortenWorktreePath(_directory, sessionId, laneId) {
116601
+ return path137.join(_internals62.osTmpdir(), "swwt", sessionId, laneId);
116602
+ }
116603
+ async function provisionWorktree(directory, laneId, sessionId, config3) {
116604
+ const branchName = `swarm-lane/${sessionId}/${laneId}`;
116605
+ let worktreePath = config3.worktree_dir ? path137.resolve(directory, config3.worktree_dir, sessionId, laneId) : path137.resolve(path137.dirname(directory), ".swarm-worktrees", sessionId, laneId);
116606
+ const budgetResult = await checkPathBudget(worktreePath, directory);
116607
+ if (budgetResult.ok === false) {
116608
+ if (config3.worktree_dir) {
116609
+ console.warn(`[swarm] Path budget warning: ${budgetResult.error} ${budgetResult.suggestion}`);
116610
+ } else {
116611
+ const shortPath = shortenWorktreePath(directory, sessionId, laneId);
116612
+ const shortBudget = await checkPathBudget(shortPath, directory);
116613
+ if (shortBudget.ok === false) {
116614
+ return { error: budgetResult.error };
116615
+ }
116616
+ worktreePath = shortPath;
116617
+ }
116618
+ }
116619
+ const checkResult = await runGit(["show-ref", "--verify", "--quiet", `refs/heads/${branchName}`], directory);
116620
+ if (checkResult.exitCode === 0) {
116621
+ return { error: `Branch already exists: ${branchName}` };
116622
+ }
116623
+ const addResult = await runGit(["worktree", "add", "-b", branchName, worktreePath, "HEAD"], directory);
116624
+ if (addResult.exitCode !== 0) {
116625
+ return {
116626
+ error: `Failed to create worktree: ${addResult.stderr.trim() || addResult.stdout.trim()}`
116627
+ };
116628
+ }
116629
+ return { worktreePath, branchName };
116630
+ }
116631
+ async function removeWorktree(worktreePath, projectRoot) {
116632
+ const isWindows = _internals62.platform === "win32";
116633
+ const MAX_RETRIES = 4;
116634
+ const RETRY_DELAY_MS = 2000;
116635
+ let lastError = "";
116636
+ for (let attempt = 0;attempt < MAX_RETRIES; attempt++) {
116637
+ const result = await runGit(["worktree", "remove", worktreePath], projectRoot);
116638
+ if (result.exitCode === 0) {
116639
+ return { success: true };
116640
+ }
116641
+ lastError = result.stderr.trim() || result.stdout.trim();
116642
+ if (isWindows && (lastError.includes("EBUSY") || lastError.includes("EPERM")) && attempt < MAX_RETRIES - 1) {
116643
+ await _internals62.sleep(RETRY_DELAY_MS);
116644
+ continue;
116645
+ }
116646
+ return { error: lastError };
116647
+ }
116648
+ return { error: lastError };
116649
+ }
116650
+ async function autoCommitDirty(worktreePath) {
116651
+ const COMMIT_MESSAGE = "swarm-lane: auto-commit before cleanup";
116652
+ const addResult = await runGit(["add", "-A"], worktreePath);
116653
+ if (addResult.exitCode !== 0) {
116654
+ return {
116655
+ committed: false,
116656
+ reason: `git add failed: ${addResult.stderr.trim() || addResult.stdout.trim()}`
116657
+ };
116658
+ }
116659
+ const commitResult = await runGit(["commit", "-m", COMMIT_MESSAGE], worktreePath);
116660
+ if (commitResult.exitCode !== 0) {
116661
+ const stderr = commitResult.stderr.trim();
116662
+ const stdout = commitResult.stdout.trim();
116663
+ if (stderr.includes("nothing to commit") || stdout.includes("nothing to commit") || stderr.includes("nothing added to commit")) {
116664
+ return { committed: false, reason: "Nothing to commit" };
116665
+ }
116666
+ return {
116667
+ committed: false,
116668
+ reason: `git commit failed: ${stderr || stdout}`
116669
+ };
116670
+ }
116671
+ return { committed: true, message: COMMIT_MESSAGE };
116672
+ }
116673
+ var SAFE_CLEAN_PATTERNS = [
116674
+ "dist/",
116675
+ "build/",
116676
+ ".turbo/",
116677
+ "coverage/",
116678
+ "node_modules/.cache/",
116679
+ ".log",
116680
+ ".tmp",
116681
+ ".o",
116682
+ ".pyc",
116683
+ ".class"
116684
+ ];
116685
+ function isSafeToClean(candidatePath) {
116686
+ const normalized = candidatePath.replace(/\\/g, "/").toLowerCase();
116687
+ return SAFE_CLEAN_PATTERNS.some((pattern) => {
116688
+ const p = pattern.toLowerCase();
116689
+ if (p.endsWith("/")) {
116690
+ return normalized.startsWith(p) || normalized.includes("/" + p);
116691
+ }
116692
+ return normalized.endsWith(p);
116693
+ });
116694
+ }
116695
+ async function cleanUntrackedFiles(worktreePath) {
116696
+ const dryRun = await runGit(["clean", "-fdn"], worktreePath);
116697
+ if (dryRun.exitCode === 0) {
116698
+ const candidates = dryRun.stdout.trim().split(`
116699
+ `).map((line) => {
116700
+ const match = line.match(/^Would remove (.+)$/);
116701
+ return match ? match[1].trim() : "";
116702
+ }).filter((p) => p.length > 0);
116703
+ const unsafePaths = candidates.filter((p) => !isSafeToClean(p));
116704
+ if (unsafePaths.length > 0) {
116705
+ console.warn(`[swarm:cleanUntrackedFiles] Skipping clean — untracked source files detected: ${unsafePaths.join(", ")}`);
116706
+ return {
116707
+ cleaned: false,
116708
+ error: "untracked source files detected — skipping clean to prevent data loss"
116709
+ };
116710
+ }
116711
+ }
116712
+ const result = await runGit(["clean", "-fd"], worktreePath);
116713
+ if (result.exitCode !== 0) {
116714
+ return {
116715
+ cleaned: false,
116716
+ error: result.stderr.trim() || result.stdout.trim()
116717
+ };
116718
+ }
116719
+ return { cleaned: true };
116720
+ }
116721
+ async function assertCleanWorkingTree(directory) {
116722
+ const [statusResult, untrackedResult] = await Promise.all([
116723
+ runGit(["status", "--porcelain"], directory),
116724
+ runGit(["ls-files", "--others", "--exclude-standard"], directory)
116725
+ ]);
116726
+ if (statusResult.exitCode !== 0) {
116727
+ return {
116728
+ clean: false,
116729
+ error: `Unable to verify working tree cleanliness: ${statusResult.stderr.trim() || statusResult.stdout.trim()}`
116730
+ };
116731
+ }
116732
+ if (untrackedResult.exitCode !== 0) {
116733
+ return {
116734
+ clean: false,
116735
+ error: `Unable to verify working tree cleanliness: ${untrackedResult.stderr.trim() || untrackedResult.stdout.trim()}`
116736
+ };
116737
+ }
116738
+ const hasChanges = statusResult.stdout.trim().length > 0;
116739
+ const hasUntracked = untrackedResult.stdout.trim().length > 0;
116740
+ if (hasChanges || hasUntracked) {
116741
+ return {
116742
+ clean: false,
116743
+ error: "Working tree has uncommitted changes. Please commit or stash before provisioning worktrees. Run 'git status' for details."
116744
+ };
116745
+ }
116746
+ return { clean: true };
116747
+ }
116748
+
116749
+ // src/turbo/lean/merge-back.ts
116750
+ var _internals63 = {
116751
+ bunSpawn,
116752
+ platform: process.platform,
116753
+ sleep: (ms) => new Promise((resolve50) => setTimeout(resolve50, ms))
116754
+ };
116755
+ var MERGE_TIMEOUT_MS = 30000;
116756
+ async function runGit2(args2, cwd, timeoutMs = MERGE_TIMEOUT_MS) {
116757
+ const proc = _internals63.bunSpawn(["git", ...args2], {
116758
+ cwd,
116759
+ timeout: timeoutMs,
116760
+ stdin: "ignore",
116761
+ stdout: "pipe",
116762
+ stderr: "pipe",
116763
+ env: { ...process.env, LC_ALL: "C" }
116764
+ });
116765
+ try {
116766
+ const exitCode = await proc.exited;
116767
+ const stdout = await proc.stdout.text();
116768
+ const stderr = await proc.stderr.text();
116769
+ return { exitCode, stdout, stderr };
116770
+ } finally {
116771
+ try {
116772
+ proc.kill();
116773
+ } catch {}
116774
+ }
116775
+ }
116776
+ function parseConflictFiles(output) {
116777
+ const files = [];
116778
+ const lines = output.split(`
116779
+ `);
116780
+ for (const line of lines) {
116781
+ const match = line.match(/CONFLICT\b.*(?:Merge conflict in |in )(.+)/);
116782
+ if (match?.[1]) {
116783
+ files.push(match[1].trim());
116784
+ }
116785
+ }
116786
+ return files;
116787
+ }
116788
+ function getMergeStrategy(config3) {
116789
+ return config3.merge_strategy ?? "merge";
116790
+ }
116791
+ async function mergeLaneBranch(primaryDir, branchName, strategy) {
116792
+ let result;
116793
+ switch (strategy) {
116794
+ case "merge":
116795
+ result = await runGit2(["merge", "--no-edit", branchName], primaryDir);
116796
+ break;
116797
+ case "rebase":
116798
+ result = await runGit2(["rebase", branchName], primaryDir);
116799
+ break;
116800
+ case "cherry-pick": {
116801
+ const mergeBaseResult = await runGit2(["merge-base", "HEAD", branchName], primaryDir);
116802
+ if (mergeBaseResult.exitCode === 0 && mergeBaseResult.stdout.trim()) {
116803
+ const mergeBase = mergeBaseResult.stdout.trim();
116804
+ result = await runGit2(["cherry-pick", `${mergeBase}..${branchName}`], primaryDir);
116805
+ } else {
116806
+ console.warn("[lean-turbo] mergeLaneBranch: git merge-base failed for cherry-pick; falling back to tip-only cherry-pick");
116807
+ result = await runGit2(["cherry-pick", branchName], primaryDir);
116808
+ }
116809
+ break;
116810
+ }
116811
+ }
116812
+ if (result.exitCode === 0) {
116813
+ return { merged: true, strategy };
116814
+ }
116815
+ const combinedOutput = `${result.stderr}
116816
+ ${result.stdout}`;
116817
+ const hasConflict = /CONFLICT/i.test(combinedOutput) || /conflict/i.test(combinedOutput);
116818
+ if (hasConflict) {
116819
+ const files = parseConflictFiles(combinedOutput);
116820
+ const abortArgs = strategy === "rebase" ? ["rebase", "--abort"] : strategy === "cherry-pick" ? ["cherry-pick", "--abort"] : ["merge", "--abort"];
116821
+ await runGit2(abortArgs, primaryDir);
116822
+ return {
116823
+ conflict: true,
116824
+ files,
116825
+ message: result.stderr.trim()
116826
+ };
116827
+ }
116828
+ return {
116829
+ error: result.stderr.trim() || result.stdout.trim()
116830
+ };
116831
+ }
116832
+ async function postMergeCleanup(directory, branchName) {
116833
+ const deleteResult = await runGit2(["branch", "-D", branchName], directory);
116834
+ const deleteOk = deleteResult.exitCode === 0;
116835
+ const pruneResult = await runGit2(["worktree", "prune"], directory);
116836
+ const pruneOk = pruneResult.exitCode === 0;
116837
+ if (deleteOk && pruneOk) {
116838
+ return { cleaned: true };
116839
+ }
116840
+ if (!deleteOk && pruneOk) {
116841
+ return {
116842
+ error: `Branch delete failed: ${deleteResult.stderr.trim() || deleteResult.stdout.trim()}`,
116843
+ partial: true
116844
+ };
116845
+ }
116846
+ return {
116847
+ error: deleteOk ? `Worktree prune failed: ${pruneResult.stderr.trim() || pruneResult.stdout.trim()}` : `Branch delete failed: ${deleteResult.stderr.trim() || deleteResult.stdout.trim()}; worktree prune failed: ${pruneResult.stderr.trim() || pruneResult.stdout.trim()}`
116848
+ };
116849
+ }
116850
+ async function attemptMergeBackFromDirty(worktreePath, branchName, primaryDir, strategy) {
116851
+ let autoCommitted = false;
116852
+ let cleaned = false;
116853
+ let autoCommitFailed = false;
116854
+ let cleanFailed = false;
116855
+ const commitResult = await autoCommitDirty(worktreePath);
116856
+ if (commitResult.committed) {
116857
+ autoCommitted = true;
116858
+ } else if (commitResult.reason !== "Nothing to commit") {
116859
+ autoCommitFailed = true;
116860
+ console.warn(`[lean-turbo] attemptMergeBackFromDirty: auto-commit failed for worktree "${worktreePath}" branch "${branchName}": ${commitResult.reason}`);
116861
+ }
116862
+ const cleanResult = await cleanUntrackedFiles(worktreePath);
116863
+ if (cleanResult.cleaned) {
116864
+ cleaned = true;
116865
+ } else {
116866
+ cleanFailed = true;
116867
+ console.warn(`[lean-turbo] attemptMergeBackFromDirty: clean untracked failed for worktree "${worktreePath}" branch "${branchName}": ${cleanResult.error}`);
116868
+ }
116869
+ if (autoCommitFailed && cleanFailed) {
116870
+ return {
116871
+ failed: true,
116872
+ stage: "cleanup",
116873
+ message: "Auto-commit and clean both failed; abandoning worktree"
116874
+ };
116875
+ }
116876
+ const mergeResult = await mergeLaneBranch(primaryDir, branchName, strategy);
116877
+ if ("merged" in mergeResult && mergeResult.merged) {
116878
+ return { merged: true, strategy, autoCommitted, cleaned };
116879
+ }
116880
+ if ("conflict" in mergeResult) {
116881
+ return {
116882
+ partial: true,
116883
+ stage: "merge",
116884
+ autoCommitted,
116885
+ cleaned,
116886
+ message: mergeResult.message
116887
+ };
116888
+ }
116889
+ if ("error" in mergeResult) {
116890
+ return {
116891
+ failed: true,
116892
+ stage: "merge",
116893
+ message: mergeResult.error
116894
+ };
116895
+ }
116896
+ return {
116897
+ failed: true,
116898
+ stage: "merge",
116899
+ message: "Merge failed with unexpected result"
116900
+ };
116901
+ }
116902
+ function extractSessionId(branchName) {
116903
+ const segments = branchName.trim().split("/");
116904
+ if (segments.length >= 3 && segments[0] === "swarm-lane") {
116905
+ return segments[1];
116906
+ }
116907
+ return null;
116908
+ }
116909
+ async function startupOrphanRecovery(directory, activeSessionIds = []) {
116910
+ const warnings = [];
116911
+ const pruneResult = await runGit2(["worktree", "prune"], directory);
116912
+ if (pruneResult.exitCode !== 0) {
116913
+ warnings.push(`git worktree prune failed: ${pruneResult.stderr.trim() || pruneResult.stdout.trim()}`);
116914
+ }
116915
+ const listResult = await runGit2(["branch", "--format=%(refname:short)", "--list", "swarm-lane/*"], directory);
116916
+ const allBranches = listResult.stdout.split(`
116917
+ `).map((line) => line.trim()).filter((line) => line.length > 0);
116918
+ const orphanBranches = [];
116919
+ for (const branch of allBranches) {
116920
+ const sessionId = extractSessionId(branch);
116921
+ if (sessionId === null || !activeSessionIds.includes(sessionId)) {
116922
+ orphanBranches.push(branch);
116923
+ warnings.push(`Orphaned swarm-lane branch "${branch}" detected in "${directory}"`);
116924
+ }
116925
+ }
116926
+ for (const warning of warnings) {
116927
+ console.warn(warning);
116928
+ }
116929
+ return {
116930
+ prunedWorktrees: pruneResult.exitCode === 0,
116931
+ remainingBranches: orphanBranches,
116932
+ warnings
116933
+ };
116934
+ }
116935
+
116936
+ // src/turbo/lean/runner.ts
116506
116937
  init_state3();
116938
+ function isTransientProvisionError(errorMsg) {
116939
+ const lower = errorMsg.toLowerCase();
116940
+ if (lower.includes("already exists") || lower.includes("not a git repository")) {
116941
+ return false;
116942
+ }
116943
+ const transientCodes = [
116944
+ "enoent",
116945
+ "econnrefused",
116946
+ "etimedout",
116947
+ "ebusy",
116948
+ "eperm",
116949
+ "enomem"
116950
+ ];
116951
+ for (const code of transientCodes) {
116952
+ if (lower.includes(code)) {
116953
+ return true;
116954
+ }
116955
+ }
116956
+ const transientMessages = [
116957
+ "disk full",
116958
+ "no space left",
116959
+ "resource temporarily unavailable"
116960
+ ];
116961
+ for (const msg of transientMessages) {
116962
+ if (lower.includes(msg)) {
116963
+ return true;
116964
+ }
116965
+ }
116966
+ if (lower.includes("fatal:")) {
116967
+ return true;
116968
+ }
116969
+ return false;
116970
+ }
116507
116971
 
116508
116972
  class LeanTurboRunner {
116509
116973
  static _internals = {
@@ -116516,7 +116980,15 @@ class LeanTurboRunner {
116516
116980
  hasActiveFullAuto,
116517
116981
  loadFullAutoRunState,
116518
116982
  writeLaneEvidence,
116519
- laneDispatchTimeoutMs: undefined
116983
+ laneDispatchTimeoutMs: undefined,
116984
+ provisionWorktree,
116985
+ removeWorktree,
116986
+ mergeLaneBranch,
116987
+ postMergeCleanup,
116988
+ attemptMergeBackFromDirty,
116989
+ startupOrphanRecovery,
116990
+ getMergeStrategy,
116991
+ assertCleanWorkingTree
116520
116992
  };
116521
116993
  _sessionOps = null;
116522
116994
  _directory;
@@ -116575,6 +117047,22 @@ class LeanTurboRunner {
116575
117047
  }
116576
117048
  }
116577
117049
  const leanConfig = this._getLeanConfig(this._leanConfig);
117050
+ if (leanConfig.worktree_isolation) {
117051
+ await LeanTurboRunner._internals.startupOrphanRecovery(this._directory, [
117052
+ this._sessionID
117053
+ ]);
117054
+ try {
117055
+ const cleanResult = await LeanTurboRunner._internals.assertCleanWorkingTree(this._directory);
117056
+ if (!cleanResult.clean) {
117057
+ console.warn(`[lean-turbo] worktree isolation requires clean working tree: ${cleanResult.error}`);
117058
+ leanConfig.worktree_isolation = false;
117059
+ }
117060
+ } catch (assertErr) {
117061
+ const assertMsg = assertErr instanceof Error ? assertErr.message : String(assertErr);
117062
+ console.warn(`[lean-turbo] unable to verify working tree cleanliness: ${assertMsg} — degrading to shared directory`);
117063
+ leanConfig.worktree_isolation = false;
117064
+ }
117065
+ }
116578
117066
  const lanePlan = LeanTurboRunner._internals.planLeanTurboLanes(this._directory, phaseNumber, { phases: plan.phases }, leanConfig);
116579
117067
  const degradedTasks = lanePlan.degradedTasks.map((d) => d.taskId);
116580
117068
  if (lanePlan.lanes.length === 0 && degradedTasks.length === 0 && lanePlan.serializedTasks.length === 0) {
@@ -116598,21 +117086,23 @@ class LeanTurboRunner {
116598
117086
  await this._withStateLock(() => this._updateDurableState(lanePlan));
116599
117087
  this._laneStatuses = new Map(lanePlan.lanes.map((lane) => [lane.laneId, { ...lane }]));
116600
117088
  const laneResults = [];
116601
- const results = await Promise.all(lanePlan.lanes.map((lane) => this._processLane(lane)));
117089
+ const results = await Promise.all(lanePlan.lanes.map((lane) => this._processLane(lane, leanConfig)));
116602
117090
  laneResults.push(...results);
117091
+ const mergeBackFailures = await this._sequentialWorktreeCleanup(laneResults, leanConfig);
116603
117092
  return {
116604
117093
  ok: true,
116605
117094
  lanes: laneResults,
116606
117095
  degradedTasks,
116607
- serializedTasks: lanePlan.serializedTasks
117096
+ serializedTasks: lanePlan.serializedTasks,
117097
+ mergeBackFailures: mergeBackFailures.length > 0 ? mergeBackFailures : undefined
116608
117098
  };
116609
117099
  }
116610
- async dispatchLane(lane, agentName) {
117100
+ async dispatchLane(lane, agentName, worktreeDirectory) {
116611
117101
  const session = this._sessionOps ?? this._client?.session;
116612
117102
  if (!session) {
116613
117103
  return { ok: false, error: "NO_CLIENT" };
116614
117104
  }
116615
- const dispatchPromise = this._doDispatch(session, lane, agentName);
117105
+ const dispatchPromise = this._doDispatch(session, lane, agentName, worktreeDirectory);
116616
117106
  const timeoutMs = LeanTurboRunner._internals.laneDispatchTimeoutMs;
116617
117107
  if (timeoutMs !== undefined && timeoutMs > 0) {
116618
117108
  const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error(`Lane dispatch timed out after ${timeoutMs}ms`)), timeoutMs));
@@ -116643,10 +117133,11 @@ class LeanTurboRunner {
116643
117133
  }
116644
117134
  return dispatchPromise;
116645
117135
  }
116646
- async _doDispatch(session, lane, agentName) {
117136
+ async _doDispatch(session, lane, agentName, worktreeDirectory) {
116647
117137
  try {
117138
+ const effectiveDirectory = worktreeDirectory ?? this._directory;
116648
117139
  const createResult = await session.create({
116649
- query: { directory: this._directory }
117140
+ query: { directory: effectiveDirectory }
116650
117141
  });
116651
117142
  if (!createResult.data) {
116652
117143
  return {
@@ -116698,6 +117189,13 @@ class LeanTurboRunner {
116698
117189
  } catch {}
116699
117190
  }
116700
117191
  this._laneLockMap = {};
117192
+ for (const [_laneId, lane] of this._laneStatuses) {
117193
+ if (lane.worktreePath) {
117194
+ try {
117195
+ await LeanTurboRunner._internals.removeWorktree(lane.worktreePath, this._directory);
117196
+ } catch {}
117197
+ }
117198
+ }
116701
117199
  await this._withStateLock(async () => {
116702
117200
  const runState = LeanTurboRunner._internals.loadLeanTurboRunState(this._directory, this._sessionID);
116703
117201
  if (runState) {
@@ -116745,7 +117243,7 @@ class LeanTurboRunner {
116745
117243
  }
116746
117244
  return defaults;
116747
117245
  }
116748
- async _processLane(lane) {
117246
+ async _processLane(lane, leanConfig) {
116749
117247
  const laneInState = this._laneStatuses.get(lane.laneId);
116750
117248
  if (laneInState) {
116751
117249
  laneInState.status = "running";
@@ -116782,12 +117280,85 @@ class LeanTurboRunner {
116782
117280
  };
116783
117281
  }
116784
117282
  this._laneLockMap[lane.laneId] = [...lane.files];
116785
- const dispatchResult = await this.dispatchLane(lane, agent);
117283
+ let worktreeDirectory;
117284
+ if (leanConfig.worktree_isolation) {
117285
+ let provisionError;
117286
+ try {
117287
+ const provisionResult = await LeanTurboRunner._internals.provisionWorktree(this._directory, lane.laneId, this._sessionID, leanConfig);
117288
+ if ("worktreePath" in provisionResult) {
117289
+ worktreeDirectory = provisionResult.worktreePath;
117290
+ if (laneInState) {
117291
+ laneInState.worktreePath = provisionResult.worktreePath;
117292
+ laneInState.branchName = provisionResult.branchName;
117293
+ }
117294
+ await this._persistLaneWorktreeFields(lane.laneId, provisionResult.worktreePath, provisionResult.branchName);
117295
+ } else {
117296
+ provisionError = provisionResult.error;
117297
+ }
117298
+ } catch (provisionErr) {
117299
+ provisionError = provisionErr instanceof Error ? provisionErr.message : String(provisionErr);
117300
+ }
117301
+ if (provisionError) {
117302
+ if (isTransientProvisionError(provisionError)) {
117303
+ console.warn(`[lean-turbo] worktree provision failed for lane ${lane.laneId}: ${provisionError} — retrying once...`);
117304
+ await new Promise((r) => setTimeout(r, 100));
117305
+ try {
117306
+ const retryResult = await LeanTurboRunner._internals.provisionWorktree(this._directory, lane.laneId, this._sessionID, leanConfig);
117307
+ if ("worktreePath" in retryResult) {
117308
+ worktreeDirectory = retryResult.worktreePath;
117309
+ if (laneInState) {
117310
+ laneInState.worktreePath = retryResult.worktreePath;
117311
+ laneInState.branchName = retryResult.branchName;
117312
+ }
117313
+ await this._persistLaneWorktreeFields(lane.laneId, retryResult.worktreePath, retryResult.branchName);
117314
+ console.warn(`[lean-turbo] worktree provision retry succeeded for lane ${lane.laneId}`);
117315
+ provisionError = undefined;
117316
+ } else {
117317
+ provisionError = retryResult.error;
117318
+ console.warn(`[lean-turbo] worktree provision retry failed for lane ${lane.laneId}: ${retryResult.error}`);
117319
+ }
117320
+ } catch (retryErr) {
117321
+ const retryMsg = retryErr instanceof Error ? retryErr.message : String(retryErr);
117322
+ console.warn(`[lean-turbo] worktree provision retry threw for lane ${lane.laneId}: ${retryMsg}`);
117323
+ }
117324
+ } else {
117325
+ console.warn(`[lean-turbo] worktree provision failed for lane ${lane.laneId}: ${provisionError}`);
117326
+ }
117327
+ }
117328
+ if (!worktreeDirectory) {
117329
+ const failMsg = `worktree provision failed: ${provisionError ?? "unknown error"}`;
117330
+ try {
117331
+ await LeanTurboRunner._internals.releaseLaneLocks(this._directory, lane.laneId);
117332
+ } catch {}
117333
+ delete this._laneLockMap[lane.laneId];
117334
+ if (laneInState) {
117335
+ laneInState.status = "failed";
117336
+ laneInState.error = failMsg;
117337
+ }
117338
+ await this._updateDurableStateLaneStatus(lane.laneId, "failed");
117339
+ await this._writeLaneEvidenceSafely(lane, "failed", {
117340
+ status: "failed",
117341
+ error: failMsg,
117342
+ agent
117343
+ });
117344
+ return {
117345
+ laneId: lane.laneId,
117346
+ status: "failed",
117347
+ taskIds: lane.taskIds,
117348
+ agent,
117349
+ error: failMsg
117350
+ };
117351
+ }
117352
+ }
117353
+ const dispatchResult = await this.dispatchLane(lane, agent, worktreeDirectory);
116786
117354
  if (!dispatchResult.ok) {
116787
117355
  try {
116788
117356
  await LeanTurboRunner._internals.releaseLaneLocks(this._directory, lane.laneId);
116789
117357
  } catch {}
116790
117358
  delete this._laneLockMap[lane.laneId];
117359
+ if (worktreeDirectory && laneInState) {
117360
+ laneInState._failureCleanupPending = true;
117361
+ }
116791
117362
  if (laneInState) {
116792
117363
  laneInState.status = "failed";
116793
117364
  laneInState.error = dispatchResult.error;
@@ -116832,6 +117403,69 @@ class LeanTurboRunner {
116832
117403
  sessionId: dispatchResult.sessionId
116833
117404
  };
116834
117405
  }
117406
+ async _sequentialWorktreeCleanup(laneResults, leanConfig) {
117407
+ const mergeBackFailures = [];
117408
+ for (const lr of laneResults) {
117409
+ const laneInState = this._laneStatuses.get(lr.laneId);
117410
+ if (!laneInState?.worktreePath)
117411
+ continue;
117412
+ let needsPostMergeCleanup = false;
117413
+ if (lr.status === "completed") {
117414
+ if (!laneInState.branchName)
117415
+ continue;
117416
+ try {
117417
+ const strategy = LeanTurboRunner._internals.getMergeStrategy(leanConfig);
117418
+ const mergeResult = await LeanTurboRunner._internals.mergeLaneBranch(this._directory, laneInState.branchName, strategy);
117419
+ if ("merged" in mergeResult && mergeResult.merged) {
117420
+ needsPostMergeCleanup = true;
117421
+ } else if ("conflict" in mergeResult && mergeResult.conflict) {
117422
+ const failureInfo = {
117423
+ laneId: lr.laneId,
117424
+ reason: mergeResult.message || "merge conflict",
117425
+ conflictFiles: mergeResult.files
117426
+ };
117427
+ mergeBackFailures.push(failureInfo);
117428
+ lr.mergeBackFailure = failureInfo;
117429
+ console.warn(`[lean-turbo] merge-back CONFLICT for lane ${lr.laneId}: ${failureInfo.reason} — worktree preserved at ${laneInState.worktreePath} for manual recovery`);
117430
+ continue;
117431
+ } else if ("error" in mergeResult && mergeResult.error) {
117432
+ const failureInfo = {
117433
+ laneId: lr.laneId,
117434
+ reason: mergeResult.error
117435
+ };
117436
+ mergeBackFailures.push(failureInfo);
117437
+ lr.mergeBackFailure = failureInfo;
117438
+ console.warn(`[lean-turbo] merge-back ERROR for lane ${lr.laneId}: ${failureInfo.reason} — worktree preserved at ${laneInState.worktreePath} for manual recovery`);
117439
+ continue;
117440
+ }
117441
+ } catch (err2) {
117442
+ const errMsg = err2 instanceof Error ? err2.message : String(err2);
117443
+ const failureInfo = {
117444
+ laneId: lr.laneId,
117445
+ reason: errMsg
117446
+ };
117447
+ mergeBackFailures.push(failureInfo);
117448
+ lr.mergeBackFailure = failureInfo;
117449
+ console.warn(`[lean-turbo] merge-back EXCEPTION for lane ${lr.laneId}: ${errMsg} — worktree preserved at ${laneInState.worktreePath} for manual recovery`);
117450
+ continue;
117451
+ }
117452
+ } else if (lr.status === "failed" && laneInState._failureCleanupPending) {
117453
+ try {
117454
+ const strategy = LeanTurboRunner._internals.getMergeStrategy(leanConfig);
117455
+ await LeanTurboRunner._internals.attemptMergeBackFromDirty(laneInState.worktreePath, laneInState.branchName ?? `swarm-lane/${this._sessionID}/${lr.laneId}`, this._directory, strategy);
117456
+ } catch {}
117457
+ }
117458
+ try {
117459
+ await LeanTurboRunner._internals.removeWorktree(laneInState.worktreePath, this._directory);
117460
+ } catch {}
117461
+ if (needsPostMergeCleanup && laneInState.branchName) {
117462
+ try {
117463
+ await LeanTurboRunner._internals.postMergeCleanup(this._directory, laneInState.branchName);
117464
+ } catch {}
117465
+ }
117466
+ }
117467
+ return mergeBackFailures;
117468
+ }
116835
117469
  _selectNextAgent() {
116836
117470
  if (this._availableAgents.length === 0) {
116837
117471
  return "coder";
@@ -116925,6 +117559,21 @@ ${fileList}
116925
117559
  LeanTurboRunner._internals.saveLeanTurboRunState(this._directory, runState);
116926
117560
  } catch {}
116927
117561
  }
117562
+ async _persistLaneWorktreeFields(laneId, worktreePath, branchName) {
117563
+ await this._withStateLock(async () => {
117564
+ try {
117565
+ const runState = LeanTurboRunner._internals.loadLeanTurboRunState(this._directory, this._sessionID);
117566
+ if (!runState)
117567
+ return;
117568
+ const lane = runState.lanes.find((l) => l.laneId === laneId);
117569
+ if (lane) {
117570
+ lane.worktreePath = worktreePath;
117571
+ lane.branchName = branchName;
117572
+ LeanTurboRunner._internals.saveLeanTurboRunState(this._directory, runState);
117573
+ }
117574
+ } catch {}
117575
+ });
117576
+ }
116928
117577
  async _updateDurableStateLaneStatus(laneId, status) {
116929
117578
  await this._withStateLock(async () => {
116930
117579
  try {
@@ -116950,7 +117599,7 @@ ${fileList}
116950
117599
 
116951
117600
  // src/tools/lean-turbo-run-phase.ts
116952
117601
  init_create_tool();
116953
- var _internals62 = {
117602
+ var _internals64 = {
116954
117603
  LeanTurboRunner,
116955
117604
  loadPluginConfigWithMeta
116956
117605
  };
@@ -116960,9 +117609,9 @@ async function executeLeanTurboRunPhase(args2) {
116960
117609
  let runError = null;
116961
117610
  let runner = null;
116962
117611
  try {
116963
- const { config: config3 } = _internals62.loadPluginConfigWithMeta(directory);
117612
+ const { config: config3 } = _internals64.loadPluginConfigWithMeta(directory);
116964
117613
  const leanConfig = config3.turbo?.strategy === "lean" ? config3.turbo.lean : undefined;
116965
- runner = new _internals62.LeanTurboRunner({
117614
+ runner = new _internals64.LeanTurboRunner({
116966
117615
  directory,
116967
117616
  sessionID,
116968
117617
  opencodeClient: swarmState.opencodeClient ?? null,
@@ -116995,6 +117644,7 @@ async function executeLeanTurboRunPhase(args2) {
116995
117644
  lanes: runResult.lanes,
116996
117645
  degradedTasks: runResult.degradedTasks,
116997
117646
  serializedTasks: runResult.serializedTasks,
117647
+ mergeBackFailures: runResult.mergeBackFailures,
116998
117648
  reason: runResult.reason
116999
117649
  };
117000
117650
  }
@@ -117121,7 +117771,7 @@ init_lint();
117121
117771
  init_spec_schema();
117122
117772
  init_create_tool();
117123
117773
  import * as fs99 from "node:fs";
117124
- import * as path137 from "node:path";
117774
+ import * as path138 from "node:path";
117125
117775
  var SPEC_FILE_NAME = "spec.md";
117126
117776
  var SWARM_DIR2 = ".swarm";
117127
117777
  var OBLIGATION_KEYWORDS = ["MUST", "SHALL", "SHOULD", "MAY"];
@@ -117174,7 +117824,7 @@ var lint_spec = createSwarmTool({
117174
117824
  async execute(_args, directory) {
117175
117825
  const errors5 = [];
117176
117826
  const warnings = [];
117177
- const specPath = path137.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
117827
+ const specPath = path138.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
117178
117828
  if (!fs99.existsSync(specPath)) {
117179
117829
  const result2 = {
117180
117830
  valid: false,
@@ -117246,12 +117896,12 @@ var lint_spec = createSwarmTool({
117246
117896
  // src/tools/mutation-test.ts
117247
117897
  init_zod();
117248
117898
  import * as fs100 from "node:fs";
117249
- import * as path139 from "node:path";
117899
+ import * as path140 from "node:path";
117250
117900
 
117251
117901
  // src/mutation/engine.ts
117252
117902
  import { spawnSync as spawnSync9 } from "node:child_process";
117253
117903
  import { unlinkSync as unlinkSync19, writeFileSync as writeFileSync26 } from "node:fs";
117254
- import * as path138 from "node:path";
117904
+ import * as path139 from "node:path";
117255
117905
 
117256
117906
  // src/mutation/equivalence.ts
117257
117907
  function isStaticallyEquivalent(originalCode, mutatedCode) {
@@ -117323,7 +117973,7 @@ function isStaticallyEquivalent(originalCode, mutatedCode) {
117323
117973
  const strippedMutated = stripCode(mutatedCode);
117324
117974
  return strippedOriginal === strippedMutated;
117325
117975
  }
117326
- var _internals63 = {
117976
+ var _internals65 = {
117327
117977
  isStaticallyEquivalent,
117328
117978
  checkEquivalence,
117329
117979
  batchCheckEquivalence
@@ -117363,7 +118013,7 @@ async function batchCheckEquivalence(patches, llmJudge) {
117363
118013
  const results = [];
117364
118014
  for (const { patch, originalCode, mutatedCode } of patches) {
117365
118015
  try {
117366
- const result = await _internals63.checkEquivalence(patch, originalCode, mutatedCode, llmJudge);
118016
+ const result = await _internals65.checkEquivalence(patch, originalCode, mutatedCode, llmJudge);
117367
118017
  results.push(result);
117368
118018
  } catch (err2) {
117369
118019
  results.push({
@@ -117382,7 +118032,7 @@ async function batchCheckEquivalence(patches, llmJudge) {
117382
118032
  var MUTATION_TIMEOUT_MS = 30000;
117383
118033
  var TOTAL_BUDGET_MS = 300000;
117384
118034
  var GIT_APPLY_TIMEOUT_MS = 5000;
117385
- var _internals64 = {
118035
+ var _internals66 = {
117386
118036
  executeMutation,
117387
118037
  computeReport,
117388
118038
  executeMutationSuite,
@@ -117397,7 +118047,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
117397
118047
  let patchFile;
117398
118048
  try {
117399
118049
  const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
117400
- patchFile = path138.join(workingDir, `.mutation_patch_${safeId2}.diff`);
118050
+ patchFile = path139.join(workingDir, `.mutation_patch_${safeId2}.diff`);
117401
118051
  try {
117402
118052
  writeFileSync26(patchFile, patch.patch);
117403
118053
  } catch (writeErr) {
@@ -117414,7 +118064,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
117414
118064
  };
117415
118065
  }
117416
118066
  try {
117417
- const applyResult = _internals64.spawnSync("git", ["apply", "--", patchFile], {
118067
+ const applyResult = _internals66.spawnSync("git", ["apply", "--", patchFile], {
117418
118068
  cwd: workingDir,
117419
118069
  timeout: GIT_APPLY_TIMEOUT_MS,
117420
118070
  stdio: "pipe"
@@ -117443,7 +118093,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
117443
118093
  }
117444
118094
  let testPassed = false;
117445
118095
  try {
117446
- const spawnResult = _internals64.spawnSync(testCommand[0], testCommand.slice(1), {
118096
+ const spawnResult = _internals66.spawnSync(testCommand[0], testCommand.slice(1), {
117447
118097
  cwd: workingDir,
117448
118098
  timeout: MUTATION_TIMEOUT_MS,
117449
118099
  stdio: "pipe"
@@ -117476,7 +118126,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
117476
118126
  } finally {
117477
118127
  if (patchFile) {
117478
118128
  try {
117479
- const revertResult = _internals64.spawnSync("git", ["apply", "-R", "--", patchFile], {
118129
+ const revertResult = _internals66.spawnSync("git", ["apply", "-R", "--", patchFile], {
117480
118130
  cwd: workingDir,
117481
118131
  timeout: GIT_APPLY_TIMEOUT_MS,
117482
118132
  stdio: "pipe"
@@ -117669,7 +118319,7 @@ async function executeMutationSuite(patches, testCommand, testFiles, workingDir,
117669
118319
  }
117670
118320
 
117671
118321
  // src/mutation/gate.ts
117672
- var _internals65 = {
118322
+ var _internals67 = {
117673
118323
  evaluateMutationGate,
117674
118324
  buildTestImprovementPrompt,
117675
118325
  buildMessage
@@ -117690,8 +118340,8 @@ function evaluateMutationGate(report, passThreshold = PASS_THRESHOLD, warnThresh
117690
118340
  } else {
117691
118341
  verdict = "fail";
117692
118342
  }
117693
- const testImprovementPrompt = _internals65.buildTestImprovementPrompt(report, passThreshold, verdict);
117694
- const message = _internals65.buildMessage(verdict, adjustedKillRate, report.killed, report.totalMutants, report.equivalent, warnThreshold);
118343
+ const testImprovementPrompt = _internals67.buildTestImprovementPrompt(report, passThreshold, verdict);
118344
+ const message = _internals67.buildMessage(verdict, adjustedKillRate, report.killed, report.totalMutants, report.equivalent, warnThreshold);
117695
118345
  return {
117696
118346
  verdict,
117697
118347
  killRate: report.killRate,
@@ -117801,7 +118451,7 @@ var mutation_test = createSwarmTool({
117801
118451
  ];
117802
118452
  for (const filePath of uniquePaths) {
117803
118453
  try {
117804
- const resolvedPath = path139.resolve(cwd, filePath);
118454
+ const resolvedPath = path140.resolve(cwd, filePath);
117805
118455
  sourceFiles.set(filePath, fs100.readFileSync(resolvedPath, "utf-8"));
117806
118456
  } catch {}
117807
118457
  }
@@ -117823,22 +118473,22 @@ init_config();
117823
118473
  init_schema();
117824
118474
  init_manager2();
117825
118475
  import * as fs110 from "node:fs";
117826
- import * as path149 from "node:path";
118476
+ import * as path150 from "node:path";
117827
118477
 
117828
118478
  // src/full-auto/phase-approval.ts
117829
118479
  init_utils2();
117830
118480
  init_logger();
117831
118481
  init_state2();
117832
118482
  import * as fs101 from "node:fs";
117833
- import * as path140 from "node:path";
118483
+ import * as path141 from "node:path";
117834
118484
  var APPROVAL_TTL_MS = 24 * 60 * 60 * 1000;
117835
118485
  function readEvidenceDir(directory, phase) {
117836
118486
  try {
117837
- const dirPath = validateSwarmPath(directory, path140.posix.join("evidence", String(phase)));
118487
+ const dirPath = validateSwarmPath(directory, path141.posix.join("evidence", String(phase)));
117838
118488
  if (!fs101.existsSync(dirPath))
117839
118489
  return [];
117840
118490
  const entries = fs101.readdirSync(dirPath);
117841
- return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path140.join(dirPath, e));
118491
+ return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path141.join(dirPath, e));
117842
118492
  } catch {
117843
118493
  return [];
117844
118494
  }
@@ -117979,16 +118629,16 @@ init_plan_schema();
117979
118629
  init_ledger();
117980
118630
  init_manager();
117981
118631
  import * as fs102 from "node:fs";
117982
- import * as path141 from "node:path";
118632
+ import * as path142 from "node:path";
117983
118633
  async function writeCheckpoint(directory) {
117984
118634
  try {
117985
118635
  const plan = await loadPlan(directory);
117986
118636
  if (!plan)
117987
118637
  return;
117988
- const swarmDir = path141.join(directory, ".swarm");
118638
+ const swarmDir = path142.join(directory, ".swarm");
117989
118639
  fs102.mkdirSync(swarmDir, { recursive: true });
117990
- const jsonPath = path141.join(swarmDir, "SWARM_PLAN.json");
117991
- const mdPath = path141.join(swarmDir, "SWARM_PLAN.md");
118640
+ const jsonPath = path142.join(swarmDir, "SWARM_PLAN.json");
118641
+ const mdPath = path142.join(swarmDir, "SWARM_PLAN.md");
117992
118642
  fs102.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
117993
118643
  const md = derivePlanMarkdown(plan);
117994
118644
  fs102.writeFileSync(mdPath, md, "utf8");
@@ -118007,7 +118657,7 @@ init_telemetry();
118007
118657
  // src/turbo/lean/phase-ready.ts
118008
118658
  init_file_locks();
118009
118659
  import * as fs103 from "node:fs";
118010
- import * as path142 from "node:path";
118660
+ import * as path143 from "node:path";
118011
118661
  init_state3();
118012
118662
  var DEFAULT_CONFIG3 = {
118013
118663
  phase_reviewer: true,
@@ -118016,7 +118666,7 @@ var DEFAULT_CONFIG3 = {
118016
118666
  };
118017
118667
  function defaultReadPlanJson(dir) {
118018
118668
  try {
118019
- const planPath = path142.join(dir, ".swarm", "plan.json");
118669
+ const planPath = path143.join(dir, ".swarm", "plan.json");
118020
118670
  if (!fs103.existsSync(planPath))
118021
118671
  return null;
118022
118672
  const raw = fs103.readFileSync(planPath, "utf-8");
@@ -118031,7 +118681,7 @@ function defaultReadPlanJson(dir) {
118031
118681
  }
118032
118682
  function readReviewerEvidenceFromFile(directory, phase) {
118033
118683
  try {
118034
- const evidencePath = path142.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
118684
+ const evidencePath = path143.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
118035
118685
  if (!fs103.existsSync(evidencePath)) {
118036
118686
  return null;
118037
118687
  }
@@ -118051,7 +118701,7 @@ function readReviewerEvidenceFromFile(directory, phase) {
118051
118701
  }
118052
118702
  function readCriticEvidenceFromFile(directory, phase) {
118053
118703
  try {
118054
- const evidencePath = path142.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
118704
+ const evidencePath = path143.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
118055
118705
  if (!fs103.existsSync(evidencePath)) {
118056
118706
  return null;
118057
118707
  }
@@ -118070,7 +118720,7 @@ function readCriticEvidenceFromFile(directory, phase) {
118070
118720
  }
118071
118721
  }
118072
118722
  function listLaneEvidenceSync(directory, phase) {
118073
- const evidenceDir = path142.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
118723
+ const evidenceDir = path143.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
118074
118724
  let entries;
118075
118725
  try {
118076
118726
  entries = fs103.readdirSync(evidenceDir);
@@ -118086,7 +118736,7 @@ function listLaneEvidenceSync(directory, phase) {
118086
118736
  }
118087
118737
  return laneIds;
118088
118738
  }
118089
- var _internals66 = {
118739
+ var _internals68 = {
118090
118740
  listActiveLocks,
118091
118741
  readPersisted: readPersisted2,
118092
118742
  readPlanJson: defaultReadPlanJson,
@@ -118140,14 +118790,14 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
118140
118790
  ...DEFAULT_CONFIG3,
118141
118791
  ...actualConfig
118142
118792
  };
118143
- const statePath = path142.join(directory, ".swarm", "turbo-state.json");
118793
+ const statePath = path143.join(directory, ".swarm", "turbo-state.json");
118144
118794
  if (!fs103.existsSync(statePath)) {
118145
118795
  return {
118146
118796
  ok: false,
118147
118797
  reason: "Lean Turbo state unreadable or missing"
118148
118798
  };
118149
118799
  }
118150
- const persisted = _internals66.readPersisted(directory);
118800
+ const persisted = _internals68.readPersisted(directory);
118151
118801
  if (!persisted) {
118152
118802
  return {
118153
118803
  ok: false,
@@ -118211,7 +118861,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
118211
118861
  }
118212
118862
  }
118213
118863
  if (runState.lanes.length > 0) {
118214
- const evidenceLaneIds = new Set(_internals66.listLaneEvidenceSync(directory, phase));
118864
+ const evidenceLaneIds = new Set(_internals68.listLaneEvidenceSync(directory, phase));
118215
118865
  for (const lane of runState.lanes) {
118216
118866
  if ((lane.status === "completed" || lane.status === "failed") && !evidenceLaneIds.has(lane.laneId)) {
118217
118867
  return {
@@ -118221,7 +118871,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
118221
118871
  }
118222
118872
  }
118223
118873
  }
118224
- const activeLocks = _internals66.listActiveLocks(directory);
118874
+ const activeLocks = _internals68.listActiveLocks(directory);
118225
118875
  const phaseLaneIds = new Set(laneIds);
118226
118876
  for (const lock of activeLocks) {
118227
118877
  if (lock.laneId && phaseLaneIds.has(lock.laneId)) {
@@ -118241,7 +118891,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
118241
118891
  }
118242
118892
  const serialDegradedTasks = runState.degradedTasks.filter((dt) => !laneTaskIds.has(dt.taskId));
118243
118893
  if (serialDegradedTasks.length > 0) {
118244
- const plan = _internals66.readPlanJson(directory);
118894
+ const plan = _internals68.readPlanJson(directory);
118245
118895
  if (!plan) {
118246
118896
  return {
118247
118897
  ok: false,
@@ -118285,7 +118935,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
118285
118935
  }
118286
118936
  const serializedTasks = runState.serializedTasks;
118287
118937
  if (Array.isArray(serializedTasks) && serializedTasks.length > 0) {
118288
- const plan = _internals66.readPlanJson(directory);
118938
+ const plan = _internals68.readPlanJson(directory);
118289
118939
  if (!plan) {
118290
118940
  return {
118291
118941
  ok: false,
@@ -118328,7 +118978,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
118328
118978
  }
118329
118979
  }
118330
118980
  if (mergedConfig.integrated_diff_required) {
118331
- const evidencePath = path142.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
118981
+ const evidencePath = path143.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
118332
118982
  let hasDiff = false;
118333
118983
  try {
118334
118984
  const content = fs103.readFileSync(evidencePath, "utf-8");
@@ -118344,7 +118994,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
118344
118994
  }
118345
118995
  let reviewerVerdict = runState.lastReviewerVerdict;
118346
118996
  if (!reviewerVerdict) {
118347
- const evidence = _internals66.readReviewerEvidence(directory, phase);
118997
+ const evidence = _internals68.readReviewerEvidence(directory, phase);
118348
118998
  reviewerVerdict = evidence?.verdict ?? undefined;
118349
118999
  }
118350
119000
  if (mergedConfig.phase_reviewer) {
@@ -118357,7 +119007,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
118357
119007
  }
118358
119008
  let criticVerdict = runState.lastCriticVerdict;
118359
119009
  if (!criticVerdict) {
118360
- const evidence = _internals66.readCriticEvidence(directory, phase);
119010
+ const evidence = _internals68.readCriticEvidence(directory, phase);
118361
119011
  criticVerdict = evidence?.verdict ?? undefined;
118362
119012
  }
118363
119013
  if (mergedConfig.phase_critic) {
@@ -118480,13 +119130,13 @@ init_qa_gate_profile();
118480
119130
  init_manager();
118481
119131
  init_state();
118482
119132
  import * as fs104 from "node:fs";
118483
- import * as path143 from "node:path";
119133
+ import * as path144 from "node:path";
118484
119134
  async function runDriftGate(ctx) {
118485
119135
  const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
118486
119136
  let driftCheckEnabled = true;
118487
119137
  let driftHasSpecMd = false;
118488
119138
  try {
118489
- const specMdPath = path143.join(dir, ".swarm", "spec.md");
119139
+ const specMdPath = path144.join(dir, ".swarm", "spec.md");
118490
119140
  driftHasSpecMd = fs104.existsSync(specMdPath);
118491
119141
  const gatePlan = await loadPlan(dir);
118492
119142
  if (gatePlan) {
@@ -118514,7 +119164,7 @@ async function runDriftGate(ctx) {
118514
119164
  }
118515
119165
  let phaseType;
118516
119166
  try {
118517
- const planPath = path143.join(dir, ".swarm", "plan.json");
119167
+ const planPath = path144.join(dir, ".swarm", "plan.json");
118518
119168
  if (fs104.existsSync(planPath)) {
118519
119169
  const planRaw = fs104.readFileSync(planPath, "utf-8");
118520
119170
  const plan = JSON.parse(planRaw);
@@ -118533,7 +119183,7 @@ async function runDriftGate(ctx) {
118533
119183
  };
118534
119184
  }
118535
119185
  try {
118536
- const driftEvidencePath = path143.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
119186
+ const driftEvidencePath = path144.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
118537
119187
  let driftVerdictFound = false;
118538
119188
  let driftVerdictApproved = false;
118539
119189
  try {
@@ -118569,7 +119219,7 @@ async function runDriftGate(ctx) {
118569
119219
  let incompleteTaskCount = 0;
118570
119220
  let planParseable = false;
118571
119221
  try {
118572
- const planPath = path143.join(dir, ".swarm", "plan.json");
119222
+ const planPath = path144.join(dir, ".swarm", "plan.json");
118573
119223
  if (fs104.existsSync(planPath)) {
118574
119224
  const planRaw = fs104.readFileSync(planPath, "utf-8");
118575
119225
  const plan = JSON.parse(planRaw);
@@ -118651,7 +119301,7 @@ init_qa_gate_profile();
118651
119301
  init_manager();
118652
119302
  init_state();
118653
119303
  import * as fs105 from "node:fs";
118654
- import * as path144 from "node:path";
119304
+ import * as path145 from "node:path";
118655
119305
  async function runFinalCouncilGate(ctx) {
118656
119306
  const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
118657
119307
  let finalCouncilEnabled = false;
@@ -118669,7 +119319,7 @@ async function runFinalCouncilGate(ctx) {
118669
119319
  const effective = getEffectiveGates(profile, overrides);
118670
119320
  if (effective.final_council === true) {
118671
119321
  finalCouncilEnabled = true;
118672
- const fcPath = path144.join(dir, ".swarm", "evidence", "final-council.json");
119322
+ const fcPath = path145.join(dir, ".swarm", "evidence", "final-council.json");
118673
119323
  let fcVerdictFound = false;
118674
119324
  let _fcVerdict;
118675
119325
  try {
@@ -118810,7 +119460,7 @@ init_qa_gate_profile();
118810
119460
  init_manager();
118811
119461
  init_state();
118812
119462
  import * as fs106 from "node:fs";
118813
- import * as path145 from "node:path";
119463
+ import * as path146 from "node:path";
118814
119464
  async function runHallucinationGate(ctx) {
118815
119465
  const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
118816
119466
  try {
@@ -118823,7 +119473,7 @@ async function runHallucinationGate(ctx) {
118823
119473
  const overrides = session?.qaGateSessionOverrides ?? {};
118824
119474
  const effective = getEffectiveGates(profile, overrides);
118825
119475
  if (effective.hallucination_guard === true) {
118826
- const hgPath = path145.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
119476
+ const hgPath = path146.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
118827
119477
  let hgVerdictFound = false;
118828
119478
  let hgVerdictApproved = false;
118829
119479
  try {
@@ -118886,7 +119536,7 @@ init_qa_gate_profile();
118886
119536
  init_manager();
118887
119537
  init_state();
118888
119538
  import * as fs107 from "node:fs";
118889
- import * as path146 from "node:path";
119539
+ import * as path147 from "node:path";
118890
119540
  async function runMutationGate(ctx) {
118891
119541
  const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
118892
119542
  try {
@@ -118899,7 +119549,7 @@ async function runMutationGate(ctx) {
118899
119549
  const overrides = session?.qaGateSessionOverrides ?? {};
118900
119550
  const effective = getEffectiveGates(profile, overrides);
118901
119551
  if (effective.mutation_test === true) {
118902
- const mgPath = path146.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
119552
+ const mgPath = path147.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
118903
119553
  let mgVerdictFound = false;
118904
119554
  let mgVerdict;
118905
119555
  try {
@@ -118962,7 +119612,7 @@ init_qa_gate_profile();
118962
119612
  init_manager();
118963
119613
  init_state();
118964
119614
  import * as fs108 from "node:fs";
118965
- import * as path147 from "node:path";
119615
+ import * as path148 from "node:path";
118966
119616
  async function runPhaseCouncilGate(ctx) {
118967
119617
  const { phase, dir, sessionID, pluginConfig, agentsDispatched, safeWarn } = ctx;
118968
119618
  let councilModeEnabled = false;
@@ -118977,7 +119627,7 @@ async function runPhaseCouncilGate(ctx) {
118977
119627
  const effective = getEffectiveGates(profile, overrides);
118978
119628
  if (effective.council_mode === true) {
118979
119629
  councilModeEnabled = true;
118980
- const pcPath = path147.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
119630
+ const pcPath = path148.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
118981
119631
  let pcVerdictFound = false;
118982
119632
  let _pcVerdict;
118983
119633
  let pcQuorumSize;
@@ -119469,7 +120119,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
119469
120119
  phase_critic: leanConfig.phase_critic,
119470
120120
  integrated_diff_required: leanConfig.integrated_diff_required
119471
120121
  } : undefined;
119472
- const leanCheck = _internals66.verifyLeanTurboPhaseReady(dir, phase, sessionID, leanPhaseReadyConfig);
120122
+ const leanCheck = _internals68.verifyLeanTurboPhaseReady(dir, phase, sessionID, leanPhaseReadyConfig);
119473
120123
  if (!leanCheck.ok) {
119474
120124
  return JSON.stringify({
119475
120125
  success: false,
@@ -119492,7 +120142,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
119492
120142
  }
119493
120143
  if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
119494
120144
  try {
119495
- const projectName = path149.basename(dir);
120145
+ const projectName = path150.basename(dir);
119496
120146
  const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
119497
120147
  if (curationResult) {
119498
120148
  const sessionState = swarmState.agentSessions.get(sessionID);
@@ -119935,7 +120585,7 @@ init_utils();
119935
120585
  init_bun_compat();
119936
120586
  init_create_tool();
119937
120587
  import * as fs111 from "node:fs";
119938
- import * as path150 from "node:path";
120588
+ import * as path151 from "node:path";
119939
120589
  var MAX_OUTPUT_BYTES6 = 52428800;
119940
120590
  var AUDIT_TIMEOUT_MS = 120000;
119941
120591
  function isValidEcosystem(value) {
@@ -119963,16 +120613,16 @@ function validateArgs3(args2) {
119963
120613
  function detectEcosystems(directory) {
119964
120614
  const ecosystems = [];
119965
120615
  const cwd = directory;
119966
- if (fs111.existsSync(path150.join(cwd, "package.json"))) {
120616
+ if (fs111.existsSync(path151.join(cwd, "package.json"))) {
119967
120617
  ecosystems.push("npm");
119968
120618
  }
119969
- if (fs111.existsSync(path150.join(cwd, "pyproject.toml")) || fs111.existsSync(path150.join(cwd, "requirements.txt"))) {
120619
+ if (fs111.existsSync(path151.join(cwd, "pyproject.toml")) || fs111.existsSync(path151.join(cwd, "requirements.txt"))) {
119970
120620
  ecosystems.push("pip");
119971
120621
  }
119972
- if (fs111.existsSync(path150.join(cwd, "Cargo.toml"))) {
120622
+ if (fs111.existsSync(path151.join(cwd, "Cargo.toml"))) {
119973
120623
  ecosystems.push("cargo");
119974
120624
  }
119975
- if (fs111.existsSync(path150.join(cwd, "go.mod"))) {
120625
+ if (fs111.existsSync(path151.join(cwd, "go.mod"))) {
119976
120626
  ecosystems.push("go");
119977
120627
  }
119978
120628
  try {
@@ -119981,13 +120631,13 @@ function detectEcosystems(directory) {
119981
120631
  ecosystems.push("dotnet");
119982
120632
  }
119983
120633
  } catch {}
119984
- if (fs111.existsSync(path150.join(cwd, "Gemfile")) || fs111.existsSync(path150.join(cwd, "Gemfile.lock"))) {
120634
+ if (fs111.existsSync(path151.join(cwd, "Gemfile")) || fs111.existsSync(path151.join(cwd, "Gemfile.lock"))) {
119985
120635
  ecosystems.push("ruby");
119986
120636
  }
119987
- if (fs111.existsSync(path150.join(cwd, "pubspec.yaml"))) {
120637
+ if (fs111.existsSync(path151.join(cwd, "pubspec.yaml"))) {
119988
120638
  ecosystems.push("dart");
119989
120639
  }
119990
- if (fs111.existsSync(path150.join(cwd, "composer.lock"))) {
120640
+ if (fs111.existsSync(path151.join(cwd, "composer.lock"))) {
119991
120641
  ecosystems.push("composer");
119992
120642
  }
119993
120643
  return ecosystems;
@@ -120000,7 +120650,7 @@ async function runNpmAudit(directory) {
120000
120650
  stderr: "pipe",
120001
120651
  cwd: directory
120002
120652
  });
120003
- const timeoutPromise = new Promise((resolve51) => setTimeout(() => resolve51("timeout"), AUDIT_TIMEOUT_MS));
120653
+ const timeoutPromise = new Promise((resolve52) => setTimeout(() => resolve52("timeout"), AUDIT_TIMEOUT_MS));
120004
120654
  const result = await Promise.race([
120005
120655
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
120006
120656
  timeoutPromise
@@ -120120,7 +120770,7 @@ async function runPipAudit(directory) {
120120
120770
  stderr: "pipe",
120121
120771
  cwd: directory
120122
120772
  });
120123
- const timeoutPromise = new Promise((resolve51) => setTimeout(() => resolve51("timeout"), AUDIT_TIMEOUT_MS));
120773
+ const timeoutPromise = new Promise((resolve52) => setTimeout(() => resolve52("timeout"), AUDIT_TIMEOUT_MS));
120124
120774
  const result = await Promise.race([
120125
120775
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
120126
120776
  timeoutPromise
@@ -120248,7 +120898,7 @@ async function runCargoAudit(directory) {
120248
120898
  stderr: "pipe",
120249
120899
  cwd: directory
120250
120900
  });
120251
- const timeoutPromise = new Promise((resolve51) => setTimeout(() => resolve51("timeout"), AUDIT_TIMEOUT_MS));
120901
+ const timeoutPromise = new Promise((resolve52) => setTimeout(() => resolve52("timeout"), AUDIT_TIMEOUT_MS));
120252
120902
  const result = await Promise.race([
120253
120903
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
120254
120904
  timeoutPromise
@@ -120372,7 +121022,7 @@ async function runGoAudit(directory) {
120372
121022
  stderr: "pipe",
120373
121023
  cwd: directory
120374
121024
  });
120375
- const timeoutPromise = new Promise((resolve51) => setTimeout(() => resolve51("timeout"), AUDIT_TIMEOUT_MS));
121025
+ const timeoutPromise = new Promise((resolve52) => setTimeout(() => resolve52("timeout"), AUDIT_TIMEOUT_MS));
120376
121026
  const result = await Promise.race([
120377
121027
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
120378
121028
  timeoutPromise
@@ -120505,7 +121155,7 @@ async function runDotnetAudit(directory) {
120505
121155
  stderr: "pipe",
120506
121156
  cwd: directory
120507
121157
  });
120508
- const timeoutPromise = new Promise((resolve51) => setTimeout(() => resolve51("timeout"), AUDIT_TIMEOUT_MS));
121158
+ const timeoutPromise = new Promise((resolve52) => setTimeout(() => resolve52("timeout"), AUDIT_TIMEOUT_MS));
120509
121159
  const result = await Promise.race([
120510
121160
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
120511
121161
  timeoutPromise
@@ -120621,7 +121271,7 @@ async function runBundleAudit(directory) {
120621
121271
  stderr: "pipe",
120622
121272
  cwd: directory
120623
121273
  });
120624
- const timeoutPromise = new Promise((resolve51) => setTimeout(() => resolve51("timeout"), AUDIT_TIMEOUT_MS));
121274
+ const timeoutPromise = new Promise((resolve52) => setTimeout(() => resolve52("timeout"), AUDIT_TIMEOUT_MS));
120625
121275
  const result = await Promise.race([
120626
121276
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
120627
121277
  timeoutPromise
@@ -120766,7 +121416,7 @@ async function runDartAudit(directory) {
120766
121416
  stderr: "pipe",
120767
121417
  cwd: directory
120768
121418
  });
120769
- const timeoutPromise = new Promise((resolve51) => setTimeout(() => resolve51("timeout"), AUDIT_TIMEOUT_MS));
121419
+ const timeoutPromise = new Promise((resolve52) => setTimeout(() => resolve52("timeout"), AUDIT_TIMEOUT_MS));
120770
121420
  const result = await Promise.race([
120771
121421
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
120772
121422
  timeoutPromise
@@ -120881,7 +121531,7 @@ async function runComposerAudit(directory) {
120881
121531
  stderr: "pipe",
120882
121532
  cwd: directory
120883
121533
  });
120884
- const timeoutPromise = new Promise((resolve51) => setTimeout(() => resolve51("timeout"), AUDIT_TIMEOUT_MS));
121534
+ const timeoutPromise = new Promise((resolve52) => setTimeout(() => resolve52("timeout"), AUDIT_TIMEOUT_MS));
120885
121535
  const result = await Promise.race([
120886
121536
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
120887
121537
  timeoutPromise
@@ -121124,7 +121774,7 @@ var pkg_audit = createSwarmTool({
121124
121774
  init_zod();
121125
121775
  init_manager2();
121126
121776
  import * as fs112 from "node:fs";
121127
- import * as path151 from "node:path";
121777
+ import * as path152 from "node:path";
121128
121778
  init_utils();
121129
121779
  init_create_tool();
121130
121780
  var MAX_FILE_SIZE = 1024 * 1024;
@@ -121247,7 +121897,7 @@ function isScaffoldFile(filePath) {
121247
121897
  if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
121248
121898
  return true;
121249
121899
  }
121250
- const filename = path151.basename(filePath);
121900
+ const filename = path152.basename(filePath);
121251
121901
  if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
121252
121902
  return true;
121253
121903
  }
@@ -121264,7 +121914,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
121264
121914
  if (regex.test(normalizedPath)) {
121265
121915
  return true;
121266
121916
  }
121267
- const filename = path151.basename(filePath);
121917
+ const filename = path152.basename(filePath);
121268
121918
  const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
121269
121919
  if (filenameRegex.test(filename)) {
121270
121920
  return true;
@@ -121273,7 +121923,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
121273
121923
  return false;
121274
121924
  }
121275
121925
  function isParserSupported(filePath) {
121276
- const ext = path151.extname(filePath).toLowerCase();
121926
+ const ext = path152.extname(filePath).toLowerCase();
121277
121927
  return SUPPORTED_PARSER_EXTENSIONS.has(ext);
121278
121928
  }
121279
121929
  function isPlanFile(filePath) {
@@ -121520,9 +122170,9 @@ async function placeholderScan(input, directory) {
121520
122170
  let filesScanned = 0;
121521
122171
  const filesWithFindings = new Set;
121522
122172
  for (const filePath of changed_files) {
121523
- const fullPath = path151.isAbsolute(filePath) ? filePath : path151.resolve(directory, filePath);
121524
- const resolvedDirectory = path151.resolve(directory);
121525
- if (!fullPath.startsWith(resolvedDirectory + path151.sep) && fullPath !== resolvedDirectory) {
122173
+ const fullPath = path152.isAbsolute(filePath) ? filePath : path152.resolve(directory, filePath);
122174
+ const resolvedDirectory = path152.resolve(directory);
122175
+ if (!fullPath.startsWith(resolvedDirectory + path152.sep) && fullPath !== resolvedDirectory) {
121526
122176
  continue;
121527
122177
  }
121528
122178
  if (!fs112.existsSync(fullPath)) {
@@ -121531,7 +122181,7 @@ async function placeholderScan(input, directory) {
121531
122181
  if (isAllowedByGlobs(filePath, allow_globs)) {
121532
122182
  continue;
121533
122183
  }
121534
- const relativeFilePath = path151.relative(directory, fullPath).replace(/\\/g, "/");
122184
+ const relativeFilePath = path152.relative(directory, fullPath).replace(/\\/g, "/");
121535
122185
  if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
121536
122186
  continue;
121537
122187
  }
@@ -121604,7 +122254,7 @@ var placeholder_scan = createSwarmTool({
121604
122254
 
121605
122255
  // src/tools/pre-check-batch.ts
121606
122256
  import * as fs116 from "node:fs";
121607
- import * as path155 from "node:path";
122257
+ import * as path156 from "node:path";
121608
122258
  init_zod();
121609
122259
  init_manager2();
121610
122260
  init_utils();
@@ -121732,11 +122382,11 @@ var quality_budget = createSwarmTool({
121732
122382
  }).optional().describe("Quality budget thresholds")
121733
122383
  },
121734
122384
  async execute(args2, directory) {
121735
- const result = await _internals68.qualityBudget(args2, directory);
122385
+ const result = await _internals70.qualityBudget(args2, directory);
121736
122386
  return JSON.stringify(result);
121737
122387
  }
121738
122388
  });
121739
- var _internals68 = {
122389
+ var _internals70 = {
121740
122390
  qualityBudget
121741
122391
  };
121742
122392
 
@@ -121745,7 +122395,7 @@ init_zod();
121745
122395
  init_manager2();
121746
122396
  init_detector();
121747
122397
  import * as fs115 from "node:fs";
121748
- import * as path154 from "node:path";
122398
+ import * as path155 from "node:path";
121749
122399
  import { extname as extname22 } from "node:path";
121750
122400
 
121751
122401
  // src/sast/rules/c.ts
@@ -122455,13 +123105,13 @@ function executeRulesSync(filePath, content, language) {
122455
123105
  // src/sast/semgrep.ts
122456
123106
  import * as child_process10 from "node:child_process";
122457
123107
  import * as fs113 from "node:fs";
122458
- import * as path152 from "node:path";
123108
+ import * as path153 from "node:path";
122459
123109
  var semgrepAvailableCache = null;
122460
123110
  var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
122461
123111
  var DEFAULT_TIMEOUT_MS3 = 30000;
122462
123112
  var MAX_OUTPUT_BYTES7 = 10 * 1024 * 1024;
122463
123113
  var KILL_GRACE_MS = 2000;
122464
- var _internals69 = {
123114
+ var _internals71 = {
122465
123115
  isSemgrepAvailable,
122466
123116
  checkSemgrepAvailable,
122467
123117
  resetSemgrepCache,
@@ -122487,7 +123137,7 @@ function isSemgrepAvailable() {
122487
123137
  }
122488
123138
  }
122489
123139
  async function checkSemgrepAvailable() {
122490
- return _internals69.isSemgrepAvailable();
123140
+ return _internals71.isSemgrepAvailable();
122491
123141
  }
122492
123142
  function resetSemgrepCache() {
122493
123143
  semgrepAvailableCache = null;
@@ -122540,7 +123190,7 @@ function mapSemgrepSeverity(severity) {
122540
123190
  }
122541
123191
  async function executeWithTimeout(command, args2, options) {
122542
123192
  const maxOutputBytes = options.maxOutputBytes ?? MAX_OUTPUT_BYTES7;
122543
- return new Promise((resolve53) => {
123193
+ return new Promise((resolve54) => {
122544
123194
  const child = child_process10.spawn(command, args2, {
122545
123195
  shell: false,
122546
123196
  cwd: options.cwd,
@@ -122572,7 +123222,7 @@ async function executeWithTimeout(command, args2, options) {
122572
123222
  escalation.unref();
122573
123223
  }
122574
123224
  }
122575
- resolve53({ ...result, truncated });
123225
+ resolve54({ ...result, truncated });
122576
123226
  };
122577
123227
  timeout = setTimeout(() => {
122578
123228
  settle({
@@ -122631,12 +123281,12 @@ async function runSemgrep(options) {
122631
123281
  const timeoutMs = options.timeoutMs || DEFAULT_TIMEOUT_MS3;
122632
123282
  if (files.length === 0) {
122633
123283
  return {
122634
- available: _internals69.isSemgrepAvailable(),
123284
+ available: _internals71.isSemgrepAvailable(),
122635
123285
  findings: [],
122636
123286
  engine: "tier_a"
122637
123287
  };
122638
123288
  }
122639
- if (!_internals69.isSemgrepAvailable()) {
123289
+ if (!_internals71.isSemgrepAvailable()) {
122640
123290
  return {
122641
123291
  available: false,
122642
123292
  findings: [],
@@ -122700,7 +123350,7 @@ async function runSemgrep(options) {
122700
123350
  }
122701
123351
  function getRulesDirectory(projectRoot) {
122702
123352
  if (projectRoot) {
122703
- return path152.resolve(projectRoot, DEFAULT_RULES_DIR);
123353
+ return path153.resolve(projectRoot, DEFAULT_RULES_DIR);
122704
123354
  }
122705
123355
  return DEFAULT_RULES_DIR;
122706
123356
  }
@@ -122721,24 +123371,24 @@ init_create_tool();
122721
123371
  init_utils2();
122722
123372
  import * as crypto12 from "node:crypto";
122723
123373
  import * as fs114 from "node:fs";
122724
- import * as path153 from "node:path";
123374
+ import * as path154 from "node:path";
122725
123375
  var BASELINE_SCHEMA_VERSION = "1.0.0";
122726
123376
  var MAX_BASELINE_FINDINGS = 2000;
122727
123377
  var MAX_BASELINE_BYTES = 2 * 1048576;
122728
123378
  var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
122729
123379
  function normalizeFindingPath(directory, file3) {
122730
- const resolved = path153.isAbsolute(file3) ? file3 : path153.resolve(directory, file3);
122731
- const rel = path153.relative(path153.resolve(directory), resolved);
123380
+ const resolved = path154.isAbsolute(file3) ? file3 : path154.resolve(directory, file3);
123381
+ const rel = path154.relative(path154.resolve(directory), resolved);
122732
123382
  return rel.replace(/\\/g, "/");
122733
123383
  }
122734
123384
  function baselineRelPath(phase) {
122735
- return path153.join("evidence", String(phase), "sast-baseline.json");
123385
+ return path154.join("evidence", String(phase), "sast-baseline.json");
122736
123386
  }
122737
123387
  function tempRelPath(phase) {
122738
- return path153.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
123388
+ return path154.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
122739
123389
  }
122740
123390
  function lockRelPath(phase) {
122741
- return path153.join("evidence", String(phase), "sast-baseline.json.lock");
123391
+ return path154.join("evidence", String(phase), "sast-baseline.json.lock");
122742
123392
  }
122743
123393
  function getLine(lines, idx) {
122744
123394
  if (idx < 0 || idx >= lines.length)
@@ -122803,7 +123453,7 @@ function assignOccurrenceIndices(findings, directory) {
122803
123453
  }
122804
123454
  const occIdx = countMap.get(baseKey) ?? 0;
122805
123455
  countMap.set(baseKey, occIdx + 1);
122806
- const fp = _internals70.fingerprintFinding(finding, directory, occIdx);
123456
+ const fp = _internals72.fingerprintFinding(finding, directory, occIdx);
122807
123457
  return {
122808
123458
  finding,
122809
123459
  index: occIdx,
@@ -122824,7 +123474,7 @@ async function acquireLock2(lockPath) {
122824
123474
  };
122825
123475
  } catch {
122826
123476
  if (attempt < LOCK_RETRY_DELAYS_MS.length) {
122827
- await new Promise((resolve54) => setTimeout(resolve54, LOCK_RETRY_DELAYS_MS[attempt]));
123477
+ await new Promise((resolve55) => setTimeout(resolve55, LOCK_RETRY_DELAYS_MS[attempt]));
122828
123478
  }
122829
123479
  }
122830
123480
  }
@@ -122859,8 +123509,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
122859
123509
  message: e instanceof Error ? e.message : "Path validation failed"
122860
123510
  };
122861
123511
  }
122862
- fs114.mkdirSync(path153.dirname(baselinePath), { recursive: true });
122863
- fs114.mkdirSync(path153.dirname(tempPath), { recursive: true });
123512
+ fs114.mkdirSync(path154.dirname(baselinePath), { recursive: true });
123513
+ fs114.mkdirSync(path154.dirname(tempPath), { recursive: true });
122864
123514
  const releaseLock = await acquireLock2(lockPath);
122865
123515
  try {
122866
123516
  let existing = null;
@@ -122872,7 +123522,7 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
122872
123522
  }
122873
123523
  } catch {}
122874
123524
  const scannedRelFiles = new Set(scannedFiles.map((f) => normalizeFindingPath(directory, f)));
122875
- const indexed = _internals70.assignOccurrenceIndices(findings, directory);
123525
+ const indexed = _internals72.assignOccurrenceIndices(findings, directory);
122876
123526
  if (existing && !opts?.force) {
122877
123527
  const prunedFingerprints = existing.fingerprints.filter((fp) => {
122878
123528
  const relFile = fp.slice(0, fp.indexOf("|"));
@@ -123012,7 +123662,7 @@ function loadBaseline(directory, phase) {
123012
123662
  };
123013
123663
  }
123014
123664
  }
123015
- var _internals70 = {
123665
+ var _internals72 = {
123016
123666
  fingerprintFinding,
123017
123667
  assignOccurrenceIndices,
123018
123668
  captureOrMergeBaseline,
@@ -123133,9 +123783,9 @@ async function sastScan(input, directory, config3) {
123133
123783
  _filesSkipped++;
123134
123784
  continue;
123135
123785
  }
123136
- const resolvedPath = path154.isAbsolute(filePath) ? filePath : path154.resolve(directory, filePath);
123137
- const resolvedDirectory = path154.resolve(directory);
123138
- if (!resolvedPath.startsWith(resolvedDirectory + path154.sep) && resolvedPath !== resolvedDirectory) {
123786
+ const resolvedPath = path155.isAbsolute(filePath) ? filePath : path155.resolve(directory, filePath);
123787
+ const resolvedDirectory = path155.resolve(directory);
123788
+ if (!resolvedPath.startsWith(resolvedDirectory + path155.sep) && resolvedPath !== resolvedDirectory) {
123139
123789
  _filesSkipped++;
123140
123790
  continue;
123141
123791
  }
@@ -123422,11 +124072,11 @@ var sast_scan = createSwarmTool({
123422
124072
  capture_baseline: safeArgs.capture_baseline,
123423
124073
  phase: safeArgs.phase
123424
124074
  };
123425
- const result = await _internals71.sastScan(input, directory);
124075
+ const result = await _internals73.sastScan(input, directory);
123426
124076
  return JSON.stringify(result, null, 2);
123427
124077
  }
123428
124078
  });
123429
- var _internals71 = {
124079
+ var _internals73 = {
123430
124080
  sastScan,
123431
124081
  sast_scan
123432
124082
  };
@@ -123450,18 +124100,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
123450
124100
  let resolved;
123451
124101
  const isWinAbs = isWindowsAbsolutePath(inputPath);
123452
124102
  if (isWinAbs) {
123453
- resolved = path155.win32.resolve(inputPath);
123454
- } else if (path155.isAbsolute(inputPath)) {
123455
- resolved = path155.resolve(inputPath);
124103
+ resolved = path156.win32.resolve(inputPath);
124104
+ } else if (path156.isAbsolute(inputPath)) {
124105
+ resolved = path156.resolve(inputPath);
123456
124106
  } else {
123457
- resolved = path155.resolve(baseDir, inputPath);
124107
+ resolved = path156.resolve(baseDir, inputPath);
123458
124108
  }
123459
- const workspaceResolved = path155.resolve(workspaceDir);
124109
+ const workspaceResolved = path156.resolve(workspaceDir);
123460
124110
  let relative31;
123461
124111
  if (isWinAbs) {
123462
- relative31 = path155.win32.relative(workspaceResolved, resolved);
124112
+ relative31 = path156.win32.relative(workspaceResolved, resolved);
123463
124113
  } else {
123464
- relative31 = path155.relative(workspaceResolved, resolved);
124114
+ relative31 = path156.relative(workspaceResolved, resolved);
123465
124115
  }
123466
124116
  if (relative31.startsWith("..")) {
123467
124117
  return "path traversal detected";
@@ -123526,7 +124176,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
123526
124176
  if (typeof file3 !== "string") {
123527
124177
  continue;
123528
124178
  }
123529
- const resolvedPath = path155.resolve(file3);
124179
+ const resolvedPath = path156.resolve(file3);
123530
124180
  const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
123531
124181
  if (validationError) {
123532
124182
  continue;
@@ -123683,7 +124333,7 @@ async function runSecretscanWithFiles(files, directory) {
123683
124333
  skippedFiles++;
123684
124334
  continue;
123685
124335
  }
123686
- const resolvedPath = path155.resolve(file3);
124336
+ const resolvedPath = path156.resolve(file3);
123687
124337
  const validationError = validatePath(resolvedPath, directory, directory);
123688
124338
  if (validationError) {
123689
124339
  skippedFiles++;
@@ -123701,7 +124351,7 @@ async function runSecretscanWithFiles(files, directory) {
123701
124351
  };
123702
124352
  }
123703
124353
  for (const file3 of validatedFiles) {
123704
- const ext = path155.extname(file3).toLowerCase();
124354
+ const ext = path156.extname(file3).toLowerCase();
123705
124355
  if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
123706
124356
  skippedFiles++;
123707
124357
  continue;
@@ -123920,7 +124570,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
123920
124570
  const preexistingFindings = [];
123921
124571
  for (const finding of findings) {
123922
124572
  const filePath = finding.location.file;
123923
- const normalised = path155.relative(directory, filePath).replace(/\\/g, "/");
124573
+ const normalised = path156.relative(directory, filePath).replace(/\\/g, "/");
123924
124574
  const changedLines = changedLineRanges.get(normalised);
123925
124575
  if (changedLines?.has(finding.location.line)) {
123926
124576
  newFindings.push(finding);
@@ -123971,7 +124621,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
123971
124621
  warn(`pre_check_batch: Invalid file path: ${file3}`);
123972
124622
  continue;
123973
124623
  }
123974
- changedFiles.push(path155.resolve(directory, file3));
124624
+ changedFiles.push(path156.resolve(directory, file3));
123975
124625
  }
123976
124626
  if (changedFiles.length === 0) {
123977
124627
  warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
@@ -124172,9 +124822,9 @@ var pre_check_batch = createSwarmTool({
124172
124822
  };
124173
124823
  return JSON.stringify(errorResult, null, 2);
124174
124824
  }
124175
- const resolvedDirectory = path155.resolve(typedArgs.directory);
124176
- const workspaceAnchor = path155.resolve(directory);
124177
- if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor + path155.sep)) {
124825
+ const resolvedDirectory = path156.resolve(typedArgs.directory);
124826
+ const workspaceAnchor = path156.resolve(directory);
124827
+ if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor + path156.sep)) {
124178
124828
  const subDirError = `directory "${typedArgs.directory}" is a subdirectory of the project root — pre_check_batch requires the project root directory "${workspaceAnchor}"`;
124179
124829
  const subDirResult = {
124180
124830
  gates_passed: false,
@@ -124226,7 +124876,7 @@ var pre_check_batch = createSwarmTool({
124226
124876
 
124227
124877
  // src/tools/repo-map.ts
124228
124878
  init_zod();
124229
- import * as path156 from "node:path";
124879
+ import * as path157 from "node:path";
124230
124880
  init_path_security();
124231
124881
  init_create_tool();
124232
124882
  var VALID_ACTIONS = [
@@ -124251,7 +124901,7 @@ function validateFile(p) {
124251
124901
  return "file contains control characters";
124252
124902
  if (containsPathTraversal(p))
124253
124903
  return "file contains path traversal";
124254
- if (path156.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
124904
+ if (path157.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
124255
124905
  return "file must be a workspace-relative path, not absolute";
124256
124906
  }
124257
124907
  return null;
@@ -124274,8 +124924,8 @@ function ok(action, payload) {
124274
124924
  }
124275
124925
  function toRelativeGraphPath(input, workspaceRoot) {
124276
124926
  const normalized = input.replace(/\\/g, "/");
124277
- if (path156.isAbsolute(normalized)) {
124278
- const rel = path156.relative(workspaceRoot, normalized).replace(/\\/g, "/");
124927
+ if (path157.isAbsolute(normalized)) {
124928
+ const rel = path157.relative(workspaceRoot, normalized).replace(/\\/g, "/");
124279
124929
  return normalizeGraphPath2(rel);
124280
124930
  }
124281
124931
  return normalizeGraphPath2(normalized);
@@ -124421,7 +125071,7 @@ var repo_map = createSwarmTool({
124421
125071
  init_zod();
124422
125072
  init_create_tool();
124423
125073
  import * as fs117 from "node:fs";
124424
- import * as path157 from "node:path";
125074
+ import * as path158 from "node:path";
124425
125075
  var SPEC_FILE = ".swarm/spec.md";
124426
125076
  var EVIDENCE_DIR4 = ".swarm/evidence";
124427
125077
  var OBLIGATION_KEYWORDS2 = ["MUST", "SHOULD", "SHALL"];
@@ -124490,7 +125140,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
124490
125140
  return [];
124491
125141
  }
124492
125142
  for (const entry of entries) {
124493
- const entryPath = path157.join(evidenceDir, entry);
125143
+ const entryPath = path158.join(evidenceDir, entry);
124494
125144
  try {
124495
125145
  const stat9 = fs117.statSync(entryPath);
124496
125146
  if (!stat9.isDirectory()) {
@@ -124506,11 +125156,11 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
124506
125156
  if (entryPhase !== String(phase)) {
124507
125157
  continue;
124508
125158
  }
124509
- const evidenceFilePath = path157.join(entryPath, "evidence.json");
125159
+ const evidenceFilePath = path158.join(entryPath, "evidence.json");
124510
125160
  try {
124511
- const resolvedPath = path157.resolve(evidenceFilePath);
124512
- const evidenceDirResolved = path157.resolve(evidenceDir);
124513
- if (!resolvedPath.startsWith(evidenceDirResolved + path157.sep)) {
125161
+ const resolvedPath = path158.resolve(evidenceFilePath);
125162
+ const evidenceDirResolved = path158.resolve(evidenceDir);
125163
+ if (!resolvedPath.startsWith(evidenceDirResolved + path158.sep)) {
124514
125164
  continue;
124515
125165
  }
124516
125166
  const stat9 = fs117.lstatSync(evidenceFilePath);
@@ -124544,7 +125194,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
124544
125194
  if (Array.isArray(diffEntry.files_changed)) {
124545
125195
  for (const file3 of diffEntry.files_changed) {
124546
125196
  if (typeof file3 === "string") {
124547
- touchedFiles.add(path157.resolve(cwd, file3));
125197
+ touchedFiles.add(path158.resolve(cwd, file3));
124548
125198
  }
124549
125199
  }
124550
125200
  }
@@ -124557,8 +125207,8 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
124557
125207
  }
124558
125208
  function searchFileForKeywords(filePath, keywords, cwd) {
124559
125209
  try {
124560
- const resolvedPath = path157.resolve(filePath);
124561
- const cwdResolved = path157.resolve(cwd);
125210
+ const resolvedPath = path158.resolve(filePath);
125211
+ const cwdResolved = path158.resolve(cwd);
124562
125212
  if (!resolvedPath.startsWith(cwdResolved)) {
124563
125213
  return false;
124564
125214
  }
@@ -124692,7 +125342,7 @@ var req_coverage = createSwarmTool({
124692
125342
  }, null, 2);
124693
125343
  }
124694
125344
  const cwd = inputDirectory || directory;
124695
- const specPath = path157.join(cwd, SPEC_FILE);
125345
+ const specPath = path158.join(cwd, SPEC_FILE);
124696
125346
  let specContent;
124697
125347
  try {
124698
125348
  specContent = fs117.readFileSync(specPath, "utf-8");
@@ -124719,7 +125369,7 @@ var req_coverage = createSwarmTool({
124719
125369
  message: "No FR requirements found in spec.md"
124720
125370
  }, null, 2);
124721
125371
  }
124722
- const evidenceDir = path157.join(cwd, EVIDENCE_DIR4);
125372
+ const evidenceDir = path158.join(cwd, EVIDENCE_DIR4);
124723
125373
  const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
124724
125374
  const analyzedRequirements = [];
124725
125375
  let coveredCount = 0;
@@ -124745,7 +125395,7 @@ var req_coverage = createSwarmTool({
124745
125395
  requirements: analyzedRequirements
124746
125396
  };
124747
125397
  const reportFilename = `req-coverage-phase-${phase}.json`;
124748
- const reportPath = path157.join(evidenceDir, reportFilename);
125398
+ const reportPath = path158.join(evidenceDir, reportFilename);
124749
125399
  try {
124750
125400
  if (!fs117.existsSync(evidenceDir)) {
124751
125401
  fs117.mkdirSync(evidenceDir, { recursive: true });
@@ -124835,7 +125485,7 @@ init_qa_gate_profile();
124835
125485
  init_file_locks();
124836
125486
  import * as crypto13 from "node:crypto";
124837
125487
  import * as fs118 from "node:fs";
124838
- import * as path158 from "node:path";
125488
+ import * as path159 from "node:path";
124839
125489
  init_ledger();
124840
125490
  init_manager();
124841
125491
  init_state();
@@ -124916,8 +125566,8 @@ async function executeSavePlan(args2, fallbackDir) {
124916
125566
  };
124917
125567
  }
124918
125568
  if (args2.working_directory && fallbackDir) {
124919
- const resolvedTarget = path158.resolve(args2.working_directory);
124920
- const resolvedRoot = path158.resolve(fallbackDir);
125569
+ const resolvedTarget = path159.resolve(args2.working_directory);
125570
+ const resolvedRoot = path159.resolve(fallbackDir);
124921
125571
  let fallbackExists = false;
124922
125572
  try {
124923
125573
  fs118.accessSync(resolvedRoot, fs118.constants.F_OK);
@@ -124926,7 +125576,7 @@ async function executeSavePlan(args2, fallbackDir) {
124926
125576
  fallbackExists = false;
124927
125577
  }
124928
125578
  if (fallbackExists) {
124929
- const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path158.sep);
125579
+ const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path159.sep);
124930
125580
  if (isSubdirectory) {
124931
125581
  return {
124932
125582
  success: false,
@@ -124942,7 +125592,7 @@ async function executeSavePlan(args2, fallbackDir) {
124942
125592
  let specMtime;
124943
125593
  let specHash;
124944
125594
  if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
124945
- const specPath = path158.join(targetWorkspace, ".swarm", "spec.md");
125595
+ const specPath = path159.join(targetWorkspace, ".swarm", "spec.md");
124946
125596
  try {
124947
125597
  const stat9 = await fs118.promises.stat(specPath);
124948
125598
  specMtime = stat9.mtime.toISOString();
@@ -124958,7 +125608,7 @@ async function executeSavePlan(args2, fallbackDir) {
124958
125608
  }
124959
125609
  }
124960
125610
  if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
124961
- const contextPath = path158.join(targetWorkspace, ".swarm", "context.md");
125611
+ const contextPath = path159.join(targetWorkspace, ".swarm", "context.md");
124962
125612
  let contextContent = "";
124963
125613
  try {
124964
125614
  contextContent = await fs118.promises.readFile(contextPath, "utf8");
@@ -125248,7 +125898,7 @@ async function executeSavePlan(args2, fallbackDir) {
125248
125898
  }
125249
125899
  await writeCheckpoint(dir).catch(() => {});
125250
125900
  try {
125251
- const markerPath = path158.join(dir, ".swarm", ".plan-write-marker");
125901
+ const markerPath = path159.join(dir, ".swarm", ".plan-write-marker");
125252
125902
  const marker = JSON.stringify({
125253
125903
  source: "save_plan",
125254
125904
  timestamp: new Date().toISOString(),
@@ -125271,7 +125921,7 @@ async function executeSavePlan(args2, fallbackDir) {
125271
125921
  return {
125272
125922
  success: true,
125273
125923
  message: "Plan saved successfully",
125274
- plan_path: path158.join(dir, ".swarm", "plan.json"),
125924
+ plan_path: path159.join(dir, ".swarm", "plan.json"),
125275
125925
  phases_count: plan.phases.length,
125276
125926
  tasks_count: tasksCount,
125277
125927
  ...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
@@ -125338,7 +125988,7 @@ var save_plan = createSwarmTool({
125338
125988
  init_zod();
125339
125989
  init_manager2();
125340
125990
  import * as fs119 from "node:fs";
125341
- import * as path159 from "node:path";
125991
+ import * as path160 from "node:path";
125342
125992
 
125343
125993
  // src/sbom/detectors/index.ts
125344
125994
  init_utils();
@@ -126188,7 +126838,7 @@ function findManifestFiles(rootDir) {
126188
126838
  try {
126189
126839
  const entries = fs119.readdirSync(dir, { withFileTypes: true });
126190
126840
  for (const entry of entries) {
126191
- const fullPath = path159.join(dir, entry.name);
126841
+ const fullPath = path160.join(dir, entry.name);
126192
126842
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
126193
126843
  continue;
126194
126844
  }
@@ -126197,7 +126847,7 @@ function findManifestFiles(rootDir) {
126197
126847
  } else if (entry.isFile()) {
126198
126848
  for (const pattern of patterns) {
126199
126849
  if (simpleGlobToRegex(pattern).test(entry.name)) {
126200
- manifestFiles.push(path159.relative(rootDir, fullPath));
126850
+ manifestFiles.push(path160.relative(rootDir, fullPath));
126201
126851
  break;
126202
126852
  }
126203
126853
  }
@@ -126215,11 +126865,11 @@ function findManifestFilesInDirs(directories, workingDir) {
126215
126865
  try {
126216
126866
  const entries = fs119.readdirSync(dir, { withFileTypes: true });
126217
126867
  for (const entry of entries) {
126218
- const fullPath = path159.join(dir, entry.name);
126868
+ const fullPath = path160.join(dir, entry.name);
126219
126869
  if (entry.isFile()) {
126220
126870
  for (const pattern of patterns) {
126221
126871
  if (simpleGlobToRegex(pattern).test(entry.name)) {
126222
- found.push(path159.relative(workingDir, fullPath));
126872
+ found.push(path160.relative(workingDir, fullPath));
126223
126873
  break;
126224
126874
  }
126225
126875
  }
@@ -126232,11 +126882,11 @@ function findManifestFilesInDirs(directories, workingDir) {
126232
126882
  function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
126233
126883
  const dirs = new Set;
126234
126884
  for (const file3 of changedFiles) {
126235
- let currentDir = path159.dirname(file3);
126885
+ let currentDir = path160.dirname(file3);
126236
126886
  while (true) {
126237
- if (currentDir && currentDir !== "." && currentDir !== path159.sep) {
126238
- dirs.add(path159.join(workingDir, currentDir));
126239
- const parent = path159.dirname(currentDir);
126887
+ if (currentDir && currentDir !== "." && currentDir !== path160.sep) {
126888
+ dirs.add(path160.join(workingDir, currentDir));
126889
+ const parent = path160.dirname(currentDir);
126240
126890
  if (parent === currentDir)
126241
126891
  break;
126242
126892
  currentDir = parent;
@@ -126320,7 +126970,7 @@ var sbom_generate = createSwarmTool({
126320
126970
  const changedFiles = obj.changed_files;
126321
126971
  const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
126322
126972
  const workingDir = directory;
126323
- const outputDir = path159.isAbsolute(relativeOutputDir) ? relativeOutputDir : path159.join(workingDir, relativeOutputDir);
126973
+ const outputDir = path160.isAbsolute(relativeOutputDir) ? relativeOutputDir : path160.join(workingDir, relativeOutputDir);
126324
126974
  let manifestFiles = [];
126325
126975
  if (scope === "all") {
126326
126976
  manifestFiles = findManifestFiles(workingDir);
@@ -126343,7 +126993,7 @@ var sbom_generate = createSwarmTool({
126343
126993
  const processedFiles = [];
126344
126994
  for (const manifestFile of manifestFiles) {
126345
126995
  try {
126346
- const fullPath = path159.isAbsolute(manifestFile) ? manifestFile : path159.join(workingDir, manifestFile);
126996
+ const fullPath = path160.isAbsolute(manifestFile) ? manifestFile : path160.join(workingDir, manifestFile);
126347
126997
  if (!fs119.existsSync(fullPath)) {
126348
126998
  continue;
126349
126999
  }
@@ -126360,7 +127010,7 @@ var sbom_generate = createSwarmTool({
126360
127010
  const bom = generateCycloneDX(allComponents);
126361
127011
  const bomJson = serializeCycloneDX(bom);
126362
127012
  const filename = generateSbomFilename();
126363
- const outputPath = path159.join(outputDir, filename);
127013
+ const outputPath = path160.join(outputDir, filename);
126364
127014
  fs119.writeFileSync(outputPath, bomJson, "utf-8");
126365
127015
  const verdict = processedFiles.length > 0 ? "pass" : "pass";
126366
127016
  try {
@@ -126405,7 +127055,7 @@ var sbom_generate = createSwarmTool({
126405
127055
  init_zod();
126406
127056
  init_create_tool();
126407
127057
  import * as fs120 from "node:fs";
126408
- import * as path160 from "node:path";
127058
+ import * as path161 from "node:path";
126409
127059
  var SPEC_CANDIDATES = [
126410
127060
  "openapi.json",
126411
127061
  "openapi.yaml",
@@ -126437,12 +127087,12 @@ function normalizePath5(p) {
126437
127087
  }
126438
127088
  function discoverSpecFile(cwd, specFileArg) {
126439
127089
  if (specFileArg) {
126440
- const resolvedPath = path160.resolve(cwd, specFileArg);
126441
- const normalizedCwd = cwd.endsWith(path160.sep) ? cwd : cwd + path160.sep;
127090
+ const resolvedPath = path161.resolve(cwd, specFileArg);
127091
+ const normalizedCwd = cwd.endsWith(path161.sep) ? cwd : cwd + path161.sep;
126442
127092
  if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
126443
127093
  throw new Error("Invalid spec_file: path traversal detected");
126444
127094
  }
126445
- const ext = path160.extname(resolvedPath).toLowerCase();
127095
+ const ext = path161.extname(resolvedPath).toLowerCase();
126446
127096
  if (!ALLOWED_EXTENSIONS.includes(ext)) {
126447
127097
  throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
126448
127098
  }
@@ -126456,7 +127106,7 @@ function discoverSpecFile(cwd, specFileArg) {
126456
127106
  return resolvedPath;
126457
127107
  }
126458
127108
  for (const candidate of SPEC_CANDIDATES) {
126459
- const candidatePath = path160.resolve(cwd, candidate);
127109
+ const candidatePath = path161.resolve(cwd, candidate);
126460
127110
  if (fs120.existsSync(candidatePath)) {
126461
127111
  const stats = fs120.statSync(candidatePath);
126462
127112
  if (stats.size <= MAX_SPEC_SIZE) {
@@ -126468,7 +127118,7 @@ function discoverSpecFile(cwd, specFileArg) {
126468
127118
  }
126469
127119
  function parseSpec(specFile) {
126470
127120
  const content = fs120.readFileSync(specFile, "utf-8");
126471
- const ext = path160.extname(specFile).toLowerCase();
127121
+ const ext = path161.extname(specFile).toLowerCase();
126472
127122
  if (ext === ".json") {
126473
127123
  return parseJsonSpec(content);
126474
127124
  }
@@ -126544,7 +127194,7 @@ function extractRoutes(cwd) {
126544
127194
  return;
126545
127195
  }
126546
127196
  for (const entry of entries) {
126547
- const fullPath = path160.join(dir, entry.name);
127197
+ const fullPath = path161.join(dir, entry.name);
126548
127198
  if (entry.isSymbolicLink()) {
126549
127199
  continue;
126550
127200
  }
@@ -126554,7 +127204,7 @@ function extractRoutes(cwd) {
126554
127204
  }
126555
127205
  walkDir2(fullPath);
126556
127206
  } else if (entry.isFile()) {
126557
- const ext = path160.extname(entry.name).toLowerCase();
127207
+ const ext = path161.extname(entry.name).toLowerCase();
126558
127208
  const baseName = entry.name.toLowerCase();
126559
127209
  if (![".ts", ".js", ".mjs"].includes(ext)) {
126560
127210
  continue;
@@ -126723,7 +127373,7 @@ init_bun_compat();
126723
127373
  init_path_security();
126724
127374
  init_create_tool();
126725
127375
  import * as fs121 from "node:fs";
126726
- import * as path161 from "node:path";
127376
+ import * as path162 from "node:path";
126727
127377
  var DEFAULT_MAX_RESULTS = 100;
126728
127378
  var DEFAULT_MAX_LINES = 200;
126729
127379
  var REGEX_TIMEOUT_MS = 5000;
@@ -126759,11 +127409,11 @@ function containsWindowsAttacks4(str) {
126759
127409
  }
126760
127410
  function isPathInWorkspace3(filePath, workspace) {
126761
127411
  try {
126762
- const resolvedPath = path161.resolve(workspace, filePath);
127412
+ const resolvedPath = path162.resolve(workspace, filePath);
126763
127413
  const realWorkspace = fs121.realpathSync(workspace);
126764
127414
  const realResolvedPath = fs121.realpathSync(resolvedPath);
126765
- const relativePath = path161.relative(realWorkspace, realResolvedPath);
126766
- if (relativePath.startsWith("..") || path161.isAbsolute(relativePath)) {
127415
+ const relativePath = path162.relative(realWorkspace, realResolvedPath);
127416
+ if (relativePath.startsWith("..") || path162.isAbsolute(relativePath)) {
126767
127417
  return false;
126768
127418
  }
126769
127419
  return true;
@@ -126776,11 +127426,11 @@ function validatePathForRead2(filePath, workspace) {
126776
127426
  }
126777
127427
  function findRgInEnvPath() {
126778
127428
  const searchPath = process.env.PATH ?? "";
126779
- for (const dir of searchPath.split(path161.delimiter)) {
127429
+ for (const dir of searchPath.split(path162.delimiter)) {
126780
127430
  if (!dir)
126781
127431
  continue;
126782
127432
  const isWindows = process.platform === "win32";
126783
- const candidate = path161.join(dir, isWindows ? "rg.exe" : "rg");
127433
+ const candidate = path162.join(dir, isWindows ? "rg.exe" : "rg");
126784
127434
  if (fs121.existsSync(candidate))
126785
127435
  return candidate;
126786
127436
  }
@@ -126835,7 +127485,7 @@ async function ripgrepSearch(opts) {
126835
127485
  stderr: "pipe",
126836
127486
  cwd: opts.workspace
126837
127487
  });
126838
- const timeout = new Promise((resolve60) => setTimeout(() => resolve60("timeout"), REGEX_TIMEOUT_MS));
127488
+ const timeout = new Promise((resolve61) => setTimeout(() => resolve61("timeout"), REGEX_TIMEOUT_MS));
126839
127489
  const exitPromise = proc.exited;
126840
127490
  const result = await Promise.race([exitPromise, timeout]);
126841
127491
  if (result === "timeout") {
@@ -126910,8 +127560,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
126910
127560
  try {
126911
127561
  const entries = fs121.readdirSync(dir, { withFileTypes: true });
126912
127562
  for (const entry of entries) {
126913
- const fullPath = path161.join(dir, entry.name);
126914
- const relativePath = path161.relative(workspace, fullPath);
127563
+ const fullPath = path162.join(dir, entry.name);
127564
+ const relativePath = path162.relative(workspace, fullPath);
126915
127565
  if (!validatePathForRead2(fullPath, workspace)) {
126916
127566
  continue;
126917
127567
  }
@@ -126952,7 +127602,7 @@ async function fallbackSearch(opts) {
126952
127602
  const matches = [];
126953
127603
  let total = 0;
126954
127604
  for (const file3 of files) {
126955
- const fullPath = path161.join(opts.workspace, file3);
127605
+ const fullPath = path162.join(opts.workspace, file3);
126956
127606
  if (!validatePathForRead2(fullPath, opts.workspace)) {
126957
127607
  continue;
126958
127608
  }
@@ -127365,7 +128015,7 @@ init_config();
127365
128015
  init_schema();
127366
128016
  init_create_tool();
127367
128017
  import { mkdir as mkdir23, rename as rename10, writeFile as writeFile16 } from "node:fs/promises";
127368
- import * as path162 from "node:path";
128018
+ import * as path163 from "node:path";
127369
128019
  var MAX_SPEC_BYTES = 256 * 1024;
127370
128020
  var spec_write = createSwarmTool({
127371
128021
  description: "Write the canonical project spec to .swarm/spec.md. Atomic write, size-bounded (256 KiB), heading-required. Honors spec_writer.allow_spec_write.",
@@ -127406,8 +128056,8 @@ var spec_write = createSwarmTool({
127406
128056
  reason: 'spec must contain at least one top-level "# Heading"'
127407
128057
  }, null, 2);
127408
128058
  }
127409
- const target = path162.join(directory, ".swarm", "spec.md");
127410
- await mkdir23(path162.dirname(target), { recursive: true });
128059
+ const target = path163.join(directory, ".swarm", "spec.md");
128060
+ await mkdir23(path163.dirname(target), { recursive: true });
127411
128061
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
127412
128062
  let finalContent = content;
127413
128063
  if (mode === "append") {
@@ -127443,7 +128093,7 @@ import {
127443
128093
  unlinkSync as unlinkSync21,
127444
128094
  writeFileSync as writeFileSync32
127445
128095
  } from "node:fs";
127446
- import path163 from "node:path";
128096
+ import path164 from "node:path";
127447
128097
  init_create_tool();
127448
128098
  init_resolve_working_directory();
127449
128099
  var VerdictSchema2 = exports_external.object({
@@ -127587,7 +128237,7 @@ var submit_phase_council_verdicts = createSwarmTool({
127587
128237
  }
127588
128238
  });
127589
128239
  function getPhaseMutationGapFinding(phaseNumber, workingDir) {
127590
- const mutationGatePath = path163.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
128240
+ const mutationGatePath = path164.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
127591
128241
  try {
127592
128242
  const raw = readFileSync81(mutationGatePath, "utf-8");
127593
128243
  const parsed = JSON.parse(raw);
@@ -127649,9 +128299,9 @@ function getPhaseMutationGapFinding(phaseNumber, workingDir) {
127649
128299
  }
127650
128300
  }
127651
128301
  function writePhaseCouncilEvidence(workingDir, synthesis) {
127652
- const evidenceDir = path163.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
128302
+ const evidenceDir = path164.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
127653
128303
  mkdirSync41(evidenceDir, { recursive: true });
127654
- const evidenceFile = path163.join(evidenceDir, "phase-council.json");
128304
+ const evidenceFile = path164.join(evidenceDir, "phase-council.json");
127655
128305
  const evidenceBundle = {
127656
128306
  entries: [
127657
128307
  {
@@ -127713,7 +128363,7 @@ init_zod();
127713
128363
  init_path_security();
127714
128364
  init_create_tool();
127715
128365
  import * as fs122 from "node:fs";
127716
- import * as path164 from "node:path";
128366
+ import * as path165 from "node:path";
127717
128367
  var BINARY_EXTENSIONS2 = new Set([
127718
128368
  ".png",
127719
128369
  ".jpg",
@@ -127749,14 +128399,14 @@ function containsWindowsAttacks5(str) {
127749
128399
  }
127750
128400
  function isPathInWorkspace4(filePath, workspace) {
127751
128401
  try {
127752
- const resolvedPath = path164.resolve(workspace, filePath);
128402
+ const resolvedPath = path165.resolve(workspace, filePath);
127753
128403
  if (!fs122.existsSync(resolvedPath)) {
127754
128404
  return true;
127755
128405
  }
127756
128406
  const realWorkspace = fs122.realpathSync(workspace);
127757
128407
  const realResolvedPath = fs122.realpathSync(resolvedPath);
127758
- const relativePath = path164.relative(realWorkspace, realResolvedPath);
127759
- if (relativePath.startsWith("..") || path164.isAbsolute(relativePath)) {
128408
+ const relativePath = path165.relative(realWorkspace, realResolvedPath);
128409
+ if (relativePath.startsWith("..") || path165.isAbsolute(relativePath)) {
127760
128410
  return false;
127761
128411
  }
127762
128412
  return true;
@@ -127871,7 +128521,7 @@ function arraysEqual2(a, b) {
127871
128521
  return true;
127872
128522
  }
127873
128523
  function isBinaryFile4(filePath) {
127874
- const ext = path164.extname(filePath).toLowerCase();
128524
+ const ext = path165.extname(filePath).toLowerCase();
127875
128525
  return BINARY_EXTENSIONS2.has(ext);
127876
128526
  }
127877
128527
  function splitDiffLines(content) {
@@ -128076,7 +128726,7 @@ var suggestPatch = createSwarmTool({
128076
128726
  });
128077
128727
  continue;
128078
128728
  }
128079
- const fullPath = path164.resolve(directory, change.file);
128729
+ const fullPath = path165.resolve(directory, change.file);
128080
128730
  if (!fs122.existsSync(fullPath)) {
128081
128731
  errors5.push({
128082
128732
  success: false,
@@ -128171,7 +128821,7 @@ var suggestPatch = createSwarmTool({
128171
128821
  const unifiedParts = [];
128172
128822
  for (const [file3, entries] of fileGroups) {
128173
128823
  entries.sort((a, b) => a.contextMatch.startLineIndex - b.contextMatch.startLineIndex);
128174
- const entryFullPath = path164.resolve(directory, file3);
128824
+ const entryFullPath = path165.resolve(directory, file3);
128175
128825
  let entryContent;
128176
128826
  try {
128177
128827
  entryContent = fs122.readFileSync(entryFullPath, "utf-8");
@@ -128372,7 +129022,7 @@ var swarm_memory_propose = createSwarmTool({
128372
129022
  evidenceRefs: exports_external.array(exports_external.string().min(1).max(500)).max(20).optional().describe("Evidence refs such as files, commits, test outputs, or URLs")
128373
129023
  },
128374
129024
  execute: async (args2, directory, ctx) => {
128375
- const { config: config3 } = _internals72.loadPluginConfigWithMeta(directory);
129025
+ const { config: config3 } = _internals74.loadPluginConfigWithMeta(directory);
128376
129026
  if (config3.memory?.enabled !== true) {
128377
129027
  return JSON.stringify({
128378
129028
  success: false,
@@ -128388,7 +129038,7 @@ var swarm_memory_propose = createSwarmTool({
128388
129038
  });
128389
129039
  }
128390
129040
  const agent = getContextAgent2(ctx);
128391
- const gateway = _internals72.createMemoryGateway({
129041
+ const gateway = _internals74.createMemoryGateway({
128392
129042
  directory,
128393
129043
  sessionID: ctx?.sessionID,
128394
129044
  agentRole: agent,
@@ -128413,7 +129063,7 @@ var swarm_memory_propose = createSwarmTool({
128413
129063
  }
128414
129064
  }
128415
129065
  });
128416
- var _internals72 = {
129066
+ var _internals74 = {
128417
129067
  loadPluginConfigWithMeta,
128418
129068
  createMemoryGateway
128419
129069
  };
@@ -128451,7 +129101,7 @@ var swarm_memory_recall = createSwarmTool({
128451
129101
  maxItems: exports_external.number().int().min(1).max(20).optional().describe("Maximum memories to return")
128452
129102
  },
128453
129103
  execute: async (args2, directory, ctx) => {
128454
- const { config: config3 } = _internals73.loadPluginConfigWithMeta(directory);
129104
+ const { config: config3 } = _internals75.loadPluginConfigWithMeta(directory);
128455
129105
  if (config3.memory?.enabled !== true) {
128456
129106
  return JSON.stringify({
128457
129107
  success: false,
@@ -128467,7 +129117,7 @@ var swarm_memory_recall = createSwarmTool({
128467
129117
  });
128468
129118
  }
128469
129119
  const agent = getContextAgent3(ctx);
128470
- const gateway = _internals73.createMemoryGateway({
129120
+ const gateway = _internals75.createMemoryGateway({
128471
129121
  directory,
128472
129122
  sessionID: ctx?.sessionID,
128473
129123
  agentRole: agent,
@@ -128500,7 +129150,7 @@ var RecallArgsSchema = exports_external.object({
128500
129150
  kinds: exports_external.array(exports_external.enum(MEMORY_KINDS2)).optional(),
128501
129151
  maxItems: exports_external.number().int().min(1).max(20).optional()
128502
129152
  });
128503
- var _internals73 = {
129153
+ var _internals75 = {
128504
129154
  loadPluginConfigWithMeta,
128505
129155
  createMemoryGateway
128506
129156
  };
@@ -128513,7 +129163,7 @@ function getContextAgent3(ctx) {
128513
129163
 
128514
129164
  // src/tools/syntax-check.ts
128515
129165
  import * as fs123 from "node:fs";
128516
- import * as path165 from "node:path";
129166
+ import * as path166 from "node:path";
128517
129167
  init_zod();
128518
129168
  init_manager2();
128519
129169
  init_detector();
@@ -128585,7 +129235,7 @@ async function syntaxCheck(input, directory, config3) {
128585
129235
  if (languages?.length) {
128586
129236
  const lowerLangs = languages.map((l) => l.toLowerCase());
128587
129237
  filesToCheck = filesToCheck.filter((file3) => {
128588
- const ext = path165.extname(file3.path).toLowerCase();
129238
+ const ext = path166.extname(file3.path).toLowerCase();
128589
129239
  const langDef = getLanguageForExtension(ext);
128590
129240
  const fileProfile = getProfileForFile(file3.path);
128591
129241
  const langId = fileProfile?.id || langDef?.id;
@@ -128595,7 +129245,7 @@ async function syntaxCheck(input, directory, config3) {
128595
129245
  const { loadGrammar: loadGrammar2 } = await Promise.resolve().then(() => (init_runtime(), exports_runtime));
128596
129246
  async function checkOneFile(fileInfo) {
128597
129247
  const { path: filePath } = fileInfo;
128598
- const fullPath = path165.isAbsolute(filePath) ? filePath : path165.join(directory, filePath);
129248
+ const fullPath = path166.isAbsolute(filePath) ? filePath : path166.join(directory, filePath);
128599
129249
  const result = {
128600
129250
  path: filePath,
128601
129251
  language: "",
@@ -128642,7 +129292,7 @@ async function syntaxCheck(input, directory, config3) {
128642
129292
  result.skipped_reason = "binary_file";
128643
129293
  return { result, counted: false, failed: false, skipped: true };
128644
129294
  }
128645
- const ext = path165.extname(filePath).toLowerCase();
129295
+ const ext = path166.extname(filePath).toLowerCase();
128646
129296
  const langDef = getLanguageForExtension(ext);
128647
129297
  result.language = profile?.id || langDef?.id || "unknown";
128648
129298
  const errors5 = extractSyntaxErrors(parser, content);
@@ -128754,7 +129404,7 @@ init_utils();
128754
129404
  init_create_tool();
128755
129405
  init_path_security();
128756
129406
  import * as fs124 from "node:fs";
128757
- import * as path166 from "node:path";
129407
+ import * as path167 from "node:path";
128758
129408
  var MAX_TEXT_LENGTH = 200;
128759
129409
  var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
128760
129410
  var SUPPORTED_EXTENSIONS4 = new Set([
@@ -128820,9 +129470,9 @@ function validatePathsInput(paths, cwd) {
128820
129470
  return { error: "paths contains path traversal", resolvedPath: null };
128821
129471
  }
128822
129472
  try {
128823
- const resolvedPath = path166.resolve(paths);
128824
- const normalizedCwd = path166.resolve(cwd);
128825
- const normalizedResolved = path166.resolve(resolvedPath);
129473
+ const resolvedPath = path167.resolve(paths);
129474
+ const normalizedCwd = path167.resolve(cwd);
129475
+ const normalizedResolved = path167.resolve(resolvedPath);
128826
129476
  if (!normalizedResolved.startsWith(normalizedCwd)) {
128827
129477
  return {
128828
129478
  error: "paths must be within the current working directory",
@@ -128838,7 +129488,7 @@ function validatePathsInput(paths, cwd) {
128838
129488
  }
128839
129489
  }
128840
129490
  function isSupportedExtension(filePath) {
128841
- const ext = path166.extname(filePath).toLowerCase();
129491
+ const ext = path167.extname(filePath).toLowerCase();
128842
129492
  return SUPPORTED_EXTENSIONS4.has(ext);
128843
129493
  }
128844
129494
  function findSourceFiles4(dir, files = []) {
@@ -128853,7 +129503,7 @@ function findSourceFiles4(dir, files = []) {
128853
129503
  if (SKIP_DIRECTORIES6.has(entry)) {
128854
129504
  continue;
128855
129505
  }
128856
- const fullPath = path166.join(dir, entry);
129506
+ const fullPath = path167.join(dir, entry);
128857
129507
  let stat9;
128858
129508
  try {
128859
129509
  stat9 = fs124.statSync(fullPath);
@@ -128965,7 +129615,7 @@ var todo_extract = createSwarmTool({
128965
129615
  filesToScan.push(scanPath);
128966
129616
  } else {
128967
129617
  const errorResult = {
128968
- error: `unsupported file extension: ${path166.extname(scanPath)}`,
129618
+ error: `unsupported file extension: ${path167.extname(scanPath)}`,
128969
129619
  total: 0,
128970
129620
  byPriority: { high: 0, medium: 0, low: 0 },
128971
129621
  entries: []
@@ -129015,18 +129665,18 @@ init_schema();
129015
129665
  init_qa_gate_profile();
129016
129666
  init_gate_evidence();
129017
129667
  import * as fs128 from "node:fs";
129018
- import * as path170 from "node:path";
129668
+ import * as path171 from "node:path";
129019
129669
 
129020
129670
  // src/hooks/diff-scope.ts
129021
129671
  init_bun_compat();
129022
129672
  import * as fs126 from "node:fs";
129023
- import * as path168 from "node:path";
129673
+ import * as path169 from "node:path";
129024
129674
 
129025
129675
  // src/utils/gitignore-warning.ts
129026
129676
  init_bun_compat();
129027
129677
  import * as fs125 from "node:fs";
129028
- import * as path167 from "node:path";
129029
- var _internals74 = { bunSpawn };
129678
+ import * as path168 from "node:path";
129679
+ var _internals76 = { bunSpawn };
129030
129680
  var _swarmGitExcludedChecked = false;
129031
129681
  function fileCoversSwarm(content) {
129032
129682
  for (const rawLine of content.split(`
@@ -129059,7 +129709,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
129059
129709
  checkIgnoreExitCode
129060
129710
  ] = await Promise.all([
129061
129711
  (async () => {
129062
- const proc = _internals74.bunSpawn(["git", "-C", directory, "rev-parse", "--show-toplevel"], GIT_SPAWN_OPTIONS);
129712
+ const proc = _internals76.bunSpawn(["git", "-C", directory, "rev-parse", "--show-toplevel"], GIT_SPAWN_OPTIONS);
129063
129713
  try {
129064
129714
  return await Promise.all([proc.exited, proc.stdout.text()]);
129065
129715
  } finally {
@@ -129069,7 +129719,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
129069
129719
  }
129070
129720
  })(),
129071
129721
  (async () => {
129072
- const proc = _internals74.bunSpawn(["git", "-C", directory, "rev-parse", "--git-path", "info/exclude"], GIT_SPAWN_OPTIONS);
129722
+ const proc = _internals76.bunSpawn(["git", "-C", directory, "rev-parse", "--git-path", "info/exclude"], GIT_SPAWN_OPTIONS);
129073
129723
  try {
129074
129724
  return await Promise.all([proc.exited, proc.stdout.text()]);
129075
129725
  } finally {
@@ -129079,7 +129729,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
129079
129729
  }
129080
129730
  })(),
129081
129731
  (async () => {
129082
- const proc = _internals74.bunSpawn(["git", "-C", directory, "check-ignore", "-q", ".swarm/.gitkeep"], GIT_SPAWN_OPTIONS);
129732
+ const proc = _internals76.bunSpawn(["git", "-C", directory, "check-ignore", "-q", ".swarm/.gitkeep"], GIT_SPAWN_OPTIONS);
129083
129733
  try {
129084
129734
  return await proc.exited;
129085
129735
  } finally {
@@ -129099,10 +129749,10 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
129099
129749
  const excludeRelPath = excludePathRaw.trim();
129100
129750
  if (!excludeRelPath)
129101
129751
  return;
129102
- const excludePath = path167.isAbsolute(excludeRelPath) ? excludeRelPath : path167.join(directory, excludeRelPath);
129752
+ const excludePath = path168.isAbsolute(excludeRelPath) ? excludeRelPath : path168.join(directory, excludeRelPath);
129103
129753
  if (checkIgnoreExitCode !== 0) {
129104
129754
  try {
129105
- fs125.mkdirSync(path167.dirname(excludePath), { recursive: true });
129755
+ fs125.mkdirSync(path168.dirname(excludePath), { recursive: true });
129106
129756
  let existing = "";
129107
129757
  try {
129108
129758
  existing = fs125.readFileSync(excludePath, "utf8");
@@ -129118,7 +129768,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
129118
129768
  }
129119
129769
  } catch {}
129120
129770
  }
129121
- const trackedProc = _internals74.bunSpawn(["git", "-C", directory, "ls-files", "--", ".swarm"], GIT_SPAWN_OPTIONS);
129771
+ const trackedProc = _internals76.bunSpawn(["git", "-C", directory, "ls-files", "--", ".swarm"], GIT_SPAWN_OPTIONS);
129122
129772
  let trackedExitCode;
129123
129773
  let trackedOutput;
129124
129774
  try {
@@ -129143,10 +129793,10 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
129143
129793
  }
129144
129794
 
129145
129795
  // src/hooks/diff-scope.ts
129146
- var _internals75 = { bunSpawn };
129796
+ var _internals77 = { bunSpawn };
129147
129797
  function getDeclaredScope(taskId, directory) {
129148
129798
  try {
129149
- const planPath = path168.join(directory, ".swarm", "plan.json");
129799
+ const planPath = path169.join(directory, ".swarm", "plan.json");
129150
129800
  if (!fs126.existsSync(planPath))
129151
129801
  return null;
129152
129802
  const raw = fs126.readFileSync(planPath, "utf-8");
@@ -129178,7 +129828,7 @@ var GIT_DIFF_SPAWN_OPTIONS = {
129178
129828
  };
129179
129829
  async function getChangedFiles(directory) {
129180
129830
  try {
129181
- const proc = _internals75.bunSpawn(["git", "diff", "--name-only", "HEAD~1"], {
129831
+ const proc = _internals77.bunSpawn(["git", "diff", "--name-only", "HEAD~1"], {
129182
129832
  cwd: directory,
129183
129833
  ...GIT_DIFF_SPAWN_OPTIONS
129184
129834
  });
@@ -129195,7 +129845,7 @@ async function getChangedFiles(directory) {
129195
129845
  return stdout.trim().split(`
129196
129846
  `).map((f) => f.trim()).filter((f) => f.length > 0);
129197
129847
  }
129198
- const proc2 = _internals75.bunSpawn(["git", "diff", "--name-only", "HEAD"], {
129848
+ const proc2 = _internals77.bunSpawn(["git", "diff", "--name-only", "HEAD"], {
129199
129849
  cwd: directory,
129200
129850
  ...GIT_DIFF_SPAWN_OPTIONS
129201
129851
  });
@@ -129252,8 +129902,8 @@ init_telemetry();
129252
129902
  // src/turbo/lean/task-completion.ts
129253
129903
  init_file_locks();
129254
129904
  import * as fs127 from "node:fs";
129255
- import * as path169 from "node:path";
129256
- var _internals76 = {
129905
+ import * as path170 from "node:path";
129906
+ var _internals78 = {
129257
129907
  listActiveLocks,
129258
129908
  verifyLeanTurboTaskCompletion
129259
129909
  };
@@ -129271,7 +129921,7 @@ var TIER_3_PATTERNS = [
129271
129921
  ];
129272
129922
  function matchesTier3Pattern(files) {
129273
129923
  for (const file3 of files) {
129274
- const fileName = path169.basename(file3);
129924
+ const fileName = path170.basename(file3);
129275
129925
  for (const pattern of TIER_3_PATTERNS) {
129276
129926
  if (pattern.test(fileName)) {
129277
129927
  return true;
@@ -129283,7 +129933,7 @@ function matchesTier3Pattern(files) {
129283
129933
  function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
129284
129934
  let persisted = null;
129285
129935
  try {
129286
- const statePath = path169.join(directory, ".swarm", "turbo-state.json");
129936
+ const statePath = path170.join(directory, ".swarm", "turbo-state.json");
129287
129937
  if (!fs127.existsSync(statePath)) {
129288
129938
  return {
129289
129939
  ok: false,
@@ -129367,11 +130017,11 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
129367
130017
  };
129368
130018
  }
129369
130019
  const phase = runState.phase ?? 0;
129370
- const evidencePath = path169.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
129371
- const expectedDir = path169.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
129372
- const resolvedPath = path169.resolve(evidencePath);
129373
- const resolvedDir = path169.resolve(expectedDir);
129374
- if (!resolvedPath.startsWith(resolvedDir + path169.sep) && resolvedPath !== resolvedDir) {
130020
+ const evidencePath = path170.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
130021
+ const expectedDir = path170.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
130022
+ const resolvedPath = path170.resolve(evidencePath);
130023
+ const resolvedDir = path170.resolve(expectedDir);
130024
+ if (!resolvedPath.startsWith(resolvedDir + path170.sep) && resolvedPath !== resolvedDir) {
129375
130025
  return {
129376
130026
  ok: false,
129377
130027
  reason: `Lane ID causes path traversal: ${lane.laneId}`,
@@ -129395,7 +130045,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
129395
130045
  }
129396
130046
  };
129397
130047
  }
129398
- const activeLocks = _internals76.listActiveLocks(directory);
130048
+ const activeLocks = _internals78.listActiveLocks(directory);
129399
130049
  const laneLocks = activeLocks.filter((lock) => lock.laneId === lane.laneId);
129400
130050
  if (laneLocks.length > 0) {
129401
130051
  return {
@@ -129411,7 +130061,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
129411
130061
  }
129412
130062
  let filesTouched = [];
129413
130063
  try {
129414
- const planPath = path169.join(directory, ".swarm", "plan.json");
130064
+ const planPath = path170.join(directory, ".swarm", "plan.json");
129415
130065
  const planRaw = fs127.readFileSync(planPath, "utf-8");
129416
130066
  const plan = JSON.parse(planRaw);
129417
130067
  for (const planPhase of plan.phases ?? []) {
@@ -129495,7 +130145,7 @@ var TIER_3_PATTERNS2 = [
129495
130145
  ];
129496
130146
  function matchesTier3Pattern2(files) {
129497
130147
  for (const file3 of files) {
129498
- const fileName = path170.basename(file3);
130148
+ const fileName = path171.basename(file3);
129499
130149
  for (const pattern of TIER_3_PATTERNS2) {
129500
130150
  if (pattern.test(fileName)) {
129501
130151
  return true;
@@ -129534,7 +130184,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
129534
130184
  if (!skipStandardTurboBypass && hasActiveTurboMode()) {
129535
130185
  const resolvedDir2 = workingDirectory;
129536
130186
  try {
129537
- const planPath = path170.join(resolvedDir2, ".swarm", "plan.json");
130187
+ const planPath = path171.join(resolvedDir2, ".swarm", "plan.json");
129538
130188
  const planRaw = fs128.readFileSync(planPath, "utf-8");
129539
130189
  const plan = JSON.parse(planRaw);
129540
130190
  for (const planPhase of plan.phases ?? []) {
@@ -129612,7 +130262,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
129612
130262
  }
129613
130263
  if (resolvedDir) {
129614
130264
  try {
129615
- const planPath = path170.join(resolvedDir, ".swarm", "plan.json");
130265
+ const planPath = path171.join(resolvedDir, ".swarm", "plan.json");
129616
130266
  const planRaw = fs128.readFileSync(planPath, "utf-8");
129617
130267
  const plan = JSON.parse(planRaw);
129618
130268
  for (const planPhase of plan.phases ?? []) {
@@ -129854,7 +130504,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
129854
130504
  };
129855
130505
  }
129856
130506
  directory = resolveResult.directory;
129857
- const planPath = path170.join(directory, ".swarm", "plan.json");
130507
+ const planPath = path171.join(directory, ".swarm", "plan.json");
129858
130508
  if (!fs128.existsSync(planPath)) {
129859
130509
  return {
129860
130510
  success: false,
@@ -129863,9 +130513,9 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
129863
130513
  };
129864
130514
  }
129865
130515
  if (fallbackDir && directory !== fallbackDir) {
129866
- const canonicalDir = fs128.realpathSync(path170.resolve(directory));
129867
- const canonicalRoot = fs128.realpathSync(path170.resolve(fallbackDir));
129868
- if (canonicalDir.startsWith(canonicalRoot + path170.sep)) {
130516
+ const canonicalDir = fs128.realpathSync(path171.resolve(directory));
130517
+ const canonicalRoot = fs128.realpathSync(path171.resolve(fallbackDir));
130518
+ if (canonicalDir.startsWith(canonicalRoot + path171.sep)) {
129869
130519
  return {
129870
130520
  success: false,
129871
130521
  message: `Invalid working_directory: "${directory}" is a subdirectory of ` + `the project root "${fallbackDir}". Pass the project root path or ` + `omit working_directory entirely.`,
@@ -129877,8 +130527,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
129877
130527
  }
129878
130528
  if (args2.status === "in_progress") {
129879
130529
  try {
129880
- const evidencePath = path170.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
129881
- fs128.mkdirSync(path170.dirname(evidencePath), { recursive: true });
130530
+ const evidencePath = path171.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
130531
+ fs128.mkdirSync(path171.dirname(evidencePath), { recursive: true });
129882
130532
  const fd = fs128.openSync(evidencePath, "wx");
129883
130533
  let writeOk = false;
129884
130534
  try {
@@ -129902,7 +130552,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
129902
130552
  recoverTaskStateFromDelegations(args2.task_id, directory);
129903
130553
  let phaseRequiresReviewer = true;
129904
130554
  try {
129905
- const planPath2 = path170.join(directory, ".swarm", "plan.json");
130555
+ const planPath2 = path171.join(directory, ".swarm", "plan.json");
129906
130556
  const planRaw = fs128.readFileSync(planPath2, "utf-8");
129907
130557
  const plan = JSON.parse(planRaw);
129908
130558
  const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
@@ -130199,7 +130849,7 @@ init_utils2();
130199
130849
  init_redaction();
130200
130850
  import { createHash as createHash13 } from "node:crypto";
130201
130851
  import { appendFile as appendFile14, mkdir as mkdir24 } from "node:fs/promises";
130202
- import * as path171 from "node:path";
130852
+ import * as path172 from "node:path";
130203
130853
  var EVIDENCE_CACHE_FILE = "evidence-cache/documents.jsonl";
130204
130854
  var MAX_EVIDENCE_TEXT_LENGTH = 4000;
130205
130855
  async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
@@ -130207,7 +130857,7 @@ async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
130207
130857
  const capturedAt = now().toISOString();
130208
130858
  const records = inputs.map((input) => createEvidenceDocumentRecord(input, capturedAt)).filter((record3) => record3 !== null);
130209
130859
  if (records.length > 0) {
130210
- await mkdir24(path171.dirname(filePath), { recursive: true });
130860
+ await mkdir24(path172.dirname(filePath), { recursive: true });
130211
130861
  await appendFile14(filePath, `${records.map((record3) => JSON.stringify(record3)).join(`
130212
130862
  `)}
130213
130863
  `, "utf-8");
@@ -130373,7 +131023,7 @@ var web_search = createSwarmTool({
130373
131023
  });
130374
131024
  async function captureSearchEvidence(directory, query, results) {
130375
131025
  try {
130376
- const written = await _internals77.writeEvidenceDocuments(directory, results.map((result) => ({
131026
+ const written = await _internals79.writeEvidenceDocuments(directory, results.map((result) => ({
130377
131027
  sourceType: "web_search",
130378
131028
  query,
130379
131029
  title: result.title,
@@ -130401,7 +131051,7 @@ async function captureSearchEvidence(directory, query, results) {
130401
131051
  };
130402
131052
  }
130403
131053
  }
130404
- var _internals77 = {
131054
+ var _internals79 = {
130405
131055
  writeEvidenceDocuments
130406
131056
  };
130407
131057
 
@@ -130415,7 +131065,7 @@ init_schema3();
130415
131065
  init_store();
130416
131066
  init_create_tool();
130417
131067
  init_resolve_working_directory();
130418
- import * as path172 from "node:path";
131068
+ import * as path173 from "node:path";
130419
131069
  var FindingSchema2 = exports_external.object({
130420
131070
  severity: exports_external.enum(["low", "medium", "high", "critical"]),
130421
131071
  category: exports_external.string().min(1),
@@ -130479,7 +131129,7 @@ var write_architecture_supervisor_evidence = createSwarmTool({
130479
131129
  if (config3.architectural_supervision?.persist_knowledge_recommendations && args2.knowledge_recommendations.length > 0) {
130480
131130
  const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
130481
131131
  const lessons = args2.knowledge_recommendations.map((r) => r.lesson);
130482
- const result = await curateAndStoreSwarm(lessons, path172.basename(dirResult.directory), { phase_number: args2.phase }, dirResult.directory, knowledgeConfig, { skipAutoPromotion: true });
131132
+ const result = await curateAndStoreSwarm(lessons, path173.basename(dirResult.directory), { phase_number: args2.phase }, dirResult.directory, knowledgeConfig, { skipAutoPromotion: true });
130483
131133
  knowledgeProposed = result.stored;
130484
131134
  }
130485
131135
  } catch {}
@@ -130515,7 +131165,7 @@ init_ledger();
130515
131165
  init_manager();
130516
131166
  init_create_tool();
130517
131167
  import fs129 from "node:fs";
130518
- import path173 from "node:path";
131168
+ import path174 from "node:path";
130519
131169
  function normalizeVerdict(verdict) {
130520
131170
  switch (verdict) {
130521
131171
  case "APPROVED":
@@ -130563,7 +131213,7 @@ async function executeWriteDriftEvidence(args2, directory) {
130563
131213
  entries: [evidenceEntry]
130564
131214
  };
130565
131215
  const filename = "drift-verifier.json";
130566
- const relativePath = path173.join("evidence", String(phase), filename);
131216
+ const relativePath = path174.join("evidence", String(phase), filename);
130567
131217
  let validatedPath;
130568
131218
  try {
130569
131219
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -130574,10 +131224,10 @@ async function executeWriteDriftEvidence(args2, directory) {
130574
131224
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
130575
131225
  }, null, 2);
130576
131226
  }
130577
- const evidenceDir = path173.dirname(validatedPath);
131227
+ const evidenceDir = path174.dirname(validatedPath);
130578
131228
  try {
130579
131229
  await fs129.promises.mkdir(evidenceDir, { recursive: true });
130580
- const tempPath = path173.join(evidenceDir, `.${filename}.tmp`);
131230
+ const tempPath = path174.join(evidenceDir, `.${filename}.tmp`);
130581
131231
  await fs129.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
130582
131232
  await fs129.promises.rename(tempPath, validatedPath);
130583
131233
  let snapshotInfo;
@@ -130674,7 +131324,7 @@ var write_drift_evidence = createSwarmTool({
130674
131324
  init_zod();
130675
131325
  init_loader();
130676
131326
  import fs130 from "node:fs";
130677
- import path174 from "node:path";
131327
+ import path175 from "node:path";
130678
131328
  init_utils2();
130679
131329
  init_manager();
130680
131330
  init_create_tool();
@@ -130768,7 +131418,7 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
130768
131418
  timestamp: synthesis.timestamp
130769
131419
  };
130770
131420
  const filename = "final-council.json";
130771
- const relativePath = path174.join("evidence", filename);
131421
+ const relativePath = path175.join("evidence", filename);
130772
131422
  let validatedPath;
130773
131423
  try {
130774
131424
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -130782,10 +131432,10 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
130782
131432
  const evidenceContent = {
130783
131433
  entries: [evidenceEntry]
130784
131434
  };
130785
- const evidenceDir = path174.dirname(validatedPath);
131435
+ const evidenceDir = path175.dirname(validatedPath);
130786
131436
  try {
130787
131437
  await fs130.promises.mkdir(evidenceDir, { recursive: true });
130788
- const tempPath = path174.join(evidenceDir, `.${filename}.tmp`);
131438
+ const tempPath = path175.join(evidenceDir, `.${filename}.tmp`);
130789
131439
  await fs130.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
130790
131440
  await fs130.promises.rename(tempPath, validatedPath);
130791
131441
  return JSON.stringify({
@@ -130845,7 +131495,7 @@ init_zod();
130845
131495
  init_utils2();
130846
131496
  init_create_tool();
130847
131497
  import fs131 from "node:fs";
130848
- import path175 from "node:path";
131498
+ import path176 from "node:path";
130849
131499
  function normalizeVerdict2(verdict) {
130850
131500
  switch (verdict) {
130851
131501
  case "APPROVED":
@@ -130893,7 +131543,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
130893
131543
  entries: [evidenceEntry]
130894
131544
  };
130895
131545
  const filename = "hallucination-guard.json";
130896
- const relativePath = path175.join("evidence", String(phase), filename);
131546
+ const relativePath = path176.join("evidence", String(phase), filename);
130897
131547
  let validatedPath;
130898
131548
  try {
130899
131549
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -130904,10 +131554,10 @@ async function executeWriteHallucinationEvidence(args2, directory) {
130904
131554
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
130905
131555
  }, null, 2);
130906
131556
  }
130907
- const evidenceDir = path175.dirname(validatedPath);
131557
+ const evidenceDir = path176.dirname(validatedPath);
130908
131558
  try {
130909
131559
  await fs131.promises.mkdir(evidenceDir, { recursive: true });
130910
- const tempPath = path175.join(evidenceDir, `.${filename}.tmp`);
131560
+ const tempPath = path176.join(evidenceDir, `.${filename}.tmp`);
130911
131561
  await fs131.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
130912
131562
  await fs131.promises.rename(tempPath, validatedPath);
130913
131563
  return JSON.stringify({
@@ -130957,7 +131607,7 @@ init_zod();
130957
131607
  init_utils2();
130958
131608
  init_create_tool();
130959
131609
  import fs132 from "node:fs";
130960
- import path176 from "node:path";
131610
+ import path177 from "node:path";
130961
131611
  function normalizeVerdict3(verdict) {
130962
131612
  switch (verdict) {
130963
131613
  case "PASS":
@@ -131031,7 +131681,7 @@ async function executeWriteMutationEvidence(args2, directory) {
131031
131681
  entries: [evidenceEntry]
131032
131682
  };
131033
131683
  const filename = "mutation-gate.json";
131034
- const relativePath = path176.join("evidence", String(phase), filename);
131684
+ const relativePath = path177.join("evidence", String(phase), filename);
131035
131685
  let validatedPath;
131036
131686
  try {
131037
131687
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -131042,10 +131692,10 @@ async function executeWriteMutationEvidence(args2, directory) {
131042
131692
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
131043
131693
  }, null, 2);
131044
131694
  }
131045
- const evidenceDir = path176.dirname(validatedPath);
131695
+ const evidenceDir = path177.dirname(validatedPath);
131046
131696
  try {
131047
131697
  await fs132.promises.mkdir(evidenceDir, { recursive: true });
131048
- const tempPath = path176.join(evidenceDir, `.${filename}.tmp`);
131698
+ const tempPath = path177.join(evidenceDir, `.${filename}.tmp`);
131049
131699
  await fs132.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
131050
131700
  await fs132.promises.rename(tempPath, validatedPath);
131051
131701
  return JSON.stringify({
@@ -131233,7 +131883,7 @@ ${footerLines.join(`
131233
131883
  init_warning_buffer();
131234
131884
  var _heartbeatTimers = new Map;
131235
131885
  var SWARM_COMMAND_SYSTEM_RULE_TAG = "[opencode-swarm:swarm-command-rule]";
131236
- var PACKAGE_ROOT2 = path178.resolve(path178.dirname(fileURLToPath5(import.meta.url)), "..");
131886
+ var PACKAGE_ROOT2 = path179.resolve(path179.dirname(fileURLToPath5(import.meta.url)), "..");
131237
131887
  function createSwarmCommandSystemRuleHook(agentDefinitions, registeredAgents) {
131238
131888
  return async (input, output) => {
131239
131889
  const { sessionID } = input;
@@ -131503,7 +132153,7 @@ async function initializeOpenCodeSwarm(ctx) {
131503
132153
  const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
131504
132154
  preflightTriggerManager = new PTM(automationConfig);
131505
132155
  const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
131506
- const swarmDir = path178.resolve(ctx.directory, ".swarm");
132156
+ const swarmDir = path179.resolve(ctx.directory, ".swarm");
131507
132157
  statusArtifact = new ASA(swarmDir);
131508
132158
  statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
131509
132159
  if (automationConfig.capabilities?.evidence_auto_summaries === true) {
@@ -132034,7 +132684,7 @@ ${promptRaw}`;
132034
132684
  const meta3 = readSkillMetadata(s.skillPath, ctx.directory);
132035
132685
  let desc = meta3.description || "";
132036
132686
  if (!desc || desc === "No description provided") {
132037
- desc = path178.basename(path178.dirname(s.skillPath));
132687
+ desc = path179.basename(path179.dirname(s.skillPath));
132038
132688
  }
132039
132689
  desc = desc.replace(/,/g, ";");
132040
132690
  return `file:${s.skillPath} (-- ${desc})`;
@@ -132044,7 +132694,7 @@ ${promptRaw}`;
132044
132694
 
132045
132695
  ${promptRaw}`;
132046
132696
  argsRecord.prompt = newPrompt;
132047
- const skillNames = topSkills.map((s) => `${path178.basename(s.skillPath)} (score: ${s.score.toFixed(2)})`).join(", ");
132697
+ const skillNames = topSkills.map((s) => `${path179.basename(s.skillPath)} (score: ${s.score.toFixed(2)})`).join(", ");
132048
132698
  console.warn(`[skill-propagation-gate] Injected skills: ${skillNames}`);
132049
132699
  for (const skill of topSkills) {
132050
132700
  try {