@wrongstack/plugins 0.287.0 → 0.291.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 +5 -5
package/dist/index.js CHANGED
@@ -483,10 +483,10 @@ async function runAutoDoc(input, api) {
483
483
  continue;
484
484
  }
485
485
  try {
486
- const { readFileSync: readFileSync25, writeFileSync: writeFileSync8 } = await import("node:fs");
486
+ const { readFileSync: readFileSync26, writeFileSync: writeFileSync8 } = await import("node:fs");
487
487
  let content;
488
488
  try {
489
- content = readFileSync25(safeFile, "utf-8");
489
+ content = readFileSync26(safeFile, "utf-8");
490
490
  } catch {
491
491
  api.log.warn(`auto-doc: could not read file ${safeFile}`);
492
492
  continue;
@@ -887,14 +887,14 @@ function hasDisabledPluginEntry(raw) {
887
887
  });
888
888
  }
889
889
  function runGit(args, cwd, signal) {
890
- return new Promise((resolve27, reject) => {
890
+ return new Promise((resolve28, reject) => {
891
891
  execFile(
892
892
  "git",
893
893
  args,
894
894
  { encoding: "utf-8", timeout: 3e3, cwd, windowsHide: true, signal },
895
895
  (error, stdout) => {
896
896
  if (error) reject(error);
897
- else resolve27(stdout);
897
+ else resolve28(stdout);
898
898
  }
899
899
  );
900
900
  });
@@ -2863,11 +2863,13 @@ var digestCounters = {
2863
2863
  mailboxDigestErrors: 0
2864
2864
  };
2865
2865
  function readCostTrackerConfig(raw) {
2866
+ const digestEveryN = raw?.["mailboxDigestEveryN"];
2867
+ const digestTo = raw?.["mailboxDigestTo"];
2866
2868
  return {
2867
2869
  budgetLimit: typeof raw?.["budgetLimit"] === "number" ? raw["budgetLimit"] : 0,
2868
2870
  warningThreshold: typeof raw?.["warningThreshold"] === "number" ? raw["warningThreshold"] : 80,
2869
- mailboxDigestEveryN: typeof raw?.["mailboxDigestEveryN"] === "number" && raw?.["mailboxDigestEveryN"] >= 0 ? Math.floor(raw?.["mailboxDigestEveryN"]) : 0,
2870
- mailboxDigestTo: typeof raw?.["mailboxDigestTo"] === "string" && (raw?.["mailboxDigestTo"]).length > 0 ? raw?.["mailboxDigestTo"] : "cost-tracker"
2871
+ mailboxDigestEveryN: typeof digestEveryN === "number" && digestEveryN >= 0 ? Math.floor(digestEveryN) : 0,
2872
+ mailboxDigestTo: typeof digestTo === "string" && digestTo.length > 0 ? digestTo : "cost-tracker"
2871
2873
  };
2872
2874
  }
2873
2875
  function estimateCost(model, promptTokens, completionTokens) {
@@ -3836,7 +3838,8 @@ import { execFileSync } from "node:child_process";
3836
3838
 
3837
3839
  // src/runtime/index.ts
3838
3840
  import { execFile as execFile2 } from "node:child_process";
3839
- import { basename, isAbsolute as isAbsolute5, relative as relative5, resolve as resolve5 } from "node:path";
3841
+ import { existsSync, readdirSync, statSync as statSync3 } from "node:fs";
3842
+ import { basename, extname, isAbsolute as isAbsolute5, relative as relative5, resolve as resolve5 } from "node:path";
3840
3843
 
3841
3844
  // src/runtime/llm.ts
3842
3845
  function stripOuterMarkdownFence(text) {
@@ -3983,12 +3986,15 @@ function runRunnerCommand(argv, options) {
3983
3986
  });
3984
3987
  return;
3985
3988
  }
3986
- const timedOut = false;
3989
+ let timedOut = false;
3987
3990
  let spawnErrored = false;
3988
3991
  const stdoutChunks = [];
3989
3992
  const stderrChunks = [];
3990
3993
  let stdoutBytes = 0;
3991
3994
  let stderrBytes = 0;
3995
+ options.signal?.addEventListener("abort", () => {
3996
+ timedOut = true;
3997
+ }, { once: true });
3992
3998
  const child = execFile2(
3993
3999
  argv[0],
3994
4000
  argv.slice(1),
@@ -4000,12 +4006,12 @@ function runRunnerCommand(argv, options) {
4000
4006
  windowsHide: true,
4001
4007
  shell: false
4002
4008
  },
4003
- (err, stdout, stderr) => {
4009
+ (err) => {
4004
4010
  if (timedOut) {
4005
4011
  resolvePromise({
4006
4012
  code: null,
4007
- stdout: Buffer.concat([...stdoutChunks, ...Buffer.isBuffer(stdout) ? [stdout] : [Buffer.from(stdout)]]).toString("utf8"),
4008
- stderr: Buffer.concat([...stderrChunks, ...Buffer.isBuffer(stderr) ? [stderr] : [Buffer.from(stderr)]]).toString("utf8"),
4013
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
4014
+ stderr: Buffer.concat(stderrChunks).toString("utf8"),
4009
4015
  timedOut: true,
4010
4016
  spawnError: false
4011
4017
  });
@@ -4014,8 +4020,8 @@ function runRunnerCommand(argv, options) {
4014
4020
  if (spawnErrored) {
4015
4021
  resolvePromise({
4016
4022
  code: 127,
4017
- stdout: Buffer.concat([...stdoutChunks, ...Buffer.isBuffer(stdout) ? [stdout] : [Buffer.from(stdout)]]).toString("utf8"),
4018
- stderr: Buffer.concat([...stderrChunks, ...Buffer.isBuffer(stderr) ? [stderr] : [Buffer.from(stderr)]]).toString("utf8"),
4023
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
4024
+ stderr: Buffer.concat(stderrChunks).toString("utf8"),
4019
4025
  timedOut: false,
4020
4026
  spawnError: true
4021
4027
  });
@@ -4026,14 +4032,8 @@ function runRunnerCommand(argv, options) {
4026
4032
  const code = typeof anyErr.code === "number" ? anyErr.code : 1;
4027
4033
  resolvePromise({
4028
4034
  code,
4029
- stdout: Buffer.concat([
4030
- ...stdoutChunks,
4031
- ...anyErr.stdout ? [Buffer.isBuffer(anyErr.stdout) ? anyErr.stdout : Buffer.from(anyErr.stdout)] : []
4032
- ]).toString("utf8"),
4033
- stderr: Buffer.concat([
4034
- ...stderrChunks,
4035
- ...anyErr.stderr ? [Buffer.isBuffer(anyErr.stderr) ? anyErr.stderr : Buffer.from(anyErr.stderr)] : []
4036
- ]).toString("utf8"),
4035
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
4036
+ stderr: Buffer.concat(stderrChunks).toString("utf8"),
4037
4037
  timedOut: false,
4038
4038
  spawnError: false
4039
4039
  });
@@ -4041,19 +4041,18 @@ function runRunnerCommand(argv, options) {
4041
4041
  }
4042
4042
  resolvePromise({
4043
4043
  code: 0,
4044
- stdout: Buffer.concat([
4045
- ...stdoutChunks,
4046
- ...Buffer.isBuffer(stdout) ? [stdout] : [Buffer.from(stdout)]
4047
- ]).toString("utf8"),
4048
- stderr: Buffer.concat([
4049
- ...stderrChunks,
4050
- ...Buffer.isBuffer(stderr) ? [stderr] : [Buffer.from(stderr)]
4051
- ]).toString("utf8"),
4044
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
4045
+ stderr: Buffer.concat(stderrChunks).toString("utf8"),
4052
4046
  timedOut: false,
4053
4047
  spawnError: false
4054
4048
  });
4055
4049
  }
4056
4050
  );
4051
+ child.on("exit", (_code, signal) => {
4052
+ if (signal !== null) {
4053
+ timedOut = true;
4054
+ }
4055
+ });
4057
4056
  child.stdout?.on("data", (chunk) => {
4058
4057
  stdoutBytes += chunk.length;
4059
4058
  if (stdoutBytes <= MAX_BUFFER_BYTES) stdoutChunks.push(chunk);
@@ -4072,6 +4071,47 @@ function runRunnerCommand(argv, options) {
4072
4071
  function withinProject(p) {
4073
4072
  return withinProjectPath(process.cwd(), p) || relative5(process.cwd(), p) === ".";
4074
4073
  }
4074
+ var DEFAULT_EXCLUDE_DIRS = ["node_modules", "dist", ".git", "coverage"];
4075
+ function collectSourceFiles(root, opts) {
4076
+ const files = [];
4077
+ if (!existsSync(root)) return files;
4078
+ const s = statSync3(root);
4079
+ if (s.isFile()) {
4080
+ if (matchesExtension(root, opts.extensions)) files.push(root);
4081
+ return files;
4082
+ }
4083
+ if (!s.isDirectory()) return files;
4084
+ const exclude = opts.excludeDirs ?? DEFAULT_EXCLUDE_DIRS;
4085
+ function walk(dir, depth) {
4086
+ if (opts.maxDepth !== void 0 && depth > opts.maxDepth) return;
4087
+ let entries;
4088
+ try {
4089
+ entries = readdirSync(dir);
4090
+ } catch {
4091
+ return;
4092
+ }
4093
+ for (const entry of entries) {
4094
+ if (exclude.includes(entry)) continue;
4095
+ const full = resolve5(dir, entry);
4096
+ let st;
4097
+ try {
4098
+ st = statSync3(full);
4099
+ } catch {
4100
+ continue;
4101
+ }
4102
+ if (st.isDirectory()) {
4103
+ walk(full, depth + 1);
4104
+ } else if (st.isFile() && matchesExtension(full, opts.extensions)) {
4105
+ files.push(full);
4106
+ }
4107
+ }
4108
+ }
4109
+ walk(root, 0);
4110
+ return files;
4111
+ }
4112
+ function matchesExtension(p, exts) {
4113
+ return exts.includes(extname(p).toLowerCase());
4114
+ }
4075
4115
 
4076
4116
  // src/diff-summary/index.ts
4077
4117
  var API_VERSION6 = "^0.1.10";
@@ -4662,7 +4702,7 @@ var error_lens_default = plugin14;
4662
4702
 
4663
4703
  // src/file-watcher/index.ts
4664
4704
  import { watch as fsWatch } from "node:fs";
4665
- import { isAbsolute as isAbsolute6, relative as relative6, resolve as resolve6 } from "node:path";
4705
+ import { isAbsolute as isAbsolute6, join, relative as relative6, resolve as resolve6 } from "node:path";
4666
4706
  var API_VERSION7 = "^0.1.10";
4667
4707
  function withinProject2(p) {
4668
4708
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
@@ -4771,7 +4811,11 @@ var plugin15 = {
4771
4811
  try {
4772
4812
  const watcher = fsWatch(dirPath, { recursive }, (eventType, filename) => {
4773
4813
  if (!filename) return;
4774
- const fullPath = `${dirPath}/${filename}`;
4814
+ if (handle.events.length > 0 && !(eventType === "change" ? handle.events.includes("change") : handle.events.includes("add") || handle.events.includes("delete"))) {
4815
+ return;
4816
+ }
4817
+ const rawPath = filename.startsWith(dirPath) ? filename : join(dirPath, filename);
4818
+ const fullPath = rawPath.replace(/\\/g, "/");
4775
4819
  const key = `${handle.id}:${fullPath}:${eventType}`;
4776
4820
  debounceEvent(
4777
4821
  key,
@@ -4990,7 +5034,7 @@ var file_watcher_default = plugin15;
4990
5034
 
4991
5035
  // src/format-on-save/index.ts
4992
5036
  import { execFileSync as execFileSync2, execSync } from "node:child_process";
4993
- import { existsSync, statSync as statSync3 } from "node:fs";
5037
+ import { existsSync as existsSync2, statSync as statSync4 } from "node:fs";
4994
5038
  var API_VERSION8 = "^0.1.10";
4995
5039
  var state14 = {
4996
5040
  invocationCount: 0,
@@ -5051,10 +5095,10 @@ function evictExpired(ttlMs) {
5051
5095
  }
5052
5096
  function formatFile(filePath, timeoutMs) {
5053
5097
  if (!withinProject(filePath)) return null;
5054
- if (!existsSync(filePath)) return null;
5098
+ if (!existsSync2(filePath)) return null;
5055
5099
  let bytesBefore;
5056
5100
  try {
5057
- bytesBefore = statSync3(filePath).size;
5101
+ bytesBefore = statSync4(filePath).size;
5058
5102
  } catch {
5059
5103
  return null;
5060
5104
  }
@@ -5071,7 +5115,7 @@ function formatFile(filePath, timeoutMs) {
5071
5115
  }
5072
5116
  let bytesAfter;
5073
5117
  try {
5074
- bytesAfter = statSync3(filePath).size;
5118
+ bytesAfter = statSync4(filePath).size;
5075
5119
  } catch {
5076
5120
  return null;
5077
5121
  }
@@ -5277,7 +5321,7 @@ var format_on_save_default = plugin16;
5277
5321
 
5278
5322
  // src/git-autocommit/index.ts
5279
5323
  import { execFileSync as execFileSync3 } from "node:child_process";
5280
- import { existsSync as existsSync2 } from "node:fs";
5324
+ import { existsSync as existsSync3 } from "node:fs";
5281
5325
  var API_VERSION9 = "^0.1.10";
5282
5326
  var commitCount = { value: 0 };
5283
5327
  var lastCommit = { hash: null, at: null };
@@ -5312,7 +5356,7 @@ function stageFiles(files, cwd) {
5312
5356
  if (!files || !Array.isArray(files)) return;
5313
5357
  const existing = files.filter((f) => {
5314
5358
  try {
5315
- return existsSync2(f);
5359
+ return existsSync3(f);
5316
5360
  } catch {
5317
5361
  return false;
5318
5362
  }
@@ -5737,7 +5781,7 @@ var git_autocommit_default = plugin17;
5737
5781
 
5738
5782
  // src/import-organizer/index.ts
5739
5783
  import { spawn } from "node:child_process";
5740
- import { existsSync as existsSync3, statSync as statSync4 } from "node:fs";
5784
+ import { existsSync as existsSync4, statSync as statSync5 } from "node:fs";
5741
5785
  import { basename as basename2, isAbsolute as isAbsolute7 } from "node:path";
5742
5786
  var ALLOWED_FIRST_TOKENS = /* @__PURE__ */ new Set([
5743
5787
  "npx",
@@ -5799,7 +5843,7 @@ function readConfig13(raw) {
5799
5843
  };
5800
5844
  }
5801
5845
  function runCommand(command, args, timeoutMs, cwd) {
5802
- return new Promise((resolve27) => {
5846
+ return new Promise((resolve28) => {
5803
5847
  let timedOut = false;
5804
5848
  const stdoutChunks = [];
5805
5849
  const stderrChunks = [];
@@ -5811,17 +5855,17 @@ function runCommand(command, args, timeoutMs, cwd) {
5811
5855
  signal: AbortSignal.timeout(timeoutMs)
5812
5856
  });
5813
5857
  } catch {
5814
- resolve27({ code: 127, stdout: "", stderr: "", timedOut: false });
5858
+ resolve28({ code: 127, stdout: "", stderr: "", timedOut: false });
5815
5859
  return;
5816
5860
  }
5817
5861
  child.stdout?.on("data", (c) => stdoutChunks.push(c));
5818
5862
  child.stderr?.on("data", (c) => stderrChunks.push(c));
5819
5863
  child.on("error", () => {
5820
- resolve27({ code: 127, stdout: "", stderr: "", timedOut: false });
5864
+ resolve28({ code: 127, stdout: "", stderr: "", timedOut: false });
5821
5865
  });
5822
5866
  child.on("close", (code) => {
5823
5867
  if (timedOut) return;
5824
- resolve27({
5868
+ resolve28({
5825
5869
  code,
5826
5870
  stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
5827
5871
  stderr: Buffer.concat(stderrChunks).toString("utf-8"),
@@ -5830,16 +5874,16 @@ function runCommand(command, args, timeoutMs, cwd) {
5830
5874
  });
5831
5875
  child.on("abort", () => {
5832
5876
  timedOut = true;
5833
- resolve27({ code: null, stdout: "", stderr: "", timedOut: true });
5877
+ resolve28({ code: null, stdout: "", stderr: "", timedOut: true });
5834
5878
  });
5835
5879
  });
5836
5880
  }
5837
5881
  async function organizeImports(filePath, cfg, cwd) {
5838
5882
  if (!withinProject(filePath)) return null;
5839
- if (!existsSync3(filePath)) return null;
5883
+ if (!existsSync4(filePath)) return null;
5840
5884
  let bytesBefore;
5841
5885
  try {
5842
- bytesBefore = statSync4(filePath).size;
5886
+ bytesBefore = statSync5(filePath).size;
5843
5887
  } catch {
5844
5888
  return null;
5845
5889
  }
@@ -5860,7 +5904,7 @@ async function organizeImports(filePath, cfg, cwd) {
5860
5904
  if (result.code === 127) return null;
5861
5905
  let bytesAfter;
5862
5906
  try {
5863
- bytesAfter = statSync4(filePath).size;
5907
+ bytesAfter = statSync5(filePath).size;
5864
5908
  } catch {
5865
5909
  return null;
5866
5910
  }
@@ -6586,9 +6630,11 @@ var knowledge_graph_default = plugin20;
6586
6630
 
6587
6631
  // src/lint-gate/index.ts
6588
6632
  import { execFile as execFile3 } from "node:child_process";
6633
+ import { readFileSync as readFileSync6 } from "node:fs";
6589
6634
  import { mkdtemp, readFile as readFile2, rm, writeFile } from "node:fs/promises";
6635
+ import { createRequire } from "node:module";
6590
6636
  import { tmpdir } from "node:os";
6591
- import { join } from "node:path";
6637
+ import { dirname as dirname4, isAbsolute as isAbsolute9, join as join2, relative as relative8, resolve as resolve8, sep } from "node:path";
6592
6638
  var API_VERSION12 = "^0.1.10";
6593
6639
  var state18 = {
6594
6640
  /** Total PreToolUse invocations. */
@@ -6622,55 +6668,74 @@ function readConfig16(raw) {
6622
6668
  fixRules: Array.isArray(r["fixRules"]) ? r["fixRules"].filter((x) => typeof x === "string") : []
6623
6669
  };
6624
6670
  }
6625
- function executable(command) {
6626
- return process.platform === "win32" && command === "npx" ? "npx.cmd" : command;
6671
+ var LINTER_PACKAGES = {
6672
+ biome: "@biomejs/biome",
6673
+ eslint: "eslint"
6674
+ };
6675
+ function isInside(parent, candidate) {
6676
+ const rel = relative8(parent, candidate);
6677
+ return rel === "" || !rel.startsWith(`..${sep}`) && rel !== ".." && !isAbsolute9(rel);
6678
+ }
6679
+ function resolveLocalLinter(name, cwd) {
6680
+ try {
6681
+ const packageName = LINTER_PACKAGES[name];
6682
+ const requireFromProject = createRequire(resolve8(cwd, "package.json"));
6683
+ const packagePath = requireFromProject.resolve(`${packageName}/package.json`);
6684
+ const packageJson = JSON.parse(readFileSync6(packagePath, "utf-8"));
6685
+ const relativeBin = typeof packageJson.bin === "string" ? packageJson.bin : packageJson.bin?.[name] ?? Object.values(packageJson.bin ?? {})[0];
6686
+ if (!relativeBin || isAbsolute9(relativeBin)) return null;
6687
+ const packageDir = dirname4(packagePath);
6688
+ const entry = resolve8(packageDir, relativeBin);
6689
+ if (!isInside(packageDir, entry)) return null;
6690
+ return {
6691
+ cmd: process.execPath,
6692
+ args: name === "biome" ? [entry, "check", "--reporter=json"] : [entry, "--format=json"],
6693
+ name
6694
+ };
6695
+ } catch {
6696
+ return null;
6697
+ }
6627
6698
  }
6628
- function runCommand2(command, args, timeoutMs, signal) {
6629
- return new Promise((resolve27) => {
6699
+ function runCommand2(command, args, timeoutMs, cwd, signal) {
6700
+ return new Promise((resolveResult) => {
6630
6701
  try {
6631
6702
  execFile3(
6632
- executable(command),
6703
+ command,
6633
6704
  args,
6634
6705
  {
6635
6706
  encoding: "utf-8",
6636
6707
  timeout: timeoutMs,
6637
- cwd: process.cwd(),
6708
+ cwd,
6638
6709
  windowsHide: true,
6710
+ shell: false,
6639
6711
  maxBuffer: 2 * 1024 * 1024,
6640
6712
  ...signal ? { signal } : {}
6641
6713
  },
6642
- (error, stdout) => resolve27({ stdout, error })
6714
+ (error, stdout) => resolveResult({ stdout, error })
6643
6715
  );
6644
6716
  } catch (err) {
6645
- resolve27({ stdout: "", error: err instanceof Error ? err : new Error(String(err)) });
6717
+ resolveResult({ stdout: "", error: err instanceof Error ? err : new Error(String(err)) });
6646
6718
  }
6647
6719
  });
6648
6720
  }
6649
- async function detectLinter(requested) {
6650
- const tryBiome = requested === "biome" || requested === "auto";
6651
- const tryEslint = requested === "eslint" || requested === "auto";
6652
- if (tryBiome) {
6653
- const probe = await runCommand2("npx", ["biome", "--version"], 5e3);
6654
- if (!probe.error) {
6655
- return { cmd: "npx", args: ["biome", "check", "--reporter=json"], name: "biome" };
6656
- }
6657
- }
6658
- if (tryEslint) {
6659
- const probe = await runCommand2("npx", ["eslint", "--version"], 5e3);
6660
- if (!probe.error) {
6661
- return { cmd: "npx", args: ["eslint", "--format=json"], name: "eslint" };
6662
- }
6721
+ async function detectLinter(requested, cwd) {
6722
+ const candidates = requested === "auto" ? ["biome", "eslint"] : [requested];
6723
+ for (const name of candidates) {
6724
+ const linter = resolveLocalLinter(name, cwd);
6725
+ if (!linter) continue;
6726
+ const probe = await runCommand2(linter.cmd, [linter.args[0], "--version"], 5e3, cwd);
6727
+ if (!probe.error) return linter;
6663
6728
  }
6664
6729
  return null;
6665
6730
  }
6666
- async function lintContent(content, filePath, linter, timeoutMs, signal) {
6731
+ async function lintContent(content, filePath, linter, timeoutMs, cwd, signal) {
6667
6732
  const ext = filePath.includes(".") ? filePath.slice(filePath.lastIndexOf(".")) : ".ts";
6668
- const tmpDir = await mkdtemp(join(tmpdir(), "lint-gate-"));
6669
- const tmpFile = join(tmpDir, `input${ext}`);
6733
+ const tmpDir = await mkdtemp(join2(tmpdir(), "lint-gate-"));
6734
+ const tmpFile = join2(tmpDir, `input${ext}`);
6670
6735
  try {
6671
6736
  await writeFile(tmpFile, content, "utf-8");
6672
6737
  const fullArgs = [...linter.args, tmpFile];
6673
- const result = await runCommand2(linter.cmd, fullArgs, timeoutMs, signal);
6738
+ const result = await runCommand2(linter.cmd, fullArgs, timeoutMs, cwd, signal);
6674
6739
  if (signal.aborted) throw signal.reason;
6675
6740
  if (result.error && !result.stdout) return null;
6676
6741
  return parseLinterOutput(result.stdout, linter.name);
@@ -6681,14 +6746,14 @@ async function lintContent(content, filePath, linter, timeoutMs, signal) {
6681
6746
  await rm(tmpDir, { recursive: true, force: true }).catch(() => void 0);
6682
6747
  }
6683
6748
  }
6684
- async function lintAndFix(content, filePath, linter, timeoutMs, signal) {
6749
+ async function lintAndFix(content, filePath, linter, timeoutMs, cwd, signal) {
6685
6750
  const ext = filePath.includes(".") ? filePath.slice(filePath.lastIndexOf(".")) : ".ts";
6686
- const tmpDir = await mkdtemp(join(tmpdir(), "lint-gate-fix-"));
6687
- const tmpFile = join(tmpDir, `input${ext}`);
6751
+ const tmpDir = await mkdtemp(join2(tmpdir(), "lint-gate-fix-"));
6752
+ const tmpFile = join2(tmpDir, `input${ext}`);
6688
6753
  try {
6689
6754
  await writeFile(tmpFile, content, "utf-8");
6690
- const fixArgs = linter.name === "biome" ? ["biome", "check", "--write", tmpFile] : ["eslint", "--fix", tmpFile];
6691
- await runCommand2(linter.cmd, fixArgs, timeoutMs, signal);
6755
+ const fixArgs = linter.name === "biome" ? [linter.args[0], "check", "--write", tmpFile] : [linter.args[0], "--fix", tmpFile];
6756
+ await runCommand2(linter.cmd, fixArgs, timeoutMs, cwd, signal);
6692
6757
  if (signal.aborted) throw signal.reason;
6693
6758
  return await readFile2(tmpFile, "utf-8");
6694
6759
  } catch {
@@ -6789,7 +6854,8 @@ var plugin21 = {
6789
6854
  state18.hookUnregister = null;
6790
6855
  state18.lastResult = null;
6791
6856
  const cfg = readConfig16(api.config.extensions?.["lint-gate"]);
6792
- const linterReady = detectLinter(cfg.linter).then((linter) => {
6857
+ const cwd = resolve8(api.config.cwd ?? process.cwd());
6858
+ const linterReady = detectLinter(cfg.linter, cwd).then((linter) => {
6793
6859
  if (!linter) {
6794
6860
  api.log.warn("lint-gate: no linter found (biome or eslint) \u2014 hook will be a no-op", {
6795
6861
  requested: cfg.linter
@@ -6826,7 +6892,14 @@ var plugin21 = {
6826
6892
  } else {
6827
6893
  return;
6828
6894
  }
6829
- const issues = await lintContent(content, filePath, linter, cfg.timeoutMs, runtime.signal);
6895
+ const issues = await lintContent(
6896
+ content,
6897
+ filePath,
6898
+ linter,
6899
+ cfg.timeoutMs,
6900
+ cwd,
6901
+ runtime.signal
6902
+ );
6830
6903
  if (issues === null) {
6831
6904
  state18.linterErrorCount += 1;
6832
6905
  return;
@@ -6866,6 +6939,7 @@ ${summary}${truncated}`
6866
6939
  filePath,
6867
6940
  linter,
6868
6941
  cfg.timeoutMs,
6942
+ cwd,
6869
6943
  runtime.signal
6870
6944
  );
6871
6945
  if (fixedContent !== content) {
@@ -6904,6 +6978,7 @@ ${remainingSummary}` : "")
6904
6978
  filePath,
6905
6979
  linter,
6906
6980
  cfg.timeoutMs,
6981
+ cwd,
6907
6982
  runtime.signal
6908
6983
  );
6909
6984
  if (fixedNewStr !== newStr) {
@@ -7363,7 +7438,7 @@ function hashString2(value) {
7363
7438
  }
7364
7439
  async function gitDiffFingerprint(cwd, signal) {
7365
7440
  try {
7366
- const diff = await new Promise((resolve27, reject) => {
7441
+ const diff = await new Promise((resolve28, reject) => {
7367
7442
  execFile4(
7368
7443
  "git",
7369
7444
  ["diff", "--no-ext-diff", "--"],
@@ -7380,7 +7455,7 @@ async function gitDiffFingerprint(cwd, signal) {
7380
7455
  },
7381
7456
  (error, stdout) => {
7382
7457
  if (error) reject(error);
7383
- else resolve27(stdout);
7458
+ else resolve28(stdout);
7384
7459
  }
7385
7460
  );
7386
7461
  });
@@ -8638,7 +8713,7 @@ var plugin_stack_observer_default = PLUGIN;
8638
8713
  // src/pr-drafter/index.ts
8639
8714
  import { execFileSync as execFileSync4 } from "node:child_process";
8640
8715
  import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "node:fs";
8641
- import { dirname as dirname4, isAbsolute as isAbsolute9, relative as relative8, resolve as resolve8 } from "node:path";
8716
+ import { dirname as dirname5, isAbsolute as isAbsolute10, relative as relative9, resolve as resolve9 } from "node:path";
8642
8717
  var API_VERSION13 = "^0.1.10";
8643
8718
  var state25 = {
8644
8719
  commits: [],
@@ -8677,10 +8752,10 @@ function readConfig23(raw) {
8677
8752
  }
8678
8753
  function resolveProjectPath6(rawPath, cwd = process.cwd()) {
8679
8754
  if (typeof rawPath !== "string" || rawPath.length === 0) return null;
8680
- const root = resolve8(cwd);
8681
- const resolved = isAbsolute9(rawPath) ? resolve8(rawPath) : resolve8(root, rawPath);
8682
- const rel = relative8(root, resolved);
8683
- if (rel === "" || !rel.startsWith("..") && !isAbsolute9(rel)) return resolved;
8755
+ const root = resolve9(cwd);
8756
+ const resolved = isAbsolute10(rawPath) ? resolve9(rawPath) : resolve9(root, rawPath);
8757
+ const rel = relative9(root, resolved);
8758
+ if (rel === "" || !rel.startsWith("..") && !isAbsolute10(rel)) return resolved;
8684
8759
  return null;
8685
8760
  }
8686
8761
  function gitBranch() {
@@ -8767,7 +8842,7 @@ async function writeDraft(cfg, llm) {
8767
8842
  }
8768
8843
  const draft = await buildDraft(cfg, llm);
8769
8844
  try {
8770
- mkdirSync4(dirname4(resolved), { recursive: true });
8845
+ mkdirSync4(dirname5(resolved), { recursive: true });
8771
8846
  writeFileSync5(resolved, draft.body);
8772
8847
  state25.draftsWritten += 1;
8773
8848
  } catch {
@@ -8894,7 +8969,7 @@ var plugin27 = {
8894
8969
  const resolved = resolveProjectPath6(cfg.outputPath);
8895
8970
  if (!resolved) return { ok: false, error: "outputPath resolves outside project" };
8896
8971
  try {
8897
- mkdirSync4(dirname4(resolved), { recursive: true });
8972
+ mkdirSync4(dirname5(resolved), { recursive: true });
8898
8973
  writeFileSync5(resolved, draft.body);
8899
8974
  state25.draftsWritten += 1;
8900
8975
  return {
@@ -9045,7 +9120,7 @@ function redactDeep(value, allow, counter) {
9045
9120
  function readConfig24(raw) {
9046
9121
  const base = {
9047
9122
  enabled: false,
9048
- mode: "warn",
9123
+ mode: "redact",
9049
9124
  scanResponse: true,
9050
9125
  allow: []
9051
9126
  };
@@ -9060,7 +9135,7 @@ function readConfig24(raw) {
9060
9135
  }) : [];
9061
9136
  return {
9062
9137
  enabled: r["enabled"] === true,
9063
- mode: r["mode"] === "redact" ? "redact" : r["mode"] === "block" ? "block" : "warn",
9138
+ mode: r["mode"] === "warn" ? "warn" : r["mode"] === "block" ? "block" : "redact",
9064
9139
  scanResponse: r["scanResponse"] !== false,
9065
9140
  allow
9066
9141
  };
@@ -9078,10 +9153,10 @@ var state26 = {
9078
9153
  var plugin28 = {
9079
9154
  name: "prompt-firewall",
9080
9155
  version: "0.1.0",
9081
- description: "Scans the provider wire for credential leaks before context reaches the LLM API (wrapProviderRunner); warn/redact/block. Opt-in; warn by default.",
9156
+ description: "Scans the provider wire for credential leaks before context reaches the LLM API (wrapProviderRunner); redact/warn/block. Opt-in; redact by default.",
9082
9157
  apiVersion: "^0.1.10",
9083
9158
  capabilities: { tools: true },
9084
- defaultConfig: { enabled: false, mode: "warn", scanResponse: true, allow: [] },
9159
+ defaultConfig: { enabled: false, mode: "redact", scanResponse: true, allow: [] },
9085
9160
  configSchema: {
9086
9161
  type: "object",
9087
9162
  properties: {
@@ -9093,8 +9168,8 @@ var plugin28 = {
9093
9168
  mode: {
9094
9169
  type: "string",
9095
9170
  enum: ["warn", "redact", "block"],
9096
- default: "warn",
9097
- description: "warn = detect only; redact = strip secrets from the request/response; block = refuse the request."
9171
+ default: "redact",
9172
+ description: "redact (default) = strip secrets from the request/response; warn = detect only; block = refuse the request."
9098
9173
  },
9099
9174
  scanResponse: {
9100
9175
  type: "boolean",
@@ -9318,6 +9393,8 @@ var BASE_PATTERNS = [
9318
9393
  ];
9319
9394
  var PATTERNS3 = [...BASE_PATTERNS];
9320
9395
  var COMBINED_REGEX = buildCombinedRegex(PATTERNS3);
9396
+ var RE_DOS_MAX_SCAN_LENGTH = 1e5;
9397
+ var RE_DOS_TIMEOUT_MS = 100;
9321
9398
  function buildCombinedRegex(patterns) {
9322
9399
  return new RegExp(patterns.map((p) => `(${p.regex.source})`).join("|"), "g");
9323
9400
  }
@@ -9338,10 +9415,17 @@ var state27 = {
9338
9415
  };
9339
9416
  function findMatches(text) {
9340
9417
  if (!text) return [];
9418
+ if (text.length > RE_DOS_MAX_SCAN_LENGTH) return [];
9341
9419
  const found = /* @__PURE__ */ new Set();
9342
9420
  COMBINED_REGEX.lastIndex = 0;
9343
9421
  let m;
9422
+ const startTime = performance.now();
9344
9423
  while ((m = COMBINED_REGEX.exec(text)) !== null) {
9424
+ if (performance.now() - startTime > RE_DOS_TIMEOUT_MS) {
9425
+ throw new Error(
9426
+ `secret-scanner: ReDoS timeout \u2014 regex scan exceeded ${RE_DOS_TIMEOUT_MS}ms on ${text.length}-char input`
9427
+ );
9428
+ }
9345
9429
  for (let i = 0; i < PATTERNS3.length; i++) {
9346
9430
  if (m[i + 1] !== void 0) {
9347
9431
  found.add(PATTERNS3[i].type);
@@ -9354,30 +9438,32 @@ function findMatches(text) {
9354
9438
  }
9355
9439
  return Array.from(found);
9356
9440
  }
9357
- function scanInput(input) {
9441
+ function scanInput(input, depth = 0) {
9358
9442
  if (input === null || input === void 0) return null;
9443
+ if (depth > 50) return null;
9359
9444
  if (typeof input === "string") {
9360
9445
  const found = findMatches(input);
9361
9446
  return found.length > 0 ? found : null;
9362
9447
  }
9363
9448
  if (Array.isArray(input)) {
9364
9449
  for (const item of input) {
9365
- const found = scanInput(item);
9450
+ const found = scanInput(item, depth + 1);
9366
9451
  if (found) return found;
9367
9452
  }
9368
9453
  return null;
9369
9454
  }
9370
9455
  if (typeof input === "object") {
9371
9456
  for (const value of Object.values(input)) {
9372
- const found = scanInput(value);
9457
+ const found = scanInput(value, depth + 1);
9373
9458
  if (found) return found;
9374
9459
  }
9375
9460
  return null;
9376
9461
  }
9377
9462
  return null;
9378
9463
  }
9379
- function redactInput(input) {
9464
+ function redactInput(input, depth = 0) {
9380
9465
  if (input === null || input === void 0) return input;
9466
+ if (depth > 50) return input;
9381
9467
  if (typeof input === "string") {
9382
9468
  return input.replace(COMBINED_REGEX, (_match, ...groups) => {
9383
9469
  for (let i = 0; i < PATTERNS3.length; i++) {
@@ -9389,12 +9475,12 @@ function redactInput(input) {
9389
9475
  });
9390
9476
  }
9391
9477
  if (Array.isArray(input)) {
9392
- return input.map((item) => redactInput(item));
9478
+ return input.map((item) => redactInput(item, depth + 1));
9393
9479
  }
9394
9480
  if (typeof input === "object") {
9395
9481
  const out = {};
9396
9482
  for (const [k, v] of Object.entries(input)) {
9397
- out[k] = redactInput(v);
9483
+ out[k] = redactInput(v, depth + 1);
9398
9484
  }
9399
9485
  return out;
9400
9486
  }
@@ -9688,15 +9774,15 @@ var secret_scanner_default = plugin29;
9688
9774
  import { expectDefined as expectDefined2 } from "@wrongstack/core";
9689
9775
  import { toErrorMessage } from "@wrongstack/core/utils";
9690
9776
  import { execFileSync as execFileSync5 } from "node:child_process";
9691
- import { existsSync as existsSync4, readFileSync as readFileSync6, readdirSync, writeFileSync as writeFileSync6 } from "node:fs";
9692
- import { isAbsolute as isAbsolute10, join as join2, relative as relative9, resolve as resolve9 } from "node:path";
9777
+ import { existsSync as existsSync5, readFileSync as readFileSync7, readdirSync as readdirSync2, writeFileSync as writeFileSync6 } from "node:fs";
9778
+ import { isAbsolute as isAbsolute11, join as join3, relative as relative10, resolve as resolve10 } from "node:path";
9693
9779
  var API_VERSION14 = "^0.1.10";
9694
9780
  function resolveProjectRoot(rawCwd, root = process.cwd()) {
9695
9781
  if (typeof rawCwd !== "string" || rawCwd.length === 0) return root;
9696
- const base = resolve9(root);
9697
- const resolved = isAbsolute10(rawCwd) ? resolve9(rawCwd) : resolve9(base, rawCwd);
9698
- const rel = relative9(base, resolved);
9699
- if (rel === "" || !rel.startsWith("..") && !isAbsolute10(rel)) return resolved;
9782
+ const base = resolve10(root);
9783
+ const resolved = isAbsolute11(rawCwd) ? resolve10(rawCwd) : resolve10(base, rawCwd);
9784
+ const rel = relative10(base, resolved);
9785
+ if (rel === "" || !rel.startsWith("..") && !isAbsolute11(rel)) return resolved;
9700
9786
  return null;
9701
9787
  }
9702
9788
  var state28 = {
@@ -9724,24 +9810,24 @@ function runGit3(args, cwd) {
9724
9810
  }
9725
9811
  function getPackageJson(cwd) {
9726
9812
  const path = cwd ? `${cwd}/package.json` : "package.json";
9727
- if (!existsSync4(path)) return null;
9813
+ if (!existsSync5(path)) return null;
9728
9814
  try {
9729
- return JSON.parse(readFileSync6(path, "utf-8"));
9815
+ return JSON.parse(readFileSync7(path, "utf-8"));
9730
9816
  } catch {
9731
9817
  return null;
9732
9818
  }
9733
9819
  }
9734
9820
  function collectManifests(root) {
9735
9821
  const paths = [];
9736
- const rootPkg = join2(root, "package.json");
9737
- if (existsSync4(rootPkg)) paths.push(rootPkg);
9822
+ const rootPkg = join3(root, "package.json");
9823
+ if (existsSync5(rootPkg)) paths.push(rootPkg);
9738
9824
  for (const group of ["packages", "apps"]) {
9739
- const groupDir = join2(root, group);
9740
- if (!existsSync4(groupDir)) continue;
9741
- for (const entry of readdirSync(groupDir, { withFileTypes: true })) {
9825
+ const groupDir = join3(root, group);
9826
+ if (!existsSync5(groupDir)) continue;
9827
+ for (const entry of readdirSync2(groupDir, { withFileTypes: true })) {
9742
9828
  if (!entry.isDirectory()) continue;
9743
- const candidate = join2(groupDir, entry.name, "package.json");
9744
- if (existsSync4(candidate)) paths.push(candidate);
9829
+ const candidate = join3(groupDir, entry.name, "package.json");
9830
+ if (existsSync5(candidate)) paths.push(candidate);
9745
9831
  }
9746
9832
  }
9747
9833
  return paths;
@@ -9931,9 +10017,9 @@ var plugin30 = {
9931
10017
  };
9932
10018
  }
9933
10019
  const root = cwd ?? process.cwd();
9934
- const bumpScript = join2(root, "scripts", "bump-version.mjs");
10020
+ const bumpScript = join3(root, "scripts", "bump-version.mjs");
9935
10021
  const changed = collectManifests(root);
9936
- if (existsSync4(bumpScript)) {
10022
+ if (existsSync5(bumpScript)) {
9937
10023
  try {
9938
10024
  execFileSync5(process.execPath, [bumpScript, "set", newVersion], {
9939
10025
  cwd: root,
@@ -9946,12 +10032,12 @@ var plugin30 = {
9946
10032
  return { ok: false, error: `bump script failed: ${msg}` };
9947
10033
  }
9948
10034
  for (const rel of ["package.json", "package-lock.json", "src/lib/utils.ts", "index.html"]) {
9949
- const p = join2(root, "website", rel);
9950
- if (existsSync4(p)) changed.push(p);
10035
+ const p = join3(root, "website", rel);
10036
+ if (existsSync5(p)) changed.push(p);
9951
10037
  }
9952
10038
  } else {
9953
10039
  for (const manifest of changed) {
9954
- const pkgData = JSON.parse(readFileSync6(manifest, "utf-8"));
10040
+ const pkgData = JSON.parse(readFileSync7(manifest, "utf-8"));
9955
10041
  pkgData.version = newVersion;
9956
10042
  writeFileSync6(manifest, JSON.stringify(pkgData, null, 2) + "\n", "utf-8");
9957
10043
  }
@@ -10626,16 +10712,16 @@ var session_recap_default = plugin31;
10626
10712
 
10627
10713
  // src/shell-check/index.ts
10628
10714
  import { execFileSync as execFileSync6, execSync as execSync2 } from "node:child_process";
10629
- import { existsSync as existsSync5, readdirSync as readdirSync2 } from "node:fs";
10630
- import { isAbsolute as isAbsolute11, join as join3, relative as relative10, resolve as resolve10 } from "node:path";
10715
+ import { existsSync as existsSync6, readdirSync as readdirSync3 } from "node:fs";
10716
+ import { isAbsolute as isAbsolute12, join as join4, relative as relative11, resolve as resolve11 } from "node:path";
10631
10717
  var API_VERSION15 = "^0.1.10";
10632
10718
  function withinProject3(p) {
10633
10719
  const root = process.cwd();
10634
- const resolved = isAbsolute11(p) ? resolve10(p) : resolve10(root, p);
10635
- const rel = relative10(root, resolved);
10720
+ const resolved = isAbsolute12(p) ? resolve11(p) : resolve11(root, p);
10721
+ const rel = relative11(root, resolved);
10636
10722
  if (rel === "" || rel === ".") return true;
10637
10723
  if (rel.startsWith("..")) return false;
10638
- if (isAbsolute11(rel)) return false;
10724
+ if (isAbsolute12(rel)) return false;
10639
10725
  return true;
10640
10726
  }
10641
10727
  var MAX_PATH_LEN = 4096;
@@ -10648,7 +10734,7 @@ var state30 = {
10648
10734
  lastRun: null
10649
10735
  };
10650
10736
  function runShellCheck(files, severity, cwd) {
10651
- if (!existsSync5("shellcheck")) {
10737
+ if (!existsSync6("shellcheck")) {
10652
10738
  try {
10653
10739
  execSync2("shellcheck --version", { encoding: "utf-8", stdio: "ignore", windowsHide: true });
10654
10740
  } catch {
@@ -10700,9 +10786,9 @@ function runShellCheck(files, severity, cwd) {
10700
10786
  function findShellFiles(dir, pattern) {
10701
10787
  const results = [];
10702
10788
  try {
10703
- const entries = readdirSync2(dir, { withFileTypes: true });
10789
+ const entries = readdirSync3(dir, { withFileTypes: true });
10704
10790
  for (const entry of entries) {
10705
- const full = join3(dir, entry.name);
10791
+ const full = join4(dir, entry.name);
10706
10792
  if (entry.isDirectory() && entry.name !== "node_modules" && entry.name !== ".git") {
10707
10793
  results.push(...findShellFiles(full, pattern));
10708
10794
  } else if (entry.isFile() && (entry.name.endsWith(".sh") || entry.name === "Dockerfile")) {
@@ -10906,7 +10992,7 @@ var shell_check_default = plugin32;
10906
10992
  import * as fs3 from "node:fs/promises";
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 {