opencode-swarm 6.74.1 → 6.76.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -14063,6 +14063,36 @@ var init_plan_schema = __esm(() => {
14063
14063
  });
14064
14064
  });
14065
14065
 
14066
+ // src/telemetry.ts
14067
+ import * as os from "os";
14068
+ function emit(event, data) {
14069
+ try {
14070
+ if (_disabled || _writeStream === null) {
14071
+ return;
14072
+ }
14073
+ const line = JSON.stringify({
14074
+ timestamp: new Date().toISOString(),
14075
+ event,
14076
+ ...data
14077
+ }) + os.EOL;
14078
+ _writeStream.write(line, (err) => {
14079
+ if (err) {
14080
+ _disabled = true;
14081
+ _writeStream = null;
14082
+ }
14083
+ });
14084
+ for (const listener of _listeners) {
14085
+ try {
14086
+ listener(event, data);
14087
+ } catch {}
14088
+ }
14089
+ } catch {}
14090
+ }
14091
+ var _writeStream = null, _listeners, _disabled = false;
14092
+ var init_telemetry = __esm(() => {
14093
+ _listeners = [];
14094
+ });
14095
+
14066
14096
  // src/utils/spec-hash.ts
14067
14097
  import { createHash } from "crypto";
14068
14098
  import { readFile } from "fs/promises";
@@ -14275,34 +14305,6 @@ async function appendLedgerEvent(directory, eventInput, options) {
14275
14305
  fs.renameSync(tempPath, ledgerPath);
14276
14306
  return event;
14277
14307
  }
14278
- async function appendLedgerEventWithRetry(directory, eventInput, options) {
14279
- const maxRetries = options.maxRetries ?? 3;
14280
- const backoffBase = options.backoffMs ?? 10;
14281
- let currentExpected = options.expectedHash;
14282
- let attempt = 0;
14283
- while (true) {
14284
- try {
14285
- return await appendLedgerEvent(directory, eventInput, {
14286
- expectedHash: currentExpected,
14287
- planHashAfter: options.planHashAfter
14288
- });
14289
- } catch (error49) {
14290
- if (!(error49 instanceof LedgerStaleWriterError) || attempt >= maxRetries) {
14291
- throw error49;
14292
- }
14293
- attempt++;
14294
- const delayMs = backoffBase * 2 ** (attempt - 1);
14295
- await new Promise((resolve2) => setTimeout(resolve2, delayMs));
14296
- if (options.verifyValid) {
14297
- const stillValid = await options.verifyValid();
14298
- if (!stillValid) {
14299
- return null;
14300
- }
14301
- }
14302
- currentExpected = computeCurrentPlanHash(directory);
14303
- }
14304
- }
14305
- }
14306
14308
  async function takeSnapshotEvent(directory, plan, options) {
14307
14309
  const payloadHash = computePlanHash(plan);
14308
14310
  const snapshotPayload = {
@@ -14481,6 +14483,39 @@ import {
14481
14483
  } from "fs";
14482
14484
  import * as fsPromises from "fs/promises";
14483
14485
  import * as path3 from "path";
14486
+ async function retryCasWithBackoff(directory, eventInput, options) {
14487
+ const maxRetries = options.maxRetries ?? CAS_MAX_RETRIES;
14488
+ let currentExpected = options.expectedHash;
14489
+ let attempt = 0;
14490
+ while (true) {
14491
+ try {
14492
+ return await appendLedgerEvent(directory, eventInput, {
14493
+ expectedHash: currentExpected,
14494
+ planHashAfter: options.planHashAfter
14495
+ });
14496
+ } catch (error49) {
14497
+ if (!(error49 instanceof LedgerStaleWriterError) || attempt >= maxRetries) {
14498
+ throw error49;
14499
+ }
14500
+ attempt++;
14501
+ const base = Math.min(CAS_BACKOFF_START_MS * 2 ** (attempt - 1), CAS_BACKOFF_CAP_MS);
14502
+ const jitter = base * CAS_BACKOFF_JITTER * (Math.random() * 2 - 1);
14503
+ const delayMs = Math.max(1, Math.round(base + jitter));
14504
+ emit("plan_ledger_cas_retry", {
14505
+ attempt,
14506
+ expectedHashPrefix: currentExpected.slice(0, 8),
14507
+ delayMs
14508
+ });
14509
+ await new Promise((resolve3) => setTimeout(resolve3, delayMs));
14510
+ if (options.verifyValid) {
14511
+ const stillValid = await options.verifyValid();
14512
+ if (!stillValid)
14513
+ return null;
14514
+ }
14515
+ currentExpected = computeCurrentPlanHash(directory);
14516
+ }
14517
+ }
14518
+ }
14484
14519
  async function loadPlanJsonOnly(directory) {
14485
14520
  const planJsonContent = await readSwarmFileAsync(directory, "plan.json");
14486
14521
  if (planJsonContent !== null) {
@@ -14933,10 +14968,9 @@ async function savePlan(directory, plan, options) {
14933
14968
  };
14934
14969
  const capturedFromStatus = oldTask.status;
14935
14970
  const capturedTaskId = task.id;
14936
- await appendLedgerEventWithRetry(directory, eventInput, {
14971
+ await retryCasWithBackoff(directory, eventInput, {
14937
14972
  expectedHash: currentHash,
14938
14973
  planHashAfter: hashAfter,
14939
- maxRetries: 3,
14940
14974
  verifyValid: async () => {
14941
14975
  const onDisk = await loadPlanJsonOnly(directory);
14942
14976
  if (!onDisk)
@@ -15308,10 +15342,11 @@ function migrateLegacyPlan(planContent, swarmId) {
15308
15342
  };
15309
15343
  return plan;
15310
15344
  }
15311
- var PlanConcurrentModificationError, startupLedgerCheckedWorkspaces, recoveryMutexes;
15345
+ var PlanConcurrentModificationError, startupLedgerCheckedWorkspaces, recoveryMutexes, CAS_BACKOFF_START_MS = 5, CAS_BACKOFF_CAP_MS = 250, CAS_BACKOFF_JITTER = 0.25, CAS_MAX_RETRIES = 3;
15312
15346
  var init_manager = __esm(() => {
15313
15347
  init_plan_schema();
15314
15348
  init_utils2();
15349
+ init_telemetry();
15315
15350
  init_utils();
15316
15351
  init_spec_hash();
15317
15352
  init_ledger();
@@ -15579,378 +15614,79 @@ var init_evidence_schema = __esm(() => {
15579
15614
  });
15580
15615
  });
15581
15616
 
15582
- // src/validation/task-id.ts
15583
- function checkUnsafeChars(taskId) {
15584
- if (!taskId || taskId.length === 0) {
15585
- return "Invalid task ID: empty string";
15586
- }
15587
- if (/\0/.test(taskId)) {
15588
- return "Invalid task ID: contains null bytes";
15589
- }
15590
- for (let i = 0;i < taskId.length; i++) {
15591
- if (taskId.charCodeAt(i) < 32) {
15592
- return "Invalid task ID: contains control characters";
15593
- }
15594
- }
15595
- if (taskId.includes("..") || taskId.includes("/") || taskId.includes("\\")) {
15596
- return "Invalid task ID: path traversal detected";
15597
- }
15598
- return;
15599
- }
15600
- function sanitizeTaskId(taskId) {
15601
- const unsafeMsg = checkUnsafeChars(taskId);
15602
- if (unsafeMsg) {
15603
- throw new Error(unsafeMsg);
15604
- }
15605
- if (STRICT_TASK_ID_PATTERN.test(taskId) || RETRO_TASK_ID_REGEX.test(taskId) || INTERNAL_TOOL_ID_REGEX.test(taskId) || GENERAL_TASK_ID_REGEX.test(taskId)) {
15606
- return taskId;
15607
- }
15608
- throw new Error(`Invalid task ID: must be alphanumeric (ASCII) with optional hyphens, underscores, or dots, got "${taskId}"`);
15609
- }
15610
- var STRICT_TASK_ID_PATTERN, RETRO_TASK_ID_REGEX, INTERNAL_TOOL_ID_REGEX, GENERAL_TASK_ID_REGEX;
15611
- var init_task_id = __esm(() => {
15612
- STRICT_TASK_ID_PATTERN = /^\d+\.\d+(\.\d+)*$/;
15613
- RETRO_TASK_ID_REGEX = /^retro-\d+$/;
15614
- INTERNAL_TOOL_ID_REGEX = /^(?:sast_scan|quality_budget|syntax_check|placeholder_scan|sbom_generate|build|secretscan)$/;
15615
- GENERAL_TASK_ID_REGEX = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
15616
- });
15617
-
15618
- // src/evidence/manager.ts
15619
- import { mkdirSync as mkdirSync2, readdirSync as readdirSync2, rmSync, statSync as statSync2 } from "fs";
15620
- import * as fs3 from "fs/promises";
15621
- import * as path5 from "path";
15622
- function isValidEvidenceType(type) {
15623
- return VALID_EVIDENCE_TYPES.includes(type);
15624
- }
15625
- async function saveEvidence(directory, taskId, evidence) {
15626
- const sanitizedTaskId = sanitizeTaskId2(taskId);
15627
- const relativePath = path5.join("evidence", sanitizedTaskId, "evidence.json");
15628
- const evidencePath = validateSwarmPath(directory, relativePath);
15629
- const evidenceDir = path5.dirname(evidencePath);
15630
- let bundle;
15631
- const existingContent = await readSwarmFileAsync(directory, relativePath);
15632
- if (existingContent !== null) {
15633
- try {
15634
- const parsed = JSON.parse(existingContent);
15635
- bundle = EvidenceBundleSchema.parse(parsed);
15636
- } catch (error49) {
15637
- warn(`Existing evidence bundle invalid for task ${sanitizedTaskId}, creating new: ${error49 instanceof Error ? error49.message : String(error49)}`);
15638
- const now = new Date().toISOString();
15639
- bundle = {
15640
- schema_version: "1.0.0",
15641
- task_id: sanitizedTaskId,
15642
- entries: [],
15643
- created_at: now,
15644
- updated_at: now
15645
- };
15646
- }
15647
- } else {
15648
- const now = new Date().toISOString();
15649
- bundle = {
15650
- schema_version: "1.0.0",
15651
- task_id: sanitizedTaskId,
15652
- entries: [],
15653
- created_at: now,
15654
- updated_at: now
15655
- };
15656
- }
15657
- const MAX_BUNDLE_ENTRIES = 100;
15658
- let entries = [...bundle.entries, evidence];
15659
- if (entries.length > MAX_BUNDLE_ENTRIES) {
15660
- entries = entries.slice(entries.length - MAX_BUNDLE_ENTRIES);
15661
- }
15662
- const updatedBundle = {
15663
- ...bundle,
15664
- entries,
15665
- updated_at: new Date().toISOString()
15617
+ // node_modules/graceful-fs/polyfills.js
15618
+ var require_polyfills = __commonJS((exports, module) => {
15619
+ var constants = __require("constants");
15620
+ var origCwd = process.cwd;
15621
+ var cwd = null;
15622
+ var platform = process.env.GRACEFUL_FS_PLATFORM || process.platform;
15623
+ process.cwd = function() {
15624
+ if (!cwd)
15625
+ cwd = origCwd.call(process);
15626
+ return cwd;
15666
15627
  };
15667
- const bundleJson = JSON.stringify(updatedBundle);
15668
- if (bundleJson.length > EVIDENCE_MAX_JSON_BYTES) {
15669
- throw new Error(`Evidence bundle size (${bundleJson.length} bytes) exceeds maximum (${EVIDENCE_MAX_JSON_BYTES} bytes)`);
15670
- }
15671
- mkdirSync2(evidenceDir, { recursive: true });
15672
- const tempPath = path5.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
15673
15628
  try {
15674
- await Bun.write(tempPath, bundleJson);
15675
- await fs3.rename(tempPath, evidencePath);
15676
- } catch (error49) {
15677
- try {
15678
- rmSync(tempPath, { force: true });
15679
- } catch {}
15680
- throw error49;
15681
- }
15682
- return updatedBundle;
15683
- }
15684
- function isFlatRetrospective(parsed) {
15685
- return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) && parsed.type === "retrospective" && !parsed.schema_version;
15686
- }
15687
- function remapLegacyTaskComplexity(entry) {
15688
- const taskComplexity = entry.task_complexity;
15689
- if (typeof taskComplexity === "string" && taskComplexity in LEGACY_TASK_COMPLEXITY_MAP) {
15690
- return {
15691
- ...entry,
15692
- task_complexity: LEGACY_TASK_COMPLEXITY_MAP[taskComplexity]
15629
+ process.cwd();
15630
+ } catch (er) {}
15631
+ if (typeof process.chdir === "function") {
15632
+ chdir = process.chdir;
15633
+ process.chdir = function(d) {
15634
+ cwd = null;
15635
+ chdir.call(process, d);
15693
15636
  };
15637
+ if (Object.setPrototypeOf)
15638
+ Object.setPrototypeOf(process.chdir, chdir);
15694
15639
  }
15695
- return entry;
15696
- }
15697
- function wrapFlatRetrospective(flatEntry, taskId) {
15698
- const now = new Date().toISOString();
15699
- const remappedEntry = remapLegacyTaskComplexity(flatEntry);
15700
- return {
15701
- schema_version: "1.0.0",
15702
- task_id: remappedEntry.task_id ?? taskId,
15703
- created_at: remappedEntry.timestamp ?? now,
15704
- updated_at: remappedEntry.timestamp ?? now,
15705
- entries: [remappedEntry]
15706
- };
15707
- }
15708
- async function loadEvidence(directory, taskId) {
15709
- const sanitizedTaskId = sanitizeTaskId2(taskId);
15710
- const relativePath = path5.join("evidence", sanitizedTaskId, "evidence.json");
15711
- const evidencePath = validateSwarmPath(directory, relativePath);
15712
- const content = await readSwarmFileAsync(directory, relativePath);
15713
- if (content === null) {
15714
- return { status: "not_found" };
15715
- }
15716
- let parsed;
15717
- try {
15718
- parsed = JSON.parse(content);
15719
- } catch {
15720
- return { status: "invalid_schema", errors: ["Invalid JSON"] };
15721
- }
15722
- if (isFlatRetrospective(parsed)) {
15723
- const wrappedBundle = wrapFlatRetrospective(parsed, sanitizedTaskId);
15724
- try {
15725
- const validated = EvidenceBundleSchema.parse(wrappedBundle);
15726
- const evidenceDir = path5.dirname(evidencePath);
15727
- const bundleJson = JSON.stringify(validated);
15728
- const tempPath = path5.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
15729
- try {
15730
- await Bun.write(tempPath, bundleJson);
15731
- await fs3.rename(tempPath, evidencePath);
15732
- } catch (writeError) {
15733
- try {
15734
- rmSync(tempPath, { force: true });
15735
- } catch {}
15736
- warn(`Failed to persist repaired flat retrospective for task ${sanitizedTaskId}: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
15737
- }
15738
- return { status: "found", bundle: validated };
15739
- } catch (error49) {
15740
- warn(`Wrapped flat retrospective failed validation for task ${sanitizedTaskId}: ${error49 instanceof Error ? error49.message : String(error49)}`);
15741
- const errors3 = error49 instanceof ZodError ? error49.issues.map((e) => `${e.path.join(".")}: ${e.message}`) : [error49 instanceof Error ? error49.message : String(error49)];
15742
- return { status: "invalid_schema", errors: errors3 };
15640
+ var chdir;
15641
+ module.exports = patch;
15642
+ function patch(fs3) {
15643
+ if (constants.hasOwnProperty("O_SYMLINK") && process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
15644
+ patchLchmod(fs3);
15645
+ }
15646
+ if (!fs3.lutimes) {
15647
+ patchLutimes(fs3);
15648
+ }
15649
+ fs3.chown = chownFix(fs3.chown);
15650
+ fs3.fchown = chownFix(fs3.fchown);
15651
+ fs3.lchown = chownFix(fs3.lchown);
15652
+ fs3.chmod = chmodFix(fs3.chmod);
15653
+ fs3.fchmod = chmodFix(fs3.fchmod);
15654
+ fs3.lchmod = chmodFix(fs3.lchmod);
15655
+ fs3.chownSync = chownFixSync(fs3.chownSync);
15656
+ fs3.fchownSync = chownFixSync(fs3.fchownSync);
15657
+ fs3.lchownSync = chownFixSync(fs3.lchownSync);
15658
+ fs3.chmodSync = chmodFixSync(fs3.chmodSync);
15659
+ fs3.fchmodSync = chmodFixSync(fs3.fchmodSync);
15660
+ fs3.lchmodSync = chmodFixSync(fs3.lchmodSync);
15661
+ fs3.stat = statFix(fs3.stat);
15662
+ fs3.fstat = statFix(fs3.fstat);
15663
+ fs3.lstat = statFix(fs3.lstat);
15664
+ fs3.statSync = statFixSync(fs3.statSync);
15665
+ fs3.fstatSync = statFixSync(fs3.fstatSync);
15666
+ fs3.lstatSync = statFixSync(fs3.lstatSync);
15667
+ if (fs3.chmod && !fs3.lchmod) {
15668
+ fs3.lchmod = function(path5, mode, cb) {
15669
+ if (cb)
15670
+ process.nextTick(cb);
15671
+ };
15672
+ fs3.lchmodSync = function() {};
15743
15673
  }
15744
- }
15745
- try {
15746
- const validated = EvidenceBundleSchema.parse(parsed);
15747
- return { status: "found", bundle: validated };
15748
- } catch (error49) {
15749
- warn(`Evidence bundle validation failed for task ${sanitizedTaskId}: ${error49 instanceof Error ? error49.message : String(error49)}`);
15750
- const errors3 = error49 instanceof ZodError ? error49.issues.map((e) => `${e.path.join(".")}: ${e.message}`) : [error49 instanceof Error ? error49.message : String(error49)];
15751
- return { status: "invalid_schema", errors: errors3 };
15752
- }
15753
- }
15754
- async function listEvidenceTaskIds(directory) {
15755
- const evidenceBasePath = validateSwarmPath(directory, "evidence");
15756
- try {
15757
- statSync2(evidenceBasePath);
15758
- } catch {
15759
- return [];
15760
- }
15761
- let entries;
15762
- try {
15763
- entries = readdirSync2(evidenceBasePath);
15764
- } catch {
15765
- return [];
15766
- }
15767
- const taskIds = [];
15768
- for (const entry of entries) {
15769
- const entryPath = path5.join(evidenceBasePath, entry);
15770
- try {
15771
- const stats = statSync2(entryPath);
15772
- if (!stats.isDirectory()) {
15773
- continue;
15774
- }
15775
- sanitizeTaskId2(entry);
15776
- taskIds.push(entry);
15777
- } catch (error49) {
15778
- if (error49 instanceof Error && !error49.message.startsWith("Invalid task ID")) {
15779
- warn(`Error reading evidence entry '${entry}': ${error49.message}`);
15780
- }
15781
- }
15782
- }
15783
- return taskIds.sort();
15784
- }
15785
- async function deleteEvidence(directory, taskId) {
15786
- const sanitizedTaskId = sanitizeTaskId2(taskId);
15787
- const relativePath = path5.join("evidence", sanitizedTaskId);
15788
- const evidenceDir = validateSwarmPath(directory, relativePath);
15789
- try {
15790
- statSync2(evidenceDir);
15791
- } catch {
15792
- return false;
15793
- }
15794
- try {
15795
- rmSync(evidenceDir, { recursive: true, force: true });
15796
- return true;
15797
- } catch (error49) {
15798
- warn(`Failed to delete evidence for task ${sanitizedTaskId}: ${error49 instanceof Error ? error49.message : String(error49)}`);
15799
- return false;
15800
- }
15801
- }
15802
- async function checkRequirementCoverage(phase, directory) {
15803
- const relativePath = path5.join("evidence", `req-coverage-phase-${phase}.json`);
15804
- const absolutePath = path5.resolve(directory, ".swarm", relativePath);
15805
- try {
15806
- await fs3.access(absolutePath);
15807
- return { exists: true, path: absolutePath };
15808
- } catch {
15809
- return { exists: false, path: absolutePath };
15810
- }
15811
- }
15812
- async function archiveEvidence(directory, maxAgeDays, maxBundles) {
15813
- const taskIds = await listEvidenceTaskIds(directory);
15814
- const cutoffDate = new Date;
15815
- cutoffDate.setDate(cutoffDate.getDate() - maxAgeDays);
15816
- const cutoffIso = cutoffDate.toISOString();
15817
- const archived = [];
15818
- const remainingBundles = [];
15819
- for (const taskId of taskIds) {
15820
- const result = await loadEvidence(directory, taskId);
15821
- if (result.status !== "found") {
15822
- continue;
15823
- }
15824
- if (result.bundle.updated_at < cutoffIso) {
15825
- const deleted = await deleteEvidence(directory, taskId);
15826
- if (deleted) {
15827
- archived.push(taskId);
15828
- }
15829
- } else {
15830
- remainingBundles.push({
15831
- taskId,
15832
- updatedAt: result.bundle.updated_at
15833
- });
15834
- }
15835
- }
15836
- if (maxBundles !== undefined && remainingBundles.length > maxBundles) {
15837
- remainingBundles.sort((a, b) => a.updatedAt.localeCompare(b.updatedAt));
15838
- const toDelete = remainingBundles.length - maxBundles;
15839
- for (let i = 0;i < toDelete; i++) {
15840
- const deleted = await deleteEvidence(directory, remainingBundles[i].taskId);
15841
- if (deleted) {
15842
- archived.push(remainingBundles[i].taskId);
15843
- }
15844
- }
15845
- }
15846
- return archived;
15847
- }
15848
- var VALID_EVIDENCE_TYPES, sanitizeTaskId2, LEGACY_TASK_COMPLEXITY_MAP;
15849
- var init_manager2 = __esm(() => {
15850
- init_zod();
15851
- init_evidence_schema();
15852
- init_utils2();
15853
- init_utils();
15854
- init_task_id();
15855
- VALID_EVIDENCE_TYPES = [
15856
- "review",
15857
- "test",
15858
- "diff",
15859
- "approval",
15860
- "note",
15861
- "retrospective",
15862
- "syntax",
15863
- "placeholder",
15864
- "sast",
15865
- "sbom",
15866
- "build",
15867
- "quality_budget",
15868
- "secretscan"
15869
- ];
15870
- sanitizeTaskId2 = sanitizeTaskId;
15871
- LEGACY_TASK_COMPLEXITY_MAP = {
15872
- low: "simple",
15873
- medium: "moderate",
15874
- high: "complex"
15875
- };
15876
- });
15877
-
15878
- // src/telemetry.ts
15879
- var init_telemetry = () => {};
15880
-
15881
- // node_modules/graceful-fs/polyfills.js
15882
- var require_polyfills = __commonJS((exports, module) => {
15883
- var constants = __require("constants");
15884
- var origCwd = process.cwd;
15885
- var cwd = null;
15886
- var platform = process.env.GRACEFUL_FS_PLATFORM || process.platform;
15887
- process.cwd = function() {
15888
- if (!cwd)
15889
- cwd = origCwd.call(process);
15890
- return cwd;
15891
- };
15892
- try {
15893
- process.cwd();
15894
- } catch (er) {}
15895
- if (typeof process.chdir === "function") {
15896
- chdir = process.chdir;
15897
- process.chdir = function(d) {
15898
- cwd = null;
15899
- chdir.call(process, d);
15900
- };
15901
- if (Object.setPrototypeOf)
15902
- Object.setPrototypeOf(process.chdir, chdir);
15903
- }
15904
- var chdir;
15905
- module.exports = patch;
15906
- function patch(fs4) {
15907
- if (constants.hasOwnProperty("O_SYMLINK") && process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
15908
- patchLchmod(fs4);
15909
- }
15910
- if (!fs4.lutimes) {
15911
- patchLutimes(fs4);
15912
- }
15913
- fs4.chown = chownFix(fs4.chown);
15914
- fs4.fchown = chownFix(fs4.fchown);
15915
- fs4.lchown = chownFix(fs4.lchown);
15916
- fs4.chmod = chmodFix(fs4.chmod);
15917
- fs4.fchmod = chmodFix(fs4.fchmod);
15918
- fs4.lchmod = chmodFix(fs4.lchmod);
15919
- fs4.chownSync = chownFixSync(fs4.chownSync);
15920
- fs4.fchownSync = chownFixSync(fs4.fchownSync);
15921
- fs4.lchownSync = chownFixSync(fs4.lchownSync);
15922
- fs4.chmodSync = chmodFixSync(fs4.chmodSync);
15923
- fs4.fchmodSync = chmodFixSync(fs4.fchmodSync);
15924
- fs4.lchmodSync = chmodFixSync(fs4.lchmodSync);
15925
- fs4.stat = statFix(fs4.stat);
15926
- fs4.fstat = statFix(fs4.fstat);
15927
- fs4.lstat = statFix(fs4.lstat);
15928
- fs4.statSync = statFixSync(fs4.statSync);
15929
- fs4.fstatSync = statFixSync(fs4.fstatSync);
15930
- fs4.lstatSync = statFixSync(fs4.lstatSync);
15931
- if (fs4.chmod && !fs4.lchmod) {
15932
- fs4.lchmod = function(path6, mode, cb) {
15933
- if (cb)
15934
- process.nextTick(cb);
15935
- };
15936
- fs4.lchmodSync = function() {};
15937
- }
15938
- if (fs4.chown && !fs4.lchown) {
15939
- fs4.lchown = function(path6, uid, gid, cb) {
15940
- if (cb)
15941
- process.nextTick(cb);
15942
- };
15943
- fs4.lchownSync = function() {};
15674
+ if (fs3.chown && !fs3.lchown) {
15675
+ fs3.lchown = function(path5, uid, gid, cb) {
15676
+ if (cb)
15677
+ process.nextTick(cb);
15678
+ };
15679
+ fs3.lchownSync = function() {};
15944
15680
  }
15945
15681
  if (platform === "win32") {
15946
- fs4.rename = typeof fs4.rename !== "function" ? fs4.rename : function(fs$rename) {
15947
- function rename2(from, to, cb) {
15682
+ fs3.rename = typeof fs3.rename !== "function" ? fs3.rename : function(fs$rename) {
15683
+ function rename(from, to, cb) {
15948
15684
  var start = Date.now();
15949
15685
  var backoff = 0;
15950
15686
  fs$rename(from, to, function CB(er) {
15951
15687
  if (er && (er.code === "EACCES" || er.code === "EPERM" || er.code === "EBUSY") && Date.now() - start < 60000) {
15952
15688
  setTimeout(function() {
15953
- fs4.stat(to, function(stater, st) {
15689
+ fs3.stat(to, function(stater, st) {
15954
15690
  if (stater && stater.code === "ENOENT")
15955
15691
  fs$rename(from, to, CB);
15956
15692
  else
@@ -15966,11 +15702,11 @@ var require_polyfills = __commonJS((exports, module) => {
15966
15702
  });
15967
15703
  }
15968
15704
  if (Object.setPrototypeOf)
15969
- Object.setPrototypeOf(rename2, fs$rename);
15970
- return rename2;
15971
- }(fs4.rename);
15705
+ Object.setPrototypeOf(rename, fs$rename);
15706
+ return rename;
15707
+ }(fs3.rename);
15972
15708
  }
15973
- fs4.read = typeof fs4.read !== "function" ? fs4.read : function(fs$read) {
15709
+ fs3.read = typeof fs3.read !== "function" ? fs3.read : function(fs$read) {
15974
15710
  function read(fd, buffer, offset, length, position, callback_) {
15975
15711
  var callback;
15976
15712
  if (callback_ && typeof callback_ === "function") {
@@ -15978,23 +15714,23 @@ var require_polyfills = __commonJS((exports, module) => {
15978
15714
  callback = function(er, _, __) {
15979
15715
  if (er && er.code === "EAGAIN" && eagCounter < 10) {
15980
15716
  eagCounter++;
15981
- return fs$read.call(fs4, fd, buffer, offset, length, position, callback);
15717
+ return fs$read.call(fs3, fd, buffer, offset, length, position, callback);
15982
15718
  }
15983
15719
  callback_.apply(this, arguments);
15984
15720
  };
15985
15721
  }
15986
- return fs$read.call(fs4, fd, buffer, offset, length, position, callback);
15722
+ return fs$read.call(fs3, fd, buffer, offset, length, position, callback);
15987
15723
  }
15988
15724
  if (Object.setPrototypeOf)
15989
15725
  Object.setPrototypeOf(read, fs$read);
15990
15726
  return read;
15991
- }(fs4.read);
15992
- fs4.readSync = typeof fs4.readSync !== "function" ? fs4.readSync : function(fs$readSync) {
15727
+ }(fs3.read);
15728
+ fs3.readSync = typeof fs3.readSync !== "function" ? fs3.readSync : function(fs$readSync) {
15993
15729
  return function(fd, buffer, offset, length, position) {
15994
15730
  var eagCounter = 0;
15995
15731
  while (true) {
15996
15732
  try {
15997
- return fs$readSync.call(fs4, fd, buffer, offset, length, position);
15733
+ return fs$readSync.call(fs3, fd, buffer, offset, length, position);
15998
15734
  } catch (er) {
15999
15735
  if (er.code === "EAGAIN" && eagCounter < 10) {
16000
15736
  eagCounter++;
@@ -16004,90 +15740,90 @@ var require_polyfills = __commonJS((exports, module) => {
16004
15740
  }
16005
15741
  }
16006
15742
  };
16007
- }(fs4.readSync);
16008
- function patchLchmod(fs5) {
16009
- fs5.lchmod = function(path6, mode, callback) {
16010
- fs5.open(path6, constants.O_WRONLY | constants.O_SYMLINK, mode, function(err, fd) {
15743
+ }(fs3.readSync);
15744
+ function patchLchmod(fs4) {
15745
+ fs4.lchmod = function(path5, mode, callback) {
15746
+ fs4.open(path5, constants.O_WRONLY | constants.O_SYMLINK, mode, function(err, fd) {
16011
15747
  if (err) {
16012
15748
  if (callback)
16013
15749
  callback(err);
16014
15750
  return;
16015
15751
  }
16016
- fs5.fchmod(fd, mode, function(err2) {
16017
- fs5.close(fd, function(err22) {
15752
+ fs4.fchmod(fd, mode, function(err2) {
15753
+ fs4.close(fd, function(err22) {
16018
15754
  if (callback)
16019
15755
  callback(err2 || err22);
16020
15756
  });
16021
15757
  });
16022
15758
  });
16023
15759
  };
16024
- fs5.lchmodSync = function(path6, mode) {
16025
- var fd = fs5.openSync(path6, constants.O_WRONLY | constants.O_SYMLINK, mode);
15760
+ fs4.lchmodSync = function(path5, mode) {
15761
+ var fd = fs4.openSync(path5, constants.O_WRONLY | constants.O_SYMLINK, mode);
16026
15762
  var threw = true;
16027
15763
  var ret;
16028
15764
  try {
16029
- ret = fs5.fchmodSync(fd, mode);
15765
+ ret = fs4.fchmodSync(fd, mode);
16030
15766
  threw = false;
16031
15767
  } finally {
16032
15768
  if (threw) {
16033
15769
  try {
16034
- fs5.closeSync(fd);
15770
+ fs4.closeSync(fd);
16035
15771
  } catch (er) {}
16036
15772
  } else {
16037
- fs5.closeSync(fd);
15773
+ fs4.closeSync(fd);
16038
15774
  }
16039
15775
  }
16040
15776
  return ret;
16041
15777
  };
16042
15778
  }
16043
- function patchLutimes(fs5) {
16044
- if (constants.hasOwnProperty("O_SYMLINK") && fs5.futimes) {
16045
- fs5.lutimes = function(path6, at, mt, cb) {
16046
- fs5.open(path6, constants.O_SYMLINK, function(er, fd) {
15779
+ function patchLutimes(fs4) {
15780
+ if (constants.hasOwnProperty("O_SYMLINK") && fs4.futimes) {
15781
+ fs4.lutimes = function(path5, at, mt, cb) {
15782
+ fs4.open(path5, constants.O_SYMLINK, function(er, fd) {
16047
15783
  if (er) {
16048
15784
  if (cb)
16049
15785
  cb(er);
16050
15786
  return;
16051
15787
  }
16052
- fs5.futimes(fd, at, mt, function(er2) {
16053
- fs5.close(fd, function(er22) {
15788
+ fs4.futimes(fd, at, mt, function(er2) {
15789
+ fs4.close(fd, function(er22) {
16054
15790
  if (cb)
16055
15791
  cb(er2 || er22);
16056
15792
  });
16057
15793
  });
16058
15794
  });
16059
15795
  };
16060
- fs5.lutimesSync = function(path6, at, mt) {
16061
- var fd = fs5.openSync(path6, constants.O_SYMLINK);
15796
+ fs4.lutimesSync = function(path5, at, mt) {
15797
+ var fd = fs4.openSync(path5, constants.O_SYMLINK);
16062
15798
  var ret;
16063
15799
  var threw = true;
16064
15800
  try {
16065
- ret = fs5.futimesSync(fd, at, mt);
15801
+ ret = fs4.futimesSync(fd, at, mt);
16066
15802
  threw = false;
16067
15803
  } finally {
16068
15804
  if (threw) {
16069
15805
  try {
16070
- fs5.closeSync(fd);
15806
+ fs4.closeSync(fd);
16071
15807
  } catch (er) {}
16072
15808
  } else {
16073
- fs5.closeSync(fd);
15809
+ fs4.closeSync(fd);
16074
15810
  }
16075
15811
  }
16076
15812
  return ret;
16077
15813
  };
16078
- } else if (fs5.futimes) {
16079
- fs5.lutimes = function(_a2, _b, _c, cb) {
15814
+ } else if (fs4.futimes) {
15815
+ fs4.lutimes = function(_a2, _b, _c, cb) {
16080
15816
  if (cb)
16081
15817
  process.nextTick(cb);
16082
15818
  };
16083
- fs5.lutimesSync = function() {};
15819
+ fs4.lutimesSync = function() {};
16084
15820
  }
16085
15821
  }
16086
15822
  function chmodFix(orig) {
16087
15823
  if (!orig)
16088
15824
  return orig;
16089
15825
  return function(target, mode, cb) {
16090
- return orig.call(fs4, target, mode, function(er) {
15826
+ return orig.call(fs3, target, mode, function(er) {
16091
15827
  if (chownErOk(er))
16092
15828
  er = null;
16093
15829
  if (cb)
@@ -16100,7 +15836,7 @@ var require_polyfills = __commonJS((exports, module) => {
16100
15836
  return orig;
16101
15837
  return function(target, mode) {
16102
15838
  try {
16103
- return orig.call(fs4, target, mode);
15839
+ return orig.call(fs3, target, mode);
16104
15840
  } catch (er) {
16105
15841
  if (!chownErOk(er))
16106
15842
  throw er;
@@ -16111,7 +15847,7 @@ var require_polyfills = __commonJS((exports, module) => {
16111
15847
  if (!orig)
16112
15848
  return orig;
16113
15849
  return function(target, uid, gid, cb) {
16114
- return orig.call(fs4, target, uid, gid, function(er) {
15850
+ return orig.call(fs3, target, uid, gid, function(er) {
16115
15851
  if (chownErOk(er))
16116
15852
  er = null;
16117
15853
  if (cb)
@@ -16124,7 +15860,7 @@ var require_polyfills = __commonJS((exports, module) => {
16124
15860
  return orig;
16125
15861
  return function(target, uid, gid) {
16126
15862
  try {
16127
- return orig.call(fs4, target, uid, gid);
15863
+ return orig.call(fs3, target, uid, gid);
16128
15864
  } catch (er) {
16129
15865
  if (!chownErOk(er))
16130
15866
  throw er;
@@ -16149,14 +15885,14 @@ var require_polyfills = __commonJS((exports, module) => {
16149
15885
  if (cb)
16150
15886
  cb.apply(this, arguments);
16151
15887
  }
16152
- return options ? orig.call(fs4, target, options, callback) : orig.call(fs4, target, callback);
15888
+ return options ? orig.call(fs3, target, options, callback) : orig.call(fs3, target, callback);
16153
15889
  };
16154
15890
  }
16155
15891
  function statFixSync(orig) {
16156
15892
  if (!orig)
16157
15893
  return orig;
16158
15894
  return function(target, options) {
16159
- var stats = options ? orig.call(fs4, target, options) : orig.call(fs4, target);
15895
+ var stats = options ? orig.call(fs3, target, options) : orig.call(fs3, target);
16160
15896
  if (stats) {
16161
15897
  if (stats.uid < 0)
16162
15898
  stats.uid += 4294967296;
@@ -16185,17 +15921,17 @@ var require_polyfills = __commonJS((exports, module) => {
16185
15921
  var require_legacy_streams = __commonJS((exports, module) => {
16186
15922
  var Stream = __require("stream").Stream;
16187
15923
  module.exports = legacy;
16188
- function legacy(fs4) {
15924
+ function legacy(fs3) {
16189
15925
  return {
16190
15926
  ReadStream,
16191
15927
  WriteStream
16192
15928
  };
16193
- function ReadStream(path6, options) {
15929
+ function ReadStream(path5, options) {
16194
15930
  if (!(this instanceof ReadStream))
16195
- return new ReadStream(path6, options);
15931
+ return new ReadStream(path5, options);
16196
15932
  Stream.call(this);
16197
15933
  var self = this;
16198
- this.path = path6;
15934
+ this.path = path5;
16199
15935
  this.fd = null;
16200
15936
  this.readable = true;
16201
15937
  this.paused = false;
@@ -16230,7 +15966,7 @@ var require_legacy_streams = __commonJS((exports, module) => {
16230
15966
  });
16231
15967
  return;
16232
15968
  }
16233
- fs4.open(this.path, this.flags, this.mode, function(err, fd) {
15969
+ fs3.open(this.path, this.flags, this.mode, function(err, fd) {
16234
15970
  if (err) {
16235
15971
  self.emit("error", err);
16236
15972
  self.readable = false;
@@ -16241,11 +15977,11 @@ var require_legacy_streams = __commonJS((exports, module) => {
16241
15977
  self._read();
16242
15978
  });
16243
15979
  }
16244
- function WriteStream(path6, options) {
15980
+ function WriteStream(path5, options) {
16245
15981
  if (!(this instanceof WriteStream))
16246
- return new WriteStream(path6, options);
15982
+ return new WriteStream(path5, options);
16247
15983
  Stream.call(this);
16248
- this.path = path6;
15984
+ this.path = path5;
16249
15985
  this.fd = null;
16250
15986
  this.writable = true;
16251
15987
  this.flags = "w";
@@ -16270,7 +16006,7 @@ var require_legacy_streams = __commonJS((exports, module) => {
16270
16006
  this.busy = false;
16271
16007
  this._queue = [];
16272
16008
  if (this.fd === null) {
16273
- this._open = fs4.open;
16009
+ this._open = fs3.open;
16274
16010
  this._queue.push([this._open, this.path, this.flags, this.mode, undefined]);
16275
16011
  this.flush();
16276
16012
  }
@@ -16300,7 +16036,7 @@ var require_clone = __commonJS((exports, module) => {
16300
16036
 
16301
16037
  // node_modules/graceful-fs/graceful-fs.js
16302
16038
  var require_graceful_fs = __commonJS((exports, module) => {
16303
- var fs4 = __require("fs");
16039
+ var fs3 = __require("fs");
16304
16040
  var polyfills = require_polyfills();
16305
16041
  var legacy = require_legacy_streams();
16306
16042
  var clone2 = require_clone();
@@ -16332,12 +16068,12 @@ var require_graceful_fs = __commonJS((exports, module) => {
16332
16068
  GFS4: `);
16333
16069
  console.error(m);
16334
16070
  };
16335
- if (!fs4[gracefulQueue]) {
16071
+ if (!fs3[gracefulQueue]) {
16336
16072
  queue = global[gracefulQueue] || [];
16337
- publishQueue(fs4, queue);
16338
- fs4.close = function(fs$close) {
16073
+ publishQueue(fs3, queue);
16074
+ fs3.close = function(fs$close) {
16339
16075
  function close(fd, cb) {
16340
- return fs$close.call(fs4, fd, function(err) {
16076
+ return fs$close.call(fs3, fd, function(err) {
16341
16077
  if (!err) {
16342
16078
  resetQueue();
16343
16079
  }
@@ -16349,48 +16085,48 @@ GFS4: `);
16349
16085
  value: fs$close
16350
16086
  });
16351
16087
  return close;
16352
- }(fs4.close);
16353
- fs4.closeSync = function(fs$closeSync) {
16088
+ }(fs3.close);
16089
+ fs3.closeSync = function(fs$closeSync) {
16354
16090
  function closeSync(fd) {
16355
- fs$closeSync.apply(fs4, arguments);
16091
+ fs$closeSync.apply(fs3, arguments);
16356
16092
  resetQueue();
16357
16093
  }
16358
16094
  Object.defineProperty(closeSync, previousSymbol, {
16359
16095
  value: fs$closeSync
16360
16096
  });
16361
16097
  return closeSync;
16362
- }(fs4.closeSync);
16098
+ }(fs3.closeSync);
16363
16099
  if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || "")) {
16364
16100
  process.on("exit", function() {
16365
- debug(fs4[gracefulQueue]);
16366
- __require("assert").equal(fs4[gracefulQueue].length, 0);
16101
+ debug(fs3[gracefulQueue]);
16102
+ __require("assert").equal(fs3[gracefulQueue].length, 0);
16367
16103
  });
16368
16104
  }
16369
16105
  }
16370
16106
  var queue;
16371
16107
  if (!global[gracefulQueue]) {
16372
- publishQueue(global, fs4[gracefulQueue]);
16373
- }
16374
- module.exports = patch(clone2(fs4));
16375
- if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs4.__patched) {
16376
- module.exports = patch(fs4);
16377
- fs4.__patched = true;
16378
- }
16379
- function patch(fs5) {
16380
- polyfills(fs5);
16381
- fs5.gracefulify = patch;
16382
- fs5.createReadStream = createReadStream;
16383
- fs5.createWriteStream = createWriteStream;
16384
- var fs$readFile = fs5.readFile;
16385
- fs5.readFile = readFile2;
16386
- function readFile2(path6, options, cb) {
16108
+ publishQueue(global, fs3[gracefulQueue]);
16109
+ }
16110
+ module.exports = patch(clone2(fs3));
16111
+ if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs3.__patched) {
16112
+ module.exports = patch(fs3);
16113
+ fs3.__patched = true;
16114
+ }
16115
+ function patch(fs4) {
16116
+ polyfills(fs4);
16117
+ fs4.gracefulify = patch;
16118
+ fs4.createReadStream = createReadStream;
16119
+ fs4.createWriteStream = createWriteStream;
16120
+ var fs$readFile = fs4.readFile;
16121
+ fs4.readFile = readFile2;
16122
+ function readFile2(path5, options, cb) {
16387
16123
  if (typeof options === "function")
16388
16124
  cb = options, options = null;
16389
- return go$readFile(path6, options, cb);
16390
- function go$readFile(path7, options2, cb2, startTime) {
16391
- return fs$readFile(path7, options2, function(err) {
16125
+ return go$readFile(path5, options, cb);
16126
+ function go$readFile(path6, options2, cb2, startTime) {
16127
+ return fs$readFile(path6, options2, function(err) {
16392
16128
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
16393
- enqueue([go$readFile, [path7, options2, cb2], err, startTime || Date.now(), Date.now()]);
16129
+ enqueue([go$readFile, [path6, options2, cb2], err, startTime || Date.now(), Date.now()]);
16394
16130
  else {
16395
16131
  if (typeof cb2 === "function")
16396
16132
  cb2.apply(this, arguments);
@@ -16398,16 +16134,16 @@ GFS4: `);
16398
16134
  });
16399
16135
  }
16400
16136
  }
16401
- var fs$writeFile = fs5.writeFile;
16402
- fs5.writeFile = writeFile2;
16403
- function writeFile2(path6, data, options, cb) {
16137
+ var fs$writeFile = fs4.writeFile;
16138
+ fs4.writeFile = writeFile2;
16139
+ function writeFile2(path5, data, options, cb) {
16404
16140
  if (typeof options === "function")
16405
16141
  cb = options, options = null;
16406
- return go$writeFile(path6, data, options, cb);
16407
- function go$writeFile(path7, data2, options2, cb2, startTime) {
16408
- return fs$writeFile(path7, data2, options2, function(err) {
16142
+ return go$writeFile(path5, data, options, cb);
16143
+ function go$writeFile(path6, data2, options2, cb2, startTime) {
16144
+ return fs$writeFile(path6, data2, options2, function(err) {
16409
16145
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
16410
- enqueue([go$writeFile, [path7, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
16146
+ enqueue([go$writeFile, [path6, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
16411
16147
  else {
16412
16148
  if (typeof cb2 === "function")
16413
16149
  cb2.apply(this, arguments);
@@ -16415,17 +16151,17 @@ GFS4: `);
16415
16151
  });
16416
16152
  }
16417
16153
  }
16418
- var fs$appendFile = fs5.appendFile;
16154
+ var fs$appendFile = fs4.appendFile;
16419
16155
  if (fs$appendFile)
16420
- fs5.appendFile = appendFile2;
16421
- function appendFile2(path6, data, options, cb) {
16156
+ fs4.appendFile = appendFile2;
16157
+ function appendFile2(path5, data, options, cb) {
16422
16158
  if (typeof options === "function")
16423
16159
  cb = options, options = null;
16424
- return go$appendFile(path6, data, options, cb);
16425
- function go$appendFile(path7, data2, options2, cb2, startTime) {
16426
- return fs$appendFile(path7, data2, options2, function(err) {
16160
+ return go$appendFile(path5, data, options, cb);
16161
+ function go$appendFile(path6, data2, options2, cb2, startTime) {
16162
+ return fs$appendFile(path6, data2, options2, function(err) {
16427
16163
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
16428
- enqueue([go$appendFile, [path7, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
16164
+ enqueue([go$appendFile, [path6, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
16429
16165
  else {
16430
16166
  if (typeof cb2 === "function")
16431
16167
  cb2.apply(this, arguments);
@@ -16433,9 +16169,9 @@ GFS4: `);
16433
16169
  });
16434
16170
  }
16435
16171
  }
16436
- var fs$copyFile = fs5.copyFile;
16172
+ var fs$copyFile = fs4.copyFile;
16437
16173
  if (fs$copyFile)
16438
- fs5.copyFile = copyFile;
16174
+ fs4.copyFile = copyFile;
16439
16175
  function copyFile(src, dest, flags, cb) {
16440
16176
  if (typeof flags === "function") {
16441
16177
  cb = flags;
@@ -16453,24 +16189,24 @@ GFS4: `);
16453
16189
  });
16454
16190
  }
16455
16191
  }
16456
- var fs$readdir = fs5.readdir;
16457
- fs5.readdir = readdir;
16192
+ var fs$readdir = fs4.readdir;
16193
+ fs4.readdir = readdir;
16458
16194
  var noReaddirOptionVersions = /^v[0-5]\./;
16459
- function readdir(path6, options, cb) {
16195
+ function readdir(path5, options, cb) {
16460
16196
  if (typeof options === "function")
16461
16197
  cb = options, options = null;
16462
- var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path7, options2, cb2, startTime) {
16463
- return fs$readdir(path7, fs$readdirCallback(path7, options2, cb2, startTime));
16464
- } : function go$readdir2(path7, options2, cb2, startTime) {
16465
- return fs$readdir(path7, options2, fs$readdirCallback(path7, options2, cb2, startTime));
16198
+ var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path6, options2, cb2, startTime) {
16199
+ return fs$readdir(path6, fs$readdirCallback(path6, options2, cb2, startTime));
16200
+ } : function go$readdir2(path6, options2, cb2, startTime) {
16201
+ return fs$readdir(path6, options2, fs$readdirCallback(path6, options2, cb2, startTime));
16466
16202
  };
16467
- return go$readdir(path6, options, cb);
16468
- function fs$readdirCallback(path7, options2, cb2, startTime) {
16203
+ return go$readdir(path5, options, cb);
16204
+ function fs$readdirCallback(path6, options2, cb2, startTime) {
16469
16205
  return function(err, files) {
16470
16206
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
16471
16207
  enqueue([
16472
16208
  go$readdir,
16473
- [path7, options2, cb2],
16209
+ [path6, options2, cb2],
16474
16210
  err,
16475
16211
  startTime || Date.now(),
16476
16212
  Date.now()
@@ -16485,21 +16221,21 @@ GFS4: `);
16485
16221
  }
16486
16222
  }
16487
16223
  if (process.version.substr(0, 4) === "v0.8") {
16488
- var legStreams = legacy(fs5);
16224
+ var legStreams = legacy(fs4);
16489
16225
  ReadStream = legStreams.ReadStream;
16490
16226
  WriteStream = legStreams.WriteStream;
16491
16227
  }
16492
- var fs$ReadStream = fs5.ReadStream;
16228
+ var fs$ReadStream = fs4.ReadStream;
16493
16229
  if (fs$ReadStream) {
16494
16230
  ReadStream.prototype = Object.create(fs$ReadStream.prototype);
16495
16231
  ReadStream.prototype.open = ReadStream$open;
16496
16232
  }
16497
- var fs$WriteStream = fs5.WriteStream;
16233
+ var fs$WriteStream = fs4.WriteStream;
16498
16234
  if (fs$WriteStream) {
16499
16235
  WriteStream.prototype = Object.create(fs$WriteStream.prototype);
16500
16236
  WriteStream.prototype.open = WriteStream$open;
16501
16237
  }
16502
- Object.defineProperty(fs5, "ReadStream", {
16238
+ Object.defineProperty(fs4, "ReadStream", {
16503
16239
  get: function() {
16504
16240
  return ReadStream;
16505
16241
  },
@@ -16509,7 +16245,7 @@ GFS4: `);
16509
16245
  enumerable: true,
16510
16246
  configurable: true
16511
16247
  });
16512
- Object.defineProperty(fs5, "WriteStream", {
16248
+ Object.defineProperty(fs4, "WriteStream", {
16513
16249
  get: function() {
16514
16250
  return WriteStream;
16515
16251
  },
@@ -16520,7 +16256,7 @@ GFS4: `);
16520
16256
  configurable: true
16521
16257
  });
16522
16258
  var FileReadStream = ReadStream;
16523
- Object.defineProperty(fs5, "FileReadStream", {
16259
+ Object.defineProperty(fs4, "FileReadStream", {
16524
16260
  get: function() {
16525
16261
  return FileReadStream;
16526
16262
  },
@@ -16531,7 +16267,7 @@ GFS4: `);
16531
16267
  configurable: true
16532
16268
  });
16533
16269
  var FileWriteStream = WriteStream;
16534
- Object.defineProperty(fs5, "FileWriteStream", {
16270
+ Object.defineProperty(fs4, "FileWriteStream", {
16535
16271
  get: function() {
16536
16272
  return FileWriteStream;
16537
16273
  },
@@ -16541,7 +16277,7 @@ GFS4: `);
16541
16277
  enumerable: true,
16542
16278
  configurable: true
16543
16279
  });
16544
- function ReadStream(path6, options) {
16280
+ function ReadStream(path5, options) {
16545
16281
  if (this instanceof ReadStream)
16546
16282
  return fs$ReadStream.apply(this, arguments), this;
16547
16283
  else
@@ -16561,7 +16297,7 @@ GFS4: `);
16561
16297
  }
16562
16298
  });
16563
16299
  }
16564
- function WriteStream(path6, options) {
16300
+ function WriteStream(path5, options) {
16565
16301
  if (this instanceof WriteStream)
16566
16302
  return fs$WriteStream.apply(this, arguments), this;
16567
16303
  else
@@ -16579,22 +16315,22 @@ GFS4: `);
16579
16315
  }
16580
16316
  });
16581
16317
  }
16582
- function createReadStream(path6, options) {
16583
- return new fs5.ReadStream(path6, options);
16318
+ function createReadStream(path5, options) {
16319
+ return new fs4.ReadStream(path5, options);
16584
16320
  }
16585
- function createWriteStream(path6, options) {
16586
- return new fs5.WriteStream(path6, options);
16321
+ function createWriteStream(path5, options) {
16322
+ return new fs4.WriteStream(path5, options);
16587
16323
  }
16588
- var fs$open = fs5.open;
16589
- fs5.open = open;
16590
- function open(path6, flags, mode, cb) {
16324
+ var fs$open = fs4.open;
16325
+ fs4.open = open;
16326
+ function open(path5, flags, mode, cb) {
16591
16327
  if (typeof mode === "function")
16592
16328
  cb = mode, mode = null;
16593
- return go$open(path6, flags, mode, cb);
16594
- function go$open(path7, flags2, mode2, cb2, startTime) {
16595
- return fs$open(path7, flags2, mode2, function(err, fd) {
16329
+ return go$open(path5, flags, mode, cb);
16330
+ function go$open(path6, flags2, mode2, cb2, startTime) {
16331
+ return fs$open(path6, flags2, mode2, function(err, fd) {
16596
16332
  if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
16597
- enqueue([go$open, [path7, flags2, mode2, cb2], err, startTime || Date.now(), Date.now()]);
16333
+ enqueue([go$open, [path6, flags2, mode2, cb2], err, startTime || Date.now(), Date.now()]);
16598
16334
  else {
16599
16335
  if (typeof cb2 === "function")
16600
16336
  cb2.apply(this, arguments);
@@ -16602,20 +16338,20 @@ GFS4: `);
16602
16338
  });
16603
16339
  }
16604
16340
  }
16605
- return fs5;
16341
+ return fs4;
16606
16342
  }
16607
16343
  function enqueue(elem) {
16608
16344
  debug("ENQUEUE", elem[0].name, elem[1]);
16609
- fs4[gracefulQueue].push(elem);
16345
+ fs3[gracefulQueue].push(elem);
16610
16346
  retry();
16611
16347
  }
16612
16348
  var retryTimer;
16613
16349
  function resetQueue() {
16614
16350
  var now = Date.now();
16615
- for (var i = 0;i < fs4[gracefulQueue].length; ++i) {
16616
- if (fs4[gracefulQueue][i].length > 2) {
16617
- fs4[gracefulQueue][i][3] = now;
16618
- fs4[gracefulQueue][i][4] = now;
16351
+ for (var i = 0;i < fs3[gracefulQueue].length; ++i) {
16352
+ if (fs3[gracefulQueue][i].length > 2) {
16353
+ fs3[gracefulQueue][i][3] = now;
16354
+ fs3[gracefulQueue][i][4] = now;
16619
16355
  }
16620
16356
  }
16621
16357
  retry();
@@ -16623,9 +16359,9 @@ GFS4: `);
16623
16359
  function retry() {
16624
16360
  clearTimeout(retryTimer);
16625
16361
  retryTimer = undefined;
16626
- if (fs4[gracefulQueue].length === 0)
16362
+ if (fs3[gracefulQueue].length === 0)
16627
16363
  return;
16628
- var elem = fs4[gracefulQueue].shift();
16364
+ var elem = fs3[gracefulQueue].shift();
16629
16365
  var fn = elem[0];
16630
16366
  var args = elem[1];
16631
16367
  var err = elem[2];
@@ -16647,7 +16383,7 @@ GFS4: `);
16647
16383
  debug("RETRY", fn.name, args);
16648
16384
  fn.apply(null, args.concat([startTime]));
16649
16385
  } else {
16650
- fs4[gracefulQueue].push(elem);
16386
+ fs3[gracefulQueue].push(elem);
16651
16387
  }
16652
16388
  }
16653
16389
  if (retryTimer === undefined) {
@@ -16951,7 +16687,7 @@ var require_signal_exit = __commonJS((exports, module) => {
16951
16687
  emitter.count -= 1;
16952
16688
  };
16953
16689
  module.exports.unload = unload;
16954
- emit = function emit2(event, code, signal) {
16690
+ emit2 = function emit3(event, code, signal) {
16955
16691
  if (emitter.emitted[event]) {
16956
16692
  return;
16957
16693
  }
@@ -16967,8 +16703,8 @@ var require_signal_exit = __commonJS((exports, module) => {
16967
16703
  var listeners = process3.listeners(sig);
16968
16704
  if (listeners.length === emitter.count) {
16969
16705
  unload();
16970
- emit("exit", null, sig);
16971
- emit("afterexit", null, sig);
16706
+ emit2("exit", null, sig);
16707
+ emit2("afterexit", null, sig);
16972
16708
  if (isWin && sig === "SIGHUP") {
16973
16709
  sig = "SIGINT";
16974
16710
  }
@@ -17004,8 +16740,8 @@ var require_signal_exit = __commonJS((exports, module) => {
17004
16740
  return;
17005
16741
  }
17006
16742
  process3.exitCode = code || 0;
17007
- emit("exit", process3.exitCode, null);
17008
- emit("afterexit", process3.exitCode, null);
16743
+ emit2("exit", process3.exitCode, null);
16744
+ emit2("afterexit", process3.exitCode, null);
17009
16745
  originalProcessReallyExit.call(process3, process3.exitCode);
17010
16746
  };
17011
16747
  originalProcessEmit = process3.emit;
@@ -17015,8 +16751,8 @@ var require_signal_exit = __commonJS((exports, module) => {
17015
16751
  process3.exitCode = arg;
17016
16752
  }
17017
16753
  var ret = originalProcessEmit.apply(this, arguments);
17018
- emit("exit", process3.exitCode, null);
17019
- emit("afterexit", process3.exitCode, null);
16754
+ emit2("exit", process3.exitCode, null);
16755
+ emit2("afterexit", process3.exitCode, null);
17020
16756
  return ret;
17021
16757
  } else {
17022
16758
  return originalProcessEmit.apply(this, arguments);
@@ -17029,7 +16765,7 @@ var require_signal_exit = __commonJS((exports, module) => {
17029
16765
  var EE;
17030
16766
  var emitter;
17031
16767
  var unload;
17032
- var emit;
16768
+ var emit2;
17033
16769
  var sigListeners;
17034
16770
  var loaded;
17035
16771
  var load;
@@ -17042,10 +16778,10 @@ var require_signal_exit = __commonJS((exports, module) => {
17042
16778
  // node_modules/proper-lockfile/lib/mtime-precision.js
17043
16779
  var require_mtime_precision = __commonJS((exports, module) => {
17044
16780
  var cacheSymbol = Symbol();
17045
- function probe(file2, fs4, callback) {
17046
- const cachedPrecision = fs4[cacheSymbol];
16781
+ function probe(file2, fs3, callback) {
16782
+ const cachedPrecision = fs3[cacheSymbol];
17047
16783
  if (cachedPrecision) {
17048
- return fs4.stat(file2, (err, stat) => {
16784
+ return fs3.stat(file2, (err, stat) => {
17049
16785
  if (err) {
17050
16786
  return callback(err);
17051
16787
  }
@@ -17053,16 +16789,16 @@ var require_mtime_precision = __commonJS((exports, module) => {
17053
16789
  });
17054
16790
  }
17055
16791
  const mtime = new Date(Math.ceil(Date.now() / 1000) * 1000 + 5);
17056
- fs4.utimes(file2, mtime, mtime, (err) => {
16792
+ fs3.utimes(file2, mtime, mtime, (err) => {
17057
16793
  if (err) {
17058
16794
  return callback(err);
17059
16795
  }
17060
- fs4.stat(file2, (err2, stat) => {
16796
+ fs3.stat(file2, (err2, stat) => {
17061
16797
  if (err2) {
17062
16798
  return callback(err2);
17063
16799
  }
17064
16800
  const precision = stat.mtime.getTime() % 1000 === 0 ? "s" : "ms";
17065
- Object.defineProperty(fs4, cacheSymbol, { value: precision });
16801
+ Object.defineProperty(fs3, cacheSymbol, { value: precision });
17066
16802
  callback(null, stat.mtime, precision);
17067
16803
  });
17068
16804
  });
@@ -17080,8 +16816,8 @@ var require_mtime_precision = __commonJS((exports, module) => {
17080
16816
 
17081
16817
  // node_modules/proper-lockfile/lib/lockfile.js
17082
16818
  var require_lockfile = __commonJS((exports, module) => {
17083
- var path6 = __require("path");
17084
- var fs4 = require_graceful_fs();
16819
+ var path5 = __require("path");
16820
+ var fs3 = require_graceful_fs();
17085
16821
  var retry = require_retry();
17086
16822
  var onExit = require_signal_exit();
17087
16823
  var mtimePrecision = require_mtime_precision();
@@ -17091,7 +16827,7 @@ var require_lockfile = __commonJS((exports, module) => {
17091
16827
  }
17092
16828
  function resolveCanonicalPath(file2, options, callback) {
17093
16829
  if (!options.realpath) {
17094
- return callback(null, path6.resolve(file2));
16830
+ return callback(null, path5.resolve(file2));
17095
16831
  }
17096
16832
  options.fs.realpath(file2, callback);
17097
16833
  }
@@ -17204,7 +16940,7 @@ var require_lockfile = __commonJS((exports, module) => {
17204
16940
  update: null,
17205
16941
  realpath: true,
17206
16942
  retries: 0,
17207
- fs: fs4,
16943
+ fs: fs3,
17208
16944
  onCompromised: (err) => {
17209
16945
  throw err;
17210
16946
  },
@@ -17248,7 +16984,7 @@ var require_lockfile = __commonJS((exports, module) => {
17248
16984
  }
17249
16985
  function unlock(file2, options, callback) {
17250
16986
  options = {
17251
- fs: fs4,
16987
+ fs: fs3,
17252
16988
  realpath: true,
17253
16989
  ...options
17254
16990
  };
@@ -17270,7 +17006,7 @@ var require_lockfile = __commonJS((exports, module) => {
17270
17006
  options = {
17271
17007
  stale: 1e4,
17272
17008
  realpath: true,
17273
- fs: fs4,
17009
+ fs: fs3,
17274
17010
  ...options
17275
17011
  };
17276
17012
  options.stale = Math.max(options.stale || 0, 2000);
@@ -17305,16 +17041,16 @@ var require_lockfile = __commonJS((exports, module) => {
17305
17041
 
17306
17042
  // node_modules/proper-lockfile/lib/adapter.js
17307
17043
  var require_adapter = __commonJS((exports, module) => {
17308
- var fs4 = require_graceful_fs();
17309
- function createSyncFs(fs5) {
17044
+ var fs3 = require_graceful_fs();
17045
+ function createSyncFs(fs4) {
17310
17046
  const methods = ["mkdir", "realpath", "stat", "rmdir", "utimes"];
17311
- const newFs = { ...fs5 };
17047
+ const newFs = { ...fs4 };
17312
17048
  methods.forEach((method) => {
17313
17049
  newFs[method] = (...args) => {
17314
17050
  const callback = args.pop();
17315
17051
  let ret;
17316
17052
  try {
17317
- ret = fs5[`${method}Sync`](...args);
17053
+ ret = fs4[`${method}Sync`](...args);
17318
17054
  } catch (err) {
17319
17055
  return callback(err);
17320
17056
  }
@@ -17324,12 +17060,12 @@ var require_adapter = __commonJS((exports, module) => {
17324
17060
  return newFs;
17325
17061
  }
17326
17062
  function toPromise(method) {
17327
- return (...args) => new Promise((resolve5, reject) => {
17063
+ return (...args) => new Promise((resolve3, reject) => {
17328
17064
  args.push((err, result) => {
17329
17065
  if (err) {
17330
17066
  reject(err);
17331
17067
  } else {
17332
- resolve5(result);
17068
+ resolve3(result);
17333
17069
  }
17334
17070
  });
17335
17071
  method(...args);
@@ -17352,7 +17088,7 @@ var require_adapter = __commonJS((exports, module) => {
17352
17088
  }
17353
17089
  function toSyncOptions(options) {
17354
17090
  options = { ...options };
17355
- options.fs = createSyncFs(options.fs || fs4);
17091
+ options.fs = createSyncFs(options.fs || fs3);
17356
17092
  if (typeof options.retries === "number" && options.retries > 0 || options.retries && typeof options.retries.retries === "number" && options.retries.retries > 0) {
17357
17093
  throw Object.assign(new Error("Cannot use retries with the sync api"), { code: "ESYNC" });
17358
17094
  }
@@ -17377,25 +17113,459 @@ var require_proper_lockfile = __commonJS((exports, module) => {
17377
17113
  const release = toSync(lockfile.lock)(file2, toSyncOptions(options));
17378
17114
  return toSync(release);
17379
17115
  }
17380
- function unlock(file2, options) {
17381
- return toPromise(lockfile.unlock)(file2, options);
17116
+ function unlock(file2, options) {
17117
+ return toPromise(lockfile.unlock)(file2, options);
17118
+ }
17119
+ function unlockSync(file2, options) {
17120
+ return toSync(lockfile.unlock)(file2, toSyncOptions(options));
17121
+ }
17122
+ function check2(file2, options) {
17123
+ return toPromise(lockfile.check)(file2, options);
17124
+ }
17125
+ function checkSync(file2, options) {
17126
+ return toSync(lockfile.check)(file2, toSyncOptions(options));
17127
+ }
17128
+ module.exports = lock;
17129
+ module.exports.lock = lock;
17130
+ module.exports.unlock = unlock;
17131
+ module.exports.lockSync = lockSync;
17132
+ module.exports.unlockSync = unlockSync;
17133
+ module.exports.check = check2;
17134
+ module.exports.checkSync = checkSync;
17135
+ });
17136
+
17137
+ // src/parallel/file-locks.ts
17138
+ import * as fs3 from "fs";
17139
+ import * as path5 from "path";
17140
+ function getLockFilePath(directory, filePath) {
17141
+ const normalized = path5.resolve(directory, filePath);
17142
+ const baseDir = path5.resolve(directory) + path5.sep;
17143
+ const pathOk = process.platform === "win32" ? normalized.toLowerCase().startsWith(baseDir.toLowerCase()) : normalized.startsWith(baseDir);
17144
+ if (!pathOk) {
17145
+ throw new Error("Invalid file path: path traversal not allowed");
17146
+ }
17147
+ const hash2 = Buffer.from(normalized).toString("base64").replace(/[/+=]/g, "_");
17148
+ return path5.join(directory, LOCKS_DIR, `${hash2}.lock`);
17149
+ }
17150
+ async function tryAcquireLock(directory, filePath, agent, taskId) {
17151
+ const lockPath = getLockFilePath(directory, filePath);
17152
+ const locksDir = path5.dirname(lockPath);
17153
+ if (!fs3.existsSync(locksDir)) {
17154
+ fs3.mkdirSync(locksDir, { recursive: true });
17155
+ }
17156
+ if (!fs3.existsSync(lockPath)) {
17157
+ fs3.writeFileSync(lockPath, "", "utf-8");
17158
+ }
17159
+ let release;
17160
+ try {
17161
+ release = await import_proper_lockfile.default.lock(lockPath, {
17162
+ stale: LOCK_TIMEOUT_MS,
17163
+ retries: { retries: 0 },
17164
+ realpath: false
17165
+ });
17166
+ } catch (err) {
17167
+ const code = err.code;
17168
+ if (code === "ELOCKED" || code === "EEXIST") {
17169
+ return { acquired: false };
17170
+ }
17171
+ throw err;
17172
+ }
17173
+ const lock = {
17174
+ filePath,
17175
+ agent,
17176
+ taskId,
17177
+ timestamp: new Date().toISOString(),
17178
+ expiresAt: Date.now() + LOCK_TIMEOUT_MS,
17179
+ _release: release
17180
+ };
17181
+ return { acquired: true, lock };
17182
+ }
17183
+ var import_proper_lockfile, LOCKS_DIR = ".swarm/locks", LOCK_TIMEOUT_MS;
17184
+ var init_file_locks = __esm(() => {
17185
+ import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
17186
+ LOCK_TIMEOUT_MS = 5 * 60 * 1000;
17187
+ });
17188
+
17189
+ // src/evidence/lock.ts
17190
+ function backoffMs(attempt) {
17191
+ const base = Math.min(BACKOFF_START_MS * 2 ** attempt, BACKOFF_MAX_MS);
17192
+ const jitter = base * BACKOFF_JITTER_RATIO * (Math.random() * 2 - 1);
17193
+ return Math.max(1, Math.round(base + jitter));
17194
+ }
17195
+ async function withEvidenceLock(directory, evidencePath, agent, taskId, fn, timeoutMs = 60000) {
17196
+ const deadline = Date.now() + timeoutMs;
17197
+ let attempt = 0;
17198
+ while (true) {
17199
+ const result = await tryAcquireLock(directory, evidencePath, agent, taskId);
17200
+ if (result.acquired) {
17201
+ const lock = result.lock;
17202
+ if (attempt > 0) {
17203
+ emit("evidence_lock_stale_recovered", {
17204
+ directory,
17205
+ evidencePath,
17206
+ agent,
17207
+ taskId,
17208
+ attempt
17209
+ });
17210
+ }
17211
+ emit("evidence_lock_acquired", {
17212
+ directory,
17213
+ evidencePath,
17214
+ agent,
17215
+ taskId,
17216
+ attempt
17217
+ });
17218
+ try {
17219
+ return await fn();
17220
+ } finally {
17221
+ if (lock._release) {
17222
+ try {
17223
+ await lock._release();
17224
+ } catch {}
17225
+ }
17226
+ }
17227
+ }
17228
+ if (Date.now() >= deadline) {
17229
+ throw new EvidenceLockTimeoutError(directory, evidencePath, agent, taskId, timeoutMs);
17230
+ }
17231
+ emit("evidence_lock_contended", {
17232
+ directory,
17233
+ evidencePath,
17234
+ agent,
17235
+ taskId,
17236
+ attempt
17237
+ });
17238
+ const delay = Math.min(backoffMs(attempt), deadline - Date.now());
17239
+ if (delay > 0) {
17240
+ await new Promise((resolve4) => setTimeout(resolve4, delay));
17241
+ }
17242
+ attempt++;
17243
+ }
17244
+ }
17245
+ var EvidenceLockTimeoutError, BACKOFF_START_MS = 50, BACKOFF_MAX_MS = 2000, BACKOFF_JITTER_RATIO = 0.25;
17246
+ var init_lock = __esm(() => {
17247
+ init_file_locks();
17248
+ init_telemetry();
17249
+ EvidenceLockTimeoutError = class EvidenceLockTimeoutError extends Error {
17250
+ directory;
17251
+ evidencePath;
17252
+ agent;
17253
+ taskId;
17254
+ constructor(directory, evidencePath, agent, taskId, timeoutMs) {
17255
+ super(`Evidence lock timeout after ${timeoutMs}ms for ${evidencePath} (agent=${agent}, task=${taskId})`);
17256
+ this.name = "EvidenceLockTimeoutError";
17257
+ this.directory = directory;
17258
+ this.evidencePath = evidencePath;
17259
+ this.agent = agent;
17260
+ this.taskId = taskId;
17261
+ }
17262
+ };
17263
+ });
17264
+
17265
+ // src/validation/task-id.ts
17266
+ function checkUnsafeChars(taskId) {
17267
+ if (!taskId || taskId.length === 0) {
17268
+ return "Invalid task ID: empty string";
17269
+ }
17270
+ if (/\0/.test(taskId)) {
17271
+ return "Invalid task ID: contains null bytes";
17272
+ }
17273
+ for (let i = 0;i < taskId.length; i++) {
17274
+ if (taskId.charCodeAt(i) < 32) {
17275
+ return "Invalid task ID: contains control characters";
17276
+ }
17277
+ }
17278
+ if (taskId.includes("..") || taskId.includes("/") || taskId.includes("\\")) {
17279
+ return "Invalid task ID: path traversal detected";
17280
+ }
17281
+ return;
17282
+ }
17283
+ function sanitizeTaskId(taskId) {
17284
+ const unsafeMsg = checkUnsafeChars(taskId);
17285
+ if (unsafeMsg) {
17286
+ throw new Error(unsafeMsg);
17287
+ }
17288
+ if (STRICT_TASK_ID_PATTERN.test(taskId) || RETRO_TASK_ID_REGEX.test(taskId) || INTERNAL_TOOL_ID_REGEX.test(taskId) || GENERAL_TASK_ID_REGEX.test(taskId)) {
17289
+ return taskId;
17290
+ }
17291
+ throw new Error(`Invalid task ID: must be alphanumeric (ASCII) with optional hyphens, underscores, or dots, got "${taskId}"`);
17292
+ }
17293
+ var STRICT_TASK_ID_PATTERN, RETRO_TASK_ID_REGEX, INTERNAL_TOOL_ID_REGEX, GENERAL_TASK_ID_REGEX;
17294
+ var init_task_id = __esm(() => {
17295
+ STRICT_TASK_ID_PATTERN = /^\d+\.\d+(\.\d+)*$/;
17296
+ RETRO_TASK_ID_REGEX = /^retro-\d+$/;
17297
+ INTERNAL_TOOL_ID_REGEX = /^(?:sast_scan|quality_budget|syntax_check|placeholder_scan|sbom_generate|build|secretscan)$/;
17298
+ GENERAL_TASK_ID_REGEX = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
17299
+ });
17300
+
17301
+ // src/evidence/manager.ts
17302
+ import { mkdirSync as mkdirSync3, readdirSync as readdirSync3, rmSync, statSync as statSync3 } from "fs";
17303
+ import * as fs4 from "fs/promises";
17304
+ import * as path6 from "path";
17305
+ function isValidEvidenceType(type) {
17306
+ return VALID_EVIDENCE_TYPES.includes(type);
17307
+ }
17308
+ async function saveEvidence(directory, taskId, evidence) {
17309
+ const sanitizedTaskId = sanitizeTaskId2(taskId);
17310
+ const relativePath = path6.join("evidence", sanitizedTaskId, "evidence.json");
17311
+ validateSwarmPath(directory, relativePath);
17312
+ return withEvidenceLock(directory, relativePath, "evidence-manager", sanitizedTaskId, async () => {
17313
+ const evidencePath = validateSwarmPath(directory, relativePath);
17314
+ const evidenceDir = path6.dirname(evidencePath);
17315
+ let bundle;
17316
+ const existingContent = await readSwarmFileAsync(directory, relativePath);
17317
+ if (existingContent !== null) {
17318
+ try {
17319
+ const parsed = JSON.parse(existingContent);
17320
+ bundle = EvidenceBundleSchema.parse(parsed);
17321
+ } catch (error49) {
17322
+ warn(`Existing evidence bundle invalid for task ${sanitizedTaskId}, creating new: ${error49 instanceof Error ? error49.message : String(error49)}`);
17323
+ const now = new Date().toISOString();
17324
+ bundle = {
17325
+ schema_version: "1.0.0",
17326
+ task_id: sanitizedTaskId,
17327
+ entries: [],
17328
+ created_at: now,
17329
+ updated_at: now
17330
+ };
17331
+ }
17332
+ } else {
17333
+ const now = new Date().toISOString();
17334
+ bundle = {
17335
+ schema_version: "1.0.0",
17336
+ task_id: sanitizedTaskId,
17337
+ entries: [],
17338
+ created_at: now,
17339
+ updated_at: now
17340
+ };
17341
+ }
17342
+ const MAX_BUNDLE_ENTRIES = 100;
17343
+ let entries = [...bundle.entries, evidence];
17344
+ if (entries.length > MAX_BUNDLE_ENTRIES) {
17345
+ entries = entries.slice(entries.length - MAX_BUNDLE_ENTRIES);
17346
+ }
17347
+ const updatedBundle = {
17348
+ ...bundle,
17349
+ entries,
17350
+ updated_at: new Date().toISOString()
17351
+ };
17352
+ const bundleJson = JSON.stringify(updatedBundle);
17353
+ if (bundleJson.length > EVIDENCE_MAX_JSON_BYTES) {
17354
+ throw new Error(`Evidence bundle size (${bundleJson.length} bytes) exceeds maximum (${EVIDENCE_MAX_JSON_BYTES} bytes)`);
17355
+ }
17356
+ mkdirSync3(evidenceDir, { recursive: true });
17357
+ const tempPath = path6.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
17358
+ try {
17359
+ await Bun.write(tempPath, bundleJson);
17360
+ await fs4.rename(tempPath, evidencePath);
17361
+ } catch (error49) {
17362
+ try {
17363
+ rmSync(tempPath, { force: true });
17364
+ } catch {}
17365
+ throw error49;
17366
+ }
17367
+ return updatedBundle;
17368
+ });
17369
+ }
17370
+ function isFlatRetrospective(parsed) {
17371
+ return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) && parsed.type === "retrospective" && !parsed.schema_version;
17372
+ }
17373
+ function remapLegacyTaskComplexity(entry) {
17374
+ const taskComplexity = entry.task_complexity;
17375
+ if (typeof taskComplexity === "string" && taskComplexity in LEGACY_TASK_COMPLEXITY_MAP) {
17376
+ return {
17377
+ ...entry,
17378
+ task_complexity: LEGACY_TASK_COMPLEXITY_MAP[taskComplexity]
17379
+ };
17380
+ }
17381
+ return entry;
17382
+ }
17383
+ function wrapFlatRetrospective(flatEntry, taskId) {
17384
+ const now = new Date().toISOString();
17385
+ const remappedEntry = remapLegacyTaskComplexity(flatEntry);
17386
+ return {
17387
+ schema_version: "1.0.0",
17388
+ task_id: remappedEntry.task_id ?? taskId,
17389
+ created_at: remappedEntry.timestamp ?? now,
17390
+ updated_at: remappedEntry.timestamp ?? now,
17391
+ entries: [remappedEntry]
17392
+ };
17393
+ }
17394
+ async function loadEvidence(directory, taskId) {
17395
+ const sanitizedTaskId = sanitizeTaskId2(taskId);
17396
+ const relativePath = path6.join("evidence", sanitizedTaskId, "evidence.json");
17397
+ const evidencePath = validateSwarmPath(directory, relativePath);
17398
+ const content = await readSwarmFileAsync(directory, relativePath);
17399
+ if (content === null) {
17400
+ return { status: "not_found" };
17401
+ }
17402
+ let parsed;
17403
+ try {
17404
+ parsed = JSON.parse(content);
17405
+ } catch {
17406
+ return { status: "invalid_schema", errors: ["Invalid JSON"] };
17407
+ }
17408
+ if (isFlatRetrospective(parsed)) {
17409
+ const wrappedBundle = wrapFlatRetrospective(parsed, sanitizedTaskId);
17410
+ try {
17411
+ const validated = EvidenceBundleSchema.parse(wrappedBundle);
17412
+ try {
17413
+ await withEvidenceLock(directory, relativePath, "evidence-loader", sanitizedTaskId, async () => {
17414
+ const evidenceDir = path6.dirname(evidencePath);
17415
+ const bundleJson = JSON.stringify(validated);
17416
+ const tempPath = path6.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
17417
+ try {
17418
+ await Bun.write(tempPath, bundleJson);
17419
+ await fs4.rename(tempPath, evidencePath);
17420
+ } catch (writeError) {
17421
+ try {
17422
+ rmSync(tempPath, { force: true });
17423
+ } catch {}
17424
+ warn(`Failed to persist repaired flat retrospective for task ${sanitizedTaskId}: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
17425
+ }
17426
+ });
17427
+ } catch (lockErr) {
17428
+ warn(`Evidence lock failed during flat-retrospective write-back for task ${sanitizedTaskId}: ${lockErr instanceof Error ? lockErr.message : String(lockErr)}`);
17429
+ }
17430
+ return { status: "found", bundle: validated };
17431
+ } catch (error49) {
17432
+ warn(`Wrapped flat retrospective failed validation for task ${sanitizedTaskId}: ${error49 instanceof Error ? error49.message : String(error49)}`);
17433
+ const errors3 = error49 instanceof ZodError ? error49.issues.map((e) => `${e.path.join(".")}: ${e.message}`) : [error49 instanceof Error ? error49.message : String(error49)];
17434
+ return { status: "invalid_schema", errors: errors3 };
17435
+ }
17436
+ }
17437
+ try {
17438
+ const validated = EvidenceBundleSchema.parse(parsed);
17439
+ return { status: "found", bundle: validated };
17440
+ } catch (error49) {
17441
+ warn(`Evidence bundle validation failed for task ${sanitizedTaskId}: ${error49 instanceof Error ? error49.message : String(error49)}`);
17442
+ const errors3 = error49 instanceof ZodError ? error49.issues.map((e) => `${e.path.join(".")}: ${e.message}`) : [error49 instanceof Error ? error49.message : String(error49)];
17443
+ return { status: "invalid_schema", errors: errors3 };
17444
+ }
17445
+ }
17446
+ async function listEvidenceTaskIds(directory) {
17447
+ const evidenceBasePath = validateSwarmPath(directory, "evidence");
17448
+ try {
17449
+ statSync3(evidenceBasePath);
17450
+ } catch {
17451
+ return [];
17452
+ }
17453
+ let entries;
17454
+ try {
17455
+ entries = readdirSync3(evidenceBasePath);
17456
+ } catch {
17457
+ return [];
17458
+ }
17459
+ const taskIds = [];
17460
+ for (const entry of entries) {
17461
+ const entryPath = path6.join(evidenceBasePath, entry);
17462
+ try {
17463
+ const stats = statSync3(entryPath);
17464
+ if (!stats.isDirectory()) {
17465
+ continue;
17466
+ }
17467
+ sanitizeTaskId2(entry);
17468
+ taskIds.push(entry);
17469
+ } catch (error49) {
17470
+ if (error49 instanceof Error && !error49.message.startsWith("Invalid task ID")) {
17471
+ warn(`Error reading evidence entry '${entry}': ${error49.message}`);
17472
+ }
17473
+ }
17474
+ }
17475
+ return taskIds.sort();
17476
+ }
17477
+ async function deleteEvidence(directory, taskId) {
17478
+ const sanitizedTaskId = sanitizeTaskId2(taskId);
17479
+ const relativePath = path6.join("evidence", sanitizedTaskId);
17480
+ const evidenceDir = validateSwarmPath(directory, relativePath);
17481
+ try {
17482
+ statSync3(evidenceDir);
17483
+ } catch {
17484
+ return false;
17485
+ }
17486
+ try {
17487
+ rmSync(evidenceDir, { recursive: true, force: true });
17488
+ return true;
17489
+ } catch (error49) {
17490
+ warn(`Failed to delete evidence for task ${sanitizedTaskId}: ${error49 instanceof Error ? error49.message : String(error49)}`);
17491
+ return false;
17382
17492
  }
17383
- function unlockSync(file2, options) {
17384
- return toSync(lockfile.unlock)(file2, toSyncOptions(options));
17493
+ }
17494
+ async function checkRequirementCoverage(phase, directory) {
17495
+ const relativePath = path6.join("evidence", `req-coverage-phase-${phase}.json`);
17496
+ const absolutePath = path6.resolve(directory, ".swarm", relativePath);
17497
+ try {
17498
+ await fs4.access(absolutePath);
17499
+ return { exists: true, path: absolutePath };
17500
+ } catch {
17501
+ return { exists: false, path: absolutePath };
17385
17502
  }
17386
- function check2(file2, options) {
17387
- return toPromise(lockfile.check)(file2, options);
17503
+ }
17504
+ async function archiveEvidence(directory, maxAgeDays, maxBundles) {
17505
+ const taskIds = await listEvidenceTaskIds(directory);
17506
+ const cutoffDate = new Date;
17507
+ cutoffDate.setDate(cutoffDate.getDate() - maxAgeDays);
17508
+ const cutoffIso = cutoffDate.toISOString();
17509
+ const archived = [];
17510
+ const remainingBundles = [];
17511
+ for (const taskId of taskIds) {
17512
+ const result = await loadEvidence(directory, taskId);
17513
+ if (result.status !== "found") {
17514
+ continue;
17515
+ }
17516
+ if (result.bundle.updated_at < cutoffIso) {
17517
+ const deleted = await deleteEvidence(directory, taskId);
17518
+ if (deleted) {
17519
+ archived.push(taskId);
17520
+ }
17521
+ } else {
17522
+ remainingBundles.push({
17523
+ taskId,
17524
+ updatedAt: result.bundle.updated_at
17525
+ });
17526
+ }
17388
17527
  }
17389
- function checkSync(file2, options) {
17390
- return toSync(lockfile.check)(file2, toSyncOptions(options));
17528
+ if (maxBundles !== undefined && remainingBundles.length > maxBundles) {
17529
+ remainingBundles.sort((a, b) => a.updatedAt.localeCompare(b.updatedAt));
17530
+ const toDelete = remainingBundles.length - maxBundles;
17531
+ for (let i = 0;i < toDelete; i++) {
17532
+ const deleted = await deleteEvidence(directory, remainingBundles[i].taskId);
17533
+ if (deleted) {
17534
+ archived.push(remainingBundles[i].taskId);
17535
+ }
17536
+ }
17391
17537
  }
17392
- module.exports = lock;
17393
- module.exports.lock = lock;
17394
- module.exports.unlock = unlock;
17395
- module.exports.lockSync = lockSync;
17396
- module.exports.unlockSync = unlockSync;
17397
- module.exports.check = check2;
17398
- module.exports.checkSync = checkSync;
17538
+ return archived;
17539
+ }
17540
+ var VALID_EVIDENCE_TYPES, sanitizeTaskId2, LEGACY_TASK_COMPLEXITY_MAP;
17541
+ var init_manager2 = __esm(() => {
17542
+ init_zod();
17543
+ init_evidence_schema();
17544
+ init_utils2();
17545
+ init_utils();
17546
+ init_lock();
17547
+ init_task_id();
17548
+ VALID_EVIDENCE_TYPES = [
17549
+ "review",
17550
+ "test",
17551
+ "diff",
17552
+ "approval",
17553
+ "note",
17554
+ "retrospective",
17555
+ "syntax",
17556
+ "placeholder",
17557
+ "sast",
17558
+ "sbom",
17559
+ "build",
17560
+ "quality_budget",
17561
+ "secretscan"
17562
+ ];
17563
+ sanitizeTaskId2 = sanitizeTaskId;
17564
+ LEGACY_TASK_COMPLEXITY_MAP = {
17565
+ low: "simple",
17566
+ medium: "moderate",
17567
+ high: "complex"
17568
+ };
17399
17569
  });
17400
17570
 
17401
17571
  // src/services/config-doctor.ts
@@ -17412,15 +17582,15 @@ __export(exports_config_doctor, {
17412
17582
  applySafeAutoFixes: () => applySafeAutoFixes
17413
17583
  });
17414
17584
  import * as crypto3 from "crypto";
17415
- import * as fs8 from "fs";
17416
- import * as os4 from "os";
17417
- import * as path17 from "path";
17585
+ import * as fs9 from "fs";
17586
+ import * as os5 from "os";
17587
+ import * as path18 from "path";
17418
17588
  function getUserConfigDir3() {
17419
- return process.env.XDG_CONFIG_HOME || path17.join(os4.homedir(), ".config");
17589
+ return process.env.XDG_CONFIG_HOME || path18.join(os5.homedir(), ".config");
17420
17590
  }
17421
17591
  function getConfigPaths(directory) {
17422
- const userConfigPath = path17.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
17423
- const projectConfigPath = path17.join(directory, ".opencode", "opencode-swarm.json");
17592
+ const userConfigPath = path18.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
17593
+ const projectConfigPath = path18.join(directory, ".opencode", "opencode-swarm.json");
17424
17594
  return { userConfigPath, projectConfigPath };
17425
17595
  }
17426
17596
  function computeHash(content) {
@@ -17445,9 +17615,9 @@ function isValidConfigPath(configPath, directory) {
17445
17615
  const normalizedUser = userConfigPath.replace(/\\/g, "/");
17446
17616
  const normalizedProject = projectConfigPath.replace(/\\/g, "/");
17447
17617
  try {
17448
- const resolvedConfig = path17.resolve(configPath);
17449
- const resolvedUser = path17.resolve(normalizedUser);
17450
- const resolvedProject = path17.resolve(normalizedProject);
17618
+ const resolvedConfig = path18.resolve(configPath);
17619
+ const resolvedUser = path18.resolve(normalizedUser);
17620
+ const resolvedProject = path18.resolve(normalizedProject);
17451
17621
  return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
17452
17622
  } catch {
17453
17623
  return false;
@@ -17457,19 +17627,19 @@ function createConfigBackup(directory) {
17457
17627
  const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
17458
17628
  let configPath = projectConfigPath;
17459
17629
  let content = null;
17460
- if (fs8.existsSync(projectConfigPath)) {
17630
+ if (fs9.existsSync(projectConfigPath)) {
17461
17631
  try {
17462
- content = fs8.readFileSync(projectConfigPath, "utf-8");
17632
+ content = fs9.readFileSync(projectConfigPath, "utf-8");
17463
17633
  } catch (error93) {
17464
17634
  log("[ConfigDoctor] project config read failed", {
17465
17635
  error: error93 instanceof Error ? error93.message : String(error93)
17466
17636
  });
17467
17637
  }
17468
17638
  }
17469
- if (content === null && fs8.existsSync(userConfigPath)) {
17639
+ if (content === null && fs9.existsSync(userConfigPath)) {
17470
17640
  configPath = userConfigPath;
17471
17641
  try {
17472
- content = fs8.readFileSync(userConfigPath, "utf-8");
17642
+ content = fs9.readFileSync(userConfigPath, "utf-8");
17473
17643
  } catch (error93) {
17474
17644
  log("[ConfigDoctor] user config read failed", {
17475
17645
  error: error93 instanceof Error ? error93.message : String(error93)
@@ -17487,12 +17657,12 @@ function createConfigBackup(directory) {
17487
17657
  };
17488
17658
  }
17489
17659
  function writeBackupArtifact(directory, backup) {
17490
- const swarmDir = path17.join(directory, ".swarm");
17491
- if (!fs8.existsSync(swarmDir)) {
17492
- fs8.mkdirSync(swarmDir, { recursive: true });
17660
+ const swarmDir = path18.join(directory, ".swarm");
17661
+ if (!fs9.existsSync(swarmDir)) {
17662
+ fs9.mkdirSync(swarmDir, { recursive: true });
17493
17663
  }
17494
17664
  const backupFilename = `config-backup-${backup.createdAt}.json`;
17495
- const backupPath = path17.join(swarmDir, backupFilename);
17665
+ const backupPath = path18.join(swarmDir, backupFilename);
17496
17666
  const artifact = {
17497
17667
  createdAt: backup.createdAt,
17498
17668
  configPath: backup.configPath,
@@ -17500,15 +17670,15 @@ function writeBackupArtifact(directory, backup) {
17500
17670
  content: backup.content,
17501
17671
  preview: backup.content.substring(0, 500) + (backup.content.length > 500 ? "..." : "")
17502
17672
  };
17503
- fs8.writeFileSync(backupPath, JSON.stringify(artifact, null, 2), "utf-8");
17673
+ fs9.writeFileSync(backupPath, JSON.stringify(artifact, null, 2), "utf-8");
17504
17674
  return backupPath;
17505
17675
  }
17506
17676
  function restoreFromBackup(backupPath, directory) {
17507
- if (!fs8.existsSync(backupPath)) {
17677
+ if (!fs9.existsSync(backupPath)) {
17508
17678
  return null;
17509
17679
  }
17510
17680
  try {
17511
- const artifact = JSON.parse(fs8.readFileSync(backupPath, "utf-8"));
17681
+ const artifact = JSON.parse(fs9.readFileSync(backupPath, "utf-8"));
17512
17682
  if (!artifact.content || !artifact.configPath || !artifact.contentHash) {
17513
17683
  return null;
17514
17684
  }
@@ -17522,11 +17692,11 @@ function restoreFromBackup(backupPath, directory) {
17522
17692
  return null;
17523
17693
  }
17524
17694
  const targetPath = artifact.configPath;
17525
- const targetDir = path17.dirname(targetPath);
17526
- if (!fs8.existsSync(targetDir)) {
17527
- fs8.mkdirSync(targetDir, { recursive: true });
17695
+ const targetDir = path18.dirname(targetPath);
17696
+ if (!fs9.existsSync(targetDir)) {
17697
+ fs9.mkdirSync(targetDir, { recursive: true });
17528
17698
  }
17529
- fs8.writeFileSync(targetPath, artifact.content, "utf-8");
17699
+ fs9.writeFileSync(targetPath, artifact.content, "utf-8");
17530
17700
  return targetPath;
17531
17701
  } catch {
17532
17702
  return null;
@@ -17536,12 +17706,12 @@ function readConfigFromFile(directory) {
17536
17706
  const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
17537
17707
  let configPath = projectConfigPath;
17538
17708
  let configContent = null;
17539
- if (fs8.existsSync(projectConfigPath)) {
17709
+ if (fs9.existsSync(projectConfigPath)) {
17540
17710
  configPath = projectConfigPath;
17541
- configContent = fs8.readFileSync(projectConfigPath, "utf-8");
17542
- } else if (fs8.existsSync(userConfigPath)) {
17711
+ configContent = fs9.readFileSync(projectConfigPath, "utf-8");
17712
+ } else if (fs9.existsSync(userConfigPath)) {
17543
17713
  configPath = userConfigPath;
17544
- configContent = fs8.readFileSync(userConfigPath, "utf-8");
17714
+ configContent = fs9.readFileSync(userConfigPath, "utf-8");
17545
17715
  }
17546
17716
  if (configContent === null) {
17547
17717
  return null;
@@ -17553,9 +17723,9 @@ function readConfigFromFile(directory) {
17553
17723
  return null;
17554
17724
  }
17555
17725
  }
17556
- function validateConfigKey(path18, value, _config) {
17726
+ function validateConfigKey(path19, value, _config) {
17557
17727
  const findings = [];
17558
- switch (path18) {
17728
+ switch (path19) {
17559
17729
  case "agents": {
17560
17730
  if (value !== undefined) {
17561
17731
  findings.push({
@@ -17802,27 +17972,27 @@ function validateConfigKey(path18, value, _config) {
17802
17972
  }
17803
17973
  return findings;
17804
17974
  }
17805
- function walkConfigAndValidate(obj, path18, config3, findings) {
17975
+ function walkConfigAndValidate(obj, path19, config3, findings) {
17806
17976
  if (obj === null || obj === undefined) {
17807
17977
  return;
17808
17978
  }
17809
- if (path18 && typeof obj === "object" && !Array.isArray(obj)) {
17810
- const keyFindings = validateConfigKey(path18, obj, config3);
17979
+ if (path19 && typeof obj === "object" && !Array.isArray(obj)) {
17980
+ const keyFindings = validateConfigKey(path19, obj, config3);
17811
17981
  findings.push(...keyFindings);
17812
17982
  }
17813
17983
  if (typeof obj !== "object") {
17814
- const keyFindings = validateConfigKey(path18, obj, config3);
17984
+ const keyFindings = validateConfigKey(path19, obj, config3);
17815
17985
  findings.push(...keyFindings);
17816
17986
  return;
17817
17987
  }
17818
17988
  if (Array.isArray(obj)) {
17819
17989
  obj.forEach((item, index) => {
17820
- walkConfigAndValidate(item, `${path18}[${index}]`, config3, findings);
17990
+ walkConfigAndValidate(item, `${path19}[${index}]`, config3, findings);
17821
17991
  });
17822
17992
  return;
17823
17993
  }
17824
17994
  for (const [key, value] of Object.entries(obj)) {
17825
- const newPath = path18 ? `${path18}.${key}` : key;
17995
+ const newPath = path19 ? `${path19}.${key}` : key;
17826
17996
  walkConfigAndValidate(value, newPath, config3, findings);
17827
17997
  }
17828
17998
  }
@@ -17837,9 +18007,9 @@ function runConfigDoctor(config3, directory) {
17837
18007
  const hasAutoFixableIssues = findings.some((f) => f.autoFixable && f.proposedFix?.risk === "low");
17838
18008
  const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
17839
18009
  let configSource = "defaults";
17840
- if (fs8.existsSync(projectConfigPath)) {
18010
+ if (fs9.existsSync(projectConfigPath)) {
17841
18011
  configSource = projectConfigPath;
17842
- } else if (fs8.existsSync(userConfigPath)) {
18012
+ } else if (fs9.existsSync(userConfigPath)) {
17843
18013
  configSource = userConfigPath;
17844
18014
  }
17845
18015
  return {
@@ -17868,12 +18038,12 @@ function applySafeAutoFixes(directory, result) {
17868
18038
  const { userConfigPath, projectConfigPath } = getConfigPaths(directory);
17869
18039
  let configPath = projectConfigPath;
17870
18040
  let configContent;
17871
- if (fs8.existsSync(projectConfigPath)) {
18041
+ if (fs9.existsSync(projectConfigPath)) {
17872
18042
  configPath = projectConfigPath;
17873
- configContent = fs8.readFileSync(projectConfigPath, "utf-8");
17874
- } else if (fs8.existsSync(userConfigPath)) {
18043
+ configContent = fs9.readFileSync(projectConfigPath, "utf-8");
18044
+ } else if (fs9.existsSync(userConfigPath)) {
17875
18045
  configPath = userConfigPath;
17876
- configContent = fs8.readFileSync(userConfigPath, "utf-8");
18046
+ configContent = fs9.readFileSync(userConfigPath, "utf-8");
17877
18047
  } else {
17878
18048
  return { appliedFixes, updatedConfigPath: null };
17879
18049
  }
@@ -17942,22 +18112,22 @@ function applySafeAutoFixes(directory, result) {
17942
18112
  }
17943
18113
  }
17944
18114
  if (appliedFixes.length > 0) {
17945
- const configDir = path17.dirname(configPath);
17946
- if (!fs8.existsSync(configDir)) {
17947
- fs8.mkdirSync(configDir, { recursive: true });
18115
+ const configDir = path18.dirname(configPath);
18116
+ if (!fs9.existsSync(configDir)) {
18117
+ fs9.mkdirSync(configDir, { recursive: true });
17948
18118
  }
17949
- fs8.writeFileSync(configPath, JSON.stringify(config3, null, 2), "utf-8");
18119
+ fs9.writeFileSync(configPath, JSON.stringify(config3, null, 2), "utf-8");
17950
18120
  updatedConfigPath = configPath;
17951
18121
  }
17952
18122
  return { appliedFixes, updatedConfigPath };
17953
18123
  }
17954
18124
  function writeDoctorArtifact(directory, result) {
17955
- const swarmDir = path17.join(directory, ".swarm");
17956
- if (!fs8.existsSync(swarmDir)) {
17957
- fs8.mkdirSync(swarmDir, { recursive: true });
18125
+ const swarmDir = path18.join(directory, ".swarm");
18126
+ if (!fs9.existsSync(swarmDir)) {
18127
+ fs9.mkdirSync(swarmDir, { recursive: true });
17958
18128
  }
17959
18129
  const artifactFilename = "config-doctor.json";
17960
- const artifactPath = path17.join(swarmDir, artifactFilename);
18130
+ const artifactPath = path18.join(swarmDir, artifactFilename);
17961
18131
  const guiOutput = {
17962
18132
  timestamp: result.timestamp,
17963
18133
  summary: result.summary,
@@ -17978,7 +18148,7 @@ function writeDoctorArtifact(directory, result) {
17978
18148
  } : null
17979
18149
  }))
17980
18150
  };
17981
- fs8.writeFileSync(artifactPath, JSON.stringify(guiOutput, null, 2), "utf-8");
18151
+ fs9.writeFileSync(artifactPath, JSON.stringify(guiOutput, null, 2), "utf-8");
17982
18152
  return artifactPath;
17983
18153
  }
17984
18154
  function shouldRunOnStartup(automationConfig) {
@@ -18318,9 +18488,9 @@ var init_evidence_summary_service = __esm(() => {
18318
18488
  });
18319
18489
 
18320
18490
  // src/cli/index.ts
18321
- import * as fs22 from "fs";
18322
- import * as os6 from "os";
18323
- import * as path32 from "path";
18491
+ import * as fs23 from "fs";
18492
+ import * as os7 from "os";
18493
+ import * as path33 from "path";
18324
18494
 
18325
18495
  // src/commands/acknowledge-spec-drift.ts
18326
18496
  init_utils2();
@@ -18456,7 +18626,7 @@ async function handleAnalyzeCommand(_directory, args) {
18456
18626
 
18457
18627
  // src/config/loader.ts
18458
18628
  import * as fs2 from "fs";
18459
- import * as os from "os";
18629
+ import * as os2 from "os";
18460
18630
  import * as path4 from "path";
18461
18631
 
18462
18632
  // src/config/schema.ts
@@ -19241,6 +19411,11 @@ var CouncilConfigSchema = exports_external.object({
19241
19411
  requireAllMembers: exports_external.boolean().default(false).describe("When true, convene_council rejects if fewer than 5 member verdicts are provided."),
19242
19412
  escalateOnMaxRounds: exports_external.string().optional().describe("Optional webhook URL or handler name invoked when maxRounds is reached without APPROVE. Declared for forward compatibility; no behavior is implemented yet.")
19243
19413
  }).strict();
19414
+ var ParallelizationConfigSchema = exports_external.object({
19415
+ enabled: exports_external.boolean().default(false),
19416
+ maxConcurrentTasks: exports_external.number().int().min(1).max(64).default(1),
19417
+ evidenceLockTimeoutMs: exports_external.number().int().min(1000).max(300000).default(60000)
19418
+ });
19244
19419
  var PluginConfigSchema = exports_external.object({
19245
19420
  agents: exports_external.record(exports_external.string(), AgentOverrideConfigSchema).optional(),
19246
19421
  swarms: exports_external.record(exports_external.string(), SwarmConfigSchema).optional(),
@@ -19289,6 +19464,7 @@ var PluginConfigSchema = exports_external.object({
19289
19464
  incremental_verify: IncrementalVerifyConfigSchema.optional(),
19290
19465
  compaction_service: CompactionConfigSchema.optional(),
19291
19466
  council: CouncilConfigSchema.optional(),
19467
+ parallelization: ParallelizationConfigSchema.optional(),
19292
19468
  turbo_mode: exports_external.boolean().default(false).optional(),
19293
19469
  full_auto: exports_external.object({
19294
19470
  enabled: exports_external.boolean().default(false),
@@ -19308,7 +19484,7 @@ var PluginConfigSchema = exports_external.object({
19308
19484
  var CONFIG_FILENAME = "opencode-swarm.json";
19309
19485
  var MAX_CONFIG_FILE_BYTES = 102400;
19310
19486
  function getUserConfigDir() {
19311
- return process.env.XDG_CONFIG_HOME || path4.join(os.homedir(), ".config");
19487
+ return process.env.XDG_CONFIG_HOME || path4.join(os2.homedir(), ".config");
19312
19488
  }
19313
19489
  function loadRawConfigFromPath(configPath) {
19314
19490
  try {
@@ -19496,8 +19672,8 @@ import { createHash as createHash3 } from "crypto";
19496
19672
 
19497
19673
  // src/db/project-db.ts
19498
19674
  import { Database } from "bun:sqlite";
19499
- import { existsSync as existsSync4, mkdirSync as mkdirSync3 } from "fs";
19500
- import { join as join6, resolve as resolve4 } from "path";
19675
+ import { existsSync as existsSync5, mkdirSync as mkdirSync4 } from "fs";
19676
+ import { join as join7, resolve as resolve5 } from "path";
19501
19677
  var MIGRATIONS = [
19502
19678
  {
19503
19679
  version: 1,
@@ -19556,19 +19732,19 @@ function runProjectMigrations(db) {
19556
19732
  }
19557
19733
  }
19558
19734
  function projectDbPath(directory) {
19559
- return join6(resolve4(directory), ".swarm", "swarm.db");
19735
+ return join7(resolve5(directory), ".swarm", "swarm.db");
19560
19736
  }
19561
19737
  function projectDbExists(directory) {
19562
- return existsSync4(projectDbPath(directory));
19738
+ return existsSync5(projectDbPath(directory));
19563
19739
  }
19564
19740
  function getProjectDb(directory) {
19565
- const key = resolve4(directory);
19741
+ const key = resolve5(directory);
19566
19742
  const existing = _projectDbs.get(key);
19567
19743
  if (existing)
19568
19744
  return existing;
19569
- const swarmDir = join6(key, ".swarm");
19570
- mkdirSync3(swarmDir, { recursive: true });
19571
- const db = new Database(join6(swarmDir, "swarm.db"));
19745
+ const swarmDir = join7(key, ".swarm");
19746
+ mkdirSync4(swarmDir, { recursive: true });
19747
+ const db = new Database(join7(swarmDir, "swarm.db"));
19572
19748
  db.run("PRAGMA journal_mode = WAL;");
19573
19749
  db.run("PRAGMA synchronous = NORMAL;");
19574
19750
  db.run("PRAGMA busy_timeout = 5000;");
@@ -20002,9 +20178,9 @@ var warnedAgents = new Set;
20002
20178
  init_manager();
20003
20179
 
20004
20180
  // src/scope/scope-persistence.ts
20005
- var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
20006
- import * as fs4 from "fs";
20007
- import * as path6 from "path";
20181
+ var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
20182
+ import * as fs5 from "fs";
20183
+ import * as path7 from "path";
20008
20184
  var DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;
20009
20185
  var LOCK_STALE_MS = 30 * 1000;
20010
20186
  var SCOPES_DIR = ".swarm/scopes";
@@ -20035,11 +20211,11 @@ var WINDOWS_RESERVED = new Set([
20035
20211
  "LPT9"
20036
20212
  ]);
20037
20213
  function getScopesDir(directory) {
20038
- return path6.join(directory, SCOPES_DIR);
20214
+ return path7.join(directory, SCOPES_DIR);
20039
20215
  }
20040
20216
  function clearAllScopes(directory) {
20041
20217
  try {
20042
- fs4.rmSync(getScopesDir(directory), { recursive: true, force: true });
20218
+ fs5.rmSync(getScopesDir(directory), { recursive: true, force: true });
20043
20219
  } catch {}
20044
20220
  }
20045
20221
 
@@ -20138,23 +20314,48 @@ function clearPendingCoderScope() {
20138
20314
 
20139
20315
  // src/state.ts
20140
20316
  init_manager();
20317
+
20318
+ // src/state/agent-run-context.ts
20319
+ class AgentRunContext {
20320
+ runId;
20321
+ activeToolCalls;
20322
+ activeAgent;
20323
+ delegationChains;
20324
+ agentSessions;
20325
+ environmentProfiles;
20326
+ toolAggregates;
20327
+ constructor(runId, toolAggregates) {
20328
+ this.runId = runId;
20329
+ this.activeToolCalls = new Map;
20330
+ this.activeAgent = new Map;
20331
+ this.delegationChains = new Map;
20332
+ this.agentSessions = new Map;
20333
+ this.environmentProfiles = new Map;
20334
+ this.toolAggregates = toolAggregates;
20335
+ }
20336
+ }
20337
+
20338
+ // src/state.ts
20141
20339
  init_telemetry();
20142
20340
  var _rehydrationCache = null;
20143
20341
  var _councilDisagreementWarned = new Set;
20342
+ var _toolAggregates = new Map;
20343
+ var defaultRunContext = new AgentRunContext("default", _toolAggregates);
20344
+ var _runContexts = new Map;
20144
20345
  var swarmState = {
20145
- activeToolCalls: new Map,
20146
- toolAggregates: new Map,
20147
- activeAgent: new Map,
20148
- delegationChains: new Map,
20346
+ activeToolCalls: defaultRunContext.activeToolCalls,
20347
+ toolAggregates: defaultRunContext.toolAggregates,
20348
+ activeAgent: defaultRunContext.activeAgent,
20349
+ delegationChains: defaultRunContext.delegationChains,
20149
20350
  pendingEvents: 0,
20150
20351
  opencodeClient: null,
20151
20352
  curatorInitAgentNames: [],
20152
20353
  curatorPhaseAgentNames: [],
20153
20354
  lastBudgetPct: 0,
20154
- agentSessions: new Map,
20355
+ agentSessions: defaultRunContext.agentSessions,
20155
20356
  pendingRehydrations: new Set,
20156
20357
  fullAutoEnabledInConfig: false,
20157
- environmentProfiles: new Map
20358
+ environmentProfiles: defaultRunContext.environmentProfiles
20158
20359
  };
20159
20360
  function resetSwarmState() {
20160
20361
  swarmState.activeToolCalls.clear();
@@ -20532,8 +20733,8 @@ init_zod();
20532
20733
 
20533
20734
  // src/tools/checkpoint.ts
20534
20735
  import * as child_process from "child_process";
20535
- import * as fs5 from "fs";
20536
- import * as path7 from "path";
20736
+ import * as fs6 from "fs";
20737
+ import * as path8 from "path";
20537
20738
 
20538
20739
  // node_modules/@opencode-ai/plugin/node_modules/zod/v4/classic/external.js
20539
20740
  var exports_external2 = {};
@@ -21264,10 +21465,10 @@ function mergeDefs2(...defs) {
21264
21465
  function cloneDef2(schema) {
21265
21466
  return mergeDefs2(schema._zod.def);
21266
21467
  }
21267
- function getElementAtPath2(obj, path7) {
21268
- if (!path7)
21468
+ function getElementAtPath2(obj, path8) {
21469
+ if (!path8)
21269
21470
  return obj;
21270
- return path7.reduce((acc, key) => acc?.[key], obj);
21471
+ return path8.reduce((acc, key) => acc?.[key], obj);
21271
21472
  }
21272
21473
  function promiseAllObject2(promisesObj) {
21273
21474
  const keys = Object.keys(promisesObj);
@@ -21626,11 +21827,11 @@ function aborted2(x, startIndex = 0) {
21626
21827
  }
21627
21828
  return false;
21628
21829
  }
21629
- function prefixIssues2(path7, issues) {
21830
+ function prefixIssues2(path8, issues) {
21630
21831
  return issues.map((iss) => {
21631
21832
  var _a2;
21632
21833
  (_a2 = iss).path ?? (_a2.path = []);
21633
- iss.path.unshift(path7);
21834
+ iss.path.unshift(path8);
21634
21835
  return iss;
21635
21836
  });
21636
21837
  }
@@ -21798,7 +21999,7 @@ function treeifyError2(error49, _mapper) {
21798
21999
  return issue3.message;
21799
22000
  };
21800
22001
  const result = { errors: [] };
21801
- const processError = (error50, path7 = []) => {
22002
+ const processError = (error50, path8 = []) => {
21802
22003
  var _a2, _b;
21803
22004
  for (const issue3 of error50.issues) {
21804
22005
  if (issue3.code === "invalid_union" && issue3.errors.length) {
@@ -21808,7 +22009,7 @@ function treeifyError2(error49, _mapper) {
21808
22009
  } else if (issue3.code === "invalid_element") {
21809
22010
  processError({ issues: issue3.issues }, issue3.path);
21810
22011
  } else {
21811
- const fullpath = [...path7, ...issue3.path];
22012
+ const fullpath = [...path8, ...issue3.path];
21812
22013
  if (fullpath.length === 0) {
21813
22014
  result.errors.push(mapper(issue3));
21814
22015
  continue;
@@ -21840,8 +22041,8 @@ function treeifyError2(error49, _mapper) {
21840
22041
  }
21841
22042
  function toDotPath2(_path) {
21842
22043
  const segs = [];
21843
- const path7 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
21844
- for (const seg of path7) {
22044
+ const path8 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
22045
+ for (const seg of path8) {
21845
22046
  if (typeof seg === "number")
21846
22047
  segs.push(`[${seg}]`);
21847
22048
  else if (typeof seg === "symbol")
@@ -32938,13 +33139,13 @@ function validateLabel(label) {
32938
33139
  return null;
32939
33140
  }
32940
33141
  function getCheckpointLogPath(directory) {
32941
- return path7.join(directory, CHECKPOINT_LOG_PATH);
33142
+ return path8.join(directory, CHECKPOINT_LOG_PATH);
32942
33143
  }
32943
33144
  function readCheckpointLog(directory) {
32944
33145
  const logPath = getCheckpointLogPath(directory);
32945
33146
  try {
32946
- if (fs5.existsSync(logPath)) {
32947
- const content = fs5.readFileSync(logPath, "utf-8");
33147
+ if (fs6.existsSync(logPath)) {
33148
+ const content = fs6.readFileSync(logPath, "utf-8");
32948
33149
  const parsed = JSON.parse(content);
32949
33150
  if (!parsed.checkpoints || !Array.isArray(parsed.checkpoints)) {
32950
33151
  return { version: 1, checkpoints: [] };
@@ -32956,13 +33157,13 @@ function readCheckpointLog(directory) {
32956
33157
  }
32957
33158
  function writeCheckpointLog(log2, directory) {
32958
33159
  const logPath = getCheckpointLogPath(directory);
32959
- const dir = path7.dirname(logPath);
32960
- if (!fs5.existsSync(dir)) {
32961
- fs5.mkdirSync(dir, { recursive: true });
33160
+ const dir = path8.dirname(logPath);
33161
+ if (!fs6.existsSync(dir)) {
33162
+ fs6.mkdirSync(dir, { recursive: true });
32962
33163
  }
32963
33164
  const tempPath = `${logPath}.tmp`;
32964
- fs5.writeFileSync(tempPath, JSON.stringify(log2, null, 2), "utf-8");
32965
- fs5.renameSync(tempPath, logPath);
33165
+ fs6.writeFileSync(tempPath, JSON.stringify(log2, null, 2), "utf-8");
33166
+ fs6.renameSync(tempPath, logPath);
32966
33167
  }
32967
33168
  function gitExec(args) {
32968
33169
  const result = child_process.spawnSync("git", args, {
@@ -33296,8 +33497,8 @@ async function handleClarifyCommand(_directory, args) {
33296
33497
 
33297
33498
  // src/commands/close.ts
33298
33499
  import { execFileSync } from "child_process";
33299
- import { promises as fs7 } from "fs";
33300
- import path12 from "path";
33500
+ import { promises as fs8 } from "fs";
33501
+ import path13 from "path";
33301
33502
  init_manager2();
33302
33503
 
33303
33504
  // src/git/branch.ts
@@ -33347,36 +33548,36 @@ function hasUncommittedChanges(cwd) {
33347
33548
  }
33348
33549
 
33349
33550
  // src/hooks/knowledge-store.ts
33350
- var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
33351
- import { existsSync as existsSync6 } from "fs";
33551
+ var import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
33552
+ import { existsSync as existsSync7 } from "fs";
33352
33553
  import { appendFile as appendFile2, mkdir, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
33353
- import * as os2 from "os";
33354
- import * as path8 from "path";
33554
+ import * as os3 from "os";
33555
+ import * as path9 from "path";
33355
33556
  function resolveSwarmKnowledgePath(directory) {
33356
- return path8.join(directory, ".swarm", "knowledge.jsonl");
33557
+ return path9.join(directory, ".swarm", "knowledge.jsonl");
33357
33558
  }
33358
33559
  function resolveSwarmRejectedPath(directory) {
33359
- return path8.join(directory, ".swarm", "knowledge-rejected.jsonl");
33560
+ return path9.join(directory, ".swarm", "knowledge-rejected.jsonl");
33360
33561
  }
33361
33562
  function resolveHiveKnowledgePath() {
33362
33563
  const platform = process.platform;
33363
- const home = os2.homedir();
33564
+ const home = os3.homedir();
33364
33565
  let dataDir;
33365
33566
  if (platform === "win32") {
33366
- dataDir = path8.join(process.env.LOCALAPPDATA || path8.join(home, "AppData", "Local"), "opencode-swarm", "Data");
33567
+ dataDir = path9.join(process.env.LOCALAPPDATA || path9.join(home, "AppData", "Local"), "opencode-swarm", "Data");
33367
33568
  } else if (platform === "darwin") {
33368
- dataDir = path8.join(home, "Library", "Application Support", "opencode-swarm");
33569
+ dataDir = path9.join(home, "Library", "Application Support", "opencode-swarm");
33369
33570
  } else {
33370
- dataDir = path8.join(process.env.XDG_DATA_HOME || path8.join(home, ".local", "share"), "opencode-swarm");
33571
+ dataDir = path9.join(process.env.XDG_DATA_HOME || path9.join(home, ".local", "share"), "opencode-swarm");
33371
33572
  }
33372
- return path8.join(dataDir, "shared-learnings.jsonl");
33573
+ return path9.join(dataDir, "shared-learnings.jsonl");
33373
33574
  }
33374
33575
  function resolveHiveRejectedPath() {
33375
33576
  const hivePath = resolveHiveKnowledgePath();
33376
- return path8.join(path8.dirname(hivePath), "shared-learnings-rejected.jsonl");
33577
+ return path9.join(path9.dirname(hivePath), "shared-learnings-rejected.jsonl");
33377
33578
  }
33378
33579
  async function readKnowledge(filePath) {
33379
- if (!existsSync6(filePath))
33580
+ if (!existsSync7(filePath))
33380
33581
  return [];
33381
33582
  const content = await readFile2(filePath, "utf-8");
33382
33583
  const results = [];
@@ -33397,16 +33598,16 @@ async function readRejectedLessons(directory) {
33397
33598
  return readKnowledge(resolveSwarmRejectedPath(directory));
33398
33599
  }
33399
33600
  async function appendKnowledge(filePath, entry) {
33400
- await mkdir(path8.dirname(filePath), { recursive: true });
33601
+ await mkdir(path9.dirname(filePath), { recursive: true });
33401
33602
  await appendFile2(filePath, `${JSON.stringify(entry)}
33402
33603
  `, "utf-8");
33403
33604
  }
33404
33605
  async function rewriteKnowledge(filePath, entries) {
33405
- const dir = path8.dirname(filePath);
33606
+ const dir = path9.dirname(filePath);
33406
33607
  await mkdir(dir, { recursive: true });
33407
33608
  let release = null;
33408
33609
  try {
33409
- release = await import_proper_lockfile2.default.lock(dir, {
33610
+ release = await import_proper_lockfile3.default.lock(dir, {
33410
33611
  retries: { retries: 5, minTimeout: 100, maxTimeout: 500 },
33411
33612
  stale: 5000
33412
33613
  });
@@ -33511,9 +33712,9 @@ function inferTags(lesson) {
33511
33712
  }
33512
33713
 
33513
33714
  // src/hooks/knowledge-validator.ts
33514
- var import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
33715
+ var import_proper_lockfile4 = __toESM(require_proper_lockfile(), 1);
33515
33716
  import { appendFile as appendFile3, mkdir as mkdir2, writeFile as writeFile3 } from "fs/promises";
33516
- import * as path9 from "path";
33717
+ import * as path10 from "path";
33517
33718
  var DANGEROUS_COMMAND_PATTERNS = [
33518
33719
  /\brm\s+-rf\b/,
33519
33720
  /\bsudo\s+rm\b/,
@@ -33768,14 +33969,14 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
33768
33969
  return;
33769
33970
  }
33770
33971
  const sanitizedReason = reason.slice(0, 500).replace(/[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f\x0d]/g, "");
33771
- const knowledgePath = path9.join(directory, ".swarm", "knowledge.jsonl");
33772
- const quarantinePath = path9.join(directory, ".swarm", "knowledge-quarantined.jsonl");
33773
- const rejectedPath = path9.join(directory, ".swarm", "knowledge-rejected.jsonl");
33774
- const swarmDir = path9.join(directory, ".swarm");
33972
+ const knowledgePath = path10.join(directory, ".swarm", "knowledge.jsonl");
33973
+ const quarantinePath = path10.join(directory, ".swarm", "knowledge-quarantined.jsonl");
33974
+ const rejectedPath = path10.join(directory, ".swarm", "knowledge-rejected.jsonl");
33975
+ const swarmDir = path10.join(directory, ".swarm");
33775
33976
  await mkdir2(swarmDir, { recursive: true });
33776
33977
  let release;
33777
33978
  try {
33778
- release = await import_proper_lockfile3.default.lock(swarmDir, {
33979
+ release = await import_proper_lockfile4.default.lock(swarmDir, {
33779
33980
  retries: { retries: 3, minTimeout: 100 }
33780
33981
  });
33781
33982
  const entries = await readKnowledge(knowledgePath);
@@ -33828,14 +34029,14 @@ async function restoreEntry(directory, entryId) {
33828
34029
  console.warn("[knowledge-validator] restoreEntry: invalid entryId rejected");
33829
34030
  return;
33830
34031
  }
33831
- const knowledgePath = path9.join(directory, ".swarm", "knowledge.jsonl");
33832
- const quarantinePath = path9.join(directory, ".swarm", "knowledge-quarantined.jsonl");
33833
- const rejectedPath = path9.join(directory, ".swarm", "knowledge-rejected.jsonl");
33834
- const swarmDir = path9.join(directory, ".swarm");
34032
+ const knowledgePath = path10.join(directory, ".swarm", "knowledge.jsonl");
34033
+ const quarantinePath = path10.join(directory, ".swarm", "knowledge-quarantined.jsonl");
34034
+ const rejectedPath = path10.join(directory, ".swarm", "knowledge-rejected.jsonl");
34035
+ const swarmDir = path10.join(directory, ".swarm");
33835
34036
  await mkdir2(swarmDir, { recursive: true });
33836
34037
  let release;
33837
34038
  try {
33838
- release = await import_proper_lockfile3.default.lock(swarmDir, {
34039
+ release = await import_proper_lockfile4.default.lock(swarmDir, {
33839
34040
  retries: { retries: 3, minTimeout: 100 }
33840
34041
  });
33841
34042
  const quarantinedEntries = await readKnowledge(quarantinePath);
@@ -33990,18 +34191,18 @@ init_utils2();
33990
34191
  init_plan_schema();
33991
34192
  init_ledger();
33992
34193
  init_manager();
33993
- import * as fs6 from "fs";
33994
- import * as path10 from "path";
34194
+ import * as fs7 from "fs";
34195
+ import * as path11 from "path";
33995
34196
  async function writeCheckpoint(directory) {
33996
34197
  try {
33997
34198
  const plan = await loadPlan(directory);
33998
34199
  if (!plan)
33999
34200
  return;
34000
- const jsonPath = path10.join(directory, "SWARM_PLAN.json");
34001
- const mdPath = path10.join(directory, "SWARM_PLAN.md");
34002
- fs6.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
34201
+ const jsonPath = path11.join(directory, "SWARM_PLAN.json");
34202
+ const mdPath = path11.join(directory, "SWARM_PLAN.md");
34203
+ fs7.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
34003
34204
  const md = derivePlanMarkdown(plan);
34004
- fs6.writeFileSync(mdPath, md, "utf8");
34205
+ fs7.writeFileSync(mdPath, md, "utf8");
34005
34206
  } catch (error93) {
34006
34207
  console.warn(`[checkpoint] Failed to write SWARM_PLAN checkpoint: ${error93 instanceof Error ? error93.message : String(error93)}`);
34007
34208
  }
@@ -34009,8 +34210,8 @@ async function writeCheckpoint(directory) {
34009
34210
 
34010
34211
  // src/session/snapshot-writer.ts
34011
34212
  init_utils2();
34012
- import { mkdirSync as mkdirSync6, renameSync as renameSync5 } from "fs";
34013
- import * as path11 from "path";
34213
+ import { mkdirSync as mkdirSync7, renameSync as renameSync5 } from "fs";
34214
+ import * as path12 from "path";
34014
34215
  init_utils();
34015
34216
  var _writeInFlight = Promise.resolve();
34016
34217
  function serializeAgentSession(s) {
@@ -34101,8 +34302,8 @@ async function writeSnapshot(directory, state) {
34101
34302
  }
34102
34303
  const content = JSON.stringify(snapshot, null, 2);
34103
34304
  const resolvedPath = validateSwarmPath(directory, "session/state.json");
34104
- const dir = path11.dirname(resolvedPath);
34105
- mkdirSync6(dir, { recursive: true });
34305
+ const dir = path12.dirname(resolvedPath);
34306
+ mkdirSync7(dir, { recursive: true });
34106
34307
  const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
34107
34308
  await Bun.write(tempPath, content);
34108
34309
  renameSync5(tempPath, resolvedPath);
@@ -34493,21 +34694,21 @@ var ACTIVE_STATE_TO_CLEAN = [
34493
34694
  ];
34494
34695
  async function handleCloseCommand(directory, args) {
34495
34696
  const planPath = validateSwarmPath(directory, "plan.json");
34496
- const swarmDir = path12.join(directory, ".swarm");
34697
+ const swarmDir = path13.join(directory, ".swarm");
34497
34698
  let planExists = false;
34498
34699
  let planData = {
34499
- title: path12.basename(directory) || "Ad-hoc session",
34700
+ title: path13.basename(directory) || "Ad-hoc session",
34500
34701
  phases: []
34501
34702
  };
34502
34703
  try {
34503
- const content = await fs7.readFile(planPath, "utf-8");
34704
+ const content = await fs8.readFile(planPath, "utf-8");
34504
34705
  planData = JSON.parse(content);
34505
34706
  planExists = true;
34506
34707
  } catch (error93) {
34507
34708
  if (error93?.code !== "ENOENT") {
34508
34709
  return `\u274C Failed to read plan.json: ${error93 instanceof Error ? error93.message : String(error93)}`;
34509
34710
  }
34510
- const swarmDirExists = await fs7.access(swarmDir).then(() => true).catch(() => false);
34711
+ const swarmDirExists = await fs8.access(swarmDir).then(() => true).catch(() => false);
34511
34712
  if (!swarmDirExists) {
34512
34713
  return `\u274C No .swarm/ directory found in ${directory}. Run /swarm close from the project root, or run /swarm plan first.`;
34513
34714
  }
@@ -34601,10 +34802,10 @@ async function handleCloseCommand(directory, args) {
34601
34802
  warnings.push(`Session retrospective write threw: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
34602
34803
  }
34603
34804
  }
34604
- const lessonsFilePath = path12.join(swarmDir, "close-lessons.md");
34805
+ const lessonsFilePath = path13.join(swarmDir, "close-lessons.md");
34605
34806
  let explicitLessons = [];
34606
34807
  try {
34607
- const lessonsText = await fs7.readFile(lessonsFilePath, "utf-8");
34808
+ const lessonsText = await fs8.readFile(lessonsFilePath, "utf-8");
34608
34809
  explicitLessons = lessonsText.split(`
34609
34810
  `).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
34610
34811
  } catch {}
@@ -34618,7 +34819,7 @@ async function handleCloseCommand(directory, args) {
34618
34819
  console.warn("[close-command] curateAndStoreSwarm error:", error93);
34619
34820
  }
34620
34821
  if (curationSucceeded && explicitLessons.length > 0) {
34621
- await fs7.unlink(lessonsFilePath).catch(() => {});
34822
+ await fs8.unlink(lessonsFilePath).catch(() => {});
34622
34823
  }
34623
34824
  if (planExists && !planAlreadyDone) {
34624
34825
  for (const phase of phases) {
@@ -34638,7 +34839,7 @@ async function handleCloseCommand(directory, args) {
34638
34839
  }
34639
34840
  }
34640
34841
  try {
34641
- await fs7.writeFile(planPath, JSON.stringify(planData, null, 2), "utf-8");
34842
+ await fs8.writeFile(planPath, JSON.stringify(planData, null, 2), "utf-8");
34642
34843
  } catch (error93) {
34643
34844
  const msg = error93 instanceof Error ? error93.message : String(error93);
34644
34845
  warnings.push(`Failed to persist terminal plan.json state: ${msg}`);
@@ -34647,53 +34848,53 @@ async function handleCloseCommand(directory, args) {
34647
34848
  }
34648
34849
  const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
34649
34850
  const suffix = Math.random().toString(36).slice(2, 8);
34650
- const archiveDir = path12.join(swarmDir, "archive", `swarm-${timestamp}-${suffix}`);
34851
+ const archiveDir = path13.join(swarmDir, "archive", `swarm-${timestamp}-${suffix}`);
34651
34852
  let archiveResult = "";
34652
34853
  let archivedFileCount = 0;
34653
34854
  const archivedActiveStateFiles = new Set;
34654
34855
  try {
34655
- await fs7.mkdir(archiveDir, { recursive: true });
34856
+ await fs8.mkdir(archiveDir, { recursive: true });
34656
34857
  for (const artifact of ARCHIVE_ARTIFACTS) {
34657
- const srcPath = path12.join(swarmDir, artifact);
34658
- const destPath = path12.join(archiveDir, artifact);
34858
+ const srcPath = path13.join(swarmDir, artifact);
34859
+ const destPath = path13.join(archiveDir, artifact);
34659
34860
  try {
34660
- await fs7.copyFile(srcPath, destPath);
34861
+ await fs8.copyFile(srcPath, destPath);
34661
34862
  archivedFileCount++;
34662
34863
  if (ACTIVE_STATE_TO_CLEAN.includes(artifact)) {
34663
34864
  archivedActiveStateFiles.add(artifact);
34664
34865
  }
34665
34866
  } catch {}
34666
34867
  }
34667
- const evidenceDir = path12.join(swarmDir, "evidence");
34668
- const archiveEvidenceDir = path12.join(archiveDir, "evidence");
34868
+ const evidenceDir = path13.join(swarmDir, "evidence");
34869
+ const archiveEvidenceDir = path13.join(archiveDir, "evidence");
34669
34870
  try {
34670
- const evidenceEntries = await fs7.readdir(evidenceDir);
34871
+ const evidenceEntries = await fs8.readdir(evidenceDir);
34671
34872
  if (evidenceEntries.length > 0) {
34672
- await fs7.mkdir(archiveEvidenceDir, { recursive: true });
34873
+ await fs8.mkdir(archiveEvidenceDir, { recursive: true });
34673
34874
  for (const entry of evidenceEntries) {
34674
- const srcEntry = path12.join(evidenceDir, entry);
34675
- const destEntry = path12.join(archiveEvidenceDir, entry);
34875
+ const srcEntry = path13.join(evidenceDir, entry);
34876
+ const destEntry = path13.join(archiveEvidenceDir, entry);
34676
34877
  try {
34677
- const stat = await fs7.stat(srcEntry);
34878
+ const stat = await fs8.stat(srcEntry);
34678
34879
  if (stat.isDirectory()) {
34679
- await fs7.mkdir(destEntry, { recursive: true });
34680
- const subEntries = await fs7.readdir(srcEntry);
34880
+ await fs8.mkdir(destEntry, { recursive: true });
34881
+ const subEntries = await fs8.readdir(srcEntry);
34681
34882
  for (const sub of subEntries) {
34682
- await fs7.copyFile(path12.join(srcEntry, sub), path12.join(destEntry, sub)).catch(() => {});
34883
+ await fs8.copyFile(path13.join(srcEntry, sub), path13.join(destEntry, sub)).catch(() => {});
34683
34884
  }
34684
34885
  } else {
34685
- await fs7.copyFile(srcEntry, destEntry);
34886
+ await fs8.copyFile(srcEntry, destEntry);
34686
34887
  }
34687
34888
  archivedFileCount++;
34688
34889
  } catch {}
34689
34890
  }
34690
34891
  }
34691
34892
  } catch {}
34692
- const sessionStatePath = path12.join(swarmDir, "session", "state.json");
34893
+ const sessionStatePath = path13.join(swarmDir, "session", "state.json");
34693
34894
  try {
34694
- const archiveSessionDir = path12.join(archiveDir, "session");
34695
- await fs7.mkdir(archiveSessionDir, { recursive: true });
34696
- await fs7.copyFile(sessionStatePath, path12.join(archiveSessionDir, "state.json"));
34895
+ const archiveSessionDir = path13.join(archiveDir, "session");
34896
+ await fs8.mkdir(archiveSessionDir, { recursive: true });
34897
+ await fs8.copyFile(sessionStatePath, path13.join(archiveSessionDir, "state.json"));
34697
34898
  archivedFileCount++;
34698
34899
  } catch {}
34699
34900
  archiveResult = `Archived ${archivedFileCount} artifact(s) to .swarm/archive/swarm-${timestamp}/`;
@@ -34716,9 +34917,9 @@ async function handleCloseCommand(directory, args) {
34716
34917
  warnings.push(`Preserved ${artifact} because it was not successfully archived.`);
34717
34918
  continue;
34718
34919
  }
34719
- const filePath = path12.join(swarmDir, artifact);
34920
+ const filePath = path13.join(swarmDir, artifact);
34720
34921
  try {
34721
- await fs7.unlink(filePath);
34922
+ await fs8.unlink(filePath);
34722
34923
  cleanedFiles.push(artifact);
34723
34924
  } catch {}
34724
34925
  }
@@ -34726,23 +34927,23 @@ async function handleCloseCommand(directory, args) {
34726
34927
  warnings.push("Skipped active-state cleanup because no active-state files were archived. Files preserved to prevent data loss.");
34727
34928
  }
34728
34929
  try {
34729
- const swarmFiles = await fs7.readdir(swarmDir);
34930
+ const swarmFiles = await fs8.readdir(swarmDir);
34730
34931
  const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
34731
34932
  for (const backup of configBackups) {
34732
34933
  try {
34733
- await fs7.unlink(path12.join(swarmDir, backup));
34934
+ await fs8.unlink(path13.join(swarmDir, backup));
34734
34935
  configBackupsRemoved++;
34735
34936
  } catch {}
34736
34937
  }
34737
34938
  const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
34738
34939
  for (const sibling of ledgerSiblings) {
34739
34940
  try {
34740
- await fs7.unlink(path12.join(swarmDir, sibling));
34941
+ await fs8.unlink(path13.join(swarmDir, sibling));
34741
34942
  } catch {}
34742
34943
  }
34743
34944
  } catch {}
34744
34945
  clearAllScopes(directory);
34745
- const contextPath = path12.join(swarmDir, "context.md");
34946
+ const contextPath = path13.join(swarmDir, "context.md");
34746
34947
  const contextContent = [
34747
34948
  "# Context",
34748
34949
  "",
@@ -34755,7 +34956,7 @@ async function handleCloseCommand(directory, args) {
34755
34956
  ].join(`
34756
34957
  `);
34757
34958
  try {
34758
- await fs7.writeFile(contextPath, contextContent, "utf-8");
34959
+ await fs8.writeFile(contextPath, contextContent, "utf-8");
34759
34960
  } catch (error93) {
34760
34961
  const msg = error93 instanceof Error ? error93.message : String(error93);
34761
34962
  warnings.push(`Failed to reset context.md: ${msg}`);
@@ -34886,7 +35087,7 @@ async function handleCloseCommand(directory, args) {
34886
35087
  ].join(`
34887
35088
  `);
34888
35089
  try {
34889
- await fs7.writeFile(closeSummaryPath, summaryContent, "utf-8");
35090
+ await fs8.writeFile(closeSummaryPath, summaryContent, "utf-8");
34890
35091
  } catch (error93) {
34891
35092
  const msg = error93 instanceof Error ? error93.message : String(error93);
34892
35093
  warnings.push(`Failed to write close-summary.md: ${msg}`);
@@ -34942,15 +35143,15 @@ ${otherWarnings.map((w) => `- ${w}`).join(`
34942
35143
  }
34943
35144
 
34944
35145
  // src/commands/config.ts
34945
- import * as os3 from "os";
34946
- import * as path13 from "path";
35146
+ import * as os4 from "os";
35147
+ import * as path14 from "path";
34947
35148
  function getUserConfigDir2() {
34948
- return process.env.XDG_CONFIG_HOME || path13.join(os3.homedir(), ".config");
35149
+ return process.env.XDG_CONFIG_HOME || path14.join(os4.homedir(), ".config");
34949
35150
  }
34950
35151
  async function handleConfigCommand(directory, _args) {
34951
35152
  const config3 = loadPluginConfig(directory);
34952
- const userConfigPath = path13.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
34953
- const projectConfigPath = path13.join(directory, ".opencode", "opencode-swarm.json");
35153
+ const userConfigPath = path14.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
35154
+ const projectConfigPath = path14.join(directory, ".opencode", "opencode-swarm.json");
34954
35155
  const lines = [
34955
35156
  "## Swarm Configuration",
34956
35157
  "",
@@ -35218,13 +35419,13 @@ function formatCurationSummary(summary) {
35218
35419
  }
35219
35420
 
35220
35421
  // src/commands/dark-matter.ts
35221
- import path15 from "path";
35422
+ import path16 from "path";
35222
35423
 
35223
35424
  // src/tools/co-change-analyzer.ts
35224
35425
  import * as child_process3 from "child_process";
35225
35426
  import { randomUUID } from "crypto";
35226
35427
  import { readdir, readFile as readFile3, stat } from "fs/promises";
35227
- import * as path14 from "path";
35428
+ import * as path15 from "path";
35228
35429
  import { promisify } from "util";
35229
35430
  function getExecFileAsync() {
35230
35431
  return promisify(child_process3.execFile);
@@ -35326,7 +35527,7 @@ async function scanSourceFiles(dir) {
35326
35527
  try {
35327
35528
  const entries = await readdir(dir, { withFileTypes: true });
35328
35529
  for (const entry of entries) {
35329
- const fullPath = path14.join(dir, entry.name);
35530
+ const fullPath = path15.join(dir, entry.name);
35330
35531
  if (entry.isDirectory()) {
35331
35532
  if (skipDirs.has(entry.name)) {
35332
35533
  continue;
@@ -35334,7 +35535,7 @@ async function scanSourceFiles(dir) {
35334
35535
  const subFiles = await scanSourceFiles(fullPath);
35335
35536
  results.push(...subFiles);
35336
35537
  } else if (entry.isFile()) {
35337
- const ext = path14.extname(entry.name);
35538
+ const ext = path15.extname(entry.name);
35338
35539
  if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
35339
35540
  results.push(fullPath);
35340
35541
  }
@@ -35356,8 +35557,8 @@ async function getStaticEdges(directory) {
35356
35557
  continue;
35357
35558
  }
35358
35559
  try {
35359
- const sourceDir = path14.dirname(sourceFile);
35360
- const resolvedPath = path14.resolve(sourceDir, importPath);
35560
+ const sourceDir = path15.dirname(sourceFile);
35561
+ const resolvedPath = path15.resolve(sourceDir, importPath);
35361
35562
  const extensions = [
35362
35563
  "",
35363
35564
  ".ts",
@@ -35382,8 +35583,8 @@ async function getStaticEdges(directory) {
35382
35583
  if (!targetFile) {
35383
35584
  continue;
35384
35585
  }
35385
- const relSource = path14.relative(directory, sourceFile).replace(/\\/g, "/");
35386
- const relTarget = path14.relative(directory, targetFile).replace(/\\/g, "/");
35586
+ const relSource = path15.relative(directory, sourceFile).replace(/\\/g, "/");
35587
+ const relTarget = path15.relative(directory, targetFile).replace(/\\/g, "/");
35387
35588
  const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
35388
35589
  edges.add(key);
35389
35590
  } catch {}
@@ -35395,7 +35596,7 @@ async function getStaticEdges(directory) {
35395
35596
  function isTestImplementationPair(fileA, fileB) {
35396
35597
  const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
35397
35598
  const getBaseName = (filePath) => {
35398
- const base = path14.basename(filePath);
35599
+ const base = path15.basename(filePath);
35399
35600
  for (const pattern of testPatterns) {
35400
35601
  if (base.endsWith(pattern)) {
35401
35602
  return base.slice(0, -pattern.length);
@@ -35405,16 +35606,16 @@ function isTestImplementationPair(fileA, fileB) {
35405
35606
  };
35406
35607
  const baseA = getBaseName(fileA);
35407
35608
  const baseB = getBaseName(fileB);
35408
- return baseA === baseB && baseA !== path14.basename(fileA) && baseA !== path14.basename(fileB);
35609
+ return baseA === baseB && baseA !== path15.basename(fileA) && baseA !== path15.basename(fileB);
35409
35610
  }
35410
35611
  function hasSharedPrefix(fileA, fileB) {
35411
- const dirA = path14.dirname(fileA);
35412
- const dirB = path14.dirname(fileB);
35612
+ const dirA = path15.dirname(fileA);
35613
+ const dirB = path15.dirname(fileB);
35413
35614
  if (dirA !== dirB) {
35414
35615
  return false;
35415
35616
  }
35416
- const baseA = path14.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
35417
- const baseB = path14.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
35617
+ const baseA = path15.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
35618
+ const baseB = path15.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
35418
35619
  if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
35419
35620
  return true;
35420
35621
  }
@@ -35468,8 +35669,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
35468
35669
  const entries = [];
35469
35670
  const now = new Date().toISOString();
35470
35671
  for (const pair of pairs.slice(0, 10)) {
35471
- const baseA = path14.basename(pair.fileA);
35472
- const baseB = path14.basename(pair.fileB);
35672
+ const baseA = path15.basename(pair.fileA);
35673
+ const baseB = path15.basename(pair.fileB);
35473
35674
  let lesson = `Files ${pair.fileA} and ${pair.fileB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
35474
35675
  if (lesson.length > 280) {
35475
35676
  lesson = `Files ${baseA} and ${baseB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
@@ -35579,7 +35780,7 @@ async function handleDarkMatterCommand(directory, args) {
35579
35780
  const output = formatDarkMatterOutput(pairs);
35580
35781
  if (pairs.length > 0) {
35581
35782
  try {
35582
- const projectName = path15.basename(path15.resolve(directory));
35783
+ const projectName = path16.basename(path16.resolve(directory));
35583
35784
  const entries = darkMatterToKnowledgeEntries(pairs, projectName);
35584
35785
  if (entries.length > 0) {
35585
35786
  const knowledgePath = resolveSwarmKnowledgePath(directory);
@@ -35600,8 +35801,8 @@ async function handleDarkMatterCommand(directory, args) {
35600
35801
 
35601
35802
  // src/services/diagnose-service.ts
35602
35803
  import * as child_process4 from "child_process";
35603
- import { existsSync as existsSync7, readdirSync as readdirSync3, readFileSync as readFileSync6, statSync as statSync4 } from "fs";
35604
- import path16 from "path";
35804
+ import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync5 } from "fs";
35805
+ import path17 from "path";
35605
35806
  import { fileURLToPath } from "url";
35606
35807
  init_manager2();
35607
35808
  init_utils2();
@@ -35806,7 +36007,7 @@ async function checkPlanSync(directory, plan) {
35806
36007
  }
35807
36008
  async function checkConfigBackups(directory) {
35808
36009
  try {
35809
- const files = readdirSync3(directory);
36010
+ const files = readdirSync4(directory);
35810
36011
  const backupCount = files.filter((f) => /\.opencode-swarm\.yaml\.bak/.test(f)).length;
35811
36012
  if (backupCount <= 5) {
35812
36013
  return {
@@ -35837,7 +36038,7 @@ async function checkConfigBackups(directory) {
35837
36038
  }
35838
36039
  async function checkGitRepository(directory) {
35839
36040
  try {
35840
- if (!existsSync7(directory) || !statSync4(directory).isDirectory()) {
36041
+ if (!existsSync8(directory) || !statSync5(directory).isDirectory()) {
35841
36042
  return {
35842
36043
  name: "Git Repository",
35843
36044
  status: "\u274C",
@@ -35901,8 +36102,8 @@ async function checkSpecStaleness(directory, plan) {
35901
36102
  };
35902
36103
  }
35903
36104
  async function checkConfigParseability(directory) {
35904
- const configPath = path16.join(directory, ".opencode/opencode-swarm.json");
35905
- if (!existsSync7(configPath)) {
36105
+ const configPath = path17.join(directory, ".opencode/opencode-swarm.json");
36106
+ if (!existsSync8(configPath)) {
35906
36107
  return {
35907
36108
  name: "Config Parseability",
35908
36109
  status: "\u2705",
@@ -35948,15 +36149,15 @@ async function checkGrammarWasmFiles() {
35948
36149
  "tree-sitter-ini.wasm",
35949
36150
  "tree-sitter-regex.wasm"
35950
36151
  ];
35951
- const thisDir = path16.dirname(fileURLToPath(import.meta.url));
36152
+ const thisDir = path17.dirname(fileURLToPath(import.meta.url));
35952
36153
  const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/services");
35953
- const grammarDir = isSource ? path16.join(thisDir, "..", "lang", "grammars") : path16.join(thisDir, "lang", "grammars");
36154
+ const grammarDir = isSource ? path17.join(thisDir, "..", "lang", "grammars") : path17.join(thisDir, "lang", "grammars");
35954
36155
  const missing = [];
35955
- if (!existsSync7(path16.join(grammarDir, "tree-sitter.wasm"))) {
36156
+ if (!existsSync8(path17.join(grammarDir, "tree-sitter.wasm"))) {
35956
36157
  missing.push("tree-sitter.wasm (core runtime)");
35957
36158
  }
35958
36159
  for (const file3 of grammarFiles) {
35959
- if (!existsSync7(path16.join(grammarDir, file3))) {
36160
+ if (!existsSync8(path17.join(grammarDir, file3))) {
35960
36161
  missing.push(file3);
35961
36162
  }
35962
36163
  }
@@ -35974,8 +36175,8 @@ async function checkGrammarWasmFiles() {
35974
36175
  };
35975
36176
  }
35976
36177
  async function checkCheckpointManifest(directory) {
35977
- const manifestPath = path16.join(directory, ".swarm/checkpoints.json");
35978
- if (!existsSync7(manifestPath)) {
36178
+ const manifestPath = path17.join(directory, ".swarm/checkpoints.json");
36179
+ if (!existsSync8(manifestPath)) {
35979
36180
  return {
35980
36181
  name: "Checkpoint Manifest",
35981
36182
  status: "\u2705",
@@ -36026,8 +36227,8 @@ async function checkCheckpointManifest(directory) {
36026
36227
  }
36027
36228
  }
36028
36229
  async function checkEventStreamIntegrity(directory) {
36029
- const eventsPath = path16.join(directory, ".swarm/events.jsonl");
36030
- if (!existsSync7(eventsPath)) {
36230
+ const eventsPath = path17.join(directory, ".swarm/events.jsonl");
36231
+ if (!existsSync8(eventsPath)) {
36031
36232
  return {
36032
36233
  name: "Event Stream",
36033
36234
  status: "\u2705",
@@ -36067,8 +36268,8 @@ async function checkEventStreamIntegrity(directory) {
36067
36268
  }
36068
36269
  }
36069
36270
  async function checkSteeringDirectives(directory) {
36070
- const eventsPath = path16.join(directory, ".swarm/events.jsonl");
36071
- if (!existsSync7(eventsPath)) {
36271
+ const eventsPath = path17.join(directory, ".swarm/events.jsonl");
36272
+ if (!existsSync8(eventsPath)) {
36072
36273
  return {
36073
36274
  name: "Steering Directives",
36074
36275
  status: "\u2705",
@@ -36123,8 +36324,8 @@ async function checkCurator(directory) {
36123
36324
  detail: "Disabled (enable via curator.enabled)"
36124
36325
  };
36125
36326
  }
36126
- const summaryPath = path16.join(directory, ".swarm/curator-summary.json");
36127
- if (!existsSync7(summaryPath)) {
36327
+ const summaryPath = path17.join(directory, ".swarm/curator-summary.json");
36328
+ if (!existsSync8(summaryPath)) {
36128
36329
  return {
36129
36330
  name: "Curator",
36130
36331
  status: "\u2705",
@@ -36271,8 +36472,8 @@ async function getDiagnoseData(directory) {
36271
36472
  checks5.push(await checkSteeringDirectives(directory));
36272
36473
  checks5.push(await checkCurator(directory));
36273
36474
  try {
36274
- const evidenceDir = path16.join(directory, ".swarm", "evidence");
36275
- const snapshotFiles = existsSync7(evidenceDir) ? readdirSync3(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
36475
+ const evidenceDir = path17.join(directory, ".swarm", "evidence");
36476
+ const snapshotFiles = existsSync8(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
36276
36477
  if (snapshotFiles.length > 0) {
36277
36478
  const latest = snapshotFiles.sort().pop();
36278
36479
  checks5.push({
@@ -36323,16 +36524,16 @@ async function handleDiagnoseCommand(directory, _args) {
36323
36524
  init_config_doctor();
36324
36525
 
36325
36526
  // src/services/tool-doctor.ts
36326
- import * as fs10 from "fs";
36327
- import * as path19 from "path";
36527
+ import * as fs11 from "fs";
36528
+ import * as path20 from "path";
36328
36529
 
36329
36530
  // src/build/discovery.ts
36330
- import * as fs9 from "fs";
36331
- import * as path18 from "path";
36531
+ import * as fs10 from "fs";
36532
+ import * as path19 from "path";
36332
36533
 
36333
36534
  // src/lang/detector.ts
36334
36535
  import { access as access2, readdir as readdir2 } from "fs/promises";
36335
- import { extname as extname2, join as join15 } from "path";
36536
+ import { extname as extname2, join as join16 } from "path";
36336
36537
 
36337
36538
  // src/lang/profiles.ts
36338
36539
  class LanguageRegistry {
@@ -37312,7 +37513,7 @@ async function detectProjectLanguages(projectDir) {
37312
37513
  if (detectFile.includes("*") || detectFile.includes("?"))
37313
37514
  continue;
37314
37515
  try {
37315
- await access2(join15(dir, detectFile));
37516
+ await access2(join16(dir, detectFile));
37316
37517
  detected.add(profile.id);
37317
37518
  break;
37318
37519
  } catch {}
@@ -37333,7 +37534,7 @@ async function detectProjectLanguages(projectDir) {
37333
37534
  const topEntries = await readdir2(projectDir, { withFileTypes: true });
37334
37535
  for (const entry of topEntries) {
37335
37536
  if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
37336
- await scanDir(join15(projectDir, entry.name));
37537
+ await scanDir(join16(projectDir, entry.name));
37337
37538
  }
37338
37539
  }
37339
37540
  } catch {}
@@ -37488,16 +37689,16 @@ function findBuildFiles(workingDir, patterns) {
37488
37689
  if (pattern.includes("*")) {
37489
37690
  const dir = workingDir;
37490
37691
  try {
37491
- const files = fs9.readdirSync(dir);
37692
+ const files = fs10.readdirSync(dir);
37492
37693
  const regex = simpleGlobToRegex(pattern);
37493
37694
  const matches = files.filter((f) => regex.test(f));
37494
37695
  if (matches.length > 0) {
37495
- return path18.join(dir, matches[0]);
37696
+ return path19.join(dir, matches[0]);
37496
37697
  }
37497
37698
  } catch {}
37498
37699
  } else {
37499
- const filePath = path18.join(workingDir, pattern);
37500
- if (fs9.existsSync(filePath)) {
37700
+ const filePath = path19.join(workingDir, pattern);
37701
+ if (fs10.existsSync(filePath)) {
37501
37702
  return filePath;
37502
37703
  }
37503
37704
  }
@@ -37505,12 +37706,12 @@ function findBuildFiles(workingDir, patterns) {
37505
37706
  return null;
37506
37707
  }
37507
37708
  function getRepoDefinedScripts(workingDir, scripts) {
37508
- const packageJsonPath = path18.join(workingDir, "package.json");
37509
- if (!fs9.existsSync(packageJsonPath)) {
37709
+ const packageJsonPath = path19.join(workingDir, "package.json");
37710
+ if (!fs10.existsSync(packageJsonPath)) {
37510
37711
  return [];
37511
37712
  }
37512
37713
  try {
37513
- const content = fs9.readFileSync(packageJsonPath, "utf-8");
37714
+ const content = fs10.readFileSync(packageJsonPath, "utf-8");
37514
37715
  const pkg = JSON.parse(content);
37515
37716
  if (!pkg.scripts || typeof pkg.scripts !== "object") {
37516
37717
  return [];
@@ -37546,8 +37747,8 @@ function findAllBuildFiles(workingDir) {
37546
37747
  const regex = simpleGlobToRegex(pattern);
37547
37748
  findFilesRecursive(workingDir, regex, allBuildFiles);
37548
37749
  } else {
37549
- const filePath = path18.join(workingDir, pattern);
37550
- if (fs9.existsSync(filePath)) {
37750
+ const filePath = path19.join(workingDir, pattern);
37751
+ if (fs10.existsSync(filePath)) {
37551
37752
  allBuildFiles.add(filePath);
37552
37753
  }
37553
37754
  }
@@ -37557,9 +37758,9 @@ function findAllBuildFiles(workingDir) {
37557
37758
  }
37558
37759
  function findFilesRecursive(dir, regex, results) {
37559
37760
  try {
37560
- const entries = fs9.readdirSync(dir, { withFileTypes: true });
37761
+ const entries = fs10.readdirSync(dir, { withFileTypes: true });
37561
37762
  for (const entry of entries) {
37562
- const fullPath = path18.join(dir, entry.name);
37763
+ const fullPath = path19.join(dir, entry.name);
37563
37764
  if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
37564
37765
  findFilesRecursive(fullPath, regex, results);
37565
37766
  } else if (entry.isFile() && regex.test(entry.name)) {
@@ -37582,8 +37783,8 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
37582
37783
  let foundCommand = false;
37583
37784
  for (const cmd of sortedCommands) {
37584
37785
  if (cmd.detectFile) {
37585
- const detectFilePath = path18.join(workingDir, cmd.detectFile);
37586
- if (!fs9.existsSync(detectFilePath)) {
37786
+ const detectFilePath = path19.join(workingDir, cmd.detectFile);
37787
+ if (!fs10.existsSync(detectFilePath)) {
37587
37788
  continue;
37588
37789
  }
37589
37790
  }
@@ -37706,7 +37907,7 @@ var BINARY_CHECKLIST = [
37706
37907
  function extractRegisteredToolKeys(indexPath) {
37707
37908
  const registeredKeys = new Set;
37708
37909
  try {
37709
- const content = fs10.readFileSync(indexPath, "utf-8");
37910
+ const content = fs11.readFileSync(indexPath, "utf-8");
37710
37911
  const toolBlockMatch = content.match(/tool:\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}/s);
37711
37912
  if (!toolBlockMatch) {
37712
37913
  return registeredKeys;
@@ -37757,9 +37958,9 @@ function checkBinaryReadiness() {
37757
37958
  }
37758
37959
  function runToolDoctor(_directory, pluginRoot) {
37759
37960
  const findings = [];
37760
- const resolvedPluginRoot = pluginRoot ?? path19.resolve(import.meta.dir, "..", "..");
37761
- const indexPath = path19.join(resolvedPluginRoot, "src", "index.ts");
37762
- if (!fs10.existsSync(indexPath)) {
37961
+ const resolvedPluginRoot = pluginRoot ?? path20.resolve(import.meta.dir, "..", "..");
37962
+ const indexPath = path20.join(resolvedPluginRoot, "src", "index.ts");
37963
+ if (!fs11.existsSync(indexPath)) {
37763
37964
  return {
37764
37965
  findings: [
37765
37966
  {
@@ -38669,14 +38870,14 @@ async function handleHistoryCommand(directory, _args) {
38669
38870
  }
38670
38871
  // src/hooks/knowledge-migrator.ts
38671
38872
  import { randomUUID as randomUUID2 } from "crypto";
38672
- import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
38873
+ import { existsSync as existsSync12, readFileSync as readFileSync10 } from "fs";
38673
38874
  import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
38674
- import * as path20 from "path";
38875
+ import * as path21 from "path";
38675
38876
  async function migrateContextToKnowledge(directory, config3) {
38676
- const sentinelPath = path20.join(directory, ".swarm", ".knowledge-migrated");
38677
- const contextPath = path20.join(directory, ".swarm", "context.md");
38877
+ const sentinelPath = path21.join(directory, ".swarm", ".knowledge-migrated");
38878
+ const contextPath = path21.join(directory, ".swarm", "context.md");
38678
38879
  const knowledgePath = resolveSwarmKnowledgePath(directory);
38679
- if (existsSync11(sentinelPath)) {
38880
+ if (existsSync12(sentinelPath)) {
38680
38881
  return {
38681
38882
  migrated: false,
38682
38883
  entriesMigrated: 0,
@@ -38685,7 +38886,7 @@ async function migrateContextToKnowledge(directory, config3) {
38685
38886
  skippedReason: "sentinel-exists"
38686
38887
  };
38687
38888
  }
38688
- if (!existsSync11(contextPath)) {
38889
+ if (!existsSync12(contextPath)) {
38689
38890
  return {
38690
38891
  migrated: false,
38691
38892
  entriesMigrated: 0,
@@ -38870,8 +39071,8 @@ function truncateLesson(text) {
38870
39071
  return `${text.slice(0, 277)}...`;
38871
39072
  }
38872
39073
  function inferProjectName(directory) {
38873
- const packageJsonPath = path20.join(directory, "package.json");
38874
- if (existsSync11(packageJsonPath)) {
39074
+ const packageJsonPath = path21.join(directory, "package.json");
39075
+ if (existsSync12(packageJsonPath)) {
38875
39076
  try {
38876
39077
  const pkg = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
38877
39078
  if (pkg.name && typeof pkg.name === "string") {
@@ -38879,7 +39080,7 @@ function inferProjectName(directory) {
38879
39080
  }
38880
39081
  } catch {}
38881
39082
  }
38882
- return path20.basename(directory);
39083
+ return path21.basename(directory);
38883
39084
  }
38884
39085
  async function writeSentinel(sentinelPath, migrated, dropped) {
38885
39086
  const sentinel = {
@@ -38891,7 +39092,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
38891
39092
  schema_version: 1,
38892
39093
  migration_tool: "knowledge-migrator.ts"
38893
39094
  };
38894
- await mkdir3(path20.dirname(sentinelPath), { recursive: true });
39095
+ await mkdir3(path21.dirname(sentinelPath), { recursive: true });
38895
39096
  await writeFile4(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
38896
39097
  }
38897
39098
 
@@ -39127,12 +39328,12 @@ async function handlePlanCommand(directory, args) {
39127
39328
  // src/services/preflight-service.ts
39128
39329
  init_manager2();
39129
39330
  init_manager();
39130
- import * as fs17 from "fs";
39131
- import * as path27 from "path";
39331
+ import * as fs18 from "fs";
39332
+ import * as path28 from "path";
39132
39333
 
39133
39334
  // src/tools/lint.ts
39134
- import * as fs11 from "fs";
39135
- import * as path21 from "path";
39335
+ import * as fs12 from "fs";
39336
+ import * as path22 from "path";
39136
39337
  init_utils();
39137
39338
 
39138
39339
  // src/utils/path-security.ts
@@ -39178,9 +39379,9 @@ function validateArgs(args) {
39178
39379
  }
39179
39380
  function getLinterCommand(linter, mode, projectDir) {
39180
39381
  const isWindows = process.platform === "win32";
39181
- const binDir = path21.join(projectDir, "node_modules", ".bin");
39182
- const biomeBin = isWindows ? path21.join(binDir, "biome.EXE") : path21.join(binDir, "biome");
39183
- const eslintBin = isWindows ? path21.join(binDir, "eslint.cmd") : path21.join(binDir, "eslint");
39382
+ const binDir = path22.join(projectDir, "node_modules", ".bin");
39383
+ const biomeBin = isWindows ? path22.join(binDir, "biome.EXE") : path22.join(binDir, "biome");
39384
+ const eslintBin = isWindows ? path22.join(binDir, "eslint.cmd") : path22.join(binDir, "eslint");
39184
39385
  switch (linter) {
39185
39386
  case "biome":
39186
39387
  if (mode === "fix") {
@@ -39196,7 +39397,7 @@ function getLinterCommand(linter, mode, projectDir) {
39196
39397
  }
39197
39398
  function getAdditionalLinterCommand(linter, mode, cwd) {
39198
39399
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
39199
- const gradlew = fs11.existsSync(path21.join(cwd, gradlewName)) ? path21.join(cwd, gradlewName) : null;
39400
+ const gradlew = fs12.existsSync(path22.join(cwd, gradlewName)) ? path22.join(cwd, gradlewName) : null;
39200
39401
  switch (linter) {
39201
39402
  case "ruff":
39202
39403
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -39230,12 +39431,12 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
39230
39431
  }
39231
39432
  }
39232
39433
  function detectRuff(cwd) {
39233
- if (fs11.existsSync(path21.join(cwd, "ruff.toml")))
39434
+ if (fs12.existsSync(path22.join(cwd, "ruff.toml")))
39234
39435
  return isCommandAvailable("ruff");
39235
39436
  try {
39236
- const pyproject = path21.join(cwd, "pyproject.toml");
39237
- if (fs11.existsSync(pyproject)) {
39238
- const content = fs11.readFileSync(pyproject, "utf-8");
39437
+ const pyproject = path22.join(cwd, "pyproject.toml");
39438
+ if (fs12.existsSync(pyproject)) {
39439
+ const content = fs12.readFileSync(pyproject, "utf-8");
39239
39440
  if (content.includes("[tool.ruff]"))
39240
39441
  return isCommandAvailable("ruff");
39241
39442
  }
@@ -39243,21 +39444,21 @@ function detectRuff(cwd) {
39243
39444
  return false;
39244
39445
  }
39245
39446
  function detectClippy(cwd) {
39246
- return fs11.existsSync(path21.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
39447
+ return fs12.existsSync(path22.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
39247
39448
  }
39248
39449
  function detectGolangciLint(cwd) {
39249
- return fs11.existsSync(path21.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
39450
+ return fs12.existsSync(path22.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
39250
39451
  }
39251
39452
  function detectCheckstyle(cwd) {
39252
- const hasMaven = fs11.existsSync(path21.join(cwd, "pom.xml"));
39253
- const hasGradle = fs11.existsSync(path21.join(cwd, "build.gradle")) || fs11.existsSync(path21.join(cwd, "build.gradle.kts"));
39254
- const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs11.existsSync(path21.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
39453
+ const hasMaven = fs12.existsSync(path22.join(cwd, "pom.xml"));
39454
+ const hasGradle = fs12.existsSync(path22.join(cwd, "build.gradle")) || fs12.existsSync(path22.join(cwd, "build.gradle.kts"));
39455
+ const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs12.existsSync(path22.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
39255
39456
  return (hasMaven || hasGradle) && hasBinary;
39256
39457
  }
39257
39458
  function detectKtlint(cwd) {
39258
- const hasKotlin = fs11.existsSync(path21.join(cwd, "build.gradle.kts")) || fs11.existsSync(path21.join(cwd, "build.gradle")) || (() => {
39459
+ const hasKotlin = fs12.existsSync(path22.join(cwd, "build.gradle.kts")) || fs12.existsSync(path22.join(cwd, "build.gradle")) || (() => {
39259
39460
  try {
39260
- return fs11.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
39461
+ return fs12.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
39261
39462
  } catch {
39262
39463
  return false;
39263
39464
  }
@@ -39266,7 +39467,7 @@ function detectKtlint(cwd) {
39266
39467
  }
39267
39468
  function detectDotnetFormat(cwd) {
39268
39469
  try {
39269
- const files = fs11.readdirSync(cwd);
39470
+ const files = fs12.readdirSync(cwd);
39270
39471
  const hasCsproj = files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"));
39271
39472
  return hasCsproj && isCommandAvailable("dotnet");
39272
39473
  } catch {
@@ -39274,14 +39475,14 @@ function detectDotnetFormat(cwd) {
39274
39475
  }
39275
39476
  }
39276
39477
  function detectCppcheck(cwd) {
39277
- if (fs11.existsSync(path21.join(cwd, "CMakeLists.txt"))) {
39478
+ if (fs12.existsSync(path22.join(cwd, "CMakeLists.txt"))) {
39278
39479
  return isCommandAvailable("cppcheck");
39279
39480
  }
39280
39481
  try {
39281
- const dirsToCheck = [cwd, path21.join(cwd, "src")];
39482
+ const dirsToCheck = [cwd, path22.join(cwd, "src")];
39282
39483
  const hasCpp = dirsToCheck.some((dir) => {
39283
39484
  try {
39284
- return fs11.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
39485
+ return fs12.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
39285
39486
  } catch {
39286
39487
  return false;
39287
39488
  }
@@ -39292,13 +39493,13 @@ function detectCppcheck(cwd) {
39292
39493
  }
39293
39494
  }
39294
39495
  function detectSwiftlint(cwd) {
39295
- return fs11.existsSync(path21.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
39496
+ return fs12.existsSync(path22.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
39296
39497
  }
39297
39498
  function detectDartAnalyze(cwd) {
39298
- return fs11.existsSync(path21.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
39499
+ return fs12.existsSync(path22.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
39299
39500
  }
39300
39501
  function detectRubocop(cwd) {
39301
- return (fs11.existsSync(path21.join(cwd, "Gemfile")) || fs11.existsSync(path21.join(cwd, "gems.rb")) || fs11.existsSync(path21.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
39502
+ return (fs12.existsSync(path22.join(cwd, "Gemfile")) || fs12.existsSync(path22.join(cwd, "gems.rb")) || fs12.existsSync(path22.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
39302
39503
  }
39303
39504
  function detectAdditionalLinter(cwd) {
39304
39505
  if (detectRuff(cwd))
@@ -39326,10 +39527,10 @@ function detectAdditionalLinter(cwd) {
39326
39527
  function findBinInAncestors(startDir, binName) {
39327
39528
  let dir = startDir;
39328
39529
  while (true) {
39329
- const candidate = path21.join(dir, "node_modules", ".bin", binName);
39330
- if (fs11.existsSync(candidate))
39530
+ const candidate = path22.join(dir, "node_modules", ".bin", binName);
39531
+ if (fs12.existsSync(candidate))
39331
39532
  return candidate;
39332
- const parent = path21.dirname(dir);
39533
+ const parent = path22.dirname(dir);
39333
39534
  if (parent === dir)
39334
39535
  break;
39335
39536
  dir = parent;
@@ -39338,11 +39539,11 @@ function findBinInAncestors(startDir, binName) {
39338
39539
  }
39339
39540
  function findBinInEnvPath(binName) {
39340
39541
  const searchPath = process.env.PATH ?? "";
39341
- for (const dir of searchPath.split(path21.delimiter)) {
39542
+ for (const dir of searchPath.split(path22.delimiter)) {
39342
39543
  if (!dir)
39343
39544
  continue;
39344
- const candidate = path21.join(dir, binName);
39345
- if (fs11.existsSync(candidate))
39545
+ const candidate = path22.join(dir, binName);
39546
+ if (fs12.existsSync(candidate))
39346
39547
  return candidate;
39347
39548
  }
39348
39549
  return null;
@@ -39350,17 +39551,17 @@ function findBinInEnvPath(binName) {
39350
39551
  async function detectAvailableLinter(directory) {
39351
39552
  if (!directory)
39352
39553
  return null;
39353
- if (!fs11.existsSync(directory))
39554
+ if (!fs12.existsSync(directory))
39354
39555
  return null;
39355
39556
  const projectDir = directory;
39356
39557
  const isWindows = process.platform === "win32";
39357
- const biomeBin = isWindows ? path21.join(projectDir, "node_modules", ".bin", "biome.EXE") : path21.join(projectDir, "node_modules", ".bin", "biome");
39358
- const eslintBin = isWindows ? path21.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path21.join(projectDir, "node_modules", ".bin", "eslint");
39558
+ const biomeBin = isWindows ? path22.join(projectDir, "node_modules", ".bin", "biome.EXE") : path22.join(projectDir, "node_modules", ".bin", "biome");
39559
+ const eslintBin = isWindows ? path22.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path22.join(projectDir, "node_modules", ".bin", "eslint");
39359
39560
  const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
39360
39561
  if (localResult)
39361
39562
  return localResult;
39362
- const biomeAncestor = findBinInAncestors(path21.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
39363
- const eslintAncestor = findBinInAncestors(path21.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
39563
+ const biomeAncestor = findBinInAncestors(path22.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
39564
+ const eslintAncestor = findBinInAncestors(path22.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
39364
39565
  if (biomeAncestor || eslintAncestor) {
39365
39566
  return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
39366
39567
  }
@@ -39379,11 +39580,11 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
39379
39580
  stderr: "pipe"
39380
39581
  });
39381
39582
  const biomeExit = biomeProc.exited;
39382
- const timeout = new Promise((resolve8) => setTimeout(() => resolve8("timeout"), DETECT_TIMEOUT));
39583
+ const timeout = new Promise((resolve9) => setTimeout(() => resolve9("timeout"), DETECT_TIMEOUT));
39383
39584
  const result = await Promise.race([biomeExit, timeout]);
39384
39585
  if (result === "timeout") {
39385
39586
  biomeProc.kill();
39386
- } else if (biomeProc.exitCode === 0 && fs11.existsSync(biomeBin)) {
39587
+ } else if (biomeProc.exitCode === 0 && fs12.existsSync(biomeBin)) {
39387
39588
  return "biome";
39388
39589
  }
39389
39590
  } catch {}
@@ -39393,11 +39594,11 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
39393
39594
  stderr: "pipe"
39394
39595
  });
39395
39596
  const eslintExit = eslintProc.exited;
39396
- const timeout = new Promise((resolve8) => setTimeout(() => resolve8("timeout"), DETECT_TIMEOUT));
39597
+ const timeout = new Promise((resolve9) => setTimeout(() => resolve9("timeout"), DETECT_TIMEOUT));
39397
39598
  const result = await Promise.race([eslintExit, timeout]);
39398
39599
  if (result === "timeout") {
39399
39600
  eslintProc.kill();
39400
- } else if (eslintProc.exitCode === 0 && fs11.existsSync(eslintBin)) {
39601
+ } else if (eslintProc.exitCode === 0 && fs12.existsSync(eslintBin)) {
39401
39602
  return "eslint";
39402
39603
  }
39403
39604
  } catch {}
@@ -39567,8 +39768,8 @@ For Rust: rustup component add clippy`
39567
39768
  });
39568
39769
 
39569
39770
  // src/tools/secretscan.ts
39570
- import * as fs12 from "fs";
39571
- import * as path22 from "path";
39771
+ import * as fs13 from "fs";
39772
+ import * as path23 from "path";
39572
39773
  var MAX_FILE_PATH_LENGTH = 500;
39573
39774
  var MAX_FILE_SIZE_BYTES = 512 * 1024;
39574
39775
  var MAX_FILES_SCANNED = 1000;
@@ -39795,11 +39996,11 @@ function isGlobOrPathPattern(pattern) {
39795
39996
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
39796
39997
  }
39797
39998
  function loadSecretScanIgnore(scanDir) {
39798
- const ignorePath = path22.join(scanDir, ".secretscanignore");
39999
+ const ignorePath = path23.join(scanDir, ".secretscanignore");
39799
40000
  try {
39800
- if (!fs12.existsSync(ignorePath))
40001
+ if (!fs13.existsSync(ignorePath))
39801
40002
  return [];
39802
- const content = fs12.readFileSync(ignorePath, "utf8");
40003
+ const content = fs13.readFileSync(ignorePath, "utf8");
39803
40004
  const patterns = [];
39804
40005
  for (const rawLine of content.split(/\r?\n/)) {
39805
40006
  const line = rawLine.trim();
@@ -39818,7 +40019,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
39818
40019
  if (exactNames.has(entry))
39819
40020
  return true;
39820
40021
  for (const pattern of globPatterns) {
39821
- if (path22.matchesGlob(relPath, pattern))
40022
+ if (path23.matchesGlob(relPath, pattern))
39822
40023
  return true;
39823
40024
  }
39824
40025
  return false;
@@ -39839,7 +40040,7 @@ function validateDirectoryInput(dir) {
39839
40040
  return null;
39840
40041
  }
39841
40042
  function isBinaryFile(filePath, buffer) {
39842
- const ext = path22.extname(filePath).toLowerCase();
40043
+ const ext = path23.extname(filePath).toLowerCase();
39843
40044
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
39844
40045
  return true;
39845
40046
  }
@@ -39914,11 +40115,11 @@ function createRedactedContext(line, findings) {
39914
40115
  result += line.slice(lastEnd);
39915
40116
  return result;
39916
40117
  }
39917
- var O_NOFOLLOW = process.platform !== "win32" ? fs12.constants.O_NOFOLLOW : undefined;
40118
+ var O_NOFOLLOW = process.platform !== "win32" ? fs13.constants.O_NOFOLLOW : undefined;
39918
40119
  function scanFileForSecrets(filePath) {
39919
40120
  const findings = [];
39920
40121
  try {
39921
- const lstat = fs12.lstatSync(filePath);
40122
+ const lstat = fs13.lstatSync(filePath);
39922
40123
  if (lstat.isSymbolicLink()) {
39923
40124
  return findings;
39924
40125
  }
@@ -39927,14 +40128,14 @@ function scanFileForSecrets(filePath) {
39927
40128
  }
39928
40129
  let buffer;
39929
40130
  if (O_NOFOLLOW !== undefined) {
39930
- const fd = fs12.openSync(filePath, "r", O_NOFOLLOW);
40131
+ const fd = fs13.openSync(filePath, "r", O_NOFOLLOW);
39931
40132
  try {
39932
- buffer = fs12.readFileSync(fd);
40133
+ buffer = fs13.readFileSync(fd);
39933
40134
  } finally {
39934
- fs12.closeSync(fd);
40135
+ fs13.closeSync(fd);
39935
40136
  }
39936
40137
  } else {
39937
- buffer = fs12.readFileSync(filePath);
40138
+ buffer = fs13.readFileSync(filePath);
39938
40139
  }
39939
40140
  if (isBinaryFile(filePath, buffer)) {
39940
40141
  return findings;
@@ -39976,9 +40177,9 @@ function isSymlinkLoop(realPath, visited) {
39976
40177
  return false;
39977
40178
  }
39978
40179
  function isPathWithinScope(realPath, scanDir) {
39979
- const resolvedScanDir = path22.resolve(scanDir);
39980
- const resolvedRealPath = path22.resolve(realPath);
39981
- return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path22.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
40180
+ const resolvedScanDir = path23.resolve(scanDir);
40181
+ const resolvedRealPath = path23.resolve(realPath);
40182
+ return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path23.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
39982
40183
  }
39983
40184
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
39984
40185
  skippedDirs: 0,
@@ -39989,7 +40190,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
39989
40190
  const files = [];
39990
40191
  let entries;
39991
40192
  try {
39992
- entries = fs12.readdirSync(dir);
40193
+ entries = fs13.readdirSync(dir);
39993
40194
  } catch {
39994
40195
  stats.fileErrors++;
39995
40196
  return files;
@@ -40004,15 +40205,15 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
40004
40205
  return a.localeCompare(b);
40005
40206
  });
40006
40207
  for (const entry of entries) {
40007
- const fullPath = path22.join(dir, entry);
40008
- const relPath = path22.relative(scanDir, fullPath).replace(/\\/g, "/");
40208
+ const fullPath = path23.join(dir, entry);
40209
+ const relPath = path23.relative(scanDir, fullPath).replace(/\\/g, "/");
40009
40210
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
40010
40211
  stats.skippedDirs++;
40011
40212
  continue;
40012
40213
  }
40013
40214
  let lstat;
40014
40215
  try {
40015
- lstat = fs12.lstatSync(fullPath);
40216
+ lstat = fs13.lstatSync(fullPath);
40016
40217
  } catch {
40017
40218
  stats.fileErrors++;
40018
40219
  continue;
@@ -40024,7 +40225,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
40024
40225
  if (lstat.isDirectory()) {
40025
40226
  let realPath;
40026
40227
  try {
40027
- realPath = fs12.realpathSync(fullPath);
40228
+ realPath = fs13.realpathSync(fullPath);
40028
40229
  } catch {
40029
40230
  stats.fileErrors++;
40030
40231
  continue;
@@ -40040,7 +40241,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
40040
40241
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
40041
40242
  files.push(...subFiles);
40042
40243
  } else if (lstat.isFile()) {
40043
- const ext = path22.extname(fullPath).toLowerCase();
40244
+ const ext = path23.extname(fullPath).toLowerCase();
40044
40245
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
40045
40246
  files.push(fullPath);
40046
40247
  } else {
@@ -40106,15 +40307,15 @@ var secretscan = createSwarmTool({
40106
40307
  }
40107
40308
  }
40108
40309
  try {
40109
- const _scanDirRaw = path22.resolve(directory);
40310
+ const _scanDirRaw = path23.resolve(directory);
40110
40311
  const scanDir = (() => {
40111
40312
  try {
40112
- return fs12.realpathSync(_scanDirRaw);
40313
+ return fs13.realpathSync(_scanDirRaw);
40113
40314
  } catch {
40114
40315
  return _scanDirRaw;
40115
40316
  }
40116
40317
  })();
40117
- if (!fs12.existsSync(scanDir)) {
40318
+ if (!fs13.existsSync(scanDir)) {
40118
40319
  const errorResult = {
40119
40320
  error: "directory not found",
40120
40321
  scan_dir: directory,
@@ -40125,7 +40326,7 @@ var secretscan = createSwarmTool({
40125
40326
  };
40126
40327
  return JSON.stringify(errorResult, null, 2);
40127
40328
  }
40128
- const dirStat = fs12.statSync(scanDir);
40329
+ const dirStat = fs13.statSync(scanDir);
40129
40330
  if (!dirStat.isDirectory()) {
40130
40331
  const errorResult = {
40131
40332
  error: "target must be a directory, not a file",
@@ -40176,7 +40377,7 @@ var secretscan = createSwarmTool({
40176
40377
  break;
40177
40378
  const fileFindings = scanFileForSecrets(filePath);
40178
40379
  try {
40179
- const stat2 = fs12.statSync(filePath);
40380
+ const stat2 = fs13.statSync(filePath);
40180
40381
  if (stat2.size > MAX_FILE_SIZE_BYTES) {
40181
40382
  skippedFiles++;
40182
40383
  continue;
@@ -40263,12 +40464,12 @@ async function runSecretscan(directory) {
40263
40464
  }
40264
40465
 
40265
40466
  // src/tools/test-runner.ts
40266
- import * as fs16 from "fs";
40267
- import * as path26 from "path";
40467
+ import * as fs17 from "fs";
40468
+ import * as path27 from "path";
40268
40469
 
40269
40470
  // src/test-impact/analyzer.ts
40270
- import fs13 from "fs";
40271
- import path23 from "path";
40471
+ import fs14 from "fs";
40472
+ import path24 from "path";
40272
40473
  var IMPORT_REGEX_ES = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
40273
40474
  var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
40274
40475
  var IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
@@ -40279,7 +40480,7 @@ function normalizePath(p) {
40279
40480
  function isCacheStale(impactMap, generatedAtMs) {
40280
40481
  for (const sourcePath of Object.keys(impactMap)) {
40281
40482
  try {
40282
- const stat2 = fs13.statSync(sourcePath);
40483
+ const stat2 = fs14.statSync(sourcePath);
40283
40484
  if (stat2.mtimeMs > generatedAtMs) {
40284
40485
  return true;
40285
40486
  }
@@ -40293,15 +40494,15 @@ function resolveRelativeImport(fromDir, importPath) {
40293
40494
  if (!importPath.startsWith(".")) {
40294
40495
  return null;
40295
40496
  }
40296
- const resolved = path23.resolve(fromDir, importPath);
40297
- if (path23.extname(resolved)) {
40298
- if (fs13.existsSync(resolved) && fs13.statSync(resolved).isFile()) {
40497
+ const resolved = path24.resolve(fromDir, importPath);
40498
+ if (path24.extname(resolved)) {
40499
+ if (fs14.existsSync(resolved) && fs14.statSync(resolved).isFile()) {
40299
40500
  return normalizePath(resolved);
40300
40501
  }
40301
40502
  } else {
40302
40503
  for (const ext of EXTENSIONS_TO_TRY) {
40303
40504
  const withExt = resolved + ext;
40304
- if (fs13.existsSync(withExt) && fs13.statSync(withExt).isFile()) {
40505
+ if (fs14.existsSync(withExt) && fs14.statSync(withExt).isFile()) {
40305
40506
  return normalizePath(withExt);
40306
40507
  }
40307
40508
  }
@@ -40320,13 +40521,13 @@ function findTestFilesSync(cwd) {
40320
40521
  function walk(dir, visitedInodes) {
40321
40522
  let entries;
40322
40523
  try {
40323
- entries = fs13.readdirSync(dir, { withFileTypes: true });
40524
+ entries = fs14.readdirSync(dir, { withFileTypes: true });
40324
40525
  } catch {
40325
40526
  return;
40326
40527
  }
40327
40528
  let dirInode;
40328
40529
  try {
40329
- dirInode = fs13.statSync(dir).ino;
40530
+ dirInode = fs14.statSync(dir).ino;
40330
40531
  } catch {
40331
40532
  return;
40332
40533
  }
@@ -40339,12 +40540,12 @@ function findTestFilesSync(cwd) {
40339
40540
  for (const entry of entries) {
40340
40541
  if (entry.isDirectory()) {
40341
40542
  if (!skipDirs.has(entry.name)) {
40342
- walk(path23.join(dir, entry.name), visitedInodes);
40543
+ walk(path24.join(dir, entry.name), visitedInodes);
40343
40544
  }
40344
40545
  } else if (entry.isFile()) {
40345
40546
  const name = entry.name;
40346
40547
  if (/\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name)) {
40347
- testFiles.push(normalizePath(path23.join(dir, entry.name)));
40548
+ testFiles.push(normalizePath(path24.join(dir, entry.name)));
40348
40549
  }
40349
40550
  }
40350
40551
  }
@@ -40374,7 +40575,7 @@ async function buildImpactMapInternal(cwd) {
40374
40575
  for (const testFile of testFiles) {
40375
40576
  let content;
40376
40577
  try {
40377
- content = fs13.readFileSync(testFile, "utf-8");
40578
+ content = fs14.readFileSync(testFile, "utf-8");
40378
40579
  } catch {
40379
40580
  continue;
40380
40581
  }
@@ -40382,7 +40583,7 @@ async function buildImpactMapInternal(cwd) {
40382
40583
  continue;
40383
40584
  }
40384
40585
  const imports = extractImports(content);
40385
- const testDir = path23.dirname(testFile);
40586
+ const testDir = path24.dirname(testFile);
40386
40587
  for (const importPath of imports) {
40387
40588
  const resolvedSource = resolveRelativeImport(testDir, importPath);
40388
40589
  if (resolvedSource === null) {
@@ -40404,10 +40605,10 @@ async function buildImpactMap(cwd) {
40404
40605
  return impactMap;
40405
40606
  }
40406
40607
  async function loadImpactMap(cwd) {
40407
- const cachePath = path23.join(cwd, ".swarm", "cache", "impact-map.json");
40408
- if (fs13.existsSync(cachePath)) {
40608
+ const cachePath = path24.join(cwd, ".swarm", "cache", "impact-map.json");
40609
+ if (fs14.existsSync(cachePath)) {
40409
40610
  try {
40410
- const content = fs13.readFileSync(cachePath, "utf-8");
40611
+ const content = fs14.readFileSync(cachePath, "utf-8");
40411
40612
  const data = JSON.parse(content);
40412
40613
  const map3 = data.map;
40413
40614
  const generatedAt = new Date(data.generatedAt).getTime();
@@ -40419,17 +40620,17 @@ async function loadImpactMap(cwd) {
40419
40620
  return buildImpactMap(cwd);
40420
40621
  }
40421
40622
  async function saveImpactMap(cwd, impactMap) {
40422
- const cacheDir = path23.join(cwd, ".swarm", "cache");
40423
- const cachePath = path23.join(cacheDir, "impact-map.json");
40424
- if (!fs13.existsSync(cacheDir)) {
40425
- fs13.mkdirSync(cacheDir, { recursive: true });
40623
+ const cacheDir = path24.join(cwd, ".swarm", "cache");
40624
+ const cachePath = path24.join(cacheDir, "impact-map.json");
40625
+ if (!fs14.existsSync(cacheDir)) {
40626
+ fs14.mkdirSync(cacheDir, { recursive: true });
40426
40627
  }
40427
40628
  const data = {
40428
40629
  generatedAt: new Date().toISOString(),
40429
40630
  fileCount: Object.keys(impactMap).length,
40430
40631
  map: impactMap
40431
40632
  };
40432
- fs13.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf-8");
40633
+ fs14.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf-8");
40433
40634
  }
40434
40635
  async function analyzeImpact(changedFiles, cwd) {
40435
40636
  if (!Array.isArray(changedFiles)) {
@@ -40446,7 +40647,7 @@ async function analyzeImpact(changedFiles, cwd) {
40446
40647
  const impactedTestsSet = new Set;
40447
40648
  const untestedFiles = [];
40448
40649
  for (const changedFile of validFiles) {
40449
- const normalizedChanged = normalizePath(path23.resolve(changedFile));
40650
+ const normalizedChanged = normalizePath(path24.resolve(changedFile));
40450
40651
  const tests = impactMap[normalizedChanged];
40451
40652
  if (tests && tests.length > 0) {
40452
40653
  for (const test of tests) {
@@ -40692,14 +40893,14 @@ function detectFlakyTests(allHistory) {
40692
40893
  }
40693
40894
 
40694
40895
  // src/test-impact/history-store.ts
40695
- import fs14 from "fs";
40696
- import path24 from "path";
40896
+ import fs15 from "fs";
40897
+ import path25 from "path";
40697
40898
  var MAX_HISTORY_PER_TEST = 20;
40698
40899
  var MAX_ERROR_LENGTH = 500;
40699
40900
  var MAX_STACK_LENGTH = 200;
40700
40901
  var MAX_CHANGED_FILES = 50;
40701
40902
  function getHistoryPath(workingDir) {
40702
- return path24.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
40903
+ return path25.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
40703
40904
  }
40704
40905
  function sanitizeErrorMessage(errorMessage) {
40705
40906
  if (errorMessage === undefined) {
@@ -40759,9 +40960,9 @@ function appendTestRun(record3, workingDir) {
40759
40960
  changedFiles: sanitizeChangedFiles(record3.changedFiles || [])
40760
40961
  };
40761
40962
  const historyPath = getHistoryPath(workingDir);
40762
- const historyDir = path24.dirname(historyPath);
40763
- if (!fs14.existsSync(historyDir)) {
40764
- fs14.mkdirSync(historyDir, { recursive: true });
40963
+ const historyDir = path25.dirname(historyPath);
40964
+ if (!fs15.existsSync(historyDir)) {
40965
+ fs15.mkdirSync(historyDir, { recursive: true });
40765
40966
  }
40766
40967
  const existingRecords = readAllRecords(historyPath);
40767
40968
  existingRecords.push(sanitizedRecord);
@@ -40786,24 +40987,24 @@ function appendTestRun(record3, workingDir) {
40786
40987
  `)}
40787
40988
  `;
40788
40989
  const tempPath = `${historyPath}.tmp`;
40789
- fs14.writeFileSync(tempPath, content, "utf-8");
40790
- fs14.renameSync(tempPath, historyPath);
40990
+ fs15.writeFileSync(tempPath, content, "utf-8");
40991
+ fs15.renameSync(tempPath, historyPath);
40791
40992
  } catch (err) {
40792
40993
  try {
40793
40994
  const tempPath = `${historyPath}.tmp`;
40794
- if (fs14.existsSync(tempPath)) {
40795
- fs14.unlinkSync(tempPath);
40995
+ if (fs15.existsSync(tempPath)) {
40996
+ fs15.unlinkSync(tempPath);
40796
40997
  }
40797
40998
  } catch {}
40798
40999
  throw new Error(`Failed to write test history: ${err instanceof Error ? err.message : String(err)}`);
40799
41000
  }
40800
41001
  }
40801
41002
  function readAllRecords(historyPath) {
40802
- if (!fs14.existsSync(historyPath)) {
41003
+ if (!fs15.existsSync(historyPath)) {
40803
41004
  return [];
40804
41005
  }
40805
41006
  try {
40806
- const content = fs14.readFileSync(historyPath, "utf-8");
41007
+ const content = fs15.readFileSync(historyPath, "utf-8");
40807
41008
  const lines = content.split(`
40808
41009
  `);
40809
41010
  const records = [];
@@ -40832,8 +41033,8 @@ function getAllHistory(workingDir) {
40832
41033
  }
40833
41034
 
40834
41035
  // src/tools/resolve-working-directory.ts
40835
- import * as fs15 from "fs";
40836
- import * as path25 from "path";
41036
+ import * as fs16 from "fs";
41037
+ import * as path26 from "path";
40837
41038
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
40838
41039
  if (workingDirectory == null || workingDirectory === "") {
40839
41040
  return { success: true, directory: fallbackDirectory };
@@ -40853,17 +41054,17 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
40853
41054
  };
40854
41055
  }
40855
41056
  }
40856
- const normalizedDir = path25.normalize(workingDirectory);
40857
- const pathParts = normalizedDir.split(path25.sep);
41057
+ const normalizedDir = path26.normalize(workingDirectory);
41058
+ const pathParts = normalizedDir.split(path26.sep);
40858
41059
  if (pathParts.includes("..")) {
40859
41060
  return {
40860
41061
  success: false,
40861
41062
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
40862
41063
  };
40863
41064
  }
40864
- const resolvedDir = path25.resolve(normalizedDir);
41065
+ const resolvedDir = path26.resolve(normalizedDir);
40865
41066
  try {
40866
- const realPath = fs15.realpathSync(resolvedDir);
41067
+ const realPath = fs16.realpathSync(resolvedDir);
40867
41068
  return { success: true, directory: realPath };
40868
41069
  } catch {
40869
41070
  return {
@@ -40944,19 +41145,19 @@ function hasDevDependency(devDeps, ...patterns) {
40944
41145
  return hasPackageJsonDependency(devDeps, ...patterns);
40945
41146
  }
40946
41147
  function detectGoTest(cwd) {
40947
- return fs16.existsSync(path26.join(cwd, "go.mod")) && isCommandAvailable("go");
41148
+ return fs17.existsSync(path27.join(cwd, "go.mod")) && isCommandAvailable("go");
40948
41149
  }
40949
41150
  function detectJavaMaven(cwd) {
40950
- return fs16.existsSync(path26.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
41151
+ return fs17.existsSync(path27.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
40951
41152
  }
40952
41153
  function detectGradle(cwd) {
40953
- const hasBuildFile = fs16.existsSync(path26.join(cwd, "build.gradle")) || fs16.existsSync(path26.join(cwd, "build.gradle.kts"));
40954
- const hasGradlew = fs16.existsSync(path26.join(cwd, "gradlew")) || fs16.existsSync(path26.join(cwd, "gradlew.bat"));
41154
+ const hasBuildFile = fs17.existsSync(path27.join(cwd, "build.gradle")) || fs17.existsSync(path27.join(cwd, "build.gradle.kts"));
41155
+ const hasGradlew = fs17.existsSync(path27.join(cwd, "gradlew")) || fs17.existsSync(path27.join(cwd, "gradlew.bat"));
40955
41156
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
40956
41157
  }
40957
41158
  function detectDotnetTest(cwd) {
40958
41159
  try {
40959
- const files = fs16.readdirSync(cwd);
41160
+ const files = fs17.readdirSync(cwd);
40960
41161
  const hasCsproj = files.some((f) => f.endsWith(".csproj"));
40961
41162
  return hasCsproj && isCommandAvailable("dotnet");
40962
41163
  } catch {
@@ -40964,32 +41165,32 @@ function detectDotnetTest(cwd) {
40964
41165
  }
40965
41166
  }
40966
41167
  function detectCTest(cwd) {
40967
- const hasSource = fs16.existsSync(path26.join(cwd, "CMakeLists.txt"));
40968
- const hasBuildCache = fs16.existsSync(path26.join(cwd, "CMakeCache.txt")) || fs16.existsSync(path26.join(cwd, "build", "CMakeCache.txt"));
41168
+ const hasSource = fs17.existsSync(path27.join(cwd, "CMakeLists.txt"));
41169
+ const hasBuildCache = fs17.existsSync(path27.join(cwd, "CMakeCache.txt")) || fs17.existsSync(path27.join(cwd, "build", "CMakeCache.txt"));
40969
41170
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
40970
41171
  }
40971
41172
  function detectSwiftTest(cwd) {
40972
- return fs16.existsSync(path26.join(cwd, "Package.swift")) && isCommandAvailable("swift");
41173
+ return fs17.existsSync(path27.join(cwd, "Package.swift")) && isCommandAvailable("swift");
40973
41174
  }
40974
41175
  function detectDartTest(cwd) {
40975
- return fs16.existsSync(path26.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
41176
+ return fs17.existsSync(path27.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
40976
41177
  }
40977
41178
  function detectRSpec(cwd) {
40978
- const hasRSpecFile = fs16.existsSync(path26.join(cwd, ".rspec"));
40979
- const hasGemfile = fs16.existsSync(path26.join(cwd, "Gemfile"));
40980
- const hasSpecDir = fs16.existsSync(path26.join(cwd, "spec"));
41179
+ const hasRSpecFile = fs17.existsSync(path27.join(cwd, ".rspec"));
41180
+ const hasGemfile = fs17.existsSync(path27.join(cwd, "Gemfile"));
41181
+ const hasSpecDir = fs17.existsSync(path27.join(cwd, "spec"));
40981
41182
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
40982
41183
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
40983
41184
  }
40984
41185
  function detectMinitest(cwd) {
40985
- return fs16.existsSync(path26.join(cwd, "test")) && (fs16.existsSync(path26.join(cwd, "Gemfile")) || fs16.existsSync(path26.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
41186
+ return fs17.existsSync(path27.join(cwd, "test")) && (fs17.existsSync(path27.join(cwd, "Gemfile")) || fs17.existsSync(path27.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
40986
41187
  }
40987
41188
  async function detectTestFramework(cwd) {
40988
41189
  const baseDir = cwd;
40989
41190
  try {
40990
- const packageJsonPath = path26.join(baseDir, "package.json");
40991
- if (fs16.existsSync(packageJsonPath)) {
40992
- const content = fs16.readFileSync(packageJsonPath, "utf-8");
41191
+ const packageJsonPath = path27.join(baseDir, "package.json");
41192
+ if (fs17.existsSync(packageJsonPath)) {
41193
+ const content = fs17.readFileSync(packageJsonPath, "utf-8");
40993
41194
  const pkg = JSON.parse(content);
40994
41195
  const _deps = pkg.dependencies || {};
40995
41196
  const devDeps = pkg.devDependencies || {};
@@ -41008,38 +41209,38 @@ async function detectTestFramework(cwd) {
41008
41209
  return "jest";
41009
41210
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
41010
41211
  return "mocha";
41011
- if (fs16.existsSync(path26.join(baseDir, "bun.lockb")) || fs16.existsSync(path26.join(baseDir, "bun.lock"))) {
41212
+ if (fs17.existsSync(path27.join(baseDir, "bun.lockb")) || fs17.existsSync(path27.join(baseDir, "bun.lock"))) {
41012
41213
  if (scripts.test?.includes("bun"))
41013
41214
  return "bun";
41014
41215
  }
41015
41216
  }
41016
41217
  } catch {}
41017
41218
  try {
41018
- const pyprojectTomlPath = path26.join(baseDir, "pyproject.toml");
41019
- const setupCfgPath = path26.join(baseDir, "setup.cfg");
41020
- const requirementsTxtPath = path26.join(baseDir, "requirements.txt");
41021
- if (fs16.existsSync(pyprojectTomlPath)) {
41022
- const content = fs16.readFileSync(pyprojectTomlPath, "utf-8");
41219
+ const pyprojectTomlPath = path27.join(baseDir, "pyproject.toml");
41220
+ const setupCfgPath = path27.join(baseDir, "setup.cfg");
41221
+ const requirementsTxtPath = path27.join(baseDir, "requirements.txt");
41222
+ if (fs17.existsSync(pyprojectTomlPath)) {
41223
+ const content = fs17.readFileSync(pyprojectTomlPath, "utf-8");
41023
41224
  if (content.includes("[tool.pytest"))
41024
41225
  return "pytest";
41025
41226
  if (content.includes("pytest"))
41026
41227
  return "pytest";
41027
41228
  }
41028
- if (fs16.existsSync(setupCfgPath)) {
41029
- const content = fs16.readFileSync(setupCfgPath, "utf-8");
41229
+ if (fs17.existsSync(setupCfgPath)) {
41230
+ const content = fs17.readFileSync(setupCfgPath, "utf-8");
41030
41231
  if (content.includes("[pytest]"))
41031
41232
  return "pytest";
41032
41233
  }
41033
- if (fs16.existsSync(requirementsTxtPath)) {
41034
- const content = fs16.readFileSync(requirementsTxtPath, "utf-8");
41234
+ if (fs17.existsSync(requirementsTxtPath)) {
41235
+ const content = fs17.readFileSync(requirementsTxtPath, "utf-8");
41035
41236
  if (content.includes("pytest"))
41036
41237
  return "pytest";
41037
41238
  }
41038
41239
  } catch {}
41039
41240
  try {
41040
- const cargoTomlPath = path26.join(baseDir, "Cargo.toml");
41041
- if (fs16.existsSync(cargoTomlPath)) {
41042
- const content = fs16.readFileSync(cargoTomlPath, "utf-8");
41241
+ const cargoTomlPath = path27.join(baseDir, "Cargo.toml");
41242
+ if (fs17.existsSync(cargoTomlPath)) {
41243
+ const content = fs17.readFileSync(cargoTomlPath, "utf-8");
41043
41244
  if (content.includes("[dev-dependencies]")) {
41044
41245
  if (content.includes("tokio") || content.includes("mockall") || content.includes("pretty_assertions")) {
41045
41246
  return "cargo";
@@ -41048,10 +41249,10 @@ async function detectTestFramework(cwd) {
41048
41249
  }
41049
41250
  } catch {}
41050
41251
  try {
41051
- const pesterConfigPath = path26.join(baseDir, "pester.config.ps1");
41052
- const pesterConfigJsonPath = path26.join(baseDir, "pester.config.ps1.json");
41053
- const pesterPs1Path = path26.join(baseDir, "tests.ps1");
41054
- if (fs16.existsSync(pesterConfigPath) || fs16.existsSync(pesterConfigJsonPath) || fs16.existsSync(pesterPs1Path)) {
41252
+ const pesterConfigPath = path27.join(baseDir, "pester.config.ps1");
41253
+ const pesterConfigJsonPath = path27.join(baseDir, "pester.config.ps1.json");
41254
+ const pesterPs1Path = path27.join(baseDir, "tests.ps1");
41255
+ if (fs17.existsSync(pesterConfigPath) || fs17.existsSync(pesterConfigJsonPath) || fs17.existsSync(pesterPs1Path)) {
41055
41256
  return "pester";
41056
41257
  }
41057
41258
  } catch {}
@@ -41075,18 +41276,12 @@ async function detectTestFramework(cwd) {
41075
41276
  return "minitest";
41076
41277
  return "none";
41077
41278
  }
41078
- var TEST_PATTERNS = [
41079
- { test: ".spec.", source: "." },
41080
- { test: ".test.", source: "." },
41081
- { test: "/__tests__/", source: "/" },
41082
- { test: "/tests/", source: "/" },
41083
- { test: "/test/", source: "/" }
41084
- ];
41085
41279
  var COMPOUND_TEST_EXTENSIONS = [
41086
41280
  ".test.ts",
41087
41281
  ".test.tsx",
41088
41282
  ".test.js",
41089
41283
  ".test.jsx",
41284
+ ".tests.ps1",
41090
41285
  ".spec.ts",
41091
41286
  ".spec.tsx",
41092
41287
  ".spec.js",
@@ -41094,51 +41289,149 @@ var COMPOUND_TEST_EXTENSIONS = [
41094
41289
  ".test.ps1",
41095
41290
  ".spec.ps1"
41096
41291
  ];
41292
+ var TEST_DIRECTORY_NAMES = ["__tests__", "tests", "test", "spec"];
41293
+ function isTestDirectoryPath(normalizedPath) {
41294
+ return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
41295
+ }
41296
+ function resolveWorkspacePath(file3, workingDir) {
41297
+ return path27.isAbsolute(file3) ? path27.resolve(file3) : path27.resolve(workingDir, file3);
41298
+ }
41299
+ function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
41300
+ if (!preferRelative)
41301
+ return absolutePath;
41302
+ return path27.relative(workingDir, absolutePath);
41303
+ }
41304
+ function dedupePush(target, value) {
41305
+ if (!target.includes(value)) {
41306
+ target.push(value);
41307
+ }
41308
+ }
41309
+ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
41310
+ switch (ext) {
41311
+ case ".go":
41312
+ return [`${nameWithoutExt}_test.go`];
41313
+ case ".py":
41314
+ return [`test_${nameWithoutExt}.py`, `${nameWithoutExt}_test.py`];
41315
+ case ".rb":
41316
+ return [`${nameWithoutExt}_spec.rb`];
41317
+ case ".java":
41318
+ return [
41319
+ `${nameWithoutExt}Test.java`,
41320
+ `${nameWithoutExt}Tests.java`,
41321
+ `Test${nameWithoutExt}.java`,
41322
+ `${nameWithoutExt}IT.java`
41323
+ ];
41324
+ case ".cs":
41325
+ return [`${nameWithoutExt}Test.cs`, `${nameWithoutExt}Tests.cs`];
41326
+ case ".kt":
41327
+ return [
41328
+ `${nameWithoutExt}Test.kt`,
41329
+ `${nameWithoutExt}Tests.kt`,
41330
+ `Test${nameWithoutExt}.kt`
41331
+ ];
41332
+ case ".ps1":
41333
+ return [`${nameWithoutExt}.Tests.ps1`, `${nameWithoutExt}.tests.ps1`];
41334
+ default:
41335
+ return [];
41336
+ }
41337
+ }
41338
+ function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
41339
+ const relativeDir = path27.dirname(relativePath);
41340
+ const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
41341
+ const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
41342
+ const rootDir = path27.join(workingDir, dirName);
41343
+ return nestedRelativeDir ? [rootDir, path27.join(rootDir, nestedRelativeDir)] : [rootDir];
41344
+ });
41345
+ const normalizedRelativePath = relativePath.replace(/\\/g, "/");
41346
+ if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
41347
+ directories.push(path27.join(workingDir, "src/test/java", path27.dirname(normalizedRelativePath.slice("src/main/java/".length))));
41348
+ }
41349
+ if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
41350
+ directories.push(path27.join(workingDir, "src/test/kotlin", path27.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
41351
+ }
41352
+ return [...new Set(directories)];
41353
+ }
41097
41354
  function hasCompoundTestExtension(filename) {
41098
41355
  const lower = filename.toLowerCase();
41099
41356
  return COMPOUND_TEST_EXTENSIONS.some((ext) => lower.endsWith(ext));
41100
41357
  }
41101
- function getTestFilesFromConvention(sourceFiles) {
41358
+ function isLanguageSpecificTestFile(basename4) {
41359
+ const lower = basename4.toLowerCase();
41360
+ if (lower.endsWith("_test.go"))
41361
+ return true;
41362
+ if (lower.endsWith(".py") && (lower.startsWith("test_") || lower.endsWith("_test.py")))
41363
+ return true;
41364
+ if (lower.endsWith("_spec.rb"))
41365
+ return true;
41366
+ if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename4) || basename4.endsWith("Test.java") || basename4.endsWith("Tests.java") || lower.endsWith("it.java")))
41367
+ return true;
41368
+ if (lower.endsWith(".cs") && (lower.endsWith("test.cs") || lower.endsWith("tests.cs")))
41369
+ return true;
41370
+ if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename4) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
41371
+ return true;
41372
+ if (lower.endsWith(".tests.ps1"))
41373
+ return true;
41374
+ return false;
41375
+ }
41376
+ function isConventionTestFilePath(filePath) {
41377
+ const normalizedPath = filePath.replace(/\\/g, "/");
41378
+ const basename4 = path27.basename(filePath);
41379
+ return hasCompoundTestExtension(basename4) || basename4.includes(".spec.") || basename4.includes(".test.") || isLanguageSpecificTestFile(basename4) || isTestDirectoryPath(normalizedPath);
41380
+ }
41381
+ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
41102
41382
  const testFiles = [];
41103
41383
  for (const file3 of sourceFiles) {
41104
- const normalizedPath = file3.replace(/\\/g, "/");
41105
- const basename4 = path26.basename(file3);
41106
- const dirname10 = path26.dirname(file3);
41107
- if (hasCompoundTestExtension(basename4) || basename4.includes(".spec.") || basename4.includes(".test.") || normalizedPath.includes("/__tests__/") || normalizedPath.includes("/tests/") || normalizedPath.includes("/test/")) {
41108
- if (!testFiles.includes(file3)) {
41109
- testFiles.push(file3);
41110
- }
41384
+ const absoluteFile = resolveWorkspacePath(file3, workingDir);
41385
+ const relativeFile = path27.relative(workingDir, absoluteFile);
41386
+ const basename4 = path27.basename(absoluteFile);
41387
+ const dirname11 = path27.dirname(absoluteFile);
41388
+ const preferRelativeOutput = !path27.isAbsolute(file3);
41389
+ if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
41390
+ dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
41111
41391
  continue;
41112
41392
  }
41113
- for (const _pattern of TEST_PATTERNS) {
41114
- const nameWithoutExt = basename4.replace(/\.[^.]+$/, "");
41115
- const ext = path26.extname(basename4);
41116
- const possibleTestFiles = [
41117
- path26.join(dirname10, `${nameWithoutExt}.spec${ext}`),
41118
- path26.join(dirname10, `${nameWithoutExt}.test${ext}`),
41119
- path26.join(dirname10, "__tests__", `${nameWithoutExt}${ext}`),
41120
- path26.join(dirname10, "tests", `${nameWithoutExt}${ext}`),
41121
- path26.join(dirname10, "test", `${nameWithoutExt}${ext}`)
41122
- ];
41123
- for (const testFile of possibleTestFiles) {
41124
- if (fs16.existsSync(testFile) && !testFiles.includes(testFile)) {
41125
- testFiles.push(testFile);
41126
- }
41393
+ const nameWithoutExt = basename4.replace(/\.[^.]+$/, "");
41394
+ const ext = path27.extname(basename4);
41395
+ const genericTestNames = [
41396
+ `${nameWithoutExt}.spec${ext}`,
41397
+ `${nameWithoutExt}.test${ext}`
41398
+ ];
41399
+ const languageSpecificTestNames = buildLanguageSpecificTestNames(nameWithoutExt, ext);
41400
+ const colocatedCandidates = [
41401
+ ...genericTestNames,
41402
+ ...languageSpecificTestNames
41403
+ ].map((candidateName) => path27.join(dirname11, candidateName));
41404
+ const testDirectoryNames = [
41405
+ basename4,
41406
+ ...genericTestNames,
41407
+ ...languageSpecificTestNames
41408
+ ];
41409
+ const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
41410
+ const possibleTestFiles = [
41411
+ ...colocatedCandidates,
41412
+ ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path27.join(dirname11, dirName, candidateName))),
41413
+ ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path27.join(candidateDir, candidateName)))
41414
+ ];
41415
+ for (const testFile of possibleTestFiles) {
41416
+ if (fs17.existsSync(testFile)) {
41417
+ dedupePush(testFiles, toWorkspaceOutputPath(testFile, workingDir, preferRelativeOutput));
41127
41418
  }
41128
41419
  }
41129
41420
  }
41130
41421
  return testFiles;
41131
41422
  }
41132
- async function getTestFilesFromGraph(sourceFiles) {
41423
+ async function getTestFilesFromGraph(sourceFiles, workingDir) {
41133
41424
  const testFiles = [];
41134
- const candidateTestFiles = getTestFilesFromConvention(sourceFiles);
41425
+ const absoluteSourceFiles = sourceFiles.map((sourceFile) => resolveWorkspacePath(sourceFile, workingDir));
41426
+ const candidateTestFiles = getTestFilesFromConvention(sourceFiles, workingDir);
41135
41427
  if (sourceFiles.length === 0) {
41136
41428
  return testFiles;
41137
41429
  }
41138
41430
  for (const testFile of candidateTestFiles) {
41139
41431
  try {
41140
- const content = fs16.readFileSync(testFile, "utf-8");
41141
- const testDir = path26.dirname(testFile);
41432
+ const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
41433
+ const content = fs17.readFileSync(absoluteTestFile, "utf-8");
41434
+ const testDir = path27.dirname(absoluteTestFile);
41142
41435
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
41143
41436
  let match;
41144
41437
  match = importRegex.exec(content);
@@ -41146,8 +41439,8 @@ async function getTestFilesFromGraph(sourceFiles) {
41146
41439
  const importPath = match[1];
41147
41440
  let resolvedImport;
41148
41441
  if (importPath.startsWith(".")) {
41149
- resolvedImport = path26.resolve(testDir, importPath);
41150
- const existingExt = path26.extname(resolvedImport);
41442
+ resolvedImport = path27.resolve(testDir, importPath);
41443
+ const existingExt = path27.extname(resolvedImport);
41151
41444
  if (!existingExt) {
41152
41445
  for (const extToTry of [
41153
41446
  ".ts",
@@ -41158,7 +41451,7 @@ async function getTestFilesFromGraph(sourceFiles) {
41158
41451
  ".cjs"
41159
41452
  ]) {
41160
41453
  const withExt = resolvedImport + extToTry;
41161
- if (sourceFiles.includes(withExt) || fs16.existsSync(withExt)) {
41454
+ if (absoluteSourceFiles.includes(withExt) || fs17.existsSync(withExt)) {
41162
41455
  resolvedImport = withExt;
41163
41456
  break;
41164
41457
  }
@@ -41167,16 +41460,14 @@ async function getTestFilesFromGraph(sourceFiles) {
41167
41460
  } else {
41168
41461
  continue;
41169
41462
  }
41170
- const importBasename = path26.basename(resolvedImport, path26.extname(resolvedImport));
41171
- const importDir = path26.dirname(resolvedImport);
41172
- for (const sourceFile of sourceFiles) {
41173
- const sourceDir = path26.dirname(sourceFile);
41174
- const sourceBasename = path26.basename(sourceFile, path26.extname(sourceFile));
41175
- const isRelatedDir = importDir === sourceDir || importDir === path26.join(sourceDir, "__tests__") || importDir === path26.join(sourceDir, "tests") || importDir === path26.join(sourceDir, "test");
41463
+ const importBasename = path27.basename(resolvedImport, path27.extname(resolvedImport));
41464
+ const importDir = path27.dirname(resolvedImport);
41465
+ for (const sourceFile of absoluteSourceFiles) {
41466
+ const sourceDir = path27.dirname(sourceFile);
41467
+ const sourceBasename = path27.basename(sourceFile, path27.extname(sourceFile));
41468
+ const isRelatedDir = importDir === sourceDir || importDir === path27.join(sourceDir, "__tests__") || importDir === path27.join(sourceDir, "tests") || importDir === path27.join(sourceDir, "test") || importDir === path27.join(sourceDir, "spec");
41176
41469
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
41177
- if (!testFiles.includes(testFile)) {
41178
- testFiles.push(testFile);
41179
- }
41470
+ dedupePush(testFiles, testFile);
41180
41471
  break;
41181
41472
  }
41182
41473
  }
@@ -41187,8 +41478,8 @@ async function getTestFilesFromGraph(sourceFiles) {
41187
41478
  while (match !== null) {
41188
41479
  const importPath = match[1];
41189
41480
  if (importPath.startsWith(".")) {
41190
- let resolvedImport = path26.resolve(testDir, importPath);
41191
- const existingExt = path26.extname(resolvedImport);
41481
+ let resolvedImport = path27.resolve(testDir, importPath);
41482
+ const existingExt = path27.extname(resolvedImport);
41192
41483
  if (!existingExt) {
41193
41484
  for (const extToTry of [
41194
41485
  ".ts",
@@ -41199,22 +41490,20 @@ async function getTestFilesFromGraph(sourceFiles) {
41199
41490
  ".cjs"
41200
41491
  ]) {
41201
41492
  const withExt = resolvedImport + extToTry;
41202
- if (sourceFiles.includes(withExt) || fs16.existsSync(withExt)) {
41493
+ if (absoluteSourceFiles.includes(withExt) || fs17.existsSync(withExt)) {
41203
41494
  resolvedImport = withExt;
41204
41495
  break;
41205
41496
  }
41206
41497
  }
41207
41498
  }
41208
- const importDir = path26.dirname(resolvedImport);
41209
- const importBasename = path26.basename(resolvedImport, path26.extname(resolvedImport));
41210
- for (const sourceFile of sourceFiles) {
41211
- const sourceDir = path26.dirname(sourceFile);
41212
- const sourceBasename = path26.basename(sourceFile, path26.extname(sourceFile));
41213
- const isRelatedDir = importDir === sourceDir || importDir === path26.join(sourceDir, "__tests__") || importDir === path26.join(sourceDir, "tests") || importDir === path26.join(sourceDir, "test");
41499
+ const importDir = path27.dirname(resolvedImport);
41500
+ const importBasename = path27.basename(resolvedImport, path27.extname(resolvedImport));
41501
+ for (const sourceFile of absoluteSourceFiles) {
41502
+ const sourceDir = path27.dirname(sourceFile);
41503
+ const sourceBasename = path27.basename(sourceFile, path27.extname(sourceFile));
41504
+ const isRelatedDir = importDir === sourceDir || importDir === path27.join(sourceDir, "__tests__") || importDir === path27.join(sourceDir, "tests") || importDir === path27.join(sourceDir, "test") || importDir === path27.join(sourceDir, "spec");
41214
41505
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
41215
- if (!testFiles.includes(testFile)) {
41216
- testFiles.push(testFile);
41217
- }
41506
+ dedupePush(testFiles, testFile);
41218
41507
  break;
41219
41508
  }
41220
41509
  }
@@ -41225,6 +41514,26 @@ async function getTestFilesFromGraph(sourceFiles) {
41225
41514
  }
41226
41515
  return testFiles;
41227
41516
  }
41517
+ function getTargetedExecutionUnsupportedReason(framework) {
41518
+ switch (framework) {
41519
+ case "go-test":
41520
+ return "go test targets packages, not individual test files";
41521
+ case "cargo":
41522
+ return "cargo test targets crates, targets, or test names rather than file paths";
41523
+ case "maven":
41524
+ return "maven test selection is class-based, not file-path based";
41525
+ case "gradle":
41526
+ return "gradle test selection is class-based, not file-path based";
41527
+ case "dotnet-test":
41528
+ return "dotnet test filters by fully qualified names, not file paths";
41529
+ case "ctest":
41530
+ return "ctest filters named tests from the build tree, not source test files";
41531
+ case "swift-test":
41532
+ return "swift test filters test names, not file paths";
41533
+ default:
41534
+ return null;
41535
+ }
41536
+ }
41228
41537
  function buildTestCommand(framework, scope, files, coverage, baseDir) {
41229
41538
  switch (framework) {
41230
41539
  case "bun": {
@@ -41295,8 +41604,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
41295
41604
  return ["mvn", "test"];
41296
41605
  case "gradle": {
41297
41606
  const isWindows = process.platform === "win32";
41298
- const hasGradlewBat = fs16.existsSync(path26.join(baseDir, "gradlew.bat"));
41299
- const hasGradlew = fs16.existsSync(path26.join(baseDir, "gradlew"));
41607
+ const hasGradlewBat = fs17.existsSync(path27.join(baseDir, "gradlew.bat"));
41608
+ const hasGradlew = fs17.existsSync(path27.join(baseDir, "gradlew"));
41300
41609
  if (hasGradlewBat && isWindows)
41301
41610
  return ["gradlew.bat", "test"];
41302
41611
  if (hasGradlew)
@@ -41313,16 +41622,25 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
41313
41622
  "cmake-build-release",
41314
41623
  "out"
41315
41624
  ];
41316
- const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(path26.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
41625
+ const actualBuildDir = buildDirCandidates.find((d) => fs17.existsSync(path27.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
41317
41626
  return ["ctest", "--test-dir", actualBuildDir];
41318
41627
  }
41319
41628
  case "swift-test":
41320
41629
  return ["swift", "test"];
41321
41630
  case "dart-test":
41322
- return isCommandAvailable("flutter") ? ["flutter", "test"] : ["dart", "test"];
41323
- case "rspec":
41324
- return isCommandAvailable("bundle") ? ["bundle", "exec", "rspec"] : ["rspec"];
41631
+ return isCommandAvailable("flutter") ? ["flutter", "test", ...files] : ["dart", "test", ...files];
41632
+ case "rspec": {
41633
+ const args = isCommandAvailable("bundle") ? ["bundle", "exec", "rspec"] : ["rspec"];
41634
+ if (scope !== "all" && files.length > 0) {
41635
+ args.push(...files);
41636
+ }
41637
+ return args;
41638
+ }
41325
41639
  case "minitest":
41640
+ if (scope !== "all" && files.length > 0) {
41641
+ const requires = files.map((f) => `require_relative '${f.replace(/\\/g, "/").replace(/'/g, "\\'")}'`).join("; ");
41642
+ return ["ruby", "-Itest", "-e", requires];
41643
+ }
41326
41644
  return [
41327
41645
  "ruby",
41328
41646
  "-Itest",
@@ -41583,6 +41901,19 @@ async function readBoundedStream(stream, maxBytes) {
41583
41901
  return { text: decoder.decode(combined), truncated };
41584
41902
  }
41585
41903
  async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
41904
+ if (scope !== "all" && files.length > 0) {
41905
+ const unsupportedReason = getTargetedExecutionUnsupportedReason(framework);
41906
+ if (unsupportedReason) {
41907
+ return {
41908
+ success: false,
41909
+ framework,
41910
+ scope,
41911
+ error: `Framework "${framework}" does not support targeted test-file execution`,
41912
+ message: `The resolved test selection cannot be run safely because ${unsupportedReason}. Use a framework-native selector manually or let the architect handle the broader sweep.`,
41913
+ outcome: "error"
41914
+ };
41915
+ }
41916
+ }
41586
41917
  const command = buildTestCommand(framework, scope, files, coverage, cwd);
41587
41918
  if (!command) {
41588
41919
  return {
@@ -41612,9 +41943,9 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
41612
41943
  stderr: "pipe",
41613
41944
  cwd
41614
41945
  });
41615
- const timeoutPromise = new Promise((resolve11) => setTimeout(() => {
41946
+ const timeoutPromise = new Promise((resolve12) => setTimeout(() => {
41616
41947
  proc.kill();
41617
- resolve11(-1);
41948
+ resolve12(-1);
41618
41949
  }, timeout_ms));
41619
41950
  const [exitCode, stdoutResult, stderrResult] = await Promise.all([
41620
41951
  Promise.race([proc.exited, timeoutPromise]),
@@ -41787,10 +42118,10 @@ function analyzeFailures(workingDir) {
41787
42118
  return report;
41788
42119
  }
41789
42120
  var test_runner = createSwarmTool({
41790
- description: 'Run project tests with framework detection. Supports bun, vitest, jest, mocha, pytest, cargo, pester, go-test, maven, gradle, dotnet-test, ctest, swift-test, dart-test, rspec, and minitest. Returns deterministic normalized JSON with framework, scope, command, totals, coverage, duration, success status, and failures. Use scope "all" for full suite, "convention" to map source files to test files, "graph" to find related tests via imports, or "impact" to find tests covering changed files using test-impact analysis.',
42121
+ description: 'Run project tests with framework detection. Supports bun, vitest, jest, mocha, pytest, cargo, pester, go-test, maven, gradle, dotnet-test, ctest, swift-test, dart-test, rspec, and minitest. Returns deterministic normalized JSON with framework, scope, command, totals, coverage, duration, success status, and failures. Use scope "all" for full suite, "convention" to accept direct test files or map source files to test files, "graph" to find related tests via imports from source files, or "impact" to find tests covering changed source files using test-impact analysis.',
41791
42122
  args: {
41792
- scope: tool.schema.enum(["all", "convention", "graph", "impact"]).optional().describe('Test scope: "all" runs full suite, "convention" maps source files to test files by naming, "graph" finds related tests via imports, "impact" finds tests covering changed files via test-impact analysis'),
41793
- files: tool.schema.array(tool.schema.string()).optional().describe("Specific files to test (used with convention or graph scope)"),
42123
+ scope: tool.schema.enum(["all", "convention", "graph", "impact"]).optional().describe('Test scope: "all" runs full suite, "convention" accepts direct test files or maps source files to tests by naming, "graph" finds related tests via imports from source files, "impact" finds tests covering changed source files via test-impact analysis'),
42124
+ files: tool.schema.array(tool.schema.string()).optional().describe('Specific files to test. For "convention", pass source files or direct test files. For "graph" and "impact", pass source files only.'),
41794
42125
  coverage: tool.schema.boolean().optional().describe("Enable coverage reporting if supported"),
41795
42126
  timeout_ms: tool.schema.number().optional().describe("Timeout in milliseconds (default 60000, max 300000)"),
41796
42127
  allow_full_suite: tool.schema.boolean().optional().describe('Explicit opt-in for scope "all". Required because full-suite output can destabilize SSE streaming.'),
@@ -41915,25 +42246,46 @@ var test_runner = createSwarmTool({
41915
42246
  let graphFallbackReason;
41916
42247
  let effectiveScope = scope;
41917
42248
  if (scope === "all") {} else if (scope === "convention") {
41918
- const sourceFiles = args.files.filter((f) => {
41919
- const ext = path26.extname(f).toLowerCase();
42249
+ const directTestFiles = args.files.filter((file3) => isConventionTestFilePath(file3));
42250
+ const sourceFiles = args.files.filter((file3) => {
42251
+ if (directTestFiles.includes(file3))
42252
+ return false;
42253
+ const ext = path27.extname(file3).toLowerCase();
41920
42254
  return SOURCE_EXTENSIONS.has(ext);
41921
42255
  });
41922
- if (sourceFiles.length === 0) {
42256
+ const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
42257
+ if (directTestFiles.length === 0 && sourceFiles.length === 0) {
41923
42258
  const errorResult = {
41924
42259
  success: false,
41925
42260
  framework,
41926
42261
  scope,
41927
- error: "Provided files contain no source files with recognized extensions",
41928
- message: "The files array must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.). Non-source files like README.md or config.json are not valid for test discovery.",
42262
+ error: "Provided files contain no recognized source files or direct test files",
42263
+ message: "The files array must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.) or a direct test file in a supported test location/naming convention.",
42264
+ outcome: "error"
42265
+ };
42266
+ return JSON.stringify(errorResult, null, 2);
42267
+ }
42268
+ if (invalidFiles.length > 0) {
42269
+ const errorResult = {
42270
+ success: false,
42271
+ framework,
42272
+ scope,
42273
+ error: "Provided files include entries that are neither recognized source files nor direct test files",
42274
+ message: `These files are not valid for targeted test discovery: ${invalidFiles.join(", ")}`,
41929
42275
  outcome: "error"
41930
42276
  };
41931
42277
  return JSON.stringify(errorResult, null, 2);
41932
42278
  }
41933
- testFiles = getTestFilesFromConvention(sourceFiles);
42279
+ testFiles = [
42280
+ ...directTestFiles,
42281
+ ...getTestFilesFromConvention(sourceFiles, workingDir)
42282
+ ].filter((file3, index, items) => items.indexOf(file3) === index);
41934
42283
  } else if (scope === "graph") {
41935
42284
  const sourceFiles = args.files.filter((f) => {
41936
- const ext = path26.extname(f).toLowerCase();
42285
+ if (isConventionTestFilePath(f)) {
42286
+ return false;
42287
+ }
42288
+ const ext = path27.extname(f).toLowerCase();
41937
42289
  return SOURCE_EXTENSIONS.has(ext);
41938
42290
  });
41939
42291
  if (sourceFiles.length === 0) {
@@ -41942,22 +42294,25 @@ var test_runner = createSwarmTool({
41942
42294
  framework,
41943
42295
  scope,
41944
42296
  error: "Provided files contain no source files with recognized extensions",
41945
- message: "The files array must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.). Non-source files like README.md or config.json are not valid for test discovery.",
42297
+ message: 'The files array for scope "graph" must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.). Direct test files belong in scope "convention".',
41946
42298
  outcome: "error"
41947
42299
  };
41948
42300
  return JSON.stringify(errorResult, null, 2);
41949
42301
  }
41950
- const graphTestFiles = await getTestFilesFromGraph(sourceFiles);
42302
+ const graphTestFiles = await getTestFilesFromGraph(sourceFiles, workingDir);
41951
42303
  if (graphTestFiles.length > 0) {
41952
42304
  testFiles = graphTestFiles;
41953
42305
  } else {
41954
42306
  graphFallbackReason = "imports resolution returned no results, falling back to convention";
41955
42307
  effectiveScope = "convention";
41956
- testFiles = getTestFilesFromConvention(sourceFiles);
42308
+ testFiles = getTestFilesFromConvention(sourceFiles, workingDir);
41957
42309
  }
41958
42310
  } else if (scope === "impact") {
41959
42311
  const sourceFiles = args.files.filter((f) => {
41960
- const ext = path26.extname(f).toLowerCase();
42312
+ if (isConventionTestFilePath(f)) {
42313
+ return false;
42314
+ }
42315
+ const ext = path27.extname(f).toLowerCase();
41961
42316
  return SOURCE_EXTENSIONS.has(ext);
41962
42317
  });
41963
42318
  if (sourceFiles.length === 0) {
@@ -41966,7 +42321,7 @@ var test_runner = createSwarmTool({
41966
42321
  framework,
41967
42322
  scope,
41968
42323
  error: "Provided files contain no source files with recognized extensions",
41969
- message: "The files array must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.).",
42324
+ message: 'The files array for scope "impact" must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.). Direct test files belong in scope "convention".',
41970
42325
  outcome: "error"
41971
42326
  };
41972
42327
  return JSON.stringify(errorResult, null, 2);
@@ -41975,36 +42330,36 @@ var test_runner = createSwarmTool({
41975
42330
  const impactResult = await analyzeImpact(sourceFiles, workingDir);
41976
42331
  if (impactResult.impactedTests.length > 0) {
41977
42332
  testFiles = impactResult.impactedTests.map((absPath) => {
41978
- const relativePath = path26.relative(workingDir, absPath);
41979
- return path26.isAbsolute(relativePath) ? absPath : relativePath;
42333
+ const relativePath = path27.relative(workingDir, absPath);
42334
+ return path27.isAbsolute(relativePath) ? absPath : relativePath;
41980
42335
  });
41981
42336
  } else {
41982
42337
  graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
41983
42338
  effectiveScope = "graph";
41984
- const graphTestFiles = await getTestFilesFromGraph(sourceFiles);
42339
+ const graphTestFiles = await getTestFilesFromGraph(sourceFiles, workingDir);
41985
42340
  if (graphTestFiles.length > 0) {
41986
42341
  testFiles = graphTestFiles;
41987
42342
  } else {
41988
42343
  graphFallbackReason = "imports resolution returned no results, falling back to convention";
41989
42344
  effectiveScope = "convention";
41990
- testFiles = getTestFilesFromConvention(sourceFiles);
42345
+ testFiles = getTestFilesFromConvention(sourceFiles, workingDir);
41991
42346
  }
41992
42347
  }
41993
42348
  } catch {
41994
42349
  graphFallbackReason = "impact analysis failed, falling back to graph";
41995
42350
  effectiveScope = "graph";
41996
- const graphTestFiles = await getTestFilesFromGraph(sourceFiles);
42351
+ const graphTestFiles = await getTestFilesFromGraph(sourceFiles, workingDir);
41997
42352
  if (graphTestFiles.length > 0) {
41998
42353
  testFiles = graphTestFiles;
41999
42354
  } else {
42000
42355
  graphFallbackReason = "imports resolution returned no results, falling back to convention";
42001
42356
  effectiveScope = "convention";
42002
- testFiles = getTestFilesFromConvention(sourceFiles);
42357
+ testFiles = getTestFilesFromConvention(sourceFiles, workingDir);
42003
42358
  }
42004
42359
  }
42005
42360
  }
42006
42361
  if (scope !== "all" && testFiles.length === 0) {
42007
- const baseMessage = "No matching test files found for the provided source files. Check that test files exist with matching naming conventions (.spec.*, .test.*, __tests__/, tests/, test/).";
42362
+ const baseMessage = "No matching test files found for the provided source files. Check that test files exist with matching naming conventions (.spec.*, .test.*, .Tests.ps1, __tests__/, tests/, test/, spec/).";
42008
42363
  const errorResult = {
42009
42364
  success: false,
42010
42365
  framework,
@@ -42069,8 +42424,8 @@ function validateDirectoryPath(dir) {
42069
42424
  if (dir.includes("..")) {
42070
42425
  throw new Error("Directory path must not contain path traversal sequences");
42071
42426
  }
42072
- const normalized = path27.normalize(dir);
42073
- const absolutePath = path27.isAbsolute(normalized) ? normalized : path27.resolve(normalized);
42427
+ const normalized = path28.normalize(dir);
42428
+ const absolutePath = path28.isAbsolute(normalized) ? normalized : path28.resolve(normalized);
42074
42429
  return absolutePath;
42075
42430
  }
42076
42431
  function validateTimeout(timeoutMs, defaultValue) {
@@ -42093,9 +42448,9 @@ function validateTimeout(timeoutMs, defaultValue) {
42093
42448
  }
42094
42449
  function getPackageVersion(dir) {
42095
42450
  try {
42096
- const packagePath = path27.join(dir, "package.json");
42097
- if (fs17.existsSync(packagePath)) {
42098
- const content = fs17.readFileSync(packagePath, "utf-8");
42451
+ const packagePath = path28.join(dir, "package.json");
42452
+ if (fs18.existsSync(packagePath)) {
42453
+ const content = fs18.readFileSync(packagePath, "utf-8");
42099
42454
  const pkg = JSON.parse(content);
42100
42455
  return pkg.version ?? null;
42101
42456
  }
@@ -42104,9 +42459,9 @@ function getPackageVersion(dir) {
42104
42459
  }
42105
42460
  function getChangelogVersion(dir) {
42106
42461
  try {
42107
- const changelogPath = path27.join(dir, "CHANGELOG.md");
42108
- if (fs17.existsSync(changelogPath)) {
42109
- const content = fs17.readFileSync(changelogPath, "utf-8");
42462
+ const changelogPath = path28.join(dir, "CHANGELOG.md");
42463
+ if (fs18.existsSync(changelogPath)) {
42464
+ const content = fs18.readFileSync(changelogPath, "utf-8");
42110
42465
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
42111
42466
  if (match) {
42112
42467
  return match[1];
@@ -42118,10 +42473,10 @@ function getChangelogVersion(dir) {
42118
42473
  function getVersionFileVersion(dir) {
42119
42474
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
42120
42475
  for (const file3 of possibleFiles) {
42121
- const filePath = path27.join(dir, file3);
42122
- if (fs17.existsSync(filePath)) {
42476
+ const filePath = path28.join(dir, file3);
42477
+ if (fs18.existsSync(filePath)) {
42123
42478
  try {
42124
- const content = fs17.readFileSync(filePath, "utf-8").trim();
42479
+ const content = fs18.readFileSync(filePath, "utf-8").trim();
42125
42480
  const match = content.match(/(\d+\.\d+\.\d+)/);
42126
42481
  if (match) {
42127
42482
  return match[1];
@@ -42445,8 +42800,8 @@ async function runEvidenceCheck(dir) {
42445
42800
  async function runRequirementCoverageCheck(dir, currentPhase) {
42446
42801
  const startTime = Date.now();
42447
42802
  try {
42448
- const specPath = path27.join(dir, ".swarm", "spec.md");
42449
- if (!fs17.existsSync(specPath)) {
42803
+ const specPath = path28.join(dir, ".swarm", "spec.md");
42804
+ if (!fs18.existsSync(specPath)) {
42450
42805
  return {
42451
42806
  type: "req_coverage",
42452
42807
  status: "skip",
@@ -42659,9 +43014,9 @@ async function handlePreflightCommand(directory, _args) {
42659
43014
  return formatPreflightMarkdown(report);
42660
43015
  }
42661
43016
  // src/knowledge/hive-promoter.ts
42662
- import * as fs18 from "fs";
42663
- import * as os5 from "os";
42664
- import * as path28 from "path";
43017
+ import * as fs19 from "fs";
43018
+ import * as os6 from "os";
43019
+ import * as path29 from "path";
42665
43020
  var DANGEROUS_PATTERNS = [
42666
43021
  [/rm\s+-rf/, "rm\\s+-rf"],
42667
43022
  [/:\s*!\s*\|/, ":\\s*!\\s*\\|"],
@@ -42704,16 +43059,16 @@ function validateLesson2(text) {
42704
43059
  }
42705
43060
  function getHiveFilePath() {
42706
43061
  const platform = process.platform;
42707
- const home = os5.homedir();
43062
+ const home = os6.homedir();
42708
43063
  let dataDir;
42709
43064
  if (platform === "win32") {
42710
- dataDir = path28.join(process.env.LOCALAPPDATA || path28.join(home, "AppData", "Local"), "opencode-swarm", "Data");
43065
+ dataDir = path29.join(process.env.LOCALAPPDATA || path29.join(home, "AppData", "Local"), "opencode-swarm", "Data");
42711
43066
  } else if (platform === "darwin") {
42712
- dataDir = path28.join(home, "Library", "Application Support", "opencode-swarm");
43067
+ dataDir = path29.join(home, "Library", "Application Support", "opencode-swarm");
42713
43068
  } else {
42714
- dataDir = path28.join(process.env.XDG_DATA_HOME || path28.join(home, ".local", "share"), "opencode-swarm");
43069
+ dataDir = path29.join(process.env.XDG_DATA_HOME || path29.join(home, ".local", "share"), "opencode-swarm");
42715
43070
  }
42716
- return path28.join(dataDir, "hive-knowledge.jsonl");
43071
+ return path29.join(dataDir, "hive-knowledge.jsonl");
42717
43072
  }
42718
43073
  async function promoteToHive(_directory, lesson, category) {
42719
43074
  const trimmed = (lesson ?? "").trim();
@@ -42725,9 +43080,9 @@ async function promoteToHive(_directory, lesson, category) {
42725
43080
  throw new Error(`Lesson rejected by validator: ${validation.reason}`);
42726
43081
  }
42727
43082
  const hivePath = getHiveFilePath();
42728
- const hiveDir = path28.dirname(hivePath);
42729
- if (!fs18.existsSync(hiveDir)) {
42730
- fs18.mkdirSync(hiveDir, { recursive: true });
43083
+ const hiveDir = path29.dirname(hivePath);
43084
+ if (!fs19.existsSync(hiveDir)) {
43085
+ fs19.mkdirSync(hiveDir, { recursive: true });
42731
43086
  }
42732
43087
  const now = new Date;
42733
43088
  const entry = {
@@ -42741,16 +43096,16 @@ async function promoteToHive(_directory, lesson, category) {
42741
43096
  promotedAt: now.toISOString(),
42742
43097
  retrievalOutcomes: { applied: 0, succeededAfter: 0, failedAfter: 0 }
42743
43098
  };
42744
- fs18.appendFileSync(hivePath, `${JSON.stringify(entry)}
43099
+ fs19.appendFileSync(hivePath, `${JSON.stringify(entry)}
42745
43100
  `, "utf-8");
42746
43101
  const preview = `${trimmed.slice(0, 50)}${trimmed.length > 50 ? "..." : ""}`;
42747
43102
  return `Promoted to hive: "${preview}" (confidence: 1.0, source: manual)`;
42748
43103
  }
42749
43104
  async function promoteFromSwarm(directory, lessonId) {
42750
- const knowledgePath = path28.join(directory, ".swarm", "knowledge.jsonl");
43105
+ const knowledgePath = path29.join(directory, ".swarm", "knowledge.jsonl");
42751
43106
  const entries = [];
42752
- if (fs18.existsSync(knowledgePath)) {
42753
- const content = fs18.readFileSync(knowledgePath, "utf-8");
43107
+ if (fs19.existsSync(knowledgePath)) {
43108
+ const content = fs19.readFileSync(knowledgePath, "utf-8");
42754
43109
  for (const line of content.split(`
42755
43110
  `)) {
42756
43111
  const t = line.trim();
@@ -42774,9 +43129,9 @@ async function promoteFromSwarm(directory, lessonId) {
42774
43129
  throw new Error(`Lesson rejected by validator: ${validation.reason}`);
42775
43130
  }
42776
43131
  const hivePath = getHiveFilePath();
42777
- const hiveDir = path28.dirname(hivePath);
42778
- if (!fs18.existsSync(hiveDir)) {
42779
- fs18.mkdirSync(hiveDir, { recursive: true });
43132
+ const hiveDir = path29.dirname(hivePath);
43133
+ if (!fs19.existsSync(hiveDir)) {
43134
+ fs19.mkdirSync(hiveDir, { recursive: true });
42780
43135
  }
42781
43136
  const now = new Date;
42782
43137
  const hiveEntry = {
@@ -42790,7 +43145,7 @@ async function promoteFromSwarm(directory, lessonId) {
42790
43145
  promotedAt: now.toISOString(),
42791
43146
  retrievalOutcomes: { applied: 0, succeededAfter: 0, failedAfter: 0 }
42792
43147
  };
42793
- fs18.appendFileSync(hivePath, `${JSON.stringify(hiveEntry)}
43148
+ fs19.appendFileSync(hivePath, `${JSON.stringify(hiveEntry)}
42794
43149
  `, "utf-8");
42795
43150
  const preview = `${lessonText.slice(0, 50)}${lessonText.length > 50 ? "..." : ""}`;
42796
43151
  return `Promoted to hive: "${preview}" (confidence: 1.0, source: manual)`;
@@ -42969,7 +43324,7 @@ async function handleQaGatesCommand(directory, args, sessionID) {
42969
43324
  }
42970
43325
 
42971
43326
  // src/commands/reset.ts
42972
- import * as fs19 from "fs";
43327
+ import * as fs20 from "fs";
42973
43328
 
42974
43329
  // src/background/manager.ts
42975
43330
  init_utils();
@@ -43024,13 +43379,13 @@ class CircuitBreaker {
43024
43379
  if (this.config.callTimeoutMs <= 0) {
43025
43380
  return fn();
43026
43381
  }
43027
- return new Promise((resolve12, reject) => {
43382
+ return new Promise((resolve13, reject) => {
43028
43383
  const timeout = setTimeout(() => {
43029
43384
  reject(new Error(`Call timeout after ${this.config.callTimeoutMs}ms`));
43030
43385
  }, this.config.callTimeoutMs);
43031
43386
  fn().then((result) => {
43032
43387
  clearTimeout(timeout);
43033
- resolve12(result);
43388
+ resolve13(result);
43034
43389
  }).catch((error93) => {
43035
43390
  clearTimeout(timeout);
43036
43391
  reject(error93);
@@ -43314,7 +43669,7 @@ class AutomationQueue {
43314
43669
 
43315
43670
  // src/background/worker.ts
43316
43671
  function sleep(ms) {
43317
- return new Promise((resolve12) => setTimeout(resolve12, ms));
43672
+ return new Promise((resolve13) => setTimeout(resolve13, ms));
43318
43673
  }
43319
43674
 
43320
43675
  class WorkerManager {
@@ -43670,8 +44025,8 @@ async function handleResetCommand(directory, args) {
43670
44025
  for (const filename of filesToReset) {
43671
44026
  try {
43672
44027
  const resolvedPath = validateSwarmPath(directory, filename);
43673
- if (fs19.existsSync(resolvedPath)) {
43674
- fs19.unlinkSync(resolvedPath);
44028
+ if (fs20.existsSync(resolvedPath)) {
44029
+ fs20.unlinkSync(resolvedPath);
43675
44030
  results.push(`- \u2705 Deleted ${filename}`);
43676
44031
  } else {
43677
44032
  results.push(`- \u23ED\uFE0F ${filename} not found (skipped)`);
@@ -43688,8 +44043,8 @@ async function handleResetCommand(directory, args) {
43688
44043
  }
43689
44044
  try {
43690
44045
  const summariesPath = validateSwarmPath(directory, "summaries");
43691
- if (fs19.existsSync(summariesPath)) {
43692
- fs19.rmSync(summariesPath, { recursive: true, force: true });
44046
+ if (fs20.existsSync(summariesPath)) {
44047
+ fs20.rmSync(summariesPath, { recursive: true, force: true });
43693
44048
  results.push("- \u2705 Deleted summaries/ directory");
43694
44049
  } else {
43695
44050
  results.push("- \u23ED\uFE0F summaries/ not found (skipped)");
@@ -43709,14 +44064,14 @@ async function handleResetCommand(directory, args) {
43709
44064
 
43710
44065
  // src/commands/reset-session.ts
43711
44066
  init_utils2();
43712
- import * as fs20 from "fs";
43713
- import * as path29 from "path";
44067
+ import * as fs21 from "fs";
44068
+ import * as path30 from "path";
43714
44069
  async function handleResetSessionCommand(directory, _args) {
43715
44070
  const results = [];
43716
44071
  try {
43717
44072
  const statePath = validateSwarmPath(directory, "session/state.json");
43718
- if (fs20.existsSync(statePath)) {
43719
- fs20.unlinkSync(statePath);
44073
+ if (fs21.existsSync(statePath)) {
44074
+ fs21.unlinkSync(statePath);
43720
44075
  results.push("\u2705 Deleted .swarm/session/state.json");
43721
44076
  } else {
43722
44077
  results.push("\u23ED\uFE0F state.json not found (already clean)");
@@ -43725,15 +44080,15 @@ async function handleResetSessionCommand(directory, _args) {
43725
44080
  results.push("\u274C Failed to delete state.json");
43726
44081
  }
43727
44082
  try {
43728
- const sessionDir = path29.dirname(validateSwarmPath(directory, "session/state.json"));
43729
- if (fs20.existsSync(sessionDir)) {
43730
- const files = fs20.readdirSync(sessionDir);
44083
+ const sessionDir = path30.dirname(validateSwarmPath(directory, "session/state.json"));
44084
+ if (fs21.existsSync(sessionDir)) {
44085
+ const files = fs21.readdirSync(sessionDir);
43731
44086
  const otherFiles = files.filter((f) => f !== "state.json");
43732
44087
  let deletedCount = 0;
43733
44088
  for (const file3 of otherFiles) {
43734
- const filePath = path29.join(sessionDir, file3);
43735
- if (fs20.lstatSync(filePath).isFile()) {
43736
- fs20.unlinkSync(filePath);
44089
+ const filePath = path30.join(sessionDir, file3);
44090
+ if (fs21.lstatSync(filePath).isFile()) {
44091
+ fs21.unlinkSync(filePath);
43737
44092
  deletedCount++;
43738
44093
  }
43739
44094
  }
@@ -43761,7 +44116,7 @@ async function handleResetSessionCommand(directory, _args) {
43761
44116
  // src/summaries/manager.ts
43762
44117
  init_utils2();
43763
44118
  init_utils();
43764
- import * as path30 from "path";
44119
+ import * as path31 from "path";
43765
44120
  var SUMMARY_ID_REGEX = /^S\d+$/;
43766
44121
  function sanitizeSummaryId(id) {
43767
44122
  if (!id || id.length === 0) {
@@ -43785,7 +44140,7 @@ function sanitizeSummaryId(id) {
43785
44140
  }
43786
44141
  async function loadFullOutput(directory, id) {
43787
44142
  const sanitizedId = sanitizeSummaryId(id);
43788
- const relativePath = path30.join("summaries", `${sanitizedId}.json`);
44143
+ const relativePath = path31.join("summaries", `${sanitizedId}.json`);
43789
44144
  validateSwarmPath(directory, relativePath);
43790
44145
  const content = await readSwarmFileAsync(directory, relativePath);
43791
44146
  if (content === null) {
@@ -43838,18 +44193,18 @@ ${error93 instanceof Error ? error93.message : String(error93)}`;
43838
44193
 
43839
44194
  // src/commands/rollback.ts
43840
44195
  init_utils2();
43841
- import * as fs21 from "fs";
43842
- import * as path31 from "path";
44196
+ import * as fs22 from "fs";
44197
+ import * as path32 from "path";
43843
44198
  async function handleRollbackCommand(directory, args) {
43844
44199
  const phaseArg = args[0];
43845
44200
  if (!phaseArg) {
43846
44201
  const manifestPath2 = validateSwarmPath(directory, "checkpoints/manifest.json");
43847
- if (!fs21.existsSync(manifestPath2)) {
44202
+ if (!fs22.existsSync(manifestPath2)) {
43848
44203
  return "No checkpoints found. Use `/swarm checkpoint` to create checkpoints.";
43849
44204
  }
43850
44205
  let manifest2;
43851
44206
  try {
43852
- manifest2 = JSON.parse(fs21.readFileSync(manifestPath2, "utf-8"));
44207
+ manifest2 = JSON.parse(fs22.readFileSync(manifestPath2, "utf-8"));
43853
44208
  } catch {
43854
44209
  return "Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.";
43855
44210
  }
@@ -43871,12 +44226,12 @@ async function handleRollbackCommand(directory, args) {
43871
44226
  return "Error: Phase number must be a positive integer.";
43872
44227
  }
43873
44228
  const manifestPath = validateSwarmPath(directory, "checkpoints/manifest.json");
43874
- if (!fs21.existsSync(manifestPath)) {
44229
+ if (!fs22.existsSync(manifestPath)) {
43875
44230
  return `Error: No checkpoints found. Cannot rollback to phase ${targetPhase}.`;
43876
44231
  }
43877
44232
  let manifest;
43878
44233
  try {
43879
- manifest = JSON.parse(fs21.readFileSync(manifestPath, "utf-8"));
44234
+ manifest = JSON.parse(fs22.readFileSync(manifestPath, "utf-8"));
43880
44235
  } catch {
43881
44236
  return `Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.`;
43882
44237
  }
@@ -43886,10 +44241,10 @@ async function handleRollbackCommand(directory, args) {
43886
44241
  return `Error: Checkpoint for phase ${targetPhase} not found. Available phases: ${available}`;
43887
44242
  }
43888
44243
  const checkpointDir = validateSwarmPath(directory, `checkpoints/phase-${targetPhase}`);
43889
- if (!fs21.existsSync(checkpointDir)) {
44244
+ if (!fs22.existsSync(checkpointDir)) {
43890
44245
  return `Error: Checkpoint directory for phase ${targetPhase} does not exist.`;
43891
44246
  }
43892
- const checkpointFiles = fs21.readdirSync(checkpointDir);
44247
+ const checkpointFiles = fs22.readdirSync(checkpointDir);
43893
44248
  if (checkpointFiles.length === 0) {
43894
44249
  return `Error: Checkpoint for phase ${targetPhase} is empty. Cannot rollback.`;
43895
44250
  }
@@ -43897,10 +44252,10 @@ async function handleRollbackCommand(directory, args) {
43897
44252
  const successes = [];
43898
44253
  const failures = [];
43899
44254
  for (const file3 of checkpointFiles) {
43900
- const src = path31.join(checkpointDir, file3);
43901
- const dest = path31.join(swarmDir, file3);
44255
+ const src = path32.join(checkpointDir, file3);
44256
+ const dest = path32.join(swarmDir, file3);
43902
44257
  try {
43903
- fs21.cpSync(src, dest, { recursive: true, force: true });
44258
+ fs22.cpSync(src, dest, { recursive: true, force: true });
43904
44259
  successes.push(file3);
43905
44260
  } catch (error93) {
43906
44261
  failures.push({ file: file3, error: error93.message });
@@ -43917,7 +44272,7 @@ async function handleRollbackCommand(directory, args) {
43917
44272
  timestamp: new Date().toISOString()
43918
44273
  };
43919
44274
  try {
43920
- fs21.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
44275
+ fs22.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
43921
44276
  `);
43922
44277
  } catch (error93) {
43923
44278
  console.error("Failed to write rollback event:", error93 instanceof Error ? error93.message : String(error93));
@@ -43960,11 +44315,11 @@ async function handleSimulateCommand(directory, args) {
43960
44315
  ];
43961
44316
  const report = reportLines.filter(Boolean).join(`
43962
44317
  `);
43963
- const fs22 = await import("fs/promises");
43964
- const path32 = await import("path");
43965
- const reportPath = path32.join(directory, ".swarm", "simulate-report.md");
43966
- await fs22.mkdir(path32.dirname(reportPath), { recursive: true });
43967
- await fs22.writeFile(reportPath, report, "utf-8");
44318
+ const fs23 = await import("fs/promises");
44319
+ const path33 = await import("path");
44320
+ const reportPath = path33.join(directory, ".swarm", "simulate-report.md");
44321
+ await fs23.mkdir(path33.dirname(reportPath), { recursive: true });
44322
+ await fs23.writeFile(reportPath, report, "utf-8");
43968
44323
  return `${darkMatterPairs.length} hidden coupling pairs detected`;
43969
44324
  }
43970
44325
 
@@ -44487,18 +44842,18 @@ function resolveCommand(tokens) {
44487
44842
  }
44488
44843
 
44489
44844
  // src/cli/index.ts
44490
- var CONFIG_DIR = path32.join(process.env.XDG_CONFIG_HOME || path32.join(os6.homedir(), ".config"), "opencode");
44491
- var OPENCODE_CONFIG_PATH = path32.join(CONFIG_DIR, "opencode.json");
44492
- var PLUGIN_CONFIG_PATH = path32.join(CONFIG_DIR, "opencode-swarm.json");
44493
- var PROMPTS_DIR = path32.join(CONFIG_DIR, "opencode-swarm");
44845
+ var CONFIG_DIR = path33.join(process.env.XDG_CONFIG_HOME || path33.join(os7.homedir(), ".config"), "opencode");
44846
+ var OPENCODE_CONFIG_PATH = path33.join(CONFIG_DIR, "opencode.json");
44847
+ var PLUGIN_CONFIG_PATH = path33.join(CONFIG_DIR, "opencode-swarm.json");
44848
+ var PROMPTS_DIR = path33.join(CONFIG_DIR, "opencode-swarm");
44494
44849
  function ensureDir(dir) {
44495
- if (!fs22.existsSync(dir)) {
44496
- fs22.mkdirSync(dir, { recursive: true });
44850
+ if (!fs23.existsSync(dir)) {
44851
+ fs23.mkdirSync(dir, { recursive: true });
44497
44852
  }
44498
44853
  }
44499
44854
  function loadJson(filepath) {
44500
44855
  try {
44501
- const content = fs22.readFileSync(filepath, "utf-8");
44856
+ const content = fs23.readFileSync(filepath, "utf-8");
44502
44857
  const stripped = content.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (match, comment) => comment ? "" : match).replace(/,(\s*[}\]])/g, "$1");
44503
44858
  return JSON.parse(stripped);
44504
44859
  } catch {
@@ -44506,7 +44861,7 @@ function loadJson(filepath) {
44506
44861
  }
44507
44862
  }
44508
44863
  function saveJson(filepath, data) {
44509
- fs22.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
44864
+ fs23.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
44510
44865
  `, "utf-8");
44511
44866
  }
44512
44867
  async function install() {
@@ -44514,7 +44869,7 @@ async function install() {
44514
44869
  `);
44515
44870
  ensureDir(CONFIG_DIR);
44516
44871
  ensureDir(PROMPTS_DIR);
44517
- const LEGACY_CONFIG_PATH = path32.join(CONFIG_DIR, "config.json");
44872
+ const LEGACY_CONFIG_PATH = path33.join(CONFIG_DIR, "config.json");
44518
44873
  let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
44519
44874
  if (!opencodeConfig) {
44520
44875
  const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
@@ -44539,7 +44894,7 @@ async function install() {
44539
44894
  saveJson(OPENCODE_CONFIG_PATH, opencodeConfig);
44540
44895
  console.log("\u2713 Added opencode-swarm to OpenCode plugins");
44541
44896
  console.log("\u2713 Disabled default OpenCode agents (explore, general)");
44542
- if (!fs22.existsSync(PLUGIN_CONFIG_PATH)) {
44897
+ if (!fs23.existsSync(PLUGIN_CONFIG_PATH)) {
44543
44898
  const defaultConfig = {
44544
44899
  agents: {
44545
44900
  coder: { model: "opencode/minimax-m2.5-free" },
@@ -44582,7 +44937,7 @@ async function uninstall() {
44582
44937
  `);
44583
44938
  const opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
44584
44939
  if (!opencodeConfig) {
44585
- if (fs22.existsSync(OPENCODE_CONFIG_PATH)) {
44940
+ if (fs23.existsSync(OPENCODE_CONFIG_PATH)) {
44586
44941
  console.log(`\u2717 Could not parse opencode config at: ${OPENCODE_CONFIG_PATH}`);
44587
44942
  return 1;
44588
44943
  } else {
@@ -44614,13 +44969,13 @@ async function uninstall() {
44614
44969
  console.log("\u2713 Re-enabled default OpenCode agents (explore, general)");
44615
44970
  if (process.argv.includes("--clean")) {
44616
44971
  let cleaned = false;
44617
- if (fs22.existsSync(PLUGIN_CONFIG_PATH)) {
44618
- fs22.unlinkSync(PLUGIN_CONFIG_PATH);
44972
+ if (fs23.existsSync(PLUGIN_CONFIG_PATH)) {
44973
+ fs23.unlinkSync(PLUGIN_CONFIG_PATH);
44619
44974
  console.log(`\u2713 Removed plugin config: ${PLUGIN_CONFIG_PATH}`);
44620
44975
  cleaned = true;
44621
44976
  }
44622
- if (fs22.existsSync(PROMPTS_DIR)) {
44623
- fs22.rmSync(PROMPTS_DIR, { recursive: true });
44977
+ if (fs23.existsSync(PROMPTS_DIR)) {
44978
+ fs23.rmSync(PROMPTS_DIR, { recursive: true });
44624
44979
  console.log(`\u2713 Removed custom prompts: ${PROMPTS_DIR}`);
44625
44980
  cleaned = true;
44626
44981
  }