opencode-swarm 7.5.1 → 7.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/agents/critic.d.ts +13 -0
  2. package/dist/background/event-bus.d.ts +8 -0
  3. package/dist/background/manager.d.ts +9 -0
  4. package/dist/build/discovery.d.ts +7 -0
  5. package/dist/cli/index.js +931 -430
  6. package/dist/commands/registry.d.ts +16 -0
  7. package/dist/config/index.d.ts +13 -0
  8. package/dist/config/schema.d.ts +10 -0
  9. package/dist/db/qa-gate-profile.d.ts +13 -0
  10. package/dist/evidence/manager.d.ts +14 -0
  11. package/dist/git/branch.d.ts +19 -0
  12. package/dist/hooks/curator-drift.d.ts +6 -0
  13. package/dist/hooks/curator.d.ts +13 -0
  14. package/dist/hooks/extractors.d.ts +11 -0
  15. package/dist/hooks/knowledge-curator.d.ts +6 -0
  16. package/dist/hooks/knowledge-migrator.d.ts +52 -1
  17. package/dist/hooks/knowledge-reader.d.ts +4 -0
  18. package/dist/hooks/knowledge-store.d.ts +21 -0
  19. package/dist/hooks/knowledge-validator.d.ts +6 -0
  20. package/dist/hooks/utils.d.ts +14 -0
  21. package/dist/index.js +958 -567
  22. package/dist/lang/detector.d.ts +4 -0
  23. package/dist/lang/index.d.ts +3 -2
  24. package/dist/lang/registry.d.ts +6 -0
  25. package/dist/mutation/engine.d.ts +5 -0
  26. package/dist/mutation/equivalence.d.ts +5 -0
  27. package/dist/mutation/gate.d.ts +8 -0
  28. package/dist/parallel/file-locks.d.ts +15 -0
  29. package/dist/plan/checkpoint.d.ts +4 -0
  30. package/dist/plan/ledger.d.ts +36 -0
  31. package/dist/plan/manager.d.ts +13 -0
  32. package/dist/sast/rules/index.d.ts +14 -0
  33. package/dist/sast/semgrep.d.ts +8 -0
  34. package/dist/services/evidence-summary-service.d.ts +51 -1
  35. package/dist/services/handoff-service.d.ts +68 -0
  36. package/dist/services/preflight-service.d.ts +67 -0
  37. package/dist/services/run-memory.d.ts +22 -0
  38. package/dist/session/snapshot-writer.d.ts +9 -0
  39. package/dist/state.d.ts +26 -0
  40. package/dist/telemetry.d.ts +12 -0
  41. package/dist/test-impact/analyzer.d.ts +20 -0
  42. package/dist/tools/co-change-analyzer.d.ts +12 -0
  43. package/dist/tools/knowledge-recall.d.ts +7 -0
  44. package/dist/tools/lint.d.ts +10 -0
  45. package/dist/tools/quality-budget.d.ts +7 -0
  46. package/dist/tools/sast-baseline.d.ts +10 -0
  47. package/dist/tools/sast-scan.d.ts +8 -0
  48. package/dist/tools/secretscan.d.ts +8 -0
  49. package/dist/tools/write-retro.d.ts +9 -0
  50. package/dist/utils/logger.d.ts +12 -0
  51. package/dist/utils/path-security.d.ts +10 -0
  52. package/dist/utils/spec-hash.d.ts +8 -0
  53. package/package.json +2 -2
package/dist/cli/index.js CHANGED
@@ -34,7 +34,7 @@ var package_default;
34
34
  var init_package = __esm(() => {
35
35
  package_default = {
36
36
  name: "opencode-swarm",
37
- version: "7.5.1",
37
+ version: "7.5.2",
38
38
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
39
39
  main: "dist/index.js",
40
40
  types: "dist/index.d.ts",
@@ -43,7 +43,7 @@ var init_package = __esm(() => {
43
43
  },
44
44
  type: "module",
45
45
  engines: {
46
- bun: ">=1.0.0"
46
+ bun: ">=1.3.13"
47
47
  },
48
48
  license: "MIT",
49
49
  repository: {
@@ -104,7 +104,19 @@ var init_package = __esm(() => {
104
104
  });
105
105
 
106
106
  // src/utils/errors.ts
107
- var init_errors = () => {};
107
+ var SwarmError;
108
+ var init_errors = __esm(() => {
109
+ SwarmError = class SwarmError extends Error {
110
+ code;
111
+ guidance;
112
+ constructor(message, code, guidance) {
113
+ super(message);
114
+ this.name = "SwarmError";
115
+ this.code = code;
116
+ this.guidance = guidance;
117
+ }
118
+ };
119
+ });
108
120
 
109
121
  // src/utils/logger.ts
110
122
  function isDebug() {
@@ -130,6 +142,7 @@ function warn(message, data) {
130
142
  console.warn(`[opencode-swarm ${timestamp}] WARN: ${message}`);
131
143
  }
132
144
  }
145
+ var init_logger = () => {};
133
146
 
134
147
  // src/utils/merge.ts
135
148
  function deepMergeInternal(base, override, depth) {
@@ -169,6 +182,7 @@ function simpleGlobToRegex(pattern, flags = "i") {
169
182
  // src/utils/index.ts
170
183
  var init_utils = __esm(() => {
171
184
  init_errors();
185
+ init_logger();
172
186
  });
173
187
 
174
188
  // src/utils/bun-compat.ts
@@ -500,6 +514,32 @@ var init_bun_compat = () => {};
500
514
 
501
515
  // src/hooks/utils.ts
502
516
  import * as path2 from "path";
517
+ function safeHook(fn) {
518
+ return async (input, output) => {
519
+ try {
520
+ await fn(input, output);
521
+ } catch (_error) {
522
+ const functionName = fn.name || "unknown";
523
+ if (_error instanceof SwarmError) {
524
+ warn(`Hook '${functionName}' failed: ${_error.message}
525
+ \u2192 ${_error.guidance}`);
526
+ } else {
527
+ warn(`Hook function '${functionName}' failed:`, _error);
528
+ }
529
+ }
530
+ };
531
+ }
532
+ function composeHandlers(...fns) {
533
+ if (fns.length === 0) {
534
+ return async () => {};
535
+ }
536
+ return async (input, output) => {
537
+ for (const fn of fns) {
538
+ const safeFn = _internals.safeHook(fn);
539
+ await safeFn(input, output);
540
+ }
541
+ };
542
+ }
503
543
  function validateSwarmPath(directory, filename) {
504
544
  if (/[\0]/.test(filename)) {
505
545
  throw new Error("Invalid filename: contains null bytes");
@@ -528,7 +568,7 @@ function validateSwarmPath(directory, filename) {
528
568
  }
529
569
  async function readSwarmFileAsync(directory, filename) {
530
570
  try {
531
- const resolvedPath = validateSwarmPath(directory, filename);
571
+ const resolvedPath = _internals.validateSwarmPath(directory, filename);
532
572
  const file = bunFile(resolvedPath);
533
573
  const content = await file.text();
534
574
  return content;
@@ -536,9 +576,11 @@ async function readSwarmFileAsync(directory, filename) {
536
576
  return null;
537
577
  }
538
578
  }
579
+ var _internals;
539
580
  var init_utils2 = __esm(() => {
540
581
  init_utils();
541
582
  init_bun_compat();
583
+ _internals = { safeHook, composeHandlers, validateSwarmPath, readSwarmFileAsync };
542
584
  });
543
585
 
544
586
  // node_modules/zod/v4/core/core.js
@@ -14519,7 +14561,7 @@ async function computeSpecHash(directory) {
14519
14561
  return hash2;
14520
14562
  }
14521
14563
  async function isSpecStale(directory, plan) {
14522
- const currentHash = await computeSpecHash(directory);
14564
+ const currentHash = await _internals2.computeSpecHash(directory);
14523
14565
  if (!plan.specHash) {
14524
14566
  return { stale: false };
14525
14567
  }
@@ -14539,7 +14581,13 @@ async function isSpecStale(directory, plan) {
14539
14581
  }
14540
14582
  return { stale: false };
14541
14583
  }
14542
- var init_spec_hash = () => {};
14584
+ var _internals2;
14585
+ var init_spec_hash = __esm(() => {
14586
+ _internals2 = {
14587
+ computeSpecHash,
14588
+ isSpecStale
14589
+ };
14590
+ });
14543
14591
 
14544
14592
  // src/plan/ledger.ts
14545
14593
  import * as crypto2 from "crypto";
@@ -15113,7 +15161,7 @@ async function loadPlan(directory) {
15113
15161
  const inSync = await isPlanMdInSync(directory, validated);
15114
15162
  if (!inSync) {
15115
15163
  try {
15116
- await regeneratePlanMarkdown(directory, validated);
15164
+ await _internals3.regeneratePlanMarkdown(directory, validated);
15117
15165
  } catch (regenError) {
15118
15166
  warn(`Failed to regenerate plan.md: ${regenError instanceof Error ? regenError.message : String(regenError)}. Proceeding with plan.json only.`);
15119
15167
  }
@@ -15246,7 +15294,7 @@ async function loadPlan(directory) {
15246
15294
  const existingMutex = recoveryMutexes.get(resolvedDir);
15247
15295
  if (existingMutex) {
15248
15296
  await existingMutex;
15249
- const postRecoveryPlan = await loadPlanJsonOnly(directory);
15297
+ const postRecoveryPlan = await _internals3.loadPlanJsonOnly(directory);
15250
15298
  if (postRecoveryPlan)
15251
15299
  return postRecoveryPlan;
15252
15300
  }
@@ -15300,7 +15348,7 @@ async function savePlan(directory, plan, options) {
15300
15348
  const validated = PlanSchema.parse(plan);
15301
15349
  if (options?.preserveCompletedStatuses !== false) {
15302
15350
  try {
15303
- const currentPlan2 = await loadPlanJsonOnly(directory);
15351
+ const currentPlan2 = await _internals3.loadPlanJsonOnly(directory);
15304
15352
  if (currentPlan2) {
15305
15353
  const completedTaskIds = new Set;
15306
15354
  for (const phase of currentPlan2.phases) {
@@ -15333,7 +15381,7 @@ async function savePlan(directory, plan, options) {
15333
15381
  phase.status = "pending";
15334
15382
  }
15335
15383
  }
15336
- const currentPlan = await loadPlanJsonOnly(directory);
15384
+ const currentPlan = await _internals3.loadPlanJsonOnly(directory);
15337
15385
  const planId = `${validated.swarm}-${validated.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
15338
15386
  const planHashForInit = computePlanHash(validated);
15339
15387
  if (!await ledgerExists(directory)) {
@@ -15449,7 +15497,7 @@ async function savePlan(directory, plan, options) {
15449
15497
  expectedHash: currentHash,
15450
15498
  planHashAfter: hashAfter,
15451
15499
  verifyValid: async () => {
15452
- const onDisk = await loadPlanJsonOnly(directory);
15500
+ const onDisk = await _internals3.loadPlanJsonOnly(directory);
15453
15501
  if (!onDisk)
15454
15502
  return true;
15455
15503
  for (const p of onDisk.phases) {
@@ -15829,7 +15877,7 @@ function migrateLegacyPlan(planContent, swarmId) {
15829
15877
  };
15830
15878
  return plan;
15831
15879
  }
15832
- var PlanConcurrentModificationError, startupLedgerCheckedWorkspaces, recoveryMutexes, CAS_BACKOFF_START_MS = 5, CAS_BACKOFF_CAP_MS = 250, CAS_BACKOFF_JITTER = 0.25, CAS_MAX_RETRIES = 3;
15880
+ var PlanConcurrentModificationError, startupLedgerCheckedWorkspaces, recoveryMutexes, _internals3, CAS_BACKOFF_START_MS = 5, CAS_BACKOFF_CAP_MS = 250, CAS_BACKOFF_JITTER = 0.25, CAS_MAX_RETRIES = 3;
15833
15881
  var init_manager = __esm(() => {
15834
15882
  init_plan_schema();
15835
15883
  init_utils2();
@@ -15846,6 +15894,11 @@ var init_manager = __esm(() => {
15846
15894
  };
15847
15895
  startupLedgerCheckedWorkspaces = new Set;
15848
15896
  recoveryMutexes = new Map;
15897
+ _internals3 = {
15898
+ loadPlan,
15899
+ loadPlanJsonOnly,
15900
+ regeneratePlanMarkdown
15901
+ };
15849
15902
  });
15850
15903
 
15851
15904
  // src/commands/acknowledge-spec-drift.ts
@@ -19360,7 +19413,7 @@ async function loadEvidence(directory, taskId) {
19360
19413
  return { status: "invalid_schema", errors: ["Invalid JSON"] };
19361
19414
  }
19362
19415
  if (isFlatRetrospective(parsed)) {
19363
- const wrappedBundle = wrapFlatRetrospective(parsed, sanitizedTaskId);
19416
+ const wrappedBundle = _internals4.wrapFlatRetrospective(parsed, sanitizedTaskId);
19364
19417
  try {
19365
19418
  const validated = EvidenceBundleSchema.parse(wrappedBundle);
19366
19419
  try {
@@ -19456,14 +19509,14 @@ async function checkRequirementCoverage(phase, directory) {
19456
19509
  }
19457
19510
  }
19458
19511
  async function archiveEvidence(directory, maxAgeDays, maxBundles) {
19459
- const taskIds = await listEvidenceTaskIds(directory);
19512
+ const taskIds = await _internals4.listEvidenceTaskIds(directory);
19460
19513
  const cutoffDate = new Date;
19461
19514
  cutoffDate.setDate(cutoffDate.getDate() - maxAgeDays);
19462
19515
  const cutoffIso = cutoffDate.toISOString();
19463
19516
  const archived = [];
19464
19517
  const remainingBundles = [];
19465
19518
  for (const taskId of taskIds) {
19466
- const result = await loadEvidence(directory, taskId);
19519
+ const result = await _internals4.loadEvidence(directory, taskId);
19467
19520
  if (result.status !== "found") {
19468
19521
  continue;
19469
19522
  }
@@ -19491,7 +19544,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles) {
19491
19544
  }
19492
19545
  return archived;
19493
19546
  }
19494
- var VALID_EVIDENCE_TYPES, sanitizeTaskId2, LEGACY_TASK_COMPLEXITY_MAP;
19547
+ var VALID_EVIDENCE_TYPES, sanitizeTaskId2, LEGACY_TASK_COMPLEXITY_MAP, _internals4;
19495
19548
  var init_manager2 = __esm(() => {
19496
19549
  init_zod();
19497
19550
  init_evidence_schema();
@@ -19521,6 +19574,11 @@ var init_manager2 = __esm(() => {
19521
19574
  medium: "moderate",
19522
19575
  high: "complex"
19523
19576
  };
19577
+ _internals4 = {
19578
+ wrapFlatRetrospective,
19579
+ loadEvidence,
19580
+ listEvidenceTaskIds
19581
+ };
19524
19582
  });
19525
19583
 
19526
19584
  // src/commands/archive.ts
@@ -19720,7 +19778,7 @@ function getProfile(directory, planId) {
19720
19778
  return row ? rowToProfile(row) : null;
19721
19779
  }
19722
19780
  function getOrCreateProfile(directory, planId, projectType) {
19723
- const existing = getProfile(directory, planId);
19781
+ const existing = _internals5.getProfile(directory, planId);
19724
19782
  if (existing)
19725
19783
  return existing;
19726
19784
  const db = getProjectDb(directory);
@@ -19736,14 +19794,14 @@ function getOrCreateProfile(directory, planId, projectType) {
19736
19794
  throw err;
19737
19795
  }
19738
19796
  }
19739
- const after = getProfile(directory, planId);
19797
+ const after = _internals5.getProfile(directory, planId);
19740
19798
  if (!after) {
19741
19799
  throw new Error(`Failed to create or load QA gate profile for plan_id=${planId}`);
19742
19800
  }
19743
19801
  return after;
19744
19802
  }
19745
19803
  function setGates(directory, planId, gates) {
19746
- const current = getProfile(directory, planId);
19804
+ const current = _internals5.getProfile(directory, planId);
19747
19805
  if (!current) {
19748
19806
  throw new Error(`No QA gate profile found for plan_id=${planId} \u2014 call getOrCreateProfile first`);
19749
19807
  }
@@ -19767,7 +19825,7 @@ function setGates(directory, planId, gates) {
19767
19825
  JSON.stringify(merged),
19768
19826
  planId
19769
19827
  ]);
19770
- const updated = getProfile(directory, planId);
19828
+ const updated = _internals5.getProfile(directory, planId);
19771
19829
  if (!updated) {
19772
19830
  throw new Error(`Failed to re-read QA gate profile after update for plan_id=${planId}`);
19773
19831
  }
@@ -19789,9 +19847,16 @@ function getEffectiveGates(profile, sessionOverrides) {
19789
19847
  }
19790
19848
  return merged;
19791
19849
  }
19792
- var DEFAULT_QA_GATES;
19850
+ var _internals5, DEFAULT_QA_GATES;
19793
19851
  var init_qa_gate_profile = __esm(() => {
19794
19852
  init_project_db();
19853
+ _internals5 = {
19854
+ getProfile,
19855
+ getOrCreateProfile,
19856
+ setGates,
19857
+ getEffectiveGates,
19858
+ computeProfileHash
19859
+ };
19795
19860
  DEFAULT_QA_GATES = {
19796
19861
  reviewer: true,
19797
19862
  test_engineer: true,
@@ -20121,6 +20186,7 @@ var init_config = __esm(() => {
20121
20186
  init_constants();
20122
20187
  init_evidence_schema();
20123
20188
  init_loader();
20189
+ init_loader();
20124
20190
  init_plan_schema();
20125
20191
  init_schema();
20126
20192
  init_spec_schema();
@@ -20245,6 +20311,9 @@ ${RESPONSE_FORMAT}
20245
20311
  ${HARD_RULES}
20246
20312
  `;
20247
20313
  });
20314
+
20315
+ // src/agents/critic.ts
20316
+ var init_critic = () => {};
20248
20317
  // src/agents/curator-agent.ts
20249
20318
  var init_curator_agent = () => {};
20250
20319
  // src/agents/reviewer.ts
@@ -20258,10 +20327,12 @@ var init_agents2 = __esm(() => {
20258
20327
  init_warning_buffer();
20259
20328
  init_architect();
20260
20329
  init_council_prompts();
20330
+ init_critic();
20261
20331
  init_curator_agent();
20262
20332
  init_reviewer();
20263
20333
  init_architect();
20264
20334
  init_council_prompts();
20335
+ init_critic();
20265
20336
  init_curator_agent();
20266
20337
  init_reviewer();
20267
20338
  warnedAgents = new Set;
@@ -20356,6 +20427,7 @@ function extractCurrentPhaseFromPlan(plan) {
20356
20427
  const statusText = statusMap[phase.status] || "PENDING";
20357
20428
  return `Phase ${phase.id}: ${phase.name} [${statusText}]`;
20358
20429
  }
20430
+ var init_extractors = () => {};
20359
20431
 
20360
20432
  // src/hooks/loop-detector.ts
20361
20433
  var init_loop_detector = __esm(() => {
@@ -20385,8 +20457,10 @@ var init_guardrails = __esm(() => {
20385
20457
  init_telemetry();
20386
20458
  init_utils();
20387
20459
  init_bun_compat();
20460
+ init_logger();
20388
20461
  init_conflict_resolution();
20389
20462
  init_delegation_gate();
20463
+ init_extractors();
20390
20464
  init_loop_detector();
20391
20465
  init_model_limits();
20392
20466
  init_normalize_tool_name();
@@ -20434,6 +20508,7 @@ var init_delegation_gate = __esm(() => {
20434
20508
  init_schema();
20435
20509
  init_state();
20436
20510
  init_telemetry();
20511
+ init_logger();
20437
20512
  init_guardrails();
20438
20513
  init_normalize_tool_name();
20439
20514
  init_utils2();
@@ -34022,6 +34097,19 @@ function getCurrentBranch(cwd) {
34022
34097
  const output = gitExec2(["rev-parse", "--abbrev-ref", "HEAD"], cwd);
34023
34098
  return output.trim();
34024
34099
  }
34100
+ function getDefaultBaseBranch(cwd) {
34101
+ try {
34102
+ gitExec2(["rev-parse", "--verify", "origin/main"], cwd);
34103
+ return "origin/main";
34104
+ } catch {
34105
+ try {
34106
+ gitExec2(["rev-parse", "--verify", "origin/master"], cwd);
34107
+ return "origin/master";
34108
+ } catch {
34109
+ return "origin/main";
34110
+ }
34111
+ }
34112
+ }
34025
34113
  function hasUncommittedChanges(cwd) {
34026
34114
  const status = gitExec2(["status", "--porcelain"], cwd);
34027
34115
  return status.trim().length > 0;
@@ -34057,7 +34145,7 @@ function resetToRemoteBranch(cwd, options) {
34057
34145
  const prunedBranches = [];
34058
34146
  try {
34059
34147
  const currentBranch = getCurrentBranch(cwd);
34060
- const defaultRemoteBranch = detectDefaultRemoteBranch(cwd);
34148
+ const defaultRemoteBranch = _internals6.detectDefaultRemoteBranch(cwd);
34061
34149
  if (!defaultRemoteBranch) {
34062
34150
  return {
34063
34151
  success: false,
@@ -34236,8 +34324,16 @@ function resetToRemoteBranch(cwd, options) {
34236
34324
  };
34237
34325
  }
34238
34326
  }
34239
- var GIT_TIMEOUT_MS2 = 30000;
34240
- var init_branch = () => {};
34327
+ var GIT_TIMEOUT_MS2 = 30000, _internals6;
34328
+ var init_branch = __esm(() => {
34329
+ init_logger();
34330
+ _internals6 = {
34331
+ gitExec: gitExec2,
34332
+ detectDefaultRemoteBranch,
34333
+ getDefaultBaseBranch,
34334
+ resetToRemoteBranch
34335
+ };
34336
+ });
34241
34337
 
34242
34338
  // src/hooks/knowledge-store.ts
34243
34339
  import { existsSync as existsSync7 } from "fs";
@@ -34407,13 +34503,77 @@ var init_knowledge_store = __esm(() => {
34407
34503
  });
34408
34504
 
34409
34505
  // src/hooks/knowledge-reader.ts
34506
+ import { existsSync as existsSync8 } from "fs";
34507
+ import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
34508
+ import * as path11 from "path";
34509
+ async function updateRetrievalOutcome(directory, phaseInfo, phaseSucceeded) {
34510
+ const shownFile = path11.join(directory, ".swarm", ".knowledge-shown.json");
34511
+ try {
34512
+ if (!existsSync8(shownFile)) {
34513
+ return;
34514
+ }
34515
+ const content = await readFile4(shownFile, "utf-8");
34516
+ const shownData = JSON.parse(content);
34517
+ const shownIds = shownData[phaseInfo];
34518
+ if (!shownIds || shownIds.length === 0) {
34519
+ return;
34520
+ }
34521
+ const swarmPath = resolveSwarmKnowledgePath(directory);
34522
+ const entries = await readKnowledge(swarmPath);
34523
+ let updated = false;
34524
+ const foundInSwarm = new Set;
34525
+ for (const entry of entries) {
34526
+ if (shownIds.includes(entry.id)) {
34527
+ entry.retrieval_outcomes.applied_count++;
34528
+ if (phaseSucceeded) {
34529
+ entry.retrieval_outcomes.succeeded_after_count++;
34530
+ } else {
34531
+ entry.retrieval_outcomes.failed_after_count++;
34532
+ }
34533
+ updated = true;
34534
+ foundInSwarm.add(entry.id);
34535
+ }
34536
+ }
34537
+ if (updated) {
34538
+ await rewriteKnowledge(swarmPath, entries);
34539
+ }
34540
+ const remainingIds = shownIds.filter((id) => !foundInSwarm.has(id));
34541
+ if (remainingIds.length === 0) {
34542
+ delete shownData[phaseInfo];
34543
+ await writeFile4(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
34544
+ return;
34545
+ }
34546
+ const hivePath = resolveHiveKnowledgePath();
34547
+ const hiveEntries = await readKnowledge(hivePath);
34548
+ let hiveUpdated = false;
34549
+ for (const entry of hiveEntries) {
34550
+ if (remainingIds.includes(entry.id)) {
34551
+ entry.retrieval_outcomes.applied_count++;
34552
+ if (phaseSucceeded) {
34553
+ entry.retrieval_outcomes.succeeded_after_count++;
34554
+ } else {
34555
+ entry.retrieval_outcomes.failed_after_count++;
34556
+ }
34557
+ hiveUpdated = true;
34558
+ }
34559
+ }
34560
+ if (hiveUpdated) {
34561
+ await rewriteKnowledge(hivePath, hiveEntries);
34562
+ }
34563
+ delete shownData[phaseInfo];
34564
+ await writeFile4(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
34565
+ } catch {
34566
+ warn("[swarm] Knowledge: failed to update retrieval outcomes");
34567
+ }
34568
+ }
34410
34569
  var init_knowledge_reader = __esm(() => {
34570
+ init_logger();
34411
34571
  init_knowledge_store();
34412
34572
  });
34413
34573
 
34414
34574
  // src/hooks/knowledge-validator.ts
34415
- import { appendFile as appendFile3, mkdir as mkdir3, writeFile as writeFile4 } from "fs/promises";
34416
- import * as path11 from "path";
34575
+ import { appendFile as appendFile3, mkdir as mkdir4, writeFile as writeFile5 } from "fs/promises";
34576
+ import * as path12 from "path";
34417
34577
  function normalizeText(text) {
34418
34578
  return text.normalize("NFKC").toLowerCase().replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
34419
34579
  }
@@ -34567,11 +34727,11 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
34567
34727
  return;
34568
34728
  }
34569
34729
  const sanitizedReason = reason.slice(0, 500).replace(/[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f\x0d]/g, "");
34570
- const knowledgePath = path11.join(directory, ".swarm", "knowledge.jsonl");
34571
- const quarantinePath = path11.join(directory, ".swarm", "knowledge-quarantined.jsonl");
34572
- const rejectedPath = path11.join(directory, ".swarm", "knowledge-rejected.jsonl");
34573
- const swarmDir = path11.join(directory, ".swarm");
34574
- await mkdir3(swarmDir, { recursive: true });
34730
+ const knowledgePath = path12.join(directory, ".swarm", "knowledge.jsonl");
34731
+ const quarantinePath = path12.join(directory, ".swarm", "knowledge-quarantined.jsonl");
34732
+ const rejectedPath = path12.join(directory, ".swarm", "knowledge-rejected.jsonl");
34733
+ const swarmDir = path12.join(directory, ".swarm");
34734
+ await mkdir4(swarmDir, { recursive: true });
34575
34735
  let release;
34576
34736
  try {
34577
34737
  release = await import_proper_lockfile4.default.lock(swarmDir, {
@@ -34592,7 +34752,7 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
34592
34752
  const jsonlContent = remaining.length > 0 ? `${remaining.map((e) => JSON.stringify(e)).join(`
34593
34753
  `)}
34594
34754
  ` : "";
34595
- await writeFile4(knowledgePath, jsonlContent, "utf-8");
34755
+ await writeFile5(knowledgePath, jsonlContent, "utf-8");
34596
34756
  await appendFile3(quarantinePath, `${JSON.stringify(quarantined)}
34597
34757
  `, "utf-8");
34598
34758
  const quarantinedEntries = await readKnowledge(quarantinePath);
@@ -34601,7 +34761,7 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
34601
34761
  const capContent = trimmed.length > 0 ? `${trimmed.map((e) => JSON.stringify(e)).join(`
34602
34762
  `)}
34603
34763
  ` : "";
34604
- await writeFile4(quarantinePath, capContent, "utf-8");
34764
+ await writeFile5(quarantinePath, capContent, "utf-8");
34605
34765
  }
34606
34766
  const rejectedRecord = {
34607
34767
  id: entryId,
@@ -34627,11 +34787,11 @@ async function restoreEntry(directory, entryId) {
34627
34787
  warn("[knowledge-validator] restoreEntry: invalid entryId rejected");
34628
34788
  return;
34629
34789
  }
34630
- const knowledgePath = path11.join(directory, ".swarm", "knowledge.jsonl");
34631
- const quarantinePath = path11.join(directory, ".swarm", "knowledge-quarantined.jsonl");
34632
- const rejectedPath = path11.join(directory, ".swarm", "knowledge-rejected.jsonl");
34633
- const swarmDir = path11.join(directory, ".swarm");
34634
- await mkdir3(swarmDir, { recursive: true });
34790
+ const knowledgePath = path12.join(directory, ".swarm", "knowledge.jsonl");
34791
+ const quarantinePath = path12.join(directory, ".swarm", "knowledge-quarantined.jsonl");
34792
+ const rejectedPath = path12.join(directory, ".swarm", "knowledge-rejected.jsonl");
34793
+ const swarmDir = path12.join(directory, ".swarm");
34794
+ await mkdir4(swarmDir, { recursive: true });
34635
34795
  let release;
34636
34796
  try {
34637
34797
  release = await import_proper_lockfile4.default.lock(swarmDir, {
@@ -34647,7 +34807,7 @@ async function restoreEntry(directory, entryId) {
34647
34807
  const jsonlContent = remaining.length > 0 ? `${remaining.map((e) => JSON.stringify(e)).join(`
34648
34808
  `)}
34649
34809
  ` : "";
34650
- await writeFile4(quarantinePath, jsonlContent, "utf-8");
34810
+ await writeFile5(quarantinePath, jsonlContent, "utf-8");
34651
34811
  await appendFile3(knowledgePath, `${JSON.stringify(original)}
34652
34812
  `, "utf-8");
34653
34813
  const rejectedEntries = await readKnowledge(rejectedPath);
@@ -34655,7 +34815,7 @@ async function restoreEntry(directory, entryId) {
34655
34815
  const rejectedContent = filtered.length > 0 ? `${filtered.map((e) => JSON.stringify(e)).join(`
34656
34816
  `)}
34657
34817
  ` : "";
34658
- await writeFile4(rejectedPath, rejectedContent, "utf-8");
34818
+ await writeFile5(rejectedPath, rejectedContent, "utf-8");
34659
34819
  } finally {
34660
34820
  if (release) {
34661
34821
  await release();
@@ -34664,6 +34824,7 @@ async function restoreEntry(directory, entryId) {
34664
34824
  }
34665
34825
  var import_proper_lockfile4, DANGEROUS_COMMAND_PATTERNS, SECURITY_DEGRADING_PATTERNS, INVISIBLE_FORMAT_CHARS, INJECTION_PATTERNS, VALID_CATEGORIES, TECH_REFERENCE_WORDS, ACTION_VERB_WORDS, NEGATION_PAIRS;
34666
34826
  var init_knowledge_validator = __esm(() => {
34827
+ init_logger();
34667
34828
  init_knowledge_store();
34668
34829
  import_proper_lockfile4 = __toESM(require_proper_lockfile(), 1);
34669
34830
  DANGEROUS_COMMAND_PATTERNS = [
@@ -34770,6 +34931,134 @@ var init_knowledge_validator = __esm(() => {
34770
34931
  });
34771
34932
 
34772
34933
  // src/hooks/knowledge-curator.ts
34934
+ function pruneSeenRetroSections() {
34935
+ const cutoff = Date.now() - 86400000;
34936
+ for (const [key, entry] of seenRetroSections) {
34937
+ if (entry.timestamp < cutoff) {
34938
+ seenRetroSections.delete(key);
34939
+ }
34940
+ }
34941
+ }
34942
+ function isWriteToSwarmPlan(input) {
34943
+ if (typeof input !== "object" || input === null)
34944
+ return false;
34945
+ const record3 = input;
34946
+ const toolName = record3.toolName;
34947
+ if (typeof toolName !== "string")
34948
+ return false;
34949
+ if (!["write", "edit", "apply_patch"].includes(toolName))
34950
+ return false;
34951
+ const rawPath = record3.path;
34952
+ const rawFile = record3.file;
34953
+ const pathField = typeof rawPath === "string" ? rawPath.replace(/\\/g, "/") : undefined;
34954
+ const fileField = typeof rawFile === "string" ? rawFile.replace(/\\/g, "/") : undefined;
34955
+ if (typeof pathField === "string" && pathField.includes(".swarm/plan.md")) {
34956
+ return true;
34957
+ }
34958
+ if (typeof fileField === "string" && fileField.includes(".swarm/plan.md")) {
34959
+ return true;
34960
+ }
34961
+ return false;
34962
+ }
34963
+ function isWriteToEvidenceFile(input) {
34964
+ if (typeof input !== "object" || input === null)
34965
+ return false;
34966
+ const record3 = input;
34967
+ const toolName = record3.toolName;
34968
+ if (typeof toolName !== "string")
34969
+ return false;
34970
+ if (!["write", "edit", "apply_patch"].includes(toolName))
34971
+ return false;
34972
+ const rawPath = record3.path;
34973
+ const rawFile = record3.file;
34974
+ const pathField = typeof rawPath === "string" ? rawPath.replace(/\\/g, "/") : undefined;
34975
+ const fileField = typeof rawFile === "string" ? rawFile.replace(/\\/g, "/") : undefined;
34976
+ const evidenceRegex = /\.swarm\/+evidence\/+/i;
34977
+ if (typeof pathField === "string" && evidenceRegex.test(pathField)) {
34978
+ return true;
34979
+ }
34980
+ if (typeof fileField === "string" && evidenceRegex.test(fileField)) {
34981
+ return true;
34982
+ }
34983
+ return false;
34984
+ }
34985
+ function extractRetrospectiveSection(planContent) {
34986
+ const headingRegex = /^###\s+Lessons\s+Learned$/m;
34987
+ const match = headingRegex.exec(planContent);
34988
+ if (!match)
34989
+ return null;
34990
+ const startIndex = match.index;
34991
+ const restOfContent = planContent.slice(startIndex);
34992
+ const firstNewline = restOfContent.indexOf(`
34993
+ `);
34994
+ const contentAfterHeading = firstNewline === -1 ? "" : restOfContent.slice(firstNewline + 1);
34995
+ const nextHeadingRegex = /^#{1,2}\s+/m;
34996
+ const nextMatch = nextHeadingRegex.exec(contentAfterHeading);
34997
+ let endIndex;
34998
+ if (nextMatch) {
34999
+ endIndex = startIndex + firstNewline + 1 + nextMatch.index;
35000
+ } else {
35001
+ endIndex = planContent.length;
35002
+ }
35003
+ return planContent.slice(startIndex, endIndex).trim();
35004
+ }
35005
+ function checkRetroChanged(sessionID, section) {
35006
+ const hash3 = `${section.length}:${section.slice(0, 100)}`;
35007
+ const lastSeen = seenRetroSections.get(sessionID);
35008
+ if (lastSeen?.value === hash3) {
35009
+ return false;
35010
+ }
35011
+ seenRetroSections.set(sessionID, { value: hash3, timestamp: Date.now() });
35012
+ return true;
35013
+ }
35014
+ function extractLessonsFromRetro(section) {
35015
+ const lessons = [];
35016
+ const lines = section.split(`
35017
+ `);
35018
+ for (const line of lines) {
35019
+ const trimmed = line.trim();
35020
+ const bulletMatch = /^[-*]\s+(.+)$/.exec(trimmed);
35021
+ if (bulletMatch) {
35022
+ const content = bulletMatch[1].trim();
35023
+ if (content) {
35024
+ lessons.push(content);
35025
+ }
35026
+ }
35027
+ }
35028
+ return lessons;
35029
+ }
35030
+ function extractRetractionsAndLessons(allLessons) {
35031
+ const retractions = [];
35032
+ const normalLessons = [];
35033
+ for (const lesson of allLessons) {
35034
+ const upper = lesson.trimStart().toUpperCase();
35035
+ if (upper.startsWith("RETRACT:") || upper.startsWith("BAD RULE:")) {
35036
+ const colonIdx = lesson.indexOf(":");
35037
+ const text = colonIdx !== -1 ? lesson.slice(colonIdx + 1).trim() : "";
35038
+ if (text)
35039
+ retractions.push(text);
35040
+ } else {
35041
+ normalLessons.push(lesson);
35042
+ }
35043
+ }
35044
+ return { retractions, normalLessons };
35045
+ }
35046
+ async function processRetractions(retractions, directory) {
35047
+ if (retractions.length === 0)
35048
+ return;
35049
+ const knowledgePath = resolveSwarmKnowledgePath(directory);
35050
+ const entries = await readKnowledge(knowledgePath) ?? [];
35051
+ for (const retractionText of retractions) {
35052
+ const normalizedRetraction = normalize2(retractionText);
35053
+ for (const entry of entries) {
35054
+ const normalizedLesson = normalize2(entry.lesson);
35055
+ if (normalizedLesson === normalizedRetraction) {
35056
+ await quarantineEntry(directory, entry.id, `Retracted by architect: ${retractionText}`, "architect");
35057
+ console.info(`[knowledge-curator] Quarantined entry ${entry.id}: "${entry.lesson}"`);
35058
+ }
35059
+ }
35060
+ }
35061
+ }
34773
35062
  async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, config3) {
34774
35063
  const knowledgePath = resolveSwarmKnowledgePath(directory);
34775
35064
  const existingEntries = await readKnowledge(knowledgePath) ?? [];
@@ -34852,7 +35141,7 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
34852
35141
  existingEntries.push(entry);
34853
35142
  }
34854
35143
  await enforceKnowledgeCap(knowledgePath, config3.swarm_max_entries);
34855
- await runAutoPromotion(directory, config3);
35144
+ await _internals7.runAutoPromotion(directory, config3);
34856
35145
  return { stored, skipped, rejected };
34857
35146
  }
34858
35147
  async function runAutoPromotion(directory, config3) {
@@ -34885,18 +35174,100 @@ async function runAutoPromotion(directory, config3) {
34885
35174
  await rewriteKnowledge(knowledgePath, entries);
34886
35175
  }
34887
35176
  }
34888
- var seenRetroSections;
35177
+ function createKnowledgeCuratorHook(directory, config3) {
35178
+ const handler = async (input, _output) => {
35179
+ pruneSeenRetroSections();
35180
+ if (!config3.enabled)
35181
+ return;
35182
+ if (!isWriteToSwarmPlan(input) && !isWriteToEvidenceFile(input))
35183
+ return;
35184
+ const sessionID = input?.sessionID ?? "default";
35185
+ const isEvidenceTrigger = isWriteToEvidenceFile(input) && !isWriteToSwarmPlan(input);
35186
+ if (isEvidenceTrigger) {
35187
+ const record3 = input;
35188
+ const rawPath = record3.path;
35189
+ const rawFile = record3.file;
35190
+ const filePath = typeof rawPath === "string" ? rawPath.replace(/\\/g, "/") : typeof rawFile === "string" ? rawFile.replace(/\\/g, "/") : null;
35191
+ if (!filePath)
35192
+ return;
35193
+ const evidenceKey = `evidence:${sessionID}:${filePath}`;
35194
+ const lastSeenEvidence = seenRetroSections.get(evidenceKey);
35195
+ const evidenceContent = await readSwarmFileAsync(directory, filePath.replace(/^.*\.swarm\//, ""));
35196
+ if (!evidenceContent)
35197
+ return;
35198
+ let evidenceData;
35199
+ try {
35200
+ evidenceData = JSON.parse(evidenceContent);
35201
+ } catch {
35202
+ return;
35203
+ }
35204
+ let lessons = [];
35205
+ if (Array.isArray(evidenceData.entries) && evidenceData.entries.length > 0) {
35206
+ const firstEntry = evidenceData.entries[0];
35207
+ if (Array.isArray(firstEntry.lessons_learned)) {
35208
+ lessons = firstEntry.lessons_learned;
35209
+ }
35210
+ } else if (Array.isArray(evidenceData.lessons_learned)) {
35211
+ lessons = evidenceData.lessons_learned;
35212
+ }
35213
+ if (lessons.length === 0)
35214
+ return;
35215
+ const evidenceHash = `${lessons.length}:${lessons.slice(0, 3).join("|")}`;
35216
+ if (lastSeenEvidence?.value === evidenceHash) {
35217
+ return;
35218
+ }
35219
+ seenRetroSections.set(evidenceKey, {
35220
+ value: evidenceHash,
35221
+ timestamp: Date.now()
35222
+ });
35223
+ const projectName2 = evidenceData.project_name ?? "unknown";
35224
+ const phaseNumber2 = typeof evidenceData.phase_number === "number" ? evidenceData.phase_number : 1;
35225
+ await _internals7.curateAndStoreSwarm(lessons, projectName2, { phase_number: phaseNumber2 }, directory, config3);
35226
+ await updateRetrievalOutcome(directory, `Phase ${phaseNumber2}`, true);
35227
+ return;
35228
+ }
35229
+ const planContent = await readSwarmFileAsync(directory, "plan.md");
35230
+ if (!planContent)
35231
+ return;
35232
+ const section = extractRetrospectiveSection(planContent);
35233
+ if (!section)
35234
+ return;
35235
+ if (!checkRetroChanged(sessionID, section))
35236
+ return;
35237
+ const allLessons = extractLessonsFromRetro(section);
35238
+ if (allLessons.length === 0)
35239
+ return;
35240
+ const { retractions, normalLessons } = extractRetractionsAndLessons(allLessons);
35241
+ await processRetractions(retractions, directory);
35242
+ if (normalLessons.length === 0)
35243
+ return;
35244
+ const projectNameMatch = /^#\s+(.+)$/m.exec(planContent);
35245
+ const projectName = projectNameMatch ? projectNameMatch[1].trim() : "unknown";
35246
+ const phaseMatch = /^Phase:\s*(\d+)/m.exec(planContent);
35247
+ const phaseNumber = phaseMatch ? parseInt(phaseMatch[1], 10) : 1;
35248
+ await _internals7.curateAndStoreSwarm(normalLessons, projectName, { phase_number: phaseNumber }, directory, config3);
35249
+ await updateRetrievalOutcome(directory, `Phase ${phaseNumber}`, true);
35250
+ };
35251
+ return safeHook(handler);
35252
+ }
35253
+ var seenRetroSections, _internals7;
34889
35254
  var init_knowledge_curator = __esm(() => {
34890
35255
  init_knowledge_reader();
34891
35256
  init_knowledge_store();
34892
35257
  init_knowledge_validator();
34893
35258
  init_utils2();
34894
35259
  seenRetroSections = new Map;
35260
+ _internals7 = {
35261
+ isWriteToEvidenceFile,
35262
+ curateAndStoreSwarm,
35263
+ runAutoPromotion,
35264
+ createKnowledgeCuratorHook
35265
+ };
34895
35266
  });
34896
35267
 
34897
35268
  // src/session/snapshot-writer.ts
34898
35269
  import { mkdirSync as mkdirSync7, renameSync as renameSync5 } from "fs";
34899
- import * as path12 from "path";
35270
+ import * as path13 from "path";
34900
35271
  function serializeAgentSession(s) {
34901
35272
  const gateLog = {};
34902
35273
  const rawGateLog = s.gateLog ?? new Map;
@@ -34986,7 +35357,7 @@ async function writeSnapshot(directory, state) {
34986
35357
  }
34987
35358
  const content = JSON.stringify(snapshot, null, 2);
34988
35359
  const resolvedPath = validateSwarmPath(directory, "session/state.json");
34989
- const dir = path12.dirname(resolvedPath);
35360
+ const dir = path13.dirname(resolvedPath);
34990
35361
  mkdirSync7(dir, { recursive: true });
34991
35362
  const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
34992
35363
  await bunWrite(tempPath, content);
@@ -34997,17 +35368,28 @@ async function writeSnapshot(directory, state) {
34997
35368
  });
34998
35369
  }
34999
35370
  }
35371
+ function createSnapshotWriterHook(directory) {
35372
+ return (_input, _output) => {
35373
+ _writeInFlight = _writeInFlight.then(() => _internals8.writeSnapshot(directory, swarmState), () => _internals8.writeSnapshot(directory, swarmState));
35374
+ return _writeInFlight;
35375
+ };
35376
+ }
35000
35377
  async function flushPendingSnapshot(directory) {
35001
- _writeInFlight = _writeInFlight.then(() => writeSnapshot(directory, swarmState), () => writeSnapshot(directory, swarmState));
35378
+ _writeInFlight = _writeInFlight.then(() => _internals8.writeSnapshot(directory, swarmState), () => _internals8.writeSnapshot(directory, swarmState));
35002
35379
  await _writeInFlight;
35003
35380
  }
35004
- var _writeInFlight;
35381
+ var _writeInFlight, _internals8;
35005
35382
  var init_snapshot_writer = __esm(() => {
35006
35383
  init_utils2();
35007
35384
  init_state();
35008
35385
  init_utils();
35009
35386
  init_bun_compat();
35010
35387
  _writeInFlight = Promise.resolve();
35388
+ _internals8 = {
35389
+ writeSnapshot,
35390
+ createSnapshotWriterHook,
35391
+ flushPendingSnapshot
35392
+ };
35011
35393
  });
35012
35394
 
35013
35395
  // src/tools/write-retro.ts
@@ -35311,7 +35693,7 @@ async function executeWriteRetro(args, directory) {
35311
35693
  }, null, 2);
35312
35694
  }
35313
35695
  }
35314
- var write_retro;
35696
+ var write_retro, _internals9;
35315
35697
  var init_write_retro = __esm(() => {
35316
35698
  init_zod();
35317
35699
  init_evidence_schema();
@@ -35358,17 +35740,21 @@ var init_write_retro = __esm(() => {
35358
35740
  task_id: args.task_id !== undefined ? String(args.task_id) : undefined,
35359
35741
  metadata: args.metadata
35360
35742
  };
35361
- return await executeWriteRetro(writeRetroArgs, directory);
35743
+ return await _internals9.executeWriteRetro(writeRetroArgs, directory);
35362
35744
  } catch {
35363
35745
  return JSON.stringify({ success: false, phase: rawPhase, message: "Invalid arguments" }, null, 2);
35364
35746
  }
35365
35747
  }
35366
35748
  });
35749
+ _internals9 = {
35750
+ executeWriteRetro,
35751
+ write_retro
35752
+ };
35367
35753
  });
35368
35754
 
35369
35755
  // src/commands/close.ts
35370
35756
  import { promises as fs7 } from "fs";
35371
- import path13 from "path";
35757
+ import path14 from "path";
35372
35758
  function guaranteeAllPlansComplete(planData) {
35373
35759
  const closedPhaseIds = [];
35374
35760
  const closedTaskIds = [];
@@ -35391,10 +35777,10 @@ function guaranteeAllPlansComplete(planData) {
35391
35777
  }
35392
35778
  async function handleCloseCommand(directory, args) {
35393
35779
  const planPath = validateSwarmPath(directory, "plan.json");
35394
- const swarmDir = path13.join(directory, ".swarm");
35780
+ const swarmDir = path14.join(directory, ".swarm");
35395
35781
  let planExists = false;
35396
35782
  let planData = {
35397
- title: path13.basename(directory) || "Ad-hoc session",
35783
+ title: path14.basename(directory) || "Ad-hoc session",
35398
35784
  phases: []
35399
35785
  };
35400
35786
  try {
@@ -35499,7 +35885,7 @@ async function handleCloseCommand(directory, args) {
35499
35885
  warnings.push(`Session retrospective write threw: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
35500
35886
  }
35501
35887
  }
35502
- const lessonsFilePath = path13.join(swarmDir, "close-lessons.md");
35888
+ const lessonsFilePath = path14.join(swarmDir, "close-lessons.md");
35503
35889
  let explicitLessons = [];
35504
35890
  try {
35505
35891
  const lessonsText = await fs7.readFile(lessonsFilePath, "utf-8");
@@ -35508,11 +35894,11 @@ async function handleCloseCommand(directory, args) {
35508
35894
  } catch {}
35509
35895
  const retroLessons = [];
35510
35896
  try {
35511
- const evidenceDir = path13.join(swarmDir, "evidence");
35897
+ const evidenceDir = path14.join(swarmDir, "evidence");
35512
35898
  const evidenceEntries = await fs7.readdir(evidenceDir);
35513
35899
  const retroDirs = evidenceEntries.filter((e) => e.startsWith("retro-")).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
35514
35900
  for (const retroDir of retroDirs) {
35515
- const evidencePath = path13.join(evidenceDir, retroDir, "evidence.json");
35901
+ const evidencePath = path14.join(evidenceDir, retroDir, "evidence.json");
35516
35902
  try {
35517
35903
  const content = await fs7.readFile(evidencePath, "utf-8");
35518
35904
  const parsed = JSON.parse(content);
@@ -35566,15 +35952,15 @@ async function handleCloseCommand(directory, args) {
35566
35952
  }
35567
35953
  const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
35568
35954
  const suffix = Math.random().toString(36).slice(2, 8);
35569
- const archiveDir = path13.join(swarmDir, "archive", `swarm-${timestamp}-${suffix}`);
35955
+ const archiveDir = path14.join(swarmDir, "archive", `swarm-${timestamp}-${suffix}`);
35570
35956
  let archiveResult = "";
35571
35957
  let archivedFileCount = 0;
35572
35958
  const archivedActiveStateFiles = new Set;
35573
35959
  try {
35574
35960
  await fs7.mkdir(archiveDir, { recursive: true });
35575
35961
  for (const artifact of ARCHIVE_ARTIFACTS) {
35576
- const srcPath = path13.join(swarmDir, artifact);
35577
- const destPath = path13.join(archiveDir, artifact);
35962
+ const srcPath = path14.join(swarmDir, artifact);
35963
+ const destPath = path14.join(archiveDir, artifact);
35578
35964
  try {
35579
35965
  await fs7.copyFile(srcPath, destPath);
35580
35966
  archivedFileCount++;
@@ -35583,22 +35969,22 @@ async function handleCloseCommand(directory, args) {
35583
35969
  }
35584
35970
  } catch {}
35585
35971
  }
35586
- const evidenceDir = path13.join(swarmDir, "evidence");
35587
- const archiveEvidenceDir = path13.join(archiveDir, "evidence");
35972
+ const evidenceDir = path14.join(swarmDir, "evidence");
35973
+ const archiveEvidenceDir = path14.join(archiveDir, "evidence");
35588
35974
  try {
35589
35975
  const evidenceEntries = await fs7.readdir(evidenceDir);
35590
35976
  if (evidenceEntries.length > 0) {
35591
35977
  await fs7.mkdir(archiveEvidenceDir, { recursive: true });
35592
35978
  for (const entry of evidenceEntries) {
35593
- const srcEntry = path13.join(evidenceDir, entry);
35594
- const destEntry = path13.join(archiveEvidenceDir, entry);
35979
+ const srcEntry = path14.join(evidenceDir, entry);
35980
+ const destEntry = path14.join(archiveEvidenceDir, entry);
35595
35981
  try {
35596
35982
  const stat2 = await fs7.stat(srcEntry);
35597
35983
  if (stat2.isDirectory()) {
35598
35984
  await fs7.mkdir(destEntry, { recursive: true });
35599
35985
  const subEntries = await fs7.readdir(srcEntry);
35600
35986
  for (const sub of subEntries) {
35601
- await fs7.copyFile(path13.join(srcEntry, sub), path13.join(destEntry, sub)).catch(() => {});
35987
+ await fs7.copyFile(path14.join(srcEntry, sub), path14.join(destEntry, sub)).catch(() => {});
35602
35988
  }
35603
35989
  } else {
35604
35990
  await fs7.copyFile(srcEntry, destEntry);
@@ -35608,11 +35994,11 @@ async function handleCloseCommand(directory, args) {
35608
35994
  }
35609
35995
  }
35610
35996
  } catch {}
35611
- const sessionStatePath = path13.join(swarmDir, "session", "state.json");
35997
+ const sessionStatePath = path14.join(swarmDir, "session", "state.json");
35612
35998
  try {
35613
- const archiveSessionDir = path13.join(archiveDir, "session");
35999
+ const archiveSessionDir = path14.join(archiveDir, "session");
35614
36000
  await fs7.mkdir(archiveSessionDir, { recursive: true });
35615
- await fs7.copyFile(sessionStatePath, path13.join(archiveSessionDir, "state.json"));
36001
+ await fs7.copyFile(sessionStatePath, path14.join(archiveSessionDir, "state.json"));
35616
36002
  archivedFileCount++;
35617
36003
  } catch {}
35618
36004
  archiveResult = `Archived ${archivedFileCount} artifact(s) to .swarm/archive/swarm-${timestamp}/`;
@@ -35635,7 +36021,7 @@ async function handleCloseCommand(directory, args) {
35635
36021
  warnings.push(`Preserved ${artifact} because it was not successfully archived.`);
35636
36022
  continue;
35637
36023
  }
35638
- const filePath = path13.join(swarmDir, artifact);
36024
+ const filePath = path14.join(swarmDir, artifact);
35639
36025
  try {
35640
36026
  await fs7.unlink(filePath);
35641
36027
  cleanedFiles.push(artifact);
@@ -35649,23 +36035,23 @@ async function handleCloseCommand(directory, args) {
35649
36035
  const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
35650
36036
  for (const backup of configBackups) {
35651
36037
  try {
35652
- await fs7.unlink(path13.join(swarmDir, backup));
36038
+ await fs7.unlink(path14.join(swarmDir, backup));
35653
36039
  configBackupsRemoved++;
35654
36040
  } catch {}
35655
36041
  }
35656
36042
  const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
35657
36043
  for (const sibling of ledgerSiblings) {
35658
36044
  try {
35659
- await fs7.unlink(path13.join(swarmDir, sibling));
36045
+ await fs7.unlink(path14.join(swarmDir, sibling));
35660
36046
  } catch {}
35661
36047
  }
35662
36048
  } catch {}
35663
36049
  let swarmPlanFilesRemoved = 0;
35664
36050
  const candidates = [
35665
- path13.join(directory, ".swarm", "SWARM_PLAN.json"),
35666
- path13.join(directory, ".swarm", "SWARM_PLAN.md"),
35667
- path13.join(directory, "SWARM_PLAN.json"),
35668
- path13.join(directory, "SWARM_PLAN.md")
36051
+ path14.join(directory, ".swarm", "SWARM_PLAN.json"),
36052
+ path14.join(directory, ".swarm", "SWARM_PLAN.md"),
36053
+ path14.join(directory, "SWARM_PLAN.json"),
36054
+ path14.join(directory, "SWARM_PLAN.md")
35669
36055
  ];
35670
36056
  for (const candidate of candidates) {
35671
36057
  try {
@@ -35673,12 +36059,12 @@ async function handleCloseCommand(directory, args) {
35673
36059
  swarmPlanFilesRemoved++;
35674
36060
  } catch (err) {
35675
36061
  if (err?.code !== "ENOENT") {
35676
- warnings.push(`Failed to remove ${path13.basename(candidate)}: ${err instanceof Error ? err.message : String(err)}`);
36062
+ warnings.push(`Failed to remove ${path14.basename(candidate)}: ${err instanceof Error ? err.message : String(err)}`);
35677
36063
  }
35678
36064
  }
35679
36065
  }
35680
36066
  clearAllScopes(directory);
35681
- const contextPath = path13.join(swarmDir, "context.md");
36067
+ const contextPath = path14.join(swarmDir, "context.md");
35682
36068
  const contextContent = [
35683
36069
  "# Context",
35684
36070
  "",
@@ -35847,14 +36233,14 @@ var init_close = __esm(() => {
35847
36233
 
35848
36234
  // src/commands/config.ts
35849
36235
  import * as os4 from "os";
35850
- import * as path14 from "path";
36236
+ import * as path15 from "path";
35851
36237
  function getUserConfigDir2() {
35852
- return process.env.XDG_CONFIG_HOME || path14.join(os4.homedir(), ".config");
36238
+ return process.env.XDG_CONFIG_HOME || path15.join(os4.homedir(), ".config");
35853
36239
  }
35854
36240
  async function handleConfigCommand(directory, _args) {
35855
36241
  const config3 = loadPluginConfig(directory);
35856
- const userConfigPath = path14.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
35857
- const projectConfigPath = path14.join(directory, ".opencode", "opencode-swarm.json");
36242
+ const userConfigPath = path15.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
36243
+ const projectConfigPath = path15.join(directory, ".opencode", "opencode-swarm.json");
35858
36244
  const lines = [
35859
36245
  "## Swarm Configuration",
35860
36246
  "",
@@ -36019,13 +36405,14 @@ var init_curator = __esm(() => {
36019
36405
  init_event_bus();
36020
36406
  init_manager();
36021
36407
  init_bun_compat();
36408
+ init_logger();
36022
36409
  init_knowledge_store();
36023
36410
  init_knowledge_validator();
36024
36411
  init_utils2();
36025
36412
  });
36026
36413
 
36027
36414
  // src/hooks/hive-promoter.ts
36028
- import path15 from "path";
36415
+ import path16 from "path";
36029
36416
  function isAlreadyInHive(entry, hiveEntries, threshold) {
36030
36417
  return findNearDuplicate(entry.lesson, hiveEntries, threshold) !== undefined;
36031
36418
  }
@@ -36204,7 +36591,7 @@ async function promoteToHive(directory, lesson, category) {
36204
36591
  schema_version: 1,
36205
36592
  created_at: new Date().toISOString(),
36206
36593
  updated_at: new Date().toISOString(),
36207
- source_project: path15.basename(directory) || "unknown",
36594
+ source_project: path16.basename(directory) || "unknown",
36208
36595
  encounter_score: 1
36209
36596
  };
36210
36597
  await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
@@ -36295,8 +36682,8 @@ var init_curate = __esm(() => {
36295
36682
  // src/tools/co-change-analyzer.ts
36296
36683
  import * as child_process3 from "child_process";
36297
36684
  import { randomUUID } from "crypto";
36298
- import { readdir, readFile as readFile4, stat as stat2 } from "fs/promises";
36299
- import * as path16 from "path";
36685
+ import { readdir, readFile as readFile5, stat as stat2 } from "fs/promises";
36686
+ import * as path17 from "path";
36300
36687
  import { promisify } from "util";
36301
36688
  function getExecFileAsync() {
36302
36689
  return promisify(child_process3.execFile);
@@ -36398,7 +36785,7 @@ async function scanSourceFiles(dir) {
36398
36785
  try {
36399
36786
  const entries = await readdir(dir, { withFileTypes: true });
36400
36787
  for (const entry of entries) {
36401
- const fullPath = path16.join(dir, entry.name);
36788
+ const fullPath = path17.join(dir, entry.name);
36402
36789
  if (entry.isDirectory()) {
36403
36790
  if (skipDirs.has(entry.name)) {
36404
36791
  continue;
@@ -36406,7 +36793,7 @@ async function scanSourceFiles(dir) {
36406
36793
  const subFiles = await scanSourceFiles(fullPath);
36407
36794
  results.push(...subFiles);
36408
36795
  } else if (entry.isFile()) {
36409
- const ext = path16.extname(entry.name);
36796
+ const ext = path17.extname(entry.name);
36410
36797
  if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
36411
36798
  results.push(fullPath);
36412
36799
  }
@@ -36420,7 +36807,7 @@ async function getStaticEdges(directory) {
36420
36807
  const sourceFiles = await scanSourceFiles(directory);
36421
36808
  for (const sourceFile of sourceFiles) {
36422
36809
  try {
36423
- const content = await readFile4(sourceFile, "utf-8");
36810
+ const content = await readFile5(sourceFile, "utf-8");
36424
36811
  const importRegex = /(?:import|require)\s*(?:\(?\s*['"`]|.*?from\s+['"`])([^'"`]+)['"`]/g;
36425
36812
  for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
36426
36813
  const importPath = match[1].trim();
@@ -36428,8 +36815,8 @@ async function getStaticEdges(directory) {
36428
36815
  continue;
36429
36816
  }
36430
36817
  try {
36431
- const sourceDir = path16.dirname(sourceFile);
36432
- const resolvedPath = path16.resolve(sourceDir, importPath);
36818
+ const sourceDir = path17.dirname(sourceFile);
36819
+ const resolvedPath = path17.resolve(sourceDir, importPath);
36433
36820
  const extensions = [
36434
36821
  "",
36435
36822
  ".ts",
@@ -36454,8 +36841,8 @@ async function getStaticEdges(directory) {
36454
36841
  if (!targetFile) {
36455
36842
  continue;
36456
36843
  }
36457
- const relSource = path16.relative(directory, sourceFile).replace(/\\/g, "/");
36458
- const relTarget = path16.relative(directory, targetFile).replace(/\\/g, "/");
36844
+ const relSource = path17.relative(directory, sourceFile).replace(/\\/g, "/");
36845
+ const relTarget = path17.relative(directory, targetFile).replace(/\\/g, "/");
36459
36846
  const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
36460
36847
  edges.add(key);
36461
36848
  } catch {}
@@ -36467,7 +36854,7 @@ async function getStaticEdges(directory) {
36467
36854
  function isTestImplementationPair(fileA, fileB) {
36468
36855
  const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
36469
36856
  const getBaseName = (filePath) => {
36470
- const base = path16.basename(filePath);
36857
+ const base = path17.basename(filePath);
36471
36858
  for (const pattern of testPatterns) {
36472
36859
  if (base.endsWith(pattern)) {
36473
36860
  return base.slice(0, -pattern.length);
@@ -36477,16 +36864,16 @@ function isTestImplementationPair(fileA, fileB) {
36477
36864
  };
36478
36865
  const baseA = getBaseName(fileA);
36479
36866
  const baseB = getBaseName(fileB);
36480
- return baseA === baseB && baseA !== path16.basename(fileA) && baseA !== path16.basename(fileB);
36867
+ return baseA === baseB && baseA !== path17.basename(fileA) && baseA !== path17.basename(fileB);
36481
36868
  }
36482
36869
  function hasSharedPrefix(fileA, fileB) {
36483
- const dirA = path16.dirname(fileA);
36484
- const dirB = path16.dirname(fileB);
36870
+ const dirA = path17.dirname(fileA);
36871
+ const dirB = path17.dirname(fileB);
36485
36872
  if (dirA !== dirB) {
36486
36873
  return false;
36487
36874
  }
36488
- const baseA = path16.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
36489
- const baseB = path16.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
36875
+ const baseA = path17.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
36876
+ const baseB = path17.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
36490
36877
  if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
36491
36878
  return true;
36492
36879
  }
@@ -36514,9 +36901,9 @@ async function detectDarkMatter(directory, options) {
36514
36901
  } catch {
36515
36902
  return [];
36516
36903
  }
36517
- const commitMap = await parseGitLog(directory, maxCommitsToAnalyze);
36518
- const matrix = buildCoChangeMatrix(commitMap);
36519
- const staticEdges = await getStaticEdges(directory);
36904
+ const commitMap = await _internals10.parseGitLog(directory, maxCommitsToAnalyze);
36905
+ const matrix = _internals10.buildCoChangeMatrix(commitMap);
36906
+ const staticEdges = await _internals10.getStaticEdges(directory);
36520
36907
  const results = [];
36521
36908
  for (const entry of matrix.values()) {
36522
36909
  const key = `${entry.fileA}::${entry.fileB}`;
@@ -36540,8 +36927,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
36540
36927
  const entries = [];
36541
36928
  const now = new Date().toISOString();
36542
36929
  for (const pair of pairs.slice(0, 10)) {
36543
- const baseA = path16.basename(pair.fileA);
36544
- const baseB = path16.basename(pair.fileB);
36930
+ const baseA = path17.basename(pair.fileA);
36931
+ const baseB = path17.basename(pair.fileB);
36545
36932
  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.`;
36546
36933
  if (lesson.length > 280) {
36547
36934
  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.`;
@@ -36596,7 +36983,7 @@ ${rows}
36596
36983
  These pairs likely share an architectural concern invisible to static analysis.
36597
36984
  Consider adding explicit documentation or extracting the shared concern.`;
36598
36985
  }
36599
- var co_change_analyzer;
36986
+ var co_change_analyzer, _internals10;
36600
36987
  var init_co_change_analyzer = __esm(() => {
36601
36988
  init_zod();
36602
36989
  init_create_tool();
@@ -36628,14 +37015,22 @@ var init_co_change_analyzer = __esm(() => {
36628
37015
  npmiThreshold,
36629
37016
  maxCommitsToAnalyze
36630
37017
  };
36631
- const pairs = await detectDarkMatter(directory, options);
36632
- return formatDarkMatterOutput(pairs);
37018
+ const pairs = await _internals10.detectDarkMatter(directory, options);
37019
+ return _internals10.formatDarkMatterOutput(pairs);
36633
37020
  }
36634
37021
  });
37022
+ _internals10 = {
37023
+ parseGitLog,
37024
+ buildCoChangeMatrix,
37025
+ getStaticEdges,
37026
+ detectDarkMatter,
37027
+ darkMatterToKnowledgeEntries,
37028
+ formatDarkMatterOutput
37029
+ };
36635
37030
  });
36636
37031
 
36637
37032
  // src/commands/dark-matter.ts
36638
- import path17 from "path";
37033
+ import path18 from "path";
36639
37034
  async function handleDarkMatterCommand(directory, args) {
36640
37035
  const options = {};
36641
37036
  for (let i = 0;i < args.length; i++) {
@@ -36657,7 +37052,7 @@ async function handleDarkMatterCommand(directory, args) {
36657
37052
  const output = formatDarkMatterOutput(pairs);
36658
37053
  if (pairs.length > 0) {
36659
37054
  try {
36660
- const projectName = path17.basename(path17.resolve(directory));
37055
+ const projectName = path18.basename(path18.resolve(directory));
36661
37056
  const entries = darkMatterToKnowledgeEntries(pairs, projectName);
36662
37057
  if (entries.length > 0) {
36663
37058
  const knowledgePath = resolveSwarmKnowledgePath(directory);
@@ -36682,67 +37077,67 @@ var init_dark_matter = __esm(() => {
36682
37077
 
36683
37078
  // src/config/cache-paths.ts
36684
37079
  import * as os5 from "os";
36685
- import * as path18 from "path";
37080
+ import * as path19 from "path";
36686
37081
  function getPluginConfigDir() {
36687
- return path18.join(process.env.XDG_CONFIG_HOME || path18.join(os5.homedir(), ".config"), "opencode");
37082
+ return path19.join(process.env.XDG_CONFIG_HOME || path19.join(os5.homedir(), ".config"), "opencode");
36688
37083
  }
36689
37084
  function getPluginCachePaths() {
36690
- const cacheBase = process.env.XDG_CACHE_HOME || path18.join(os5.homedir(), ".cache");
37085
+ const cacheBase = process.env.XDG_CACHE_HOME || path19.join(os5.homedir(), ".cache");
36691
37086
  const configDir = getPluginConfigDir();
36692
37087
  const paths = [
36693
- path18.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
36694
- path18.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
36695
- path18.join(configDir, "node_modules", "opencode-swarm")
37088
+ path19.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
37089
+ path19.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
37090
+ path19.join(configDir, "node_modules", "opencode-swarm")
36696
37091
  ];
36697
37092
  if (process.platform === "darwin") {
36698
- const libCaches = path18.join(os5.homedir(), "Library", "Caches");
36699
- paths.push(path18.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path18.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
37093
+ const libCaches = path19.join(os5.homedir(), "Library", "Caches");
37094
+ paths.push(path19.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path19.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
36700
37095
  }
36701
37096
  if (process.platform === "win32") {
36702
- const localAppData = process.env.LOCALAPPDATA || path18.join(os5.homedir(), "AppData", "Local");
36703
- const appData = process.env.APPDATA || path18.join(os5.homedir(), "AppData", "Roaming");
36704
- paths.push(path18.join(localAppData, "opencode", "node_modules", "opencode-swarm"), path18.join(localAppData, "opencode", "packages", "opencode-swarm@latest"), path18.join(appData, "opencode", "node_modules", "opencode-swarm"));
37097
+ const localAppData = process.env.LOCALAPPDATA || path19.join(os5.homedir(), "AppData", "Local");
37098
+ const appData = process.env.APPDATA || path19.join(os5.homedir(), "AppData", "Roaming");
37099
+ paths.push(path19.join(localAppData, "opencode", "node_modules", "opencode-swarm"), path19.join(localAppData, "opencode", "packages", "opencode-swarm@latest"), path19.join(appData, "opencode", "node_modules", "opencode-swarm"));
36705
37100
  }
36706
37101
  return paths;
36707
37102
  }
36708
37103
  function getPluginLockFilePaths() {
36709
- const cacheBase = process.env.XDG_CACHE_HOME || path18.join(os5.homedir(), ".cache");
37104
+ const cacheBase = process.env.XDG_CACHE_HOME || path19.join(os5.homedir(), ".cache");
36710
37105
  const configDir = getPluginConfigDir();
36711
37106
  const paths = [
36712
- path18.join(cacheBase, "opencode", "bun.lock"),
36713
- path18.join(cacheBase, "opencode", "bun.lockb"),
36714
- path18.join(configDir, "package-lock.json")
37107
+ path19.join(cacheBase, "opencode", "bun.lock"),
37108
+ path19.join(cacheBase, "opencode", "bun.lockb"),
37109
+ path19.join(configDir, "package-lock.json")
36715
37110
  ];
36716
37111
  if (process.platform === "darwin") {
36717
- const libCaches = path18.join(os5.homedir(), "Library", "Caches");
36718
- paths.push(path18.join(libCaches, "opencode", "bun.lock"), path18.join(libCaches, "opencode", "bun.lockb"));
37112
+ const libCaches = path19.join(os5.homedir(), "Library", "Caches");
37113
+ paths.push(path19.join(libCaches, "opencode", "bun.lock"), path19.join(libCaches, "opencode", "bun.lockb"));
36719
37114
  }
36720
37115
  if (process.platform === "win32") {
36721
- const localAppData = process.env.LOCALAPPDATA || path18.join(os5.homedir(), "AppData", "Local");
36722
- paths.push(path18.join(localAppData, "opencode", "bun.lock"), path18.join(localAppData, "opencode", "bun.lockb"));
37116
+ const localAppData = process.env.LOCALAPPDATA || path19.join(os5.homedir(), "AppData", "Local");
37117
+ paths.push(path19.join(localAppData, "opencode", "bun.lock"), path19.join(localAppData, "opencode", "bun.lockb"));
36723
37118
  }
36724
37119
  return paths;
36725
37120
  }
36726
37121
  var init_cache_paths = () => {};
36727
37122
 
36728
37123
  // src/services/version-check.ts
36729
- import { existsSync as existsSync8, mkdirSync as mkdirSync8, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
37124
+ import { existsSync as existsSync9, mkdirSync as mkdirSync8, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
36730
37125
  import { homedir as homedir5 } from "os";
36731
- import { join as join16 } from "path";
37126
+ import { join as join17 } from "path";
36732
37127
  function cacheDir() {
36733
37128
  const xdg = process.env.XDG_CACHE_HOME;
36734
- const base = xdg && xdg.length > 0 ? xdg : join16(homedir5(), ".cache");
36735
- return join16(base, "opencode-swarm");
37129
+ const base = xdg && xdg.length > 0 ? xdg : join17(homedir5(), ".cache");
37130
+ return join17(base, "opencode-swarm");
36736
37131
  }
36737
37132
  function cacheFile() {
36738
- return join16(cacheDir(), "version-check.json");
37133
+ return join17(cacheDir(), "version-check.json");
36739
37134
  }
36740
37135
  function readVersionCache() {
36741
37136
  try {
36742
- const path19 = cacheFile();
36743
- if (!existsSync8(path19))
37137
+ const path20 = cacheFile();
37138
+ if (!existsSync9(path20))
36744
37139
  return null;
36745
- const raw = readFileSync5(path19, "utf-8");
37140
+ const raw = readFileSync5(path20, "utf-8");
36746
37141
  const parsed = JSON.parse(raw);
36747
37142
  if (typeof parsed?.checkedAt !== "number")
36748
37143
  return null;
@@ -36781,8 +37176,8 @@ var init_version_check = __esm(() => {
36781
37176
 
36782
37177
  // src/services/diagnose-service.ts
36783
37178
  import * as child_process4 from "child_process";
36784
- import { existsSync as existsSync9, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync6 } from "fs";
36785
- import path19 from "path";
37179
+ import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync6 } from "fs";
37180
+ import path20 from "path";
36786
37181
  import { fileURLToPath } from "url";
36787
37182
  function validateTaskDag(plan) {
36788
37183
  const allTaskIds = new Set;
@@ -37015,7 +37410,7 @@ async function checkConfigBackups(directory) {
37015
37410
  }
37016
37411
  async function checkGitRepository(directory) {
37017
37412
  try {
37018
- if (!existsSync9(directory) || !statSync6(directory).isDirectory()) {
37413
+ if (!existsSync10(directory) || !statSync6(directory).isDirectory()) {
37019
37414
  return {
37020
37415
  name: "Git Repository",
37021
37416
  status: "\u274C",
@@ -37079,8 +37474,8 @@ async function checkSpecStaleness(directory, plan) {
37079
37474
  };
37080
37475
  }
37081
37476
  async function checkConfigParseability(directory) {
37082
- const configPath = path19.join(directory, ".opencode/opencode-swarm.json");
37083
- if (!existsSync9(configPath)) {
37477
+ const configPath = path20.join(directory, ".opencode/opencode-swarm.json");
37478
+ if (!existsSync10(configPath)) {
37084
37479
  return {
37085
37480
  name: "Config Parseability",
37086
37481
  status: "\u2705",
@@ -37108,7 +37503,7 @@ function resolveGrammarDir(thisDir) {
37108
37503
  const normalized = thisDir.replace(/\\/g, "/");
37109
37504
  const isSource = normalized.endsWith("/src/services");
37110
37505
  const isCliBundle = normalized.endsWith("/cli");
37111
- return isSource || isCliBundle ? path19.join(thisDir, "..", "lang", "grammars") : path19.join(thisDir, "lang", "grammars");
37506
+ return isSource || isCliBundle ? path20.join(thisDir, "..", "lang", "grammars") : path20.join(thisDir, "lang", "grammars");
37112
37507
  }
37113
37508
  async function checkGrammarWasmFiles() {
37114
37509
  const grammarFiles = [
@@ -37132,14 +37527,14 @@ async function checkGrammarWasmFiles() {
37132
37527
  "tree-sitter-ini.wasm",
37133
37528
  "tree-sitter-regex.wasm"
37134
37529
  ];
37135
- const thisDir = path19.dirname(fileURLToPath(import.meta.url));
37530
+ const thisDir = path20.dirname(fileURLToPath(import.meta.url));
37136
37531
  const grammarDir = resolveGrammarDir(thisDir);
37137
37532
  const missing = [];
37138
- if (!existsSync9(path19.join(grammarDir, "tree-sitter.wasm"))) {
37533
+ if (!existsSync10(path20.join(grammarDir, "tree-sitter.wasm"))) {
37139
37534
  missing.push("tree-sitter.wasm (core runtime)");
37140
37535
  }
37141
37536
  for (const file3 of grammarFiles) {
37142
- if (!existsSync9(path19.join(grammarDir, file3))) {
37537
+ if (!existsSync10(path20.join(grammarDir, file3))) {
37143
37538
  missing.push(file3);
37144
37539
  }
37145
37540
  }
@@ -37157,8 +37552,8 @@ async function checkGrammarWasmFiles() {
37157
37552
  };
37158
37553
  }
37159
37554
  async function checkCheckpointManifest(directory) {
37160
- const manifestPath = path19.join(directory, ".swarm/checkpoints.json");
37161
- if (!existsSync9(manifestPath)) {
37555
+ const manifestPath = path20.join(directory, ".swarm/checkpoints.json");
37556
+ if (!existsSync10(manifestPath)) {
37162
37557
  return {
37163
37558
  name: "Checkpoint Manifest",
37164
37559
  status: "\u2705",
@@ -37209,8 +37604,8 @@ async function checkCheckpointManifest(directory) {
37209
37604
  }
37210
37605
  }
37211
37606
  async function checkEventStreamIntegrity(directory) {
37212
- const eventsPath = path19.join(directory, ".swarm/events.jsonl");
37213
- if (!existsSync9(eventsPath)) {
37607
+ const eventsPath = path20.join(directory, ".swarm/events.jsonl");
37608
+ if (!existsSync10(eventsPath)) {
37214
37609
  return {
37215
37610
  name: "Event Stream",
37216
37611
  status: "\u2705",
@@ -37250,8 +37645,8 @@ async function checkEventStreamIntegrity(directory) {
37250
37645
  }
37251
37646
  }
37252
37647
  async function checkSteeringDirectives(directory) {
37253
- const eventsPath = path19.join(directory, ".swarm/events.jsonl");
37254
- if (!existsSync9(eventsPath)) {
37648
+ const eventsPath = path20.join(directory, ".swarm/events.jsonl");
37649
+ if (!existsSync10(eventsPath)) {
37255
37650
  return {
37256
37651
  name: "Steering Directives",
37257
37652
  status: "\u2705",
@@ -37306,8 +37701,8 @@ async function checkCurator(directory) {
37306
37701
  detail: "Disabled (enable via curator.enabled)"
37307
37702
  };
37308
37703
  }
37309
- const summaryPath = path19.join(directory, ".swarm/curator-summary.json");
37310
- if (!existsSync9(summaryPath)) {
37704
+ const summaryPath = path20.join(directory, ".swarm/curator-summary.json");
37705
+ if (!existsSync10(summaryPath)) {
37311
37706
  return {
37312
37707
  name: "Curator",
37313
37708
  status: "\u2705",
@@ -37472,8 +37867,8 @@ async function getDiagnoseData(directory) {
37472
37867
  checks5.push(await checkSteeringDirectives(directory));
37473
37868
  checks5.push(await checkCurator(directory));
37474
37869
  try {
37475
- const evidenceDir = path19.join(directory, ".swarm", "evidence");
37476
- const snapshotFiles = existsSync9(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
37870
+ const evidenceDir = path20.join(directory, ".swarm", "evidence");
37871
+ const snapshotFiles = existsSync10(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
37477
37872
  if (snapshotFiles.length > 0) {
37478
37873
  const latest = snapshotFiles.sort().pop();
37479
37874
  checks5.push({
@@ -37506,11 +37901,11 @@ async function getDiagnoseData(directory) {
37506
37901
  const cacheRows = [];
37507
37902
  for (const cachePath of cachePaths) {
37508
37903
  try {
37509
- if (!existsSync9(cachePath)) {
37904
+ if (!existsSync10(cachePath)) {
37510
37905
  cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
37511
37906
  continue;
37512
37907
  }
37513
- const pkgJsonPath = path19.join(cachePath, "package.json");
37908
+ const pkgJsonPath = path20.join(cachePath, "package.json");
37514
37909
  try {
37515
37910
  const raw = readFileSync6(pkgJsonPath, "utf-8");
37516
37911
  const parsed = JSON.parse(raw);
@@ -37598,13 +37993,13 @@ __export(exports_config_doctor, {
37598
37993
  import * as crypto3 from "crypto";
37599
37994
  import * as fs8 from "fs";
37600
37995
  import * as os6 from "os";
37601
- import * as path20 from "path";
37996
+ import * as path21 from "path";
37602
37997
  function getUserConfigDir3() {
37603
- return process.env.XDG_CONFIG_HOME || path20.join(os6.homedir(), ".config");
37998
+ return process.env.XDG_CONFIG_HOME || path21.join(os6.homedir(), ".config");
37604
37999
  }
37605
38000
  function getConfigPaths(directory) {
37606
- const userConfigPath = path20.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
37607
- const projectConfigPath = path20.join(directory, ".opencode", "opencode-swarm.json");
38001
+ const userConfigPath = path21.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
38002
+ const projectConfigPath = path21.join(directory, ".opencode", "opencode-swarm.json");
37608
38003
  return { userConfigPath, projectConfigPath };
37609
38004
  }
37610
38005
  function computeHash(content) {
@@ -37629,9 +38024,9 @@ function isValidConfigPath(configPath, directory) {
37629
38024
  const normalizedUser = userConfigPath.replace(/\\/g, "/");
37630
38025
  const normalizedProject = projectConfigPath.replace(/\\/g, "/");
37631
38026
  try {
37632
- const resolvedConfig = path20.resolve(configPath);
37633
- const resolvedUser = path20.resolve(normalizedUser);
37634
- const resolvedProject = path20.resolve(normalizedProject);
38027
+ const resolvedConfig = path21.resolve(configPath);
38028
+ const resolvedUser = path21.resolve(normalizedUser);
38029
+ const resolvedProject = path21.resolve(normalizedProject);
37635
38030
  return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
37636
38031
  } catch {
37637
38032
  return false;
@@ -37671,12 +38066,12 @@ function createConfigBackup(directory) {
37671
38066
  };
37672
38067
  }
37673
38068
  function writeBackupArtifact(directory, backup) {
37674
- const swarmDir = path20.join(directory, ".swarm");
38069
+ const swarmDir = path21.join(directory, ".swarm");
37675
38070
  if (!fs8.existsSync(swarmDir)) {
37676
38071
  fs8.mkdirSync(swarmDir, { recursive: true });
37677
38072
  }
37678
38073
  const backupFilename = `config-backup-${backup.createdAt}.json`;
37679
- const backupPath = path20.join(swarmDir, backupFilename);
38074
+ const backupPath = path21.join(swarmDir, backupFilename);
37680
38075
  const artifact = {
37681
38076
  createdAt: backup.createdAt,
37682
38077
  configPath: backup.configPath,
@@ -37706,7 +38101,7 @@ function restoreFromBackup(backupPath, directory) {
37706
38101
  return null;
37707
38102
  }
37708
38103
  const targetPath = artifact.configPath;
37709
- const targetDir = path20.dirname(targetPath);
38104
+ const targetDir = path21.dirname(targetPath);
37710
38105
  if (!fs8.existsSync(targetDir)) {
37711
38106
  fs8.mkdirSync(targetDir, { recursive: true });
37712
38107
  }
@@ -37737,9 +38132,9 @@ function readConfigFromFile(directory) {
37737
38132
  return null;
37738
38133
  }
37739
38134
  }
37740
- function validateConfigKey(path21, value, _config) {
38135
+ function validateConfigKey(path22, value, _config) {
37741
38136
  const findings = [];
37742
- switch (path21) {
38137
+ switch (path22) {
37743
38138
  case "agents": {
37744
38139
  if (value !== undefined) {
37745
38140
  findings.push({
@@ -37986,27 +38381,27 @@ function validateConfigKey(path21, value, _config) {
37986
38381
  }
37987
38382
  return findings;
37988
38383
  }
37989
- function walkConfigAndValidate(obj, path21, config3, findings) {
38384
+ function walkConfigAndValidate(obj, path22, config3, findings) {
37990
38385
  if (obj === null || obj === undefined) {
37991
38386
  return;
37992
38387
  }
37993
- if (path21 && typeof obj === "object" && !Array.isArray(obj)) {
37994
- const keyFindings = validateConfigKey(path21, obj, config3);
38388
+ if (path22 && typeof obj === "object" && !Array.isArray(obj)) {
38389
+ const keyFindings = validateConfigKey(path22, obj, config3);
37995
38390
  findings.push(...keyFindings);
37996
38391
  }
37997
38392
  if (typeof obj !== "object") {
37998
- const keyFindings = validateConfigKey(path21, obj, config3);
38393
+ const keyFindings = validateConfigKey(path22, obj, config3);
37999
38394
  findings.push(...keyFindings);
38000
38395
  return;
38001
38396
  }
38002
38397
  if (Array.isArray(obj)) {
38003
38398
  obj.forEach((item, index) => {
38004
- walkConfigAndValidate(item, `${path21}[${index}]`, config3, findings);
38399
+ walkConfigAndValidate(item, `${path22}[${index}]`, config3, findings);
38005
38400
  });
38006
38401
  return;
38007
38402
  }
38008
38403
  for (const [key, value] of Object.entries(obj)) {
38009
- const newPath = path21 ? `${path21}.${key}` : key;
38404
+ const newPath = path22 ? `${path22}.${key}` : key;
38010
38405
  walkConfigAndValidate(value, newPath, config3, findings);
38011
38406
  }
38012
38407
  }
@@ -38126,7 +38521,7 @@ function applySafeAutoFixes(directory, result) {
38126
38521
  }
38127
38522
  }
38128
38523
  if (appliedFixes.length > 0) {
38129
- const configDir = path20.dirname(configPath);
38524
+ const configDir = path21.dirname(configPath);
38130
38525
  if (!fs8.existsSync(configDir)) {
38131
38526
  fs8.mkdirSync(configDir, { recursive: true });
38132
38527
  }
@@ -38136,12 +38531,12 @@ function applySafeAutoFixes(directory, result) {
38136
38531
  return { appliedFixes, updatedConfigPath };
38137
38532
  }
38138
38533
  function writeDoctorArtifact(directory, result) {
38139
- const swarmDir = path20.join(directory, ".swarm");
38534
+ const swarmDir = path21.join(directory, ".swarm");
38140
38535
  if (!fs8.existsSync(swarmDir)) {
38141
38536
  fs8.mkdirSync(swarmDir, { recursive: true });
38142
38537
  }
38143
38538
  const artifactFilename = "config-doctor.json";
38144
- const artifactPath = path20.join(swarmDir, artifactFilename);
38539
+ const artifactPath = path21.join(swarmDir, artifactFilename);
38145
38540
  const guiOutput = {
38146
38541
  timestamp: result.timestamp,
38147
38542
  summary: result.summary,
@@ -39188,7 +39583,7 @@ var init_profiles = __esm(() => {
39188
39583
 
39189
39584
  // src/lang/detector.ts
39190
39585
  import { access as access3, readdir as readdir2 } from "fs/promises";
39191
- import { extname as extname2, join as join18 } from "path";
39586
+ import { extname as extname2, join as join19 } from "path";
39192
39587
  async function detectProjectLanguages(projectDir) {
39193
39588
  const detected = new Set;
39194
39589
  async function scanDir(dir) {
@@ -39204,7 +39599,7 @@ async function detectProjectLanguages(projectDir) {
39204
39599
  if (detectFile.includes("*") || detectFile.includes("?"))
39205
39600
  continue;
39206
39601
  try {
39207
- await access3(join18(dir, detectFile));
39602
+ await access3(join19(dir, detectFile));
39208
39603
  detected.add(profile.id);
39209
39604
  break;
39210
39605
  } catch {}
@@ -39225,7 +39620,7 @@ async function detectProjectLanguages(projectDir) {
39225
39620
  const topEntries = await readdir2(projectDir, { withFileTypes: true });
39226
39621
  for (const entry of topEntries) {
39227
39622
  if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
39228
- await scanDir(join18(projectDir, entry.name));
39623
+ await scanDir(join19(projectDir, entry.name));
39229
39624
  }
39230
39625
  }
39231
39626
  } catch {}
@@ -39244,7 +39639,7 @@ var init_detector = __esm(() => {
39244
39639
 
39245
39640
  // src/build/discovery.ts
39246
39641
  import * as fs9 from "fs";
39247
- import * as path21 from "path";
39642
+ import * as path22 from "path";
39248
39643
  function isCommandAvailable(command) {
39249
39644
  if (toolchainCache.has(command)) {
39250
39645
  return toolchainCache.get(command);
@@ -39276,11 +39671,11 @@ function findBuildFiles(workingDir, patterns) {
39276
39671
  const regex = simpleGlobToRegex(pattern);
39277
39672
  const matches = files.filter((f) => regex.test(f));
39278
39673
  if (matches.length > 0) {
39279
- return path21.join(dir, matches[0]);
39674
+ return path22.join(dir, matches[0]);
39280
39675
  }
39281
39676
  } catch {}
39282
39677
  } else {
39283
- const filePath = path21.join(workingDir, pattern);
39678
+ const filePath = path22.join(workingDir, pattern);
39284
39679
  if (fs9.existsSync(filePath)) {
39285
39680
  return filePath;
39286
39681
  }
@@ -39289,7 +39684,7 @@ function findBuildFiles(workingDir, patterns) {
39289
39684
  return null;
39290
39685
  }
39291
39686
  function getRepoDefinedScripts(workingDir, scripts) {
39292
- const packageJsonPath = path21.join(workingDir, "package.json");
39687
+ const packageJsonPath = path22.join(workingDir, "package.json");
39293
39688
  if (!fs9.existsSync(packageJsonPath)) {
39294
39689
  return [];
39295
39690
  }
@@ -39330,7 +39725,7 @@ function findAllBuildFiles(workingDir) {
39330
39725
  const regex = simpleGlobToRegex(pattern);
39331
39726
  findFilesRecursive(workingDir, regex, allBuildFiles);
39332
39727
  } else {
39333
- const filePath = path21.join(workingDir, pattern);
39728
+ const filePath = path22.join(workingDir, pattern);
39334
39729
  if (fs9.existsSync(filePath)) {
39335
39730
  allBuildFiles.add(filePath);
39336
39731
  }
@@ -39343,7 +39738,7 @@ function findFilesRecursive(dir, regex, results) {
39343
39738
  try {
39344
39739
  const entries = fs9.readdirSync(dir, { withFileTypes: true });
39345
39740
  for (const entry of entries) {
39346
- const fullPath = path21.join(dir, entry.name);
39741
+ const fullPath = path22.join(dir, entry.name);
39347
39742
  if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
39348
39743
  findFilesRecursive(fullPath, regex, results);
39349
39744
  } else if (entry.isFile() && regex.test(entry.name)) {
@@ -39366,7 +39761,7 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
39366
39761
  let foundCommand = false;
39367
39762
  for (const cmd of sortedCommands) {
39368
39763
  if (cmd.detectFile) {
39369
- const detectFilePath = path21.join(workingDir, cmd.detectFile);
39764
+ const detectFilePath = path22.join(workingDir, cmd.detectFile);
39370
39765
  if (!fs9.existsSync(detectFilePath)) {
39371
39766
  continue;
39372
39767
  }
@@ -39399,7 +39794,7 @@ async function discoverBuildCommands(workingDir, options) {
39399
39794
  const scope = options?.scope ?? "all";
39400
39795
  const changedFiles = options?.changedFiles ?? [];
39401
39796
  const _filesToCheck = filterByScope(workingDir, scope, changedFiles);
39402
- const profileResult = await discoverBuildCommandsFromProfiles(workingDir);
39797
+ const profileResult = await _internals11.discoverBuildCommandsFromProfiles(workingDir);
39403
39798
  const profileCommands = profileResult.commands;
39404
39799
  const profileSkipped = profileResult.skipped;
39405
39800
  const coveredEcosystems = new Set;
@@ -39456,7 +39851,13 @@ async function discoverBuildCommands(workingDir, options) {
39456
39851
  commands.sort((a, b) => a.priority - b.priority);
39457
39852
  return { commands, skipped };
39458
39853
  }
39459
- var ECOSYSTEMS, PROFILE_TO_ECOSYSTEM_NAMES, toolchainCache, build_discovery;
39854
+ function clearToolchainCache() {
39855
+ toolchainCache.clear();
39856
+ }
39857
+ function getEcosystems() {
39858
+ return ECOSYSTEMS.map((e) => e.ecosystem);
39859
+ }
39860
+ var ECOSYSTEMS, PROFILE_TO_ECOSYSTEM_NAMES, toolchainCache, _internals11, build_discovery;
39460
39861
  var init_discovery = __esm(() => {
39461
39862
  init_dist();
39462
39863
  init_detector();
@@ -39574,6 +39975,13 @@ var init_discovery = __esm(() => {
39574
39975
  php: ["php-composer"]
39575
39976
  };
39576
39977
  toolchainCache = new Map;
39978
+ _internals11 = {
39979
+ isCommandAvailable,
39980
+ discoverBuildCommandsFromProfiles,
39981
+ discoverBuildCommands,
39982
+ clearToolchainCache,
39983
+ getEcosystems
39984
+ };
39577
39985
  build_discovery = tool({
39578
39986
  description: "Discover build commands for various ecosystems in a project directory",
39579
39987
  args: {
@@ -39593,7 +40001,7 @@ var init_discovery = __esm(() => {
39593
40001
 
39594
40002
  // src/services/tool-doctor.ts
39595
40003
  import * as fs10 from "fs";
39596
- import * as path22 from "path";
40004
+ import * as path23 from "path";
39597
40005
  function extractRegisteredToolKeys(indexPath) {
39598
40006
  const registeredKeys = new Set;
39599
40007
  try {
@@ -39648,8 +40056,8 @@ function checkBinaryReadiness() {
39648
40056
  }
39649
40057
  function runToolDoctor(_directory, pluginRoot) {
39650
40058
  const findings = [];
39651
- const resolvedPluginRoot = pluginRoot ?? path22.resolve(import.meta.dir, "..", "..");
39652
- const indexPath = path22.join(resolvedPluginRoot, "src", "index.ts");
40059
+ const resolvedPluginRoot = pluginRoot ?? path23.resolve(import.meta.dir, "..", "..");
40060
+ const indexPath = path23.join(resolvedPluginRoot, "src", "index.ts");
39653
40061
  if (!fs10.existsSync(indexPath)) {
39654
40062
  return {
39655
40063
  findings: [
@@ -39819,6 +40227,7 @@ var exports_evidence_summary_service = {};
39819
40227
  __export(exports_evidence_summary_service, {
39820
40228
  isAutoSummaryEnabled: () => isAutoSummaryEnabled,
39821
40229
  buildEvidenceSummary: () => buildEvidenceSummary,
40230
+ _internals: () => _internals12,
39822
40231
  REQUIRED_EVIDENCE_TYPES: () => REQUIRED_EVIDENCE_TYPES,
39823
40232
  EVIDENCE_SUMMARY_VERSION: () => EVIDENCE_SUMMARY_VERSION
39824
40233
  });
@@ -39856,14 +40265,14 @@ function getTaskStatus(task, bundle) {
39856
40265
  if (task?.status) {
39857
40266
  return task.status;
39858
40267
  }
39859
- const entries = normalizeBundleEntries(bundle);
40268
+ const entries = _internals12.normalizeBundleEntries(bundle);
39860
40269
  if (entries.length > 0) {
39861
40270
  return "completed";
39862
40271
  }
39863
40272
  return "pending";
39864
40273
  }
39865
40274
  function isEvidenceComplete(bundle) {
39866
- const entries = normalizeBundleEntries(bundle);
40275
+ const entries = _internals12.normalizeBundleEntries(bundle);
39867
40276
  if (entries.length === 0) {
39868
40277
  return {
39869
40278
  isComplete: false,
@@ -39899,10 +40308,10 @@ async function buildTaskSummary(directory, task, taskId) {
39899
40308
  const result = await loadEvidence(directory, taskId);
39900
40309
  const bundle = result.status === "found" ? result.bundle : null;
39901
40310
  const phase = task?.phase ?? 0;
39902
- const status = getTaskStatus(task, bundle);
39903
- const evidenceCheck = isEvidenceComplete(bundle);
39904
- const blockers = getTaskBlockers(task, evidenceCheck, status);
39905
- const entries = normalizeBundleEntries(bundle);
40311
+ const status = _internals12.getTaskStatus(task, bundle);
40312
+ const evidenceCheck = _internals12.isEvidenceComplete(bundle);
40313
+ const blockers = _internals12.getTaskBlockers(task, evidenceCheck, status);
40314
+ const entries = _internals12.normalizeBundleEntries(bundle);
39906
40315
  const hasReview = entries.some((e) => e.type === "review");
39907
40316
  const hasTest = entries.some((e) => e.type === "test");
39908
40317
  const hasApproval = entries.some((e) => e.type === "approval");
@@ -39931,12 +40340,12 @@ async function buildPhaseSummary(directory, phase) {
39931
40340
  const taskSummaries = [];
39932
40341
  const _taskMap = new Map(phase.tasks.map((t) => [t.id, t]));
39933
40342
  for (const task of phase.tasks) {
39934
- const summary = await buildTaskSummary(directory, task, task.id);
40343
+ const summary = await _internals12.buildTaskSummary(directory, task, task.id);
39935
40344
  taskSummaries.push(summary);
39936
40345
  }
39937
40346
  const extraTaskIds = taskIds.filter((id) => !phaseTaskIds.has(id));
39938
40347
  for (const taskId of extraTaskIds) {
39939
- const summary = await buildTaskSummary(directory, undefined, taskId);
40348
+ const summary = await _internals12.buildTaskSummary(directory, undefined, taskId);
39940
40349
  if (summary.phase === phase.id) {
39941
40350
  taskSummaries.push(summary);
39942
40351
  }
@@ -40037,7 +40446,7 @@ async function buildEvidenceSummary(directory, currentPhase) {
40037
40446
  let totalTasks = 0;
40038
40447
  let completedTasks = 0;
40039
40448
  for (const phase of phasesToProcess) {
40040
- const summary = await buildPhaseSummary(directory, phase);
40449
+ const summary = await _internals12.buildPhaseSummary(directory, phase);
40041
40450
  phaseSummaries.push(summary);
40042
40451
  totalTasks += summary.totalTasks;
40043
40452
  completedTasks += summary.completedTasks;
@@ -40059,7 +40468,7 @@ async function buildEvidenceSummary(directory, currentPhase) {
40059
40468
  overallBlockers,
40060
40469
  summaryText: ""
40061
40470
  };
40062
- artifact.summaryText = generateSummaryText(artifact);
40471
+ artifact.summaryText = _internals12.generateSummaryText(artifact);
40063
40472
  log("[EvidenceSummary] Summary built", {
40064
40473
  phases: phaseSummaries.length,
40065
40474
  totalTasks,
@@ -40078,7 +40487,7 @@ function isAutoSummaryEnabled(automationConfig) {
40078
40487
  }
40079
40488
  return automationConfig.capabilities?.evidence_auto_summaries === true;
40080
40489
  }
40081
- var VALID_EVIDENCE_TYPES2, REQUIRED_EVIDENCE_TYPES, EVIDENCE_SUMMARY_VERSION = "1.0.0";
40490
+ var VALID_EVIDENCE_TYPES2, REQUIRED_EVIDENCE_TYPES, EVIDENCE_SUMMARY_VERSION = "1.0.0", _internals12;
40082
40491
  var init_evidence_summary_service = __esm(() => {
40083
40492
  init_manager2();
40084
40493
  init_manager();
@@ -40092,6 +40501,17 @@ var init_evidence_summary_service = __esm(() => {
40092
40501
  "retrospective"
40093
40502
  ]);
40094
40503
  REQUIRED_EVIDENCE_TYPES = ["review", "test"];
40504
+ _internals12 = {
40505
+ buildEvidenceSummary,
40506
+ isAutoSummaryEnabled,
40507
+ normalizeBundleEntries,
40508
+ getTaskStatus,
40509
+ isEvidenceComplete,
40510
+ getTaskBlockers,
40511
+ buildTaskSummary,
40512
+ buildPhaseSummary,
40513
+ generateSummaryText
40514
+ };
40095
40515
  });
40096
40516
 
40097
40517
  // src/services/evidence-service.ts
@@ -40391,7 +40811,7 @@ function extractCurrentPhaseFromPlan2(plan) {
40391
40811
  if (!plan) {
40392
40812
  return { currentPhase: null, currentTask: null, incompleteTasks: [] };
40393
40813
  }
40394
- if (!validatePlanPhases(plan)) {
40814
+ if (!_internals13.validatePlanPhases(plan)) {
40395
40815
  return { currentPhase: null, currentTask: null, incompleteTasks: [] };
40396
40816
  }
40397
40817
  let currentPhase = null;
@@ -40533,9 +40953,9 @@ function extractPhaseMetrics(content) {
40533
40953
  async function getHandoffData(directory) {
40534
40954
  const now = new Date().toISOString();
40535
40955
  const sessionContent = await readSwarmFileAsync(directory, "session/state.json");
40536
- const sessionState = parseSessionState(sessionContent);
40956
+ const sessionState = _internals13.parseSessionState(sessionContent);
40537
40957
  const plan = await loadPlanJsonOnly(directory);
40538
- const planInfo = extractCurrentPhaseFromPlan2(plan);
40958
+ const planInfo = _internals13.extractCurrentPhaseFromPlan(plan);
40539
40959
  if (!plan) {
40540
40960
  const planMdContent = await readSwarmFileAsync(directory, "plan.md");
40541
40961
  if (planMdContent) {
@@ -40554,8 +40974,8 @@ async function getHandoffData(directory) {
40554
40974
  }
40555
40975
  }
40556
40976
  const contextContent = await readSwarmFileAsync(directory, "context.md");
40557
- const recentDecisions = extractDecisions(contextContent);
40558
- const rawPhaseMetrics = extractPhaseMetrics(contextContent);
40977
+ const recentDecisions = _internals13.extractDecisions(contextContent);
40978
+ const rawPhaseMetrics = _internals13.extractPhaseMetrics(contextContent);
40559
40979
  const phaseMetrics = sanitizeString(rawPhaseMetrics, 1000);
40560
40980
  let delegationState = null;
40561
40981
  if (sessionState?.delegationState) {
@@ -40719,12 +41139,24 @@ ${lines.join(`
40719
41139
  `)}
40720
41140
  \`\`\``;
40721
41141
  }
40722
- var RTL_OVERRIDE_PATTERN, MAX_TASK_ID_LENGTH = 100, MAX_DECISION_LENGTH = 500, MAX_INCOMPLETE_TASKS = 20;
41142
+ var RTL_OVERRIDE_PATTERN, MAX_TASK_ID_LENGTH = 100, MAX_DECISION_LENGTH = 500, MAX_INCOMPLETE_TASKS = 20, _internals13;
40723
41143
  var init_handoff_service = __esm(() => {
40724
41144
  init_utils2();
40725
41145
  init_manager();
40726
41146
  init_utils();
40727
41147
  RTL_OVERRIDE_PATTERN = /[\u202e\u202d\u202c\u200f]/g;
41148
+ _internals13 = {
41149
+ getHandoffData,
41150
+ formatHandoffMarkdown,
41151
+ formatContinuationPrompt,
41152
+ escapeHtml,
41153
+ sanitizeString,
41154
+ validatePlanPhases,
41155
+ extractCurrentPhaseFromPlan: extractCurrentPhaseFromPlan2,
41156
+ parseSessionState,
41157
+ extractDecisions,
41158
+ extractPhaseMetrics
41159
+ };
40728
41160
  });
40729
41161
 
40730
41162
  // src/commands/handoff.ts
@@ -41116,14 +41548,23 @@ var init_issue = __esm(() => {
41116
41548
 
41117
41549
  // src/hooks/knowledge-migrator.ts
41118
41550
  import { randomUUID as randomUUID2 } from "crypto";
41119
- import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
41120
- import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
41121
- import * as path23 from "path";
41551
+ import { existsSync as existsSync14, readFileSync as readFileSync10 } from "fs";
41552
+ import { mkdir as mkdir5, readFile as readFile6, writeFile as writeFile6 } from "fs/promises";
41553
+ import * as path24 from "path";
41554
+ async function migrateKnowledgeToExternal(_directory, _config) {
41555
+ return {
41556
+ migrated: false,
41557
+ entriesMigrated: 0,
41558
+ entriesDropped: 0,
41559
+ entriesTotal: 0,
41560
+ skippedReason: "no-context-file"
41561
+ };
41562
+ }
41122
41563
  async function migrateContextToKnowledge(directory, config3) {
41123
- const sentinelPath = path23.join(directory, ".swarm", ".knowledge-migrated");
41124
- const contextPath = path23.join(directory, ".swarm", "context.md");
41564
+ const sentinelPath = path24.join(directory, ".swarm", ".knowledge-migrated");
41565
+ const contextPath = path24.join(directory, ".swarm", "context.md");
41125
41566
  const knowledgePath = resolveSwarmKnowledgePath(directory);
41126
- if (existsSync13(sentinelPath)) {
41567
+ if (existsSync14(sentinelPath)) {
41127
41568
  return {
41128
41569
  migrated: false,
41129
41570
  entriesMigrated: 0,
@@ -41132,7 +41573,7 @@ async function migrateContextToKnowledge(directory, config3) {
41132
41573
  skippedReason: "sentinel-exists"
41133
41574
  };
41134
41575
  }
41135
- if (!existsSync13(contextPath)) {
41576
+ if (!existsSync14(contextPath)) {
41136
41577
  return {
41137
41578
  migrated: false,
41138
41579
  entriesMigrated: 0,
@@ -41141,7 +41582,7 @@ async function migrateContextToKnowledge(directory, config3) {
41141
41582
  skippedReason: "no-context-file"
41142
41583
  };
41143
41584
  }
41144
- const contextContent = await readFile5(contextPath, "utf-8");
41585
+ const contextContent = await readFile6(contextPath, "utf-8");
41145
41586
  if (contextContent.trim().length === 0) {
41146
41587
  return {
41147
41588
  migrated: false,
@@ -41151,9 +41592,9 @@ async function migrateContextToKnowledge(directory, config3) {
41151
41592
  skippedReason: "empty-context"
41152
41593
  };
41153
41594
  }
41154
- const rawEntries = parseContextMd(contextContent);
41595
+ const rawEntries = _internals14.parseContextMd(contextContent);
41155
41596
  if (rawEntries.length === 0) {
41156
- await writeSentinel(sentinelPath, 0, 0);
41597
+ await _internals14.writeSentinel(sentinelPath, 0, 0);
41157
41598
  return {
41158
41599
  migrated: true,
41159
41600
  entriesMigrated: 0,
@@ -41164,10 +41605,10 @@ async function migrateContextToKnowledge(directory, config3) {
41164
41605
  const existing = await readKnowledge(knowledgePath);
41165
41606
  let migrated = 0;
41166
41607
  let dropped = 0;
41167
- const projectName = inferProjectName(directory);
41608
+ const projectName = _internals14.inferProjectName(directory);
41168
41609
  for (const raw of rawEntries) {
41169
41610
  if (config3.validation_enabled !== false) {
41170
- const category = raw.categoryHint ?? inferCategoryFromText(raw.text);
41611
+ const category = raw.categoryHint ?? _internals14.inferCategoryFromText(raw.text);
41171
41612
  const result = validateLesson(raw.text, existing.map((e) => e.lesson), {
41172
41613
  category,
41173
41614
  scope: "global",
@@ -41187,8 +41628,8 @@ async function migrateContextToKnowledge(directory, config3) {
41187
41628
  const entry = {
41188
41629
  id: randomUUID2(),
41189
41630
  tier: "swarm",
41190
- lesson: truncateLesson(raw.text),
41191
- category: raw.categoryHint ?? inferCategoryFromText(raw.text),
41631
+ lesson: _internals14.truncateLesson(raw.text),
41632
+ category: raw.categoryHint ?? _internals14.inferCategoryFromText(raw.text),
41192
41633
  tags: [...inferredTags, `migration:${raw.sourceSection}`],
41193
41634
  scope: "global",
41194
41635
  confidence: 0.3,
@@ -41211,7 +41652,7 @@ async function migrateContextToKnowledge(directory, config3) {
41211
41652
  if (migrated > 0) {
41212
41653
  await rewriteKnowledge(knowledgePath, existing);
41213
41654
  }
41214
- await writeSentinel(sentinelPath, migrated, dropped);
41655
+ await _internals14.writeSentinel(sentinelPath, migrated, dropped);
41215
41656
  log(`[knowledge-migrator] Migrated ${migrated} entries, dropped ${dropped}`);
41216
41657
  return {
41217
41658
  migrated: true,
@@ -41221,7 +41662,7 @@ async function migrateContextToKnowledge(directory, config3) {
41221
41662
  };
41222
41663
  }
41223
41664
  function parseContextMd(content) {
41224
- const sections = splitIntoSections(content);
41665
+ const sections = _internals14.splitIntoSections(content);
41225
41666
  const entries = [];
41226
41667
  const seen = new Set;
41227
41668
  const sectionPatterns = [
@@ -41237,7 +41678,7 @@ function parseContextMd(content) {
41237
41678
  const match = sectionPatterns.find((sp) => sp.pattern.test(section.heading));
41238
41679
  if (!match)
41239
41680
  continue;
41240
- const bullets = extractBullets(section.body);
41681
+ const bullets = _internals14.extractBullets(section.body);
41241
41682
  for (const bullet of bullets) {
41242
41683
  if (bullet.length < 15)
41243
41684
  continue;
@@ -41246,9 +41687,9 @@ function parseContextMd(content) {
41246
41687
  continue;
41247
41688
  seen.add(normalized);
41248
41689
  entries.push({
41249
- text: truncateLesson(bullet),
41690
+ text: _internals14.truncateLesson(bullet),
41250
41691
  sourceSection: match.sourceSection,
41251
- categoryHint: inferCategoryFromText(bullet)
41692
+ categoryHint: _internals14.inferCategoryFromText(bullet)
41252
41693
  });
41253
41694
  }
41254
41695
  }
@@ -41317,8 +41758,8 @@ function truncateLesson(text) {
41317
41758
  return `${text.slice(0, 277)}...`;
41318
41759
  }
41319
41760
  function inferProjectName(directory) {
41320
- const packageJsonPath = path23.join(directory, "package.json");
41321
- if (existsSync13(packageJsonPath)) {
41761
+ const packageJsonPath = path24.join(directory, "package.json");
41762
+ if (existsSync14(packageJsonPath)) {
41322
41763
  try {
41323
41764
  const pkg = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
41324
41765
  if (pkg.name && typeof pkg.name === "string") {
@@ -41326,7 +41767,7 @@ function inferProjectName(directory) {
41326
41767
  }
41327
41768
  } catch {}
41328
41769
  }
41329
- return path23.basename(directory);
41770
+ return path24.basename(directory);
41330
41771
  }
41331
41772
  async function writeSentinel(sentinelPath, migrated, dropped) {
41332
41773
  const sentinel = {
@@ -41338,16 +41779,29 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
41338
41779
  schema_version: 1,
41339
41780
  migration_tool: "knowledge-migrator.ts"
41340
41781
  };
41341
- await mkdir4(path23.dirname(sentinelPath), { recursive: true });
41342
- await writeFile5(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
41782
+ await mkdir5(path24.dirname(sentinelPath), { recursive: true });
41783
+ await writeFile6(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
41343
41784
  }
41785
+ var _internals14;
41344
41786
  var init_knowledge_migrator = __esm(() => {
41787
+ init_logger();
41345
41788
  init_knowledge_store();
41346
41789
  init_knowledge_validator();
41790
+ _internals14 = {
41791
+ migrateContextToKnowledge,
41792
+ migrateKnowledgeToExternal,
41793
+ parseContextMd,
41794
+ splitIntoSections,
41795
+ extractBullets,
41796
+ inferCategoryFromText,
41797
+ truncateLesson,
41798
+ inferProjectName,
41799
+ writeSentinel
41800
+ };
41347
41801
  });
41348
41802
 
41349
41803
  // src/commands/knowledge.ts
41350
- import { join as join22 } from "path";
41804
+ import { join as join23 } from "path";
41351
41805
  function resolveEntryByPrefix(entries, inputId) {
41352
41806
  const exact = entries.find((e) => e.id === inputId);
41353
41807
  if (exact)
@@ -41398,7 +41852,7 @@ async function handleKnowledgeRestoreCommand(directory, args) {
41398
41852
  return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
41399
41853
  }
41400
41854
  try {
41401
- const quarantinePath = join22(directory, ".swarm", "knowledge-quarantined.jsonl");
41855
+ const quarantinePath = join23(directory, ".swarm", "knowledge-quarantined.jsonl");
41402
41856
  const entries = await readKnowledge(quarantinePath);
41403
41857
  const resolved = resolveEntryByPrefix(entries, inputId);
41404
41858
  if ("error" in resolved) {
@@ -41847,7 +42301,7 @@ var init_path_security = () => {};
41847
42301
 
41848
42302
  // src/tools/lint.ts
41849
42303
  import * as fs11 from "fs";
41850
- import * as path24 from "path";
42304
+ import * as path25 from "path";
41851
42305
  function validateArgs(args) {
41852
42306
  if (typeof args !== "object" || args === null)
41853
42307
  return false;
@@ -41858,9 +42312,9 @@ function validateArgs(args) {
41858
42312
  }
41859
42313
  function getLinterCommand(linter, mode, projectDir) {
41860
42314
  const isWindows = process.platform === "win32";
41861
- const binDir = path24.join(projectDir, "node_modules", ".bin");
41862
- const biomeBin = isWindows ? path24.join(binDir, "biome.EXE") : path24.join(binDir, "biome");
41863
- const eslintBin = isWindows ? path24.join(binDir, "eslint.cmd") : path24.join(binDir, "eslint");
42315
+ const binDir = path25.join(projectDir, "node_modules", ".bin");
42316
+ const biomeBin = isWindows ? path25.join(binDir, "biome.EXE") : path25.join(binDir, "biome");
42317
+ const eslintBin = isWindows ? path25.join(binDir, "eslint.cmd") : path25.join(binDir, "eslint");
41864
42318
  switch (linter) {
41865
42319
  case "biome":
41866
42320
  if (mode === "fix") {
@@ -41876,7 +42330,7 @@ function getLinterCommand(linter, mode, projectDir) {
41876
42330
  }
41877
42331
  function getAdditionalLinterCommand(linter, mode, cwd) {
41878
42332
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
41879
- const gradlew = fs11.existsSync(path24.join(cwd, gradlewName)) ? path24.join(cwd, gradlewName) : null;
42333
+ const gradlew = fs11.existsSync(path25.join(cwd, gradlewName)) ? path25.join(cwd, gradlewName) : null;
41880
42334
  switch (linter) {
41881
42335
  case "ruff":
41882
42336
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -41910,10 +42364,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
41910
42364
  }
41911
42365
  }
41912
42366
  function detectRuff(cwd) {
41913
- if (fs11.existsSync(path24.join(cwd, "ruff.toml")))
42367
+ if (fs11.existsSync(path25.join(cwd, "ruff.toml")))
41914
42368
  return isCommandAvailable("ruff");
41915
42369
  try {
41916
- const pyproject = path24.join(cwd, "pyproject.toml");
42370
+ const pyproject = path25.join(cwd, "pyproject.toml");
41917
42371
  if (fs11.existsSync(pyproject)) {
41918
42372
  const content = fs11.readFileSync(pyproject, "utf-8");
41919
42373
  if (content.includes("[tool.ruff]"))
@@ -41923,19 +42377,19 @@ function detectRuff(cwd) {
41923
42377
  return false;
41924
42378
  }
41925
42379
  function detectClippy(cwd) {
41926
- return fs11.existsSync(path24.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
42380
+ return fs11.existsSync(path25.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
41927
42381
  }
41928
42382
  function detectGolangciLint(cwd) {
41929
- return fs11.existsSync(path24.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
42383
+ return fs11.existsSync(path25.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
41930
42384
  }
41931
42385
  function detectCheckstyle(cwd) {
41932
- const hasMaven = fs11.existsSync(path24.join(cwd, "pom.xml"));
41933
- const hasGradle = fs11.existsSync(path24.join(cwd, "build.gradle")) || fs11.existsSync(path24.join(cwd, "build.gradle.kts"));
41934
- const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs11.existsSync(path24.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
42386
+ const hasMaven = fs11.existsSync(path25.join(cwd, "pom.xml"));
42387
+ const hasGradle = fs11.existsSync(path25.join(cwd, "build.gradle")) || fs11.existsSync(path25.join(cwd, "build.gradle.kts"));
42388
+ const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs11.existsSync(path25.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
41935
42389
  return (hasMaven || hasGradle) && hasBinary;
41936
42390
  }
41937
42391
  function detectKtlint(cwd) {
41938
- const hasKotlin = fs11.existsSync(path24.join(cwd, "build.gradle.kts")) || fs11.existsSync(path24.join(cwd, "build.gradle")) || (() => {
42392
+ const hasKotlin = fs11.existsSync(path25.join(cwd, "build.gradle.kts")) || fs11.existsSync(path25.join(cwd, "build.gradle")) || (() => {
41939
42393
  try {
41940
42394
  return fs11.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
41941
42395
  } catch {
@@ -41954,11 +42408,11 @@ function detectDotnetFormat(cwd) {
41954
42408
  }
41955
42409
  }
41956
42410
  function detectCppcheck(cwd) {
41957
- if (fs11.existsSync(path24.join(cwd, "CMakeLists.txt"))) {
42411
+ if (fs11.existsSync(path25.join(cwd, "CMakeLists.txt"))) {
41958
42412
  return isCommandAvailable("cppcheck");
41959
42413
  }
41960
42414
  try {
41961
- const dirsToCheck = [cwd, path24.join(cwd, "src")];
42415
+ const dirsToCheck = [cwd, path25.join(cwd, "src")];
41962
42416
  const hasCpp = dirsToCheck.some((dir) => {
41963
42417
  try {
41964
42418
  return fs11.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
@@ -41972,13 +42426,13 @@ function detectCppcheck(cwd) {
41972
42426
  }
41973
42427
  }
41974
42428
  function detectSwiftlint(cwd) {
41975
- return fs11.existsSync(path24.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
42429
+ return fs11.existsSync(path25.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
41976
42430
  }
41977
42431
  function detectDartAnalyze(cwd) {
41978
- return fs11.existsSync(path24.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
42432
+ return fs11.existsSync(path25.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
41979
42433
  }
41980
42434
  function detectRubocop(cwd) {
41981
- return (fs11.existsSync(path24.join(cwd, "Gemfile")) || fs11.existsSync(path24.join(cwd, "gems.rb")) || fs11.existsSync(path24.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
42435
+ return (fs11.existsSync(path25.join(cwd, "Gemfile")) || fs11.existsSync(path25.join(cwd, "gems.rb")) || fs11.existsSync(path25.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
41982
42436
  }
41983
42437
  function detectAdditionalLinter(cwd) {
41984
42438
  if (detectRuff(cwd))
@@ -42006,10 +42460,10 @@ function detectAdditionalLinter(cwd) {
42006
42460
  function findBinInAncestors(startDir, binName) {
42007
42461
  let dir = startDir;
42008
42462
  while (true) {
42009
- const candidate = path24.join(dir, "node_modules", ".bin", binName);
42463
+ const candidate = path25.join(dir, "node_modules", ".bin", binName);
42010
42464
  if (fs11.existsSync(candidate))
42011
42465
  return candidate;
42012
- const parent = path24.dirname(dir);
42466
+ const parent = path25.dirname(dir);
42013
42467
  if (parent === dir)
42014
42468
  break;
42015
42469
  dir = parent;
@@ -42018,10 +42472,10 @@ function findBinInAncestors(startDir, binName) {
42018
42472
  }
42019
42473
  function findBinInEnvPath(binName) {
42020
42474
  const searchPath = process.env.PATH ?? "";
42021
- for (const dir of searchPath.split(path24.delimiter)) {
42475
+ for (const dir of searchPath.split(path25.delimiter)) {
42022
42476
  if (!dir)
42023
42477
  continue;
42024
- const candidate = path24.join(dir, binName);
42478
+ const candidate = path25.join(dir, binName);
42025
42479
  if (fs11.existsSync(candidate))
42026
42480
  return candidate;
42027
42481
  }
@@ -42034,13 +42488,13 @@ async function detectAvailableLinter(directory) {
42034
42488
  return null;
42035
42489
  const projectDir = directory;
42036
42490
  const isWindows = process.platform === "win32";
42037
- const biomeBin = isWindows ? path24.join(projectDir, "node_modules", ".bin", "biome.EXE") : path24.join(projectDir, "node_modules", ".bin", "biome");
42038
- const eslintBin = isWindows ? path24.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path24.join(projectDir, "node_modules", ".bin", "eslint");
42491
+ const biomeBin = isWindows ? path25.join(projectDir, "node_modules", ".bin", "biome.EXE") : path25.join(projectDir, "node_modules", ".bin", "biome");
42492
+ const eslintBin = isWindows ? path25.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path25.join(projectDir, "node_modules", ".bin", "eslint");
42039
42493
  const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
42040
42494
  if (localResult)
42041
42495
  return localResult;
42042
- const biomeAncestor = findBinInAncestors(path24.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
42043
- const eslintAncestor = findBinInAncestors(path24.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
42496
+ const biomeAncestor = findBinInAncestors(path25.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
42497
+ const eslintAncestor = findBinInAncestors(path25.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
42044
42498
  if (biomeAncestor || eslintAncestor) {
42045
42499
  return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
42046
42500
  }
@@ -42199,7 +42653,7 @@ async function runAdditionalLint(linter, mode, cwd) {
42199
42653
  };
42200
42654
  }
42201
42655
  }
42202
- var MAX_OUTPUT_BYTES = 512000, MAX_COMMAND_LENGTH = 500, lint;
42656
+ var MAX_OUTPUT_BYTES = 512000, MAX_COMMAND_LENGTH = 500, lint, _internals15;
42203
42657
  var init_lint = __esm(() => {
42204
42658
  init_zod();
42205
42659
  init_discovery();
@@ -42231,15 +42685,15 @@ var init_lint = __esm(() => {
42231
42685
  }
42232
42686
  const { mode } = args;
42233
42687
  const cwd = directory;
42234
- const linter = await detectAvailableLinter(directory);
42688
+ const linter = await _internals15.detectAvailableLinter(directory);
42235
42689
  if (linter) {
42236
- const result = await runLint(linter, mode, directory);
42690
+ const result = await _internals15.runLint(linter, mode, directory);
42237
42691
  return JSON.stringify(result, null, 2);
42238
42692
  }
42239
- const additionalLinter = detectAdditionalLinter(cwd);
42693
+ const additionalLinter = _internals15.detectAdditionalLinter(cwd);
42240
42694
  if (additionalLinter) {
42241
42695
  warn(`[lint] Using ${additionalLinter} linter for this project`);
42242
- const result = await runAdditionalLint(additionalLinter, mode, cwd);
42696
+ const result = await _internals15.runAdditionalLint(additionalLinter, mode, cwd);
42243
42697
  return JSON.stringify(result, null, 2);
42244
42698
  }
42245
42699
  const errorResult = {
@@ -42253,11 +42707,17 @@ For Rust: rustup component add clippy`
42253
42707
  return JSON.stringify(errorResult, null, 2);
42254
42708
  }
42255
42709
  });
42710
+ _internals15 = {
42711
+ detectAvailableLinter,
42712
+ runLint,
42713
+ detectAdditionalLinter,
42714
+ runAdditionalLint
42715
+ };
42256
42716
  });
42257
42717
 
42258
42718
  // src/tools/secretscan.ts
42259
42719
  import * as fs12 from "fs";
42260
- import * as path25 from "path";
42720
+ import * as path26 from "path";
42261
42721
  function calculateShannonEntropy(str) {
42262
42722
  if (str.length === 0)
42263
42723
  return 0;
@@ -42305,7 +42765,7 @@ function isGlobOrPathPattern(pattern) {
42305
42765
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
42306
42766
  }
42307
42767
  function loadSecretScanIgnore(scanDir) {
42308
- const ignorePath = path25.join(scanDir, ".secretscanignore");
42768
+ const ignorePath = path26.join(scanDir, ".secretscanignore");
42309
42769
  try {
42310
42770
  if (!fs12.existsSync(ignorePath))
42311
42771
  return [];
@@ -42328,7 +42788,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
42328
42788
  if (exactNames.has(entry))
42329
42789
  return true;
42330
42790
  for (const pattern of globPatterns) {
42331
- if (path25.matchesGlob(relPath, pattern))
42791
+ if (path26.matchesGlob(relPath, pattern))
42332
42792
  return true;
42333
42793
  }
42334
42794
  return false;
@@ -42349,7 +42809,7 @@ function validateDirectoryInput(dir) {
42349
42809
  return null;
42350
42810
  }
42351
42811
  function isBinaryFile(filePath, buffer) {
42352
- const ext = path25.extname(filePath).toLowerCase();
42812
+ const ext = path26.extname(filePath).toLowerCase();
42353
42813
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
42354
42814
  return true;
42355
42815
  }
@@ -42485,9 +42945,9 @@ function isSymlinkLoop(realPath, visited) {
42485
42945
  return false;
42486
42946
  }
42487
42947
  function isPathWithinScope(realPath, scanDir) {
42488
- const resolvedScanDir = path25.resolve(scanDir);
42489
- const resolvedRealPath = path25.resolve(realPath);
42490
- return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path25.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
42948
+ const resolvedScanDir = path26.resolve(scanDir);
42949
+ const resolvedRealPath = path26.resolve(realPath);
42950
+ return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path26.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
42491
42951
  }
42492
42952
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
42493
42953
  skippedDirs: 0,
@@ -42513,8 +42973,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
42513
42973
  return a.localeCompare(b);
42514
42974
  });
42515
42975
  for (const entry of entries) {
42516
- const fullPath = path25.join(dir, entry);
42517
- const relPath = path25.relative(scanDir, fullPath).replace(/\\/g, "/");
42976
+ const fullPath = path26.join(dir, entry);
42977
+ const relPath = path26.relative(scanDir, fullPath).replace(/\\/g, "/");
42518
42978
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
42519
42979
  stats.skippedDirs++;
42520
42980
  continue;
@@ -42549,7 +43009,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
42549
43009
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
42550
43010
  files.push(...subFiles);
42551
43011
  } else if (lstat.isFile()) {
42552
- const ext = path25.extname(fullPath).toLowerCase();
43012
+ const ext = path26.extname(fullPath).toLowerCase();
42553
43013
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
42554
43014
  files.push(fullPath);
42555
43015
  } else {
@@ -42561,7 +43021,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
42561
43021
  }
42562
43022
  async function runSecretscan(directory) {
42563
43023
  try {
42564
- const result = await secretscan.execute({ directory }, {});
43024
+ const result = await _internals16.secretscan.execute({ directory }, {});
42565
43025
  const jsonStr = typeof result === "string" ? result : result.output;
42566
43026
  return JSON.parse(jsonStr);
42567
43027
  } catch (e) {
@@ -42576,7 +43036,7 @@ async function runSecretscan(directory) {
42576
43036
  return errorResult;
42577
43037
  }
42578
43038
  }
42579
- var MAX_FILE_PATH_LENGTH = 500, MAX_FILE_SIZE_BYTES, MAX_FILES_SCANNED = 1000, MAX_FINDINGS = 100, MAX_OUTPUT_BYTES2 = 512000, MAX_LINE_LENGTH = 1e4, MAX_CONTENT_BYTES, BINARY_SIGNATURES, BINARY_PREFIX_BYTES = 4, BINARY_NULL_CHECK_BYTES = 8192, BINARY_NULL_THRESHOLD = 0.1, DEFAULT_EXCLUDE_DIRS, DEFAULT_EXCLUDE_EXTENSIONS, SECRET_PATTERNS, O_NOFOLLOW, secretscan;
43039
+ var MAX_FILE_PATH_LENGTH = 500, MAX_FILE_SIZE_BYTES, MAX_FILES_SCANNED = 1000, MAX_FINDINGS = 100, MAX_OUTPUT_BYTES2 = 512000, MAX_LINE_LENGTH = 1e4, MAX_CONTENT_BYTES, BINARY_SIGNATURES, BINARY_PREFIX_BYTES = 4, BINARY_NULL_CHECK_BYTES = 8192, BINARY_NULL_THRESHOLD = 0.1, DEFAULT_EXCLUDE_DIRS, DEFAULT_EXCLUDE_EXTENSIONS, SECRET_PATTERNS, O_NOFOLLOW, secretscan, _internals16;
42580
43040
  var init_secretscan = __esm(() => {
42581
43041
  init_zod();
42582
43042
  init_path_security();
@@ -42809,7 +43269,7 @@ var init_secretscan = __esm(() => {
42809
43269
  }
42810
43270
  }
42811
43271
  try {
42812
- const _scanDirRaw = path25.resolve(directory);
43272
+ const _scanDirRaw = path26.resolve(directory);
42813
43273
  const scanDir = (() => {
42814
43274
  try {
42815
43275
  return fs12.realpathSync(_scanDirRaw);
@@ -42948,11 +43408,15 @@ var init_secretscan = __esm(() => {
42948
43408
  }
42949
43409
  }
42950
43410
  });
43411
+ _internals16 = {
43412
+ secretscan,
43413
+ runSecretscan
43414
+ };
42951
43415
  });
42952
43416
 
42953
43417
  // src/test-impact/analyzer.ts
42954
43418
  import fs13 from "fs";
42955
- import path26 from "path";
43419
+ import path27 from "path";
42956
43420
  function normalizePath(p) {
42957
43421
  return p.replace(/\\/g, "/");
42958
43422
  }
@@ -42973,8 +43437,8 @@ function resolveRelativeImport(fromDir, importPath) {
42973
43437
  if (!importPath.startsWith(".")) {
42974
43438
  return null;
42975
43439
  }
42976
- const resolved = path26.resolve(fromDir, importPath);
42977
- if (path26.extname(resolved)) {
43440
+ const resolved = path27.resolve(fromDir, importPath);
43441
+ if (path27.extname(resolved)) {
42978
43442
  if (fs13.existsSync(resolved) && fs13.statSync(resolved).isFile()) {
42979
43443
  return normalizePath(resolved);
42980
43444
  }
@@ -43019,12 +43483,12 @@ function findTestFilesSync(cwd) {
43019
43483
  for (const entry of entries) {
43020
43484
  if (entry.isDirectory()) {
43021
43485
  if (!skipDirs.has(entry.name)) {
43022
- walk(path26.join(dir, entry.name), visitedInodes);
43486
+ walk(path27.join(dir, entry.name), visitedInodes);
43023
43487
  }
43024
43488
  } else if (entry.isFile()) {
43025
43489
  const name = entry.name;
43026
43490
  if (/\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name)) {
43027
- testFiles.push(normalizePath(path26.join(dir, entry.name)));
43491
+ testFiles.push(normalizePath(path27.join(dir, entry.name)));
43028
43492
  }
43029
43493
  }
43030
43494
  }
@@ -43062,7 +43526,7 @@ async function buildImpactMapInternal(cwd) {
43062
43526
  continue;
43063
43527
  }
43064
43528
  const imports = extractImports(content);
43065
- const testDir = path26.dirname(testFile);
43529
+ const testDir = path27.dirname(testFile);
43066
43530
  for (const importPath of imports) {
43067
43531
  const resolvedSource = resolveRelativeImport(testDir, importPath);
43068
43532
  if (resolvedSource === null) {
@@ -43079,28 +43543,28 @@ async function buildImpactMapInternal(cwd) {
43079
43543
  return impactMap;
43080
43544
  }
43081
43545
  async function buildImpactMap(cwd) {
43082
- const impactMap = await buildImpactMapInternal(cwd);
43083
- await saveImpactMap(cwd, impactMap);
43546
+ const impactMap = await _internals17.buildImpactMapInternal(cwd);
43547
+ await _internals17.saveImpactMap(cwd, impactMap);
43084
43548
  return impactMap;
43085
43549
  }
43086
43550
  async function loadImpactMap(cwd) {
43087
- const cachePath = path26.join(cwd, ".swarm", "cache", "impact-map.json");
43551
+ const cachePath = path27.join(cwd, ".swarm", "cache", "impact-map.json");
43088
43552
  if (fs13.existsSync(cachePath)) {
43089
43553
  try {
43090
43554
  const content = fs13.readFileSync(cachePath, "utf-8");
43091
43555
  const data = JSON.parse(content);
43092
43556
  const map3 = data.map;
43093
43557
  const generatedAt = new Date(data.generatedAt).getTime();
43094
- if (!isCacheStale(map3, generatedAt)) {
43558
+ if (!_internals17.isCacheStale(map3, generatedAt)) {
43095
43559
  return map3;
43096
43560
  }
43097
43561
  } catch {}
43098
43562
  }
43099
- return buildImpactMap(cwd);
43563
+ return _internals17.buildImpactMap(cwd);
43100
43564
  }
43101
43565
  async function saveImpactMap(cwd, impactMap) {
43102
- const cacheDir2 = path26.join(cwd, ".swarm", "cache");
43103
- const cachePath = path26.join(cacheDir2, "impact-map.json");
43566
+ const cacheDir2 = path27.join(cwd, ".swarm", "cache");
43567
+ const cachePath = path27.join(cacheDir2, "impact-map.json");
43104
43568
  if (!fs13.existsSync(cacheDir2)) {
43105
43569
  fs13.mkdirSync(cacheDir2, { recursive: true });
43106
43570
  }
@@ -43122,11 +43586,11 @@ async function analyzeImpact(changedFiles, cwd) {
43122
43586
  };
43123
43587
  }
43124
43588
  const validFiles = changedFiles.filter((f) => typeof f === "string" && f.length > 0 && !f.includes("\x00"));
43125
- const impactMap = await loadImpactMap(cwd);
43589
+ const impactMap = await _internals17.loadImpactMap(cwd);
43126
43590
  const impactedTestsSet = new Set;
43127
43591
  const untestedFiles = [];
43128
43592
  for (const changedFile of validFiles) {
43129
- const normalizedChanged = normalizePath(path26.resolve(changedFile));
43593
+ const normalizedChanged = normalizePath(path27.resolve(changedFile));
43130
43594
  const tests = impactMap[normalizedChanged];
43131
43595
  if (tests && tests.length > 0) {
43132
43596
  for (const test of tests) {
@@ -43163,12 +43627,24 @@ async function analyzeImpact(changedFiles, cwd) {
43163
43627
  impactMap
43164
43628
  };
43165
43629
  }
43166
- var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, EXTENSIONS_TO_TRY;
43630
+ var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, EXTENSIONS_TO_TRY, _internals17;
43167
43631
  var init_analyzer = __esm(() => {
43168
43632
  IMPORT_REGEX_ES = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
43169
43633
  IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
43170
43634
  IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
43171
43635
  EXTENSIONS_TO_TRY = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
43636
+ _internals17 = {
43637
+ normalizePath,
43638
+ isCacheStale,
43639
+ resolveRelativeImport,
43640
+ findTestFilesSync,
43641
+ extractImports,
43642
+ buildImpactMapInternal,
43643
+ buildImpactMap,
43644
+ loadImpactMap,
43645
+ saveImpactMap,
43646
+ analyzeImpact
43647
+ };
43172
43648
  });
43173
43649
 
43174
43650
  // src/test-impact/failure-classifier.ts
@@ -43378,9 +43854,9 @@ var FLAKY_THRESHOLD = 0.3, MIN_RUNS_FOR_QUARANTINE = 5, MAX_HISTORY_RUNS = 20;
43378
43854
 
43379
43855
  // src/test-impact/history-store.ts
43380
43856
  import fs14 from "fs";
43381
- import path27 from "path";
43857
+ import path28 from "path";
43382
43858
  function getHistoryPath(workingDir) {
43383
- return path27.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
43859
+ return path28.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
43384
43860
  }
43385
43861
  function sanitizeErrorMessage(errorMessage) {
43386
43862
  if (errorMessage === undefined) {
@@ -43435,7 +43911,7 @@ function appendTestRun(record3, workingDir) {
43435
43911
  changedFiles: sanitizeChangedFiles(record3.changedFiles || [])
43436
43912
  };
43437
43913
  const historyPath = getHistoryPath(workingDir);
43438
- const historyDir = path27.dirname(historyPath);
43914
+ const historyDir = path28.dirname(historyPath);
43439
43915
  if (!fs14.existsSync(historyDir)) {
43440
43916
  fs14.mkdirSync(historyDir, { recursive: true });
43441
43917
  }
@@ -43517,7 +43993,7 @@ var init_history_store = __esm(() => {
43517
43993
 
43518
43994
  // src/tools/resolve-working-directory.ts
43519
43995
  import * as fs15 from "fs";
43520
- import * as path28 from "path";
43996
+ import * as path29 from "path";
43521
43997
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
43522
43998
  if (workingDirectory == null || workingDirectory === "") {
43523
43999
  return { success: true, directory: fallbackDirectory };
@@ -43537,15 +44013,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
43537
44013
  };
43538
44014
  }
43539
44015
  }
43540
- const normalizedDir = path28.normalize(workingDirectory);
43541
- const pathParts = normalizedDir.split(path28.sep);
44016
+ const normalizedDir = path29.normalize(workingDirectory);
44017
+ const pathParts = normalizedDir.split(path29.sep);
43542
44018
  if (pathParts.includes("..")) {
43543
44019
  return {
43544
44020
  success: false,
43545
44021
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
43546
44022
  };
43547
44023
  }
43548
- const resolvedDir = path28.resolve(normalizedDir);
44024
+ const resolvedDir = path29.resolve(normalizedDir);
43549
44025
  let statResult;
43550
44026
  try {
43551
44027
  statResult = fs15.statSync(resolvedDir);
@@ -43561,7 +44037,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
43561
44037
  message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
43562
44038
  };
43563
44039
  }
43564
- const resolvedFallback = path28.resolve(fallbackDirectory);
44040
+ const resolvedFallback = path29.resolve(fallbackDirectory);
43565
44041
  let fallbackExists = false;
43566
44042
  try {
43567
44043
  fs15.statSync(resolvedFallback);
@@ -43571,7 +44047,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
43571
44047
  }
43572
44048
  if (workingDirectory != null && workingDirectory !== "") {
43573
44049
  if (fallbackExists) {
43574
- const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path28.sep);
44050
+ const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path29.sep);
43575
44051
  if (isSubdirectory) {
43576
44052
  return {
43577
44053
  success: false,
@@ -43593,7 +44069,7 @@ var init_resolve_working_directory = () => {};
43593
44069
 
43594
44070
  // src/tools/test-runner.ts
43595
44071
  import * as fs16 from "fs";
43596
- import * as path29 from "path";
44072
+ import * as path30 from "path";
43597
44073
  function isAbsolutePath(str) {
43598
44074
  if (str.startsWith("/"))
43599
44075
  return true;
@@ -43658,14 +44134,14 @@ function hasDevDependency(devDeps, ...patterns) {
43658
44134
  return hasPackageJsonDependency(devDeps, ...patterns);
43659
44135
  }
43660
44136
  function detectGoTest(cwd) {
43661
- return fs16.existsSync(path29.join(cwd, "go.mod")) && isCommandAvailable("go");
44137
+ return fs16.existsSync(path30.join(cwd, "go.mod")) && isCommandAvailable("go");
43662
44138
  }
43663
44139
  function detectJavaMaven(cwd) {
43664
- return fs16.existsSync(path29.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
44140
+ return fs16.existsSync(path30.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
43665
44141
  }
43666
44142
  function detectGradle(cwd) {
43667
- const hasBuildFile = fs16.existsSync(path29.join(cwd, "build.gradle")) || fs16.existsSync(path29.join(cwd, "build.gradle.kts"));
43668
- const hasGradlew = fs16.existsSync(path29.join(cwd, "gradlew")) || fs16.existsSync(path29.join(cwd, "gradlew.bat"));
44143
+ const hasBuildFile = fs16.existsSync(path30.join(cwd, "build.gradle")) || fs16.existsSync(path30.join(cwd, "build.gradle.kts"));
44144
+ const hasGradlew = fs16.existsSync(path30.join(cwd, "gradlew")) || fs16.existsSync(path30.join(cwd, "gradlew.bat"));
43669
44145
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
43670
44146
  }
43671
44147
  function detectDotnetTest(cwd) {
@@ -43678,30 +44154,30 @@ function detectDotnetTest(cwd) {
43678
44154
  }
43679
44155
  }
43680
44156
  function detectCTest(cwd) {
43681
- const hasSource = fs16.existsSync(path29.join(cwd, "CMakeLists.txt"));
43682
- const hasBuildCache = fs16.existsSync(path29.join(cwd, "CMakeCache.txt")) || fs16.existsSync(path29.join(cwd, "build", "CMakeCache.txt"));
44157
+ const hasSource = fs16.existsSync(path30.join(cwd, "CMakeLists.txt"));
44158
+ const hasBuildCache = fs16.existsSync(path30.join(cwd, "CMakeCache.txt")) || fs16.existsSync(path30.join(cwd, "build", "CMakeCache.txt"));
43683
44159
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
43684
44160
  }
43685
44161
  function detectSwiftTest(cwd) {
43686
- return fs16.existsSync(path29.join(cwd, "Package.swift")) && isCommandAvailable("swift");
44162
+ return fs16.existsSync(path30.join(cwd, "Package.swift")) && isCommandAvailable("swift");
43687
44163
  }
43688
44164
  function detectDartTest(cwd) {
43689
- return fs16.existsSync(path29.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
44165
+ return fs16.existsSync(path30.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
43690
44166
  }
43691
44167
  function detectRSpec(cwd) {
43692
- const hasRSpecFile = fs16.existsSync(path29.join(cwd, ".rspec"));
43693
- const hasGemfile = fs16.existsSync(path29.join(cwd, "Gemfile"));
43694
- const hasSpecDir = fs16.existsSync(path29.join(cwd, "spec"));
44168
+ const hasRSpecFile = fs16.existsSync(path30.join(cwd, ".rspec"));
44169
+ const hasGemfile = fs16.existsSync(path30.join(cwd, "Gemfile"));
44170
+ const hasSpecDir = fs16.existsSync(path30.join(cwd, "spec"));
43695
44171
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
43696
44172
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
43697
44173
  }
43698
44174
  function detectMinitest(cwd) {
43699
- return fs16.existsSync(path29.join(cwd, "test")) && (fs16.existsSync(path29.join(cwd, "Gemfile")) || fs16.existsSync(path29.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
44175
+ return fs16.existsSync(path30.join(cwd, "test")) && (fs16.existsSync(path30.join(cwd, "Gemfile")) || fs16.existsSync(path30.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
43700
44176
  }
43701
44177
  async function detectTestFramework(cwd) {
43702
44178
  const baseDir = cwd;
43703
44179
  try {
43704
- const packageJsonPath = path29.join(baseDir, "package.json");
44180
+ const packageJsonPath = path30.join(baseDir, "package.json");
43705
44181
  if (fs16.existsSync(packageJsonPath)) {
43706
44182
  const content = fs16.readFileSync(packageJsonPath, "utf-8");
43707
44183
  const pkg = JSON.parse(content);
@@ -43722,16 +44198,16 @@ async function detectTestFramework(cwd) {
43722
44198
  return "jest";
43723
44199
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
43724
44200
  return "mocha";
43725
- if (fs16.existsSync(path29.join(baseDir, "bun.lockb")) || fs16.existsSync(path29.join(baseDir, "bun.lock"))) {
44201
+ if (fs16.existsSync(path30.join(baseDir, "bun.lockb")) || fs16.existsSync(path30.join(baseDir, "bun.lock"))) {
43726
44202
  if (scripts.test?.includes("bun"))
43727
44203
  return "bun";
43728
44204
  }
43729
44205
  }
43730
44206
  } catch {}
43731
44207
  try {
43732
- const pyprojectTomlPath = path29.join(baseDir, "pyproject.toml");
43733
- const setupCfgPath = path29.join(baseDir, "setup.cfg");
43734
- const requirementsTxtPath = path29.join(baseDir, "requirements.txt");
44208
+ const pyprojectTomlPath = path30.join(baseDir, "pyproject.toml");
44209
+ const setupCfgPath = path30.join(baseDir, "setup.cfg");
44210
+ const requirementsTxtPath = path30.join(baseDir, "requirements.txt");
43735
44211
  if (fs16.existsSync(pyprojectTomlPath)) {
43736
44212
  const content = fs16.readFileSync(pyprojectTomlPath, "utf-8");
43737
44213
  if (content.includes("[tool.pytest"))
@@ -43751,7 +44227,7 @@ async function detectTestFramework(cwd) {
43751
44227
  }
43752
44228
  } catch {}
43753
44229
  try {
43754
- const cargoTomlPath = path29.join(baseDir, "Cargo.toml");
44230
+ const cargoTomlPath = path30.join(baseDir, "Cargo.toml");
43755
44231
  if (fs16.existsSync(cargoTomlPath)) {
43756
44232
  const content = fs16.readFileSync(cargoTomlPath, "utf-8");
43757
44233
  if (content.includes("[dev-dependencies]")) {
@@ -43762,9 +44238,9 @@ async function detectTestFramework(cwd) {
43762
44238
  }
43763
44239
  } catch {}
43764
44240
  try {
43765
- const pesterConfigPath = path29.join(baseDir, "pester.config.ps1");
43766
- const pesterConfigJsonPath = path29.join(baseDir, "pester.config.ps1.json");
43767
- const pesterPs1Path = path29.join(baseDir, "tests.ps1");
44241
+ const pesterConfigPath = path30.join(baseDir, "pester.config.ps1");
44242
+ const pesterConfigJsonPath = path30.join(baseDir, "pester.config.ps1.json");
44243
+ const pesterPs1Path = path30.join(baseDir, "tests.ps1");
43768
44244
  if (fs16.existsSync(pesterConfigPath) || fs16.existsSync(pesterConfigJsonPath) || fs16.existsSync(pesterPs1Path)) {
43769
44245
  return "pester";
43770
44246
  }
@@ -43793,12 +44269,12 @@ function isTestDirectoryPath(normalizedPath) {
43793
44269
  return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
43794
44270
  }
43795
44271
  function resolveWorkspacePath(file3, workingDir) {
43796
- return path29.isAbsolute(file3) ? path29.resolve(file3) : path29.resolve(workingDir, file3);
44272
+ return path30.isAbsolute(file3) ? path30.resolve(file3) : path30.resolve(workingDir, file3);
43797
44273
  }
43798
44274
  function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
43799
44275
  if (!preferRelative)
43800
44276
  return absolutePath;
43801
- return path29.relative(workingDir, absolutePath);
44277
+ return path30.relative(workingDir, absolutePath);
43802
44278
  }
43803
44279
  function dedupePush(target, value) {
43804
44280
  if (!target.includes(value)) {
@@ -43835,18 +44311,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
43835
44311
  }
43836
44312
  }
43837
44313
  function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
43838
- const relativeDir = path29.dirname(relativePath);
44314
+ const relativeDir = path30.dirname(relativePath);
43839
44315
  const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
43840
44316
  const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
43841
- const rootDir = path29.join(workingDir, dirName);
43842
- return nestedRelativeDir ? [rootDir, path29.join(rootDir, nestedRelativeDir)] : [rootDir];
44317
+ const rootDir = path30.join(workingDir, dirName);
44318
+ return nestedRelativeDir ? [rootDir, path30.join(rootDir, nestedRelativeDir)] : [rootDir];
43843
44319
  });
43844
44320
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
43845
44321
  if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
43846
- directories.push(path29.join(workingDir, "src/test/java", path29.dirname(normalizedRelativePath.slice("src/main/java/".length))));
44322
+ directories.push(path30.join(workingDir, "src/test/java", path30.dirname(normalizedRelativePath.slice("src/main/java/".length))));
43847
44323
  }
43848
44324
  if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
43849
- directories.push(path29.join(workingDir, "src/test/kotlin", path29.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
44325
+ directories.push(path30.join(workingDir, "src/test/kotlin", path30.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
43850
44326
  }
43851
44327
  return [...new Set(directories)];
43852
44328
  }
@@ -43874,23 +44350,23 @@ function isLanguageSpecificTestFile(basename5) {
43874
44350
  }
43875
44351
  function isConventionTestFilePath(filePath) {
43876
44352
  const normalizedPath = filePath.replace(/\\/g, "/");
43877
- const basename5 = path29.basename(filePath);
44353
+ const basename5 = path30.basename(filePath);
43878
44354
  return hasCompoundTestExtension(basename5) || basename5.includes(".spec.") || basename5.includes(".test.") || isLanguageSpecificTestFile(basename5) || isTestDirectoryPath(normalizedPath);
43879
44355
  }
43880
44356
  function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
43881
44357
  const testFiles = [];
43882
44358
  for (const file3 of sourceFiles) {
43883
44359
  const absoluteFile = resolveWorkspacePath(file3, workingDir);
43884
- const relativeFile = path29.relative(workingDir, absoluteFile);
43885
- const basename5 = path29.basename(absoluteFile);
43886
- const dirname12 = path29.dirname(absoluteFile);
43887
- const preferRelativeOutput = !path29.isAbsolute(file3);
44360
+ const relativeFile = path30.relative(workingDir, absoluteFile);
44361
+ const basename5 = path30.basename(absoluteFile);
44362
+ const dirname13 = path30.dirname(absoluteFile);
44363
+ const preferRelativeOutput = !path30.isAbsolute(file3);
43888
44364
  if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
43889
44365
  dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
43890
44366
  continue;
43891
44367
  }
43892
44368
  const nameWithoutExt = basename5.replace(/\.[^.]+$/, "");
43893
- const ext = path29.extname(basename5);
44369
+ const ext = path30.extname(basename5);
43894
44370
  const genericTestNames = [
43895
44371
  `${nameWithoutExt}.spec${ext}`,
43896
44372
  `${nameWithoutExt}.test${ext}`
@@ -43899,7 +44375,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
43899
44375
  const colocatedCandidates = [
43900
44376
  ...genericTestNames,
43901
44377
  ...languageSpecificTestNames
43902
- ].map((candidateName) => path29.join(dirname12, candidateName));
44378
+ ].map((candidateName) => path30.join(dirname13, candidateName));
43903
44379
  const testDirectoryNames = [
43904
44380
  basename5,
43905
44381
  ...genericTestNames,
@@ -43908,8 +44384,8 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
43908
44384
  const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
43909
44385
  const possibleTestFiles = [
43910
44386
  ...colocatedCandidates,
43911
- ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path29.join(dirname12, dirName, candidateName))),
43912
- ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path29.join(candidateDir, candidateName)))
44387
+ ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path30.join(dirname13, dirName, candidateName))),
44388
+ ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path30.join(candidateDir, candidateName)))
43913
44389
  ];
43914
44390
  for (const testFile of possibleTestFiles) {
43915
44391
  if (fs16.existsSync(testFile)) {
@@ -43930,7 +44406,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
43930
44406
  try {
43931
44407
  const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
43932
44408
  const content = fs16.readFileSync(absoluteTestFile, "utf-8");
43933
- const testDir = path29.dirname(absoluteTestFile);
44409
+ const testDir = path30.dirname(absoluteTestFile);
43934
44410
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
43935
44411
  let match;
43936
44412
  match = importRegex.exec(content);
@@ -43938,8 +44414,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
43938
44414
  const importPath = match[1];
43939
44415
  let resolvedImport;
43940
44416
  if (importPath.startsWith(".")) {
43941
- resolvedImport = path29.resolve(testDir, importPath);
43942
- const existingExt = path29.extname(resolvedImport);
44417
+ resolvedImport = path30.resolve(testDir, importPath);
44418
+ const existingExt = path30.extname(resolvedImport);
43943
44419
  if (!existingExt) {
43944
44420
  for (const extToTry of [
43945
44421
  ".ts",
@@ -43959,12 +44435,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
43959
44435
  } else {
43960
44436
  continue;
43961
44437
  }
43962
- const importBasename = path29.basename(resolvedImport, path29.extname(resolvedImport));
43963
- const importDir = path29.dirname(resolvedImport);
44438
+ const importBasename = path30.basename(resolvedImport, path30.extname(resolvedImport));
44439
+ const importDir = path30.dirname(resolvedImport);
43964
44440
  for (const sourceFile of absoluteSourceFiles) {
43965
- const sourceDir = path29.dirname(sourceFile);
43966
- const sourceBasename = path29.basename(sourceFile, path29.extname(sourceFile));
43967
- const isRelatedDir = importDir === sourceDir || importDir === path29.join(sourceDir, "__tests__") || importDir === path29.join(sourceDir, "tests") || importDir === path29.join(sourceDir, "test") || importDir === path29.join(sourceDir, "spec");
44441
+ const sourceDir = path30.dirname(sourceFile);
44442
+ const sourceBasename = path30.basename(sourceFile, path30.extname(sourceFile));
44443
+ const isRelatedDir = importDir === sourceDir || importDir === path30.join(sourceDir, "__tests__") || importDir === path30.join(sourceDir, "tests") || importDir === path30.join(sourceDir, "test") || importDir === path30.join(sourceDir, "spec");
43968
44444
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
43969
44445
  dedupePush(testFiles, testFile);
43970
44446
  break;
@@ -43977,8 +44453,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
43977
44453
  while (match !== null) {
43978
44454
  const importPath = match[1];
43979
44455
  if (importPath.startsWith(".")) {
43980
- let resolvedImport = path29.resolve(testDir, importPath);
43981
- const existingExt = path29.extname(resolvedImport);
44456
+ let resolvedImport = path30.resolve(testDir, importPath);
44457
+ const existingExt = path30.extname(resolvedImport);
43982
44458
  if (!existingExt) {
43983
44459
  for (const extToTry of [
43984
44460
  ".ts",
@@ -43995,12 +44471,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
43995
44471
  }
43996
44472
  }
43997
44473
  }
43998
- const importDir = path29.dirname(resolvedImport);
43999
- const importBasename = path29.basename(resolvedImport, path29.extname(resolvedImport));
44474
+ const importDir = path30.dirname(resolvedImport);
44475
+ const importBasename = path30.basename(resolvedImport, path30.extname(resolvedImport));
44000
44476
  for (const sourceFile of absoluteSourceFiles) {
44001
- const sourceDir = path29.dirname(sourceFile);
44002
- const sourceBasename = path29.basename(sourceFile, path29.extname(sourceFile));
44003
- const isRelatedDir = importDir === sourceDir || importDir === path29.join(sourceDir, "__tests__") || importDir === path29.join(sourceDir, "tests") || importDir === path29.join(sourceDir, "test") || importDir === path29.join(sourceDir, "spec");
44477
+ const sourceDir = path30.dirname(sourceFile);
44478
+ const sourceBasename = path30.basename(sourceFile, path30.extname(sourceFile));
44479
+ const isRelatedDir = importDir === sourceDir || importDir === path30.join(sourceDir, "__tests__") || importDir === path30.join(sourceDir, "tests") || importDir === path30.join(sourceDir, "test") || importDir === path30.join(sourceDir, "spec");
44004
44480
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
44005
44481
  dedupePush(testFiles, testFile);
44006
44482
  break;
@@ -44103,8 +44579,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
44103
44579
  return ["mvn", "test"];
44104
44580
  case "gradle": {
44105
44581
  const isWindows = process.platform === "win32";
44106
- const hasGradlewBat = fs16.existsSync(path29.join(baseDir, "gradlew.bat"));
44107
- const hasGradlew = fs16.existsSync(path29.join(baseDir, "gradlew"));
44582
+ const hasGradlewBat = fs16.existsSync(path30.join(baseDir, "gradlew.bat"));
44583
+ const hasGradlew = fs16.existsSync(path30.join(baseDir, "gradlew"));
44108
44584
  if (hasGradlewBat && isWindows)
44109
44585
  return ["gradlew.bat", "test"];
44110
44586
  if (hasGradlew)
@@ -44121,7 +44597,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
44121
44597
  "cmake-build-release",
44122
44598
  "out"
44123
44599
  ];
44124
- const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(path29.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
44600
+ const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(path30.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
44125
44601
  return ["ctest", "--test-dir", actualBuildDir];
44126
44602
  }
44127
44603
  case "swift-test":
@@ -44774,7 +45250,7 @@ var init_test_runner = __esm(() => {
44774
45250
  const sourceFiles = args.files.filter((file3) => {
44775
45251
  if (directTestFiles.includes(file3))
44776
45252
  return false;
44777
- const ext = path29.extname(file3).toLowerCase();
45253
+ const ext = path30.extname(file3).toLowerCase();
44778
45254
  return SOURCE_EXTENSIONS.has(ext);
44779
45255
  });
44780
45256
  const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
@@ -44809,7 +45285,7 @@ var init_test_runner = __esm(() => {
44809
45285
  if (isConventionTestFilePath(f)) {
44810
45286
  return false;
44811
45287
  }
44812
- const ext = path29.extname(f).toLowerCase();
45288
+ const ext = path30.extname(f).toLowerCase();
44813
45289
  return SOURCE_EXTENSIONS.has(ext);
44814
45290
  });
44815
45291
  if (sourceFiles.length === 0) {
@@ -44836,7 +45312,7 @@ var init_test_runner = __esm(() => {
44836
45312
  if (isConventionTestFilePath(f)) {
44837
45313
  return false;
44838
45314
  }
44839
- const ext = path29.extname(f).toLowerCase();
45315
+ const ext = path30.extname(f).toLowerCase();
44840
45316
  return SOURCE_EXTENSIONS.has(ext);
44841
45317
  });
44842
45318
  if (sourceFiles.length === 0) {
@@ -44854,8 +45330,8 @@ var init_test_runner = __esm(() => {
44854
45330
  const impactResult = await analyzeImpact(sourceFiles, workingDir);
44855
45331
  if (impactResult.impactedTests.length > 0) {
44856
45332
  testFiles = impactResult.impactedTests.map((absPath) => {
44857
- const relativePath = path29.relative(workingDir, absPath);
44858
- return path29.isAbsolute(relativePath) ? absPath : relativePath;
45333
+ const relativePath = path30.relative(workingDir, absPath);
45334
+ return path30.isAbsolute(relativePath) ? absPath : relativePath;
44859
45335
  });
44860
45336
  } else {
44861
45337
  graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
@@ -44931,7 +45407,7 @@ var init_test_runner = __esm(() => {
44931
45407
 
44932
45408
  // src/services/preflight-service.ts
44933
45409
  import * as fs17 from "fs";
44934
- import * as path30 from "path";
45410
+ import * as path31 from "path";
44935
45411
  function validateDirectoryPath(dir) {
44936
45412
  if (!dir || typeof dir !== "string") {
44937
45413
  throw new Error("Directory path is required");
@@ -44939,8 +45415,8 @@ function validateDirectoryPath(dir) {
44939
45415
  if (dir.includes("..")) {
44940
45416
  throw new Error("Directory path must not contain path traversal sequences");
44941
45417
  }
44942
- const normalized = path30.normalize(dir);
44943
- const absolutePath = path30.isAbsolute(normalized) ? normalized : path30.resolve(normalized);
45418
+ const normalized = path31.normalize(dir);
45419
+ const absolutePath = path31.isAbsolute(normalized) ? normalized : path31.resolve(normalized);
44944
45420
  return absolutePath;
44945
45421
  }
44946
45422
  function validateTimeout(timeoutMs, defaultValue) {
@@ -44963,7 +45439,7 @@ function validateTimeout(timeoutMs, defaultValue) {
44963
45439
  }
44964
45440
  function getPackageVersion(dir) {
44965
45441
  try {
44966
- const packagePath = path30.join(dir, "package.json");
45442
+ const packagePath = path31.join(dir, "package.json");
44967
45443
  if (fs17.existsSync(packagePath)) {
44968
45444
  const content = fs17.readFileSync(packagePath, "utf-8");
44969
45445
  const pkg = JSON.parse(content);
@@ -44974,7 +45450,7 @@ function getPackageVersion(dir) {
44974
45450
  }
44975
45451
  function getChangelogVersion(dir) {
44976
45452
  try {
44977
- const changelogPath = path30.join(dir, "CHANGELOG.md");
45453
+ const changelogPath = path31.join(dir, "CHANGELOG.md");
44978
45454
  if (fs17.existsSync(changelogPath)) {
44979
45455
  const content = fs17.readFileSync(changelogPath, "utf-8");
44980
45456
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
@@ -44988,7 +45464,7 @@ function getChangelogVersion(dir) {
44988
45464
  function getVersionFileVersion(dir) {
44989
45465
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
44990
45466
  for (const file3 of possibleFiles) {
44991
- const filePath = path30.join(dir, file3);
45467
+ const filePath = path31.join(dir, file3);
44992
45468
  if (fs17.existsSync(filePath)) {
44993
45469
  try {
44994
45470
  const content = fs17.readFileSync(filePath, "utf-8").trim();
@@ -45004,9 +45480,9 @@ function getVersionFileVersion(dir) {
45004
45480
  async function runVersionCheck(dir, _timeoutMs) {
45005
45481
  const startTime = Date.now();
45006
45482
  try {
45007
- const packageVersion = getPackageVersion(dir);
45008
- const changelogVersion = getChangelogVersion(dir);
45009
- const versionFileVersion = getVersionFileVersion(dir);
45483
+ const packageVersion = _internals18.getPackageVersion(dir);
45484
+ const changelogVersion = _internals18.getChangelogVersion(dir);
45485
+ const versionFileVersion = _internals18.getVersionFileVersion(dir);
45010
45486
  const versions3 = [];
45011
45487
  if (packageVersion)
45012
45488
  versions3.push(`package.json: ${packageVersion}`);
@@ -45315,7 +45791,7 @@ async function runEvidenceCheck(dir) {
45315
45791
  async function runRequirementCoverageCheck(dir, currentPhase) {
45316
45792
  const startTime = Date.now();
45317
45793
  try {
45318
- const specPath = path30.join(dir, ".swarm", "spec.md");
45794
+ const specPath = path31.join(dir, ".swarm", "spec.md");
45319
45795
  if (!fs17.existsSync(specPath)) {
45320
45796
  return {
45321
45797
  type: "req_coverage",
@@ -45356,7 +45832,7 @@ async function runPreflight(dir, phase, config3) {
45356
45832
  const reportId = `preflight-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
45357
45833
  let validatedDir;
45358
45834
  try {
45359
- validatedDir = validateDirectoryPath(dir);
45835
+ validatedDir = _internals18.validateDirectoryPath(dir);
45360
45836
  } catch (error93) {
45361
45837
  return {
45362
45838
  id: reportId,
@@ -45376,7 +45852,7 @@ async function runPreflight(dir, phase, config3) {
45376
45852
  }
45377
45853
  let validatedTimeout;
45378
45854
  try {
45379
- validatedTimeout = validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
45855
+ validatedTimeout = _internals18.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
45380
45856
  } catch (error93) {
45381
45857
  return {
45382
45858
  id: reportId,
@@ -45417,12 +45893,12 @@ async function runPreflight(dir, phase, config3) {
45417
45893
  });
45418
45894
  const checks5 = [];
45419
45895
  log("[Preflight] Running lint check...");
45420
- const lintResult = await runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
45896
+ const lintResult = await _internals18.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
45421
45897
  checks5.push(lintResult);
45422
45898
  log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`);
45423
45899
  if (!cfg.skipTests) {
45424
45900
  log("[Preflight] Running tests check...");
45425
- const testsResult = await runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
45901
+ const testsResult = await _internals18.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
45426
45902
  checks5.push(testsResult);
45427
45903
  log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`);
45428
45904
  } else {
@@ -45434,7 +45910,7 @@ async function runPreflight(dir, phase, config3) {
45434
45910
  }
45435
45911
  if (!cfg.skipSecrets) {
45436
45912
  log("[Preflight] Running secrets check...");
45437
- const secretsResult = await runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
45913
+ const secretsResult = await _internals18.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
45438
45914
  checks5.push(secretsResult);
45439
45915
  log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`);
45440
45916
  } else {
@@ -45446,7 +45922,7 @@ async function runPreflight(dir, phase, config3) {
45446
45922
  }
45447
45923
  if (!cfg.skipEvidence) {
45448
45924
  log("[Preflight] Running evidence check...");
45449
- const evidenceResult = await runEvidenceCheck(validatedDir);
45925
+ const evidenceResult = await _internals18.runEvidenceCheck(validatedDir);
45450
45926
  checks5.push(evidenceResult);
45451
45927
  log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`);
45452
45928
  } else {
@@ -45457,12 +45933,12 @@ async function runPreflight(dir, phase, config3) {
45457
45933
  });
45458
45934
  }
45459
45935
  log("[Preflight] Running requirement coverage check...");
45460
- const reqCoverageResult = await runRequirementCoverageCheck(validatedDir, phase);
45936
+ const reqCoverageResult = await _internals18.runRequirementCoverageCheck(validatedDir, phase);
45461
45937
  checks5.push(reqCoverageResult);
45462
45938
  log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`);
45463
45939
  if (!cfg.skipVersion) {
45464
45940
  log("[Preflight] Running version check...");
45465
- const versionResult = await runVersionCheck(validatedDir, cfg.checkTimeoutMs);
45941
+ const versionResult = await _internals18.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
45466
45942
  checks5.push(versionResult);
45467
45943
  log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`);
45468
45944
  } else {
@@ -45525,10 +46001,10 @@ function formatPreflightMarkdown(report) {
45525
46001
  async function handlePreflightCommand(directory, _args) {
45526
46002
  const plan = await loadPlan(directory);
45527
46003
  const phase = plan?.current_phase ?? 1;
45528
- const report = await runPreflight(directory, phase);
45529
- return formatPreflightMarkdown(report);
46004
+ const report = await _internals18.runPreflight(directory, phase);
46005
+ return _internals18.formatPreflightMarkdown(report);
45530
46006
  }
45531
- var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG;
46007
+ var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG, _internals18;
45532
46008
  var init_preflight_service = __esm(() => {
45533
46009
  init_manager2();
45534
46010
  init_manager();
@@ -45545,6 +46021,22 @@ var init_preflight_service = __esm(() => {
45545
46021
  testScope: "convention",
45546
46022
  linter: "biome"
45547
46023
  };
46024
+ _internals18 = {
46025
+ runPreflight,
46026
+ formatPreflightMarkdown,
46027
+ handlePreflightCommand,
46028
+ validateDirectoryPath,
46029
+ validateTimeout,
46030
+ getPackageVersion,
46031
+ getChangelogVersion,
46032
+ getVersionFileVersion,
46033
+ runVersionCheck,
46034
+ runLintCheck,
46035
+ runTestsCheck,
46036
+ runSecretsCheck,
46037
+ runEvidenceCheck,
46038
+ runRequirementCoverageCheck
46039
+ };
45548
46040
  });
45549
46041
 
45550
46042
  // src/commands/preflight.ts
@@ -46418,7 +46910,7 @@ var init_manager3 = __esm(() => {
46418
46910
 
46419
46911
  // src/commands/reset.ts
46420
46912
  import * as fs18 from "fs";
46421
- import * as path31 from "path";
46913
+ import * as path32 from "path";
46422
46914
  async function handleResetCommand(directory, args) {
46423
46915
  const hasConfirm = args.includes("--confirm");
46424
46916
  if (!hasConfirm) {
@@ -46458,7 +46950,7 @@ async function handleResetCommand(directory, args) {
46458
46950
  }
46459
46951
  for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
46460
46952
  try {
46461
- const rootPath = path31.join(directory, filename);
46953
+ const rootPath = path32.join(directory, filename);
46462
46954
  if (fs18.existsSync(rootPath)) {
46463
46955
  fs18.unlinkSync(rootPath);
46464
46956
  results.push(`- \u2705 Deleted ${filename} (root)`);
@@ -46498,7 +46990,7 @@ var init_reset = __esm(() => {
46498
46990
 
46499
46991
  // src/commands/reset-session.ts
46500
46992
  import * as fs19 from "fs";
46501
- import * as path32 from "path";
46993
+ import * as path33 from "path";
46502
46994
  async function handleResetSessionCommand(directory, _args) {
46503
46995
  const results = [];
46504
46996
  try {
@@ -46513,13 +47005,13 @@ async function handleResetSessionCommand(directory, _args) {
46513
47005
  results.push("\u274C Failed to delete state.json");
46514
47006
  }
46515
47007
  try {
46516
- const sessionDir = path32.dirname(validateSwarmPath(directory, "session/state.json"));
47008
+ const sessionDir = path33.dirname(validateSwarmPath(directory, "session/state.json"));
46517
47009
  if (fs19.existsSync(sessionDir)) {
46518
47010
  const files = fs19.readdirSync(sessionDir);
46519
47011
  const otherFiles = files.filter((f) => f !== "state.json");
46520
47012
  let deletedCount = 0;
46521
47013
  for (const file3 of otherFiles) {
46522
- const filePath = path32.join(sessionDir, file3);
47014
+ const filePath = path33.join(sessionDir, file3);
46523
47015
  if (fs19.lstatSync(filePath).isFile()) {
46524
47016
  fs19.unlinkSync(filePath);
46525
47017
  deletedCount++;
@@ -46551,7 +47043,7 @@ var init_reset_session = __esm(() => {
46551
47043
  });
46552
47044
 
46553
47045
  // src/summaries/manager.ts
46554
- import * as path33 from "path";
47046
+ import * as path34 from "path";
46555
47047
  function sanitizeSummaryId(id) {
46556
47048
  if (!id || id.length === 0) {
46557
47049
  throw new Error("Invalid summary ID: empty string");
@@ -46574,7 +47066,7 @@ function sanitizeSummaryId(id) {
46574
47066
  }
46575
47067
  async function loadFullOutput(directory, id) {
46576
47068
  const sanitizedId = sanitizeSummaryId(id);
46577
- const relativePath = path33.join("summaries", `${sanitizedId}.json`);
47069
+ const relativePath = path34.join("summaries", `${sanitizedId}.json`);
46578
47070
  validateSwarmPath(directory, relativePath);
46579
47071
  const content = await readSwarmFileAsync(directory, relativePath);
46580
47072
  if (content === null) {
@@ -46637,7 +47129,7 @@ var init_retrieve = __esm(() => {
46637
47129
 
46638
47130
  // src/commands/rollback.ts
46639
47131
  import * as fs20 from "fs";
46640
- import * as path34 from "path";
47132
+ import * as path35 from "path";
46641
47133
  async function handleRollbackCommand(directory, args) {
46642
47134
  const phaseArg = args[0];
46643
47135
  if (!phaseArg) {
@@ -46702,8 +47194,8 @@ async function handleRollbackCommand(directory, args) {
46702
47194
  if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
46703
47195
  continue;
46704
47196
  }
46705
- const src = path34.join(checkpointDir, file3);
46706
- const dest = path34.join(swarmDir, file3);
47197
+ const src = path35.join(checkpointDir, file3);
47198
+ const dest = path35.join(swarmDir, file3);
46707
47199
  try {
46708
47200
  fs20.cpSync(src, dest, { recursive: true, force: true });
46709
47201
  successes.push(file3);
@@ -46722,12 +47214,12 @@ async function handleRollbackCommand(directory, args) {
46722
47214
  ].join(`
46723
47215
  `);
46724
47216
  }
46725
- const existingLedgerPath = path34.join(swarmDir, "plan-ledger.jsonl");
47217
+ const existingLedgerPath = path35.join(swarmDir, "plan-ledger.jsonl");
46726
47218
  if (fs20.existsSync(existingLedgerPath)) {
46727
47219
  fs20.unlinkSync(existingLedgerPath);
46728
47220
  }
46729
47221
  try {
46730
- const planJsonPath = path34.join(swarmDir, "plan.json");
47222
+ const planJsonPath = path35.join(swarmDir, "plan.json");
46731
47223
  if (fs20.existsSync(planJsonPath)) {
46732
47224
  const planRaw = fs20.readFileSync(planJsonPath, "utf-8");
46733
47225
  const plan = PlanSchema.parse(JSON.parse(planRaw));
@@ -46805,9 +47297,9 @@ async function handleSimulateCommand(directory, args) {
46805
47297
  const report = reportLines.filter(Boolean).join(`
46806
47298
  `);
46807
47299
  const fs21 = await import("fs/promises");
46808
- const path35 = await import("path");
46809
- const reportPath = path35.join(directory, ".swarm", "simulate-report.md");
46810
- await fs21.mkdir(path35.dirname(reportPath), { recursive: true });
47300
+ const path36 = await import("path");
47301
+ const reportPath = path36.join(directory, ".swarm", "simulate-report.md");
47302
+ await fs21.mkdir(path36.dirname(reportPath), { recursive: true });
46811
47303
  await fs21.writeFile(reportPath, report, "utf-8");
46812
47304
  return `${darkMatterPairs.length} hidden coupling pairs detected`;
46813
47305
  }
@@ -46982,6 +47474,7 @@ async function handleStatusCommand(directory, agents) {
46982
47474
  return formatStatusMarkdown(statusData);
46983
47475
  }
46984
47476
  var init_status_service = __esm(() => {
47477
+ init_extractors();
46985
47478
  init_utils2();
46986
47479
  init_manager();
46987
47480
  init_state();
@@ -47161,7 +47654,7 @@ __export(exports_commands, {
47161
47654
  COMMAND_REGISTRY: () => COMMAND_REGISTRY
47162
47655
  });
47163
47656
  import fs21 from "fs";
47164
- import path35 from "path";
47657
+ import path36 from "path";
47165
47658
  function buildHelpText() {
47166
47659
  const lines = ["## Swarm Commands", ""];
47167
47660
  const CATEGORIES = [
@@ -47270,9 +47763,9 @@ function createSwarmCommandHandler(directory, agents) {
47270
47763
  return;
47271
47764
  }
47272
47765
  let isFirstRun = false;
47273
- const sentinelPath = path35.join(directory, ".swarm", ".first-run-complete");
47766
+ const sentinelPath = path36.join(directory, ".swarm", ".first-run-complete");
47274
47767
  try {
47275
- const swarmDir = path35.join(directory, ".swarm");
47768
+ const swarmDir = path36.join(directory, ".swarm");
47276
47769
  fs21.mkdirSync(swarmDir, { recursive: true });
47277
47770
  fs21.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
47278
47771
  `, { flag: "wx" });
@@ -47387,7 +47880,7 @@ function findSimilarCommands(query) {
47387
47880
  return cmd.toLowerCase().includes(q) || q.includes(cmd.toLowerCase());
47388
47881
  }).map((cmd) => ({
47389
47882
  cmd,
47390
- score: cmd.length < q.length ? q.length - cmd.length : levenshteinDistance(q, cmd)
47883
+ score: cmd.length < q.length ? q.length - cmd.length : _internals19.levenshteinDistance(q, cmd)
47391
47884
  }));
47392
47885
  scored.sort((a, b) => a.score - b.score);
47393
47886
  return scored.slice(0, 3).map((s) => s.cmd);
@@ -47417,11 +47910,11 @@ async function handleHelpCommand(ctx) {
47417
47910
  return buildHelpText2();
47418
47911
  }
47419
47912
  const tokens = targetCommand.split(/\s+/);
47420
- const resolved = resolveCommand(tokens);
47913
+ const resolved = _internals19.resolveCommand(tokens);
47421
47914
  if (resolved) {
47422
- return buildDetailedHelp(resolved.key, resolved.entry);
47915
+ return _internals19.buildDetailedHelp(resolved.key, resolved.entry);
47423
47916
  }
47424
- const similar = findSimilarCommands(targetCommand);
47917
+ const similar = _internals19.findSimilarCommands(targetCommand);
47425
47918
  const { buildHelpText: fullHelp } = await Promise.resolve().then(() => (init_commands(), exports_commands));
47426
47919
  if (similar.length > 0) {
47427
47920
  return `Command '/swarm ${targetCommand}' not found.
@@ -47457,24 +47950,24 @@ function validateAliases() {
47457
47950
  }
47458
47951
  aliasTargets.get(target).push(name);
47459
47952
  const visited = new Set;
47460
- const path36 = [];
47953
+ const path37 = [];
47461
47954
  let current = target;
47462
47955
  while (current) {
47463
47956
  const currentEntry = COMMAND_REGISTRY[current];
47464
47957
  if (!currentEntry)
47465
47958
  break;
47466
47959
  if (visited.has(current)) {
47467
- const cycleStart = path36.indexOf(current);
47960
+ const cycleStart = path37.indexOf(current);
47468
47961
  const fullChain = [
47469
47962
  name,
47470
- ...path36.slice(0, cycleStart > 0 ? cycleStart : path36.length),
47963
+ ...path37.slice(0, cycleStart > 0 ? cycleStart : path37.length),
47471
47964
  current
47472
47965
  ].join(" \u2192 ");
47473
47966
  errors5.push(`Circular alias detected: ${fullChain}`);
47474
47967
  break;
47475
47968
  }
47476
47969
  visited.add(current);
47477
- path36.push(current);
47970
+ path37.push(current);
47478
47971
  current = currentEntry.aliasOf || "";
47479
47972
  }
47480
47973
  }
@@ -47515,7 +48008,7 @@ function resolveCommand(tokens) {
47515
48008
  }
47516
48009
  return null;
47517
48010
  }
47518
- var COMMAND_REGISTRY, VALID_COMMANDS, validation;
48011
+ var COMMAND_REGISTRY, VALID_COMMANDS, _internals19, validation;
47519
48012
  var init_registry = __esm(() => {
47520
48013
  init_acknowledge_spec_drift();
47521
48014
  init_agents();
@@ -47576,7 +48069,7 @@ var init_registry = __esm(() => {
47576
48069
  clashesWithNativeCcCommand: "/agents"
47577
48070
  },
47578
48071
  help: {
47579
- handler: (ctx) => handleHelpCommand(ctx),
48072
+ handler: (ctx) => _internals19.handleHelpCommand(ctx),
47580
48073
  description: "Show help for swarm commands",
47581
48074
  category: "core",
47582
48075
  args: "[command]",
@@ -47906,7 +48399,15 @@ var init_registry = __esm(() => {
47906
48399
  }
47907
48400
  };
47908
48401
  VALID_COMMANDS = Object.keys(COMMAND_REGISTRY);
47909
- validation = validateAliases();
48402
+ _internals19 = {
48403
+ handleHelpCommand,
48404
+ validateAliases,
48405
+ resolveCommand,
48406
+ levenshteinDistance,
48407
+ findSimilarCommands,
48408
+ buildDetailedHelp
48409
+ };
48410
+ validation = _internals19.validateAliases();
47910
48411
  if (!validation.valid) {
47911
48412
  throw new Error(`COMMAND_REGISTRY alias validation failed:
47912
48413
  ${validation.errors.join(`
@@ -47926,53 +48427,53 @@ init_cache_paths();
47926
48427
  init_constants();
47927
48428
  import * as fs22 from "fs";
47928
48429
  import * as os7 from "os";
47929
- import * as path36 from "path";
48430
+ import * as path37 from "path";
47930
48431
  var { version: version4 } = package_default;
47931
48432
  var CONFIG_DIR = getPluginConfigDir();
47932
- var OPENCODE_CONFIG_PATH = path36.join(CONFIG_DIR, "opencode.json");
47933
- var PLUGIN_CONFIG_PATH = path36.join(CONFIG_DIR, "opencode-swarm.json");
47934
- var PROMPTS_DIR = path36.join(CONFIG_DIR, "opencode-swarm");
48433
+ var OPENCODE_CONFIG_PATH = path37.join(CONFIG_DIR, "opencode.json");
48434
+ var PLUGIN_CONFIG_PATH = path37.join(CONFIG_DIR, "opencode-swarm.json");
48435
+ var PROMPTS_DIR = path37.join(CONFIG_DIR, "opencode-swarm");
47935
48436
  var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
47936
48437
  var OPENCODE_PLUGIN_LOCK_FILE_PATHS = getPluginLockFilePaths();
47937
48438
  function isSafeCachePath(p) {
47938
- const resolved = path36.resolve(p);
47939
- const home = path36.resolve(os7.homedir());
48439
+ const resolved = path37.resolve(p);
48440
+ const home = path37.resolve(os7.homedir());
47940
48441
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
47941
48442
  return false;
47942
48443
  }
47943
- const segments = resolved.split(path36.sep).filter((s) => s.length > 0);
48444
+ const segments = resolved.split(path37.sep).filter((s) => s.length > 0);
47944
48445
  if (segments.length < 4) {
47945
48446
  return false;
47946
48447
  }
47947
- const leaf = path36.basename(resolved);
48448
+ const leaf = path37.basename(resolved);
47948
48449
  if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
47949
48450
  return false;
47950
48451
  }
47951
- const parent = path36.basename(path36.dirname(resolved));
48452
+ const parent = path37.basename(path37.dirname(resolved));
47952
48453
  if (parent !== "packages" && parent !== "node_modules") {
47953
48454
  return false;
47954
48455
  }
47955
- const grandparent = path36.basename(path36.dirname(path36.dirname(resolved)));
48456
+ const grandparent = path37.basename(path37.dirname(path37.dirname(resolved)));
47956
48457
  if (grandparent !== "opencode") {
47957
48458
  return false;
47958
48459
  }
47959
48460
  return true;
47960
48461
  }
47961
48462
  function isSafeLockFilePath(p) {
47962
- const resolved = path36.resolve(p);
47963
- const home = path36.resolve(os7.homedir());
48463
+ const resolved = path37.resolve(p);
48464
+ const home = path37.resolve(os7.homedir());
47964
48465
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
47965
48466
  return false;
47966
48467
  }
47967
- const segments = resolved.split(path36.sep).filter((s) => s.length > 0);
48468
+ const segments = resolved.split(path37.sep).filter((s) => s.length > 0);
47968
48469
  if (segments.length < 4) {
47969
48470
  return false;
47970
48471
  }
47971
- const leaf = path36.basename(resolved);
48472
+ const leaf = path37.basename(resolved);
47972
48473
  if (leaf !== "bun.lock" && leaf !== "bun.lockb" && leaf !== "package-lock.json") {
47973
48474
  return false;
47974
48475
  }
47975
- const parent = path36.basename(path36.dirname(resolved));
48476
+ const parent = path37.basename(path37.dirname(resolved));
47976
48477
  if (parent !== "opencode") {
47977
48478
  return false;
47978
48479
  }
@@ -47998,8 +48499,8 @@ function saveJson(filepath, data) {
47998
48499
  }
47999
48500
  function writeProjectConfigIfMissing(cwd) {
48000
48501
  try {
48001
- const opencodeDir = path36.join(cwd, ".opencode");
48002
- const projectConfigPath = path36.join(opencodeDir, "opencode-swarm.json");
48502
+ const opencodeDir = path37.join(cwd, ".opencode");
48503
+ const projectConfigPath = path37.join(opencodeDir, "opencode-swarm.json");
48003
48504
  if (fs22.existsSync(projectConfigPath)) {
48004
48505
  return;
48005
48506
  }
@@ -48020,7 +48521,7 @@ async function install() {
48020
48521
  `);
48021
48522
  ensureDir(CONFIG_DIR);
48022
48523
  ensureDir(PROMPTS_DIR);
48023
- const LEGACY_CONFIG_PATH = path36.join(CONFIG_DIR, "config.json");
48524
+ const LEGACY_CONFIG_PATH = path37.join(CONFIG_DIR, "config.json");
48024
48525
  let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
48025
48526
  if (!opencodeConfig) {
48026
48527
  const legacyConfig = loadJson(LEGACY_CONFIG_PATH);