@wrongstack/plugins 0.287.0 → 0.289.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.
Files changed (40) hide show
  1. package/dist/accessibility-auditor/index.d.ts.map +1 -1
  2. package/dist/accessibility-auditor.js +45 -42
  3. package/dist/auto-i18n-extractor.js +1 -1
  4. package/dist/code-metrics/index.d.ts.map +1 -1
  5. package/dist/code-metrics.js +46 -42
  6. package/dist/cost-tracker/index.d.ts.map +1 -1
  7. package/dist/cost-tracker.js +4 -2
  8. package/dist/dead-code-detector.js +3 -3
  9. package/dist/diff-summary.js +1 -1
  10. package/dist/doc-sync-guard.js +3 -3
  11. package/dist/duplicate-code-detector/index.d.ts.map +1 -1
  12. package/dist/duplicate-code-detector.js +47 -43
  13. package/dist/feature-flag-tracker/index.d.ts.map +1 -1
  14. package/dist/feature-flag-tracker.js +46 -42
  15. package/dist/file-watcher/index.d.ts.map +1 -1
  16. package/dist/file-watcher.js +6 -2
  17. package/dist/format-on-save.js +1 -1
  18. package/dist/import-organizer.js +1 -1
  19. package/dist/index.js +396 -539
  20. package/dist/interface-contract-guard/index.d.ts.map +1 -1
  21. package/dist/interface-contract-guard.js +46 -42
  22. package/dist/lint-gate/index.d.ts.map +1 -1
  23. package/dist/lint-gate.js +61 -30
  24. package/dist/migration-planner.js +1 -1
  25. package/dist/prompt-firewall/index.d.ts +14 -6
  26. package/dist/prompt-firewall/index.d.ts.map +1 -1
  27. package/dist/prompt-firewall.js +7 -6
  28. package/dist/refactor-suggester/index.d.ts.map +1 -1
  29. package/dist/refactor-suggester.js +46 -42
  30. package/dist/runtime/index.d.ts +24 -0
  31. package/dist/runtime/index.d.ts.map +1 -1
  32. package/dist/runtime.js +63 -24
  33. package/dist/schema-evolution-guard.js +1 -1
  34. package/dist/secret-scanner/index.d.ts.map +1 -1
  35. package/dist/secret-scanner.js +17 -6
  36. package/dist/security-hotspot-scanner.js +1 -1
  37. package/dist/spec-linker.js +396 -539
  38. package/dist/test-runner-gate.js +1 -1
  39. package/dist/type-gate.js +19 -23
  40. package/package.json +3 -3
@@ -486,10 +486,10 @@ async function runAutoDoc(input, api) {
486
486
  continue;
487
487
  }
488
488
  try {
489
- const { readFileSync: readFileSync25, writeFileSync: writeFileSync8 } = await import("node:fs");
489
+ const { readFileSync: readFileSync26, writeFileSync: writeFileSync8 } = await import("node:fs");
490
490
  let content;
491
491
  try {
492
- content = readFileSync25(safeFile, "utf-8");
492
+ content = readFileSync26(safeFile, "utf-8");
493
493
  } catch {
494
494
  api.log.warn(`auto-doc: could not read file ${safeFile}`);
495
495
  continue;
@@ -890,14 +890,14 @@ function hasDisabledPluginEntry(raw) {
890
890
  });
891
891
  }
892
892
  function runGit(args, cwd, signal) {
893
- return new Promise((resolve27, reject) => {
893
+ return new Promise((resolve28, reject) => {
894
894
  execFile(
895
895
  "git",
896
896
  args,
897
897
  { encoding: "utf-8", timeout: 3e3, cwd, windowsHide: true, signal },
898
898
  (error, stdout) => {
899
899
  if (error) reject(error);
900
- else resolve27(stdout);
900
+ else resolve28(stdout);
901
901
  }
902
902
  );
903
903
  });
@@ -2866,11 +2866,13 @@ var digestCounters = {
2866
2866
  mailboxDigestErrors: 0
2867
2867
  };
2868
2868
  function readCostTrackerConfig(raw) {
2869
+ const digestEveryN = raw?.["mailboxDigestEveryN"];
2870
+ const digestTo = raw?.["mailboxDigestTo"];
2869
2871
  return {
2870
2872
  budgetLimit: typeof raw?.["budgetLimit"] === "number" ? raw["budgetLimit"] : 0,
2871
2873
  warningThreshold: typeof raw?.["warningThreshold"] === "number" ? raw["warningThreshold"] : 80,
2872
- mailboxDigestEveryN: typeof raw?.["mailboxDigestEveryN"] === "number" && raw?.["mailboxDigestEveryN"] >= 0 ? Math.floor(raw?.["mailboxDigestEveryN"]) : 0,
2873
- mailboxDigestTo: typeof raw?.["mailboxDigestTo"] === "string" && (raw?.["mailboxDigestTo"]).length > 0 ? raw?.["mailboxDigestTo"] : "cost-tracker"
2874
+ mailboxDigestEveryN: typeof digestEveryN === "number" && digestEveryN >= 0 ? Math.floor(digestEveryN) : 0,
2875
+ mailboxDigestTo: typeof digestTo === "string" && digestTo.length > 0 ? digestTo : "cost-tracker"
2874
2876
  };
2875
2877
  }
2876
2878
  function estimateCost(model, promptTokens, completionTokens) {
@@ -3839,7 +3841,8 @@ import { execFileSync } from "node:child_process";
3839
3841
 
3840
3842
  // src/runtime/index.ts
3841
3843
  import { execFile as execFile2 } from "node:child_process";
3842
- import { basename, isAbsolute as isAbsolute5, relative as relative5, resolve as resolve5 } from "node:path";
3844
+ import { existsSync, readdirSync, statSync as statSync3 } from "node:fs";
3845
+ import { basename, extname, isAbsolute as isAbsolute5, relative as relative5, resolve as resolve5 } from "node:path";
3843
3846
 
3844
3847
  // src/runtime/llm.ts
3845
3848
  function stripOuterMarkdownFence(text) {
@@ -3986,12 +3989,15 @@ function runRunnerCommand(argv, options) {
3986
3989
  });
3987
3990
  return;
3988
3991
  }
3989
- const timedOut = false;
3992
+ let timedOut = false;
3990
3993
  let spawnErrored = false;
3991
3994
  const stdoutChunks = [];
3992
3995
  const stderrChunks = [];
3993
3996
  let stdoutBytes = 0;
3994
3997
  let stderrBytes = 0;
3998
+ options.signal?.addEventListener("abort", () => {
3999
+ timedOut = true;
4000
+ }, { once: true });
3995
4001
  const child = execFile2(
3996
4002
  argv[0],
3997
4003
  argv.slice(1),
@@ -4003,12 +4009,12 @@ function runRunnerCommand(argv, options) {
4003
4009
  windowsHide: true,
4004
4010
  shell: false
4005
4011
  },
4006
- (err, stdout, stderr) => {
4012
+ (err) => {
4007
4013
  if (timedOut) {
4008
4014
  resolvePromise({
4009
4015
  code: null,
4010
- stdout: Buffer.concat([...stdoutChunks, ...Buffer.isBuffer(stdout) ? [stdout] : [Buffer.from(stdout)]]).toString("utf8"),
4011
- stderr: Buffer.concat([...stderrChunks, ...Buffer.isBuffer(stderr) ? [stderr] : [Buffer.from(stderr)]]).toString("utf8"),
4016
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
4017
+ stderr: Buffer.concat(stderrChunks).toString("utf8"),
4012
4018
  timedOut: true,
4013
4019
  spawnError: false
4014
4020
  });
@@ -4017,8 +4023,8 @@ function runRunnerCommand(argv, options) {
4017
4023
  if (spawnErrored) {
4018
4024
  resolvePromise({
4019
4025
  code: 127,
4020
- stdout: Buffer.concat([...stdoutChunks, ...Buffer.isBuffer(stdout) ? [stdout] : [Buffer.from(stdout)]]).toString("utf8"),
4021
- stderr: Buffer.concat([...stderrChunks, ...Buffer.isBuffer(stderr) ? [stderr] : [Buffer.from(stderr)]]).toString("utf8"),
4026
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
4027
+ stderr: Buffer.concat(stderrChunks).toString("utf8"),
4022
4028
  timedOut: false,
4023
4029
  spawnError: true
4024
4030
  });
@@ -4029,14 +4035,8 @@ function runRunnerCommand(argv, options) {
4029
4035
  const code = typeof anyErr.code === "number" ? anyErr.code : 1;
4030
4036
  resolvePromise({
4031
4037
  code,
4032
- stdout: Buffer.concat([
4033
- ...stdoutChunks,
4034
- ...anyErr.stdout ? [Buffer.isBuffer(anyErr.stdout) ? anyErr.stdout : Buffer.from(anyErr.stdout)] : []
4035
- ]).toString("utf8"),
4036
- stderr: Buffer.concat([
4037
- ...stderrChunks,
4038
- ...anyErr.stderr ? [Buffer.isBuffer(anyErr.stderr) ? anyErr.stderr : Buffer.from(anyErr.stderr)] : []
4039
- ]).toString("utf8"),
4038
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
4039
+ stderr: Buffer.concat(stderrChunks).toString("utf8"),
4040
4040
  timedOut: false,
4041
4041
  spawnError: false
4042
4042
  });
@@ -4044,19 +4044,18 @@ function runRunnerCommand(argv, options) {
4044
4044
  }
4045
4045
  resolvePromise({
4046
4046
  code: 0,
4047
- stdout: Buffer.concat([
4048
- ...stdoutChunks,
4049
- ...Buffer.isBuffer(stdout) ? [stdout] : [Buffer.from(stdout)]
4050
- ]).toString("utf8"),
4051
- stderr: Buffer.concat([
4052
- ...stderrChunks,
4053
- ...Buffer.isBuffer(stderr) ? [stderr] : [Buffer.from(stderr)]
4054
- ]).toString("utf8"),
4047
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
4048
+ stderr: Buffer.concat(stderrChunks).toString("utf8"),
4055
4049
  timedOut: false,
4056
4050
  spawnError: false
4057
4051
  });
4058
4052
  }
4059
4053
  );
4054
+ child.on("exit", (_code, signal) => {
4055
+ if (signal !== null) {
4056
+ timedOut = true;
4057
+ }
4058
+ });
4060
4059
  child.stdout?.on("data", (chunk) => {
4061
4060
  stdoutBytes += chunk.length;
4062
4061
  if (stdoutBytes <= MAX_BUFFER_BYTES) stdoutChunks.push(chunk);
@@ -4075,6 +4074,47 @@ function runRunnerCommand(argv, options) {
4075
4074
  function withinProject(p) {
4076
4075
  return withinProjectPath(process.cwd(), p) || relative5(process.cwd(), p) === ".";
4077
4076
  }
4077
+ var DEFAULT_EXCLUDE_DIRS = ["node_modules", "dist", ".git", "coverage"];
4078
+ function collectSourceFiles(root, opts) {
4079
+ const files = [];
4080
+ if (!existsSync(root)) return files;
4081
+ const s = statSync3(root);
4082
+ if (s.isFile()) {
4083
+ if (matchesExtension(root, opts.extensions)) files.push(root);
4084
+ return files;
4085
+ }
4086
+ if (!s.isDirectory()) return files;
4087
+ const exclude = opts.excludeDirs ?? DEFAULT_EXCLUDE_DIRS;
4088
+ function walk(dir, depth) {
4089
+ if (opts.maxDepth !== void 0 && depth > opts.maxDepth) return;
4090
+ let entries;
4091
+ try {
4092
+ entries = readdirSync(dir);
4093
+ } catch {
4094
+ return;
4095
+ }
4096
+ for (const entry of entries) {
4097
+ if (exclude.includes(entry)) continue;
4098
+ const full = resolve5(dir, entry);
4099
+ let st;
4100
+ try {
4101
+ st = statSync3(full);
4102
+ } catch {
4103
+ continue;
4104
+ }
4105
+ if (st.isDirectory()) {
4106
+ walk(full, depth + 1);
4107
+ } else if (st.isFile() && matchesExtension(full, opts.extensions)) {
4108
+ files.push(full);
4109
+ }
4110
+ }
4111
+ }
4112
+ walk(root, 0);
4113
+ return files;
4114
+ }
4115
+ function matchesExtension(p, exts) {
4116
+ return exts.includes(extname(p).toLowerCase());
4117
+ }
4078
4118
 
4079
4119
  // src/diff-summary/index.ts
4080
4120
  var API_VERSION6 = "^0.1.10";
@@ -4665,7 +4705,7 @@ var error_lens_default = plugin14;
4665
4705
 
4666
4706
  // src/file-watcher/index.ts
4667
4707
  import { watch as fsWatch } from "node:fs";
4668
- import { isAbsolute as isAbsolute6, relative as relative6, resolve as resolve6 } from "node:path";
4708
+ import { isAbsolute as isAbsolute6, join, relative as relative6, resolve as resolve6 } from "node:path";
4669
4709
  var API_VERSION7 = "^0.1.10";
4670
4710
  function withinProject2(p) {
4671
4711
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
@@ -4774,7 +4814,11 @@ var plugin15 = {
4774
4814
  try {
4775
4815
  const watcher = fsWatch(dirPath, { recursive }, (eventType, filename) => {
4776
4816
  if (!filename) return;
4777
- const fullPath = `${dirPath}/${filename}`;
4817
+ if (handle.events.length > 0 && !(eventType === "change" ? handle.events.includes("change") : handle.events.includes("add") || handle.events.includes("delete"))) {
4818
+ return;
4819
+ }
4820
+ const rawPath = filename.startsWith(dirPath) ? filename : join(dirPath, filename);
4821
+ const fullPath = rawPath.replace(/\\/g, "/");
4778
4822
  const key = `${handle.id}:${fullPath}:${eventType}`;
4779
4823
  debounceEvent(
4780
4824
  key,
@@ -4993,7 +5037,7 @@ var file_watcher_default = plugin15;
4993
5037
 
4994
5038
  // src/format-on-save/index.ts
4995
5039
  import { execFileSync as execFileSync2, execSync } from "node:child_process";
4996
- import { existsSync, statSync as statSync3 } from "node:fs";
5040
+ import { existsSync as existsSync2, statSync as statSync4 } from "node:fs";
4997
5041
  var API_VERSION8 = "^0.1.10";
4998
5042
  var state14 = {
4999
5043
  invocationCount: 0,
@@ -5054,10 +5098,10 @@ function evictExpired(ttlMs) {
5054
5098
  }
5055
5099
  function formatFile(filePath, timeoutMs) {
5056
5100
  if (!withinProject(filePath)) return null;
5057
- if (!existsSync(filePath)) return null;
5101
+ if (!existsSync2(filePath)) return null;
5058
5102
  let bytesBefore;
5059
5103
  try {
5060
- bytesBefore = statSync3(filePath).size;
5104
+ bytesBefore = statSync4(filePath).size;
5061
5105
  } catch {
5062
5106
  return null;
5063
5107
  }
@@ -5074,7 +5118,7 @@ function formatFile(filePath, timeoutMs) {
5074
5118
  }
5075
5119
  let bytesAfter;
5076
5120
  try {
5077
- bytesAfter = statSync3(filePath).size;
5121
+ bytesAfter = statSync4(filePath).size;
5078
5122
  } catch {
5079
5123
  return null;
5080
5124
  }
@@ -5280,7 +5324,7 @@ var format_on_save_default = plugin16;
5280
5324
 
5281
5325
  // src/git-autocommit/index.ts
5282
5326
  import { execFileSync as execFileSync3 } from "node:child_process";
5283
- import { existsSync as existsSync2 } from "node:fs";
5327
+ import { existsSync as existsSync3 } from "node:fs";
5284
5328
  var API_VERSION9 = "^0.1.10";
5285
5329
  var commitCount = { value: 0 };
5286
5330
  var lastCommit = { hash: null, at: null };
@@ -5315,7 +5359,7 @@ function stageFiles(files, cwd) {
5315
5359
  if (!files || !Array.isArray(files)) return;
5316
5360
  const existing = files.filter((f) => {
5317
5361
  try {
5318
- return existsSync2(f);
5362
+ return existsSync3(f);
5319
5363
  } catch {
5320
5364
  return false;
5321
5365
  }
@@ -5740,7 +5784,7 @@ var git_autocommit_default = plugin17;
5740
5784
 
5741
5785
  // src/import-organizer/index.ts
5742
5786
  import { spawn } from "node:child_process";
5743
- import { existsSync as existsSync3, statSync as statSync4 } from "node:fs";
5787
+ import { existsSync as existsSync4, statSync as statSync5 } from "node:fs";
5744
5788
  import { basename as basename2, isAbsolute as isAbsolute7 } from "node:path";
5745
5789
  var ALLOWED_FIRST_TOKENS = /* @__PURE__ */ new Set([
5746
5790
  "npx",
@@ -5802,7 +5846,7 @@ function readConfig13(raw) {
5802
5846
  };
5803
5847
  }
5804
5848
  function runCommand(command, args, timeoutMs, cwd) {
5805
- return new Promise((resolve27) => {
5849
+ return new Promise((resolve28) => {
5806
5850
  let timedOut = false;
5807
5851
  const stdoutChunks = [];
5808
5852
  const stderrChunks = [];
@@ -5814,17 +5858,17 @@ function runCommand(command, args, timeoutMs, cwd) {
5814
5858
  signal: AbortSignal.timeout(timeoutMs)
5815
5859
  });
5816
5860
  } catch {
5817
- resolve27({ code: 127, stdout: "", stderr: "", timedOut: false });
5861
+ resolve28({ code: 127, stdout: "", stderr: "", timedOut: false });
5818
5862
  return;
5819
5863
  }
5820
5864
  child.stdout?.on("data", (c) => stdoutChunks.push(c));
5821
5865
  child.stderr?.on("data", (c) => stderrChunks.push(c));
5822
5866
  child.on("error", () => {
5823
- resolve27({ code: 127, stdout: "", stderr: "", timedOut: false });
5867
+ resolve28({ code: 127, stdout: "", stderr: "", timedOut: false });
5824
5868
  });
5825
5869
  child.on("close", (code) => {
5826
5870
  if (timedOut) return;
5827
- resolve27({
5871
+ resolve28({
5828
5872
  code,
5829
5873
  stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
5830
5874
  stderr: Buffer.concat(stderrChunks).toString("utf-8"),
@@ -5833,16 +5877,16 @@ function runCommand(command, args, timeoutMs, cwd) {
5833
5877
  });
5834
5878
  child.on("abort", () => {
5835
5879
  timedOut = true;
5836
- resolve27({ code: null, stdout: "", stderr: "", timedOut: true });
5880
+ resolve28({ code: null, stdout: "", stderr: "", timedOut: true });
5837
5881
  });
5838
5882
  });
5839
5883
  }
5840
5884
  async function organizeImports(filePath, cfg, cwd) {
5841
5885
  if (!withinProject(filePath)) return null;
5842
- if (!existsSync3(filePath)) return null;
5886
+ if (!existsSync4(filePath)) return null;
5843
5887
  let bytesBefore;
5844
5888
  try {
5845
- bytesBefore = statSync4(filePath).size;
5889
+ bytesBefore = statSync5(filePath).size;
5846
5890
  } catch {
5847
5891
  return null;
5848
5892
  }
@@ -5863,7 +5907,7 @@ async function organizeImports(filePath, cfg, cwd) {
5863
5907
  if (result.code === 127) return null;
5864
5908
  let bytesAfter;
5865
5909
  try {
5866
- bytesAfter = statSync4(filePath).size;
5910
+ bytesAfter = statSync5(filePath).size;
5867
5911
  } catch {
5868
5912
  return null;
5869
5913
  }
@@ -6589,9 +6633,11 @@ var knowledge_graph_default = plugin20;
6589
6633
 
6590
6634
  // src/lint-gate/index.ts
6591
6635
  import { execFile as execFile3 } from "node:child_process";
6636
+ import { readFileSync as readFileSync6 } from "node:fs";
6592
6637
  import { mkdtemp, readFile as readFile2, rm, writeFile } from "node:fs/promises";
6638
+ import { createRequire } from "node:module";
6593
6639
  import { tmpdir } from "node:os";
6594
- import { join } from "node:path";
6640
+ import { dirname as dirname4, isAbsolute as isAbsolute9, join as join2, relative as relative8, resolve as resolve8, sep } from "node:path";
6595
6641
  var API_VERSION12 = "^0.1.10";
6596
6642
  var state18 = {
6597
6643
  /** Total PreToolUse invocations. */
@@ -6625,55 +6671,74 @@ function readConfig16(raw) {
6625
6671
  fixRules: Array.isArray(r["fixRules"]) ? r["fixRules"].filter((x) => typeof x === "string") : []
6626
6672
  };
6627
6673
  }
6628
- function executable(command) {
6629
- return process.platform === "win32" && command === "npx" ? "npx.cmd" : command;
6674
+ var LINTER_PACKAGES = {
6675
+ biome: "@biomejs/biome",
6676
+ eslint: "eslint"
6677
+ };
6678
+ function isInside(parent, candidate) {
6679
+ const rel = relative8(parent, candidate);
6680
+ return rel === "" || !rel.startsWith(`..${sep}`) && rel !== ".." && !isAbsolute9(rel);
6681
+ }
6682
+ function resolveLocalLinter(name, cwd) {
6683
+ try {
6684
+ const packageName = LINTER_PACKAGES[name];
6685
+ const requireFromProject = createRequire(resolve8(cwd, "package.json"));
6686
+ const packagePath = requireFromProject.resolve(`${packageName}/package.json`);
6687
+ const packageJson = JSON.parse(readFileSync6(packagePath, "utf-8"));
6688
+ const relativeBin = typeof packageJson.bin === "string" ? packageJson.bin : packageJson.bin?.[name] ?? Object.values(packageJson.bin ?? {})[0];
6689
+ if (!relativeBin || isAbsolute9(relativeBin)) return null;
6690
+ const packageDir = dirname4(packagePath);
6691
+ const entry = resolve8(packageDir, relativeBin);
6692
+ if (!isInside(packageDir, entry)) return null;
6693
+ return {
6694
+ cmd: process.execPath,
6695
+ args: name === "biome" ? [entry, "check", "--reporter=json"] : [entry, "--format=json"],
6696
+ name
6697
+ };
6698
+ } catch {
6699
+ return null;
6700
+ }
6630
6701
  }
6631
- function runCommand2(command, args, timeoutMs, signal) {
6632
- return new Promise((resolve27) => {
6702
+ function runCommand2(command, args, timeoutMs, cwd, signal) {
6703
+ return new Promise((resolveResult) => {
6633
6704
  try {
6634
6705
  execFile3(
6635
- executable(command),
6706
+ command,
6636
6707
  args,
6637
6708
  {
6638
6709
  encoding: "utf-8",
6639
6710
  timeout: timeoutMs,
6640
- cwd: process.cwd(),
6711
+ cwd,
6641
6712
  windowsHide: true,
6713
+ shell: false,
6642
6714
  maxBuffer: 2 * 1024 * 1024,
6643
6715
  ...signal ? { signal } : {}
6644
6716
  },
6645
- (error, stdout) => resolve27({ stdout, error })
6717
+ (error, stdout) => resolveResult({ stdout, error })
6646
6718
  );
6647
6719
  } catch (err) {
6648
- resolve27({ stdout: "", error: err instanceof Error ? err : new Error(String(err)) });
6720
+ resolveResult({ stdout: "", error: err instanceof Error ? err : new Error(String(err)) });
6649
6721
  }
6650
6722
  });
6651
6723
  }
6652
- async function detectLinter(requested) {
6653
- const tryBiome = requested === "biome" || requested === "auto";
6654
- const tryEslint = requested === "eslint" || requested === "auto";
6655
- if (tryBiome) {
6656
- const probe = await runCommand2("npx", ["biome", "--version"], 5e3);
6657
- if (!probe.error) {
6658
- return { cmd: "npx", args: ["biome", "check", "--reporter=json"], name: "biome" };
6659
- }
6660
- }
6661
- if (tryEslint) {
6662
- const probe = await runCommand2("npx", ["eslint", "--version"], 5e3);
6663
- if (!probe.error) {
6664
- return { cmd: "npx", args: ["eslint", "--format=json"], name: "eslint" };
6665
- }
6724
+ async function detectLinter(requested, cwd) {
6725
+ const candidates = requested === "auto" ? ["biome", "eslint"] : [requested];
6726
+ for (const name of candidates) {
6727
+ const linter = resolveLocalLinter(name, cwd);
6728
+ if (!linter) continue;
6729
+ const probe = await runCommand2(linter.cmd, [linter.args[0], "--version"], 5e3, cwd);
6730
+ if (!probe.error) return linter;
6666
6731
  }
6667
6732
  return null;
6668
6733
  }
6669
- async function lintContent(content, filePath, linter, timeoutMs, signal) {
6734
+ async function lintContent(content, filePath, linter, timeoutMs, cwd, signal) {
6670
6735
  const ext = filePath.includes(".") ? filePath.slice(filePath.lastIndexOf(".")) : ".ts";
6671
- const tmpDir = await mkdtemp(join(tmpdir(), "lint-gate-"));
6672
- const tmpFile = join(tmpDir, `input${ext}`);
6736
+ const tmpDir = await mkdtemp(join2(tmpdir(), "lint-gate-"));
6737
+ const tmpFile = join2(tmpDir, `input${ext}`);
6673
6738
  try {
6674
6739
  await writeFile(tmpFile, content, "utf-8");
6675
6740
  const fullArgs = [...linter.args, tmpFile];
6676
- const result = await runCommand2(linter.cmd, fullArgs, timeoutMs, signal);
6741
+ const result = await runCommand2(linter.cmd, fullArgs, timeoutMs, cwd, signal);
6677
6742
  if (signal.aborted) throw signal.reason;
6678
6743
  if (result.error && !result.stdout) return null;
6679
6744
  return parseLinterOutput(result.stdout, linter.name);
@@ -6684,14 +6749,14 @@ async function lintContent(content, filePath, linter, timeoutMs, signal) {
6684
6749
  await rm(tmpDir, { recursive: true, force: true }).catch(() => void 0);
6685
6750
  }
6686
6751
  }
6687
- async function lintAndFix(content, filePath, linter, timeoutMs, signal) {
6752
+ async function lintAndFix(content, filePath, linter, timeoutMs, cwd, signal) {
6688
6753
  const ext = filePath.includes(".") ? filePath.slice(filePath.lastIndexOf(".")) : ".ts";
6689
- const tmpDir = await mkdtemp(join(tmpdir(), "lint-gate-fix-"));
6690
- const tmpFile = join(tmpDir, `input${ext}`);
6754
+ const tmpDir = await mkdtemp(join2(tmpdir(), "lint-gate-fix-"));
6755
+ const tmpFile = join2(tmpDir, `input${ext}`);
6691
6756
  try {
6692
6757
  await writeFile(tmpFile, content, "utf-8");
6693
- const fixArgs = linter.name === "biome" ? ["biome", "check", "--write", tmpFile] : ["eslint", "--fix", tmpFile];
6694
- await runCommand2(linter.cmd, fixArgs, timeoutMs, signal);
6758
+ const fixArgs = linter.name === "biome" ? [linter.args[0], "check", "--write", tmpFile] : [linter.args[0], "--fix", tmpFile];
6759
+ await runCommand2(linter.cmd, fixArgs, timeoutMs, cwd, signal);
6695
6760
  if (signal.aborted) throw signal.reason;
6696
6761
  return await readFile2(tmpFile, "utf-8");
6697
6762
  } catch {
@@ -6792,7 +6857,8 @@ var plugin21 = {
6792
6857
  state18.hookUnregister = null;
6793
6858
  state18.lastResult = null;
6794
6859
  const cfg = readConfig16(api.config.extensions?.["lint-gate"]);
6795
- const linterReady = detectLinter(cfg.linter).then((linter) => {
6860
+ const cwd = resolve8(api.config.cwd ?? process.cwd());
6861
+ const linterReady = detectLinter(cfg.linter, cwd).then((linter) => {
6796
6862
  if (!linter) {
6797
6863
  api.log.warn("lint-gate: no linter found (biome or eslint) \u2014 hook will be a no-op", {
6798
6864
  requested: cfg.linter
@@ -6829,7 +6895,14 @@ var plugin21 = {
6829
6895
  } else {
6830
6896
  return;
6831
6897
  }
6832
- const issues = await lintContent(content, filePath, linter, cfg.timeoutMs, runtime.signal);
6898
+ const issues = await lintContent(
6899
+ content,
6900
+ filePath,
6901
+ linter,
6902
+ cfg.timeoutMs,
6903
+ cwd,
6904
+ runtime.signal
6905
+ );
6833
6906
  if (issues === null) {
6834
6907
  state18.linterErrorCount += 1;
6835
6908
  return;
@@ -6869,6 +6942,7 @@ ${summary}${truncated}`
6869
6942
  filePath,
6870
6943
  linter,
6871
6944
  cfg.timeoutMs,
6945
+ cwd,
6872
6946
  runtime.signal
6873
6947
  );
6874
6948
  if (fixedContent !== content) {
@@ -6907,6 +6981,7 @@ ${remainingSummary}` : "")
6907
6981
  filePath,
6908
6982
  linter,
6909
6983
  cfg.timeoutMs,
6984
+ cwd,
6910
6985
  runtime.signal
6911
6986
  );
6912
6987
  if (fixedNewStr !== newStr) {
@@ -7366,7 +7441,7 @@ function hashString2(value) {
7366
7441
  }
7367
7442
  async function gitDiffFingerprint(cwd, signal) {
7368
7443
  try {
7369
- const diff = await new Promise((resolve27, reject) => {
7444
+ const diff = await new Promise((resolve28, reject) => {
7370
7445
  execFile4(
7371
7446
  "git",
7372
7447
  ["diff", "--no-ext-diff", "--"],
@@ -7383,7 +7458,7 @@ async function gitDiffFingerprint(cwd, signal) {
7383
7458
  },
7384
7459
  (error, stdout) => {
7385
7460
  if (error) reject(error);
7386
- else resolve27(stdout);
7461
+ else resolve28(stdout);
7387
7462
  }
7388
7463
  );
7389
7464
  });
@@ -8641,7 +8716,7 @@ var plugin_stack_observer_default = PLUGIN;
8641
8716
  // src/pr-drafter/index.ts
8642
8717
  import { execFileSync as execFileSync4 } from "node:child_process";
8643
8718
  import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "node:fs";
8644
- import { dirname as dirname4, isAbsolute as isAbsolute9, relative as relative8, resolve as resolve8 } from "node:path";
8719
+ import { dirname as dirname5, isAbsolute as isAbsolute10, relative as relative9, resolve as resolve9 } from "node:path";
8645
8720
  var API_VERSION13 = "^0.1.10";
8646
8721
  var state25 = {
8647
8722
  commits: [],
@@ -8680,10 +8755,10 @@ function readConfig23(raw) {
8680
8755
  }
8681
8756
  function resolveProjectPath6(rawPath, cwd = process.cwd()) {
8682
8757
  if (typeof rawPath !== "string" || rawPath.length === 0) return null;
8683
- const root = resolve8(cwd);
8684
- const resolved = isAbsolute9(rawPath) ? resolve8(rawPath) : resolve8(root, rawPath);
8685
- const rel = relative8(root, resolved);
8686
- if (rel === "" || !rel.startsWith("..") && !isAbsolute9(rel)) return resolved;
8758
+ const root = resolve9(cwd);
8759
+ const resolved = isAbsolute10(rawPath) ? resolve9(rawPath) : resolve9(root, rawPath);
8760
+ const rel = relative9(root, resolved);
8761
+ if (rel === "" || !rel.startsWith("..") && !isAbsolute10(rel)) return resolved;
8687
8762
  return null;
8688
8763
  }
8689
8764
  function gitBranch() {
@@ -8770,7 +8845,7 @@ async function writeDraft(cfg, llm) {
8770
8845
  }
8771
8846
  const draft = await buildDraft(cfg, llm);
8772
8847
  try {
8773
- mkdirSync4(dirname4(resolved), { recursive: true });
8848
+ mkdirSync4(dirname5(resolved), { recursive: true });
8774
8849
  writeFileSync5(resolved, draft.body);
8775
8850
  state25.draftsWritten += 1;
8776
8851
  } catch {
@@ -8897,7 +8972,7 @@ var plugin27 = {
8897
8972
  const resolved = resolveProjectPath6(cfg.outputPath);
8898
8973
  if (!resolved) return { ok: false, error: "outputPath resolves outside project" };
8899
8974
  try {
8900
- mkdirSync4(dirname4(resolved), { recursive: true });
8975
+ mkdirSync4(dirname5(resolved), { recursive: true });
8901
8976
  writeFileSync5(resolved, draft.body);
8902
8977
  state25.draftsWritten += 1;
8903
8978
  return {
@@ -9048,7 +9123,7 @@ function redactDeep(value, allow, counter) {
9048
9123
  function readConfig24(raw) {
9049
9124
  const base = {
9050
9125
  enabled: false,
9051
- mode: "warn",
9126
+ mode: "redact",
9052
9127
  scanResponse: true,
9053
9128
  allow: []
9054
9129
  };
@@ -9063,7 +9138,7 @@ function readConfig24(raw) {
9063
9138
  }) : [];
9064
9139
  return {
9065
9140
  enabled: r["enabled"] === true,
9066
- mode: r["mode"] === "redact" ? "redact" : r["mode"] === "block" ? "block" : "warn",
9141
+ mode: r["mode"] === "warn" ? "warn" : r["mode"] === "block" ? "block" : "redact",
9067
9142
  scanResponse: r["scanResponse"] !== false,
9068
9143
  allow
9069
9144
  };
@@ -9081,10 +9156,10 @@ var state26 = {
9081
9156
  var plugin28 = {
9082
9157
  name: "prompt-firewall",
9083
9158
  version: "0.1.0",
9084
- description: "Scans the provider wire for credential leaks before context reaches the LLM API (wrapProviderRunner); warn/redact/block. Opt-in; warn by default.",
9159
+ description: "Scans the provider wire for credential leaks before context reaches the LLM API (wrapProviderRunner); redact/warn/block. Opt-in; redact by default.",
9085
9160
  apiVersion: "^0.1.10",
9086
9161
  capabilities: { tools: true },
9087
- defaultConfig: { enabled: false, mode: "warn", scanResponse: true, allow: [] },
9162
+ defaultConfig: { enabled: false, mode: "redact", scanResponse: true, allow: [] },
9088
9163
  configSchema: {
9089
9164
  type: "object",
9090
9165
  properties: {
@@ -9096,8 +9171,8 @@ var plugin28 = {
9096
9171
  mode: {
9097
9172
  type: "string",
9098
9173
  enum: ["warn", "redact", "block"],
9099
- default: "warn",
9100
- description: "warn = detect only; redact = strip secrets from the request/response; block = refuse the request."
9174
+ default: "redact",
9175
+ description: "redact (default) = strip secrets from the request/response; warn = detect only; block = refuse the request."
9101
9176
  },
9102
9177
  scanResponse: {
9103
9178
  type: "boolean",
@@ -9321,6 +9396,8 @@ var BASE_PATTERNS = [
9321
9396
  ];
9322
9397
  var PATTERNS3 = [...BASE_PATTERNS];
9323
9398
  var COMBINED_REGEX = buildCombinedRegex(PATTERNS3);
9399
+ var RE_DOS_MAX_SCAN_LENGTH = 1e5;
9400
+ var RE_DOS_TIMEOUT_MS = 100;
9324
9401
  function buildCombinedRegex(patterns) {
9325
9402
  return new RegExp(patterns.map((p) => `(${p.regex.source})`).join("|"), "g");
9326
9403
  }
@@ -9341,10 +9418,17 @@ var state27 = {
9341
9418
  };
9342
9419
  function findMatches(text) {
9343
9420
  if (!text) return [];
9421
+ if (text.length > RE_DOS_MAX_SCAN_LENGTH) return [];
9344
9422
  const found = /* @__PURE__ */ new Set();
9345
9423
  COMBINED_REGEX.lastIndex = 0;
9346
9424
  let m;
9425
+ const startTime = performance.now();
9347
9426
  while ((m = COMBINED_REGEX.exec(text)) !== null) {
9427
+ if (performance.now() - startTime > RE_DOS_TIMEOUT_MS) {
9428
+ throw new Error(
9429
+ `secret-scanner: ReDoS timeout \u2014 regex scan exceeded ${RE_DOS_TIMEOUT_MS}ms on ${text.length}-char input`
9430
+ );
9431
+ }
9348
9432
  for (let i = 0; i < PATTERNS3.length; i++) {
9349
9433
  if (m[i + 1] !== void 0) {
9350
9434
  found.add(PATTERNS3[i].type);
@@ -9357,30 +9441,32 @@ function findMatches(text) {
9357
9441
  }
9358
9442
  return Array.from(found);
9359
9443
  }
9360
- function scanInput(input) {
9444
+ function scanInput(input, depth = 0) {
9361
9445
  if (input === null || input === void 0) return null;
9446
+ if (depth > 50) return null;
9362
9447
  if (typeof input === "string") {
9363
9448
  const found = findMatches(input);
9364
9449
  return found.length > 0 ? found : null;
9365
9450
  }
9366
9451
  if (Array.isArray(input)) {
9367
9452
  for (const item of input) {
9368
- const found = scanInput(item);
9453
+ const found = scanInput(item, depth + 1);
9369
9454
  if (found) return found;
9370
9455
  }
9371
9456
  return null;
9372
9457
  }
9373
9458
  if (typeof input === "object") {
9374
9459
  for (const value of Object.values(input)) {
9375
- const found = scanInput(value);
9460
+ const found = scanInput(value, depth + 1);
9376
9461
  if (found) return found;
9377
9462
  }
9378
9463
  return null;
9379
9464
  }
9380
9465
  return null;
9381
9466
  }
9382
- function redactInput(input) {
9467
+ function redactInput(input, depth = 0) {
9383
9468
  if (input === null || input === void 0) return input;
9469
+ if (depth > 50) return input;
9384
9470
  if (typeof input === "string") {
9385
9471
  return input.replace(COMBINED_REGEX, (_match, ...groups) => {
9386
9472
  for (let i = 0; i < PATTERNS3.length; i++) {
@@ -9392,12 +9478,12 @@ function redactInput(input) {
9392
9478
  });
9393
9479
  }
9394
9480
  if (Array.isArray(input)) {
9395
- return input.map((item) => redactInput(item));
9481
+ return input.map((item) => redactInput(item, depth + 1));
9396
9482
  }
9397
9483
  if (typeof input === "object") {
9398
9484
  const out = {};
9399
9485
  for (const [k, v] of Object.entries(input)) {
9400
- out[k] = redactInput(v);
9486
+ out[k] = redactInput(v, depth + 1);
9401
9487
  }
9402
9488
  return out;
9403
9489
  }
@@ -9691,15 +9777,15 @@ var secret_scanner_default = plugin29;
9691
9777
  import { expectDefined as expectDefined2 } from "@wrongstack/core";
9692
9778
  import { toErrorMessage } from "@wrongstack/core/utils";
9693
9779
  import { execFileSync as execFileSync5 } from "node:child_process";
9694
- import { existsSync as existsSync4, readFileSync as readFileSync6, readdirSync, writeFileSync as writeFileSync6 } from "node:fs";
9695
- import { isAbsolute as isAbsolute10, join as join2, relative as relative9, resolve as resolve9 } from "node:path";
9780
+ import { existsSync as existsSync5, readFileSync as readFileSync7, readdirSync as readdirSync2, writeFileSync as writeFileSync6 } from "node:fs";
9781
+ import { isAbsolute as isAbsolute11, join as join3, relative as relative10, resolve as resolve10 } from "node:path";
9696
9782
  var API_VERSION14 = "^0.1.10";
9697
9783
  function resolveProjectRoot(rawCwd, root = process.cwd()) {
9698
9784
  if (typeof rawCwd !== "string" || rawCwd.length === 0) return root;
9699
- const base = resolve9(root);
9700
- const resolved = isAbsolute10(rawCwd) ? resolve9(rawCwd) : resolve9(base, rawCwd);
9701
- const rel = relative9(base, resolved);
9702
- if (rel === "" || !rel.startsWith("..") && !isAbsolute10(rel)) return resolved;
9785
+ const base = resolve10(root);
9786
+ const resolved = isAbsolute11(rawCwd) ? resolve10(rawCwd) : resolve10(base, rawCwd);
9787
+ const rel = relative10(base, resolved);
9788
+ if (rel === "" || !rel.startsWith("..") && !isAbsolute11(rel)) return resolved;
9703
9789
  return null;
9704
9790
  }
9705
9791
  var state28 = {
@@ -9727,24 +9813,24 @@ function runGit3(args, cwd) {
9727
9813
  }
9728
9814
  function getPackageJson(cwd) {
9729
9815
  const path = cwd ? `${cwd}/package.json` : "package.json";
9730
- if (!existsSync4(path)) return null;
9816
+ if (!existsSync5(path)) return null;
9731
9817
  try {
9732
- return JSON.parse(readFileSync6(path, "utf-8"));
9818
+ return JSON.parse(readFileSync7(path, "utf-8"));
9733
9819
  } catch {
9734
9820
  return null;
9735
9821
  }
9736
9822
  }
9737
9823
  function collectManifests(root) {
9738
9824
  const paths = [];
9739
- const rootPkg = join2(root, "package.json");
9740
- if (existsSync4(rootPkg)) paths.push(rootPkg);
9825
+ const rootPkg = join3(root, "package.json");
9826
+ if (existsSync5(rootPkg)) paths.push(rootPkg);
9741
9827
  for (const group of ["packages", "apps"]) {
9742
- const groupDir = join2(root, group);
9743
- if (!existsSync4(groupDir)) continue;
9744
- for (const entry of readdirSync(groupDir, { withFileTypes: true })) {
9828
+ const groupDir = join3(root, group);
9829
+ if (!existsSync5(groupDir)) continue;
9830
+ for (const entry of readdirSync2(groupDir, { withFileTypes: true })) {
9745
9831
  if (!entry.isDirectory()) continue;
9746
- const candidate = join2(groupDir, entry.name, "package.json");
9747
- if (existsSync4(candidate)) paths.push(candidate);
9832
+ const candidate = join3(groupDir, entry.name, "package.json");
9833
+ if (existsSync5(candidate)) paths.push(candidate);
9748
9834
  }
9749
9835
  }
9750
9836
  return paths;
@@ -9934,9 +10020,9 @@ var plugin30 = {
9934
10020
  };
9935
10021
  }
9936
10022
  const root = cwd ?? process.cwd();
9937
- const bumpScript = join2(root, "scripts", "bump-version.mjs");
10023
+ const bumpScript = join3(root, "scripts", "bump-version.mjs");
9938
10024
  const changed = collectManifests(root);
9939
- if (existsSync4(bumpScript)) {
10025
+ if (existsSync5(bumpScript)) {
9940
10026
  try {
9941
10027
  execFileSync5(process.execPath, [bumpScript, "set", newVersion], {
9942
10028
  cwd: root,
@@ -9949,12 +10035,12 @@ var plugin30 = {
9949
10035
  return { ok: false, error: `bump script failed: ${msg}` };
9950
10036
  }
9951
10037
  for (const rel of ["package.json", "package-lock.json", "src/lib/utils.ts", "index.html"]) {
9952
- const p = join2(root, "website", rel);
9953
- if (existsSync4(p)) changed.push(p);
10038
+ const p = join3(root, "website", rel);
10039
+ if (existsSync5(p)) changed.push(p);
9954
10040
  }
9955
10041
  } else {
9956
10042
  for (const manifest of changed) {
9957
- const pkgData = JSON.parse(readFileSync6(manifest, "utf-8"));
10043
+ const pkgData = JSON.parse(readFileSync7(manifest, "utf-8"));
9958
10044
  pkgData.version = newVersion;
9959
10045
  writeFileSync6(manifest, JSON.stringify(pkgData, null, 2) + "\n", "utf-8");
9960
10046
  }
@@ -10629,16 +10715,16 @@ var session_recap_default = plugin31;
10629
10715
 
10630
10716
  // src/shell-check/index.ts
10631
10717
  import { execFileSync as execFileSync6, execSync as execSync2 } from "node:child_process";
10632
- import { existsSync as existsSync5, readdirSync as readdirSync2 } from "node:fs";
10633
- import { isAbsolute as isAbsolute11, join as join3, relative as relative10, resolve as resolve10 } from "node:path";
10718
+ import { existsSync as existsSync6, readdirSync as readdirSync3 } from "node:fs";
10719
+ import { isAbsolute as isAbsolute12, join as join4, relative as relative11, resolve as resolve11 } from "node:path";
10634
10720
  var API_VERSION15 = "^0.1.10";
10635
10721
  function withinProject3(p) {
10636
10722
  const root = process.cwd();
10637
- const resolved = isAbsolute11(p) ? resolve10(p) : resolve10(root, p);
10638
- const rel = relative10(root, resolved);
10723
+ const resolved = isAbsolute12(p) ? resolve11(p) : resolve11(root, p);
10724
+ const rel = relative11(root, resolved);
10639
10725
  if (rel === "" || rel === ".") return true;
10640
10726
  if (rel.startsWith("..")) return false;
10641
- if (isAbsolute11(rel)) return false;
10727
+ if (isAbsolute12(rel)) return false;
10642
10728
  return true;
10643
10729
  }
10644
10730
  var MAX_PATH_LEN = 4096;
@@ -10651,7 +10737,7 @@ var state30 = {
10651
10737
  lastRun: null
10652
10738
  };
10653
10739
  function runShellCheck(files, severity, cwd) {
10654
- if (!existsSync5("shellcheck")) {
10740
+ if (!existsSync6("shellcheck")) {
10655
10741
  try {
10656
10742
  execSync2("shellcheck --version", { encoding: "utf-8", stdio: "ignore", windowsHide: true });
10657
10743
  } catch {
@@ -10703,9 +10789,9 @@ function runShellCheck(files, severity, cwd) {
10703
10789
  function findShellFiles(dir, pattern) {
10704
10790
  const results = [];
10705
10791
  try {
10706
- const entries = readdirSync2(dir, { withFileTypes: true });
10792
+ const entries = readdirSync3(dir, { withFileTypes: true });
10707
10793
  for (const entry of entries) {
10708
- const full = join3(dir, entry.name);
10794
+ const full = join4(dir, entry.name);
10709
10795
  if (entry.isDirectory() && entry.name !== "node_modules" && entry.name !== ".git") {
10710
10796
  results.push(...findShellFiles(full, pattern));
10711
10797
  } else if (entry.isFile() && (entry.name.endsWith(".sh") || entry.name === "Dockerfile")) {
@@ -10906,7 +10992,7 @@ var plugin32 = {
10906
10992
  var shell_check_default = plugin32;
10907
10993
 
10908
10994
  // src/template-engine/index.ts
10909
- import { isAbsolute as isAbsolute12 } from "node:path";
10995
+ import { isAbsolute as isAbsolute13 } from "node:path";
10910
10996
  var API_VERSION16 = "^0.1.10";
10911
10997
  var templates = /* @__PURE__ */ new Map();
10912
10998
  function expandTemplate(template, variables) {
@@ -10953,7 +11039,7 @@ function renderTemplateRaw(template, variables) {
10953
11039
  return result;
10954
11040
  }
10955
11041
  function validateRelativeTemplatePath(field, value) {
10956
- if (isAbsolute12(value) || value.split(/[\\/]+/).includes("..")) {
11042
+ if (isAbsolute13(value) || value.split(/[\\/]+/).includes("..")) {
10957
11043
  return `${field} must be a relative path without ".." components`;
10958
11044
  }
10959
11045
  return null;
@@ -11080,8 +11166,8 @@ var plugin33 = {
11080
11166
  }
11081
11167
  let content;
11082
11168
  try {
11083
- const { readFileSync: readFileSync25 } = await import("node:fs");
11084
- content = readFileSync25(template_path, "utf-8");
11169
+ const { readFileSync: readFileSync26 } = await import("node:fs");
11170
+ content = readFileSync26(template_path, "utf-8");
11085
11171
  } catch (err) {
11086
11172
  return { ok: false, error: `Could not read template file: ${err}` };
11087
11173
  }
@@ -11214,8 +11300,8 @@ var plugin33 = {
11214
11300
  var template_engine_default = plugin33;
11215
11301
 
11216
11302
  // src/test-coverage-gate/index.ts
11217
- import { readFileSync as readFileSync7 } from "node:fs";
11218
- import { isAbsolute as isAbsolute13, relative as relative11, resolve as resolve11 } from "node:path";
11303
+ import { readFileSync as readFileSync8 } from "node:fs";
11304
+ import { isAbsolute as isAbsolute14, relative as relative12, resolve as resolve12 } from "node:path";
11219
11305
  var API_VERSION17 = "^0.1.10";
11220
11306
  var state31 = {
11221
11307
  invocationCount: 0,
@@ -11251,16 +11337,16 @@ function readConfig27(raw) {
11251
11337
  function withinProject4(p) {
11252
11338
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
11253
11339
  const root = process.cwd();
11254
- const resolved = isAbsolute13(p) ? resolve11(p) : resolve11(root, p);
11255
- const rel = relative11(root, resolved);
11340
+ const resolved = isAbsolute14(p) ? resolve12(p) : resolve12(root, p);
11341
+ const rel = relative12(root, resolved);
11256
11342
  if (rel === "" || rel === ".") return true;
11257
11343
  if (rel.startsWith("..")) return false;
11258
- if (isAbsolute13(rel)) return false;
11344
+ if (isAbsolute14(rel)) return false;
11259
11345
  return true;
11260
11346
  }
11261
11347
  function readCoverageSummary(coveragePath) {
11262
11348
  try {
11263
- const raw = readFileSync7(coveragePath, "utf-8");
11349
+ const raw = readFileSync8(coveragePath, "utf-8");
11264
11350
  return JSON.parse(raw);
11265
11351
  } catch {
11266
11352
  return null;
@@ -11477,7 +11563,7 @@ var test_coverage_gate_default = plugin34;
11477
11563
  // src/test-runner-gate/index.ts
11478
11564
  import { execFile as execFile5 } from "node:child_process";
11479
11565
  import { access } from "node:fs/promises";
11480
- import { basename as basename3, dirname as dirname5, isAbsolute as isAbsolute14, join as join4 } from "node:path";
11566
+ import { basename as basename3, dirname as dirname6, isAbsolute as isAbsolute15, join as join5 } from "node:path";
11481
11567
  var API_VERSION18 = "^0.1.10";
11482
11568
  var state32 = {
11483
11569
  invocationCount: 0,
@@ -11560,7 +11646,7 @@ var ALLOWED_COMMAND_TOKENS = /* @__PURE__ */ new Set([
11560
11646
  function resolveTestFiles(sourcePath, patterns) {
11561
11647
  const name = basename3(sourcePath).replace(/\.[^.]+$/, "");
11562
11648
  const pathNoExt = sourcePath.replace(/\.[^.]+$/, "");
11563
- const dir = dirname5(sourcePath);
11649
+ const dir = dirname6(sourcePath);
11564
11650
  const candidates = [];
11565
11651
  for (const pattern of patterns) {
11566
11652
  const candidate = pattern.replace(/\{name\}/g, name).replace(/\{path\}/g, pathNoExt).replace(/\{dir\}/g, dir);
@@ -11569,7 +11655,7 @@ function resolveTestFiles(sourcePath, patterns) {
11569
11655
  candidates.push(candidate);
11570
11656
  } else {
11571
11657
  candidates.push(candidate);
11572
- candidates.push(join4(dir, candidate));
11658
+ candidates.push(join5(dir, candidate));
11573
11659
  }
11574
11660
  }
11575
11661
  }
@@ -11596,12 +11682,12 @@ async function detectRunner(requested) {
11596
11682
  const match = candidates.find((c) => c.name === requested);
11597
11683
  if (!match) return null;
11598
11684
  try {
11599
- await new Promise((resolve27, reject) => {
11685
+ await new Promise((resolve28, reject) => {
11600
11686
  execFile5("npx", [`${match.name}`, "--version"], {
11601
11687
  encoding: "utf-8",
11602
11688
  timeout: 5e3,
11603
11689
  cwd: process.cwd()
11604
- }, (err) => err ? reject(err) : resolve27());
11690
+ }, (err) => err ? reject(err) : resolve28());
11605
11691
  });
11606
11692
  return match;
11607
11693
  } catch {
@@ -11610,12 +11696,12 @@ async function detectRunner(requested) {
11610
11696
  }
11611
11697
  for (const candidate of candidates) {
11612
11698
  try {
11613
- await new Promise((resolve27, reject) => {
11699
+ await new Promise((resolve28, reject) => {
11614
11700
  execFile5("npx", [`${candidate.name}`, "--version"], {
11615
11701
  encoding: "utf-8",
11616
11702
  timeout: 5e3,
11617
11703
  cwd: process.cwd()
11618
- }, (err) => err ? reject(err) : resolve27());
11704
+ }, (err) => err ? reject(err) : resolve28());
11619
11705
  });
11620
11706
  return candidate;
11621
11707
  } catch {
@@ -11630,7 +11716,7 @@ function resolveAllowedCommand2(customCommand) {
11630
11716
  if (ALLOWED_COMMAND_TOKENS.has(head)) {
11631
11717
  return { cmd: head, args: tokens.slice(1) };
11632
11718
  }
11633
- if (isAbsolute14(head)) {
11719
+ if (isAbsolute15(head)) {
11634
11720
  if (!withinProject(head)) return null;
11635
11721
  const base = basename3(head);
11636
11722
  if (ALLOWED_COMMAND_TOKENS.has(base)) {
@@ -11661,14 +11747,14 @@ async function runTests(testFile, runner, customCommand, timeoutMs) {
11661
11747
  let stdout = "";
11662
11748
  try {
11663
11749
  const { stdout: out } = await new Promise(
11664
- (resolve27, reject) => {
11750
+ (resolve28, reject) => {
11665
11751
  execFile5(
11666
11752
  cmd,
11667
11753
  fullArgs,
11668
11754
  { encoding: "utf-8", timeout: timeoutMs, cwd: process.cwd() },
11669
11755
  (err, out2, stderr) => {
11670
11756
  if (err) reject(Object.assign(err, { stdout: out2, stderr }));
11671
- else resolve27({ stdout: out2, stderr });
11757
+ else resolve28({ stdout: out2, stderr });
11672
11758
  }
11673
11759
  );
11674
11760
  }
@@ -11965,7 +12051,7 @@ var test_runner_gate_default = plugin35;
11965
12051
 
11966
12052
  // src/type-gate/index.ts
11967
12053
  import { execFileSync as execFileSync7 } from "node:child_process";
11968
- import { existsSync as existsSync6 } from "node:fs";
12054
+ import { existsSync as existsSync7 } from "node:fs";
11969
12055
  var API_VERSION19 = "^0.1.10";
11970
12056
  var state33 = {
11971
12057
  invocationCount: 0,
@@ -12038,7 +12124,7 @@ function runTypeCheck(cfg) {
12038
12124
  argv = [...argv, "-p", tsConfig];
12039
12125
  }
12040
12126
  }
12041
- if (!cfg.command && tsConfig && !existsSync6(tsConfig)) {
12127
+ if (!cfg.command && tsConfig && !existsSync7(tsConfig)) {
12042
12128
  return null;
12043
12129
  }
12044
12130
  let stdout = "";
@@ -13233,7 +13319,7 @@ function estimateRequestTokens(request, charsPerToken) {
13233
13319
  walk(request["messages"]);
13234
13320
  return Math.ceil(chars / charsPerToken);
13235
13321
  }
13236
- var sleep = (ms) => new Promise((resolve27) => setTimeout(resolve27, ms));
13322
+ var sleep = (ms) => new Promise((resolve28) => setTimeout(resolve28, ms));
13237
13323
  var plugin40 = {
13238
13324
  name: "token-throttle",
13239
13325
  version: "0.1.0",
@@ -13379,8 +13465,8 @@ var plugin40 = {
13379
13465
  var token_throttle_default = plugin40;
13380
13466
 
13381
13467
  // src/accessibility-auditor/index.ts
13382
- import { existsSync as existsSync7, readFileSync as readFileSync8, readdirSync as readdirSync3, statSync as statSync5 } from "node:fs";
13383
- import { isAbsolute as isAbsolute15, relative as relative12, resolve as resolve12 } from "node:path";
13468
+ import { readFileSync as readFileSync9 } from "node:fs";
13469
+ import { isAbsolute as isAbsolute16, relative as relative13, resolve as resolve13 } from "node:path";
13384
13470
  var API_VERSION21 = "^0.1.10";
13385
13471
  var state38 = {
13386
13472
  auditCount: 0,
@@ -13411,45 +13497,6 @@ function readConfig33(raw) {
13411
13497
  function normalizeExtensions(exts) {
13412
13498
  return exts.map((e) => e.startsWith(".") ? e.toLowerCase() : `.${e.toLowerCase()}`);
13413
13499
  }
13414
- function matchesExtension(p, exts) {
13415
- const dot = p.lastIndexOf(".");
13416
- if (dot === -1) return false;
13417
- return exts.includes(p.slice(dot).toLowerCase());
13418
- }
13419
- function collectUiFiles(root, exts) {
13420
- const files = [];
13421
- if (!existsSync7(root)) return files;
13422
- const s = statSync5(root);
13423
- if (s.isFile()) {
13424
- if (matchesExtension(root, exts)) files.push(root);
13425
- return files;
13426
- }
13427
- if (!s.isDirectory()) return files;
13428
- function walk(dir) {
13429
- let entries;
13430
- try {
13431
- entries = readdirSync3(dir);
13432
- } catch {
13433
- return;
13434
- }
13435
- for (const entry of entries) {
13436
- const full = resolve12(dir, entry);
13437
- let st;
13438
- try {
13439
- st = statSync5(full);
13440
- } catch {
13441
- continue;
13442
- }
13443
- if (st.isDirectory()) {
13444
- walk(full);
13445
- } else if (st.isFile() && matchesExtension(full, exts)) {
13446
- files.push(full);
13447
- }
13448
- }
13449
- }
13450
- walk(root);
13451
- return files;
13452
- }
13453
13500
  var TAG_IMG = /<img\b[^>]*>/gi;
13454
13501
  var TAG_INPUT = /<input\b[^>]*\/?>/gi;
13455
13502
  var TAG_BUTTON = /<button\b[^>]*>([\s\S]*?)<\/button>/gi;
@@ -13470,7 +13517,7 @@ function hasMeaningfulAlt(tag) {
13470
13517
  function auditFile(filePath, projectRoot) {
13471
13518
  let content;
13472
13519
  try {
13473
- content = readFileSync8(filePath, "utf-8");
13520
+ content = readFileSync9(filePath, "utf-8");
13474
13521
  } catch {
13475
13522
  return [];
13476
13523
  }
@@ -13479,7 +13526,7 @@ function auditFile(filePath, projectRoot) {
13479
13526
  const idsByValue = /* @__PURE__ */ new Map();
13480
13527
  function add(line, rule, severity, message) {
13481
13528
  findings.push({
13482
- file: relative12(projectRoot, filePath),
13529
+ file: relative13(projectRoot, filePath),
13483
13530
  line,
13484
13531
  rule,
13485
13532
  severity,
@@ -13558,9 +13605,9 @@ function auditFile(filePath, projectRoot) {
13558
13605
  }
13559
13606
  function auditPath(rawPath, cfg) {
13560
13607
  const root = process.cwd();
13561
- const resolved = isAbsolute15(rawPath) ? resolve12(rawPath) : resolve12(root, rawPath);
13608
+ const resolved = isAbsolute16(rawPath) ? resolve13(rawPath) : resolve13(root, rawPath);
13562
13609
  const exts = normalizeExtensions(cfg.includeExtensions);
13563
- const files = collectUiFiles(resolved, exts);
13610
+ const files = collectSourceFiles(resolved, { extensions: exts });
13564
13611
  const findings = [];
13565
13612
  for (const file of files) {
13566
13613
  const fileFindings = auditFile(file, root);
@@ -13568,7 +13615,7 @@ function auditPath(rawPath, cfg) {
13568
13615
  if (findings.length >= cfg.maxFindings) break;
13569
13616
  }
13570
13617
  return {
13571
- path: relative12(root, resolved),
13618
+ path: relative13(root, resolved),
13572
13619
  findings: findings.slice(0, cfg.maxFindings),
13573
13620
  fileCount: files.length
13574
13621
  };
@@ -13774,8 +13821,8 @@ var accessibility_auditor_default = plugin41;
13774
13821
 
13775
13822
  // src/api-compatibility-gate/index.ts
13776
13823
  import { execFileSync as execFileSync8 } from "node:child_process";
13777
- import { existsSync as existsSync8, readFileSync as readFileSync9 } from "node:fs";
13778
- import { basename as basename4, dirname as dirname6, extname, isAbsolute as isAbsolute16, relative as relative13, resolve as resolve13 } from "node:path";
13824
+ import { existsSync as existsSync8, readFileSync as readFileSync10 } from "node:fs";
13825
+ import { basename as basename4, dirname as dirname7, extname as extname2, isAbsolute as isAbsolute17, relative as relative14, resolve as resolve14 } from "node:path";
13779
13826
  var API_VERSION22 = "^0.1.10";
13780
13827
  var state39 = {
13781
13828
  invocationCount: 0,
@@ -13839,25 +13886,25 @@ function matchesAnyPattern(filePath, patterns) {
13839
13886
  return patterns.some((p) => patternToRegex(p).test(normalized));
13840
13887
  }
13841
13888
  function resolveToProjectRoot(filePath) {
13842
- if (isAbsolute16(filePath)) return resolve13(filePath);
13843
- return resolve13(process.cwd(), filePath);
13889
+ if (isAbsolute17(filePath)) return resolve14(filePath);
13890
+ return resolve14(process.cwd(), filePath);
13844
13891
  }
13845
13892
  function withinProject5(filePath) {
13846
13893
  if (typeof filePath !== "string" || filePath.length === 0 || filePath.length > 4096) return false;
13847
13894
  const resolved = resolveToProjectRoot(filePath);
13848
- const rel = relative13(process.cwd(), resolved);
13895
+ const rel = relative14(process.cwd(), resolved);
13849
13896
  if (rel === "" || rel === ".") return true;
13850
13897
  if (rel.startsWith("..")) return false;
13851
- if (isAbsolute16(rel)) return false;
13898
+ if (isAbsolute17(rel)) return false;
13852
13899
  return true;
13853
13900
  }
13854
13901
  function isPackageEntryPoint(filePath) {
13855
13902
  const resolved = resolveToProjectRoot(filePath);
13856
- const dir = dirname6(resolved);
13857
- const pkgPath = resolve13(dir, "package.json");
13903
+ const dir = dirname7(resolved);
13904
+ const pkgPath = resolve14(dir, "package.json");
13858
13905
  if (!existsSync8(pkgPath)) return false;
13859
13906
  try {
13860
- const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
13907
+ const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
13861
13908
  const entries = [];
13862
13909
  if (pkg.main) entries.push(pkg.main);
13863
13910
  if (pkg.module) entries.push(pkg.module);
@@ -13875,9 +13922,9 @@ function isPackageEntryPoint(filePath) {
13875
13922
  }
13876
13923
  }
13877
13924
  for (const entry of entries) {
13878
- const entryResolved = resolve13(dir, entry);
13925
+ const entryResolved = resolve14(dir, entry);
13879
13926
  if (entryResolved === resolved) return true;
13880
- if (basename4(dirname6(entryResolved)) === basename4(dirname6(resolved)) && basename4(entryResolved, extname(entryResolved)) === basename4(resolved, extname(resolved))) {
13927
+ if (basename4(dirname7(entryResolved)) === basename4(dirname7(resolved)) && basename4(entryResolved, extname2(entryResolved)) === basename4(resolved, extname2(resolved))) {
13881
13928
  return true;
13882
13929
  }
13883
13930
  }
@@ -13928,7 +13975,7 @@ function extractExports(source) {
13928
13975
  }
13929
13976
  function readGitVersion(filePath) {
13930
13977
  const resolved = resolveToProjectRoot(filePath);
13931
- const relPath = normalizePath2(relative13(process.cwd(), resolved));
13978
+ const relPath = normalizePath2(relative14(process.cwd(), resolved));
13932
13979
  try {
13933
13980
  const out = execFileSync8("git", ["show", `HEAD:${relPath}`], {
13934
13981
  encoding: "utf-8",
@@ -13943,7 +13990,7 @@ function readGitVersion(filePath) {
13943
13990
  function readCurrentFile(filePath) {
13944
13991
  try {
13945
13992
  const resolved = resolveToProjectRoot(filePath);
13946
- return readFileSync9(resolved, "utf-8");
13993
+ return readFileSync10(resolved, "utf-8");
13947
13994
  } catch {
13948
13995
  return null;
13949
13996
  }
@@ -14128,7 +14175,7 @@ var plugin42 = {
14128
14175
  var api_compatibility_gate_default = plugin42;
14129
14176
 
14130
14177
  // src/auto-i18n-extractor/index.ts
14131
- import { readFileSync as readFileSync10 } from "node:fs";
14178
+ import { readFileSync as readFileSync11 } from "node:fs";
14132
14179
  var API_VERSION23 = "^0.1.10";
14133
14180
  var state40 = {
14134
14181
  filesScanned: 0,
@@ -14213,7 +14260,7 @@ function extractStrings(content, cfg) {
14213
14260
  }
14214
14261
  function readSourceFile(filePath) {
14215
14262
  try {
14216
- return readFileSync10(filePath, "utf-8");
14263
+ return readFileSync11(filePath, "utf-8");
14217
14264
  } catch {
14218
14265
  return null;
14219
14266
  }
@@ -14449,8 +14496,8 @@ ${lines.join("\n")}${more}`;
14449
14496
  var auto_i18n_extractor_default = plugin43;
14450
14497
 
14451
14498
  // src/code-metrics/index.ts
14452
- import { existsSync as existsSync9, readFileSync as readFileSync11, readdirSync as readdirSync4, statSync as statSync6 } from "node:fs";
14453
- import { extname as extname2, isAbsolute as isAbsolute17, relative as relative14, resolve as resolve14 } from "node:path";
14499
+ import { readFileSync as readFileSync12 } from "node:fs";
14500
+ import { isAbsolute as isAbsolute18, relative as relative15, resolve as resolve15 } from "node:path";
14454
14501
  var API_VERSION24 = "^0.1.10";
14455
14502
  var state41 = {
14456
14503
  measureCount: 0,
@@ -14476,49 +14523,11 @@ function readConfig36(raw) {
14476
14523
  function normalizeExtensions2(exts) {
14477
14524
  return exts.map((e) => e.startsWith(".") ? e.toLowerCase() : `.${e.toLowerCase()}`);
14478
14525
  }
14479
- function matchesExtension2(p, exts) {
14480
- return exts.includes(extname2(p).toLowerCase());
14481
- }
14482
- function collectSourceFiles(root, exts) {
14483
- const files = [];
14484
- if (!existsSync9(root)) return files;
14485
- const s = statSync6(root);
14486
- if (s.isFile()) {
14487
- if (matchesExtension2(root, exts)) files.push(root);
14488
- return files;
14489
- }
14490
- if (!s.isDirectory()) return files;
14491
- function walk(dir) {
14492
- let entries;
14493
- try {
14494
- entries = readdirSync4(dir);
14495
- } catch {
14496
- return;
14497
- }
14498
- for (const entry of entries) {
14499
- if (entry === "node_modules" || entry === "dist" || entry === ".git" || entry === "coverage") continue;
14500
- const full = resolve14(dir, entry);
14501
- let st;
14502
- try {
14503
- st = statSync6(full);
14504
- } catch {
14505
- continue;
14506
- }
14507
- if (st.isDirectory()) {
14508
- walk(full);
14509
- } else if (st.isFile() && matchesExtension2(full, exts)) {
14510
- files.push(full);
14511
- }
14512
- }
14513
- }
14514
- walk(root);
14515
- return files;
14516
- }
14517
14526
  function toPosix(p) {
14518
14527
  return p.replace(/\\/g, "/");
14519
14528
  }
14520
14529
  function relativePath(p) {
14521
- return toPosix(relative14(process.cwd(), p));
14530
+ return toPosix(relative15(process.cwd(), p));
14522
14531
  }
14523
14532
  function countFunctions(content) {
14524
14533
  let count = 0;
@@ -14595,14 +14604,14 @@ function analyzeFile(filePath, content) {
14595
14604
  }
14596
14605
  function measurePath(rawPath, cfg) {
14597
14606
  const root = process.cwd();
14598
- const resolved = isAbsolute17(rawPath) ? resolve14(rawPath) : resolve14(root, rawPath);
14607
+ const resolved = isAbsolute18(rawPath) ? resolve15(rawPath) : resolve15(root, rawPath);
14599
14608
  const exts = normalizeExtensions2(cfg.extensions);
14600
- const allFiles = collectSourceFiles(resolved, exts);
14609
+ const allFiles = collectSourceFiles(resolved, { extensions: exts });
14601
14610
  const files = allFiles.slice(0, cfg.maxFiles);
14602
14611
  const metrics = [];
14603
14612
  for (const p of files) {
14604
14613
  try {
14605
- const content = readFileSync11(p, "utf-8");
14614
+ const content = readFileSync12(p, "utf-8");
14606
14615
  metrics.push(analyzeFile(p, content));
14607
14616
  } catch {
14608
14617
  }
@@ -14656,12 +14665,12 @@ var plugin44 = {
14656
14665
  if (!sourcePath || typeof sourcePath !== "string") return;
14657
14666
  if (!withinProject(sourcePath)) return;
14658
14667
  const exts = normalizeExtensions2(cfg.extensions);
14659
- if (!matchesExtension2(sourcePath, exts)) return;
14668
+ if (!matchesExtension(sourcePath, exts)) return;
14660
14669
  state41.hookInvocationCount += 1;
14661
- const resolved = resolve14(process.cwd(), sourcePath);
14670
+ const resolved = resolve15(process.cwd(), sourcePath);
14662
14671
  let content;
14663
14672
  try {
14664
- content = readFileSync11(resolved, "utf-8");
14673
+ content = readFileSync12(resolved, "utf-8");
14665
14674
  } catch {
14666
14675
  state41.errorCount += 1;
14667
14676
  return;
@@ -14702,7 +14711,7 @@ var plugin44 = {
14702
14711
  state41.fileCount += result.files.length;
14703
14712
  return {
14704
14713
  ok: true,
14705
- path: relativePath(resolve14(process.cwd(), rawPath)),
14714
+ path: relativePath(resolve15(process.cwd(), rawPath)),
14706
14715
  files: result.files,
14707
14716
  totalFiles: result.totalFiles,
14708
14717
  capped: result.totalFiles > cfg.maxFiles
@@ -14773,8 +14782,8 @@ var plugin44 = {
14773
14782
  var code_metrics_default = plugin44;
14774
14783
 
14775
14784
  // src/dead-code-detector/index.ts
14776
- import { readdirSync as readdirSync5, readFileSync as readFileSync12, statSync as statSync7 } from "node:fs";
14777
- import { extname as extname3, join as join5, relative as relative15, resolve as resolve15 } from "node:path";
14785
+ import { readdirSync as readdirSync4, readFileSync as readFileSync13, statSync as statSync6 } from "node:fs";
14786
+ import { extname as extname3, join as join6, relative as relative16, resolve as resolve16 } from "node:path";
14778
14787
  var API_VERSION25 = "^0.1.10";
14779
14788
  var state42 = {
14780
14789
  scanCount: 0,
@@ -14808,24 +14817,24 @@ function gatherFiles(root, depth, cfg) {
14808
14817
  function walk(dir, remaining) {
14809
14818
  let entries;
14810
14819
  try {
14811
- entries = readdirSync5(dir, { withFileTypes: true });
14820
+ entries = readdirSync4(dir, { withFileTypes: true });
14812
14821
  } catch {
14813
14822
  return;
14814
14823
  }
14815
14824
  for (const entry of entries) {
14816
14825
  if (entry.isDirectory()) {
14817
14826
  if (remaining > 0 && !cfg.excludeDirs.includes(entry.name)) {
14818
- walk(join5(dir, entry.name), remaining - 1);
14827
+ walk(join6(dir, entry.name), remaining - 1);
14819
14828
  }
14820
14829
  } else if (entry.isFile()) {
14821
14830
  const ext = extname3(entry.name).toLowerCase();
14822
14831
  if (cfg.extensions.includes(ext)) {
14823
- files.push(join5(dir, entry.name));
14832
+ files.push(join6(dir, entry.name));
14824
14833
  }
14825
14834
  }
14826
14835
  }
14827
14836
  }
14828
- walk(resolve15(root), depth);
14837
+ walk(resolve16(root), depth);
14829
14838
  return files;
14830
14839
  }
14831
14840
  function stripNoise(content) {
@@ -14901,7 +14910,7 @@ function scan(root, depth, cfg) {
14901
14910
  const files = [];
14902
14911
  for (const p of filePaths) {
14903
14912
  try {
14904
- const content = readFileSync12(p, "utf-8");
14913
+ const content = readFileSync13(p, "utf-8");
14905
14914
  files.push({ path: p, content, stripped: stripNoise(content) });
14906
14915
  } catch {
14907
14916
  }
@@ -14909,11 +14918,11 @@ function scan(root, depth, cfg) {
14909
14918
  return { findings: findUnusedSymbols(files), scannedFiles: files.length };
14910
14919
  }
14911
14920
  function resolveScanRoot(rawPath) {
14912
- const resolved = resolve15(process.cwd(), rawPath);
14921
+ const resolved = resolve16(process.cwd(), rawPath);
14913
14922
  try {
14914
- const stats = statSync7(resolved);
14923
+ const stats = statSync6(resolved);
14915
14924
  if (!stats.isDirectory()) {
14916
- return resolve15(resolved, "..");
14925
+ return resolve16(resolved, "..");
14917
14926
  }
14918
14927
  } catch {
14919
14928
  }
@@ -14923,7 +14932,7 @@ function toPosix2(p) {
14923
14932
  return p.replace(/\\/g, "/");
14924
14933
  }
14925
14934
  function relativePath2(p) {
14926
- return toPosix2(relative15(process.cwd(), p));
14935
+ return toPosix2(relative16(process.cwd(), p));
14927
14936
  }
14928
14937
  var plugin45 = {
14929
14938
  name: "dead-code-detector",
@@ -14994,8 +15003,8 @@ var plugin45 = {
14994
15003
  state42.errorCount += 1;
14995
15004
  return;
14996
15005
  }
14997
- const changedFile = resolve15(process.cwd(), sourcePath);
14998
- const relevant = result.findings.filter((f) => resolve15(f.file) === changedFile);
15006
+ const changedFile = resolve16(process.cwd(), sourcePath);
15007
+ const relevant = result.findings.filter((f) => resolve16(f.file) === changedFile);
14999
15008
  if (relevant.length === 0) {
15000
15009
  state42.missCount += 1;
15001
15010
  return;
@@ -15115,7 +15124,7 @@ var dead_code_detector_default = plugin45;
15115
15124
 
15116
15125
  // src/dependency-vulnerability-gate/index.ts
15117
15126
  import { execFileSync as execFileSync9 } from "node:child_process";
15118
- import { existsSync as existsSync10 } from "node:fs";
15127
+ import { existsSync as existsSync9 } from "node:fs";
15119
15128
  var API_VERSION26 = "^0.1.10";
15120
15129
  var state43 = {
15121
15130
  invocations: 0,
@@ -15228,7 +15237,7 @@ function isInstallCommand(input) {
15228
15237
  return INSTALL_RE2.test(command);
15229
15238
  }
15230
15239
  function detectManager() {
15231
- return existsSync10("pnpm-lock.yaml") ? "pnpm" : "npm";
15240
+ return existsSync9("pnpm-lock.yaml") ? "pnpm" : "npm";
15232
15241
  }
15233
15242
  function runAudit(cfg) {
15234
15243
  const manager = detectManager();
@@ -15631,8 +15640,8 @@ Consider mentioning these changes in the documentation.`;
15631
15640
  var doc_sync_guard_default = plugin47;
15632
15641
 
15633
15642
  // src/duplicate-code-detector/index.ts
15634
- import { existsSync as existsSync11, readFileSync as readFileSync13, readdirSync as readdirSync6, statSync as statSync8 } from "node:fs";
15635
- import { extname as extname5, isAbsolute as isAbsolute18, relative as relative16, resolve as resolve16 } from "node:path";
15643
+ import { readFileSync as readFileSync14 } from "node:fs";
15644
+ import { isAbsolute as isAbsolute19, relative as relative17, resolve as resolve17 } from "node:path";
15636
15645
  var API_VERSION28 = "^0.1.10";
15637
15646
  var state45 = {
15638
15647
  scanCount: 0,
@@ -15663,49 +15672,11 @@ function readConfig40(raw) {
15663
15672
  maxFindings: typeof r["maxFindings"] === "number" && r["maxFindings"] >= 1 && r["maxFindings"] <= 500 ? r["maxFindings"] : DEFAULTS37.maxFindings
15664
15673
  };
15665
15674
  }
15666
- function matchesExtension3(p, exts) {
15667
- const ext = extname5(p).toLowerCase();
15668
- return exts.includes(ext);
15669
- }
15670
- function collectSourceFiles2(root, cfg) {
15671
- const files = [];
15672
- if (!existsSync11(root)) return files;
15673
- const s = statSync8(root);
15674
- if (s.isFile()) {
15675
- if (matchesExtension3(root, cfg.extensions)) files.push(root);
15676
- return files;
15677
- }
15678
- if (!s.isDirectory()) return files;
15679
- function walk(dir) {
15680
- let entries;
15681
- try {
15682
- entries = readdirSync6(dir);
15683
- } catch {
15684
- return;
15685
- }
15686
- for (const entry of entries) {
15687
- const full = resolve16(dir, entry);
15688
- let st;
15689
- try {
15690
- st = statSync8(full);
15691
- } catch {
15692
- continue;
15693
- }
15694
- if (st.isDirectory()) {
15695
- if (!cfg.excludeDirs.includes(entry)) walk(full);
15696
- } else if (st.isFile() && matchesExtension3(full, cfg.extensions)) {
15697
- files.push(full);
15698
- }
15699
- }
15700
- }
15701
- walk(root);
15702
- return files;
15703
- }
15704
15675
  function toPosix3(p) {
15705
15676
  return p.replace(/\\/g, "/");
15706
15677
  }
15707
15678
  function relativePath3(p) {
15708
- return toPosix3(relative16(process.cwd(), p));
15679
+ return toPosix3(relative17(process.cwd(), p));
15709
15680
  }
15710
15681
  function removeInlineComments(line) {
15711
15682
  return line.replace(/\/\/.*$/, "").replace(/\/\*[\s\S]*?\*\//, "");
@@ -15763,12 +15734,12 @@ function findDuplicates(files, minLines, maxFindings) {
15763
15734
  }
15764
15735
  function scanPath(rawPath, cfg) {
15765
15736
  const root = process.cwd();
15766
- const resolved = isAbsolute18(rawPath) ? resolve16(rawPath) : resolve16(root, rawPath);
15767
- const filePaths = collectSourceFiles2(resolved, cfg);
15737
+ const resolved = isAbsolute19(rawPath) ? resolve17(rawPath) : resolve17(root, rawPath);
15738
+ const filePaths = collectSourceFiles(resolved, { extensions: cfg.extensions, excludeDirs: cfg.excludeDirs });
15768
15739
  const files = /* @__PURE__ */ new Map();
15769
15740
  for (const p of filePaths) {
15770
15741
  try {
15771
- files.set(p, readFileSync13(p, "utf-8"));
15742
+ files.set(p, readFileSync14(p, "utf-8"));
15772
15743
  } catch {
15773
15744
  }
15774
15745
  }
@@ -15848,24 +15819,24 @@ var plugin48 = {
15848
15819
  const now = Date.now();
15849
15820
  const lastWarning = state45.lastHookWarning.get(sourcePath);
15850
15821
  if (lastWarning !== void 0 && now - lastWarning < 6e4) return;
15851
- const changedFile = resolve16(process.cwd(), sourcePath);
15822
+ const changedFile = resolve17(process.cwd(), sourcePath);
15852
15823
  let content;
15853
15824
  try {
15854
- content = readFileSync13(changedFile, "utf-8");
15825
+ content = readFileSync14(changedFile, "utf-8");
15855
15826
  } catch {
15856
15827
  state45.errorCount += 1;
15857
15828
  return;
15858
15829
  }
15859
15830
  const changedWindows = extractWindows(changedFile, content, cfg.minLines);
15860
15831
  if (changedWindows.length === 0) return;
15861
- const projectRoot = resolve16(process.cwd());
15832
+ const projectRoot = resolve17(process.cwd());
15862
15833
  let otherFiles;
15863
15834
  try {
15864
- const filePaths = collectSourceFiles2(projectRoot, cfg).filter((p) => p !== changedFile);
15835
+ const filePaths = collectSourceFiles(projectRoot, { extensions: cfg.extensions, excludeDirs: cfg.excludeDirs }).filter((p) => p !== changedFile);
15865
15836
  otherFiles = /* @__PURE__ */ new Map();
15866
15837
  for (const p of filePaths) {
15867
15838
  try {
15868
- otherFiles.set(p, readFileSync13(p, "utf-8"));
15839
+ otherFiles.set(p, readFileSync14(p, "utf-8"));
15869
15840
  } catch {
15870
15841
  }
15871
15842
  }
@@ -15924,7 +15895,7 @@ var plugin48 = {
15924
15895
  state45.findingCount += result.findings.length;
15925
15896
  return {
15926
15897
  ok: true,
15927
- path: relativePath3(resolve16(process.cwd(), rawPath)),
15898
+ path: relativePath3(resolve17(process.cwd(), rawPath)),
15928
15899
  scannedFiles: result.scannedFiles,
15929
15900
  minLines: cfg.minLines,
15930
15901
  findings: result.findings
@@ -16003,8 +15974,8 @@ var plugin48 = {
16003
15974
  var duplicate_code_detector_default = plugin48;
16004
15975
 
16005
15976
  // src/feature-flag-tracker/index.ts
16006
- import { existsSync as existsSync12, readFileSync as readFileSync14, readdirSync as readdirSync7, statSync as statSync9 } from "node:fs";
16007
- import { extname as extname6, isAbsolute as isAbsolute19, relative as relative17, resolve as resolve17 } from "node:path";
15977
+ import { readFileSync as readFileSync15 } from "node:fs";
15978
+ import { isAbsolute as isAbsolute20, relative as relative18, resolve as resolve18 } from "node:path";
16008
15979
  var API_VERSION29 = "^0.1.10";
16009
15980
  var state46 = {
16010
15981
  scanCount: 0,
@@ -16039,49 +16010,11 @@ function readConfig41(raw) {
16039
16010
  function normalizeExtensions3(exts) {
16040
16011
  return exts.map((e) => e.startsWith(".") ? e.toLowerCase() : `.${e.toLowerCase()}`);
16041
16012
  }
16042
- function matchesExtension4(p, exts) {
16043
- return exts.includes(extname6(p).toLowerCase());
16044
- }
16045
- function collectSourceFiles3(root, exts) {
16046
- const files = [];
16047
- if (!existsSync12(root)) return files;
16048
- const s = statSync9(root);
16049
- if (s.isFile()) {
16050
- if (matchesExtension4(root, exts)) files.push(root);
16051
- return files;
16052
- }
16053
- if (!s.isDirectory()) return files;
16054
- function walk(dir) {
16055
- let entries;
16056
- try {
16057
- entries = readdirSync7(dir);
16058
- } catch {
16059
- return;
16060
- }
16061
- for (const entry of entries) {
16062
- if (entry === "node_modules" || entry === "dist" || entry === ".git" || entry === "coverage") continue;
16063
- const full = resolve17(dir, entry);
16064
- let st;
16065
- try {
16066
- st = statSync9(full);
16067
- } catch {
16068
- continue;
16069
- }
16070
- if (st.isDirectory()) {
16071
- walk(full);
16072
- } else if (st.isFile() && matchesExtension4(full, exts)) {
16073
- files.push(full);
16074
- }
16075
- }
16076
- }
16077
- walk(root);
16078
- return files;
16079
- }
16080
16013
  function toPosix4(p) {
16081
16014
  return p.replace(/\\/g, "/");
16082
16015
  }
16083
16016
  function relativePath4(p) {
16084
- return toPosix4(relative17(process.cwd(), p));
16017
+ return toPosix4(relative18(process.cwd(), p));
16085
16018
  }
16086
16019
  function compilePatterns(patterns) {
16087
16020
  const sources = [...DEFAULT_PATTERNS2, ...patterns];
@@ -16111,14 +16044,14 @@ function scanFile(filePath, content, patterns, maxFindings) {
16111
16044
  }
16112
16045
  function scanPath2(rawPath, cfg) {
16113
16046
  const root = process.cwd();
16114
- const resolved = isAbsolute19(rawPath) ? resolve17(rawPath) : resolve17(root, rawPath);
16047
+ const resolved = isAbsolute20(rawPath) ? resolve18(rawPath) : resolve18(root, rawPath);
16115
16048
  const exts = normalizeExtensions3(cfg.extensions);
16116
- const files = collectSourceFiles3(resolved, exts);
16049
+ const files = collectSourceFiles(resolved, { extensions: exts });
16117
16050
  const patterns = compilePatterns(cfg.patterns);
16118
16051
  const usages = [];
16119
16052
  for (const p of files) {
16120
16053
  try {
16121
- const content = readFileSync14(p, "utf-8");
16054
+ const content = readFileSync15(p, "utf-8");
16122
16055
  usages.push(...scanFile(p, content, patterns, cfg.maxFindings));
16123
16056
  if (usages.length >= cfg.maxFindings) break;
16124
16057
  } catch {
@@ -16180,12 +16113,12 @@ var plugin49 = {
16180
16113
  if (!sourcePath || typeof sourcePath !== "string") return;
16181
16114
  if (!withinProject(sourcePath)) return;
16182
16115
  const exts = normalizeExtensions3(cfg.extensions);
16183
- if (!matchesExtension4(sourcePath, exts)) return;
16116
+ if (!matchesExtension(sourcePath, exts)) return;
16184
16117
  state46.hookInvocationCount += 1;
16185
- const resolved = resolve17(process.cwd(), sourcePath);
16118
+ const resolved = resolve18(process.cwd(), sourcePath);
16186
16119
  let content;
16187
16120
  try {
16188
- content = readFileSync14(resolved, "utf-8");
16121
+ content = readFileSync15(resolved, "utf-8");
16189
16122
  } catch {
16190
16123
  state46.errorCount += 1;
16191
16124
  return;
@@ -16231,7 +16164,7 @@ Make sure flag behavior is intentional and consider updating flag inventory/docs
16231
16164
  state46.flagCount += result.usages.length;
16232
16165
  return {
16233
16166
  ok: true,
16234
- path: relativePath4(resolve17(process.cwd(), rawPath)),
16167
+ path: relativePath4(resolve18(process.cwd(), rawPath)),
16235
16168
  scannedFiles: result.scannedFiles,
16236
16169
  usages: result.usages
16237
16170
  };
@@ -16306,8 +16239,8 @@ Make sure flag behavior is intentional and consider updating flag inventory/docs
16306
16239
  var feature_flag_tracker_default = plugin49;
16307
16240
 
16308
16241
  // src/interface-contract-guard/index.ts
16309
- import { existsSync as existsSync13, readFileSync as readFileSync15, readdirSync as readdirSync8, statSync as statSync10 } from "node:fs";
16310
- import { extname as extname7, isAbsolute as isAbsolute20, relative as relative18, resolve as resolve18 } from "node:path";
16242
+ import { readFileSync as readFileSync16 } from "node:fs";
16243
+ import { isAbsolute as isAbsolute21, relative as relative19, resolve as resolve19 } from "node:path";
16311
16244
  var API_VERSION30 = "^0.1.10";
16312
16245
  var state47 = {
16313
16246
  scanCount: 0,
@@ -16334,49 +16267,11 @@ function readConfig42(raw) {
16334
16267
  function normalizeExtensions4(exts) {
16335
16268
  return exts.map((e) => e.startsWith(".") ? e.toLowerCase() : `.${e.toLowerCase()}`);
16336
16269
  }
16337
- function matchesExtension5(p, exts) {
16338
- return exts.includes(extname7(p).toLowerCase());
16339
- }
16340
- function collectSourceFiles4(root, exts) {
16341
- const files = [];
16342
- if (!existsSync13(root)) return files;
16343
- const s = statSync10(root);
16344
- if (s.isFile()) {
16345
- if (matchesExtension5(root, exts)) files.push(root);
16346
- return files;
16347
- }
16348
- if (!s.isDirectory()) return files;
16349
- function walk(dir) {
16350
- let entries;
16351
- try {
16352
- entries = readdirSync8(dir);
16353
- } catch {
16354
- return;
16355
- }
16356
- for (const entry of entries) {
16357
- if (entry === "node_modules" || entry === "dist" || entry === ".git" || entry === "coverage") continue;
16358
- const full = resolve18(dir, entry);
16359
- let st;
16360
- try {
16361
- st = statSync10(full);
16362
- } catch {
16363
- continue;
16364
- }
16365
- if (st.isDirectory()) {
16366
- walk(full);
16367
- } else if (st.isFile() && matchesExtension5(full, exts)) {
16368
- files.push(full);
16369
- }
16370
- }
16371
- }
16372
- walk(root);
16373
- return files;
16374
- }
16375
16270
  function toPosix5(p) {
16376
16271
  return p.replace(/\\/g, "/");
16377
16272
  }
16378
16273
  function relativePath5(p) {
16379
- return toPosix5(relative18(process.cwd(), p));
16274
+ return toPosix5(relative19(process.cwd(), p));
16380
16275
  }
16381
16276
  var INTERFACE_RE = /(?:export\s+)?interface\s+([A-Za-z_$][A-Za-z0-9_$]*)/g;
16382
16277
  function extractInterfaceNames(content) {
@@ -16396,13 +16291,13 @@ function hasImplementer(name, contents) {
16396
16291
  }
16397
16292
  function scanPath3(rawPath, cfg) {
16398
16293
  const root = process.cwd();
16399
- const resolved = isAbsolute20(rawPath) ? resolve18(rawPath) : resolve18(root, rawPath);
16294
+ const resolved = isAbsolute21(rawPath) ? resolve19(rawPath) : resolve19(root, rawPath);
16400
16295
  const exts = normalizeExtensions4(cfg.extensions);
16401
- const files = collectSourceFiles4(resolved, exts);
16296
+ const files = collectSourceFiles(resolved, { extensions: exts });
16402
16297
  const contents = [];
16403
16298
  for (const p of files) {
16404
16299
  try {
16405
- contents.push({ path: p, content: readFileSync15(p, "utf-8") });
16300
+ contents.push({ path: p, content: readFileSync16(p, "utf-8") });
16406
16301
  } catch {
16407
16302
  }
16408
16303
  }
@@ -16472,12 +16367,12 @@ var plugin50 = {
16472
16367
  if (!sourcePath || typeof sourcePath !== "string") return;
16473
16368
  if (!withinProject(sourcePath)) return;
16474
16369
  const exts = normalizeExtensions4(cfg.extensions);
16475
- if (!matchesExtension5(sourcePath, exts)) return;
16370
+ if (!matchesExtension(sourcePath, exts)) return;
16476
16371
  state47.hookInvocationCount += 1;
16477
- const resolved = resolve18(process.cwd(), sourcePath);
16372
+ const resolved = resolve19(process.cwd(), sourcePath);
16478
16373
  let content;
16479
16374
  try {
16480
- content = readFileSync15(resolved, "utf-8");
16375
+ content = readFileSync16(resolved, "utf-8");
16481
16376
  } catch {
16482
16377
  state47.errorCount += 1;
16483
16378
  return;
@@ -16522,7 +16417,7 @@ If you changed member shapes, search the project for implementers/\`satisfies\`/
16522
16417
  state47.findingCount += result.findings.length;
16523
16418
  return {
16524
16419
  ok: true,
16525
- path: relativePath5(resolve18(process.cwd(), rawPath)),
16420
+ path: relativePath5(resolve19(process.cwd(), rawPath)),
16526
16421
  scannedFiles: result.scannedFiles,
16527
16422
  findings: result.findings
16528
16423
  };
@@ -16595,8 +16490,8 @@ If you changed member shapes, search the project for implementers/\`satisfies\`/
16595
16490
  var interface_contract_guard_default = plugin50;
16596
16491
 
16597
16492
  // src/license-audit-gate/index.ts
16598
- import { readFileSync as readFileSync16 } from "node:fs";
16599
- import { resolve as resolve19 } from "node:path";
16493
+ import { readFileSync as readFileSync17 } from "node:fs";
16494
+ import { resolve as resolve20 } from "node:path";
16600
16495
  var API_VERSION31 = "^0.1.10";
16601
16496
  var state48 = {
16602
16497
  invocations: 0,
@@ -16672,8 +16567,8 @@ function auditPackages(names, allowedLicenses) {
16672
16567
  for (const name of names) {
16673
16568
  let licenses = [];
16674
16569
  try {
16675
- const pkgPath = resolve19("node_modules", name, "package.json");
16676
- const raw = JSON.parse(readFileSync16(pkgPath, "utf-8"));
16570
+ const pkgPath = resolve20("node_modules", name, "package.json");
16571
+ const raw = JSON.parse(readFileSync17(pkgPath, "utf-8"));
16677
16572
  licenses = extractLicenseStrings(raw);
16678
16573
  } catch {
16679
16574
  errors.push(name);
@@ -16852,7 +16747,7 @@ Allowed licenses: ${cfg.allowedLicenses.join(", ")}
16852
16747
  var license_audit_gate_default = plugin51;
16853
16748
 
16854
16749
  // src/migration-planner/index.ts
16855
- import { existsSync as existsSync14, readFileSync as readFileSync17 } from "node:fs";
16750
+ import { existsSync as existsSync10, readFileSync as readFileSync18 } from "node:fs";
16856
16751
  var API_VERSION32 = "^0.1.10";
16857
16752
  var state49 = {
16858
16753
  plansGenerated: 0,
@@ -16890,9 +16785,9 @@ function readChangelog(packageName, cfg) {
16890
16785
  candidates.push(`node_modules/${packageName}/changelog.md`);
16891
16786
  for (const candidate of candidates) {
16892
16787
  if (!withinProject(candidate)) continue;
16893
- if (existsSync14(candidate)) {
16788
+ if (existsSync10(candidate)) {
16894
16789
  try {
16895
- const content = readFileSync17(candidate, "utf-8");
16790
+ const content = readFileSync18(candidate, "utf-8");
16896
16791
  return { source: candidate, content: content.slice(0, cfg.maxChars) };
16897
16792
  } catch {
16898
16793
  }
@@ -17314,8 +17209,8 @@ var plugin52 = {
17314
17209
  var migration_planner_default = plugin52;
17315
17210
 
17316
17211
  // src/performance-regression-gate/index.ts
17317
- import { existsSync as existsSync15, readFileSync as readFileSync18 } from "node:fs";
17318
- import { isAbsolute as isAbsolute21, relative as relative19, resolve as resolve20 } from "node:path";
17212
+ import { existsSync as existsSync11, readFileSync as readFileSync19 } from "node:fs";
17213
+ import { isAbsolute as isAbsolute22, relative as relative20, resolve as resolve21 } from "node:path";
17319
17214
  var API_VERSION33 = "^0.1.10";
17320
17215
  var state50 = {
17321
17216
  invocationCount: 0,
@@ -17340,18 +17235,18 @@ function readConfig45(raw) {
17340
17235
  }
17341
17236
  function withinProject6(p, cwd = process.cwd()) {
17342
17237
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
17343
- const root = resolve20(cwd);
17344
- const resolved = isAbsolute21(p) ? resolve20(p) : resolve20(root, p);
17345
- const rel = relative19(root, resolved);
17238
+ const root = resolve21(cwd);
17239
+ const resolved = isAbsolute22(p) ? resolve21(p) : resolve21(root, p);
17240
+ const rel = relative20(root, resolved);
17346
17241
  if (rel === "" || rel === ".") return true;
17347
17242
  if (rel.startsWith("..")) return false;
17348
- if (isAbsolute21(rel)) return false;
17243
+ if (isAbsolute22(rel)) return false;
17349
17244
  return true;
17350
17245
  }
17351
17246
  function resolveProjectPath7(rawPath, cwd = process.cwd()) {
17352
17247
  if (typeof rawPath !== "string" || rawPath.length === 0) return null;
17353
- const root = resolve20(cwd);
17354
- const resolved = isAbsolute21(rawPath) ? resolve20(rawPath) : resolve20(root, rawPath);
17248
+ const root = resolve21(cwd);
17249
+ const resolved = isAbsolute22(rawPath) ? resolve21(rawPath) : resolve21(root, rawPath);
17355
17250
  if (!withinProject6(resolved, cwd)) return null;
17356
17251
  return resolved;
17357
17252
  }
@@ -17380,9 +17275,9 @@ function flattenResults(results) {
17380
17275
  return flat;
17381
17276
  }
17382
17277
  function loadResults(path) {
17383
- if (!path || !existsSync15(path)) return null;
17278
+ if (!path || !existsSync11(path)) return null;
17384
17279
  try {
17385
- const raw = JSON.parse(readFileSync18(path, "utf-8"));
17280
+ const raw = JSON.parse(readFileSync19(path, "utf-8"));
17386
17281
  return raw;
17387
17282
  } catch {
17388
17283
  return null;
@@ -17627,8 +17522,8 @@ var plugin53 = {
17627
17522
  var performance_regression_gate_default = plugin53;
17628
17523
 
17629
17524
  // src/refactor-suggester/index.ts
17630
- import { existsSync as existsSync16, readFileSync as readFileSync19, readdirSync as readdirSync9, statSync as statSync11 } from "node:fs";
17631
- import { extname as extname8, isAbsolute as isAbsolute22, relative as relative20, resolve as resolve21 } from "node:path";
17525
+ import { readFileSync as readFileSync20 } from "node:fs";
17526
+ import { isAbsolute as isAbsolute23, relative as relative21, resolve as resolve22 } from "node:path";
17632
17527
  var API_VERSION34 = "^0.1.10";
17633
17528
  var state51 = {
17634
17529
  scanCount: 0,
@@ -17667,49 +17562,11 @@ function readConfig46(raw) {
17667
17562
  function normalizeExtensions5(exts) {
17668
17563
  return exts.map((e) => e.startsWith(".") ? e.toLowerCase() : `.${e.toLowerCase()}`);
17669
17564
  }
17670
- function matchesExtension6(p, exts) {
17671
- return exts.includes(extname8(p).toLowerCase());
17672
- }
17673
- function collectSourceFiles5(root, exts) {
17674
- const files = [];
17675
- if (!existsSync16(root)) return files;
17676
- const s = statSync11(root);
17677
- if (s.isFile()) {
17678
- if (matchesExtension6(root, exts)) files.push(root);
17679
- return files;
17680
- }
17681
- if (!s.isDirectory()) return files;
17682
- function walk(dir) {
17683
- let entries;
17684
- try {
17685
- entries = readdirSync9(dir);
17686
- } catch {
17687
- return;
17688
- }
17689
- for (const entry of entries) {
17690
- if (entry === "node_modules" || entry === "dist" || entry === ".git" || entry === "coverage") continue;
17691
- const full = resolve21(dir, entry);
17692
- let st;
17693
- try {
17694
- st = statSync11(full);
17695
- } catch {
17696
- continue;
17697
- }
17698
- if (st.isDirectory()) {
17699
- walk(full);
17700
- } else if (st.isFile() && matchesExtension6(full, exts)) {
17701
- files.push(full);
17702
- }
17703
- }
17704
- }
17705
- walk(root);
17706
- return files;
17707
- }
17708
17565
  function toPosix6(p) {
17709
17566
  return p.replace(/\\/g, "/");
17710
17567
  }
17711
17568
  function relativePath6(p) {
17712
- return toPosix6(relative20(process.cwd(), p));
17569
+ return toPosix6(relative21(process.cwd(), p));
17713
17570
  }
17714
17571
  function leadingIndentLevel(line) {
17715
17572
  const leading = line.match(/^(\s*)/)?.[1] ?? "";
@@ -17796,13 +17653,13 @@ function detectSmells(filePath, content, rules) {
17796
17653
  }
17797
17654
  function scanPath4(rawPath, cfg) {
17798
17655
  const root = process.cwd();
17799
- const resolved = isAbsolute22(rawPath) ? resolve21(rawPath) : resolve21(root, rawPath);
17656
+ const resolved = isAbsolute23(rawPath) ? resolve22(rawPath) : resolve22(root, rawPath);
17800
17657
  const exts = normalizeExtensions5(cfg.extensions);
17801
- const files = collectSourceFiles5(resolved, exts);
17658
+ const files = collectSourceFiles(resolved, { extensions: exts });
17802
17659
  const suggestions = [];
17803
17660
  for (const p of files) {
17804
17661
  try {
17805
- const content = readFileSync19(p, "utf-8");
17662
+ const content = readFileSync20(p, "utf-8");
17806
17663
  suggestions.push(...detectSmells(p, content, cfg.rules));
17807
17664
  if (suggestions.length >= cfg.maxSuggestions) break;
17808
17665
  } catch {
@@ -17867,15 +17724,15 @@ var plugin54 = {
17867
17724
  if (!sourcePath || typeof sourcePath !== "string") return;
17868
17725
  if (!withinProject(sourcePath)) return;
17869
17726
  const exts = normalizeExtensions5(cfg.extensions);
17870
- if (!matchesExtension6(sourcePath, exts)) return;
17727
+ if (!matchesExtension(sourcePath, exts)) return;
17871
17728
  state51.hookInvocationCount += 1;
17872
17729
  const now = Date.now();
17873
17730
  const lastWarning = state51.lastHookWarning.get(sourcePath);
17874
17731
  if (lastWarning !== void 0 && now - lastWarning < 6e4) return;
17875
- const resolved = resolve21(process.cwd(), sourcePath);
17732
+ const resolved = resolve22(process.cwd(), sourcePath);
17876
17733
  let content;
17877
17734
  try {
17878
- content = readFileSync19(resolved, "utf-8");
17735
+ content = readFileSync20(resolved, "utf-8");
17879
17736
  } catch {
17880
17737
  state51.errorCount += 1;
17881
17738
  return;
@@ -17919,7 +17776,7 @@ var plugin54 = {
17919
17776
  state51.suggestionCount += result.suggestions.length;
17920
17777
  return {
17921
17778
  ok: true,
17922
- path: relativePath6(resolve21(process.cwd(), rawPath)),
17779
+ path: relativePath6(resolve22(process.cwd(), rawPath)),
17923
17780
  scannedFiles: result.scannedFiles,
17924
17781
  suggestions: result.suggestions,
17925
17782
  rules: cfg.rules
@@ -18322,7 +18179,7 @@ var plugin55 = {
18322
18179
  var release_notes_generator_default = plugin55;
18323
18180
 
18324
18181
  // src/schema-evolution-guard/index.ts
18325
- import { readFileSync as readFileSync20 } from "node:fs";
18182
+ import { readFileSync as readFileSync21 } from "node:fs";
18326
18183
  import { basename as basename6 } from "node:path";
18327
18184
  var API_VERSION36 = "^0.1.10";
18328
18185
  var state53 = {
@@ -18525,7 +18382,7 @@ var plugin56 = {
18525
18382
  content = toolInput["content"];
18526
18383
  } else if (withinProject(filePath)) {
18527
18384
  try {
18528
- content = readFileSync20(filePath, "utf-8");
18385
+ content = readFileSync21(filePath, "utf-8");
18529
18386
  } catch {
18530
18387
  content = void 0;
18531
18388
  }
@@ -18629,8 +18486,8 @@ ${body}${suffix}`;
18629
18486
  var schema_evolution_guard_default = plugin56;
18630
18487
 
18631
18488
  // src/security-hotspot-scanner/index.ts
18632
- import { readdirSync as readdirSync10, readFileSync as readFileSync21, statSync as statSync12 } from "node:fs";
18633
- import { isAbsolute as isAbsolute23, relative as relative21, resolve as resolve22 } from "node:path";
18489
+ import { readdirSync as readdirSync5, readFileSync as readFileSync22, statSync as statSync7 } from "node:fs";
18490
+ import { isAbsolute as isAbsolute24, relative as relative22, resolve as resolve23 } from "node:path";
18634
18491
  var API_VERSION37 = "^0.1.10";
18635
18492
  var state54 = {
18636
18493
  scanCount: 0,
@@ -18715,7 +18572,7 @@ function isSourceFile2(filePath, extensions) {
18715
18572
  function scanPath5(inputPath, cfg) {
18716
18573
  const start = Date.now();
18717
18574
  const root = process.cwd();
18718
- const resolved = isAbsolute23(inputPath) ? resolve22(inputPath) : resolve22(root, inputPath);
18575
+ const resolved = isAbsolute24(inputPath) ? resolve23(inputPath) : resolve23(root, inputPath);
18719
18576
  if (!withinProject(inputPath)) {
18720
18577
  return {
18721
18578
  path: inputPath,
@@ -18732,11 +18589,11 @@ function scanPath5(inputPath, cfg) {
18732
18589
  const scanFile2 = (filePath) => {
18733
18590
  if (!isSourceFile2(filePath, cfg.scanOnChange)) return;
18734
18591
  try {
18735
- const content = readFileSync21(filePath, "utf-8");
18592
+ const content = readFileSync22(filePath, "utf-8");
18736
18593
  filesScanned += 1;
18737
18594
  const findings = scanSource(content, maxPerFile);
18738
18595
  for (const f of findings) {
18739
- allFindings.push({ ...f, snippet: `${relative21(root, filePath)}:${f.line}: ${f.snippet}` });
18596
+ allFindings.push({ ...f, snippet: `${relative22(root, filePath)}:${f.line}: ${f.snippet}` });
18740
18597
  if (allFindings.length >= cfg.maxFindings) return;
18741
18598
  }
18742
18599
  } catch {
@@ -18745,15 +18602,15 @@ function scanPath5(inputPath, cfg) {
18745
18602
  const walk = (dir) => {
18746
18603
  let entries;
18747
18604
  try {
18748
- entries = readdirSync10(dir);
18605
+ entries = readdirSync5(dir);
18749
18606
  } catch {
18750
18607
  return;
18751
18608
  }
18752
18609
  for (const entry of entries) {
18753
18610
  if (allFindings.length >= cfg.maxFindings) return;
18754
- const full = resolve22(dir, entry);
18611
+ const full = resolve23(dir, entry);
18755
18612
  try {
18756
- const st = statSync12(full);
18613
+ const st = statSync7(full);
18757
18614
  if (st.isDirectory()) {
18758
18615
  if (entry.startsWith(".") || entry === "node_modules" || entry === "dist" || entry === "coverage") {
18759
18616
  continue;
@@ -18767,7 +18624,7 @@ function scanPath5(inputPath, cfg) {
18767
18624
  }
18768
18625
  };
18769
18626
  try {
18770
- const st = statSync12(resolved);
18627
+ const st = statSync7(resolved);
18771
18628
  if (st.isDirectory()) {
18772
18629
  walk(resolved);
18773
18630
  } else if (st.isFile()) {
@@ -19020,7 +18877,7 @@ var security_hotspot_scanner_default = plugin57;
19020
18877
 
19021
18878
  // src/semantic-search-indexer/index.ts
19022
18879
  import * as fs2 from "node:fs/promises";
19023
- import { isAbsolute as isAbsolute24, relative as relative22, resolve as resolve23 } from "node:path";
18880
+ import { isAbsolute as isAbsolute25, relative as relative23, resolve as resolve24 } from "node:path";
19024
18881
  var API_VERSION38 = "^0.1.10";
19025
18882
  var state55 = {
19026
18883
  index: null,
@@ -19095,18 +18952,18 @@ function normalizeSlashes2(p) {
19095
18952
  function withinProject7(p) {
19096
18953
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
19097
18954
  const root = normalizeSlashes2(process.cwd());
19098
- const resolved = normalizeSlashes2(isAbsolute24(p) ? resolve23(p) : resolve23(root, p));
19099
- const rel = normalizeSlashes2(relative22(root, resolved));
18955
+ const resolved = normalizeSlashes2(isAbsolute25(p) ? resolve24(p) : resolve24(root, p));
18956
+ const rel = normalizeSlashes2(relative23(root, resolved));
19100
18957
  if (rel === "" || rel === ".") return true;
19101
18958
  if (rel.startsWith("..")) return false;
19102
- if (isAbsolute24(rel)) return false;
18959
+ if (isAbsolute25(rel)) return false;
19103
18960
  return true;
19104
18961
  }
19105
18962
  function resolveProjectPath8(p) {
19106
18963
  const raw = typeof p === "string" && p.length > 0 ? p : ".";
19107
18964
  if (!withinProject7(raw)) return null;
19108
18965
  const root = normalizeSlashes2(process.cwd());
19109
- return normalizeSlashes2(isAbsolute24(raw) ? resolve23(raw) : resolve23(root, raw));
18966
+ return normalizeSlashes2(isAbsolute25(raw) ? resolve24(raw) : resolve24(root, raw));
19110
18967
  }
19111
18968
  function tokenize(text, minLength) {
19112
18969
  const tokens = [];
@@ -19136,7 +18993,7 @@ function shouldIndexFile(filePath, cfg) {
19136
18993
  var INDEX_BATCH_SIZE = 32;
19137
18994
  var YIELD_EVERY_FILES = 64;
19138
18995
  function yieldEventLoop() {
19139
- return new Promise((resolve27) => setImmediate(resolve27));
18996
+ return new Promise((resolve28) => setImmediate(resolve28));
19140
18997
  }
19141
18998
  function addFileToIndex(relPath, content, size, cfg) {
19142
18999
  if (!state55.index || content.includes("\0")) return;
@@ -19190,8 +19047,8 @@ async function walkDirectory(absPath, cfg, excludes, fileBatch) {
19190
19047
  state55.truncated = true;
19191
19048
  return;
19192
19049
  }
19193
- const absChild = normalizeSlashes2(resolve23(absPath, ent.name));
19194
- const relChild = normalizeSlashes2(relative22(root, absChild));
19050
+ const absChild = normalizeSlashes2(resolve24(absPath, ent.name));
19051
+ const relChild = normalizeSlashes2(relative23(root, absChild));
19195
19052
  if (relChild === "" || relChild === ".") continue;
19196
19053
  if (excludes.some((re) => re.test(relChild))) continue;
19197
19054
  if (ent.isDirectory()) {
@@ -19233,7 +19090,7 @@ async function buildIndex(rootPath, cfg) {
19233
19090
  return;
19234
19091
  }
19235
19092
  if (rootStats.isFile()) {
19236
- const relPath = normalizeSlashes2(relative22(normalizeSlashes2(process.cwd()), rootPath));
19093
+ const relPath = normalizeSlashes2(relative23(normalizeSlashes2(process.cwd()), rootPath));
19237
19094
  await indexFileFromStats(rootPath, relPath === "" ? "." : relPath, rootStats, cfg);
19238
19095
  state55.fileCount = state55.index.files.size;
19239
19096
  } else if (rootStats.isDirectory()) {
@@ -19526,8 +19383,8 @@ var plugin58 = {
19526
19383
  var semantic_search_indexer_default = plugin58;
19527
19384
 
19528
19385
  // src/smart-rename/index.ts
19529
- import { readFileSync as readFileSync22, writeFileSync as writeFileSync7 } from "node:fs";
19530
- import { extname as extname9, isAbsolute as isAbsolute25, relative as relative23, resolve as resolve24 } from "node:path";
19386
+ import { readFileSync as readFileSync23, writeFileSync as writeFileSync7 } from "node:fs";
19387
+ import { extname as extname5, isAbsolute as isAbsolute26, relative as relative24, resolve as resolve25 } from "node:path";
19531
19388
  var API_VERSION39 = "^0.1.10";
19532
19389
  var state56 = {
19533
19390
  renameCount: 0,
@@ -19549,18 +19406,18 @@ function readConfig51(raw) {
19549
19406
  function withinProject8(p) {
19550
19407
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
19551
19408
  const root = process.cwd();
19552
- const resolved = isAbsolute25(p) ? resolve24(p) : resolve24(root, p);
19553
- const rel = relative23(root, resolved);
19409
+ const resolved = isAbsolute26(p) ? resolve25(p) : resolve25(root, p);
19410
+ const rel = relative24(root, resolved);
19554
19411
  if (rel === "" || rel === ".") return true;
19555
19412
  if (rel.startsWith("..")) return false;
19556
- if (isAbsolute25(rel)) return false;
19413
+ if (isAbsolute26(rel)) return false;
19557
19414
  return true;
19558
19415
  }
19559
19416
  function toPosix7(p) {
19560
19417
  return p.replace(/\\/g, "/");
19561
19418
  }
19562
19419
  function relativePath7(p) {
19563
- return toPosix7(relative23(process.cwd(), p));
19420
+ return toPosix7(relative24(process.cwd(), p));
19564
19421
  }
19565
19422
  function escapeRegex2(s) {
19566
19423
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -19631,14 +19488,14 @@ var plugin59 = {
19631
19488
  if (!withinProject8(rawPath)) {
19632
19489
  return { ok: false, error: "path is outside the project root" };
19633
19490
  }
19634
- const ext = extname9(rawPath).toLowerCase();
19491
+ const ext = extname5(rawPath).toLowerCase();
19635
19492
  if (!cfg.extensions.includes(ext)) {
19636
19493
  return { ok: false, error: `extension ${ext} is not allowed for rename` };
19637
19494
  }
19638
- const resolved = resolve24(process.cwd(), rawPath);
19495
+ const resolved = resolve25(process.cwd(), rawPath);
19639
19496
  let content;
19640
19497
  try {
19641
- content = readFileSync22(resolved, "utf-8");
19498
+ content = readFileSync23(resolved, "utf-8");
19642
19499
  } catch (err) {
19643
19500
  state56.errorCount += 1;
19644
19501
  return { ok: false, error: String(err) };
@@ -19695,9 +19552,9 @@ var smart_rename_default = plugin59;
19695
19552
 
19696
19553
  // src/test-flake-detector/index.ts
19697
19554
  import { execFileSync as execFileSync11 } from "node:child_process";
19698
- import { readFileSync as readFileSync23 } from "node:fs";
19699
- import { createRequire } from "node:module";
19700
- import { dirname as dirname7, isAbsolute as isAbsolute26, relative as relative24, resolve as resolve25 } from "node:path";
19555
+ import { readFileSync as readFileSync24 } from "node:fs";
19556
+ import { createRequire as createRequire2 } from "node:module";
19557
+ import { dirname as dirname8, isAbsolute as isAbsolute27, relative as relative25, resolve as resolve26 } from "node:path";
19701
19558
  var API_VERSION40 = "^0.1.10";
19702
19559
  var state57 = {
19703
19560
  invocationCount: 0,
@@ -19768,15 +19625,15 @@ var ALLOWED_RUNNER_FLAGS = /* @__PURE__ */ new Set([
19768
19625
  ]);
19769
19626
  function withinProject9(p) {
19770
19627
  if (p.length === 0 || p.length > 4096 || p.startsWith("-")) return false;
19771
- const root = resolve25(process.cwd());
19772
- const resolved = isAbsolute26(p) ? resolve25(p) : resolve25(root, p);
19773
- const rel = relative24(root, resolved);
19774
- return rel === "" || !rel.startsWith("..") && !isAbsolute26(rel);
19628
+ const root = resolve26(process.cwd());
19629
+ const resolved = isAbsolute27(p) ? resolve26(p) : resolve26(root, p);
19630
+ const rel = relative25(root, resolved);
19631
+ return rel === "" || !rel.startsWith("..") && !isAbsolute27(rel);
19775
19632
  }
19776
- function isInside(parent, child) {
19633
+ function isInside2(parent, child) {
19777
19634
  if (parent === child) return true;
19778
- const rel = relative24(parent, child);
19779
- return rel !== "" && !rel.startsWith("..") && !isAbsolute26(rel);
19635
+ const rel = relative25(parent, child);
19636
+ return rel !== "" && !rel.startsWith("..") && !isAbsolute27(rel);
19780
19637
  }
19781
19638
  function tokenizeCommand(command) {
19782
19639
  const trimmed = command.trim();
@@ -19813,14 +19670,14 @@ function resolveTestCommand(baseCommand, testPattern) {
19813
19670
  if (runnerArgs.some((arg) => !ALLOWED_RUNNER_FLAGS.has(arg))) return null;
19814
19671
  let resolvedEntry;
19815
19672
  try {
19816
- const requireFromProject = createRequire(resolve25(process.cwd(), "package.json"));
19673
+ const requireFromProject = createRequire2(resolve26(process.cwd(), "package.json"));
19817
19674
  const packagePath = requireFromProject.resolve(`${runner}/package.json`);
19818
- const packageJson = JSON.parse(readFileSync23(packagePath, "utf8"));
19675
+ const packageJson = JSON.parse(readFileSync24(packagePath, "utf8"));
19819
19676
  const relativeBin = typeof packageJson.bin === "string" ? packageJson.bin : packageJson.bin?.[runner] ?? Object.values(packageJson.bin ?? {})[0];
19820
19677
  if (!relativeBin) return null;
19821
- const packageDir = dirname7(packagePath);
19822
- const candidate = resolve25(packageDir, relativeBin);
19823
- if (isAbsolute26(relativeBin) || !isInside(packageDir, candidate)) {
19678
+ const packageDir = dirname8(packagePath);
19679
+ const candidate = resolve26(packageDir, relativeBin);
19680
+ if (isAbsolute27(relativeBin) || !isInside2(packageDir, candidate)) {
19824
19681
  return null;
19825
19682
  }
19826
19683
  resolvedEntry = candidate;
@@ -20051,8 +19908,8 @@ var plugin60 = {
20051
19908
  var test_flake_detector_default = plugin60;
20052
19909
 
20053
19910
  // src/test-generator/index.ts
20054
- import { readFileSync as readFileSync24 } from "node:fs";
20055
- import { isAbsolute as isAbsolute27, relative as relative25, resolve as resolve26 } from "node:path";
19911
+ import { readFileSync as readFileSync25 } from "node:fs";
19912
+ import { isAbsolute as isAbsolute28, relative as relative26, resolve as resolve27 } from "node:path";
20056
19913
  var API_VERSION41 = "^0.1.10";
20057
19914
  var state58 = {
20058
19915
  generateCount: 0,
@@ -20087,18 +19944,18 @@ function readConfig53(raw) {
20087
19944
  function withinProject10(p) {
20088
19945
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
20089
19946
  const root = process.cwd();
20090
- const resolved = isAbsolute27(p) ? resolve26(p) : resolve26(root, p);
20091
- const rel = relative25(root, resolved);
19947
+ const resolved = isAbsolute28(p) ? resolve27(p) : resolve27(root, p);
19948
+ const rel = relative26(root, resolved);
20092
19949
  if (rel === "" || rel === ".") return true;
20093
19950
  if (rel.startsWith("..")) return false;
20094
- if (isAbsolute27(rel)) return false;
19951
+ if (isAbsolute28(rel)) return false;
20095
19952
  return true;
20096
19953
  }
20097
19954
  function toPosix8(p) {
20098
19955
  return p.replace(/\\/g, "/");
20099
19956
  }
20100
19957
  function relativePath8(p) {
20101
- return toPosix8(relative25(process.cwd(), p));
19958
+ return toPosix8(relative26(process.cwd(), p));
20102
19959
  }
20103
19960
  function detectExports(content) {
20104
19961
  const exports = [];
@@ -20192,7 +20049,7 @@ function generateTestContent(sourcePath, sourceModule, detected, cfg) {
20192
20049
  return lines.join("\n");
20193
20050
  }
20194
20051
  function generateForFile(filePath, cfg) {
20195
- const sourceContent = readFileSync24(filePath, "utf-8");
20052
+ const sourceContent = readFileSync25(filePath, "utf-8");
20196
20053
  const detected = detectExports(sourceContent);
20197
20054
  const sourceFile = relativePath8(filePath);
20198
20055
  const sourceParts = sourceFile.split("/");
@@ -20311,7 +20168,7 @@ var plugin61 = {
20311
20168
  if (!withinProject10(rawPath)) {
20312
20169
  return { ok: false, error: "path is outside the project root" };
20313
20170
  }
20314
- const resolved = resolve26(process.cwd(), rawPath);
20171
+ const resolved = resolve27(process.cwd(), rawPath);
20315
20172
  state58.generateCount += 1;
20316
20173
  let result;
20317
20174
  try {