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