opencode-swarm 7.66.2 → 7.67.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -52,7 +52,7 @@ var package_default;
52
52
  var init_package = __esm(() => {
53
53
  package_default = {
54
54
  name: "opencode-swarm",
55
- version: "7.66.2",
55
+ version: "7.67.0",
56
56
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
57
57
  main: "dist/index.js",
58
58
  types: "dist/index.d.ts",
@@ -17968,7 +17968,7 @@ function resolveExternalSkillsConfig(input) {
17968
17968
  };
17969
17969
  return merged;
17970
17970
  }
17971
- var SEPARATORS, CANONICAL_ROLES_LONGEST_FIRST, CANONICAL_ROLES_SET, AgentOverrideConfigSchema, SwarmConfigSchema, HooksConfigSchema, ScoringWeightsSchema, DecisionDecaySchema, TokenRatiosSchema, ScoringConfigSchema, ContextBudgetConfigSchema, EvidenceConfigSchema, GateFeatureSchema, PlaceholderScanConfigSchema, QualityBudgetConfigSchema, GateConfigSchema, PipelineConfigSchema, PhaseCompleteConfigSchema, SummaryConfigSchema, ReviewPassesConfigSchema, AdversarialDetectionConfigSchema, AdversarialTestingConfigSchemaBase, AdversarialTestingConfigSchema, IntegrationAnalysisConfigSchema, DocsConfigSchema, DesignDocsConfigSchema, UIReviewConfigSchema, CompactionAdvisoryConfigSchema, LintConfigSchema, SecretscanConfigSchema, GuardrailsProfileSchema, DEFAULT_AGENT_PROFILES, DEFAULT_ARCHITECT_PROFILE, GuardrailsConfigSchema, WatchdogConfigSchema, SelfReviewConfigSchema, ToolFilterConfigSchema, PlanCursorConfigSchema, ContextMapConfigSchema, CheckpointConfigSchema, AutomationModeSchema, AutomationCapabilitiesSchema, AutomationConfigSchemaBase, AutomationConfigSchema, KnowledgeConfigSchema, MemoryConfigSchema, CuratorConfigSchema, ArchitecturalSupervisionConfigSchema, KnowledgeApplicationConfigSchema, SkillPropagationConfigSchema, SkillImproverConfigSchema, SpecWriterConfigSchema, SlopDetectorConfigSchema, IncrementalVerifyConfigSchema, CompactionConfigSchema, PrmConfigSchema, AgentAuthorityRuleSchema, AuthorityConfigSchema, GeneralCouncilMemberConfigSchema, GeneralCouncilConfigSchema, CouncilConfigSchema, ParallelizationConfigSchema, WorktreeIsolationConfigSchema, LeanTurboConfigSchema, StandardTurboConfigSchema, LeanTurboStrategyConfigSchema, TurboConfigSchema, ExternalSkillCandidateSourceTypeSchema, ExternalSkillCandidateEvaluationVerdictSchema, DiscoverySourceSchema, ExternalSkillCandidateSchema, ExternalSkillsConfigSchema, DEFAULT_EXTERNAL_SKILLS_CONFIG, PluginConfigSchema;
17971
+ var SEPARATORS, CANONICAL_ROLES_LONGEST_FIRST, CANONICAL_ROLES_SET, AgentOverrideConfigSchema, SwarmConfigSchema, HooksConfigSchema, ScoringWeightsSchema, DecisionDecaySchema, TokenRatiosSchema, ScoringConfigSchema, ContextBudgetConfigSchema, EvidenceConfigSchema, GateFeatureSchema, PlaceholderScanConfigSchema, QualityBudgetConfigSchema, GateConfigSchema, PipelineConfigSchema, PhaseCompleteConfigSchema, SummaryConfigSchema, ReviewPassesConfigSchema, AdversarialDetectionConfigSchema, AdversarialTestingConfigSchemaBase, AdversarialTestingConfigSchema, IntegrationAnalysisConfigSchema, DocsConfigSchema, DesignDocsConfigSchema, UIReviewConfigSchema, CompactionAdvisoryConfigSchema, LintConfigSchema, SecretscanConfigSchema, GuardrailsProfileSchema, DEFAULT_AGENT_PROFILES, DEFAULT_ARCHITECT_PROFILE, GuardrailsConfigSchema, WatchdogConfigSchema, SelfReviewConfigSchema, ToolFilterConfigSchema, PlanCursorConfigSchema, ContextMapConfigSchema, CheckpointConfigSchema, AutomationModeSchema, AutomationCapabilitiesSchema, AutomationConfigSchemaBase, AutomationConfigSchema, KnowledgeConfigSchema, MemoryConfigSchema, CuratorConfigSchema, ArchitecturalSupervisionConfigSchema, KnowledgeApplicationConfigSchema, SkillPropagationConfigSchema, SkillImproverConfigSchema, SpecWriterConfigSchema, SlopDetectorConfigSchema, IncrementalVerifyConfigSchema, CompactionConfigSchema, PrmConfigSchema, AgentAuthorityRuleSchema, AuthorityConfigSchema, GeneralCouncilMemberConfigSchema, GeneralCouncilConfigSchema, CouncilConfigSchema, PrMonitorConfigSchema, ParallelizationConfigSchema, WorktreeIsolationConfigSchema, LeanTurboConfigSchema, StandardTurboConfigSchema, LeanTurboStrategyConfigSchema, TurboConfigSchema, ExternalSkillCandidateSourceTypeSchema, ExternalSkillCandidateEvaluationVerdictSchema, DiscoverySourceSchema, ExternalSkillCandidateSchema, ExternalSkillsConfigSchema, DEFAULT_EXTERNAL_SKILLS_CONFIG, PluginConfigSchema;
17972
17972
  var init_schema = __esm(() => {
17973
17973
  init_zod();
17974
17974
  init_constants();
@@ -18647,6 +18647,24 @@ var init_schema = __esm(() => {
18647
18647
  phaseConcernsAllowComplete: exports_external.boolean().default(true).describe("When true, a phase-level council CONCERNS verdict with only MEDIUM/LOW findings does NOT block phase completion \u2014 the advisory notes are logged as warnings and the phase proceeds. When false, CONCERNS blocks like REJECT. Note: HIGH/CRITICAL findings from CONCERNS members are always promoted to requiredFixes and block at the tool level regardless of this setting. Default: true."),
18648
18648
  general: GeneralCouncilConfigSchema.optional()
18649
18649
  }).strict();
18650
+ PrMonitorConfigSchema = exports_external.object({
18651
+ enabled: exports_external.boolean().default(false),
18652
+ poll_interval_seconds: exports_external.number().int().min(30).max(300).default(60),
18653
+ max_subscriptions: exports_external.number().int().min(1).max(100).default(20),
18654
+ max_prs_per_cycle: exports_external.number().int().min(1).max(20).default(5),
18655
+ max_concurrent_pr_polls: exports_external.number().int().min(1).max(10).default(3),
18656
+ poll_timeout_ms: exports_external.number().int().min(5000).max(120000).default(30000),
18657
+ failure_threshold: exports_external.number().int().min(1).max(20).default(5),
18658
+ cooldown_seconds: exports_external.number().int().min(5).max(600).default(30),
18659
+ max_cooldown_seconds: exports_external.number().int().min(30).max(3600).default(300),
18660
+ cleanup_ttl_days: exports_external.number().int().min(1).max(90).default(7),
18661
+ auto_unsubscribe_on_merge: exports_external.boolean().default(true),
18662
+ auto_unsubscribe_on_close: exports_external.boolean().default(true),
18663
+ notify_ci_failure: exports_external.boolean().default(true),
18664
+ notify_new_comments: exports_external.boolean().default(true),
18665
+ notify_merge_conflict: exports_external.boolean().default(true),
18666
+ auto_pr_feedback: exports_external.boolean().default(false)
18667
+ }).strict();
18650
18668
  ParallelizationConfigSchema = exports_external.object({
18651
18669
  enabled: exports_external.boolean().default(false),
18652
18670
  maxConcurrentTasks: exports_external.number().int().min(1).max(64).default(1),
@@ -18788,7 +18806,7 @@ var init_schema = __esm(() => {
18788
18806
  const trimmed = v.trim();
18789
18807
  return trimmed === "" ? false : trimmed;
18790
18808
  }),
18791
- swarms: exports_external.record(exports_external.string(), SwarmConfigSchema).optional(),
18809
+ swarms: exports_external.record(exports_external.string().regex(/^[^_]+$/, "Swarm ID must not contain underscores"), SwarmConfigSchema).optional(),
18792
18810
  max_iterations: exports_external.number().min(1).max(10).default(5),
18793
18811
  pipeline: PipelineConfigSchema.optional(),
18794
18812
  phase_complete: PhaseCompleteConfigSchema.optional(),
@@ -18991,6 +19009,7 @@ var init_schema = __esm(() => {
18991
19009
  every_minutes: 20
18992
19010
  }
18993
19011
  })),
19012
+ pr_monitor: PrMonitorConfigSchema.optional(),
18994
19013
  external_skills: ExternalSkillsConfigSchema.optional()
18995
19014
  });
18996
19015
  });
@@ -22299,7 +22318,7 @@ var init_docs = () => {};
22299
22318
  // src/agents/reviewer.ts
22300
22319
  var init_reviewer = () => {};
22301
22320
  // src/agents/index.ts
22302
- var warnedAgents, KNOWN_VARIANT_VALUES;
22321
+ var warnedAgents, _swarmAgentsMap, KNOWN_VARIANT_VALUES;
22303
22322
  var init_agents2 = __esm(() => {
22304
22323
  init_config();
22305
22324
  init_constants();
@@ -22318,6 +22337,7 @@ var init_agents2 = __esm(() => {
22318
22337
  init_docs();
22319
22338
  init_reviewer();
22320
22339
  warnedAgents = new Set;
22340
+ _swarmAgentsMap = new Map;
22321
22341
  KNOWN_VARIANT_VALUES = new Set([
22322
22342
  "low",
22323
22343
  "medium",
@@ -53493,6 +53513,217 @@ var init_pr_feedback = __esm(() => {
53493
53513
  init_pr_ref();
53494
53514
  });
53495
53515
 
53516
+ // src/background/pr-subscriptions.ts
53517
+ import * as fs17 from "fs";
53518
+ import * as path43 from "path";
53519
+ function storePath(directory) {
53520
+ return validateSwarmPath(directory, PR_SUBSCRIPTIONS_FILE);
53521
+ }
53522
+ function ensureSwarmDir2(directory) {
53523
+ fs17.mkdirSync(path43.resolve(directory, ".swarm", "pr-monitor"), {
53524
+ recursive: true
53525
+ });
53526
+ }
53527
+ function buildCorrelationId(sessionID, repoFullName, prNumber) {
53528
+ return `${sessionID}::${repoFullName}::${prNumber}`;
53529
+ }
53530
+ function readAllRecords(directory) {
53531
+ let raw;
53532
+ try {
53533
+ raw = fs17.readFileSync(storePath(directory), "utf-8");
53534
+ } catch (err) {
53535
+ if (err.code === "ENOENT")
53536
+ return [];
53537
+ log(`[pr-monitor] readAllRecords failed: ${err instanceof Error ? err.message : String(err)}`);
53538
+ return [];
53539
+ }
53540
+ const folded = new Map;
53541
+ for (const line of raw.split(`
53542
+ `)) {
53543
+ const trimmed = line.trim();
53544
+ if (trimmed.length === 0)
53545
+ continue;
53546
+ let parsedJson;
53547
+ try {
53548
+ parsedJson = JSON.parse(trimmed);
53549
+ } catch {
53550
+ continue;
53551
+ }
53552
+ const result = RecordSchema.safeParse(parsedJson);
53553
+ if (!result.success)
53554
+ continue;
53555
+ folded.set(result.data.correlationId, result.data);
53556
+ }
53557
+ return [...folded.values()];
53558
+ }
53559
+ function appendRecord(directory, record3) {
53560
+ const result = RecordSchema.safeParse(record3);
53561
+ if (!result.success) {
53562
+ throw new Error(`Invalid subscription record: ${result.error.message}`);
53563
+ }
53564
+ ensureSwarmDir2(directory);
53565
+ fs17.appendFileSync(storePath(directory), `${JSON.stringify(record3)}
53566
+ `, "utf-8");
53567
+ }
53568
+ async function subscribe(directory, input) {
53569
+ if (!directory || directory.trim() === "") {
53570
+ throw new Error("directory is required");
53571
+ }
53572
+ if (!input.sessionID || input.sessionID.trim() === "") {
53573
+ throw new Error("sessionID is required and must be non-empty");
53574
+ }
53575
+ if (!input.repoFullName || input.repoFullName.trim() === "") {
53576
+ throw new Error("repoFullName is required and must be non-empty");
53577
+ }
53578
+ if (!input.prUrl || input.prUrl.trim() === "") {
53579
+ throw new Error("prUrl is required and must be non-empty");
53580
+ }
53581
+ if (!input.prNumber || !Number.isInteger(input.prNumber) || input.prNumber <= 0) {
53582
+ throw new Error("prNumber is required and must be a positive integer");
53583
+ }
53584
+ const correlationId = buildCorrelationId(input.sessionID, input.repoFullName, input.prNumber);
53585
+ const now = Date.now();
53586
+ return withEvidenceLock(directory, PR_SUBSCRIPTIONS_FILE, STORE_LOCK_AGENT, STORE_LOCK_TASK, async () => {
53587
+ const existing = readAllRecords(directory);
53588
+ const match = existing.find((r) => r.correlationId === correlationId && r.status === "active");
53589
+ if (match) {
53590
+ onSubscriptionCreated?.(directory, match);
53591
+ return match;
53592
+ }
53593
+ if (input.maxSubscriptions !== undefined && input.maxSubscriptions > 0) {
53594
+ const activeCount = existing.filter((r) => r.status === "active").length;
53595
+ if (activeCount >= input.maxSubscriptions) {
53596
+ throw new Error(`PR subscription limit reached: ${activeCount}/${input.maxSubscriptions}`);
53597
+ }
53598
+ }
53599
+ const record3 = {
53600
+ correlationId,
53601
+ sessionID: input.sessionID,
53602
+ prNumber: input.prNumber,
53603
+ repoFullName: input.repoFullName,
53604
+ prUrl: input.prUrl,
53605
+ lastCheckedAt: now,
53606
+ isWatching: true,
53607
+ hasUnaddressedEvents: false,
53608
+ status: "active",
53609
+ createdAt: now,
53610
+ updatedAt: now,
53611
+ errorCount: 0
53612
+ };
53613
+ appendRecord(directory, record3);
53614
+ onSubscriptionCreated?.(directory, record3);
53615
+ return record3;
53616
+ });
53617
+ }
53618
+ async function unsubscribe(directory, correlationId) {
53619
+ if (!correlationId)
53620
+ return null;
53621
+ return withEvidenceLock(directory, PR_SUBSCRIPTIONS_FILE, STORE_LOCK_AGENT, STORE_LOCK_TASK, async () => {
53622
+ const existing = readAllRecords(directory);
53623
+ const match = existing.find((r) => r.correlationId === correlationId && r.status === "active");
53624
+ if (!match)
53625
+ return null;
53626
+ const now = Date.now();
53627
+ const removed = {
53628
+ ...match,
53629
+ status: "removed",
53630
+ isWatching: false,
53631
+ updatedAt: now
53632
+ };
53633
+ appendRecord(directory, removed);
53634
+ return removed;
53635
+ });
53636
+ }
53637
+ async function listActive(directory) {
53638
+ return readAllRecords(directory).filter((r) => r.status === "active");
53639
+ }
53640
+ var PR_SUBSCRIPTIONS_FILE = "pr-monitor/subscriptions.jsonl", STORE_LOCK_AGENT = "pr-monitor", STORE_LOCK_TASK = "pr-subscriptions", onSubscriptionCreated = null, RecordSchema;
53641
+ var init_pr_subscriptions = __esm(() => {
53642
+ init_zod();
53643
+ init_lock();
53644
+ init_utils2();
53645
+ init_utils();
53646
+ RecordSchema = exports_external.object({
53647
+ correlationId: exports_external.string().min(1),
53648
+ sessionID: exports_external.string().min(1),
53649
+ prNumber: exports_external.number().int().positive(),
53650
+ repoFullName: exports_external.string().regex(/^[^/]+\/[^/]+$/, "Must be owner/repo format"),
53651
+ prUrl: exports_external.string().min(1).regex(/^https:\/\/github\.com\/[^/]+\/[^/]+\/pull\/\d+$/, "Must be a valid GitHub PR URL"),
53652
+ headRefOid: exports_external.string().optional(),
53653
+ lastCheckedAt: exports_external.number(),
53654
+ lastCommentId: exports_external.string().optional(),
53655
+ lastCheckRunSet: exports_external.string().optional(),
53656
+ mergeableState: exports_external.string().optional(),
53657
+ isWatching: exports_external.boolean(),
53658
+ hasUnaddressedEvents: exports_external.boolean(),
53659
+ status: exports_external.enum(["active", "removed", "expired"]),
53660
+ createdAt: exports_external.number(),
53661
+ updatedAt: exports_external.number(),
53662
+ errorCount: exports_external.number().int().min(0),
53663
+ customPollIntervalSeconds: exports_external.number().int().positive().optional(),
53664
+ customFailureThreshold: exports_external.number().int().min(0).optional(),
53665
+ customCooldownSeconds: exports_external.number().int().min(0).optional()
53666
+ }).strict();
53667
+ });
53668
+
53669
+ // src/commands/pr-monitor-status.ts
53670
+ function formatRelativeTime(epochMs) {
53671
+ const diffMs = Date.now() - epochMs;
53672
+ if (diffMs < 0)
53673
+ return "just now";
53674
+ if (diffMs < 5000)
53675
+ return "just now";
53676
+ const diffSeconds = Math.floor(diffMs / 1000);
53677
+ if (diffSeconds < 60)
53678
+ return `${diffSeconds} seconds ago`;
53679
+ const diffMinutes = Math.floor(diffSeconds / 60);
53680
+ if (diffMinutes < 60)
53681
+ return `${diffMinutes} minute${diffMinutes === 1 ? "" : "s"} ago`;
53682
+ const diffHours = Math.floor(diffMinutes / 60);
53683
+ if (diffHours < 24)
53684
+ return `${diffHours} hour${diffHours === 1 ? "" : "s"} ago`;
53685
+ const diffDays = Math.floor(diffHours / 24);
53686
+ return `${diffDays} day${diffDays === 1 ? "" : "s"} ago`;
53687
+ }
53688
+ async function handlePrMonitorStatusCommand(directory, _args, sessionID) {
53689
+ const allActive = await _internals26.listActive(directory);
53690
+ const sessionSubs = allActive.filter((record3) => record3.sessionID === sessionID);
53691
+ if (sessionSubs.length === 0) {
53692
+ return "No active PR subscriptions for this session.";
53693
+ }
53694
+ const lines = [];
53695
+ lines.push(`PR Monitor Status \u2014 Session: ${sessionID}`);
53696
+ lines.push("");
53697
+ const totalActive = allActive.length;
53698
+ lines.push(`Active subscriptions (${sessionSubs.length}):`);
53699
+ for (let i = 0;i < sessionSubs.length; i++) {
53700
+ const sub = sessionSubs[i];
53701
+ const index = i + 1;
53702
+ lines.push(` ${index}. ${sub.repoFullName}#${sub.prNumber}`);
53703
+ lines.push(` URL: ${sub.prUrl}`);
53704
+ lines.push(` Last checked: ${formatRelativeTime(sub.lastCheckedAt)}`);
53705
+ lines.push(` Watching: ${sub.isWatching ? "yes" : "no"}`);
53706
+ lines.push(` Errors: ${sub.errorCount}`);
53707
+ if (i < sessionSubs.length - 1) {
53708
+ lines.push("");
53709
+ }
53710
+ }
53711
+ lines.push("");
53712
+ if (totalActive !== sessionSubs.length) {
53713
+ lines.push(`Total active across all sessions: ${totalActive}`);
53714
+ }
53715
+ return lines.join(`
53716
+ `);
53717
+ }
53718
+ var _internals26;
53719
+ var init_pr_monitor_status = __esm(() => {
53720
+ init_pr_subscriptions();
53721
+ _internals26 = {
53722
+ formatRelativeTime,
53723
+ listActive
53724
+ };
53725
+ });
53726
+
53496
53727
  // src/commands/pr-review.ts
53497
53728
  function parseArgs6(args) {
53498
53729
  const out = { council: false, rest: [] };
@@ -53552,6 +53783,172 @@ var init_pr_review = __esm(() => {
53552
53783
  `);
53553
53784
  });
53554
53785
 
53786
+ // src/commands/pr-subscribe.ts
53787
+ async function handlePrSubscribeCommand(directory, args, sessionID) {
53788
+ const rest = args.filter((t) => t.trim().length > 0);
53789
+ if (rest.length === 0) {
53790
+ return [
53791
+ "Usage: /swarm pr subscribe <pr-url|owner/repo#N|N>",
53792
+ "",
53793
+ "Subscribes the current session to receive advisory notifications",
53794
+ "for the specified PR. Requires pr_monitor.enabled: true in config.",
53795
+ "",
53796
+ " /swarm pr subscribe https://github.com/owner/repo/pull/42",
53797
+ " /swarm pr subscribe owner/repo#42",
53798
+ " /swarm pr subscribe 42"
53799
+ ].join(`
53800
+ `);
53801
+ }
53802
+ const refToken = rest[0];
53803
+ const prInfo = parsePrRef(refToken, directory);
53804
+ if (!prInfo) {
53805
+ if (looksLikePrRef(refToken)) {
53806
+ return [
53807
+ `Error: Could not resolve PR reference from "${refToken}".`,
53808
+ "",
53809
+ "That looked like a PR reference but could not be resolved.",
53810
+ "Pass a full URL or `owner/repo#N`, or verify your git",
53811
+ "`origin` remote points to a GitHub repository."
53812
+ ].join(`
53813
+ `);
53814
+ }
53815
+ return [
53816
+ `Error: "${refToken}" is not a valid PR reference.`,
53817
+ "",
53818
+ "Expected: full GitHub URL, owner/repo#N shorthand,",
53819
+ "or a bare PR number (resolved against origin)."
53820
+ ].join(`
53821
+ `);
53822
+ }
53823
+ const repoFullName = `${prInfo.owner}/${prInfo.repo}`;
53824
+ const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
53825
+ try {
53826
+ const config3 = _internals27.loadPluginConfig(directory);
53827
+ const prMonitorConfig = config3.pr_monitor;
53828
+ if (!prMonitorConfig?.enabled) {
53829
+ return [
53830
+ "Error: PR Monitor is not enabled.",
53831
+ "",
53832
+ "Set `pr_monitor.enabled: true` in your opencode config to enable."
53833
+ ].join(`
53834
+ `);
53835
+ }
53836
+ await _internals27.subscribe(directory, {
53837
+ sessionID,
53838
+ prNumber: prInfo.number,
53839
+ repoFullName,
53840
+ prUrl,
53841
+ maxSubscriptions: prMonitorConfig?.max_subscriptions
53842
+ });
53843
+ return [
53844
+ `Subscribed to ${prUrl}`,
53845
+ `Session: ${sessionID}`,
53846
+ `PR: ${repoFullName}#${prInfo.number}`,
53847
+ "",
53848
+ "The background PR monitor will now check this PR for",
53849
+ "CI failures, new comments, review state changes, and",
53850
+ "merge/close events. Notifications appear as session-scoped",
53851
+ "advisories with dedup tokens."
53852
+ ].join(`
53853
+ `);
53854
+ } catch (err) {
53855
+ const message = err instanceof Error ? err.message : String(err);
53856
+ return [`Error: Failed to subscribe to ${prUrl}`, "", message].join(`
53857
+ `);
53858
+ }
53859
+ }
53860
+ var _internals27;
53861
+ var init_pr_subscribe = __esm(() => {
53862
+ init_pr_subscriptions();
53863
+ init_loader();
53864
+ init_pr_ref();
53865
+ _internals27 = {
53866
+ loadPluginConfig,
53867
+ subscribe
53868
+ };
53869
+ });
53870
+
53871
+ // src/commands/pr-unsubscribe.ts
53872
+ async function handlePrUnsubscribeCommand(directory, args, sessionID) {
53873
+ const rest = args.filter((t) => t.trim().length > 0);
53874
+ if (rest.length === 0) {
53875
+ return [
53876
+ "Usage: /swarm pr unsubscribe <pr-url|owner/repo#N|N>",
53877
+ "",
53878
+ "Unsubscribes the current session from receiving advisory",
53879
+ "notifications for the specified PR. Removes the active",
53880
+ "subscription record.",
53881
+ "",
53882
+ " /swarm pr unsubscribe https://github.com/owner/repo/pull/42",
53883
+ " /swarm pr unsubscribe owner/repo#42",
53884
+ " /swarm pr unsubscribe 42"
53885
+ ].join(`
53886
+ `);
53887
+ }
53888
+ const refToken = rest[0];
53889
+ const prInfo = _internals28.parsePrRef(refToken, directory);
53890
+ if (!prInfo) {
53891
+ if (_internals28.looksLikePrRef(refToken)) {
53892
+ return [
53893
+ `Error: Could not resolve PR reference from "${refToken}".`,
53894
+ "",
53895
+ "That looked like a PR reference but could not be resolved.",
53896
+ "Pass a full URL or `owner/repo#N`, or verify your git",
53897
+ "`origin` remote points to a GitHub repository."
53898
+ ].join(`
53899
+ `);
53900
+ }
53901
+ return [
53902
+ `Error: "${refToken}" is not a valid PR reference.`,
53903
+ "",
53904
+ "Expected: full GitHub URL, owner/repo#N shorthand,",
53905
+ "or a bare PR number (resolved against origin)."
53906
+ ].join(`
53907
+ `);
53908
+ }
53909
+ const repoFullName = `${prInfo.owner}/${prInfo.repo}`;
53910
+ const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
53911
+ try {
53912
+ const correlationId = _internals28.buildCorrelationId(sessionID, repoFullName, prInfo.number);
53913
+ const result = await _internals28.unsubscribe(directory, correlationId);
53914
+ if (!result) {
53915
+ return [
53916
+ `Not subscribed to ${prUrl}`,
53917
+ `Session: ${sessionID}`,
53918
+ `PR: ${repoFullName}#${prInfo.number}`,
53919
+ "",
53920
+ "No active subscription found for this session and PR.",
53921
+ "Use /swarm pr subscribe to start monitoring."
53922
+ ].join(`
53923
+ `);
53924
+ }
53925
+ return [
53926
+ `Unsubscribed from ${prUrl}`,
53927
+ `Session: ${sessionID}`,
53928
+ `PR: ${repoFullName}#${prInfo.number}`,
53929
+ "",
53930
+ "The background PR monitor will no longer check this PR for",
53931
+ "the current session. Use /swarm pr subscribe to re-subscribe."
53932
+ ].join(`
53933
+ `);
53934
+ } catch (err) {
53935
+ const message = err instanceof Error ? err.message : String(err);
53936
+ return [`Error: Failed to unsubscribe from ${prUrl}`, "", message].join(`
53937
+ `);
53938
+ }
53939
+ }
53940
+ var _internals28;
53941
+ var init_pr_unsubscribe = __esm(() => {
53942
+ init_pr_subscriptions();
53943
+ init_pr_ref();
53944
+ _internals28 = {
53945
+ unsubscribe,
53946
+ buildCorrelationId,
53947
+ parsePrRef,
53948
+ looksLikePrRef
53949
+ };
53950
+ });
53951
+
53555
53952
  // src/utils/path-security.ts
53556
53953
  function containsPathTraversal(str) {
53557
53954
  if (/\.\.[/\\]/.test(str))
@@ -53584,8 +53981,8 @@ function containsControlChars(str) {
53584
53981
  var init_path_security = () => {};
53585
53982
 
53586
53983
  // src/tools/lint.ts
53587
- import * as fs17 from "fs";
53588
- import * as path43 from "path";
53984
+ import * as fs18 from "fs";
53985
+ import * as path44 from "path";
53589
53986
  function validateArgs(args) {
53590
53987
  if (typeof args !== "object" || args === null)
53591
53988
  return false;
@@ -53596,9 +53993,9 @@ function validateArgs(args) {
53596
53993
  }
53597
53994
  function getLinterCommand(linter, mode, projectDir) {
53598
53995
  const isWindows = process.platform === "win32";
53599
- const binDir = path43.join(projectDir, "node_modules", ".bin");
53600
- const biomeBin = isWindows ? path43.join(binDir, "biome.EXE") : path43.join(binDir, "biome");
53601
- const eslintBin = isWindows ? path43.join(binDir, "eslint.cmd") : path43.join(binDir, "eslint");
53996
+ const binDir = path44.join(projectDir, "node_modules", ".bin");
53997
+ const biomeBin = isWindows ? path44.join(binDir, "biome.EXE") : path44.join(binDir, "biome");
53998
+ const eslintBin = isWindows ? path44.join(binDir, "eslint.cmd") : path44.join(binDir, "eslint");
53602
53999
  switch (linter) {
53603
54000
  case "biome":
53604
54001
  if (mode === "fix") {
@@ -53614,7 +54011,7 @@ function getLinterCommand(linter, mode, projectDir) {
53614
54011
  }
53615
54012
  function getAdditionalLinterCommand(linter, mode, cwd) {
53616
54013
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
53617
- const gradlew = fs17.existsSync(path43.join(cwd, gradlewName)) ? path43.join(cwd, gradlewName) : null;
54014
+ const gradlew = fs18.existsSync(path44.join(cwd, gradlewName)) ? path44.join(cwd, gradlewName) : null;
53618
54015
  switch (linter) {
53619
54016
  case "ruff":
53620
54017
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -53648,12 +54045,12 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
53648
54045
  }
53649
54046
  }
53650
54047
  function detectRuff(cwd) {
53651
- if (fs17.existsSync(path43.join(cwd, "ruff.toml")))
54048
+ if (fs18.existsSync(path44.join(cwd, "ruff.toml")))
53652
54049
  return isCommandAvailable("ruff");
53653
54050
  try {
53654
- const pyproject = path43.join(cwd, "pyproject.toml");
53655
- if (fs17.existsSync(pyproject)) {
53656
- const content = fs17.readFileSync(pyproject, "utf-8");
54051
+ const pyproject = path44.join(cwd, "pyproject.toml");
54052
+ if (fs18.existsSync(pyproject)) {
54053
+ const content = fs18.readFileSync(pyproject, "utf-8");
53657
54054
  if (content.includes("[tool.ruff]"))
53658
54055
  return isCommandAvailable("ruff");
53659
54056
  }
@@ -53661,21 +54058,21 @@ function detectRuff(cwd) {
53661
54058
  return false;
53662
54059
  }
53663
54060
  function detectClippy(cwd) {
53664
- return fs17.existsSync(path43.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
54061
+ return fs18.existsSync(path44.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
53665
54062
  }
53666
54063
  function detectGolangciLint(cwd) {
53667
- return fs17.existsSync(path43.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
54064
+ return fs18.existsSync(path44.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
53668
54065
  }
53669
54066
  function detectCheckstyle(cwd) {
53670
- const hasMaven = fs17.existsSync(path43.join(cwd, "pom.xml"));
53671
- const hasGradle = fs17.existsSync(path43.join(cwd, "build.gradle")) || fs17.existsSync(path43.join(cwd, "build.gradle.kts"));
53672
- const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs17.existsSync(path43.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
54067
+ const hasMaven = fs18.existsSync(path44.join(cwd, "pom.xml"));
54068
+ const hasGradle = fs18.existsSync(path44.join(cwd, "build.gradle")) || fs18.existsSync(path44.join(cwd, "build.gradle.kts"));
54069
+ const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs18.existsSync(path44.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
53673
54070
  return (hasMaven || hasGradle) && hasBinary;
53674
54071
  }
53675
54072
  function detectKtlint(cwd) {
53676
- const hasKotlin = fs17.existsSync(path43.join(cwd, "build.gradle.kts")) || fs17.existsSync(path43.join(cwd, "build.gradle")) || (() => {
54073
+ const hasKotlin = fs18.existsSync(path44.join(cwd, "build.gradle.kts")) || fs18.existsSync(path44.join(cwd, "build.gradle")) || (() => {
53677
54074
  try {
53678
- return fs17.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
54075
+ return fs18.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
53679
54076
  } catch {
53680
54077
  return false;
53681
54078
  }
@@ -53684,7 +54081,7 @@ function detectKtlint(cwd) {
53684
54081
  }
53685
54082
  function detectDotnetFormat(cwd) {
53686
54083
  try {
53687
- const files = fs17.readdirSync(cwd);
54084
+ const files = fs18.readdirSync(cwd);
53688
54085
  const hasCsproj = files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"));
53689
54086
  return hasCsproj && isCommandAvailable("dotnet");
53690
54087
  } catch {
@@ -53692,14 +54089,14 @@ function detectDotnetFormat(cwd) {
53692
54089
  }
53693
54090
  }
53694
54091
  function detectCppcheck(cwd) {
53695
- if (fs17.existsSync(path43.join(cwd, "CMakeLists.txt"))) {
54092
+ if (fs18.existsSync(path44.join(cwd, "CMakeLists.txt"))) {
53696
54093
  return isCommandAvailable("cppcheck");
53697
54094
  }
53698
54095
  try {
53699
- const dirsToCheck = [cwd, path43.join(cwd, "src")];
54096
+ const dirsToCheck = [cwd, path44.join(cwd, "src")];
53700
54097
  const hasCpp = dirsToCheck.some((dir) => {
53701
54098
  try {
53702
- return fs17.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
54099
+ return fs18.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
53703
54100
  } catch {
53704
54101
  return false;
53705
54102
  }
@@ -53710,13 +54107,13 @@ function detectCppcheck(cwd) {
53710
54107
  }
53711
54108
  }
53712
54109
  function detectSwiftlint(cwd) {
53713
- return fs17.existsSync(path43.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
54110
+ return fs18.existsSync(path44.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
53714
54111
  }
53715
54112
  function detectDartAnalyze(cwd) {
53716
- return fs17.existsSync(path43.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
54113
+ return fs18.existsSync(path44.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
53717
54114
  }
53718
54115
  function detectRubocop(cwd) {
53719
- return (fs17.existsSync(path43.join(cwd, "Gemfile")) || fs17.existsSync(path43.join(cwd, "gems.rb")) || fs17.existsSync(path43.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
54116
+ return (fs18.existsSync(path44.join(cwd, "Gemfile")) || fs18.existsSync(path44.join(cwd, "gems.rb")) || fs18.existsSync(path44.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
53720
54117
  }
53721
54118
  function detectAdditionalLinter(cwd) {
53722
54119
  if (detectRuff(cwd))
@@ -53744,10 +54141,10 @@ function detectAdditionalLinter(cwd) {
53744
54141
  function findBinInAncestors(startDir, binName) {
53745
54142
  let dir = startDir;
53746
54143
  while (true) {
53747
- const candidate = path43.join(dir, "node_modules", ".bin", binName);
53748
- if (fs17.existsSync(candidate))
54144
+ const candidate = path44.join(dir, "node_modules", ".bin", binName);
54145
+ if (fs18.existsSync(candidate))
53749
54146
  return candidate;
53750
- const parent = path43.dirname(dir);
54147
+ const parent = path44.dirname(dir);
53751
54148
  if (parent === dir)
53752
54149
  break;
53753
54150
  dir = parent;
@@ -53756,11 +54153,11 @@ function findBinInAncestors(startDir, binName) {
53756
54153
  }
53757
54154
  function findBinInEnvPath(binName) {
53758
54155
  const searchPath = process.env.PATH ?? "";
53759
- for (const dir of searchPath.split(path43.delimiter)) {
54156
+ for (const dir of searchPath.split(path44.delimiter)) {
53760
54157
  if (!dir)
53761
54158
  continue;
53762
- const candidate = path43.join(dir, binName);
53763
- if (fs17.existsSync(candidate))
54159
+ const candidate = path44.join(dir, binName);
54160
+ if (fs18.existsSync(candidate))
53764
54161
  return candidate;
53765
54162
  }
53766
54163
  return null;
@@ -53768,17 +54165,17 @@ function findBinInEnvPath(binName) {
53768
54165
  async function detectAvailableLinter(directory) {
53769
54166
  if (!directory)
53770
54167
  return null;
53771
- if (!fs17.existsSync(directory))
54168
+ if (!fs18.existsSync(directory))
53772
54169
  return null;
53773
54170
  const projectDir = directory;
53774
54171
  const isWindows = process.platform === "win32";
53775
- const biomeBin = isWindows ? path43.join(projectDir, "node_modules", ".bin", "biome.EXE") : path43.join(projectDir, "node_modules", ".bin", "biome");
53776
- const eslintBin = isWindows ? path43.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path43.join(projectDir, "node_modules", ".bin", "eslint");
54172
+ const biomeBin = isWindows ? path44.join(projectDir, "node_modules", ".bin", "biome.EXE") : path44.join(projectDir, "node_modules", ".bin", "biome");
54173
+ const eslintBin = isWindows ? path44.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path44.join(projectDir, "node_modules", ".bin", "eslint");
53777
54174
  const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
53778
54175
  if (localResult)
53779
54176
  return localResult;
53780
- const biomeAncestor = findBinInAncestors(path43.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
53781
- const eslintAncestor = findBinInAncestors(path43.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
54177
+ const biomeAncestor = findBinInAncestors(path44.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
54178
+ const eslintAncestor = findBinInAncestors(path44.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
53782
54179
  if (biomeAncestor || eslintAncestor) {
53783
54180
  return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
53784
54181
  }
@@ -53797,11 +54194,11 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
53797
54194
  stderr: "pipe"
53798
54195
  });
53799
54196
  const biomeExit = biomeProc.exited;
53800
- const timeout = new Promise((resolve15) => setTimeout(() => resolve15("timeout"), DETECT_TIMEOUT));
54197
+ const timeout = new Promise((resolve16) => setTimeout(() => resolve16("timeout"), DETECT_TIMEOUT));
53801
54198
  const result = await Promise.race([biomeExit, timeout]);
53802
54199
  if (result === "timeout") {
53803
54200
  biomeProc.kill();
53804
- } else if (biomeProc.exitCode === 0 && fs17.existsSync(biomeBin)) {
54201
+ } else if (biomeProc.exitCode === 0 && fs18.existsSync(biomeBin)) {
53805
54202
  return "biome";
53806
54203
  }
53807
54204
  } catch {}
@@ -53811,11 +54208,11 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
53811
54208
  stderr: "pipe"
53812
54209
  });
53813
54210
  const eslintExit = eslintProc.exited;
53814
- const timeout = new Promise((resolve15) => setTimeout(() => resolve15("timeout"), DETECT_TIMEOUT));
54211
+ const timeout = new Promise((resolve16) => setTimeout(() => resolve16("timeout"), DETECT_TIMEOUT));
53815
54212
  const result = await Promise.race([eslintExit, timeout]);
53816
54213
  if (result === "timeout") {
53817
54214
  eslintProc.kill();
53818
- } else if (eslintProc.exitCode === 0 && fs17.existsSync(eslintBin)) {
54215
+ } else if (eslintProc.exitCode === 0 && fs18.existsSync(eslintBin)) {
53819
54216
  return "eslint";
53820
54217
  }
53821
54218
  } catch {}
@@ -53937,7 +54334,7 @@ async function runAdditionalLint(linter, mode, cwd) {
53937
54334
  };
53938
54335
  }
53939
54336
  }
53940
- var MAX_OUTPUT_BYTES = 512000, MAX_COMMAND_LENGTH = 500, lint, _internals26;
54337
+ var MAX_OUTPUT_BYTES = 512000, MAX_COMMAND_LENGTH = 500, lint, _internals29;
53941
54338
  var init_lint = __esm(() => {
53942
54339
  init_zod();
53943
54340
  init_discovery();
@@ -53969,15 +54366,15 @@ var init_lint = __esm(() => {
53969
54366
  }
53970
54367
  const { mode } = args;
53971
54368
  const cwd = directory;
53972
- const linter = await _internals26.detectAvailableLinter(directory);
54369
+ const linter = await _internals29.detectAvailableLinter(directory);
53973
54370
  if (linter) {
53974
- const result = await _internals26.runLint(linter, mode, directory);
54371
+ const result = await _internals29.runLint(linter, mode, directory);
53975
54372
  return JSON.stringify(result, null, 2);
53976
54373
  }
53977
- const additionalLinter = _internals26.detectAdditionalLinter(cwd);
54374
+ const additionalLinter = _internals29.detectAdditionalLinter(cwd);
53978
54375
  if (additionalLinter) {
53979
54376
  warn(`[lint] Using ${additionalLinter} linter for this project`);
53980
- const result = await _internals26.runAdditionalLint(additionalLinter, mode, cwd);
54377
+ const result = await _internals29.runAdditionalLint(additionalLinter, mode, cwd);
53981
54378
  return JSON.stringify(result, null, 2);
53982
54379
  }
53983
54380
  const errorResult = {
@@ -53991,7 +54388,7 @@ For Rust: rustup component add clippy`
53991
54388
  return JSON.stringify(errorResult, null, 2);
53992
54389
  }
53993
54390
  });
53994
- _internals26 = {
54391
+ _internals29 = {
53995
54392
  detectAvailableLinter,
53996
54393
  runLint,
53997
54394
  detectAdditionalLinter,
@@ -54000,8 +54397,8 @@ For Rust: rustup component add clippy`
54000
54397
  });
54001
54398
 
54002
54399
  // src/tools/secretscan.ts
54003
- import * as fs18 from "fs";
54004
- import * as path44 from "path";
54400
+ import * as fs19 from "fs";
54401
+ import * as path45 from "path";
54005
54402
  function calculateShannonEntropy(str) {
54006
54403
  if (str.length === 0)
54007
54404
  return 0;
@@ -54049,11 +54446,11 @@ function isGlobOrPathPattern(pattern) {
54049
54446
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
54050
54447
  }
54051
54448
  function loadSecretScanIgnore(scanDir) {
54052
- const ignorePath = path44.join(scanDir, ".secretscanignore");
54449
+ const ignorePath = path45.join(scanDir, ".secretscanignore");
54053
54450
  try {
54054
- if (!fs18.existsSync(ignorePath))
54451
+ if (!fs19.existsSync(ignorePath))
54055
54452
  return [];
54056
- const content = fs18.readFileSync(ignorePath, "utf8");
54453
+ const content = fs19.readFileSync(ignorePath, "utf8");
54057
54454
  const patterns = [];
54058
54455
  for (const rawLine of content.split(/\r?\n/)) {
54059
54456
  const line = rawLine.trim();
@@ -54072,7 +54469,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
54072
54469
  if (exactNames.has(entry))
54073
54470
  return true;
54074
54471
  for (const pattern of globPatterns) {
54075
- if (path44.matchesGlob(relPath, pattern))
54472
+ if (path45.matchesGlob(relPath, pattern))
54076
54473
  return true;
54077
54474
  }
54078
54475
  return false;
@@ -54093,7 +54490,7 @@ function validateDirectoryInput(dir) {
54093
54490
  return null;
54094
54491
  }
54095
54492
  function isBinaryFile(filePath, buffer) {
54096
- const ext = path44.extname(filePath).toLowerCase();
54493
+ const ext = path45.extname(filePath).toLowerCase();
54097
54494
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
54098
54495
  return true;
54099
54496
  }
@@ -54171,7 +54568,7 @@ function createRedactedContext(line, findings) {
54171
54568
  function scanFileForSecrets(filePath) {
54172
54569
  const findings = [];
54173
54570
  try {
54174
- const lstat = fs18.lstatSync(filePath);
54571
+ const lstat = fs19.lstatSync(filePath);
54175
54572
  if (lstat.isSymbolicLink()) {
54176
54573
  return findings;
54177
54574
  }
@@ -54180,14 +54577,14 @@ function scanFileForSecrets(filePath) {
54180
54577
  }
54181
54578
  let buffer;
54182
54579
  if (O_NOFOLLOW !== undefined) {
54183
- const fd = fs18.openSync(filePath, "r", O_NOFOLLOW);
54580
+ const fd = fs19.openSync(filePath, "r", O_NOFOLLOW);
54184
54581
  try {
54185
- buffer = fs18.readFileSync(fd);
54582
+ buffer = fs19.readFileSync(fd);
54186
54583
  } finally {
54187
- fs18.closeSync(fd);
54584
+ fs19.closeSync(fd);
54188
54585
  }
54189
54586
  } else {
54190
- buffer = fs18.readFileSync(filePath);
54587
+ buffer = fs19.readFileSync(filePath);
54191
54588
  }
54192
54589
  if (isBinaryFile(filePath, buffer)) {
54193
54590
  return findings;
@@ -54229,9 +54626,9 @@ function isSymlinkLoop(realPath, visited) {
54229
54626
  return false;
54230
54627
  }
54231
54628
  function isPathWithinScope(realPath, scanDir) {
54232
- const resolvedScanDir = path44.resolve(scanDir);
54233
- const resolvedRealPath = path44.resolve(realPath);
54234
- return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path44.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
54629
+ const resolvedScanDir = path45.resolve(scanDir);
54630
+ const resolvedRealPath = path45.resolve(realPath);
54631
+ return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path45.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
54235
54632
  }
54236
54633
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
54237
54634
  skippedDirs: 0,
@@ -54242,7 +54639,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
54242
54639
  const files = [];
54243
54640
  let entries;
54244
54641
  try {
54245
- entries = fs18.readdirSync(dir);
54642
+ entries = fs19.readdirSync(dir);
54246
54643
  } catch {
54247
54644
  stats.fileErrors++;
54248
54645
  return files;
@@ -54257,15 +54654,15 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
54257
54654
  return a.localeCompare(b);
54258
54655
  });
54259
54656
  for (const entry of entries) {
54260
- const fullPath = path44.join(dir, entry);
54261
- const relPath = path44.relative(scanDir, fullPath).replace(/\\/g, "/");
54657
+ const fullPath = path45.join(dir, entry);
54658
+ const relPath = path45.relative(scanDir, fullPath).replace(/\\/g, "/");
54262
54659
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
54263
54660
  stats.skippedDirs++;
54264
54661
  continue;
54265
54662
  }
54266
54663
  let lstat;
54267
54664
  try {
54268
- lstat = fs18.lstatSync(fullPath);
54665
+ lstat = fs19.lstatSync(fullPath);
54269
54666
  } catch {
54270
54667
  stats.fileErrors++;
54271
54668
  continue;
@@ -54277,7 +54674,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
54277
54674
  if (lstat.isDirectory()) {
54278
54675
  let realPath;
54279
54676
  try {
54280
- realPath = fs18.realpathSync(fullPath);
54677
+ realPath = fs19.realpathSync(fullPath);
54281
54678
  } catch {
54282
54679
  stats.fileErrors++;
54283
54680
  continue;
@@ -54293,7 +54690,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
54293
54690
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
54294
54691
  files.push(...subFiles);
54295
54692
  } else if (lstat.isFile()) {
54296
- const ext = path44.extname(fullPath).toLowerCase();
54693
+ const ext = path45.extname(fullPath).toLowerCase();
54297
54694
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
54298
54695
  files.push(fullPath);
54299
54696
  } else {
@@ -54305,7 +54702,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
54305
54702
  }
54306
54703
  async function runSecretscan(directory) {
54307
54704
  try {
54308
- const result = await _internals27.secretscan.execute({ directory }, {});
54705
+ const result = await _internals30.secretscan.execute({ directory }, {});
54309
54706
  const jsonStr = typeof result === "string" ? result : result.output;
54310
54707
  return JSON.parse(jsonStr);
54311
54708
  } catch (e) {
@@ -54320,7 +54717,7 @@ async function runSecretscan(directory) {
54320
54717
  return errorResult;
54321
54718
  }
54322
54719
  }
54323
- 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_PATTERNS2, O_NOFOLLOW, secretscan, _internals27;
54720
+ 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_PATTERNS2, O_NOFOLLOW, secretscan, _internals30;
54324
54721
  var init_secretscan = __esm(() => {
54325
54722
  init_zod();
54326
54723
  init_path_security();
@@ -54496,7 +54893,7 @@ var init_secretscan = __esm(() => {
54496
54893
  redactTemplate: () => "SK[REDACTED]"
54497
54894
  }
54498
54895
  ];
54499
- O_NOFOLLOW = process.platform !== "win32" ? fs18.constants.O_NOFOLLOW : undefined;
54896
+ O_NOFOLLOW = process.platform !== "win32" ? fs19.constants.O_NOFOLLOW : undefined;
54500
54897
  secretscan = createSwarmTool({
54501
54898
  description: "Scan directory for potential secrets (API keys, tokens, passwords) using regex patterns and entropy heuristics. Returns metadata-only findings with redacted previews - NEVER returns raw secrets. Excludes common directories (node_modules, .git, dist, etc.) by default. Supports glob patterns (e.g. **/.svelte-kit/**, **/*.test.ts) and reads .secretscanignore at the scan root.",
54502
54899
  args: {
@@ -54553,15 +54950,15 @@ var init_secretscan = __esm(() => {
54553
54950
  }
54554
54951
  }
54555
54952
  try {
54556
- const _scanDirRaw = path44.resolve(directory);
54953
+ const _scanDirRaw = path45.resolve(directory);
54557
54954
  const scanDir = (() => {
54558
54955
  try {
54559
- return fs18.realpathSync(_scanDirRaw);
54956
+ return fs19.realpathSync(_scanDirRaw);
54560
54957
  } catch {
54561
54958
  return _scanDirRaw;
54562
54959
  }
54563
54960
  })();
54564
- if (!fs18.existsSync(scanDir)) {
54961
+ if (!fs19.existsSync(scanDir)) {
54565
54962
  const errorResult = {
54566
54963
  error: "directory not found",
54567
54964
  scan_dir: directory,
@@ -54572,7 +54969,7 @@ var init_secretscan = __esm(() => {
54572
54969
  };
54573
54970
  return JSON.stringify(errorResult, null, 2);
54574
54971
  }
54575
- const dirStat = fs18.statSync(scanDir);
54972
+ const dirStat = fs19.statSync(scanDir);
54576
54973
  if (!dirStat.isDirectory()) {
54577
54974
  const errorResult = {
54578
54975
  error: "target must be a directory, not a file",
@@ -54623,7 +55020,7 @@ var init_secretscan = __esm(() => {
54623
55020
  break;
54624
55021
  const fileFindings = scanFileForSecrets(filePath);
54625
55022
  try {
54626
- const stat5 = fs18.statSync(filePath);
55023
+ const stat5 = fs19.statSync(filePath);
54627
55024
  if (stat5.size > MAX_FILE_SIZE_BYTES) {
54628
55025
  skippedFiles++;
54629
55026
  continue;
@@ -54692,19 +55089,19 @@ var init_secretscan = __esm(() => {
54692
55089
  }
54693
55090
  }
54694
55091
  });
54695
- _internals27 = {
55092
+ _internals30 = {
54696
55093
  secretscan,
54697
55094
  runSecretscan
54698
55095
  };
54699
55096
  });
54700
55097
 
54701
55098
  // src/lang/default-backend.ts
54702
- import * as fs19 from "fs";
54703
- import * as path45 from "path";
55099
+ import * as fs20 from "fs";
55100
+ import * as path46 from "path";
54704
55101
  function detectFileExists(dir, pattern) {
54705
55102
  if (pattern.includes("*") || pattern.includes("?")) {
54706
55103
  try {
54707
- const files = fs19.readdirSync(dir);
55104
+ const files = fs20.readdirSync(dir);
54708
55105
  const regex = new RegExp(`^${pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".")}$`);
54709
55106
  return files.some((f) => regex.test(f));
54710
55107
  } catch {
@@ -54712,7 +55109,7 @@ function detectFileExists(dir, pattern) {
54712
55109
  }
54713
55110
  }
54714
55111
  try {
54715
- fs19.accessSync(path45.join(dir, pattern));
55112
+ fs20.accessSync(path46.join(dir, pattern));
54716
55113
  return true;
54717
55114
  } catch {
54718
55115
  return false;
@@ -54851,8 +55248,8 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
54851
55248
  return ["mvn", "test"];
54852
55249
  case "gradle": {
54853
55250
  const isWindows = process.platform === "win32";
54854
- const hasGradlewBat = fs19.existsSync(path45.join(dir, "gradlew.bat"));
54855
- const hasGradlew = fs19.existsSync(path45.join(dir, "gradlew"));
55251
+ const hasGradlewBat = fs20.existsSync(path46.join(dir, "gradlew.bat"));
55252
+ const hasGradlew = fs20.existsSync(path46.join(dir, "gradlew"));
54856
55253
  if (hasGradlewBat && isWindows)
54857
55254
  return ["gradlew.bat", "test"];
54858
55255
  if (hasGradlew)
@@ -54869,7 +55266,7 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
54869
55266
  "cmake-build-release",
54870
55267
  "out"
54871
55268
  ];
54872
- const actualBuildDir = buildDirCandidates.find((d) => fs19.existsSync(path45.join(dir, d, "CMakeCache.txt"))) ?? "build";
55269
+ const actualBuildDir = buildDirCandidates.find((d) => fs20.existsSync(path46.join(dir, d, "CMakeCache.txt"))) ?? "build";
54873
55270
  return ["ctest", "--test-dir", actualBuildDir];
54874
55271
  }
54875
55272
  case "swift-test":
@@ -55158,23 +55555,23 @@ async function defaultSelectBuildCommand(profile, dir) {
55158
55555
  return null;
55159
55556
  }
55160
55557
  async function defaultTestFilesFor(profile, sourceFile, dir) {
55161
- const ext = path45.extname(sourceFile);
55558
+ const ext = path46.extname(sourceFile);
55162
55559
  if (!profile.extensions.includes(ext))
55163
55560
  return [];
55164
- const base = path45.basename(sourceFile, ext);
55165
- const rel = path45.relative(dir, sourceFile);
55166
- const relDir = path45.dirname(rel);
55561
+ const base = path46.basename(sourceFile, ext);
55562
+ const rel = path46.relative(dir, sourceFile);
55563
+ const relDir = path46.dirname(rel);
55167
55564
  const stripSrc = relDir.replace(/^src(\/|\\)/, "");
55168
55565
  const candidates = new Set;
55169
55566
  for (const tDir of ["tests", "test", "__tests__", "spec"]) {
55170
55567
  for (const suffix of ["", "_test", ".test", "_spec", ".spec"]) {
55171
- candidates.add(path45.join(dir, tDir, stripSrc, `${base}${suffix}${ext}`));
55568
+ candidates.add(path46.join(dir, tDir, stripSrc, `${base}${suffix}${ext}`));
55172
55569
  }
55173
55570
  }
55174
55571
  const existing = [];
55175
55572
  for (const c of candidates) {
55176
55573
  try {
55177
- fs19.accessSync(c);
55574
+ fs20.accessSync(c);
55178
55575
  existing.push(c);
55179
55576
  } catch {}
55180
55577
  }
@@ -55208,8 +55605,8 @@ var init_default_backend = __esm(() => {
55208
55605
  });
55209
55606
 
55210
55607
  // src/lang/backends/go.ts
55211
- import * as fs20 from "fs";
55212
- import * as path46 from "path";
55608
+ import * as fs21 from "fs";
55609
+ import * as path47 from "path";
55213
55610
  function extractImports(_sourceFile, source) {
55214
55611
  const out = new Set;
55215
55612
  IMPORT_REGEX_SINGLE.lastIndex = 0;
@@ -55235,7 +55632,7 @@ function extractImports(_sourceFile, source) {
55235
55632
  async function selectFramework(dir) {
55236
55633
  let content;
55237
55634
  try {
55238
- content = fs20.readFileSync(path46.join(dir, "go.mod"), "utf-8");
55635
+ content = fs21.readFileSync(path47.join(dir, "go.mod"), "utf-8");
55239
55636
  } catch {
55240
55637
  return null;
55241
55638
  }
@@ -55256,16 +55653,16 @@ async function selectFramework(dir) {
55256
55653
  async function selectEntryPoints(dir) {
55257
55654
  const points = [];
55258
55655
  try {
55259
- fs20.accessSync(path46.join(dir, "main.go"));
55656
+ fs21.accessSync(path47.join(dir, "main.go"));
55260
55657
  points.push("main.go");
55261
55658
  } catch {}
55262
55659
  try {
55263
- const cmdDir = path46.join(dir, "cmd");
55264
- const subdirs = fs20.readdirSync(cmdDir, { withFileTypes: true }).filter((d) => d.isDirectory());
55660
+ const cmdDir = path47.join(dir, "cmd");
55661
+ const subdirs = fs21.readdirSync(cmdDir, { withFileTypes: true }).filter((d) => d.isDirectory());
55265
55662
  for (const sub of subdirs) {
55266
- const main = path46.join("cmd", sub.name, "main.go");
55663
+ const main = path47.join("cmd", sub.name, "main.go");
55267
55664
  try {
55268
- fs20.accessSync(path46.join(dir, main));
55665
+ fs21.accessSync(path47.join(dir, main));
55269
55666
  points.push(main);
55270
55667
  } catch {}
55271
55668
  }
@@ -55284,19 +55681,19 @@ function buildGoBackend() {
55284
55681
  selectEntryPoints
55285
55682
  };
55286
55683
  }
55287
- var PROFILE_ID = "go", IMPORT_REGEX_SINGLE, IMPORT_REGEX_GROUP, IMPORT_REGEX_GROUP_LINE, _internals28;
55684
+ var PROFILE_ID = "go", IMPORT_REGEX_SINGLE, IMPORT_REGEX_GROUP, IMPORT_REGEX_GROUP_LINE, _internals31;
55288
55685
  var init_go = __esm(() => {
55289
55686
  init_default_backend();
55290
55687
  init_profiles();
55291
55688
  IMPORT_REGEX_SINGLE = /^\s*import\s+(?:[a-zA-Z_.][a-zA-Z0-9_]*\s+)?"([^"]+)"/gm;
55292
55689
  IMPORT_REGEX_GROUP = /^\s*import\s*\(([\s\S]*?)\)/gm;
55293
55690
  IMPORT_REGEX_GROUP_LINE = /(?:[a-zA-Z_.][a-zA-Z0-9_]*\s+)?"([^"]+)"/g;
55294
- _internals28 = { extractImports };
55691
+ _internals31 = { extractImports };
55295
55692
  });
55296
55693
 
55297
55694
  // src/lang/backends/python.ts
55298
- import * as fs21 from "fs";
55299
- import * as path47 from "path";
55695
+ import * as fs22 from "fs";
55696
+ import * as path48 from "path";
55300
55697
  function parseImportTargets(rawTargets) {
55301
55698
  const cleaned = rawTargets.replace(/[()]/g, "").split(`
55302
55699
  `).map((line) => line.replace(/#.*$/, "").replace(/\\\s*$/, "")).join(" ");
@@ -55356,7 +55753,7 @@ async function selectFramework2(dir) {
55356
55753
  ];
55357
55754
  for (const candidate of ["pyproject.toml", "requirements.txt", "setup.py"]) {
55358
55755
  try {
55359
- const content = fs21.readFileSync(path47.join(dir, candidate), "utf-8");
55756
+ const content = fs22.readFileSync(path48.join(dir, candidate), "utf-8");
55360
55757
  const lower = content.toLowerCase();
55361
55758
  for (const [pkg, name] of candidates) {
55362
55759
  if (lower.includes(pkg)) {
@@ -55370,7 +55767,7 @@ async function selectFramework2(dir) {
55370
55767
  async function selectEntryPoints2(dir) {
55371
55768
  const points = new Set;
55372
55769
  try {
55373
- const content = fs21.readFileSync(path47.join(dir, "pyproject.toml"), "utf-8");
55770
+ const content = fs22.readFileSync(path48.join(dir, "pyproject.toml"), "utf-8");
55374
55771
  const scriptsBlock = content.match(/\[project\.scripts\][\s\S]*?(?=\n\[|$)/);
55375
55772
  if (scriptsBlock) {
55376
55773
  for (const line of scriptsBlock[0].split(`
@@ -55385,7 +55782,7 @@ async function selectEntryPoints2(dir) {
55385
55782
  } catch {}
55386
55783
  for (const name of ["manage.py", "main.py", "app.py", "__main__.py"]) {
55387
55784
  try {
55388
- fs21.accessSync(path47.join(dir, name));
55785
+ fs22.accessSync(path48.join(dir, name));
55389
55786
  points.add(name);
55390
55787
  } catch {}
55391
55788
  }
@@ -55403,18 +55800,18 @@ function buildPythonBackend() {
55403
55800
  selectEntryPoints: selectEntryPoints2
55404
55801
  };
55405
55802
  }
55406
- var PROFILE_ID2 = "python", IMPORT_REGEX_FROM_WITH_TARGETS, IMPORT_REGEX_IMPORT, _internals29;
55803
+ var PROFILE_ID2 = "python", IMPORT_REGEX_FROM_WITH_TARGETS, IMPORT_REGEX_IMPORT, _internals32;
55407
55804
  var init_python = __esm(() => {
55408
55805
  init_default_backend();
55409
55806
  init_profiles();
55410
55807
  IMPORT_REGEX_FROM_WITH_TARGETS = /^\s*from\s+(\.*[\w.]*)\s+import\s+(\([^)]*\)|[^\n#]+)/gm;
55411
55808
  IMPORT_REGEX_IMPORT = /^\s*import\s+([^\n#]+)/gm;
55412
- _internals29 = { extractImports: extractImports2 };
55809
+ _internals32 = { extractImports: extractImports2 };
55413
55810
  });
55414
55811
 
55415
55812
  // src/test-impact/analyzer.ts
55416
- import fs22 from "fs";
55417
- import path48 from "path";
55813
+ import fs23 from "fs";
55814
+ import path49 from "path";
55418
55815
  function normalizePath(p) {
55419
55816
  return p.replace(/\\/g, "/");
55420
55817
  }
@@ -55434,7 +55831,7 @@ function sharedTrailingSegments(a, b) {
55434
55831
  function isCacheStale(impactMap, generatedAtMs) {
55435
55832
  for (const sourcePath of Object.keys(impactMap)) {
55436
55833
  try {
55437
- const stat5 = fs22.statSync(sourcePath);
55834
+ const stat5 = fs23.statSync(sourcePath);
55438
55835
  if (stat5.mtimeMs > generatedAtMs) {
55439
55836
  return true;
55440
55837
  }
@@ -55448,15 +55845,15 @@ function resolveRelativeImport(fromDir, importPath) {
55448
55845
  if (!importPath.startsWith(".")) {
55449
55846
  return null;
55450
55847
  }
55451
- const resolved = path48.resolve(fromDir, importPath);
55452
- if (path48.extname(resolved)) {
55453
- if (fs22.existsSync(resolved) && fs22.statSync(resolved).isFile()) {
55848
+ const resolved = path49.resolve(fromDir, importPath);
55849
+ if (path49.extname(resolved)) {
55850
+ if (fs23.existsSync(resolved) && fs23.statSync(resolved).isFile()) {
55454
55851
  return normalizePath(resolved);
55455
55852
  }
55456
55853
  } else {
55457
55854
  for (const ext of EXTENSIONS_TO_TRY) {
55458
55855
  const withExt = resolved + ext;
55459
- if (fs22.existsSync(withExt) && fs22.statSync(withExt).isFile()) {
55856
+ if (fs23.existsSync(withExt) && fs23.statSync(withExt).isFile()) {
55460
55857
  return normalizePath(withExt);
55461
55858
  }
55462
55859
  }
@@ -55469,29 +55866,29 @@ function resolvePythonImport(fromDir, module) {
55469
55866
  const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
55470
55867
  let baseDir = fromDir;
55471
55868
  for (let i = 1;i < leadingDots; i++) {
55472
- baseDir = path48.dirname(baseDir);
55869
+ baseDir = path49.dirname(baseDir);
55473
55870
  }
55474
55871
  const rest = module.slice(leadingDots);
55475
55872
  if (rest.length === 0) {
55476
- const initPath = path48.join(baseDir, "__init__.py");
55477
- if (fs22.existsSync(initPath) && fs22.statSync(initPath).isFile()) {
55873
+ const initPath = path49.join(baseDir, "__init__.py");
55874
+ if (fs23.existsSync(initPath) && fs23.statSync(initPath).isFile()) {
55478
55875
  return normalizePath(initPath);
55479
55876
  }
55480
55877
  return null;
55481
55878
  }
55482
- const subpath = rest.replace(/\./g, path48.sep);
55879
+ const subpath = rest.replace(/\./g, path49.sep);
55483
55880
  const candidates = [
55484
- `${path48.join(baseDir, subpath)}.py`,
55485
- path48.join(baseDir, subpath, "__init__.py")
55881
+ `${path49.join(baseDir, subpath)}.py`,
55882
+ path49.join(baseDir, subpath, "__init__.py")
55486
55883
  ];
55487
55884
  for (const c of candidates) {
55488
- if (fs22.existsSync(c) && fs22.statSync(c).isFile())
55885
+ if (fs23.existsSync(c) && fs23.statSync(c).isFile())
55489
55886
  return normalizePath(c);
55490
55887
  }
55491
55888
  return null;
55492
55889
  }
55493
55890
  function findGoModule(fromDir) {
55494
- const resolved = path48.resolve(fromDir);
55891
+ const resolved = path49.resolve(fromDir);
55495
55892
  let cur = resolved;
55496
55893
  const walked = [];
55497
55894
  for (let i = 0;i < 16; i++) {
@@ -55503,8 +55900,8 @@ function findGoModule(fromDir) {
55503
55900
  }
55504
55901
  walked.push(cur);
55505
55902
  try {
55506
- const goMod = path48.join(cur, "go.mod");
55507
- const content = fs22.readFileSync(goMod, "utf-8");
55903
+ const goMod = path49.join(cur, "go.mod");
55904
+ const content = fs23.readFileSync(goMod, "utf-8");
55508
55905
  const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
55509
55906
  if (moduleMatch) {
55510
55907
  const result = { moduleRoot: cur, modulePath: moduleMatch[1] };
@@ -55514,10 +55911,10 @@ function findGoModule(fromDir) {
55514
55911
  }
55515
55912
  } catch {}
55516
55913
  try {
55517
- fs22.accessSync(path48.join(cur, ".git"));
55914
+ fs23.accessSync(path49.join(cur, ".git"));
55518
55915
  break;
55519
55916
  } catch {}
55520
- const parent = path48.dirname(cur);
55917
+ const parent = path49.dirname(cur);
55521
55918
  if (parent === cur)
55522
55919
  break;
55523
55920
  cur = parent;
@@ -55529,20 +55926,20 @@ function findGoModule(fromDir) {
55529
55926
  function resolveGoImport(fromDir, importPath) {
55530
55927
  let dir = null;
55531
55928
  if (importPath.startsWith(".")) {
55532
- dir = path48.resolve(fromDir, importPath);
55929
+ dir = path49.resolve(fromDir, importPath);
55533
55930
  } else {
55534
55931
  const mod = findGoModule(fromDir);
55535
55932
  if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
55536
55933
  const subpath = importPath.slice(mod.modulePath.length);
55537
- dir = path48.join(mod.moduleRoot, subpath);
55934
+ dir = path49.join(mod.moduleRoot, subpath);
55538
55935
  }
55539
55936
  }
55540
55937
  if (dir === null)
55541
55938
  return [];
55542
- if (!fs22.existsSync(dir) || !fs22.statSync(dir).isDirectory())
55939
+ if (!fs23.existsSync(dir) || !fs23.statSync(dir).isDirectory())
55543
55940
  return [];
55544
55941
  try {
55545
- return fs22.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath(path48.join(dir, f)));
55942
+ return fs23.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath(path49.join(dir, f)));
55546
55943
  } catch {
55547
55944
  return [];
55548
55945
  }
@@ -55562,13 +55959,13 @@ function findTestFilesSync(cwd) {
55562
55959
  function walk(dir, visitedInodes) {
55563
55960
  let entries;
55564
55961
  try {
55565
- entries = fs22.readdirSync(dir, { withFileTypes: true });
55962
+ entries = fs23.readdirSync(dir, { withFileTypes: true });
55566
55963
  } catch {
55567
55964
  return;
55568
55965
  }
55569
55966
  let dirInode;
55570
55967
  try {
55571
- dirInode = fs22.statSync(dir).ino;
55968
+ dirInode = fs23.statSync(dir).ino;
55572
55969
  } catch {
55573
55970
  return;
55574
55971
  }
@@ -55581,15 +55978,15 @@ function findTestFilesSync(cwd) {
55581
55978
  for (const entry of entries) {
55582
55979
  if (entry.isDirectory()) {
55583
55980
  if (!skipDirs.has(entry.name)) {
55584
- walk(path48.join(dir, entry.name), visitedInodes);
55981
+ walk(path49.join(dir, entry.name), visitedInodes);
55585
55982
  }
55586
55983
  } else if (entry.isFile()) {
55587
55984
  const name = entry.name;
55588
55985
  const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name);
55589
- const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path48.sep}tests${path48.sep}`) && name.endsWith(".py");
55986
+ const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path49.sep}tests${path49.sep}`) && name.endsWith(".py");
55590
55987
  const isGoTest = /.+_test\.go$/.test(name);
55591
55988
  if (isTsTest || isPyTest || isGoTest) {
55592
- testFiles.push(normalizePath(path48.join(dir, entry.name)));
55989
+ testFiles.push(normalizePath(path49.join(dir, entry.name)));
55593
55990
  }
55594
55991
  }
55595
55992
  }
@@ -55614,8 +56011,8 @@ function extractImports3(content) {
55614
56011
  ];
55615
56012
  }
55616
56013
  function addImpactEdgesForTestFile(testFile, content, impactMap) {
55617
- const ext = path48.extname(testFile).toLowerCase();
55618
- const testDir = path48.dirname(testFile);
56014
+ const ext = path49.extname(testFile).toLowerCase();
56015
+ const testDir = path49.dirname(testFile);
55619
56016
  function addEdge(source) {
55620
56017
  if (!impactMap[source])
55621
56018
  impactMap[source] = [];
@@ -55633,7 +56030,7 @@ function addImpactEdgesForTestFile(testFile, content, impactMap) {
55633
56030
  return;
55634
56031
  }
55635
56032
  if (PYTHON_EXTENSIONS.has(ext)) {
55636
- const modules = _internals29.extractImports(testFile, content);
56033
+ const modules = _internals32.extractImports(testFile, content);
55637
56034
  for (const mod of modules) {
55638
56035
  const resolved = resolvePythonImport(testDir, mod);
55639
56036
  if (resolved !== null)
@@ -55642,7 +56039,7 @@ function addImpactEdgesForTestFile(testFile, content, impactMap) {
55642
56039
  return;
55643
56040
  }
55644
56041
  if (GO_EXTENSIONS.has(ext)) {
55645
- const imports = _internals28.extractImports(testFile, content);
56042
+ const imports = _internals31.extractImports(testFile, content);
55646
56043
  for (const importPath of imports) {
55647
56044
  const sourceFiles = resolveGoImport(testDir, importPath);
55648
56045
  for (const source of sourceFiles)
@@ -55657,7 +56054,7 @@ async function buildImpactMapInternal(cwd) {
55657
56054
  for (const testFile of testFiles) {
55658
56055
  let content;
55659
56056
  try {
55660
- content = fs22.readFileSync(testFile, "utf-8");
56057
+ content = fs23.readFileSync(testFile, "utf-8");
55661
56058
  } catch {
55662
56059
  continue;
55663
56060
  }
@@ -55669,22 +56066,22 @@ async function buildImpactMapInternal(cwd) {
55669
56066
  return impactMap;
55670
56067
  }
55671
56068
  async function buildImpactMap(cwd) {
55672
- const impactMap = await _internals30.buildImpactMapInternal(cwd);
55673
- await _internals30.saveImpactMap(cwd, impactMap);
56069
+ const impactMap = await _internals33.buildImpactMapInternal(cwd);
56070
+ await _internals33.saveImpactMap(cwd, impactMap);
55674
56071
  return impactMap;
55675
56072
  }
55676
56073
  async function loadImpactMap(cwd, options) {
55677
- const cachePath = path48.join(cwd, ".swarm", "cache", "impact-map.json");
55678
- if (fs22.existsSync(cachePath)) {
56074
+ const cachePath = path49.join(cwd, ".swarm", "cache", "impact-map.json");
56075
+ if (fs23.existsSync(cachePath)) {
55679
56076
  try {
55680
- const content = fs22.readFileSync(cachePath, "utf-8");
56077
+ const content = fs23.readFileSync(cachePath, "utf-8");
55681
56078
  const data = JSON.parse(content);
55682
56079
  if (data.map !== null && typeof data.map === "object" && !Array.isArray(data.map)) {
55683
56080
  const map3 = data.map;
55684
56081
  const hasValidValues = Object.values(map3).every((v) => Array.isArray(v) && v.every((item) => typeof item === "string"));
55685
56082
  if (hasValidValues) {
55686
56083
  const generatedAt = new Date(data.generatedAt).getTime();
55687
- if (!_internals30.isCacheStale(map3, generatedAt)) {
56084
+ if (!_internals33.isCacheStale(map3, generatedAt)) {
55688
56085
  return map3;
55689
56086
  }
55690
56087
  if (options?.skipRebuild) {
@@ -55704,24 +56101,24 @@ async function loadImpactMap(cwd, options) {
55704
56101
  if (options?.skipRebuild) {
55705
56102
  return {};
55706
56103
  }
55707
- return _internals30.buildImpactMap(cwd);
56104
+ return _internals33.buildImpactMap(cwd);
55708
56105
  }
55709
56106
  async function saveImpactMap(cwd, impactMap) {
55710
- if (!path48.isAbsolute(cwd)) {
56107
+ if (!path49.isAbsolute(cwd)) {
55711
56108
  throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
55712
56109
  }
55713
- _internals30.validateProjectRoot(cwd);
55714
- const cacheDir2 = path48.join(cwd, ".swarm", "cache");
55715
- const cachePath = path48.join(cacheDir2, "impact-map.json");
55716
- if (!fs22.existsSync(cacheDir2)) {
55717
- fs22.mkdirSync(cacheDir2, { recursive: true });
56110
+ _internals33.validateProjectRoot(cwd);
56111
+ const cacheDir2 = path49.join(cwd, ".swarm", "cache");
56112
+ const cachePath = path49.join(cacheDir2, "impact-map.json");
56113
+ if (!fs23.existsSync(cacheDir2)) {
56114
+ fs23.mkdirSync(cacheDir2, { recursive: true });
55718
56115
  }
55719
56116
  const data = {
55720
56117
  generatedAt: new Date().toISOString(),
55721
56118
  fileCount: Object.keys(impactMap).length,
55722
56119
  map: impactMap
55723
56120
  };
55724
- fs22.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf-8");
56121
+ fs23.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf-8");
55725
56122
  }
55726
56123
  async function analyzeImpact(changedFiles, cwd, budget) {
55727
56124
  if (!Array.isArray(changedFiles)) {
@@ -55734,7 +56131,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
55734
56131
  };
55735
56132
  }
55736
56133
  const validFiles = changedFiles.filter((f) => typeof f === "string" && f.length > 0 && !f.includes("\x00"));
55737
- const impactMap = await _internals30.loadImpactMap(cwd);
56134
+ const impactMap = await _internals33.loadImpactMap(cwd);
55738
56135
  const impactedTestsSet = new Set;
55739
56136
  const untestedFiles = [];
55740
56137
  let visitedCount = 0;
@@ -55744,7 +56141,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
55744
56141
  budgetExceeded = true;
55745
56142
  break;
55746
56143
  }
55747
- const normalizedChanged = normalizePath(path48.resolve(changedFile));
56144
+ const normalizedChanged = normalizePath(path49.resolve(changedFile));
55748
56145
  const tests = impactMap[normalizedChanged];
55749
56146
  if (tests && tests.length > 0) {
55750
56147
  for (const test of tests) {
@@ -55758,13 +56155,13 @@ async function analyzeImpact(changedFiles, cwd, budget) {
55758
56155
  if (budgetExceeded)
55759
56156
  break;
55760
56157
  } else {
55761
- const changedDir = normalizePath(path48.dirname(normalizedChanged));
55762
- const changedInputDir = normalizePath(path48.dirname(changedFile));
56158
+ const changedDir = normalizePath(path49.dirname(normalizedChanged));
56159
+ const changedInputDir = normalizePath(path49.dirname(changedFile));
55763
56160
  const suffixMatches = Object.entries(impactMap).filter(([sourcePath]) => {
55764
56161
  return sourcePath.endsWith(changedFile) || changedFile.endsWith(sourcePath) || sourcePath.endsWith(normalizedChanged) || normalizedChanged.endsWith(sourcePath);
55765
56162
  }).sort(([sourceA], [sourceB]) => {
55766
- const sourceDirA = normalizePath(path48.dirname(sourceA));
55767
- const sourceDirB = normalizePath(path48.dirname(sourceB));
56163
+ const sourceDirA = normalizePath(path49.dirname(sourceA));
56164
+ const sourceDirB = normalizePath(path49.dirname(sourceB));
55768
56165
  const exactA = sourceDirA === changedDir || changedInputDir !== "." && (sourceDirA === changedInputDir || sourceDirA.endsWith(`/${changedInputDir}`));
55769
56166
  const exactB = sourceDirB === changedDir || changedInputDir !== "." && (sourceDirB === changedInputDir || sourceDirB.endsWith(`/${changedInputDir}`));
55770
56167
  if (exactA !== exactB)
@@ -55819,7 +56216,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
55819
56216
  budgetExceeded
55820
56217
  };
55821
56218
  }
55822
- var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, TS_EXTENSIONS, PYTHON_EXTENSIONS, GO_EXTENSIONS, EXTENSIONS_TO_TRY, goModuleCache, _internals30;
56219
+ var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, TS_EXTENSIONS, PYTHON_EXTENSIONS, GO_EXTENSIONS, EXTENSIONS_TO_TRY, goModuleCache, _internals33;
55823
56220
  var init_analyzer = __esm(() => {
55824
56221
  init_manager2();
55825
56222
  init_go();
@@ -55832,7 +56229,7 @@ var init_analyzer = __esm(() => {
55832
56229
  GO_EXTENSIONS = new Set([".go"]);
55833
56230
  EXTENSIONS_TO_TRY = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
55834
56231
  goModuleCache = new Map;
55835
- _internals30 = {
56232
+ _internals33 = {
55836
56233
  validateProjectRoot,
55837
56234
  normalizePath,
55838
56235
  isCacheStale,
@@ -56071,16 +56468,16 @@ function detectFlakyTests(allHistory) {
56071
56468
  var FLAKY_THRESHOLD = 0.3, MIN_RUNS_FOR_QUARANTINE = 5, MAX_HISTORY_RUNS = 20;
56072
56469
 
56073
56470
  // src/test-impact/history-store.ts
56074
- import fs23 from "fs";
56075
- import path49 from "path";
56471
+ import fs24 from "fs";
56472
+ import path50 from "path";
56076
56473
  function getHistoryPath(workingDir) {
56077
56474
  if (!workingDir) {
56078
56475
  throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
56079
56476
  }
56080
- if (!path49.isAbsolute(workingDir)) {
56477
+ if (!path50.isAbsolute(workingDir)) {
56081
56478
  throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
56082
56479
  }
56083
- return path49.join(workingDir, ".swarm", "cache", "test-history.jsonl");
56480
+ return path50.join(workingDir, ".swarm", "cache", "test-history.jsonl");
56084
56481
  }
56085
56482
  function sanitizeErrorMessage(errorMessage) {
56086
56483
  if (errorMessage === undefined) {
@@ -56167,13 +56564,13 @@ function batchAppendTestRuns(records, workingDir) {
56167
56564
  }
56168
56565
  }
56169
56566
  const historyPath = getHistoryPath(workingDir);
56170
- const historyDir = path49.dirname(historyPath);
56171
- _internals31.validateProjectRoot(workingDir);
56172
- if (!fs23.existsSync(historyDir)) {
56173
- fs23.mkdirSync(historyDir, { recursive: true });
56567
+ const historyDir = path50.dirname(historyPath);
56568
+ _internals34.validateProjectRoot(workingDir);
56569
+ if (!fs24.existsSync(historyDir)) {
56570
+ fs24.mkdirSync(historyDir, { recursive: true });
56174
56571
  }
56175
56572
  withHistoryWriteLock(historyPath, () => {
56176
- const existingRecords = readAllRecords(historyPath);
56573
+ const existingRecords = readAllRecords2(historyPath);
56177
56574
  const sanitizedRecords = records.map((record3) => ({
56178
56575
  ...record3,
56179
56576
  timestamp: record3.timestamp || new Date().toISOString(),
@@ -56204,13 +56601,13 @@ function batchAppendTestRuns(records, workingDir) {
56204
56601
  `)}
56205
56602
  `;
56206
56603
  const tempPath = `${historyPath}.tmp`;
56207
- fs23.writeFileSync(tempPath, content, "utf-8");
56208
- fs23.renameSync(tempPath, historyPath);
56604
+ fs24.writeFileSync(tempPath, content, "utf-8");
56605
+ fs24.renameSync(tempPath, historyPath);
56209
56606
  } catch (err) {
56210
56607
  try {
56211
56608
  const tempPath = `${historyPath}.tmp`;
56212
- if (fs23.existsSync(tempPath)) {
56213
- fs23.unlinkSync(tempPath);
56609
+ if (fs24.existsSync(tempPath)) {
56610
+ fs24.unlinkSync(tempPath);
56214
56611
  }
56215
56612
  } catch {}
56216
56613
  throw new Error(`Failed to write test history: ${err instanceof Error ? err.message : String(err)}`);
@@ -56222,7 +56619,7 @@ function withHistoryWriteLock(historyPath, fn) {
56222
56619
  const deadline = Date.now() + HISTORY_WRITE_LOCK_TIMEOUT_MS;
56223
56620
  while (true) {
56224
56621
  try {
56225
- fs23.mkdirSync(lockPath);
56622
+ fs24.mkdirSync(lockPath);
56226
56623
  break;
56227
56624
  } catch (error93) {
56228
56625
  const code = error93 instanceof Error && "code" in error93 ? error93.code : undefined;
@@ -56233,9 +56630,9 @@ function withHistoryWriteLock(historyPath, fn) {
56233
56630
  throw new Error(`Timed out waiting for test history lock: ${historyPath}`);
56234
56631
  }
56235
56632
  try {
56236
- const lockStat = fs23.statSync(lockPath);
56633
+ const lockStat = fs24.statSync(lockPath);
56237
56634
  if (Date.now() - lockStat.mtimeMs >= HISTORY_WRITE_LOCK_STALE_MS) {
56238
- fs23.rmSync(lockPath, { recursive: true, force: true });
56635
+ fs24.rmSync(lockPath, { recursive: true, force: true });
56239
56636
  continue;
56240
56637
  }
56241
56638
  } catch {}
@@ -56250,7 +56647,7 @@ function withHistoryWriteLock(historyPath, fn) {
56250
56647
  return fn();
56251
56648
  } finally {
56252
56649
  try {
56253
- fs23.rmSync(lockPath, { recursive: true, force: true });
56650
+ fs24.rmSync(lockPath, { recursive: true, force: true });
56254
56651
  } catch {}
56255
56652
  }
56256
56653
  function sleepSync(ms) {
@@ -56258,12 +56655,12 @@ function withHistoryWriteLock(historyPath, fn) {
56258
56655
  while (Date.now() < until) {}
56259
56656
  }
56260
56657
  }
56261
- function readAllRecords(historyPath) {
56262
- if (!fs23.existsSync(historyPath)) {
56658
+ function readAllRecords2(historyPath) {
56659
+ if (!fs24.existsSync(historyPath)) {
56263
56660
  return [];
56264
56661
  }
56265
56662
  try {
56266
- const content = fs23.readFileSync(historyPath, "utf-8");
56663
+ const content = fs24.readFileSync(historyPath, "utf-8");
56267
56664
  const lines = content.split(`
56268
56665
  `);
56269
56666
  const records = [];
@@ -56287,11 +56684,11 @@ function readAllRecords(historyPath) {
56287
56684
  }
56288
56685
  function getAllHistory(workingDir) {
56289
56686
  const historyPath = getHistoryPath(workingDir);
56290
- const records = readAllRecords(historyPath);
56687
+ const records = readAllRecords2(historyPath);
56291
56688
  records.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
56292
56689
  return records;
56293
56690
  }
56294
- var MAX_HISTORY_PER_TEST = 20, MAX_ERROR_LENGTH = 500, MAX_STACK_LENGTH = 200, MAX_CHANGED_FILES = 50, HISTORY_WRITE_LOCK_TIMEOUT_MS = 5000, HISTORY_WRITE_LOCK_STALE_MS = 60000, HISTORY_WRITE_LOCK_BACKOFF_MS = 10, DANGEROUS_PROPERTY_NAMES, _internals31;
56691
+ var MAX_HISTORY_PER_TEST = 20, MAX_ERROR_LENGTH = 500, MAX_STACK_LENGTH = 200, MAX_CHANGED_FILES = 50, HISTORY_WRITE_LOCK_TIMEOUT_MS = 5000, HISTORY_WRITE_LOCK_STALE_MS = 60000, HISTORY_WRITE_LOCK_BACKOFF_MS = 10, DANGEROUS_PROPERTY_NAMES, _internals34;
56295
56692
  var init_history_store = __esm(() => {
56296
56693
  init_manager2();
56297
56694
  DANGEROUS_PROPERTY_NAMES = new Set([
@@ -56299,14 +56696,14 @@ var init_history_store = __esm(() => {
56299
56696
  "constructor",
56300
56697
  "prototype"
56301
56698
  ]);
56302
- _internals31 = {
56699
+ _internals34 = {
56303
56700
  validateProjectRoot
56304
56701
  };
56305
56702
  });
56306
56703
 
56307
56704
  // src/tools/resolve-working-directory.ts
56308
- import * as fs24 from "fs";
56309
- import * as path50 from "path";
56705
+ import * as fs25 from "fs";
56706
+ import * as path51 from "path";
56310
56707
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
56311
56708
  if (workingDirectory == null || workingDirectory === "") {
56312
56709
  if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
@@ -56338,18 +56735,18 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
56338
56735
  };
56339
56736
  }
56340
56737
  }
56341
- const rawPathParts = workingDirectory.split(path50.sep);
56738
+ const rawPathParts = workingDirectory.split(path51.sep);
56342
56739
  if (rawPathParts.includes("..")) {
56343
56740
  return {
56344
56741
  success: false,
56345
56742
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
56346
56743
  };
56347
56744
  }
56348
- const normalizedDir = path50.normalize(workingDirectory);
56349
- const resolvedDir = path50.resolve(normalizedDir);
56745
+ const normalizedDir = path51.normalize(workingDirectory);
56746
+ const resolvedDir = path51.resolve(normalizedDir);
56350
56747
  let statResult;
56351
56748
  try {
56352
- statResult = fs24.statSync(resolvedDir);
56749
+ statResult = fs25.statSync(resolvedDir);
56353
56750
  } catch {
56354
56751
  return {
56355
56752
  success: false,
@@ -56365,16 +56762,16 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
56365
56762
  if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
56366
56763
  return { success: true, directory: resolvedDir };
56367
56764
  }
56368
- const resolvedFallback = path50.resolve(fallbackDirectory);
56765
+ const resolvedFallback = path51.resolve(fallbackDirectory);
56369
56766
  let fallbackExists = false;
56370
56767
  try {
56371
- fs24.statSync(resolvedFallback);
56768
+ fs25.statSync(resolvedFallback);
56372
56769
  fallbackExists = true;
56373
56770
  } catch {
56374
56771
  fallbackExists = false;
56375
56772
  }
56376
56773
  if (fallbackExists) {
56377
- const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path50.sep);
56774
+ const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path51.sep);
56378
56775
  if (isSubdirectory) {
56379
56776
  return {
56380
56777
  success: false,
@@ -56420,8 +56817,8 @@ var init_registry_backend = __esm(() => {
56420
56817
  });
56421
56818
 
56422
56819
  // src/lang/framework-detector.ts
56423
- import * as fs25 from "fs";
56424
- import * as path51 from "path";
56820
+ import * as fs26 from "fs";
56821
+ import * as path52 from "path";
56425
56822
  function detectLaravelProject(directory) {
56426
56823
  const signals = getLaravelSignals(directory);
56427
56824
  const signalCount = [
@@ -56438,21 +56835,21 @@ function getLaravelSignals(directory) {
56438
56835
  return { hasArtisanFile, hasLaravelFrameworkDep, hasConfigApp };
56439
56836
  }
56440
56837
  function checkArtisanFile(directory) {
56441
- const artisanPath = path51.join(directory, "artisan");
56442
- if (!fs25.existsSync(artisanPath))
56838
+ const artisanPath = path52.join(directory, "artisan");
56839
+ if (!fs26.existsSync(artisanPath))
56443
56840
  return false;
56444
56841
  try {
56445
- return fs25.statSync(artisanPath).isFile();
56842
+ return fs26.statSync(artisanPath).isFile();
56446
56843
  } catch {
56447
56844
  return false;
56448
56845
  }
56449
56846
  }
56450
56847
  function checkLaravelFrameworkDep(directory) {
56451
- const composerPath = path51.join(directory, "composer.json");
56452
- if (!fs25.existsSync(composerPath))
56848
+ const composerPath = path52.join(directory, "composer.json");
56849
+ if (!fs26.existsSync(composerPath))
56453
56850
  return false;
56454
56851
  try {
56455
- const content = fs25.readFileSync(composerPath, "utf-8");
56852
+ const content = fs26.readFileSync(composerPath, "utf-8");
56456
56853
  const parsed = JSON.parse(content);
56457
56854
  const require2 = parsed?.require ?? {};
56458
56855
  return typeof require2["laravel/framework"] === "string";
@@ -56461,7 +56858,7 @@ function checkLaravelFrameworkDep(directory) {
56461
56858
  }
56462
56859
  }
56463
56860
  function checkConfigApp(directory) {
56464
- return fs25.existsSync(path51.join(directory, "config", "app.php"));
56861
+ return fs26.existsSync(path52.join(directory, "config", "app.php"));
56465
56862
  }
56466
56863
  var init_framework_detector = () => {};
56467
56864
 
@@ -56493,18 +56890,18 @@ var init_php = __esm(() => {
56493
56890
  });
56494
56891
 
56495
56892
  // src/lang/backends/typescript.ts
56496
- import * as fs26 from "fs";
56497
- import * as path52 from "path";
56893
+ import * as fs27 from "fs";
56894
+ import * as path53 from "path";
56498
56895
  function readPackageJsonRaw(dir) {
56499
56896
  try {
56500
- const content = fs26.readFileSync(path52.join(dir, "package.json"), "utf-8");
56897
+ const content = fs27.readFileSync(path53.join(dir, "package.json"), "utf-8");
56501
56898
  return JSON.parse(content);
56502
56899
  } catch {
56503
56900
  return null;
56504
56901
  }
56505
56902
  }
56506
56903
  function readPackageJson(dir) {
56507
- return _internals32.readPackageJsonRaw(dir);
56904
+ return _internals35.readPackageJsonRaw(dir);
56508
56905
  }
56509
56906
  function readPackageJsonTestScript(dir) {
56510
56907
  return readPackageJson(dir)?.scripts?.test ?? null;
@@ -56674,7 +57071,7 @@ function buildTypescriptBackend() {
56674
57071
  selectEntryPoints: selectEntryPoints3
56675
57072
  };
56676
57073
  }
56677
- var PROFILE_ID4 = "typescript", IMPORT_REGEX_ES2, IMPORT_REGEX_BARE, IMPORT_REGEX_REQUIRE2, IMPORT_REGEX_DYNAMIC, IMPORT_REGEX_REEXPORT2, _internals32;
57074
+ var PROFILE_ID4 = "typescript", IMPORT_REGEX_ES2, IMPORT_REGEX_BARE, IMPORT_REGEX_REQUIRE2, IMPORT_REGEX_DYNAMIC, IMPORT_REGEX_REEXPORT2, _internals35;
56678
57075
  var init_typescript = __esm(() => {
56679
57076
  init_default_backend();
56680
57077
  init_profiles();
@@ -56683,7 +57080,7 @@ var init_typescript = __esm(() => {
56683
57080
  IMPORT_REGEX_REQUIRE2 = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
56684
57081
  IMPORT_REGEX_DYNAMIC = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
56685
57082
  IMPORT_REGEX_REEXPORT2 = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
56686
- _internals32 = {
57083
+ _internals35 = {
56687
57084
  readPackageJsonRaw,
56688
57085
  readPackageJsonTestScript,
56689
57086
  frameworkFromScriptsTest
@@ -56716,13 +57113,13 @@ __export(exports_dispatch, {
56716
57113
  pickedProfiles: () => pickedProfiles,
56717
57114
  pickBackend: () => pickBackend,
56718
57115
  clearDispatchCache: () => clearDispatchCache,
56719
- _internals: () => _internals33
57116
+ _internals: () => _internals36
56720
57117
  });
56721
- import * as fs27 from "fs";
56722
- import * as path53 from "path";
57118
+ import * as fs28 from "fs";
57119
+ import * as path54 from "path";
56723
57120
  function safeReaddirSet(dir) {
56724
57121
  try {
56725
- return new Set(fs27.readdirSync(dir));
57122
+ return new Set(fs28.readdirSync(dir));
56726
57123
  } catch {
56727
57124
  return new Set;
56728
57125
  }
@@ -56736,14 +57133,14 @@ function manifestHash(dir) {
56736
57133
  if (!entries.has(name))
56737
57134
  continue;
56738
57135
  try {
56739
- const stat5 = fs27.statSync(path53.join(dir, name));
57136
+ const stat5 = fs28.statSync(path54.join(dir, name));
56740
57137
  parts.push(`${name}:${stat5.size}:${stat5.mtimeMs}:${stat5.ino}`);
56741
57138
  } catch {}
56742
57139
  }
56743
57140
  return parts.join("|");
56744
57141
  }
56745
57142
  function findManifestRoot(start) {
56746
- const resolved = path53.resolve(start);
57143
+ const resolved = path54.resolve(start);
56747
57144
  const cached3 = manifestRootCache.get(resolved);
56748
57145
  if (cached3 !== undefined)
56749
57146
  return cached3;
@@ -56762,7 +57159,7 @@ function findManifestRoot(start) {
56762
57159
  return cur;
56763
57160
  }
56764
57161
  }
56765
- const parent = path53.dirname(cur);
57162
+ const parent = path54.dirname(cur);
56766
57163
  if (parent === cur)
56767
57164
  break;
56768
57165
  cur = parent;
@@ -56771,7 +57168,7 @@ function findManifestRoot(start) {
56771
57168
  return start;
56772
57169
  }
56773
57170
  function evictIfNeeded() {
56774
- if (cache.size <= _internals33.cacheCapacity)
57171
+ if (cache.size <= _internals36.cacheCapacity)
56775
57172
  return;
56776
57173
  let oldestKey;
56777
57174
  let oldestOrder = Infinity;
@@ -56802,7 +57199,7 @@ async function pickBackend(dir) {
56802
57199
  evictIfNeeded();
56803
57200
  return null;
56804
57201
  }
56805
- const profiles = await _internals33.detectProjectLanguages(root);
57202
+ const profiles = await _internals36.detectProjectLanguages(root);
56806
57203
  if (profiles.length === 0) {
56807
57204
  cache.set(cacheKey, {
56808
57205
  hash: hash4,
@@ -56834,12 +57231,12 @@ function clearDispatchCache() {
56834
57231
  manifestRootCache.clear();
56835
57232
  insertCounter = 0;
56836
57233
  }
56837
- var _internals33, cache, insertCounter = 0, MANIFEST_FILES, _MANIFEST_SET, manifestRootCache;
57234
+ var _internals36, cache, insertCounter = 0, MANIFEST_FILES, _MANIFEST_SET, manifestRootCache;
56838
57235
  var init_dispatch = __esm(() => {
56839
57236
  init_backends();
56840
57237
  init_detector();
56841
57238
  init_registry_backend();
56842
- _internals33 = {
57239
+ _internals36 = {
56843
57240
  detectProjectLanguages,
56844
57241
  cacheCapacity: 64
56845
57242
  };
@@ -56871,14 +57268,14 @@ var init_dispatch = __esm(() => {
56871
57268
  });
56872
57269
 
56873
57270
  // src/tools/test-runner.ts
56874
- import * as fs28 from "fs";
56875
- import * as path54 from "path";
57271
+ import * as fs29 from "fs";
57272
+ import * as path55 from "path";
56876
57273
  async function estimateFanOut(sourceFiles, cwd) {
56877
57274
  try {
56878
57275
  const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
56879
57276
  const uniqueTestFiles = new Set;
56880
57277
  for (const sourceFile of sourceFiles) {
56881
- const resolvedPath = path54.resolve(cwd, sourceFile);
57278
+ const resolvedPath = path55.resolve(cwd, sourceFile);
56882
57279
  const normalizedPath = resolvedPath.replace(/\\/g, "/");
56883
57280
  const testFiles = impactMap[normalizedPath];
56884
57281
  if (testFiles) {
@@ -56960,19 +57357,19 @@ function hasDevDependency(devDeps, ...patterns) {
56960
57357
  return hasPackageJsonDependency(devDeps, ...patterns);
56961
57358
  }
56962
57359
  function detectGoTest(cwd) {
56963
- return fs28.existsSync(path54.join(cwd, "go.mod")) && isCommandAvailable("go");
57360
+ return fs29.existsSync(path55.join(cwd, "go.mod")) && isCommandAvailable("go");
56964
57361
  }
56965
57362
  function detectJavaMaven(cwd) {
56966
- return fs28.existsSync(path54.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
57363
+ return fs29.existsSync(path55.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
56967
57364
  }
56968
57365
  function detectGradle(cwd) {
56969
- const hasBuildFile = fs28.existsSync(path54.join(cwd, "build.gradle")) || fs28.existsSync(path54.join(cwd, "build.gradle.kts"));
56970
- const hasGradlew = fs28.existsSync(path54.join(cwd, "gradlew")) || fs28.existsSync(path54.join(cwd, "gradlew.bat"));
57366
+ const hasBuildFile = fs29.existsSync(path55.join(cwd, "build.gradle")) || fs29.existsSync(path55.join(cwd, "build.gradle.kts"));
57367
+ const hasGradlew = fs29.existsSync(path55.join(cwd, "gradlew")) || fs29.existsSync(path55.join(cwd, "gradlew.bat"));
56971
57368
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
56972
57369
  }
56973
57370
  function detectDotnetTest(cwd) {
56974
57371
  try {
56975
- const files = fs28.readdirSync(cwd);
57372
+ const files = fs29.readdirSync(cwd);
56976
57373
  const hasCsproj = files.some((f) => f.endsWith(".csproj"));
56977
57374
  return hasCsproj && isCommandAvailable("dotnet");
56978
57375
  } catch {
@@ -56980,25 +57377,25 @@ function detectDotnetTest(cwd) {
56980
57377
  }
56981
57378
  }
56982
57379
  function detectCTest(cwd) {
56983
- const hasSource = fs28.existsSync(path54.join(cwd, "CMakeLists.txt"));
56984
- const hasBuildCache = fs28.existsSync(path54.join(cwd, "CMakeCache.txt")) || fs28.existsSync(path54.join(cwd, "build", "CMakeCache.txt"));
57380
+ const hasSource = fs29.existsSync(path55.join(cwd, "CMakeLists.txt"));
57381
+ const hasBuildCache = fs29.existsSync(path55.join(cwd, "CMakeCache.txt")) || fs29.existsSync(path55.join(cwd, "build", "CMakeCache.txt"));
56985
57382
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
56986
57383
  }
56987
57384
  function detectSwiftTest(cwd) {
56988
- return fs28.existsSync(path54.join(cwd, "Package.swift")) && isCommandAvailable("swift");
57385
+ return fs29.existsSync(path55.join(cwd, "Package.swift")) && isCommandAvailable("swift");
56989
57386
  }
56990
57387
  function detectDartTest(cwd) {
56991
- return fs28.existsSync(path54.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
57388
+ return fs29.existsSync(path55.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
56992
57389
  }
56993
57390
  function detectRSpec(cwd) {
56994
- const hasRSpecFile = fs28.existsSync(path54.join(cwd, ".rspec"));
56995
- const hasGemfile = fs28.existsSync(path54.join(cwd, "Gemfile"));
56996
- const hasSpecDir = fs28.existsSync(path54.join(cwd, "spec"));
57391
+ const hasRSpecFile = fs29.existsSync(path55.join(cwd, ".rspec"));
57392
+ const hasGemfile = fs29.existsSync(path55.join(cwd, "Gemfile"));
57393
+ const hasSpecDir = fs29.existsSync(path55.join(cwd, "spec"));
56997
57394
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
56998
57395
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
56999
57396
  }
57000
57397
  function detectMinitest(cwd) {
57001
- return fs28.existsSync(path54.join(cwd, "test")) && (fs28.existsSync(path54.join(cwd, "Gemfile")) || fs28.existsSync(path54.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
57398
+ return fs29.existsSync(path55.join(cwd, "test")) && (fs29.existsSync(path55.join(cwd, "Gemfile")) || fs29.existsSync(path55.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
57002
57399
  }
57003
57400
  async function detectTestFrameworkViaDispatch(cwd) {
57004
57401
  try {
@@ -57061,9 +57458,9 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
57061
57458
  async function detectTestFramework(cwd) {
57062
57459
  const baseDir = cwd;
57063
57460
  try {
57064
- const packageJsonPath = path54.join(baseDir, "package.json");
57065
- if (fs28.existsSync(packageJsonPath)) {
57066
- const content = fs28.readFileSync(packageJsonPath, "utf-8");
57461
+ const packageJsonPath = path55.join(baseDir, "package.json");
57462
+ if (fs29.existsSync(packageJsonPath)) {
57463
+ const content = fs29.readFileSync(packageJsonPath, "utf-8");
57067
57464
  const pkg = JSON.parse(content);
57068
57465
  const _deps = pkg.dependencies || {};
57069
57466
  const devDeps = pkg.devDependencies || {};
@@ -57082,38 +57479,38 @@ async function detectTestFramework(cwd) {
57082
57479
  return "jest";
57083
57480
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
57084
57481
  return "mocha";
57085
- if (fs28.existsSync(path54.join(baseDir, "bun.lockb")) || fs28.existsSync(path54.join(baseDir, "bun.lock"))) {
57482
+ if (fs29.existsSync(path55.join(baseDir, "bun.lockb")) || fs29.existsSync(path55.join(baseDir, "bun.lock"))) {
57086
57483
  if (scripts.test?.includes("bun"))
57087
57484
  return "bun";
57088
57485
  }
57089
57486
  }
57090
57487
  } catch {}
57091
57488
  try {
57092
- const pyprojectTomlPath = path54.join(baseDir, "pyproject.toml");
57093
- const setupCfgPath = path54.join(baseDir, "setup.cfg");
57094
- const requirementsTxtPath = path54.join(baseDir, "requirements.txt");
57095
- if (fs28.existsSync(pyprojectTomlPath)) {
57096
- const content = fs28.readFileSync(pyprojectTomlPath, "utf-8");
57489
+ const pyprojectTomlPath = path55.join(baseDir, "pyproject.toml");
57490
+ const setupCfgPath = path55.join(baseDir, "setup.cfg");
57491
+ const requirementsTxtPath = path55.join(baseDir, "requirements.txt");
57492
+ if (fs29.existsSync(pyprojectTomlPath)) {
57493
+ const content = fs29.readFileSync(pyprojectTomlPath, "utf-8");
57097
57494
  if (content.includes("[tool.pytest"))
57098
57495
  return "pytest";
57099
57496
  if (content.includes("pytest"))
57100
57497
  return "pytest";
57101
57498
  }
57102
- if (fs28.existsSync(setupCfgPath)) {
57103
- const content = fs28.readFileSync(setupCfgPath, "utf-8");
57499
+ if (fs29.existsSync(setupCfgPath)) {
57500
+ const content = fs29.readFileSync(setupCfgPath, "utf-8");
57104
57501
  if (content.includes("[pytest]"))
57105
57502
  return "pytest";
57106
57503
  }
57107
- if (fs28.existsSync(requirementsTxtPath)) {
57108
- const content = fs28.readFileSync(requirementsTxtPath, "utf-8");
57504
+ if (fs29.existsSync(requirementsTxtPath)) {
57505
+ const content = fs29.readFileSync(requirementsTxtPath, "utf-8");
57109
57506
  if (content.includes("pytest"))
57110
57507
  return "pytest";
57111
57508
  }
57112
57509
  } catch {}
57113
57510
  try {
57114
- const cargoTomlPath = path54.join(baseDir, "Cargo.toml");
57115
- if (fs28.existsSync(cargoTomlPath)) {
57116
- const content = fs28.readFileSync(cargoTomlPath, "utf-8");
57511
+ const cargoTomlPath = path55.join(baseDir, "Cargo.toml");
57512
+ if (fs29.existsSync(cargoTomlPath)) {
57513
+ const content = fs29.readFileSync(cargoTomlPath, "utf-8");
57117
57514
  if (content.includes("[dev-dependencies]")) {
57118
57515
  if (content.includes("tokio") || content.includes("mockall") || content.includes("pretty_assertions")) {
57119
57516
  return "cargo";
@@ -57122,10 +57519,10 @@ async function detectTestFramework(cwd) {
57122
57519
  }
57123
57520
  } catch {}
57124
57521
  try {
57125
- const pesterConfigPath = path54.join(baseDir, "pester.config.ps1");
57126
- const pesterConfigJsonPath = path54.join(baseDir, "pester.config.ps1.json");
57127
- const pesterPs1Path = path54.join(baseDir, "tests.ps1");
57128
- if (fs28.existsSync(pesterConfigPath) || fs28.existsSync(pesterConfigJsonPath) || fs28.existsSync(pesterPs1Path)) {
57522
+ const pesterConfigPath = path55.join(baseDir, "pester.config.ps1");
57523
+ const pesterConfigJsonPath = path55.join(baseDir, "pester.config.ps1.json");
57524
+ const pesterPs1Path = path55.join(baseDir, "tests.ps1");
57525
+ if (fs29.existsSync(pesterConfigPath) || fs29.existsSync(pesterConfigJsonPath) || fs29.existsSync(pesterPs1Path)) {
57129
57526
  return "pester";
57130
57527
  }
57131
57528
  } catch {}
@@ -57153,12 +57550,12 @@ function isTestDirectoryPath(normalizedPath) {
57153
57550
  return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
57154
57551
  }
57155
57552
  function resolveWorkspacePath(file3, workingDir) {
57156
- return path54.isAbsolute(file3) ? path54.resolve(file3) : path54.resolve(workingDir, file3);
57553
+ return path55.isAbsolute(file3) ? path55.resolve(file3) : path55.resolve(workingDir, file3);
57157
57554
  }
57158
57555
  function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
57159
57556
  if (!preferRelative)
57160
57557
  return absolutePath;
57161
- return path54.relative(workingDir, absolutePath);
57558
+ return path55.relative(workingDir, absolutePath);
57162
57559
  }
57163
57560
  function dedupePush(target, value) {
57164
57561
  if (!target.includes(value)) {
@@ -57195,18 +57592,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
57195
57592
  }
57196
57593
  }
57197
57594
  function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
57198
- const relativeDir = path54.dirname(relativePath);
57595
+ const relativeDir = path55.dirname(relativePath);
57199
57596
  const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
57200
57597
  const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
57201
- const rootDir = path54.join(workingDir, dirName);
57202
- return nestedRelativeDir ? [rootDir, path54.join(rootDir, nestedRelativeDir)] : [rootDir];
57598
+ const rootDir = path55.join(workingDir, dirName);
57599
+ return nestedRelativeDir ? [rootDir, path55.join(rootDir, nestedRelativeDir)] : [rootDir];
57203
57600
  });
57204
57601
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
57205
57602
  if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
57206
- directories.push(path54.join(workingDir, "src/test/java", path54.dirname(normalizedRelativePath.slice("src/main/java/".length))));
57603
+ directories.push(path55.join(workingDir, "src/test/java", path55.dirname(normalizedRelativePath.slice("src/main/java/".length))));
57207
57604
  }
57208
57605
  if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
57209
- directories.push(path54.join(workingDir, "src/test/kotlin", path54.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
57606
+ directories.push(path55.join(workingDir, "src/test/kotlin", path55.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
57210
57607
  }
57211
57608
  return [...new Set(directories)];
57212
57609
  }
@@ -57234,23 +57631,23 @@ function isLanguageSpecificTestFile(basename9) {
57234
57631
  }
57235
57632
  function isConventionTestFilePath(filePath) {
57236
57633
  const normalizedPath = filePath.replace(/\\/g, "/");
57237
- const basename9 = path54.basename(filePath);
57634
+ const basename9 = path55.basename(filePath);
57238
57635
  return hasCompoundTestExtension(basename9) || basename9.includes(".spec.") || basename9.includes(".test.") || isLanguageSpecificTestFile(basename9) || isTestDirectoryPath(normalizedPath);
57239
57636
  }
57240
57637
  function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
57241
57638
  const testFiles = [];
57242
57639
  for (const file3 of sourceFiles) {
57243
57640
  const absoluteFile = resolveWorkspacePath(file3, workingDir);
57244
- const relativeFile = path54.relative(workingDir, absoluteFile);
57245
- const basename9 = path54.basename(absoluteFile);
57246
- const dirname31 = path54.dirname(absoluteFile);
57247
- const preferRelativeOutput = !path54.isAbsolute(file3);
57641
+ const relativeFile = path55.relative(workingDir, absoluteFile);
57642
+ const basename9 = path55.basename(absoluteFile);
57643
+ const dirname31 = path55.dirname(absoluteFile);
57644
+ const preferRelativeOutput = !path55.isAbsolute(file3);
57248
57645
  if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
57249
57646
  dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
57250
57647
  continue;
57251
57648
  }
57252
57649
  const nameWithoutExt = basename9.replace(/\.[^.]+$/, "");
57253
- const ext = path54.extname(basename9);
57650
+ const ext = path55.extname(basename9);
57254
57651
  const genericTestNames = [
57255
57652
  `${nameWithoutExt}.spec${ext}`,
57256
57653
  `${nameWithoutExt}.test${ext}`
@@ -57259,7 +57656,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
57259
57656
  const colocatedCandidates = [
57260
57657
  ...genericTestNames,
57261
57658
  ...languageSpecificTestNames
57262
- ].map((candidateName) => path54.join(dirname31, candidateName));
57659
+ ].map((candidateName) => path55.join(dirname31, candidateName));
57263
57660
  const testDirectoryNames = [
57264
57661
  basename9,
57265
57662
  ...genericTestNames,
@@ -57268,11 +57665,11 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
57268
57665
  const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
57269
57666
  const possibleTestFiles = [
57270
57667
  ...colocatedCandidates,
57271
- ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path54.join(dirname31, dirName, candidateName))),
57272
- ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path54.join(candidateDir, candidateName)))
57668
+ ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path55.join(dirname31, dirName, candidateName))),
57669
+ ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path55.join(candidateDir, candidateName)))
57273
57670
  ];
57274
57671
  for (const testFile of possibleTestFiles) {
57275
- if (fs28.existsSync(testFile)) {
57672
+ if (fs29.existsSync(testFile)) {
57276
57673
  dedupePush(testFiles, toWorkspaceOutputPath(testFile, workingDir, preferRelativeOutput));
57277
57674
  }
57278
57675
  }
@@ -57289,8 +57686,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
57289
57686
  for (const testFile of candidateTestFiles) {
57290
57687
  try {
57291
57688
  const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
57292
- const content = fs28.readFileSync(absoluteTestFile, "utf-8");
57293
- const testDir = path54.dirname(absoluteTestFile);
57689
+ const content = fs29.readFileSync(absoluteTestFile, "utf-8");
57690
+ const testDir = path55.dirname(absoluteTestFile);
57294
57691
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
57295
57692
  let match;
57296
57693
  match = importRegex.exec(content);
@@ -57298,8 +57695,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
57298
57695
  const importPath = match[1];
57299
57696
  let resolvedImport;
57300
57697
  if (importPath.startsWith(".")) {
57301
- resolvedImport = path54.resolve(testDir, importPath);
57302
- const existingExt = path54.extname(resolvedImport);
57698
+ resolvedImport = path55.resolve(testDir, importPath);
57699
+ const existingExt = path55.extname(resolvedImport);
57303
57700
  if (!existingExt) {
57304
57701
  for (const extToTry of [
57305
57702
  ".ts",
@@ -57310,7 +57707,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
57310
57707
  ".cjs"
57311
57708
  ]) {
57312
57709
  const withExt = resolvedImport + extToTry;
57313
- if (absoluteSourceFiles.includes(withExt) || fs28.existsSync(withExt)) {
57710
+ if (absoluteSourceFiles.includes(withExt) || fs29.existsSync(withExt)) {
57314
57711
  resolvedImport = withExt;
57315
57712
  break;
57316
57713
  }
@@ -57319,12 +57716,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
57319
57716
  } else {
57320
57717
  continue;
57321
57718
  }
57322
- const importBasename = path54.basename(resolvedImport, path54.extname(resolvedImport));
57323
- const importDir = path54.dirname(resolvedImport);
57719
+ const importBasename = path55.basename(resolvedImport, path55.extname(resolvedImport));
57720
+ const importDir = path55.dirname(resolvedImport);
57324
57721
  for (const sourceFile of absoluteSourceFiles) {
57325
- const sourceDir = path54.dirname(sourceFile);
57326
- const sourceBasename = path54.basename(sourceFile, path54.extname(sourceFile));
57327
- const isRelatedDir = importDir === sourceDir || importDir === path54.join(sourceDir, "__tests__") || importDir === path54.join(sourceDir, "tests") || importDir === path54.join(sourceDir, "test") || importDir === path54.join(sourceDir, "spec");
57722
+ const sourceDir = path55.dirname(sourceFile);
57723
+ const sourceBasename = path55.basename(sourceFile, path55.extname(sourceFile));
57724
+ const isRelatedDir = importDir === sourceDir || importDir === path55.join(sourceDir, "__tests__") || importDir === path55.join(sourceDir, "tests") || importDir === path55.join(sourceDir, "test") || importDir === path55.join(sourceDir, "spec");
57328
57725
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
57329
57726
  dedupePush(testFiles, testFile);
57330
57727
  break;
@@ -57337,8 +57734,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
57337
57734
  while (match !== null) {
57338
57735
  const importPath = match[1];
57339
57736
  if (importPath.startsWith(".")) {
57340
- let resolvedImport = path54.resolve(testDir, importPath);
57341
- const existingExt = path54.extname(resolvedImport);
57737
+ let resolvedImport = path55.resolve(testDir, importPath);
57738
+ const existingExt = path55.extname(resolvedImport);
57342
57739
  if (!existingExt) {
57343
57740
  for (const extToTry of [
57344
57741
  ".ts",
@@ -57349,18 +57746,18 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
57349
57746
  ".cjs"
57350
57747
  ]) {
57351
57748
  const withExt = resolvedImport + extToTry;
57352
- if (absoluteSourceFiles.includes(withExt) || fs28.existsSync(withExt)) {
57749
+ if (absoluteSourceFiles.includes(withExt) || fs29.existsSync(withExt)) {
57353
57750
  resolvedImport = withExt;
57354
57751
  break;
57355
57752
  }
57356
57753
  }
57357
57754
  }
57358
- const importDir = path54.dirname(resolvedImport);
57359
- const importBasename = path54.basename(resolvedImport, path54.extname(resolvedImport));
57755
+ const importDir = path55.dirname(resolvedImport);
57756
+ const importBasename = path55.basename(resolvedImport, path55.extname(resolvedImport));
57360
57757
  for (const sourceFile of absoluteSourceFiles) {
57361
- const sourceDir = path54.dirname(sourceFile);
57362
- const sourceBasename = path54.basename(sourceFile, path54.extname(sourceFile));
57363
- const isRelatedDir = importDir === sourceDir || importDir === path54.join(sourceDir, "__tests__") || importDir === path54.join(sourceDir, "tests") || importDir === path54.join(sourceDir, "test") || importDir === path54.join(sourceDir, "spec");
57758
+ const sourceDir = path55.dirname(sourceFile);
57759
+ const sourceBasename = path55.basename(sourceFile, path55.extname(sourceFile));
57760
+ const isRelatedDir = importDir === sourceDir || importDir === path55.join(sourceDir, "__tests__") || importDir === path55.join(sourceDir, "tests") || importDir === path55.join(sourceDir, "test") || importDir === path55.join(sourceDir, "spec");
57364
57761
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
57365
57762
  dedupePush(testFiles, testFile);
57366
57763
  break;
@@ -57480,8 +57877,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir, bail) {
57480
57877
  return ["mvn", "test"];
57481
57878
  case "gradle": {
57482
57879
  const isWindows = process.platform === "win32";
57483
- const hasGradlewBat = fs28.existsSync(path54.join(baseDir, "gradlew.bat"));
57484
- const hasGradlew = fs28.existsSync(path54.join(baseDir, "gradlew"));
57880
+ const hasGradlewBat = fs29.existsSync(path55.join(baseDir, "gradlew.bat"));
57881
+ const hasGradlew = fs29.existsSync(path55.join(baseDir, "gradlew"));
57485
57882
  if (hasGradlewBat && isWindows)
57486
57883
  return ["gradlew.bat", "test"];
57487
57884
  if (hasGradlew)
@@ -57498,7 +57895,7 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir, bail) {
57498
57895
  "cmake-build-release",
57499
57896
  "out"
57500
57897
  ];
57501
- const actualBuildDir = buildDirCandidates.find((d) => fs28.existsSync(path54.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
57898
+ const actualBuildDir = buildDirCandidates.find((d) => fs29.existsSync(path55.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
57502
57899
  return ["ctest", "--test-dir", actualBuildDir];
57503
57900
  }
57504
57901
  case "swift-test":
@@ -57932,13 +58329,13 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
57932
58329
  };
57933
58330
  }
57934
58331
  const startTime = Date.now();
57935
- const vitestJsonOutputPath = framework === "vitest" ? path54.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
58332
+ const vitestJsonOutputPath = framework === "vitest" ? path55.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
57936
58333
  try {
57937
58334
  if (vitestJsonOutputPath) {
57938
58335
  try {
57939
- fs28.mkdirSync(path54.dirname(vitestJsonOutputPath), { recursive: true });
57940
- if (fs28.existsSync(vitestJsonOutputPath)) {
57941
- fs28.unlinkSync(vitestJsonOutputPath);
58336
+ fs29.mkdirSync(path55.dirname(vitestJsonOutputPath), { recursive: true });
58337
+ if (fs29.existsSync(vitestJsonOutputPath)) {
58338
+ fs29.unlinkSync(vitestJsonOutputPath);
57942
58339
  }
57943
58340
  } catch {}
57944
58341
  }
@@ -57947,9 +58344,9 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
57947
58344
  stderr: "pipe",
57948
58345
  cwd
57949
58346
  });
57950
- const timeoutPromise = new Promise((resolve19) => setTimeout(() => {
58347
+ const timeoutPromise = new Promise((resolve20) => setTimeout(() => {
57951
58348
  proc.kill();
57952
- resolve19(-1);
58349
+ resolve20(-1);
57953
58350
  }, timeout_ms));
57954
58351
  const [exitCode, stdoutResult, stderrResult] = await Promise.all([
57955
58352
  Promise.race([proc.exited, timeoutPromise]),
@@ -57964,8 +58361,8 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
57964
58361
  }
57965
58362
  if (vitestJsonOutputPath) {
57966
58363
  try {
57967
- if (fs28.existsSync(vitestJsonOutputPath)) {
57968
- const vitestJsonOutput = fs28.readFileSync(vitestJsonOutputPath, "utf-8");
58364
+ if (fs29.existsSync(vitestJsonOutputPath)) {
58365
+ const vitestJsonOutput = fs29.readFileSync(vitestJsonOutputPath, "utf-8");
57969
58366
  if (vitestJsonOutput.trim().length > 0) {
57970
58367
  output += (output ? `
57971
58368
  ` : "") + vitestJsonOutput;
@@ -58052,10 +58449,10 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
58052
58449
  }
58053
58450
  function normalizeHistoryTestFile(testFile, workingDir) {
58054
58451
  const normalized = testFile.replace(/\\/g, "/");
58055
- if (!path54.isAbsolute(testFile))
58452
+ if (!path55.isAbsolute(testFile))
58056
58453
  return normalized;
58057
- const relative11 = path54.relative(workingDir, testFile);
58058
- if (relative11.startsWith("..") || path54.isAbsolute(relative11)) {
58454
+ const relative11 = path55.relative(workingDir, testFile);
58455
+ if (relative11.startsWith("..") || path55.isAbsolute(relative11)) {
58059
58456
  return normalized;
58060
58457
  }
58061
58458
  return relative11.replace(/\\/g, "/");
@@ -58393,7 +58790,7 @@ var init_test_runner = __esm(() => {
58393
58790
  const sourceFiles = args.files.filter((file3) => {
58394
58791
  if (directTestFiles.includes(file3))
58395
58792
  return false;
58396
- const ext = path54.extname(file3).toLowerCase();
58793
+ const ext = path55.extname(file3).toLowerCase();
58397
58794
  return SOURCE_EXTENSIONS.has(ext);
58398
58795
  });
58399
58796
  const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
@@ -58439,7 +58836,7 @@ var init_test_runner = __esm(() => {
58439
58836
  if (isConventionTestFilePath(f)) {
58440
58837
  return false;
58441
58838
  }
58442
- const ext = path54.extname(f).toLowerCase();
58839
+ const ext = path55.extname(f).toLowerCase();
58443
58840
  return SOURCE_EXTENSIONS.has(ext);
58444
58841
  });
58445
58842
  if (sourceFiles.length === 0) {
@@ -58489,7 +58886,7 @@ var init_test_runner = __esm(() => {
58489
58886
  if (isConventionTestFilePath(f)) {
58490
58887
  return false;
58491
58888
  }
58492
- const ext = path54.extname(f).toLowerCase();
58889
+ const ext = path55.extname(f).toLowerCase();
58493
58890
  return SOURCE_EXTENSIONS.has(ext);
58494
58891
  });
58495
58892
  if (sourceFiles.length === 0) {
@@ -58541,8 +58938,8 @@ var init_test_runner = __esm(() => {
58541
58938
  }
58542
58939
  if (impactResult.impactedTests.length > 0) {
58543
58940
  testFiles = impactResult.impactedTests.map((absPath) => {
58544
- const relativePath = path54.relative(workingDir, absPath);
58545
- return path54.isAbsolute(relativePath) ? absPath : relativePath;
58941
+ const relativePath = path55.relative(workingDir, absPath);
58942
+ return path55.isAbsolute(relativePath) ? absPath : relativePath;
58546
58943
  });
58547
58944
  } else {
58548
58945
  graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
@@ -58620,8 +59017,8 @@ var init_test_runner = __esm(() => {
58620
59017
  });
58621
59018
 
58622
59019
  // src/services/preflight-service.ts
58623
- import * as fs29 from "fs";
58624
- import * as path55 from "path";
59020
+ import * as fs30 from "fs";
59021
+ import * as path56 from "path";
58625
59022
  function validateDirectoryPath(dir) {
58626
59023
  if (!dir || typeof dir !== "string") {
58627
59024
  throw new Error("Directory path is required");
@@ -58629,8 +59026,8 @@ function validateDirectoryPath(dir) {
58629
59026
  if (dir.includes("..")) {
58630
59027
  throw new Error("Directory path must not contain path traversal sequences");
58631
59028
  }
58632
- const normalized = path55.normalize(dir);
58633
- const absolutePath = path55.isAbsolute(normalized) ? normalized : path55.resolve(normalized);
59029
+ const normalized = path56.normalize(dir);
59030
+ const absolutePath = path56.isAbsolute(normalized) ? normalized : path56.resolve(normalized);
58634
59031
  return absolutePath;
58635
59032
  }
58636
59033
  function validateTimeout(timeoutMs, defaultValue) {
@@ -58653,9 +59050,9 @@ function validateTimeout(timeoutMs, defaultValue) {
58653
59050
  }
58654
59051
  function getPackageVersion(dir) {
58655
59052
  try {
58656
- const packagePath = path55.join(dir, "package.json");
58657
- if (fs29.existsSync(packagePath)) {
58658
- const content = fs29.readFileSync(packagePath, "utf-8");
59053
+ const packagePath = path56.join(dir, "package.json");
59054
+ if (fs30.existsSync(packagePath)) {
59055
+ const content = fs30.readFileSync(packagePath, "utf-8");
58659
59056
  const pkg = JSON.parse(content);
58660
59057
  return pkg.version ?? null;
58661
59058
  }
@@ -58664,9 +59061,9 @@ function getPackageVersion(dir) {
58664
59061
  }
58665
59062
  function getChangelogVersion(dir) {
58666
59063
  try {
58667
- const changelogPath = path55.join(dir, "CHANGELOG.md");
58668
- if (fs29.existsSync(changelogPath)) {
58669
- const content = fs29.readFileSync(changelogPath, "utf-8");
59064
+ const changelogPath = path56.join(dir, "CHANGELOG.md");
59065
+ if (fs30.existsSync(changelogPath)) {
59066
+ const content = fs30.readFileSync(changelogPath, "utf-8");
58670
59067
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
58671
59068
  if (match) {
58672
59069
  return match[1];
@@ -58678,10 +59075,10 @@ function getChangelogVersion(dir) {
58678
59075
  function getVersionFileVersion(dir) {
58679
59076
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
58680
59077
  for (const file3 of possibleFiles) {
58681
- const filePath = path55.join(dir, file3);
58682
- if (fs29.existsSync(filePath)) {
59078
+ const filePath = path56.join(dir, file3);
59079
+ if (fs30.existsSync(filePath)) {
58683
59080
  try {
58684
- const content = fs29.readFileSync(filePath, "utf-8").trim();
59081
+ const content = fs30.readFileSync(filePath, "utf-8").trim();
58685
59082
  const match = content.match(/(\d+\.\d+\.\d+)/);
58686
59083
  if (match) {
58687
59084
  return match[1];
@@ -58694,9 +59091,9 @@ function getVersionFileVersion(dir) {
58694
59091
  async function runVersionCheck(dir, _timeoutMs) {
58695
59092
  const startTime = Date.now();
58696
59093
  try {
58697
- const packageVersion = _internals34.getPackageVersion(dir);
58698
- const changelogVersion = _internals34.getChangelogVersion(dir);
58699
- const versionFileVersion = _internals34.getVersionFileVersion(dir);
59094
+ const packageVersion = _internals37.getPackageVersion(dir);
59095
+ const changelogVersion = _internals37.getChangelogVersion(dir);
59096
+ const versionFileVersion = _internals37.getVersionFileVersion(dir);
58700
59097
  const versions3 = [];
58701
59098
  if (packageVersion)
58702
59099
  versions3.push(`package.json: ${packageVersion}`);
@@ -59060,7 +59457,7 @@ async function runPreflight(dir, phase, config3) {
59060
59457
  const reportId = `preflight-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
59061
59458
  let validatedDir;
59062
59459
  try {
59063
- validatedDir = _internals34.validateDirectoryPath(dir);
59460
+ validatedDir = _internals37.validateDirectoryPath(dir);
59064
59461
  } catch (error93) {
59065
59462
  return {
59066
59463
  id: reportId,
@@ -59080,7 +59477,7 @@ async function runPreflight(dir, phase, config3) {
59080
59477
  }
59081
59478
  let validatedTimeout;
59082
59479
  try {
59083
- validatedTimeout = _internals34.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
59480
+ validatedTimeout = _internals37.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
59084
59481
  } catch (error93) {
59085
59482
  return {
59086
59483
  id: reportId,
@@ -59121,12 +59518,12 @@ async function runPreflight(dir, phase, config3) {
59121
59518
  });
59122
59519
  const checks5 = [];
59123
59520
  log("[Preflight] Running lint check...");
59124
- const lintResult = await _internals34.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
59521
+ const lintResult = await _internals37.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
59125
59522
  checks5.push(lintResult);
59126
59523
  log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`);
59127
59524
  if (!cfg.skipTests) {
59128
59525
  log("[Preflight] Running tests check...");
59129
- const testsResult = await _internals34.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
59526
+ const testsResult = await _internals37.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
59130
59527
  checks5.push(testsResult);
59131
59528
  log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`);
59132
59529
  } else {
@@ -59138,7 +59535,7 @@ async function runPreflight(dir, phase, config3) {
59138
59535
  }
59139
59536
  if (!cfg.skipSecrets) {
59140
59537
  log("[Preflight] Running secrets check...");
59141
- const secretsResult = await _internals34.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
59538
+ const secretsResult = await _internals37.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
59142
59539
  checks5.push(secretsResult);
59143
59540
  log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`);
59144
59541
  } else {
@@ -59150,7 +59547,7 @@ async function runPreflight(dir, phase, config3) {
59150
59547
  }
59151
59548
  if (!cfg.skipEvidence) {
59152
59549
  log("[Preflight] Running evidence check...");
59153
- const evidenceResult = await _internals34.runEvidenceCheck(validatedDir);
59550
+ const evidenceResult = await _internals37.runEvidenceCheck(validatedDir);
59154
59551
  checks5.push(evidenceResult);
59155
59552
  log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`);
59156
59553
  } else {
@@ -59161,12 +59558,12 @@ async function runPreflight(dir, phase, config3) {
59161
59558
  });
59162
59559
  }
59163
59560
  log("[Preflight] Running requirement coverage check...");
59164
- const reqCoverageResult = await _internals34.runRequirementCoverageCheck(validatedDir, phase);
59561
+ const reqCoverageResult = await _internals37.runRequirementCoverageCheck(validatedDir, phase);
59165
59562
  checks5.push(reqCoverageResult);
59166
59563
  log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`);
59167
59564
  if (!cfg.skipVersion) {
59168
59565
  log("[Preflight] Running version check...");
59169
- const versionResult = await _internals34.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
59566
+ const versionResult = await _internals37.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
59170
59567
  checks5.push(versionResult);
59171
59568
  log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`);
59172
59569
  } else {
@@ -59229,10 +59626,10 @@ function formatPreflightMarkdown(report) {
59229
59626
  async function handlePreflightCommand(directory, _args) {
59230
59627
  const plan = await loadPlan(directory);
59231
59628
  const phase = plan?.current_phase ?? 1;
59232
- const report = await _internals34.runPreflight(directory, phase);
59233
- return _internals34.formatPreflightMarkdown(report);
59629
+ const report = await _internals37.runPreflight(directory, phase);
59630
+ return _internals37.formatPreflightMarkdown(report);
59234
59631
  }
59235
- var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG, _internals34;
59632
+ var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG, _internals37;
59236
59633
  var init_preflight_service = __esm(() => {
59237
59634
  init_gate_bridge();
59238
59635
  init_manager2();
@@ -59251,7 +59648,7 @@ var init_preflight_service = __esm(() => {
59251
59648
  testScope: "convention",
59252
59649
  linter: "biome"
59253
59650
  };
59254
- _internals34 = {
59651
+ _internals37 = {
59255
59652
  runPreflight,
59256
59653
  formatPreflightMarkdown,
59257
59654
  handlePreflightCommand,
@@ -59499,13 +59896,13 @@ class CircuitBreaker {
59499
59896
  if (this.config.callTimeoutMs <= 0) {
59500
59897
  return fn();
59501
59898
  }
59502
- return new Promise((resolve20, reject) => {
59899
+ return new Promise((resolve21, reject) => {
59503
59900
  const timeout = setTimeout(() => {
59504
59901
  reject(new Error(`Call timeout after ${this.config.callTimeoutMs}ms`));
59505
59902
  }, this.config.callTimeoutMs);
59506
59903
  fn().then((result) => {
59507
59904
  clearTimeout(timeout);
59508
- resolve20(result);
59905
+ resolve21(result);
59509
59906
  }).catch((error93) => {
59510
59907
  clearTimeout(timeout);
59511
59908
  reject(error93);
@@ -59792,7 +60189,7 @@ var init_queue = __esm(() => {
59792
60189
 
59793
60190
  // src/background/worker.ts
59794
60191
  function sleep(ms) {
59795
- return new Promise((resolve20) => setTimeout(resolve20, ms));
60192
+ return new Promise((resolve21) => setTimeout(resolve21, ms));
59796
60193
  }
59797
60194
 
59798
60195
  class WorkerManager {
@@ -60137,8 +60534,8 @@ var init_manager3 = __esm(() => {
60137
60534
  });
60138
60535
 
60139
60536
  // src/commands/reset.ts
60140
- import * as fs30 from "fs";
60141
- import * as path56 from "path";
60537
+ import * as fs31 from "fs";
60538
+ import * as path57 from "path";
60142
60539
  async function handleResetCommand(directory, args) {
60143
60540
  const hasConfirm = args.includes("--confirm");
60144
60541
  if (!hasConfirm) {
@@ -60166,8 +60563,8 @@ async function handleResetCommand(directory, args) {
60166
60563
  for (const filename of filesToReset) {
60167
60564
  try {
60168
60565
  const resolvedPath = validateSwarmPath(directory, filename);
60169
- if (fs30.existsSync(resolvedPath)) {
60170
- fs30.unlinkSync(resolvedPath);
60566
+ if (fs31.existsSync(resolvedPath)) {
60567
+ fs31.unlinkSync(resolvedPath);
60171
60568
  results.push(`- \u2705 Deleted ${filename}`);
60172
60569
  } else {
60173
60570
  results.push(`- \u23ED\uFE0F ${filename} not found (skipped)`);
@@ -60178,9 +60575,9 @@ async function handleResetCommand(directory, args) {
60178
60575
  }
60179
60576
  for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
60180
60577
  try {
60181
- const rootPath = path56.join(directory, filename);
60182
- if (fs30.existsSync(rootPath)) {
60183
- fs30.unlinkSync(rootPath);
60578
+ const rootPath = path57.join(directory, filename);
60579
+ if (fs31.existsSync(rootPath)) {
60580
+ fs31.unlinkSync(rootPath);
60184
60581
  results.push(`- \u2705 Deleted ${filename} (root)`);
60185
60582
  }
60186
60583
  } catch {}
@@ -60193,8 +60590,8 @@ async function handleResetCommand(directory, args) {
60193
60590
  }
60194
60591
  try {
60195
60592
  const summariesPath = validateSwarmPath(directory, "summaries");
60196
- if (fs30.existsSync(summariesPath)) {
60197
- fs30.rmSync(summariesPath, { recursive: true, force: true });
60593
+ if (fs31.existsSync(summariesPath)) {
60594
+ fs31.rmSync(summariesPath, { recursive: true, force: true });
60198
60595
  results.push("- \u2705 Deleted summaries/ directory");
60199
60596
  } else {
60200
60597
  results.push("- \u23ED\uFE0F summaries/ not found (skipped)");
@@ -60217,14 +60614,14 @@ var init_reset = __esm(() => {
60217
60614
  });
60218
60615
 
60219
60616
  // src/commands/reset-session.ts
60220
- import * as fs31 from "fs";
60221
- import * as path57 from "path";
60617
+ import * as fs32 from "fs";
60618
+ import * as path58 from "path";
60222
60619
  async function handleResetSessionCommand(directory, _args) {
60223
60620
  const results = [];
60224
60621
  try {
60225
60622
  const statePath = validateSwarmPath(directory, "session/state.json");
60226
- if (fs31.existsSync(statePath)) {
60227
- fs31.unlinkSync(statePath);
60623
+ if (fs32.existsSync(statePath)) {
60624
+ fs32.unlinkSync(statePath);
60228
60625
  results.push("\u2705 Deleted .swarm/session/state.json");
60229
60626
  } else {
60230
60627
  results.push("\u23ED\uFE0F state.json not found (already clean)");
@@ -60233,15 +60630,15 @@ async function handleResetSessionCommand(directory, _args) {
60233
60630
  results.push("\u274C Failed to delete state.json");
60234
60631
  }
60235
60632
  try {
60236
- const sessionDir = path57.dirname(validateSwarmPath(directory, "session/state.json"));
60237
- if (fs31.existsSync(sessionDir)) {
60238
- const files = fs31.readdirSync(sessionDir);
60633
+ const sessionDir = path58.dirname(validateSwarmPath(directory, "session/state.json"));
60634
+ if (fs32.existsSync(sessionDir)) {
60635
+ const files = fs32.readdirSync(sessionDir);
60239
60636
  const otherFiles = files.filter((f) => f !== "state.json");
60240
60637
  let deletedCount = 0;
60241
60638
  for (const file3 of otherFiles) {
60242
- const filePath = path57.join(sessionDir, file3);
60243
- if (fs31.lstatSync(filePath).isFile()) {
60244
- fs31.unlinkSync(filePath);
60639
+ const filePath = path58.join(sessionDir, file3);
60640
+ if (fs32.lstatSync(filePath).isFile()) {
60641
+ fs32.unlinkSync(filePath);
60245
60642
  deletedCount++;
60246
60643
  }
60247
60644
  }
@@ -60271,7 +60668,7 @@ var init_reset_session = __esm(() => {
60271
60668
  });
60272
60669
 
60273
60670
  // src/summaries/manager.ts
60274
- import * as path58 from "path";
60671
+ import * as path59 from "path";
60275
60672
  function sanitizeSummaryId(id) {
60276
60673
  if (!id || id.length === 0) {
60277
60674
  throw new Error("Invalid summary ID: empty string");
@@ -60294,7 +60691,7 @@ function sanitizeSummaryId(id) {
60294
60691
  }
60295
60692
  async function loadFullOutput(directory, id) {
60296
60693
  const sanitizedId = sanitizeSummaryId(id);
60297
- const relativePath = path58.join("summaries", `${sanitizedId}.json`);
60694
+ const relativePath = path59.join("summaries", `${sanitizedId}.json`);
60298
60695
  validateSwarmPath(directory, relativePath);
60299
60696
  const content = await readSwarmFileAsync(directory, relativePath);
60300
60697
  if (content === null) {
@@ -60356,18 +60753,18 @@ var init_retrieve = __esm(() => {
60356
60753
  });
60357
60754
 
60358
60755
  // src/commands/rollback.ts
60359
- import * as fs32 from "fs";
60360
- import * as path59 from "path";
60756
+ import * as fs33 from "fs";
60757
+ import * as path60 from "path";
60361
60758
  async function handleRollbackCommand(directory, args) {
60362
60759
  const phaseArg = args[0];
60363
60760
  if (!phaseArg) {
60364
60761
  const manifestPath2 = validateSwarmPath(directory, "checkpoints/manifest.json");
60365
- if (!fs32.existsSync(manifestPath2)) {
60762
+ if (!fs33.existsSync(manifestPath2)) {
60366
60763
  return "No checkpoints found. Use `/swarm checkpoint` to create checkpoints.";
60367
60764
  }
60368
60765
  let manifest2;
60369
60766
  try {
60370
- manifest2 = JSON.parse(fs32.readFileSync(manifestPath2, "utf-8"));
60767
+ manifest2 = JSON.parse(fs33.readFileSync(manifestPath2, "utf-8"));
60371
60768
  } catch {
60372
60769
  return "Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.";
60373
60770
  }
@@ -60389,12 +60786,12 @@ async function handleRollbackCommand(directory, args) {
60389
60786
  return "Error: Phase number must be a positive integer.";
60390
60787
  }
60391
60788
  const manifestPath = validateSwarmPath(directory, "checkpoints/manifest.json");
60392
- if (!fs32.existsSync(manifestPath)) {
60789
+ if (!fs33.existsSync(manifestPath)) {
60393
60790
  return `Error: No checkpoints found. Cannot rollback to phase ${targetPhase}.`;
60394
60791
  }
60395
60792
  let manifest;
60396
60793
  try {
60397
- manifest = JSON.parse(fs32.readFileSync(manifestPath, "utf-8"));
60794
+ manifest = JSON.parse(fs33.readFileSync(manifestPath, "utf-8"));
60398
60795
  } catch {
60399
60796
  return `Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.`;
60400
60797
  }
@@ -60404,10 +60801,10 @@ async function handleRollbackCommand(directory, args) {
60404
60801
  return `Error: Checkpoint for phase ${targetPhase} not found. Available phases: ${available}`;
60405
60802
  }
60406
60803
  const checkpointDir = validateSwarmPath(directory, `checkpoints/phase-${targetPhase}`);
60407
- if (!fs32.existsSync(checkpointDir)) {
60804
+ if (!fs33.existsSync(checkpointDir)) {
60408
60805
  return `Error: Checkpoint directory for phase ${targetPhase} does not exist.`;
60409
60806
  }
60410
- const checkpointFiles = fs32.readdirSync(checkpointDir);
60807
+ const checkpointFiles = fs33.readdirSync(checkpointDir);
60411
60808
  if (checkpointFiles.length === 0) {
60412
60809
  return `Error: Checkpoint for phase ${targetPhase} is empty. Cannot rollback.`;
60413
60810
  }
@@ -60422,10 +60819,10 @@ async function handleRollbackCommand(directory, args) {
60422
60819
  if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
60423
60820
  continue;
60424
60821
  }
60425
- const src = path59.join(checkpointDir, file3);
60426
- const dest = path59.join(swarmDir, file3);
60822
+ const src = path60.join(checkpointDir, file3);
60823
+ const dest = path60.join(swarmDir, file3);
60427
60824
  try {
60428
- fs32.cpSync(src, dest, { recursive: true, force: true });
60825
+ fs33.cpSync(src, dest, { recursive: true, force: true });
60429
60826
  successes.push(file3);
60430
60827
  } catch (error93) {
60431
60828
  failures.push({ file: file3, error: error93.message });
@@ -60442,14 +60839,14 @@ async function handleRollbackCommand(directory, args) {
60442
60839
  ].join(`
60443
60840
  `);
60444
60841
  }
60445
- const existingLedgerPath = path59.join(swarmDir, "plan-ledger.jsonl");
60446
- if (fs32.existsSync(existingLedgerPath)) {
60447
- fs32.unlinkSync(existingLedgerPath);
60842
+ const existingLedgerPath = path60.join(swarmDir, "plan-ledger.jsonl");
60843
+ if (fs33.existsSync(existingLedgerPath)) {
60844
+ fs33.unlinkSync(existingLedgerPath);
60448
60845
  }
60449
60846
  try {
60450
- const planJsonPath = path59.join(swarmDir, "plan.json");
60451
- if (fs32.existsSync(planJsonPath)) {
60452
- const planRaw = fs32.readFileSync(planJsonPath, "utf-8");
60847
+ const planJsonPath = path60.join(swarmDir, "plan.json");
60848
+ if (fs33.existsSync(planJsonPath)) {
60849
+ const planRaw = fs33.readFileSync(planJsonPath, "utf-8");
60453
60850
  const plan = PlanSchema.parse(JSON.parse(planRaw));
60454
60851
  const planId = derivePlanId(plan);
60455
60852
  const planHash = computePlanHash(plan);
@@ -60476,7 +60873,7 @@ async function handleRollbackCommand(directory, args) {
60476
60873
  timestamp: new Date().toISOString()
60477
60874
  };
60478
60875
  try {
60479
- fs32.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
60876
+ fs33.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
60480
60877
  `);
60481
60878
  } catch (error93) {
60482
60879
  console.error("Failed to write rollback event:", error93 instanceof Error ? error93.message : String(error93));
@@ -60705,11 +61102,11 @@ Ensure this is a git repository with commit history.`;
60705
61102
  const report = reportLines.filter(Boolean).join(`
60706
61103
  `);
60707
61104
  try {
60708
- const fs33 = await import("fs/promises");
60709
- const path60 = await import("path");
60710
- const reportPath = path60.join(directory, ".swarm", "simulate-report.md");
60711
- await fs33.mkdir(path60.dirname(reportPath), { recursive: true });
60712
- await fs33.writeFile(reportPath, report, "utf-8");
61105
+ const fs34 = await import("fs/promises");
61106
+ const path61 = await import("path");
61107
+ const reportPath = path61.join(directory, ".swarm", "simulate-report.md");
61108
+ await fs34.mkdir(path61.dirname(reportPath), { recursive: true });
61109
+ await fs34.writeFile(reportPath, report, "utf-8");
60713
61110
  } catch (err) {
60714
61111
  const writeErr = err instanceof Error ? err.message : String(err);
60715
61112
  warn(`simulate: failed to write report to ${directory}/.swarm/simulate-report.md`, writeErr);
@@ -60763,15 +61160,15 @@ var init_knowledge_escalator = __esm(() => {
60763
61160
  });
60764
61161
 
60765
61162
  // src/turbo/lean/state.ts
60766
- import * as fs33 from "fs";
60767
- import * as path60 from "path";
61163
+ import * as fs34 from "fs";
61164
+ import * as path61 from "path";
60768
61165
  function nowISO2() {
60769
61166
  return new Date().toISOString();
60770
61167
  }
60771
- function ensureSwarmDir2(directory) {
60772
- const swarmDir = path60.resolve(directory, ".swarm");
60773
- if (!fs33.existsSync(swarmDir)) {
60774
- fs33.mkdirSync(swarmDir, { recursive: true });
61168
+ function ensureSwarmDir3(directory) {
61169
+ const swarmDir = path61.resolve(directory, ".swarm");
61170
+ if (!fs34.existsSync(swarmDir)) {
61171
+ fs34.mkdirSync(swarmDir, { recursive: true });
60775
61172
  }
60776
61173
  return swarmDir;
60777
61174
  }
@@ -60813,17 +61210,17 @@ function markStateUnreadable2(directory, reason) {
60813
61210
  }
60814
61211
  function readPersisted2(directory) {
60815
61212
  try {
60816
- const filePath = path60.join(directory, ".swarm", STATE_FILE2);
60817
- if (!fs33.existsSync(filePath)) {
61213
+ const filePath = path61.join(directory, ".swarm", STATE_FILE2);
61214
+ if (!fs34.existsSync(filePath)) {
60818
61215
  const seed = emptyPersisted2();
60819
61216
  try {
60820
- ensureSwarmDir2(directory);
60821
- fs33.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
61217
+ ensureSwarmDir3(directory);
61218
+ fs34.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
60822
61219
  `, "utf-8");
60823
61220
  } catch {}
60824
61221
  return seed;
60825
61222
  }
60826
- const raw = fs33.readFileSync(filePath, "utf-8");
61223
+ const raw = fs34.readFileSync(filePath, "utf-8");
60827
61224
  const parsed = JSON.parse(raw);
60828
61225
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || parsed.version !== 1 || !parsed.sessions || typeof parsed.sessions !== "object" || Array.isArray(parsed.sessions)) {
60829
61226
  markStateUnreadable2(directory, `malformed shape (version=${parsed?.version}, sessions type=${Array.isArray(parsed?.sessions) ? "array" : typeof parsed?.sessions})`);
@@ -60848,8 +61245,8 @@ function writePersisted2(directory, persisted) {
60848
61245
  let tmpPath;
60849
61246
  let payload;
60850
61247
  try {
60851
- ensureSwarmDir2(directory);
60852
- filePath = path60.join(directory, ".swarm", STATE_FILE2);
61248
+ ensureSwarmDir3(directory);
61249
+ filePath = path61.join(directory, ".swarm", STATE_FILE2);
60853
61250
  tmpPath = `${filePath}.tmp.${Date.now()}`;
60854
61251
  persisted.updatedAt = nowISO2();
60855
61252
  payload = `${JSON.stringify(persisted, null, 2)}
@@ -60860,14 +61257,14 @@ function writePersisted2(directory, persisted) {
60860
61257
  throw new Error(`Lean Turbo state persistence prepare failed: ${msg}`);
60861
61258
  }
60862
61259
  try {
60863
- fs33.writeFileSync(tmpPath, payload, "utf-8");
60864
- fs33.renameSync(tmpPath, filePath);
61260
+ fs34.writeFileSync(tmpPath, payload, "utf-8");
61261
+ fs34.renameSync(tmpPath, filePath);
60865
61262
  } catch (error93) {
60866
61263
  const msg = error93 instanceof Error ? error93.message : String(error93);
60867
61264
  error(`[turbo/lean/state] Failed to persist ${STATE_FILE2} atomically: ${msg}`);
60868
61265
  try {
60869
- if (fs33.existsSync(tmpPath)) {
60870
- fs33.unlinkSync(tmpPath);
61266
+ if (fs34.existsSync(tmpPath)) {
61267
+ fs34.unlinkSync(tmpPath);
60871
61268
  }
60872
61269
  } catch {}
60873
61270
  throw new Error(`Lean Turbo state persistence failed: ${msg}`);
@@ -60976,10 +61373,10 @@ var init_context_budget_service = __esm(() => {
60976
61373
 
60977
61374
  // src/services/status-service.ts
60978
61375
  import * as fsSync3 from "fs";
60979
- import * as path61 from "path";
61376
+ import * as path62 from "path";
60980
61377
  function readSpecStalenessSnapshot(directory) {
60981
61378
  try {
60982
- const p = path61.join(directory, ".swarm", "spec-staleness.json");
61379
+ const p = path62.join(directory, ".swarm", "spec-staleness.json");
60983
61380
  if (!fsSync3.existsSync(p))
60984
61381
  return { stale: false };
60985
61382
  const raw = fsSync3.readFileSync(p, "utf-8");
@@ -61074,7 +61471,7 @@ async function getStatusData(directory, agents) {
61074
61471
  }
61075
61472
  function enrichWithLeanTurbo(status, directory) {
61076
61473
  const turboMode = hasActiveTurboMode();
61077
- const leanActive = _internals35.hasActiveLeanTurbo();
61474
+ const leanActive = _internals38.hasActiveLeanTurbo();
61078
61475
  let turboStrategy = "off";
61079
61476
  if (leanActive) {
61080
61477
  turboStrategy = "lean";
@@ -61093,7 +61490,7 @@ function enrichWithLeanTurbo(status, directory) {
61093
61490
  }
61094
61491
  }
61095
61492
  if (leanSessionID) {
61096
- const runState = _internals35.loadLeanTurboRunState(directory, leanSessionID);
61493
+ const runState = _internals38.loadLeanTurboRunState(directory, leanSessionID);
61097
61494
  if (runState) {
61098
61495
  status.leanTurboPhase = runState.phase;
61099
61496
  status.leanMaxParallelCoders = runState.maxParallelCoders;
@@ -61125,7 +61522,7 @@ function enrichWithLeanTurbo(status, directory) {
61125
61522
  }
61126
61523
  }
61127
61524
  }
61128
- status.fullAutoActive = _internals35.hasActiveFullAuto();
61525
+ status.fullAutoActive = _internals38.hasActiveFullAuto();
61129
61526
  return status;
61130
61527
  }
61131
61528
  function formatStatusMarkdown(status) {
@@ -61213,7 +61610,7 @@ async function handleStatusCommand(directory, agents) {
61213
61610
  }
61214
61611
  return formatStatusMarkdown(statusData);
61215
61612
  }
61216
- var _internals35;
61613
+ var _internals38;
61217
61614
  var init_status_service = __esm(() => {
61218
61615
  init_extractors();
61219
61616
  init_knowledge_escalator();
@@ -61223,7 +61620,7 @@ var init_status_service = __esm(() => {
61223
61620
  init_state3();
61224
61621
  init_compaction_service();
61225
61622
  init_context_budget_service();
61226
- _internals35 = {
61623
+ _internals38 = {
61227
61624
  loadLeanTurboRunState,
61228
61625
  hasActiveLeanTurbo,
61229
61626
  hasActiveFullAuto
@@ -61314,7 +61711,7 @@ async function handleTurboCommand(directory, args, sessionID) {
61314
61711
  if (arg0 === "on") {
61315
61712
  let strategy = "standard";
61316
61713
  try {
61317
- const { config: config3 } = _internals36.loadPluginConfigWithMeta(directory);
61714
+ const { config: config3 } = _internals39.loadPluginConfigWithMeta(directory);
61318
61715
  if (config3.turbo?.strategy === "lean") {
61319
61716
  strategy = "lean";
61320
61717
  }
@@ -61369,7 +61766,7 @@ function enableLeanTurbo(session, directory, sessionID) {
61369
61766
  let maxParallelCoders = 4;
61370
61767
  let conflictPolicy = "serialize";
61371
61768
  try {
61372
- const { config: config3 } = _internals36.loadPluginConfigWithMeta(directory);
61769
+ const { config: config3 } = _internals39.loadPluginConfigWithMeta(directory);
61373
61770
  const leanConfig = config3.turbo?.lean;
61374
61771
  if (leanConfig) {
61375
61772
  maxParallelCoders = leanConfig.max_parallel_coders ?? 4;
@@ -61439,13 +61836,13 @@ function buildStatusMessage2(session, directory, sessionID) {
61439
61836
  ].join(`
61440
61837
  `);
61441
61838
  }
61442
- var _internals36;
61839
+ var _internals39;
61443
61840
  var init_turbo = __esm(() => {
61444
61841
  init_config();
61445
61842
  init_state();
61446
61843
  init_state3();
61447
61844
  init_logger();
61448
- _internals36 = {
61845
+ _internals39 = {
61449
61846
  loadPluginConfigWithMeta
61450
61847
  };
61451
61848
  });
@@ -61512,8 +61909,8 @@ var init_write_retro2 = __esm(() => {
61512
61909
  });
61513
61910
 
61514
61911
  // src/commands/command-dispatch.ts
61515
- import fs34 from "fs";
61516
- import path62 from "path";
61912
+ import fs35 from "fs";
61913
+ import path63 from "path";
61517
61914
  function normalizeSwarmCommandInput(command, argumentText) {
61518
61915
  if (command !== "swarm" && !command.startsWith("swarm-")) {
61519
61916
  return { isSwarmCommand: false, tokens: [] };
@@ -61538,7 +61935,7 @@ function formatCommandNotFound(tokens) {
61538
61935
  const attemptedCommand = tokens[0] || "";
61539
61936
  const MAX_DISPLAY = 100;
61540
61937
  const displayCommand = attemptedCommand.length > MAX_DISPLAY ? `${attemptedCommand.slice(0, MAX_DISPLAY)}...` : attemptedCommand;
61541
- const similar = _internals37.findSimilarCommands(attemptedCommand);
61938
+ const similar = _internals40.findSimilarCommands(attemptedCommand);
61542
61939
  const header = `Command \`/swarm ${displayCommand}\` not found.`;
61543
61940
  const suggestions = similar.length > 0 ? `Did you mean:
61544
61941
  ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
@@ -61549,11 +61946,11 @@ ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
61549
61946
  `);
61550
61947
  }
61551
61948
  function maybeMarkFirstRun(directory) {
61552
- const sentinelPath = path62.join(directory, ".swarm", ".first-run-complete");
61949
+ const sentinelPath = path63.join(directory, ".swarm", ".first-run-complete");
61553
61950
  try {
61554
- const swarmDir = path62.join(directory, ".swarm");
61555
- fs34.mkdirSync(swarmDir, { recursive: true });
61556
- fs34.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
61951
+ const swarmDir = path63.join(directory, ".swarm");
61952
+ fs35.mkdirSync(swarmDir, { recursive: true });
61953
+ fs35.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
61557
61954
  `, { flag: "wx" });
61558
61955
  return true;
61559
61956
  } catch {
@@ -62083,7 +62480,7 @@ async function buildSwarmCommandPrompt(args) {
62083
62480
  packageRoot,
62084
62481
  registeredAgents
62085
62482
  } = args;
62086
- const resolved = _internals37.resolveCommand(tokens);
62483
+ const resolved = _internals40.resolveCommand(tokens);
62087
62484
  if (!resolved) {
62088
62485
  if (tokens.length === 0) {
62089
62486
  return buildHelpText();
@@ -62253,7 +62650,7 @@ function findSimilarCommands(query) {
62253
62650
  }
62254
62651
  const scored = VALID_COMMANDS.map((cmd) => {
62255
62652
  const cmdLower = cmd.toLowerCase();
62256
- const fullScore = _internals37.levenshteinDistance(q, cmdLower);
62653
+ const fullScore = _internals40.levenshteinDistance(q, cmdLower);
62257
62654
  let tokenScore = Infinity;
62258
62655
  if (cmd.includes(" ") || cmd.includes("-")) {
62259
62656
  const qTokens = q.split(/[\s-]+/);
@@ -62266,7 +62663,7 @@ function findSimilarCommands(query) {
62266
62663
  for (const ct of cmdTokens) {
62267
62664
  if (ct.length === 0)
62268
62665
  continue;
62269
- const dist = _internals37.levenshteinDistance(qt, ct);
62666
+ const dist = _internals40.levenshteinDistance(qt, ct);
62270
62667
  if (dist < minDist)
62271
62668
  minDist = dist;
62272
62669
  }
@@ -62276,7 +62673,7 @@ function findSimilarCommands(query) {
62276
62673
  }
62277
62674
  const dashStrippedQ = q.replace(/-/g, "");
62278
62675
  const dashStrippedCmd = cmdLower.replace(/-/g, "");
62279
- const dashScore = _internals37.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
62676
+ const dashScore = _internals40.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
62280
62677
  const score = Math.min(fullScore, tokenScore, dashScore);
62281
62678
  return { cmd, score };
62282
62679
  });
@@ -62308,11 +62705,11 @@ async function handleHelpCommand(ctx) {
62308
62705
  return buildHelpText2();
62309
62706
  }
62310
62707
  const tokens = targetCommand.split(/\s+/);
62311
- const resolved = _internals37.resolveCommand(tokens);
62708
+ const resolved = _internals40.resolveCommand(tokens);
62312
62709
  if (resolved) {
62313
- return _internals37.buildDetailedHelp(resolved.key, resolved.entry);
62710
+ return _internals40.buildDetailedHelp(resolved.key, resolved.entry);
62314
62711
  }
62315
- const similar = _internals37.findSimilarCommands(targetCommand);
62712
+ const similar = _internals40.findSimilarCommands(targetCommand);
62316
62713
  const { buildHelpText: fullHelp } = await Promise.resolve().then(() => (init_commands(), exports_commands));
62317
62714
  if (similar.length > 0) {
62318
62715
  return `Command '/swarm ${targetCommand}' not found.
@@ -62354,24 +62751,24 @@ function validateAliases() {
62354
62751
  }
62355
62752
  aliasTargets.get(target).push(name);
62356
62753
  const visited = new Set;
62357
- const path63 = [];
62754
+ const path64 = [];
62358
62755
  let current = target;
62359
62756
  while (current) {
62360
62757
  const currentEntry = COMMAND_REGISTRY[current];
62361
62758
  if (!currentEntry)
62362
62759
  break;
62363
62760
  if (visited.has(current)) {
62364
- const cycleStart = path63.indexOf(current);
62761
+ const cycleStart = path64.indexOf(current);
62365
62762
  const fullChain = [
62366
62763
  name,
62367
- ...path63.slice(0, cycleStart > 0 ? cycleStart : path63.length),
62764
+ ...path64.slice(0, cycleStart > 0 ? cycleStart : path64.length),
62368
62765
  current
62369
62766
  ].join(" \u2192 ");
62370
62767
  errors5.push(`Circular alias detected: ${fullChain}`);
62371
62768
  break;
62372
62769
  }
62373
62770
  visited.add(current);
62374
- path63.push(current);
62771
+ path64.push(current);
62375
62772
  current = currentEntry.aliasOf || "";
62376
62773
  }
62377
62774
  }
@@ -62412,7 +62809,7 @@ function resolveCommand(tokens) {
62412
62809
  }
62413
62810
  return null;
62414
62811
  }
62415
- var COMMAND_REGISTRY, VALID_COMMANDS, _internals37, validation;
62812
+ var COMMAND_REGISTRY, VALID_COMMANDS, _internals40, validation;
62416
62813
  var init_registry = __esm(() => {
62417
62814
  init_bundled_skills();
62418
62815
  init_acknowledge_spec_drift();
@@ -62442,7 +62839,10 @@ var init_registry = __esm(() => {
62442
62839
  init_memory2();
62443
62840
  init_plan();
62444
62841
  init_pr_feedback();
62842
+ init_pr_monitor_status();
62445
62843
  init_pr_review();
62844
+ init_pr_subscribe();
62845
+ init_pr_unsubscribe();
62446
62846
  init_preflight();
62447
62847
  init_promote();
62448
62848
  init_qa_gates();
@@ -62490,7 +62890,7 @@ var init_registry = __esm(() => {
62490
62890
  clashesWithNativeCcCommand: "/agents"
62491
62891
  },
62492
62892
  help: {
62493
- handler: (ctx) => _internals37.handleHelpCommand(ctx),
62893
+ handler: (ctx) => _internals40.handleHelpCommand(ctx),
62494
62894
  description: "Show help for swarm commands",
62495
62895
  category: "core",
62496
62896
  args: "[command]",
@@ -62768,6 +63168,27 @@ Subcommands:
62768
63168
  details: "Triggers MODE: PR_FEEDBACK \u2014 ingests existing pull-request feedback (review threads, requested changes, CI/check failures, merge conflicts, stale branch state, pasted notes), verifies every claim against source, clusters related problems, fixes confirmed items, validates the branch, and reports closure status for every ledger item. Distinct from /swarm pr-review, which discovers new findings. The PR reference is optional: with none, the architect builds the ledger from the current PR/branch; text after the reference is forwarded as extra instructions. Supports full GitHub URL, owner/repo#N shorthand, or bare PR number (resolved against origin).",
62769
63169
  category: "agent"
62770
63170
  },
63171
+ "pr subscribe": {
63172
+ handler: (ctx) => handlePrSubscribeCommand(ctx.directory, ctx.args, ctx.sessionID),
63173
+ description: "Subscribe the current session to PR state-change notifications",
63174
+ args: "<pr-url|owner/repo#N|N>",
63175
+ details: "Subscribes the current session to receive advisory notifications for the specified PR. When pr_monitor.enabled is true, the background polling worker will detect CI failures, new comments, merge conflicts, review state changes, and merge/close events. Notifications are delivered as session-scoped advisories with dedup tokens. Supports full GitHub URL, owner/repo#N shorthand, or bare PR number (resolved against origin). Requires pr_monitor.enabled: true in config.",
63176
+ category: "agent"
63177
+ },
63178
+ "pr unsubscribe": {
63179
+ handler: (ctx) => handlePrUnsubscribeCommand(ctx.directory, ctx.args, ctx.sessionID),
63180
+ description: "Unsubscribe the current session from PR state-change notifications",
63181
+ args: "<pr-url|owner/repo#N|N>",
63182
+ details: "Unsubscribes the current session from receiving advisory notifications for the specified PR. Removes the active subscription record. Supports full GitHub URL, owner/repo#N shorthand, or bare PR number (resolved against origin).",
63183
+ category: "agent"
63184
+ },
63185
+ "pr status": {
63186
+ handler: (ctx) => handlePrMonitorStatusCommand(ctx.directory, ctx.args, ctx.sessionID),
63187
+ description: "Show PR monitor subscription status for the current session",
63188
+ args: "",
63189
+ details: "Displays all active PR subscriptions for the current session. Shows PR URL, last checked time, watching status, and error count per subscription. Also shows total active subscriptions across all sessions.",
63190
+ category: "agent"
63191
+ },
62771
63192
  "deep-dive": {
62772
63193
  handler: (ctx) => handleModeCommandWithBundledSkills(ctx, handleDeepDiveCommand),
62773
63194
  description: "Launch deep codebase audit with parallel explorer waves, dual reviewers, and critic challenge [scope]",
@@ -63017,7 +63438,7 @@ Subcommands:
63017
63438
  }
63018
63439
  };
63019
63440
  VALID_COMMANDS = Object.keys(COMMAND_REGISTRY);
63020
- _internals37 = {
63441
+ _internals40 = {
63021
63442
  handleHelpCommand,
63022
63443
  validateAliases,
63023
63444
  resolveCommand,
@@ -63025,7 +63446,7 @@ Subcommands:
63025
63446
  findSimilarCommands,
63026
63447
  buildDetailedHelp
63027
63448
  };
63028
- validation = _internals37.validateAliases();
63449
+ validation = _internals40.validateAliases();
63029
63450
  if (!validation.valid) {
63030
63451
  throw new Error(`COMMAND_REGISTRY alias validation failed:
63031
63452
  ${validation.errors.join(`
@@ -63043,72 +63464,72 @@ init_package();
63043
63464
  init_registry();
63044
63465
  init_cache_paths();
63045
63466
  init_constants();
63046
- import * as fs35 from "fs";
63467
+ import * as fs36 from "fs";
63047
63468
  import * as os9 from "os";
63048
- import * as path63 from "path";
63469
+ import * as path64 from "path";
63049
63470
  var { version: version5 } = package_default;
63050
63471
  var CONFIG_DIR = getPluginConfigDir();
63051
- var OPENCODE_CONFIG_PATH = path63.join(CONFIG_DIR, "opencode.json");
63052
- var PLUGIN_CONFIG_PATH = path63.join(CONFIG_DIR, "opencode-swarm.json");
63053
- var PROMPTS_DIR = path63.join(CONFIG_DIR, "opencode-swarm");
63472
+ var OPENCODE_CONFIG_PATH = path64.join(CONFIG_DIR, "opencode.json");
63473
+ var PLUGIN_CONFIG_PATH = path64.join(CONFIG_DIR, "opencode-swarm.json");
63474
+ var PROMPTS_DIR = path64.join(CONFIG_DIR, "opencode-swarm");
63054
63475
  var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
63055
63476
  var OPENCODE_PLUGIN_LOCK_FILE_PATHS = getPluginLockFilePaths();
63056
63477
  function isSafeCachePath(p) {
63057
- const resolved = path63.resolve(p);
63058
- const home = path63.resolve(os9.homedir());
63478
+ const resolved = path64.resolve(p);
63479
+ const home = path64.resolve(os9.homedir());
63059
63480
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
63060
63481
  return false;
63061
63482
  }
63062
- const segments = resolved.split(path63.sep).filter((s) => s.length > 0);
63483
+ const segments = resolved.split(path64.sep).filter((s) => s.length > 0);
63063
63484
  if (segments.length < 4) {
63064
63485
  return false;
63065
63486
  }
63066
- const leaf = path63.basename(resolved);
63487
+ const leaf = path64.basename(resolved);
63067
63488
  if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
63068
63489
  return false;
63069
63490
  }
63070
- const parent = path63.basename(path63.dirname(resolved));
63491
+ const parent = path64.basename(path64.dirname(resolved));
63071
63492
  if (parent !== "packages" && parent !== "node_modules") {
63072
63493
  return false;
63073
63494
  }
63074
- const grandparent = path63.basename(path63.dirname(path63.dirname(resolved)));
63495
+ const grandparent = path64.basename(path64.dirname(path64.dirname(resolved)));
63075
63496
  if (grandparent !== "opencode") {
63076
63497
  return false;
63077
63498
  }
63078
63499
  return true;
63079
63500
  }
63080
63501
  function isSafeLockFilePath(p) {
63081
- const resolved = path63.resolve(p);
63082
- const home = path63.resolve(os9.homedir());
63502
+ const resolved = path64.resolve(p);
63503
+ const home = path64.resolve(os9.homedir());
63083
63504
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
63084
63505
  return false;
63085
63506
  }
63086
- const segments = resolved.split(path63.sep).filter((s) => s.length > 0);
63507
+ const segments = resolved.split(path64.sep).filter((s) => s.length > 0);
63087
63508
  if (segments.length < 4) {
63088
63509
  return false;
63089
63510
  }
63090
- const leaf = path63.basename(resolved);
63511
+ const leaf = path64.basename(resolved);
63091
63512
  if (leaf !== "bun.lock" && leaf !== "bun.lockb" && leaf !== "package-lock.json") {
63092
63513
  return false;
63093
63514
  }
63094
- const parent = path63.basename(path63.dirname(resolved));
63515
+ const parent = path64.basename(path64.dirname(resolved));
63095
63516
  if (parent !== "opencode") {
63096
63517
  return false;
63097
63518
  }
63098
- const grandparent = path63.basename(path63.dirname(path63.dirname(resolved)));
63519
+ const grandparent = path64.basename(path64.dirname(path64.dirname(resolved)));
63099
63520
  if (grandparent === "opencode") {
63100
63521
  return false;
63101
63522
  }
63102
63523
  return true;
63103
63524
  }
63104
63525
  function ensureDir(dir) {
63105
- if (!fs35.existsSync(dir)) {
63106
- fs35.mkdirSync(dir, { recursive: true });
63526
+ if (!fs36.existsSync(dir)) {
63527
+ fs36.mkdirSync(dir, { recursive: true });
63107
63528
  }
63108
63529
  }
63109
63530
  function loadJson(filepath) {
63110
63531
  try {
63111
- const content = fs35.readFileSync(filepath, "utf-8");
63532
+ const content = fs36.readFileSync(filepath, "utf-8");
63112
63533
  const stripped = content.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (match, comment) => comment ? "" : match).replace(/,(\s*[}\]])/g, "$1");
63113
63534
  return JSON.parse(stripped);
63114
63535
  } catch {
@@ -63116,14 +63537,14 @@ function loadJson(filepath) {
63116
63537
  }
63117
63538
  }
63118
63539
  function saveJson(filepath, data) {
63119
- fs35.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
63540
+ fs36.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
63120
63541
  `, "utf-8");
63121
63542
  }
63122
63543
  function writeProjectConfigIfMissing(cwd) {
63123
63544
  try {
63124
- const opencodeDir = path63.join(cwd, ".opencode");
63125
- const projectConfigPath = path63.join(opencodeDir, "opencode-swarm.json");
63126
- if (fs35.existsSync(projectConfigPath)) {
63545
+ const opencodeDir = path64.join(cwd, ".opencode");
63546
+ const projectConfigPath = path64.join(opencodeDir, "opencode-swarm.json");
63547
+ if (fs36.existsSync(projectConfigPath)) {
63127
63548
  return;
63128
63549
  }
63129
63550
  ensureDir(opencodeDir);
@@ -63139,7 +63560,7 @@ async function install() {
63139
63560
  `);
63140
63561
  ensureDir(CONFIG_DIR);
63141
63562
  ensureDir(PROMPTS_DIR);
63142
- const LEGACY_CONFIG_PATH = path63.join(CONFIG_DIR, "config.json");
63563
+ const LEGACY_CONFIG_PATH = path64.join(CONFIG_DIR, "config.json");
63143
63564
  let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
63144
63565
  if (!opencodeConfig) {
63145
63566
  const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
@@ -63186,7 +63607,7 @@ async function install() {
63186
63607
  console.warn(`\u26A0 Could not clear opencode lock file \u2014 you may need to delete it manually:
63187
63608
  ${failed}`);
63188
63609
  }
63189
- if (!fs35.existsSync(PLUGIN_CONFIG_PATH)) {
63610
+ if (!fs36.existsSync(PLUGIN_CONFIG_PATH)) {
63190
63611
  const defaultConfig = {
63191
63612
  agents: { ...DEFAULT_AGENT_CONFIGS },
63192
63613
  max_iterations: 5
@@ -63265,14 +63686,14 @@ function evictPluginCaches() {
63265
63686
  const cleared = [];
63266
63687
  const failed = [];
63267
63688
  for (const cachePath of OPENCODE_PLUGIN_CACHE_PATHS) {
63268
- if (!fs35.existsSync(cachePath))
63689
+ if (!fs36.existsSync(cachePath))
63269
63690
  continue;
63270
63691
  if (!isSafeCachePath(cachePath)) {
63271
63692
  failed.push(`${cachePath} (refused: failed safety check)`);
63272
63693
  continue;
63273
63694
  }
63274
63695
  try {
63275
- fs35.rmSync(cachePath, { recursive: true, force: true });
63696
+ fs36.rmSync(cachePath, { recursive: true, force: true });
63276
63697
  cleared.push(cachePath);
63277
63698
  } catch (err) {
63278
63699
  failed.push(`${cachePath} (${err instanceof Error ? err.message : String(err)})`);
@@ -63284,14 +63705,14 @@ function evictLockFiles() {
63284
63705
  const cleared = [];
63285
63706
  const failed = [];
63286
63707
  for (const lockPath of OPENCODE_PLUGIN_LOCK_FILE_PATHS) {
63287
- if (!fs35.existsSync(lockPath))
63708
+ if (!fs36.existsSync(lockPath))
63288
63709
  continue;
63289
63710
  if (!isSafeLockFilePath(lockPath)) {
63290
63711
  failed.push(`${lockPath} (refused: failed safety check)`);
63291
63712
  continue;
63292
63713
  }
63293
63714
  try {
63294
- fs35.unlinkSync(lockPath);
63715
+ fs36.unlinkSync(lockPath);
63295
63716
  cleared.push(lockPath);
63296
63717
  } catch (err) {
63297
63718
  const code = err?.code;
@@ -63310,7 +63731,7 @@ async function uninstall() {
63310
63731
  `);
63311
63732
  const opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
63312
63733
  if (!opencodeConfig) {
63313
- if (fs35.existsSync(OPENCODE_CONFIG_PATH)) {
63734
+ if (fs36.existsSync(OPENCODE_CONFIG_PATH)) {
63314
63735
  console.log(`\u2717 Could not parse opencode config at: ${OPENCODE_CONFIG_PATH}`);
63315
63736
  return 1;
63316
63737
  } else {
@@ -63342,13 +63763,13 @@ async function uninstall() {
63342
63763
  console.log("\u2713 Re-enabled default OpenCode agents (explore, general)");
63343
63764
  if (process.argv.includes("--clean")) {
63344
63765
  let cleaned = false;
63345
- if (fs35.existsSync(PLUGIN_CONFIG_PATH)) {
63346
- fs35.unlinkSync(PLUGIN_CONFIG_PATH);
63766
+ if (fs36.existsSync(PLUGIN_CONFIG_PATH)) {
63767
+ fs36.unlinkSync(PLUGIN_CONFIG_PATH);
63347
63768
  console.log(`\u2713 Removed plugin config: ${PLUGIN_CONFIG_PATH}`);
63348
63769
  cleaned = true;
63349
63770
  }
63350
- if (fs35.existsSync(PROMPTS_DIR)) {
63351
- fs35.rmSync(PROMPTS_DIR, { recursive: true });
63771
+ if (fs36.existsSync(PROMPTS_DIR)) {
63772
+ fs36.rmSync(PROMPTS_DIR, { recursive: true });
63352
63773
  console.log(`\u2713 Removed custom prompts: ${PROMPTS_DIR}`);
63353
63774
  cleaned = true;
63354
63775
  }