@wrongstack/plugins 0.284.1 → 0.286.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 (263) hide show
  1. package/README.md +18 -14
  2. package/dist/accessibility-auditor/index.d.ts +38 -0
  3. package/dist/accessibility-auditor/index.d.ts.map +1 -0
  4. package/dist/accessibility-auditor.d.ts +2 -40
  5. package/dist/accessibility-auditor.js +10 -15
  6. package/dist/agent-handoff/index.d.ts +35 -0
  7. package/dist/agent-handoff/index.d.ts.map +1 -0
  8. package/dist/agent-handoff.d.ts +2 -37
  9. package/dist/agent-handoff.js +3 -2
  10. package/dist/api-compatibility-gate/index.d.ts +36 -0
  11. package/dist/api-compatibility-gate/index.d.ts.map +1 -0
  12. package/dist/api-compatibility-gate.d.ts +2 -38
  13. package/dist/api-compatibility-gate.js +6 -6
  14. package/dist/auto-doc/index.d.ts +20 -0
  15. package/dist/auto-doc/index.d.ts.map +1 -0
  16. package/dist/auto-doc.d.ts +2 -22
  17. package/dist/auto-doc.js +5 -5
  18. package/dist/auto-escalate/index.d.ts +43 -0
  19. package/dist/auto-escalate/index.d.ts.map +1 -0
  20. package/dist/auto-escalate.d.ts +2 -45
  21. package/dist/auto-escalate.js +5 -2
  22. package/dist/auto-i18n-extractor/index.d.ts +34 -0
  23. package/dist/auto-i18n-extractor/index.d.ts.map +1 -0
  24. package/dist/auto-i18n-extractor.d.ts +2 -36
  25. package/dist/auto-i18n-extractor.js +6 -7
  26. package/dist/branch-guard/index.d.ts +32 -0
  27. package/dist/branch-guard/index.d.ts.map +1 -0
  28. package/dist/branch-guard.d.ts +2 -34
  29. package/dist/branch-guard.js +4 -4
  30. package/dist/catalog.d.ts +39 -0
  31. package/dist/catalog.d.ts.map +1 -0
  32. package/dist/changelog-writer/index.d.ts +71 -0
  33. package/dist/changelog-writer/index.d.ts.map +1 -0
  34. package/dist/changelog-writer.d.ts +2 -73
  35. package/dist/changelog-writer.js +9 -5
  36. package/dist/checkpoint/index.d.ts +53 -0
  37. package/dist/checkpoint/index.d.ts.map +1 -0
  38. package/dist/checkpoint.d.ts +2 -55
  39. package/dist/checkpoint.js +6 -6
  40. package/dist/code-metrics/index.d.ts +29 -0
  41. package/dist/code-metrics/index.d.ts.map +1 -0
  42. package/dist/code-metrics.d.ts +2 -31
  43. package/dist/code-metrics.js +13 -15
  44. package/dist/commit-validator/index.d.ts +31 -0
  45. package/dist/commit-validator/index.d.ts.map +1 -0
  46. package/dist/commit-validator.d.ts +2 -33
  47. package/dist/commit-validator.js +5 -3
  48. package/dist/config-validator/index.d.ts +46 -0
  49. package/dist/config-validator/index.d.ts.map +1 -0
  50. package/dist/config-validator.d.ts +2 -48
  51. package/dist/config-validator.js +8 -4
  52. package/dist/context-pins/index.d.ts +43 -0
  53. package/dist/context-pins/index.d.ts.map +1 -0
  54. package/dist/context-pins.d.ts +2 -45
  55. package/dist/context-pins.js +5 -5
  56. package/dist/cost-tracker/index.d.ts +51 -0
  57. package/dist/cost-tracker/index.d.ts.map +1 -0
  58. package/dist/cost-tracker.d.ts +2 -53
  59. package/dist/cost-tracker.js +4 -4
  60. package/dist/cron/index.d.ts +12 -0
  61. package/dist/cron/index.d.ts.map +1 -0
  62. package/dist/cron.d.ts +2 -14
  63. package/dist/cron.js +3 -2
  64. package/dist/dead-code-detector/index.d.ts +32 -0
  65. package/dist/dead-code-detector/index.d.ts.map +1 -0
  66. package/dist/dead-code-detector.d.ts +2 -34
  67. package/dist/dead-code-detector.js +8 -9
  68. package/dist/dep-guard/index.d.ts +63 -0
  69. package/dist/dep-guard/index.d.ts.map +1 -0
  70. package/dist/dep-guard.d.ts +2 -65
  71. package/dist/dep-guard.js +6 -2
  72. package/dist/dependency-vulnerability-gate/index.d.ts +33 -0
  73. package/dist/dependency-vulnerability-gate/index.d.ts.map +1 -0
  74. package/dist/dependency-vulnerability-gate.d.ts +2 -35
  75. package/dist/dependency-vulnerability-gate.js +5 -5
  76. package/dist/diff-summary/index.d.ts +34 -0
  77. package/dist/diff-summary/index.d.ts.map +1 -0
  78. package/dist/diff-summary.d.ts +2 -36
  79. package/dist/diff-summary.js +5 -5
  80. package/dist/doc-sync-guard/index.d.ts +31 -0
  81. package/dist/doc-sync-guard/index.d.ts.map +1 -0
  82. package/dist/doc-sync-guard.d.ts +2 -33
  83. package/dist/doc-sync-guard.js +4 -4
  84. package/dist/duplicate-code-detector/index.d.ts +31 -0
  85. package/dist/duplicate-code-detector/index.d.ts.map +1 -0
  86. package/dist/duplicate-code-detector.d.ts +2 -33
  87. package/dist/duplicate-code-detector.js +5 -5
  88. package/dist/error-lens/index.d.ts +65 -0
  89. package/dist/error-lens/index.d.ts.map +1 -0
  90. package/dist/error-lens.d.ts +2 -67
  91. package/dist/error-lens.js +5 -2
  92. package/dist/feature-flag-tracker/index.d.ts +36 -0
  93. package/dist/feature-flag-tracker/index.d.ts.map +1 -0
  94. package/dist/feature-flag-tracker.d.ts +2 -38
  95. package/dist/feature-flag-tracker.js +6 -7
  96. package/dist/file-watcher/index.d.ts +12 -0
  97. package/dist/file-watcher/index.d.ts.map +1 -0
  98. package/dist/file-watcher.d.ts +2 -14
  99. package/dist/file-watcher.js +7 -7
  100. package/dist/format-on-save/index.d.ts +33 -0
  101. package/dist/format-on-save/index.d.ts.map +1 -0
  102. package/dist/format-on-save.d.ts +2 -35
  103. package/dist/format-on-save.js +6 -6
  104. package/dist/git-autocommit/index.d.ts +15 -0
  105. package/dist/git-autocommit/index.d.ts.map +1 -0
  106. package/dist/git-autocommit.d.ts +2 -17
  107. package/dist/git-autocommit.js +5 -5
  108. package/dist/import-organizer/index.d.ts +50 -0
  109. package/dist/import-organizer/index.d.ts.map +1 -0
  110. package/dist/import-organizer.d.ts +2 -52
  111. package/dist/import-organizer.js +6 -6
  112. package/dist/index.d.ts +186 -64
  113. package/dist/index.d.ts.map +1 -0
  114. package/dist/index.js +992 -454
  115. package/dist/injection-shield/index.d.ts +47 -0
  116. package/dist/injection-shield/index.d.ts.map +1 -0
  117. package/dist/injection-shield.d.ts +2 -49
  118. package/dist/injection-shield.js +4 -2
  119. package/dist/interface-contract-guard/index.d.ts +35 -0
  120. package/dist/interface-contract-guard/index.d.ts.map +1 -0
  121. package/dist/interface-contract-guard.d.ts +2 -37
  122. package/dist/interface-contract-guard.js +6 -7
  123. package/dist/knowledge-graph/index.d.ts +43 -0
  124. package/dist/knowledge-graph/index.d.ts.map +1 -0
  125. package/dist/knowledge-graph.d.ts +2 -45
  126. package/dist/knowledge-graph.js +5 -5
  127. package/dist/license-audit-gate/index.d.ts +32 -0
  128. package/dist/license-audit-gate/index.d.ts.map +1 -0
  129. package/dist/license-audit-gate.d.ts +2 -34
  130. package/dist/license-audit-gate.js +6 -7
  131. package/dist/lint-gate/index.d.ts +31 -0
  132. package/dist/lint-gate/index.d.ts.map +1 -0
  133. package/dist/lint-gate.d.ts +2 -33
  134. package/dist/lint-gate.js +7 -7
  135. package/dist/llm-cache/index.d.ts +54 -0
  136. package/dist/llm-cache/index.d.ts.map +1 -0
  137. package/dist/llm-cache.d.ts +2 -56
  138. package/dist/llm-cache.js +6 -4
  139. package/dist/loop-breaker/index.d.ts +4 -0
  140. package/dist/loop-breaker/index.d.ts.map +1 -0
  141. package/dist/loop-breaker.d.ts +2 -5
  142. package/dist/loop-breaker.js +4 -4
  143. package/dist/migration-planner/index.d.ts +28 -0
  144. package/dist/migration-planner/index.d.ts.map +1 -0
  145. package/dist/migration-planner.d.ts +2 -30
  146. package/dist/migration-planner.js +5 -5
  147. package/dist/model-router/index.d.ts +67 -0
  148. package/dist/model-router/index.d.ts.map +1 -0
  149. package/dist/model-router.d.ts +2 -69
  150. package/dist/model-router.js +5 -2
  151. package/dist/notify-hub/index.d.ts +43 -0
  152. package/dist/notify-hub/index.d.ts.map +1 -0
  153. package/dist/notify-hub.d.ts +2 -45
  154. package/dist/notify-hub.js +3 -2
  155. package/dist/path-guard/index.d.ts +52 -0
  156. package/dist/path-guard/index.d.ts.map +1 -0
  157. package/dist/path-guard.d.ts +2 -54
  158. package/dist/path-guard.js +5 -2
  159. package/dist/performance-regression-gate/index.d.ts +31 -0
  160. package/dist/performance-regression-gate/index.d.ts.map +1 -0
  161. package/dist/performance-regression-gate.d.ts +2 -33
  162. package/dist/performance-regression-gate.js +5 -5
  163. package/dist/plugin-stack-observer/index.d.ts +33 -0
  164. package/dist/plugin-stack-observer/index.d.ts.map +1 -0
  165. package/dist/plugin-stack-observer.d.ts +2 -35
  166. package/dist/plugin-stack-observer.js +3 -2
  167. package/dist/pr-drafter/index.d.ts +33 -0
  168. package/dist/pr-drafter/index.d.ts.map +1 -0
  169. package/dist/pr-drafter.d.ts +2 -35
  170. package/dist/pr-drafter.js +6 -6
  171. package/dist/prompt-firewall/index.d.ts +55 -0
  172. package/dist/prompt-firewall/index.d.ts.map +1 -0
  173. package/dist/prompt-firewall.d.ts +2 -57
  174. package/dist/prompt-firewall.js +5 -2
  175. package/dist/refactor-suggester/index.d.ts +36 -0
  176. package/dist/refactor-suggester/index.d.ts.map +1 -0
  177. package/dist/refactor-suggester.d.ts +2 -38
  178. package/dist/refactor-suggester.js +16 -17
  179. package/dist/release-notes-generator/index.d.ts +25 -0
  180. package/dist/release-notes-generator/index.d.ts.map +1 -0
  181. package/dist/release-notes-generator.d.ts +2 -27
  182. package/dist/release-notes-generator.js +28 -10
  183. package/dist/runtime/index.d.ts +124 -0
  184. package/dist/runtime/index.d.ts.map +1 -0
  185. package/dist/runtime.d.ts +1 -0
  186. package/dist/runtime.js +216 -0
  187. package/dist/schema-evolution-guard/index.d.ts +40 -0
  188. package/dist/schema-evolution-guard/index.d.ts.map +1 -0
  189. package/dist/schema-evolution-guard.d.ts +2 -42
  190. package/dist/schema-evolution-guard.js +5 -5
  191. package/dist/secret-scanner/index.d.ts +32 -0
  192. package/dist/secret-scanner/index.d.ts.map +1 -0
  193. package/dist/secret-scanner.d.ts +2 -34
  194. package/dist/secret-scanner.js +3 -2
  195. package/dist/security-hotspot-scanner/index.d.ts +28 -0
  196. package/dist/security-hotspot-scanner/index.d.ts.map +1 -0
  197. package/dist/security-hotspot-scanner.d.ts +2 -30
  198. package/dist/security-hotspot-scanner.js +6 -6
  199. package/dist/semantic-search-indexer/index.d.ts +36 -0
  200. package/dist/semantic-search-indexer/index.d.ts.map +1 -0
  201. package/dist/semantic-search-indexer.d.ts +2 -38
  202. package/dist/semantic-search-indexer.js +22 -6
  203. package/dist/semver-bump/index.d.ts +24 -0
  204. package/dist/semver-bump/index.d.ts.map +1 -0
  205. package/dist/semver-bump.d.ts +2 -26
  206. package/dist/semver-bump.js +10 -8
  207. package/dist/session-recap/index.d.ts +48 -0
  208. package/dist/session-recap/index.d.ts.map +1 -0
  209. package/dist/session-recap.d.ts +2 -50
  210. package/dist/session-recap.js +6 -4
  211. package/dist/shell-check/index.d.ts +14 -0
  212. package/dist/shell-check/index.d.ts.map +1 -0
  213. package/dist/shell-check.d.ts +2 -16
  214. package/dist/shell-check.js +6 -6
  215. package/dist/smart-rename/index.d.ts +24 -0
  216. package/dist/smart-rename/index.d.ts.map +1 -0
  217. package/dist/smart-rename.d.ts +2 -26
  218. package/dist/smart-rename.js +5 -5
  219. package/dist/spec-linker/index.d.ts +49 -0
  220. package/dist/spec-linker/index.d.ts.map +1 -0
  221. package/dist/spec-linker.d.ts +2 -51
  222. package/dist/spec-linker.js +20086 -244
  223. package/dist/template-engine/index.d.ts +13 -0
  224. package/dist/template-engine/index.d.ts.map +1 -0
  225. package/dist/template-engine.d.ts +2 -15
  226. package/dist/template-engine.js +7 -7
  227. package/dist/test-coverage-gate/index.d.ts +35 -0
  228. package/dist/test-coverage-gate/index.d.ts.map +1 -0
  229. package/dist/test-coverage-gate.d.ts +2 -37
  230. package/dist/test-coverage-gate.js +5 -5
  231. package/dist/test-flake-detector/index.d.ts +25 -0
  232. package/dist/test-flake-detector/index.d.ts.map +1 -0
  233. package/dist/test-flake-detector.d.ts +2 -27
  234. package/dist/test-flake-detector.js +98 -13
  235. package/dist/test-generator/index.d.ts +30 -0
  236. package/dist/test-generator/index.d.ts.map +1 -0
  237. package/dist/test-generator.d.ts +2 -32
  238. package/dist/test-generator.js +19 -20
  239. package/dist/test-runner-gate/index.d.ts +35 -0
  240. package/dist/test-runner-gate/index.d.ts.map +1 -0
  241. package/dist/test-runner-gate.d.ts +2 -37
  242. package/dist/test-runner-gate.js +6 -6
  243. package/dist/todo-listener/index.d.ts +35 -0
  244. package/dist/todo-listener/index.d.ts.map +1 -0
  245. package/dist/todo-listener.d.ts +2 -37
  246. package/dist/todo-listener.js +3 -2
  247. package/dist/todo-tracker/index.d.ts +4 -0
  248. package/dist/todo-tracker/index.d.ts.map +1 -0
  249. package/dist/todo-tracker.d.ts +2 -5
  250. package/dist/todo-tracker.js +5 -5
  251. package/dist/token-budget/index.d.ts +38 -0
  252. package/dist/token-budget/index.d.ts.map +1 -0
  253. package/dist/token-budget.d.ts +2 -40
  254. package/dist/token-budget.js +3 -2
  255. package/dist/token-throttle/index.d.ts +52 -0
  256. package/dist/token-throttle/index.d.ts.map +1 -0
  257. package/dist/token-throttle.d.ts +2 -54
  258. package/dist/token-throttle.js +6 -2
  259. package/dist/type-gate/index.d.ts +35 -0
  260. package/dist/type-gate/index.d.ts.map +1 -0
  261. package/dist/type-gate.d.ts +2 -37
  262. package/dist/type-gate.js +236 -43
  263. package/package.json +10 -7
package/dist/index.js CHANGED
@@ -1,14 +1,3 @@
1
- import { dirname, resolve, extname, isAbsolute, relative, join, basename } from 'path';
2
- import { execSync, execFileSync, execFile, spawn } from 'child_process';
3
- import * as fs from 'fs';
4
- import { readFileSync, writeFileSync, mkdirSync, statSync, watch, existsSync, readdirSync } from 'fs';
5
- import * as fsp from 'fs/promises';
6
- import { readFile, stat, mkdtemp, writeFile, rm } from 'fs/promises';
7
- import { expectDefined } from '@wrongstack/core';
8
- import { tmpdir } from 'os';
9
- import { randomUUID, createHash } from 'crypto';
10
- import { toErrorMessage } from '@wrongstack/core/utils';
11
-
12
1
  // src/agent-handoff/index.ts
13
2
  var API_VERSION = "^0.1.10";
14
3
  var state = {
@@ -305,6 +294,9 @@ var plugin = {
305
294
  }
306
295
  };
307
296
  var agent_handoff_default = plugin;
297
+
298
+ // src/auto-doc/index.ts
299
+ import { isAbsolute, relative, resolve } from "node:path";
308
300
  var AUTO_DOC_API_VERSION = "^0.1.10";
309
301
  function resolveProjectPath(rawPath, cwd = process.cwd()) {
310
302
  if (typeof rawPath !== "string" || rawPath.length === 0) return null;
@@ -491,10 +483,10 @@ async function runAutoDoc(input, api) {
491
483
  continue;
492
484
  }
493
485
  try {
494
- const { readFileSync: readFileSync24, writeFileSync: writeFileSync8 } = await import('fs');
486
+ const { readFileSync: readFileSync25, writeFileSync: writeFileSync8 } = await import("node:fs");
495
487
  let content;
496
488
  try {
497
- content = readFileSync24(safeFile, "utf-8");
489
+ content = readFileSync25(safeFile, "utf-8");
498
490
  } catch {
499
491
  api.log.warn(`auto-doc: could not read file ${safeFile}`);
500
492
  continue;
@@ -840,6 +832,9 @@ var plugin3 = {
840
832
  }
841
833
  };
842
834
  var auto_escalate_default = plugin3;
835
+
836
+ // src/branch-guard/index.ts
837
+ import { execFile } from "node:child_process";
843
838
  var API_VERSION2 = "^0.1.10";
844
839
  var state4 = {
845
840
  invocationCount: 0,
@@ -892,14 +887,14 @@ function hasDisabledPluginEntry(raw) {
892
887
  });
893
888
  }
894
889
  function runGit(args, cwd, signal) {
895
- return new Promise((resolve34, reject) => {
890
+ return new Promise((resolve36, reject) => {
896
891
  execFile(
897
892
  "git",
898
893
  args,
899
894
  { encoding: "utf-8", timeout: 3e3, cwd, windowsHide: true, signal },
900
895
  (error, stdout) => {
901
896
  if (error) reject(error);
902
- else resolve34(stdout);
897
+ else resolve36(stdout);
903
898
  }
904
899
  );
905
900
  });
@@ -1138,6 +1133,10 @@ var plugin4 = {
1138
1133
  }
1139
1134
  };
1140
1135
  var branch_guard_default = plugin4;
1136
+
1137
+ // src/changelog-writer/index.ts
1138
+ import { readFileSync, writeFileSync } from "node:fs";
1139
+ import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2 } from "node:path";
1141
1140
  var state5 = {
1142
1141
  entries: [],
1143
1142
  filesTouched: /* @__PURE__ */ new Set(),
@@ -1154,10 +1153,10 @@ var DEFAULTS3 = {
1154
1153
  maxEntries: 200
1155
1154
  };
1156
1155
  function resolveProjectPath2(rawPath, cwd = process.cwd()) {
1157
- const root = resolve(cwd);
1158
- const resolved = isAbsolute(rawPath) ? resolve(rawPath) : resolve(root, rawPath);
1159
- const rel = relative(root, resolved);
1160
- if (rel === "" || !rel.startsWith("..") && !isAbsolute(rel)) return resolved;
1156
+ const root = resolve2(cwd);
1157
+ const resolved = isAbsolute2(rawPath) ? resolve2(rawPath) : resolve2(root, rawPath);
1158
+ const rel = relative2(root, resolved);
1159
+ if (rel === "" || !rel.startsWith("..") && !isAbsolute2(rel)) return resolved;
1161
1160
  return null;
1162
1161
  }
1163
1162
  function readConfig4(raw) {
@@ -1512,6 +1511,11 @@ var plugin5 = {
1512
1511
  }
1513
1512
  };
1514
1513
  var changelog_writer_default = plugin5;
1514
+
1515
+ // src/checkpoint/index.ts
1516
+ import { mkdirSync, readFileSync as readFileSync2, statSync, writeFileSync as writeFileSync2 } from "node:fs";
1517
+ import { readFile, stat } from "node:fs/promises";
1518
+ import { dirname, isAbsolute as isAbsolute3, relative as relative3, resolve as resolve3 } from "node:path";
1515
1519
  var state6 = {
1516
1520
  snapshots: [],
1517
1521
  nextId: 1,
@@ -1537,10 +1541,10 @@ function readConfig5(raw) {
1537
1541
  };
1538
1542
  }
1539
1543
  function resolveProjectPath3(rawPath, cwd = process.cwd()) {
1540
- const root = resolve(cwd);
1541
- const resolved = isAbsolute(rawPath) ? resolve(rawPath) : resolve(root, rawPath);
1542
- const rel = relative(root, resolved);
1543
- if (rel === "" || !rel.startsWith("..") && !isAbsolute(rel)) return resolved;
1544
+ const root = resolve3(cwd);
1545
+ const resolved = isAbsolute3(rawPath) ? resolve3(rawPath) : resolve3(root, rawPath);
1546
+ const rel = relative3(root, resolved);
1547
+ if (rel === "" || !rel.startsWith("..") && !isAbsolute3(rel)) return resolved;
1544
1548
  return null;
1545
1549
  }
1546
1550
  function hashContent(s) {
@@ -1555,7 +1559,7 @@ function captureFile(path, maxBytes) {
1555
1559
  try {
1556
1560
  const st = statSync(path);
1557
1561
  if (st.size > maxBytes) return "too-large";
1558
- const content = readFileSync(path, "utf-8");
1562
+ const content = readFileSync2(path, "utf-8");
1559
1563
  return { path, content, bytes: st.size };
1560
1564
  } catch {
1561
1565
  return { path, content: null, bytes: 0 };
@@ -1809,7 +1813,7 @@ var plugin6 = {
1809
1813
  }
1810
1814
  try {
1811
1815
  mkdirSync(dirname(f.path), { recursive: true });
1812
- writeFileSync(f.path, f.content);
1816
+ writeFileSync2(f.path, f.content);
1813
1817
  restored.push(f.path);
1814
1818
  } catch (err) {
1815
1819
  errors.push({ path: f.path, error: err instanceof Error ? err.message : String(err) });
@@ -1950,7 +1954,8 @@ function parseCommitMessage(message, cfg) {
1950
1954
  errors.push(
1951
1955
  `Type "${type}" is not in allowedTypes: ${cfg.allowedTypes.join(", ")}. Standard types: ${STANDARD_TYPES.join(", ")}.`
1952
1956
  );
1953
- } else if (cfg.allowedTypes.length === 0 && !STANDARD_TYPES.includes(type)) ;
1957
+ } else if (cfg.allowedTypes.length === 0 && !STANDARD_TYPES.includes(type)) {
1958
+ }
1954
1959
  if (cfg.requireScope && !scope) {
1955
1960
  errors.push("A scope is required (e.g. feat(auth): ...).");
1956
1961
  }
@@ -2244,6 +2249,9 @@ Suggested rewrite (${suggest.model}):
2244
2249
  }
2245
2250
  };
2246
2251
  var commit_validator_default = plugin7;
2252
+
2253
+ // src/config-validator/index.ts
2254
+ import { readFileSync as readFileSync3, statSync as statSync2 } from "node:fs";
2247
2255
  var state8 = {
2248
2256
  invocations: 0,
2249
2257
  filesChecked: 0,
@@ -2504,8 +2512,8 @@ var plugin8 = {
2504
2512
  if (!cfg.extensions.some((ext) => lower.endsWith(ext))) return;
2505
2513
  let text;
2506
2514
  try {
2507
- if (statSync(raw).size > cfg.maxFileBytes) return;
2508
- text = readFileSync(raw, "utf-8");
2515
+ if (statSync2(raw).size > cfg.maxFileBytes) return;
2516
+ text = readFileSync3(raw, "utf-8");
2509
2517
  } catch {
2510
2518
  return;
2511
2519
  }
@@ -2586,6 +2594,10 @@ var plugin8 = {
2586
2594
  }
2587
2595
  };
2588
2596
  var config_validator_default = plugin8;
2597
+
2598
+ // src/context-pins/index.ts
2599
+ import * as fs from "node:fs";
2600
+ import { dirname as dirname2, isAbsolute as isAbsolute4, relative as relative4, resolve as resolve4 } from "node:path";
2589
2601
  var state9 = {
2590
2602
  pins: [],
2591
2603
  nextId: 1,
@@ -2602,10 +2614,10 @@ var DEFAULTS7 = {
2602
2614
  };
2603
2615
  function resolveProjectPath4(rawPath, cwd = process.cwd()) {
2604
2616
  if (typeof rawPath !== "string" || rawPath.length === 0) return "";
2605
- const root = resolve(cwd);
2606
- const resolved = isAbsolute(rawPath) ? resolve(rawPath) : resolve(root, rawPath);
2607
- const rel = relative(root, resolved);
2608
- if (rel === "" || !rel.startsWith("..") && !isAbsolute(rel)) return resolved;
2617
+ const root = resolve4(cwd);
2618
+ const resolved = isAbsolute4(rawPath) ? resolve4(rawPath) : resolve4(root, rawPath);
2619
+ const rel = relative4(root, resolved);
2620
+ if (rel === "" || !rel.startsWith("..") && !isAbsolute4(rel)) return resolved;
2609
2621
  return null;
2610
2622
  }
2611
2623
  function readConfig8(raw) {
@@ -2635,7 +2647,7 @@ function loadPins(filePath) {
2635
2647
  function persistPins(filePath) {
2636
2648
  if (!filePath) return true;
2637
2649
  try {
2638
- fs.mkdirSync(dirname(filePath), { recursive: true });
2650
+ fs.mkdirSync(dirname2(filePath), { recursive: true });
2639
2651
  fs.writeFileSync(filePath, JSON.stringify({ pins: state9.pins, nextId: state9.nextId }, null, 2));
2640
2652
  return true;
2641
2653
  } catch {
@@ -2829,6 +2841,9 @@ var plugin9 = {
2829
2841
  }
2830
2842
  };
2831
2843
  var context_pins_default = plugin9;
2844
+
2845
+ // src/cost-tracker/index.ts
2846
+ import { expectDefined } from "@wrongstack/core";
2832
2847
  var API_VERSION4 = "^0.1.10";
2833
2848
  var PRICING = {
2834
2849
  "gpt-4o": { input: 5, output: 15 },
@@ -3786,15 +3801,19 @@ ${notes.map((n) => ` - ${n}`).join("\n")}`
3786
3801
  }
3787
3802
  };
3788
3803
  var dep_guard_default = plugin12;
3804
+
3805
+ // src/diff-summary/index.ts
3806
+ import { execFileSync } from "node:child_process";
3807
+ import { isAbsolute as isAbsolute5, relative as relative5, resolve as resolve5 } from "node:path";
3789
3808
  var API_VERSION6 = "^0.1.10";
3790
3809
  function withinProject(p) {
3791
3810
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
3792
3811
  const root = process.cwd();
3793
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
3794
- const rel = relative(root, resolved);
3812
+ const resolved = isAbsolute5(p) ? resolve5(p) : resolve5(root, p);
3813
+ const rel = relative5(root, resolved);
3795
3814
  if (rel === "" || rel === ".") return true;
3796
3815
  if (rel.startsWith("..")) return false;
3797
- if (isAbsolute(rel)) return false;
3816
+ if (isAbsolute5(rel)) return false;
3798
3817
  return true;
3799
3818
  }
3800
3819
  var state12 = {
@@ -4381,15 +4400,19 @@ ${errorLine ?? "(no error line)"}
4381
4400
  }
4382
4401
  };
4383
4402
  var error_lens_default = plugin14;
4403
+
4404
+ // src/file-watcher/index.ts
4405
+ import { watch as fsWatch } from "node:fs";
4406
+ import { isAbsolute as isAbsolute6, relative as relative6, resolve as resolve6 } from "node:path";
4384
4407
  var API_VERSION7 = "^0.1.10";
4385
4408
  function withinProject2(p) {
4386
4409
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
4387
4410
  const root = process.cwd();
4388
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
4389
- const rel = relative(root, resolved);
4411
+ const resolved = isAbsolute6(p) ? resolve6(p) : resolve6(root, p);
4412
+ const rel = relative6(root, resolved);
4390
4413
  if (rel === "" || rel === ".") return true;
4391
4414
  if (rel.startsWith("..")) return false;
4392
- if (isAbsolute(rel)) return false;
4415
+ if (isAbsolute6(rel)) return false;
4393
4416
  return true;
4394
4417
  }
4395
4418
  var watch_idCounter = 0;
@@ -4487,7 +4510,7 @@ var plugin15 = {
4487
4510
  }
4488
4511
  function safeWatchDir(dirPath, recursive, handle) {
4489
4512
  try {
4490
- const watcher = watch(dirPath, { recursive }, (eventType, filename) => {
4513
+ const watcher = fsWatch(dirPath, { recursive }, (eventType, filename) => {
4491
4514
  if (!filename) return;
4492
4515
  const fullPath = `${dirPath}/${filename}`;
4493
4516
  const key = `${handle.id}:${fullPath}:${eventType}`;
@@ -4508,7 +4531,7 @@ var plugin15 = {
4508
4531
  `index:${fullPath}`,
4509
4532
  async () => {
4510
4533
  try {
4511
- const { enqueueReindex } = await import('@wrongstack/tools/codebase-index');
4534
+ const { enqueueReindex } = await import("@wrongstack/tools/codebase-index");
4512
4535
  const root = safeIndexRoot || dirPath;
4513
4536
  enqueueReindex({
4514
4537
  projectRoot: root,
@@ -4692,15 +4715,20 @@ var plugin15 = {
4692
4715
  }
4693
4716
  };
4694
4717
  var file_watcher_default = plugin15;
4718
+
4719
+ // src/format-on-save/index.ts
4720
+ import { execFileSync as execFileSync2, execSync } from "node:child_process";
4721
+ import { existsSync, statSync as statSync3 } from "node:fs";
4722
+ import { isAbsolute as isAbsolute7, relative as relative7, resolve as resolve7 } from "node:path";
4695
4723
  var API_VERSION8 = "^0.1.10";
4696
4724
  function withinProject3(p) {
4697
4725
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
4698
4726
  const root = process.cwd();
4699
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
4700
- const rel = relative(root, resolved);
4727
+ const resolved = isAbsolute7(p) ? resolve7(p) : resolve7(root, p);
4728
+ const rel = relative7(root, resolved);
4701
4729
  if (rel === "" || rel === ".") return true;
4702
4730
  if (rel.startsWith("..")) return false;
4703
- if (isAbsolute(rel)) return false;
4731
+ if (isAbsolute7(rel)) return false;
4704
4732
  return true;
4705
4733
  }
4706
4734
  var state14 = {
@@ -4765,12 +4793,12 @@ function formatFile(filePath, timeoutMs) {
4765
4793
  if (!existsSync(filePath)) return null;
4766
4794
  let bytesBefore;
4767
4795
  try {
4768
- bytesBefore = statSync(filePath).size;
4796
+ bytesBefore = statSync3(filePath).size;
4769
4797
  } catch {
4770
4798
  return null;
4771
4799
  }
4772
4800
  try {
4773
- execFileSync("npx", ["biome", "format", "--write", filePath], {
4801
+ execFileSync2("npx", ["biome", "format", "--write", filePath], {
4774
4802
  encoding: "utf-8",
4775
4803
  timeout: timeoutMs,
4776
4804
  cwd: process.cwd(),
@@ -4782,7 +4810,7 @@ function formatFile(filePath, timeoutMs) {
4782
4810
  }
4783
4811
  let bytesAfter;
4784
4812
  try {
4785
- bytesAfter = statSync(filePath).size;
4813
+ bytesAfter = statSync3(filePath).size;
4786
4814
  } catch {
4787
4815
  return null;
4788
4816
  }
@@ -4790,7 +4818,7 @@ function formatFile(filePath, timeoutMs) {
4790
4818
  return { changed: true, bytesBefore, bytesAfter };
4791
4819
  }
4792
4820
  try {
4793
- execFileSync("npx", ["biome", "format", filePath], {
4821
+ execFileSync2("npx", ["biome", "format", filePath], {
4794
4822
  encoding: "utf-8",
4795
4823
  timeout: timeoutMs,
4796
4824
  cwd: process.cwd(),
@@ -4985,6 +5013,10 @@ var plugin16 = {
4985
5013
  }
4986
5014
  };
4987
5015
  var format_on_save_default = plugin16;
5016
+
5017
+ // src/git-autocommit/index.ts
5018
+ import { execFileSync as execFileSync3 } from "node:child_process";
5019
+ import { existsSync as existsSync2 } from "node:fs";
4988
5020
  var API_VERSION9 = "^0.1.10";
4989
5021
  var commitCount = { value: 0 };
4990
5022
  var lastCommit = { hash: null, at: null };
@@ -4993,7 +5025,7 @@ var DEFAULT_GIT_TIMEOUT_MS = 3e4;
4993
5025
  var GIT_COMMIT_TIMEOUT_MS = 5 * 6e4;
4994
5026
  function runGit2(args, cwd, timeoutMs = DEFAULT_GIT_TIMEOUT_MS) {
4995
5027
  try {
4996
- return execFileSync("git", args, {
5028
+ return execFileSync3("git", args, {
4997
5029
  encoding: "utf-8",
4998
5030
  cwd,
4999
5031
  stdio: ["pipe", "pipe", "pipe"],
@@ -5019,7 +5051,7 @@ function stageFiles(files, cwd) {
5019
5051
  if (!files || !Array.isArray(files)) return;
5020
5052
  const existing = files.filter((f) => {
5021
5053
  try {
5022
- return existsSync(f);
5054
+ return existsSync2(f);
5023
5055
  } catch {
5024
5056
  return false;
5025
5057
  }
@@ -5441,14 +5473,19 @@ ${preCommitDiff}
5441
5473
  }
5442
5474
  };
5443
5475
  var git_autocommit_default = plugin17;
5476
+
5477
+ // src/import-organizer/index.ts
5478
+ import { spawn } from "node:child_process";
5479
+ import { existsSync as existsSync3, statSync as statSync4 } from "node:fs";
5480
+ import { basename, isAbsolute as isAbsolute8, relative as relative8, resolve as resolve8 } from "node:path";
5444
5481
  function withinProject4(p) {
5445
5482
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
5446
5483
  const root = process.cwd();
5447
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
5448
- const rel = relative(root, resolved);
5484
+ const resolved = isAbsolute8(p) ? resolve8(p) : resolve8(root, p);
5485
+ const rel = relative8(root, resolved);
5449
5486
  if (rel === "" || rel === ".") return true;
5450
5487
  if (rel.startsWith("..")) return false;
5451
- if (isAbsolute(rel)) return false;
5488
+ if (isAbsolute8(rel)) return false;
5452
5489
  return true;
5453
5490
  }
5454
5491
  var ALLOWED_FIRST_TOKENS = /* @__PURE__ */ new Set([
@@ -5470,12 +5507,12 @@ function resolveAllowedCommand(command) {
5470
5507
  if (ALLOWED_FIRST_TOKENS.has(head)) {
5471
5508
  return { cmd: head, args: tokens.slice(1) };
5472
5509
  }
5473
- if (isAbsolute(head)) {
5510
+ if (isAbsolute8(head)) {
5474
5511
  if (!withinProject4(head)) return null;
5475
5512
  const base = basename(head);
5476
5513
  if (ALLOWED_FIRST_TOKENS.has(base)) return { cmd: head, args: tokens.slice(1) };
5477
5514
  }
5478
- if (!isAbsolute(head) && withinProject4(head)) {
5515
+ if (!isAbsolute8(head) && withinProject4(head)) {
5479
5516
  const base = basename(head);
5480
5517
  if (ALLOWED_FIRST_TOKENS.has(base)) return { cmd: head, args: tokens.slice(1) };
5481
5518
  }
@@ -5511,7 +5548,7 @@ function readConfig13(raw) {
5511
5548
  };
5512
5549
  }
5513
5550
  function runCommand(command, args, timeoutMs, cwd) {
5514
- return new Promise((resolve34) => {
5551
+ return new Promise((resolve36) => {
5515
5552
  let timedOut = false;
5516
5553
  const stdoutChunks = [];
5517
5554
  const stderrChunks = [];
@@ -5523,17 +5560,17 @@ function runCommand(command, args, timeoutMs, cwd) {
5523
5560
  signal: AbortSignal.timeout(timeoutMs)
5524
5561
  });
5525
5562
  } catch {
5526
- resolve34({ code: 127, stdout: "", stderr: "", timedOut: false });
5563
+ resolve36({ code: 127, stdout: "", stderr: "", timedOut: false });
5527
5564
  return;
5528
5565
  }
5529
5566
  child.stdout?.on("data", (c) => stdoutChunks.push(c));
5530
5567
  child.stderr?.on("data", (c) => stderrChunks.push(c));
5531
5568
  child.on("error", () => {
5532
- resolve34({ code: 127, stdout: "", stderr: "", timedOut: false });
5569
+ resolve36({ code: 127, stdout: "", stderr: "", timedOut: false });
5533
5570
  });
5534
5571
  child.on("close", (code) => {
5535
5572
  if (timedOut) return;
5536
- resolve34({
5573
+ resolve36({
5537
5574
  code,
5538
5575
  stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
5539
5576
  stderr: Buffer.concat(stderrChunks).toString("utf-8"),
@@ -5542,16 +5579,16 @@ function runCommand(command, args, timeoutMs, cwd) {
5542
5579
  });
5543
5580
  child.on("abort", () => {
5544
5581
  timedOut = true;
5545
- resolve34({ code: null, stdout: "", stderr: "", timedOut: true });
5582
+ resolve36({ code: null, stdout: "", stderr: "", timedOut: true });
5546
5583
  });
5547
5584
  });
5548
5585
  }
5549
5586
  async function organizeImports(filePath, cfg, cwd) {
5550
5587
  if (!withinProject4(filePath)) return null;
5551
- if (!existsSync(filePath)) return null;
5588
+ if (!existsSync3(filePath)) return null;
5552
5589
  let bytesBefore;
5553
5590
  try {
5554
- bytesBefore = statSync(filePath).size;
5591
+ bytesBefore = statSync4(filePath).size;
5555
5592
  } catch {
5556
5593
  return null;
5557
5594
  }
@@ -5572,7 +5609,7 @@ async function organizeImports(filePath, cfg, cwd) {
5572
5609
  if (result.code === 127) return null;
5573
5610
  let bytesAfter;
5574
5611
  try {
5575
- bytesAfter = statSync(filePath).size;
5612
+ bytesAfter = statSync4(filePath).size;
5576
5613
  } catch {
5577
5614
  return null;
5578
5615
  }
@@ -5972,6 +6009,10 @@ var plugin19 = {
5972
6009
  }
5973
6010
  };
5974
6011
  var injection_shield_default = plugin19;
6012
+
6013
+ // src/knowledge-graph/index.ts
6014
+ import { mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "node:fs";
6015
+ import { dirname as dirname3, isAbsolute as isAbsolute9, relative as relative9, resolve as resolve9 } from "node:path";
5975
6016
  var API_VERSION11 = "^0.1.10";
5976
6017
  var state17 = {
5977
6018
  facts: [],
@@ -5992,10 +6033,10 @@ var DEFAULTS14 = {
5992
6033
  };
5993
6034
  function resolveProjectPath5(rawPath, cwd = process.cwd()) {
5994
6035
  if (typeof rawPath !== "string" || rawPath.length === 0) return null;
5995
- const root = resolve(cwd);
5996
- const resolved = isAbsolute(rawPath) ? resolve(rawPath) : resolve(root, rawPath);
5997
- const rel = relative(root, resolved);
5998
- if (rel === "" || !rel.startsWith("..") && !isAbsolute(rel)) return resolved;
6036
+ const root = resolve9(cwd);
6037
+ const resolved = isAbsolute9(rawPath) ? resolve9(rawPath) : resolve9(root, rawPath);
6038
+ const rel = relative9(root, resolved);
6039
+ if (rel === "" || !rel.startsWith("..") && !isAbsolute9(rel)) return resolved;
5999
6040
  return null;
6000
6041
  }
6001
6042
  function readConfig15(raw) {
@@ -6013,7 +6054,7 @@ function readConfig15(raw) {
6013
6054
  function loadFacts(filePath) {
6014
6055
  if (!filePath) return { facts: [], nextId: 1 };
6015
6056
  try {
6016
- const raw = JSON.parse(readFileSync(filePath, "utf-8"));
6057
+ const raw = JSON.parse(readFileSync5(filePath, "utf-8"));
6017
6058
  const facts = Array.isArray(raw.facts) ? raw.facts.filter(
6018
6059
  (f) => !!f && typeof f === "object" && typeof f.id === "string" && typeof f.subject === "string" && typeof f.relation === "string" && typeof f.object === "string"
6019
6060
  ) : [];
@@ -6026,8 +6067,8 @@ function loadFacts(filePath) {
6026
6067
  function persistFacts(filePath) {
6027
6068
  if (!filePath) return true;
6028
6069
  try {
6029
- mkdirSync(dirname(filePath), { recursive: true });
6030
- writeFileSync(
6070
+ mkdirSync3(dirname3(filePath), { recursive: true });
6071
+ writeFileSync4(
6031
6072
  filePath,
6032
6073
  JSON.stringify({ facts: state17.facts, nextId: state17.nextId }, null, 2)
6033
6074
  );
@@ -6291,6 +6332,12 @@ var plugin20 = {
6291
6332
  }
6292
6333
  };
6293
6334
  var knowledge_graph_default = plugin20;
6335
+
6336
+ // src/lint-gate/index.ts
6337
+ import { execFile as execFile2 } from "node:child_process";
6338
+ import { mkdtemp, readFile as readFile2, rm, writeFile } from "node:fs/promises";
6339
+ import { tmpdir } from "node:os";
6340
+ import { join } from "node:path";
6294
6341
  var API_VERSION12 = "^0.1.10";
6295
6342
  var state18 = {
6296
6343
  /** Total PreToolUse invocations. */
@@ -6328,9 +6375,9 @@ function executable(command) {
6328
6375
  return process.platform === "win32" && command === "npx" ? "npx.cmd" : command;
6329
6376
  }
6330
6377
  function runCommand2(command, args, timeoutMs, signal) {
6331
- return new Promise((resolve34) => {
6378
+ return new Promise((resolve36) => {
6332
6379
  try {
6333
- execFile(
6380
+ execFile2(
6334
6381
  executable(command),
6335
6382
  args,
6336
6383
  {
@@ -6341,10 +6388,10 @@ function runCommand2(command, args, timeoutMs, signal) {
6341
6388
  maxBuffer: 2 * 1024 * 1024,
6342
6389
  ...signal ? { signal } : {}
6343
6390
  },
6344
- (error, stdout) => resolve34({ stdout, error })
6391
+ (error, stdout) => resolve36({ stdout, error })
6345
6392
  );
6346
6393
  } catch (err) {
6347
- resolve34({ stdout: "", error: err instanceof Error ? err : new Error(String(err)) });
6394
+ resolve36({ stdout: "", error: err instanceof Error ? err : new Error(String(err)) });
6348
6395
  }
6349
6396
  });
6350
6397
  }
@@ -6392,7 +6439,7 @@ async function lintAndFix(content, filePath, linter, timeoutMs, signal) {
6392
6439
  const fixArgs = linter.name === "biome" ? ["biome", "check", "--write", tmpFile] : ["eslint", "--fix", tmpFile];
6393
6440
  await runCommand2(linter.cmd, fixArgs, timeoutMs, signal);
6394
6441
  if (signal.aborted) throw signal.reason;
6395
- return await readFile(tmpFile, "utf-8");
6442
+ return await readFile2(tmpFile, "utf-8");
6396
6443
  } catch {
6397
6444
  if (signal.aborted) throw signal.reason;
6398
6445
  return content;
@@ -6519,7 +6566,7 @@ var plugin21 = {
6519
6566
  const newStr = inp["new_string"];
6520
6567
  if (typeof oldStr !== "string" || typeof newStr !== "string") return;
6521
6568
  try {
6522
- const current = await readFile(filePath, "utf-8");
6569
+ const current = await readFile2(filePath, "utf-8");
6523
6570
  content = applyEdit(current, oldStr, newStr);
6524
6571
  } catch {
6525
6572
  return;
@@ -6713,6 +6760,9 @@ ${summary}${truncated}`
6713
6760
  }
6714
6761
  };
6715
6762
  var lint_gate_default = plugin21;
6763
+
6764
+ // src/llm-cache/index.ts
6765
+ import { createHash } from "node:crypto";
6716
6766
  var state19 = {
6717
6767
  cache: /* @__PURE__ */ new Map(),
6718
6768
  hits: 0,
@@ -6964,6 +7014,9 @@ var plugin22 = {
6964
7014
  }
6965
7015
  };
6966
7016
  var llm_cache_default = plugin22;
7017
+
7018
+ // src/loop-breaker/index.ts
7019
+ import { execFile as execFile3 } from "node:child_process";
6967
7020
  var state20 = {
6968
7021
  lastFingerprint: null,
6969
7022
  streak: 0,
@@ -7059,8 +7112,8 @@ function hashString2(value) {
7059
7112
  }
7060
7113
  async function gitDiffFingerprint(cwd, signal) {
7061
7114
  try {
7062
- const diff = await new Promise((resolve34, reject) => {
7063
- execFile(
7115
+ const diff = await new Promise((resolve36, reject) => {
7116
+ execFile3(
7064
7117
  "git",
7065
7118
  ["diff", "--no-ext-diff", "--"],
7066
7119
  {
@@ -7076,7 +7129,7 @@ async function gitDiffFingerprint(cwd, signal) {
7076
7129
  },
7077
7130
  (error, stdout) => {
7078
7131
  if (error) reject(error);
7079
- else resolve34(stdout);
7132
+ else resolve36(stdout);
7080
7133
  }
7081
7134
  );
7082
7135
  });
@@ -8330,6 +8383,11 @@ function readConfig22(raw) {
8330
8383
  };
8331
8384
  }
8332
8385
  var plugin_stack_observer_default = PLUGIN;
8386
+
8387
+ // src/pr-drafter/index.ts
8388
+ import { execFileSync as execFileSync4 } from "node:child_process";
8389
+ import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "node:fs";
8390
+ import { dirname as dirname4, isAbsolute as isAbsolute10, relative as relative10, resolve as resolve10 } from "node:path";
8333
8391
  var API_VERSION13 = "^0.1.10";
8334
8392
  var state25 = {
8335
8393
  commits: [],
@@ -8368,15 +8426,15 @@ function readConfig23(raw) {
8368
8426
  }
8369
8427
  function resolveProjectPath6(rawPath, cwd = process.cwd()) {
8370
8428
  if (typeof rawPath !== "string" || rawPath.length === 0) return null;
8371
- const root = resolve(cwd);
8372
- const resolved = isAbsolute(rawPath) ? resolve(rawPath) : resolve(root, rawPath);
8373
- const rel = relative(root, resolved);
8374
- if (rel === "" || !rel.startsWith("..") && !isAbsolute(rel)) return resolved;
8429
+ const root = resolve10(cwd);
8430
+ const resolved = isAbsolute10(rawPath) ? resolve10(rawPath) : resolve10(root, rawPath);
8431
+ const rel = relative10(root, resolved);
8432
+ if (rel === "" || !rel.startsWith("..") && !isAbsolute10(rel)) return resolved;
8375
8433
  return null;
8376
8434
  }
8377
8435
  function gitBranch() {
8378
8436
  try {
8379
- const out = execFileSync("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
8437
+ const out = execFileSync4("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
8380
8438
  encoding: "utf-8",
8381
8439
  cwd: process.cwd(),
8382
8440
  stdio: ["pipe", "pipe", "ignore"],
@@ -8389,7 +8447,7 @@ function gitBranch() {
8389
8447
  }
8390
8448
  function gitDiff() {
8391
8449
  try {
8392
- return execFileSync("git", ["diff", "--stat"], {
8450
+ return execFileSync4("git", ["diff", "--stat"], {
8393
8451
  encoding: "utf-8",
8394
8452
  cwd: process.cwd(),
8395
8453
  stdio: ["pipe", "pipe", "ignore"],
@@ -8458,8 +8516,8 @@ async function writeDraft(cfg, llm) {
8458
8516
  }
8459
8517
  const draft = await buildDraft(cfg, llm);
8460
8518
  try {
8461
- mkdirSync(dirname(resolved), { recursive: true });
8462
- writeFileSync(resolved, draft.body);
8519
+ mkdirSync4(dirname4(resolved), { recursive: true });
8520
+ writeFileSync5(resolved, draft.body);
8463
8521
  state25.draftsWritten += 1;
8464
8522
  } catch {
8465
8523
  state25.draftErrors += 1;
@@ -8585,8 +8643,8 @@ var plugin27 = {
8585
8643
  const resolved = resolveProjectPath6(cfg.outputPath);
8586
8644
  if (!resolved) return { ok: false, error: "outputPath resolves outside project" };
8587
8645
  try {
8588
- mkdirSync(dirname(resolved), { recursive: true });
8589
- writeFileSync(resolved, draft.body);
8646
+ mkdirSync4(dirname4(resolved), { recursive: true });
8647
+ writeFileSync5(resolved, draft.body);
8590
8648
  state25.draftsWritten += 1;
8591
8649
  return {
8592
8650
  ok: true,
@@ -9374,13 +9432,20 @@ var plugin29 = {
9374
9432
  }
9375
9433
  };
9376
9434
  var secret_scanner_default = plugin29;
9435
+
9436
+ // src/semver-bump/index.ts
9437
+ import { expectDefined as expectDefined2 } from "@wrongstack/core";
9438
+ import { toErrorMessage } from "@wrongstack/core/utils";
9439
+ import { execFileSync as execFileSync5 } from "node:child_process";
9440
+ import { existsSync as existsSync4, readFileSync as readFileSync6, readdirSync, writeFileSync as writeFileSync6 } from "node:fs";
9441
+ import { isAbsolute as isAbsolute11, join as join2, relative as relative11, resolve as resolve11 } from "node:path";
9377
9442
  var API_VERSION14 = "^0.1.10";
9378
9443
  function resolveProjectRoot(rawCwd, root = process.cwd()) {
9379
9444
  if (typeof rawCwd !== "string" || rawCwd.length === 0) return root;
9380
- const base = resolve(root);
9381
- const resolved = isAbsolute(rawCwd) ? resolve(rawCwd) : resolve(base, rawCwd);
9382
- const rel = relative(base, resolved);
9383
- if (rel === "" || !rel.startsWith("..") && !isAbsolute(rel)) return resolved;
9445
+ const base = resolve11(root);
9446
+ const resolved = isAbsolute11(rawCwd) ? resolve11(rawCwd) : resolve11(base, rawCwd);
9447
+ const rel = relative11(base, resolved);
9448
+ if (rel === "" || !rel.startsWith("..") && !isAbsolute11(rel)) return resolved;
9384
9449
  return null;
9385
9450
  }
9386
9451
  var state28 = {
@@ -9393,7 +9458,7 @@ var state28 = {
9393
9458
  };
9394
9459
  function runGit3(args, cwd) {
9395
9460
  try {
9396
- return execFileSync("git", args, {
9461
+ return execFileSync5("git", args, {
9397
9462
  encoding: "utf-8",
9398
9463
  cwd,
9399
9464
  stdio: ["pipe", "pipe", "pipe"],
@@ -9408,24 +9473,24 @@ function runGit3(args, cwd) {
9408
9473
  }
9409
9474
  function getPackageJson(cwd) {
9410
9475
  const path = cwd ? `${cwd}/package.json` : "package.json";
9411
- if (!existsSync(path)) return null;
9476
+ if (!existsSync4(path)) return null;
9412
9477
  try {
9413
- return JSON.parse(readFileSync(path, "utf-8"));
9478
+ return JSON.parse(readFileSync6(path, "utf-8"));
9414
9479
  } catch {
9415
9480
  return null;
9416
9481
  }
9417
9482
  }
9418
9483
  function collectManifests(root) {
9419
9484
  const paths = [];
9420
- const rootPkg = join(root, "package.json");
9421
- if (existsSync(rootPkg)) paths.push(rootPkg);
9485
+ const rootPkg = join2(root, "package.json");
9486
+ if (existsSync4(rootPkg)) paths.push(rootPkg);
9422
9487
  for (const group of ["packages", "apps"]) {
9423
- const groupDir = join(root, group);
9424
- if (!existsSync(groupDir)) continue;
9488
+ const groupDir = join2(root, group);
9489
+ if (!existsSync4(groupDir)) continue;
9425
9490
  for (const entry of readdirSync(groupDir, { withFileTypes: true })) {
9426
9491
  if (!entry.isDirectory()) continue;
9427
- const candidate = join(groupDir, entry.name, "package.json");
9428
- if (existsSync(candidate)) paths.push(candidate);
9492
+ const candidate = join2(groupDir, entry.name, "package.json");
9493
+ if (existsSync4(candidate)) paths.push(candidate);
9429
9494
  }
9430
9495
  }
9431
9496
  return paths;
@@ -9434,9 +9499,9 @@ function parseVersion(v) {
9434
9499
  const m = v.match(/^v?(\d+)\.(\d+)\.(\d+)/);
9435
9500
  if (!m) return [0, 0, 0];
9436
9501
  return [
9437
- Number.parseInt(expectDefined(m[1]), 10),
9438
- Number.parseInt(expectDefined(m[2]), 10),
9439
- Number.parseInt(expectDefined(m[3]), 10)
9502
+ Number.parseInt(expectDefined2(m[1]), 10),
9503
+ Number.parseInt(expectDefined2(m[2]), 10),
9504
+ Number.parseInt(expectDefined2(m[3]), 10)
9440
9505
  ];
9441
9506
  }
9442
9507
  function bumpVersion(version, part) {
@@ -9615,11 +9680,11 @@ var plugin30 = {
9615
9680
  };
9616
9681
  }
9617
9682
  const root = cwd ?? process.cwd();
9618
- const bumpScript = join(root, "scripts", "bump-version.mjs");
9683
+ const bumpScript = join2(root, "scripts", "bump-version.mjs");
9619
9684
  const changed = collectManifests(root);
9620
- if (existsSync(bumpScript)) {
9685
+ if (existsSync4(bumpScript)) {
9621
9686
  try {
9622
- execFileSync(process.execPath, [bumpScript, "set", newVersion], {
9687
+ execFileSync5(process.execPath, [bumpScript, "set", newVersion], {
9623
9688
  cwd: root,
9624
9689
  stdio: ["pipe", "pipe", "pipe"],
9625
9690
  timeout: 3e4,
@@ -9630,14 +9695,14 @@ var plugin30 = {
9630
9695
  return { ok: false, error: `bump script failed: ${msg}` };
9631
9696
  }
9632
9697
  for (const rel of ["package.json", "package-lock.json", "src/lib/utils.ts", "index.html"]) {
9633
- const p = join(root, "website", rel);
9634
- if (existsSync(p)) changed.push(p);
9698
+ const p = join2(root, "website", rel);
9699
+ if (existsSync4(p)) changed.push(p);
9635
9700
  }
9636
9701
  } else {
9637
9702
  for (const manifest of changed) {
9638
- const pkgData = JSON.parse(readFileSync(manifest, "utf-8"));
9703
+ const pkgData = JSON.parse(readFileSync6(manifest, "utf-8"));
9639
9704
  pkgData.version = newVersion;
9640
- writeFileSync(manifest, JSON.stringify(pkgData, null, 2) + "\n", "utf-8");
9705
+ writeFileSync6(manifest, JSON.stringify(pkgData, null, 2) + "\n", "utf-8");
9641
9706
  }
9642
9707
  }
9643
9708
  try {
@@ -9969,7 +10034,7 @@ async function readTranscriptTail(transcriptPath, n) {
9969
10034
  if (!transcriptPath || n <= 0) return [];
9970
10035
  let raw;
9971
10036
  try {
9972
- const { readFile: readFile6 } = await import('fs/promises');
10037
+ const { readFile: readFile6 } = await import("node:fs/promises");
9973
10038
  raw = await readFile6(transcriptPath, "utf-8");
9974
10039
  } catch {
9975
10040
  return [];
@@ -10071,7 +10136,8 @@ var plugin31 = {
10071
10136
  const p = payload;
10072
10137
  const toolName = p?.tool ?? p?.name ?? eventName;
10073
10138
  if (typeof toolName === "string") bumpToolCount(toolName);
10074
- if (toolName === "git_autocommit" || toolName.startsWith("git ")) ;
10139
+ if (toolName === "git_autocommit" || toolName.startsWith("git ")) {
10140
+ }
10075
10141
  });
10076
10142
  state29.eventUnsubscribers.push(offTool);
10077
10143
  const offResult = api.onPattern("tool.result", (_event, payload) => {
@@ -10306,14 +10372,19 @@ Tokens: ${recap.tokens.total.input} in / ${recap.tokens.total.output} out
10306
10372
  }
10307
10373
  };
10308
10374
  var session_recap_default = plugin31;
10375
+
10376
+ // src/shell-check/index.ts
10377
+ import { execFileSync as execFileSync6, execSync as execSync2 } from "node:child_process";
10378
+ import { existsSync as existsSync5, readdirSync as readdirSync2 } from "node:fs";
10379
+ import { isAbsolute as isAbsolute12, join as join3, relative as relative12, resolve as resolve12 } from "node:path";
10309
10380
  var API_VERSION15 = "^0.1.10";
10310
10381
  function withinProject5(p) {
10311
10382
  const root = process.cwd();
10312
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
10313
- const rel = relative(root, resolved);
10383
+ const resolved = isAbsolute12(p) ? resolve12(p) : resolve12(root, p);
10384
+ const rel = relative12(root, resolved);
10314
10385
  if (rel === "" || rel === ".") return true;
10315
10386
  if (rel.startsWith("..")) return false;
10316
- if (isAbsolute(rel)) return false;
10387
+ if (isAbsolute12(rel)) return false;
10317
10388
  return true;
10318
10389
  }
10319
10390
  var MAX_PATH_LEN = 4096;
@@ -10326,9 +10397,9 @@ var state30 = {
10326
10397
  lastRun: null
10327
10398
  };
10328
10399
  function runShellCheck(files, severity, cwd) {
10329
- if (!existsSync("shellcheck")) {
10400
+ if (!existsSync5("shellcheck")) {
10330
10401
  try {
10331
- execSync("shellcheck --version", { encoding: "utf-8", stdio: "ignore", windowsHide: true });
10402
+ execSync2("shellcheck --version", { encoding: "utf-8", stdio: "ignore", windowsHide: true });
10332
10403
  } catch {
10333
10404
  throw new Error(
10334
10405
  "shellcheck is not installed. Install via: apt install shellcheck / brew install shellcheck"
@@ -10345,7 +10416,7 @@ function runShellCheck(files, severity, cwd) {
10345
10416
  const args = ["-f", "json", "-S", severityFlag, ...files];
10346
10417
  let raw;
10347
10418
  try {
10348
- raw = execFileSync("shellcheck", args, {
10419
+ raw = execFileSync6("shellcheck", args, {
10349
10420
  encoding: "utf-8",
10350
10421
  cwd,
10351
10422
  stdio: ["pipe", "pipe", "pipe"],
@@ -10378,9 +10449,9 @@ function runShellCheck(files, severity, cwd) {
10378
10449
  function findShellFiles(dir, pattern) {
10379
10450
  const results = [];
10380
10451
  try {
10381
- const entries = readdirSync(dir, { withFileTypes: true });
10452
+ const entries = readdirSync2(dir, { withFileTypes: true });
10382
10453
  for (const entry of entries) {
10383
- const full = join(dir, entry.name);
10454
+ const full = join3(dir, entry.name);
10384
10455
  if (entry.isDirectory() && entry.name !== "node_modules" && entry.name !== ".git") {
10385
10456
  results.push(...findShellFiles(full, pattern));
10386
10457
  } else if (entry.isFile() && (entry.name.endsWith(".sh") || entry.name === "Dockerfile")) {
@@ -10579,6 +10650,12 @@ var plugin32 = {
10579
10650
  }
10580
10651
  };
10581
10652
  var shell_check_default = plugin32;
10653
+
10654
+ // src/spec-linker/index.ts
10655
+ import * as fs3 from "node:fs/promises";
10656
+
10657
+ // src/template-engine/index.ts
10658
+ import { isAbsolute as isAbsolute13 } from "node:path";
10582
10659
  var API_VERSION16 = "^0.1.10";
10583
10660
  var templates = /* @__PURE__ */ new Map();
10584
10661
  function expandTemplate(template, variables) {
@@ -10625,7 +10702,7 @@ function renderTemplateRaw(template, variables) {
10625
10702
  return result;
10626
10703
  }
10627
10704
  function validateRelativeTemplatePath(field, value) {
10628
- if (isAbsolute(value) || value.split(/[\\/]+/).includes("..")) {
10705
+ if (isAbsolute13(value) || value.split(/[\\/]+/).includes("..")) {
10629
10706
  return `${field} must be a relative path without ".." components`;
10630
10707
  }
10631
10708
  return null;
@@ -10698,7 +10775,7 @@ var plugin33 = {
10698
10775
  if (output_path) {
10699
10776
  const pathError = validateRelativeTemplatePath("output_path", output_path);
10700
10777
  if (pathError) return { ok: false, error: pathError };
10701
- const { writeFileSync: writeFileSync8 } = await import('fs');
10778
+ const { writeFileSync: writeFileSync8 } = await import("node:fs");
10702
10779
  writeFileSync8(output_path, result, "utf-8");
10703
10780
  return {
10704
10781
  ok: true,
@@ -10752,8 +10829,8 @@ var plugin33 = {
10752
10829
  }
10753
10830
  let content;
10754
10831
  try {
10755
- const { readFileSync: readFileSync24 } = await import('fs');
10756
- content = readFileSync24(template_path, "utf-8");
10832
+ const { readFileSync: readFileSync25 } = await import("node:fs");
10833
+ content = readFileSync25(template_path, "utf-8");
10757
10834
  } catch (err) {
10758
10835
  return { ok: false, error: `Could not read template file: ${err}` };
10759
10836
  }
@@ -10766,7 +10843,7 @@ var plugin33 = {
10766
10843
  if (output_path) {
10767
10844
  const pathError = validateRelativeTemplatePath("output_path", output_path);
10768
10845
  if (pathError) return { ok: false, error: pathError };
10769
- const { writeFileSync: writeFileSync8 } = await import('fs');
10846
+ const { writeFileSync: writeFileSync8 } = await import("node:fs");
10770
10847
  writeFileSync8(output_path, result, "utf-8");
10771
10848
  return {
10772
10849
  ok: true,
@@ -10884,6 +10961,10 @@ var plugin33 = {
10884
10961
  }
10885
10962
  };
10886
10963
  var template_engine_default = plugin33;
10964
+
10965
+ // src/test-coverage-gate/index.ts
10966
+ import { readFileSync as readFileSync7 } from "node:fs";
10967
+ import { isAbsolute as isAbsolute14, relative as relative13, resolve as resolve13 } from "node:path";
10887
10968
  var API_VERSION17 = "^0.1.10";
10888
10969
  var state31 = {
10889
10970
  invocationCount: 0,
@@ -10919,16 +11000,16 @@ function readConfig27(raw) {
10919
11000
  function withinProject6(p) {
10920
11001
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
10921
11002
  const root = process.cwd();
10922
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
10923
- const rel = relative(root, resolved);
11003
+ const resolved = isAbsolute14(p) ? resolve13(p) : resolve13(root, p);
11004
+ const rel = relative13(root, resolved);
10924
11005
  if (rel === "" || rel === ".") return true;
10925
11006
  if (rel.startsWith("..")) return false;
10926
- if (isAbsolute(rel)) return false;
11007
+ if (isAbsolute14(rel)) return false;
10927
11008
  return true;
10928
11009
  }
10929
11010
  function readCoverageSummary(coveragePath) {
10930
11011
  try {
10931
- const raw = readFileSync(coveragePath, "utf-8");
11012
+ const raw = readFileSync7(coveragePath, "utf-8");
10932
11013
  return JSON.parse(raw);
10933
11014
  } catch {
10934
11015
  return null;
@@ -11141,6 +11222,11 @@ var plugin34 = {
11141
11222
  }
11142
11223
  };
11143
11224
  var test_coverage_gate_default = plugin34;
11225
+
11226
+ // src/test-runner-gate/index.ts
11227
+ import { execFileSync as execFileSync7, execSync as execSync3 } from "node:child_process";
11228
+ import { existsSync as existsSync6 } from "node:fs";
11229
+ import { basename as basename2, dirname as dirname5, isAbsolute as isAbsolute15, join as join4, relative as relative14, resolve as resolve14 } from "node:path";
11144
11230
  var API_VERSION18 = "^0.1.10";
11145
11231
  var state32 = {
11146
11232
  invocationCount: 0,
@@ -11209,11 +11295,11 @@ var lastPassedHash = /* @__PURE__ */ new Map();
11209
11295
  function withinProject7(p) {
11210
11296
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
11211
11297
  const root = process.cwd();
11212
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
11213
- const rel = relative(root, resolved);
11298
+ const resolved = isAbsolute15(p) ? resolve14(p) : resolve14(root, p);
11299
+ const rel = relative14(root, resolved);
11214
11300
  if (rel === "" || rel === ".") return true;
11215
11301
  if (rel.startsWith("..")) return false;
11216
- if (isAbsolute(rel)) return false;
11302
+ if (isAbsolute15(rel)) return false;
11217
11303
  return true;
11218
11304
  }
11219
11305
  var ALLOWED_COMMAND_TOKENS = /* @__PURE__ */ new Set([
@@ -11231,9 +11317,9 @@ var ALLOWED_COMMAND_TOKENS = /* @__PURE__ */ new Set([
11231
11317
  // by basename in resolveAllowedCommand().
11232
11318
  ]);
11233
11319
  function resolveTestFiles(sourcePath, patterns) {
11234
- const name = basename(sourcePath).replace(/\.[^.]+$/, "");
11320
+ const name = basename2(sourcePath).replace(/\.[^.]+$/, "");
11235
11321
  const pathNoExt = sourcePath.replace(/\.[^.]+$/, "");
11236
- const dir = dirname(sourcePath);
11322
+ const dir = dirname5(sourcePath);
11237
11323
  const candidates = [];
11238
11324
  for (const pattern of patterns) {
11239
11325
  const candidate = pattern.replace(/\{name\}/g, name).replace(/\{path\}/g, pathNoExt).replace(/\{dir\}/g, dir);
@@ -11242,7 +11328,7 @@ function resolveTestFiles(sourcePath, patterns) {
11242
11328
  candidates.push(candidate);
11243
11329
  } else {
11244
11330
  candidates.push(candidate);
11245
- candidates.push(join(dir, candidate));
11331
+ candidates.push(join4(dir, candidate));
11246
11332
  }
11247
11333
  }
11248
11334
  }
@@ -11251,7 +11337,7 @@ function resolveTestFiles(sourcePath, patterns) {
11251
11337
  function findTestFile(sourcePath, patterns) {
11252
11338
  const candidates = resolveTestFiles(sourcePath, patterns);
11253
11339
  for (const candidate of candidates) {
11254
- if (existsSync(candidate)) return candidate;
11340
+ if (existsSync6(candidate)) return candidate;
11255
11341
  }
11256
11342
  return null;
11257
11343
  }
@@ -11265,7 +11351,7 @@ function detectRunner(requested) {
11265
11351
  const match = candidates.find((c) => c.name === requested);
11266
11352
  if (!match) return null;
11267
11353
  try {
11268
- execSync(`npx ${match.name} --version`, {
11354
+ execSync3(`npx ${match.name} --version`, {
11269
11355
  encoding: "utf-8",
11270
11356
  timeout: 5e3,
11271
11357
  cwd: process.cwd(),
@@ -11278,7 +11364,7 @@ function detectRunner(requested) {
11278
11364
  }
11279
11365
  for (const candidate of candidates) {
11280
11366
  try {
11281
- execSync(`npx ${candidate.name} --version`, {
11367
+ execSync3(`npx ${candidate.name} --version`, {
11282
11368
  encoding: "utf-8",
11283
11369
  timeout: 5e3,
11284
11370
  cwd: process.cwd(),
@@ -11297,9 +11383,9 @@ function resolveAllowedCommand2(customCommand) {
11297
11383
  if (ALLOWED_COMMAND_TOKENS.has(head)) {
11298
11384
  return { cmd: head, args: tokens.slice(1) };
11299
11385
  }
11300
- if (isAbsolute(head)) {
11386
+ if (isAbsolute15(head)) {
11301
11387
  if (!withinProject7(head)) return null;
11302
- const base = basename(head);
11388
+ const base = basename2(head);
11303
11389
  if (ALLOWED_COMMAND_TOKENS.has(base)) {
11304
11390
  return { cmd: head, args: tokens.slice(1) };
11305
11391
  }
@@ -11327,7 +11413,7 @@ function runTests(testFile, runner, customCommand, timeoutMs) {
11327
11413
  const fullArgs = [...cmdArgs, ...trailing];
11328
11414
  let stdout = "";
11329
11415
  try {
11330
- stdout = execFileSync(cmd, fullArgs, {
11416
+ stdout = execFileSync7(cmd, fullArgs, {
11331
11417
  encoding: "utf-8",
11332
11418
  timeout: timeoutMs,
11333
11419
  cwd: process.cwd(),
@@ -11622,6 +11708,201 @@ Fix the failing tests or revert the change if it broke something.`
11622
11708
  }
11623
11709
  };
11624
11710
  var test_runner_gate_default = plugin35;
11711
+
11712
+ // src/type-gate/index.ts
11713
+ import { execFileSync as execFileSync8 } from "node:child_process";
11714
+ import { existsSync as existsSync7 } from "node:fs";
11715
+ import { isAbsolute as isAbsolute17, relative as relative16, resolve as resolve16 } from "node:path";
11716
+
11717
+ // src/runtime/index.ts
11718
+ import { execFile as execFile4 } from "node:child_process";
11719
+ import { basename as basename3, isAbsolute as isAbsolute16, relative as relative15, resolve as resolve15 } from "node:path";
11720
+ var META_CHARS = /["'`;&|<>\r\n]/;
11721
+ var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
11722
+ function hasLeadingDash(arg) {
11723
+ return arg.length > 0 && arg.startsWith("-");
11724
+ }
11725
+ function safeSplit(command) {
11726
+ const trimmed = command.trim();
11727
+ if (!trimmed || META_CHARS.test(trimmed)) return null;
11728
+ return trimmed.split(/\s+/).filter(Boolean);
11729
+ }
11730
+ function withinProjectPath(projectRoot, candidate) {
11731
+ if (candidate.length === 0 || candidate.length > 4096) return false;
11732
+ if (hasLeadingDash(candidate)) return false;
11733
+ const resolved = isAbsolute16(candidate) ? resolve15(candidate) : resolve15(projectRoot, candidate);
11734
+ const rel = relative15(projectRoot, resolved);
11735
+ return rel === "" || !rel.startsWith("..") && !isAbsolute16(rel);
11736
+ }
11737
+ function everyFlagAllowed(allowed, args) {
11738
+ for (const arg of args) {
11739
+ if (!hasLeadingDash(arg)) continue;
11740
+ if (allowed === null) return false;
11741
+ if (!allowed.has(arg)) return false;
11742
+ }
11743
+ return true;
11744
+ }
11745
+ function sanitizeRunnerPath(value, options = {}) {
11746
+ if (!value || hasLeadingDash(value)) return null;
11747
+ const projectRoot = resolve15(options.projectRoot ?? process.cwd());
11748
+ if (!withinProjectPath(projectRoot, value)) return null;
11749
+ return isAbsolute16(value) ? resolve15(value) : resolve15(projectRoot, value);
11750
+ }
11751
+ function resolveRunnerCommand(runtime, command, options = {}) {
11752
+ const tokens = safeSplit(command);
11753
+ if (!tokens || tokens.length === 0) return null;
11754
+ const projectRoot = resolve15(options.projectRoot ?? process.cwd());
11755
+ const launcher = runtime.packageManager;
11756
+ const [head, second, ...rest] = tokens;
11757
+ if (!head) return null;
11758
+ const display = tokens.join(" ");
11759
+ if (launcher !== "none" && tokens.length === 1 && head === launcher) {
11760
+ return null;
11761
+ }
11762
+ if (head === runtime.executable) {
11763
+ if (!everyFlagAllowed(runtime.allowedFlags, [second, ...rest].filter((v) => Boolean(v)))) {
11764
+ return null;
11765
+ }
11766
+ return {
11767
+ cmd: head,
11768
+ args: [second, ...rest].filter((v) => Boolean(v)),
11769
+ display
11770
+ };
11771
+ }
11772
+ if (launcher !== "none" && head === launcher && runtime.subcommands.length === 0 && second === runtime.executable) {
11773
+ if (!everyFlagAllowed(runtime.allowedFlags, rest)) return null;
11774
+ return { cmd: head, args: [second, ...rest], display };
11775
+ }
11776
+ if (launcher !== "none" && head === launcher && runtime.subcommands.length > 0) {
11777
+ const subcommand = runtime.subcommands[0];
11778
+ const exe = rest[0];
11779
+ if (second === subcommand && exe === runtime.executable) {
11780
+ const tail = rest.slice(1);
11781
+ if (!everyFlagAllowed(runtime.allowedFlags, tail)) return null;
11782
+ return { cmd: head, args: [second, exe, ...tail], display };
11783
+ }
11784
+ }
11785
+ if (isAbsolute16(head)) {
11786
+ if (!withinProjectPath(projectRoot, head)) return null;
11787
+ const base = basename3(head);
11788
+ if (base !== runtime.executable && base !== launcher) return null;
11789
+ if (second !== runtime.executable) return null;
11790
+ if (!everyFlagAllowed(runtime.allowedFlags, rest)) return null;
11791
+ return { cmd: head, args: [second, ...rest], display };
11792
+ }
11793
+ return null;
11794
+ }
11795
+ function runRunnerCommand(argv, options) {
11796
+ if (argv.length === 0) {
11797
+ return Promise.resolve({
11798
+ code: null,
11799
+ stdout: "",
11800
+ stderr: "runtime helper: empty argv",
11801
+ timedOut: false,
11802
+ spawnError: true
11803
+ });
11804
+ }
11805
+ return new Promise((resolvePromise) => {
11806
+ const projectRoot = resolve15(options.projectRoot ?? process.cwd());
11807
+ const trimmedCwd = options.cwd.trim();
11808
+ if (!withinProjectPath(projectRoot, trimmedCwd)) {
11809
+ resolvePromise({
11810
+ code: null,
11811
+ stdout: "",
11812
+ stderr: "runtime helper: cwd outside project",
11813
+ timedOut: false,
11814
+ spawnError: true
11815
+ });
11816
+ return;
11817
+ }
11818
+ const timedOut = false;
11819
+ let spawnErrored = false;
11820
+ const stdoutChunks = [];
11821
+ const stderrChunks = [];
11822
+ let stdoutBytes = 0;
11823
+ let stderrBytes = 0;
11824
+ const child = execFile4(
11825
+ argv[0],
11826
+ argv.slice(1),
11827
+ {
11828
+ cwd: trimmedCwd,
11829
+ timeout: options.timeoutMs,
11830
+ signal: options.signal,
11831
+ maxBuffer: MAX_BUFFER_BYTES,
11832
+ windowsHide: true,
11833
+ shell: false
11834
+ },
11835
+ (err, stdout, stderr) => {
11836
+ if (timedOut) {
11837
+ resolvePromise({
11838
+ code: null,
11839
+ stdout: Buffer.concat([...stdoutChunks, ...Buffer.isBuffer(stdout) ? [stdout] : [Buffer.from(stdout)]]).toString("utf8"),
11840
+ stderr: Buffer.concat([...stderrChunks, ...Buffer.isBuffer(stderr) ? [stderr] : [Buffer.from(stderr)]]).toString("utf8"),
11841
+ timedOut: true,
11842
+ spawnError: false
11843
+ });
11844
+ return;
11845
+ }
11846
+ if (spawnErrored) {
11847
+ resolvePromise({
11848
+ code: 127,
11849
+ stdout: Buffer.concat([...stdoutChunks, ...Buffer.isBuffer(stdout) ? [stdout] : [Buffer.from(stdout)]]).toString("utf8"),
11850
+ stderr: Buffer.concat([...stderrChunks, ...Buffer.isBuffer(stderr) ? [stderr] : [Buffer.from(stderr)]]).toString("utf8"),
11851
+ timedOut: false,
11852
+ spawnError: true
11853
+ });
11854
+ return;
11855
+ }
11856
+ if (err) {
11857
+ const anyErr = err;
11858
+ const code = typeof anyErr.code === "number" ? anyErr.code : 1;
11859
+ resolvePromise({
11860
+ code,
11861
+ stdout: Buffer.concat([
11862
+ ...stdoutChunks,
11863
+ ...anyErr.stdout ? [Buffer.isBuffer(anyErr.stdout) ? anyErr.stdout : Buffer.from(anyErr.stdout)] : []
11864
+ ]).toString("utf8"),
11865
+ stderr: Buffer.concat([
11866
+ ...stderrChunks,
11867
+ ...anyErr.stderr ? [Buffer.isBuffer(anyErr.stderr) ? anyErr.stderr : Buffer.from(anyErr.stderr)] : []
11868
+ ]).toString("utf8"),
11869
+ timedOut: false,
11870
+ spawnError: false
11871
+ });
11872
+ return;
11873
+ }
11874
+ resolvePromise({
11875
+ code: 0,
11876
+ stdout: Buffer.concat([
11877
+ ...stdoutChunks,
11878
+ ...Buffer.isBuffer(stdout) ? [stdout] : [Buffer.from(stdout)]
11879
+ ]).toString("utf8"),
11880
+ stderr: Buffer.concat([
11881
+ ...stderrChunks,
11882
+ ...Buffer.isBuffer(stderr) ? [stderr] : [Buffer.from(stderr)]
11883
+ ]).toString("utf8"),
11884
+ timedOut: false,
11885
+ spawnError: false
11886
+ });
11887
+ }
11888
+ );
11889
+ child.stdout?.on("data", (chunk) => {
11890
+ stdoutBytes += chunk.length;
11891
+ if (stdoutBytes <= MAX_BUFFER_BYTES) stdoutChunks.push(chunk);
11892
+ });
11893
+ child.stderr?.on("data", (chunk) => {
11894
+ stderrBytes += chunk.length;
11895
+ if (stderrBytes <= MAX_BUFFER_BYTES) stderrChunks.push(chunk);
11896
+ });
11897
+ child.on("error", (err) => {
11898
+ if (err.code === "ENOENT" || err.code === "EPERM" || err.code === "EACCES") {
11899
+ spawnErrored = true;
11900
+ }
11901
+ });
11902
+ });
11903
+ }
11904
+
11905
+ // src/type-gate/index.ts
11625
11906
  var API_VERSION19 = "^0.1.10";
11626
11907
  var state33 = {
11627
11908
  invocationCount: 0,
@@ -11658,63 +11939,59 @@ function readConfig29(raw) {
11658
11939
  function withinProject8(p) {
11659
11940
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
11660
11941
  const root = process.cwd();
11661
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
11662
- const rel = relative(root, resolved);
11942
+ const resolved = isAbsolute17(p) ? resolve16(p) : resolve16(root, p);
11943
+ const rel = relative16(root, resolved);
11663
11944
  if (rel === "" || rel === ".") return true;
11664
11945
  if (rel.startsWith("..")) return false;
11665
- if (isAbsolute(rel)) return false;
11946
+ if (isAbsolute17(rel)) return false;
11666
11947
  return true;
11667
11948
  }
11668
- var ALLOWED_COMMAND_TOKENS2 = /* @__PURE__ */ new Set([
11669
- "npx",
11670
- "pnpm",
11671
- "npm",
11672
- "yarn",
11673
- "bun",
11674
- "tsc",
11675
- "node",
11676
- "tsx"
11677
- ]);
11678
- function resolveAllowedCommand3(customCommand) {
11679
- const tokens = customCommand.split(/\s+/).filter(Boolean);
11680
- if (tokens.length === 0) return null;
11681
- const head = tokens[0];
11682
- if (ALLOWED_COMMAND_TOKENS2.has(head)) {
11683
- return { cmd: head, args: tokens.slice(1) };
11684
- }
11685
- if (isAbsolute(head)) {
11686
- if (!withinProject8(head)) return null;
11687
- const base = head.split(/[/\\]/).pop() ?? "";
11688
- if (ALLOWED_COMMAND_TOKENS2.has(base)) {
11689
- return { cmd: head, args: tokens.slice(1) };
11690
- }
11691
- }
11692
- return null;
11949
+ var TSC_RUNTIME = {
11950
+ id: "typescript",
11951
+ packageManager: "pnpm",
11952
+ executable: "tsc",
11953
+ allowedFlags: /* @__PURE__ */ new Set([
11954
+ "--noEmit",
11955
+ "--pretty",
11956
+ "--pretty=false",
11957
+ "--incremental",
11958
+ "--watch",
11959
+ "--build",
11960
+ "--filter"
11961
+ ]),
11962
+ subcommands: ["exec"],
11963
+ defaultCommand: "pnpm exec tsc --noEmit"
11964
+ };
11965
+ function validateTsConfigPath(p) {
11966
+ const sanitized = sanitizeRunnerPath(p);
11967
+ return sanitized;
11693
11968
  }
11694
11969
  function runTypeCheck(cfg) {
11695
11970
  const start = Date.now();
11696
- const tsConfig = cfg.tsConfigPath;
11697
- let cmd;
11698
- let args;
11971
+ const rawTsConfig = cfg.tsConfigPath;
11972
+ const validTsConfig = rawTsConfig && rawTsConfig !== "tsconfig.json" ? validateTsConfigPath(rawTsConfig) : null;
11973
+ if (rawTsConfig && rawTsConfig !== "tsconfig.json" && !validTsConfig) {
11974
+ return null;
11975
+ }
11976
+ const tsConfig = validTsConfig ?? (rawTsConfig || "tsconfig.json");
11977
+ let argv;
11699
11978
  if (cfg.command) {
11700
- const resolved = resolveAllowedCommand3(cfg.command);
11979
+ const resolved = resolveRunnerCommand(TSC_RUNTIME, cfg.command);
11701
11980
  if (!resolved) return null;
11702
- cmd = resolved.cmd;
11703
- args = resolved.args;
11981
+ argv = [resolved.cmd, ...resolved.args];
11704
11982
  } else {
11705
- cmd = "npx";
11706
- args = ["tsc", "--noEmit"];
11983
+ argv = ["npx", "tsc", "--noEmit"];
11707
11984
  if (tsConfig && tsConfig !== "tsconfig.json") {
11708
- args.push("-p", tsConfig);
11985
+ argv = [...argv, "-p", tsConfig];
11709
11986
  }
11710
11987
  }
11711
- if (!cfg.command && tsConfig && !existsSync(tsConfig)) {
11988
+ if (!cfg.command && tsConfig && !existsSync7(tsConfig)) {
11712
11989
  return null;
11713
11990
  }
11714
11991
  let stdout = "";
11715
11992
  let stderr = "";
11716
11993
  try {
11717
- const out = execFileSync(cmd, args, {
11994
+ const out = execFileSync8(argv[0], argv.slice(1), {
11718
11995
  encoding: "utf-8",
11719
11996
  timeout: cfg.timeoutMs,
11720
11997
  cwd: process.cwd(),
@@ -11728,6 +12005,7 @@ function runTypeCheck(cfg) {
11728
12005
  stdout = e.stdout ?? "";
11729
12006
  stderr = e.stderr ?? "";
11730
12007
  }
12008
+ void runRunnerCommand;
11731
12009
  const combined = `${stdout}
11732
12010
  ${stderr}`.trim();
11733
12011
  const durationMs = Date.now() - start;
@@ -11745,6 +12023,12 @@ ${stderr}`.trim();
11745
12023
  var plugin36 = {
11746
12024
  name: "type-gate",
11747
12025
  version: "0.1.0",
12026
+ runtime: {
12027
+ language: "typescript",
12028
+ packageManager: "pnpm",
12029
+ executable: "tsc",
12030
+ defaultCommand: "pnpm exec tsc --noEmit"
12031
+ },
11748
12032
  description: "PostToolUse hook that runs TypeScript type-checking after every write or edit to a source file",
11749
12033
  apiVersion: API_VERSION19,
11750
12034
  capabilities: { tools: true, hooks: true },
@@ -12141,6 +12425,10 @@ var plugin37 = {
12141
12425
  }
12142
12426
  };
12143
12427
  var todo_listener_default = plugin37;
12428
+
12429
+ // src/todo-tracker/index.ts
12430
+ import * as fsp from "node:fs/promises";
12431
+ import { randomUUID } from "node:crypto";
12144
12432
  function deriveFilePath(api) {
12145
12433
  const raw = api.config.extensions?.["todo-tracker"];
12146
12434
  const explicit = typeof raw?.["filePath"] === "string" ? raw["filePath"] : null;
@@ -12892,7 +13180,7 @@ function estimateRequestTokens(request, charsPerToken) {
12892
13180
  walk(request["messages"]);
12893
13181
  return Math.ceil(chars / charsPerToken);
12894
13182
  }
12895
- var sleep = (ms) => new Promise((resolve34) => setTimeout(resolve34, ms));
13183
+ var sleep = (ms) => new Promise((resolve36) => setTimeout(resolve36, ms));
12896
13184
  var plugin40 = {
12897
13185
  name: "token-throttle",
12898
13186
  version: "0.1.0",
@@ -13036,6 +13324,10 @@ var plugin40 = {
13036
13324
  }
13037
13325
  };
13038
13326
  var token_throttle_default = plugin40;
13327
+
13328
+ // src/accessibility-auditor/index.ts
13329
+ import { existsSync as existsSync8, readFileSync as readFileSync8, readdirSync as readdirSync3, statSync as statSync5 } from "node:fs";
13330
+ import { isAbsolute as isAbsolute18, relative as relative17, resolve as resolve17 } from "node:path";
13039
13331
  var API_VERSION21 = "^0.1.10";
13040
13332
  var state38 = {
13041
13333
  auditCount: 0,
@@ -13066,11 +13358,11 @@ function readConfig33(raw) {
13066
13358
  function withinProject9(p) {
13067
13359
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
13068
13360
  const root = process.cwd();
13069
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
13070
- const rel = relative(root, resolved);
13361
+ const resolved = isAbsolute18(p) ? resolve17(p) : resolve17(root, p);
13362
+ const rel = relative17(root, resolved);
13071
13363
  if (rel === "" || rel === ".") return true;
13072
13364
  if (rel.startsWith("..")) return false;
13073
- if (isAbsolute(rel)) return false;
13365
+ if (isAbsolute18(rel)) return false;
13074
13366
  return true;
13075
13367
  }
13076
13368
  function normalizeExtensions(exts) {
@@ -13083,8 +13375,8 @@ function matchesExtension(p, exts) {
13083
13375
  }
13084
13376
  function collectUiFiles(root, exts) {
13085
13377
  const files = [];
13086
- if (!existsSync(root)) return files;
13087
- const s = statSync(root);
13378
+ if (!existsSync8(root)) return files;
13379
+ const s = statSync5(root);
13088
13380
  if (s.isFile()) {
13089
13381
  if (matchesExtension(root, exts)) files.push(root);
13090
13382
  return files;
@@ -13093,15 +13385,15 @@ function collectUiFiles(root, exts) {
13093
13385
  function walk(dir) {
13094
13386
  let entries;
13095
13387
  try {
13096
- entries = readdirSync(dir);
13388
+ entries = readdirSync3(dir);
13097
13389
  } catch {
13098
13390
  return;
13099
13391
  }
13100
13392
  for (const entry of entries) {
13101
- const full = resolve(dir, entry);
13393
+ const full = resolve17(dir, entry);
13102
13394
  let st;
13103
13395
  try {
13104
- st = statSync(full);
13396
+ st = statSync5(full);
13105
13397
  } catch {
13106
13398
  continue;
13107
13399
  }
@@ -13135,7 +13427,7 @@ function hasMeaningfulAlt(tag) {
13135
13427
  function auditFile(filePath, projectRoot) {
13136
13428
  let content;
13137
13429
  try {
13138
- content = readFileSync(filePath, "utf-8");
13430
+ content = readFileSync8(filePath, "utf-8");
13139
13431
  } catch {
13140
13432
  return [];
13141
13433
  }
@@ -13144,7 +13436,7 @@ function auditFile(filePath, projectRoot) {
13144
13436
  const idsByValue = /* @__PURE__ */ new Map();
13145
13437
  function add(line, rule, severity, message) {
13146
13438
  findings.push({
13147
- file: relative(projectRoot, filePath),
13439
+ file: relative17(projectRoot, filePath),
13148
13440
  line,
13149
13441
  rule,
13150
13442
  severity,
@@ -13154,24 +13446,21 @@ function auditFile(filePath, projectRoot) {
13154
13446
  for (let i = 0; i < lines.length; i++) {
13155
13447
  const line = lines[i];
13156
13448
  const lineNo = i + 1;
13157
- let idMatch;
13158
- while ((idMatch = ATTR_ID.exec(line)) !== null) {
13449
+ for (const idMatch of line.matchAll(ATTR_ID)) {
13159
13450
  const id = idMatch[1];
13160
13451
  const list = idsByValue.get(id) ?? [];
13161
13452
  list.push(lineNo);
13162
13453
  idsByValue.set(id, list);
13163
13454
  }
13164
13455
  ATTR_ID.lastIndex = 0;
13165
- let imgMatch;
13166
- while ((imgMatch = TAG_IMG.exec(line)) !== null) {
13456
+ for (const imgMatch of line.matchAll(TAG_IMG)) {
13167
13457
  const tag = imgMatch[0];
13168
13458
  if (!hasMeaningfulAlt(tag)) {
13169
13459
  add(lineNo, "missing-alt", "error", "<img> is missing meaningful alt text");
13170
13460
  }
13171
13461
  }
13172
13462
  TAG_IMG.lastIndex = 0;
13173
- let inputMatch;
13174
- while ((inputMatch = TAG_INPUT.exec(line)) !== null) {
13463
+ for (const inputMatch of line.matchAll(TAG_INPUT)) {
13175
13464
  const tag = inputMatch[0];
13176
13465
  const typeMatch = tag.match(/\btype\s*=\s*["']?([^"'\s>]*)["']?/i);
13177
13466
  const type = typeMatch ? typeMatch[1].toLowerCase() : "text";
@@ -13196,8 +13485,7 @@ function auditFile(filePath, projectRoot) {
13196
13485
  }
13197
13486
  }
13198
13487
  TAG_INPUT.lastIndex = 0;
13199
- let buttonMatch;
13200
- while ((buttonMatch = TAG_BUTTON.exec(line)) !== null) {
13488
+ for (const buttonMatch of line.matchAll(TAG_BUTTON)) {
13201
13489
  const tag = buttonMatch[0];
13202
13490
  const inner = buttonMatch[1] ?? "";
13203
13491
  const hasText = inner.replace(/\s+/g, "").length > 0;
@@ -13208,8 +13496,7 @@ function auditFile(filePath, projectRoot) {
13208
13496
  }
13209
13497
  }
13210
13498
  TAG_BUTTON.lastIndex = 0;
13211
- let inputButtonMatch;
13212
- while ((inputButtonMatch = INPUT_BUTTON.exec(line)) !== null) {
13499
+ for (const inputButtonMatch of line.matchAll(INPUT_BUTTON)) {
13213
13500
  const tag = inputButtonMatch[0];
13214
13501
  if (!ATTR_VALUE.test(tag) && !ATTR_ARIA_LABEL.test(tag) && !ATTR_TITLE.test(tag)) {
13215
13502
  add(lineNo, "missing-button-text", "error", `<input type="${inputButtonMatch[1]}"> is missing value/aria-label/title`);
@@ -13228,7 +13515,7 @@ function auditFile(filePath, projectRoot) {
13228
13515
  }
13229
13516
  function auditPath(rawPath, cfg) {
13230
13517
  const root = process.cwd();
13231
- const resolved = isAbsolute(rawPath) ? resolve(rawPath) : resolve(root, rawPath);
13518
+ const resolved = isAbsolute18(rawPath) ? resolve17(rawPath) : resolve17(root, rawPath);
13232
13519
  const exts = normalizeExtensions(cfg.includeExtensions);
13233
13520
  const files = collectUiFiles(resolved, exts);
13234
13521
  const findings = [];
@@ -13238,7 +13525,7 @@ function auditPath(rawPath, cfg) {
13238
13525
  if (findings.length >= cfg.maxFindings) break;
13239
13526
  }
13240
13527
  return {
13241
- path: relative(root, resolved),
13528
+ path: relative17(root, resolved),
13242
13529
  findings: findings.slice(0, cfg.maxFindings),
13243
13530
  fileCount: files.length
13244
13531
  };
@@ -13441,6 +13728,11 @@ var plugin41 = {
13441
13728
  }
13442
13729
  };
13443
13730
  var accessibility_auditor_default = plugin41;
13731
+
13732
+ // src/api-compatibility-gate/index.ts
13733
+ import { execFileSync as execFileSync9 } from "node:child_process";
13734
+ import { existsSync as existsSync9, readFileSync as readFileSync9 } from "node:fs";
13735
+ import { basename as basename4, dirname as dirname6, extname, isAbsolute as isAbsolute19, relative as relative18, resolve as resolve18 } from "node:path";
13444
13736
  var API_VERSION22 = "^0.1.10";
13445
13737
  var state39 = {
13446
13738
  invocationCount: 0,
@@ -13504,25 +13796,25 @@ function matchesAnyPattern(filePath, patterns) {
13504
13796
  return patterns.some((p) => patternToRegex(p).test(normalized));
13505
13797
  }
13506
13798
  function resolveToProjectRoot(filePath) {
13507
- if (isAbsolute(filePath)) return resolve(filePath);
13508
- return resolve(process.cwd(), filePath);
13799
+ if (isAbsolute19(filePath)) return resolve18(filePath);
13800
+ return resolve18(process.cwd(), filePath);
13509
13801
  }
13510
13802
  function withinProject10(filePath) {
13511
13803
  if (typeof filePath !== "string" || filePath.length === 0 || filePath.length > 4096) return false;
13512
13804
  const resolved = resolveToProjectRoot(filePath);
13513
- const rel = relative(process.cwd(), resolved);
13805
+ const rel = relative18(process.cwd(), resolved);
13514
13806
  if (rel === "" || rel === ".") return true;
13515
13807
  if (rel.startsWith("..")) return false;
13516
- if (isAbsolute(rel)) return false;
13808
+ if (isAbsolute19(rel)) return false;
13517
13809
  return true;
13518
13810
  }
13519
13811
  function isPackageEntryPoint(filePath) {
13520
13812
  const resolved = resolveToProjectRoot(filePath);
13521
- const dir = dirname(resolved);
13522
- const pkgPath = resolve(dir, "package.json");
13523
- if (!existsSync(pkgPath)) return false;
13813
+ const dir = dirname6(resolved);
13814
+ const pkgPath = resolve18(dir, "package.json");
13815
+ if (!existsSync9(pkgPath)) return false;
13524
13816
  try {
13525
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
13817
+ const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
13526
13818
  const entries = [];
13527
13819
  if (pkg.main) entries.push(pkg.main);
13528
13820
  if (pkg.module) entries.push(pkg.module);
@@ -13540,9 +13832,9 @@ function isPackageEntryPoint(filePath) {
13540
13832
  }
13541
13833
  }
13542
13834
  for (const entry of entries) {
13543
- const entryResolved = resolve(dir, entry);
13835
+ const entryResolved = resolve18(dir, entry);
13544
13836
  if (entryResolved === resolved) return true;
13545
- if (basename(dirname(entryResolved)) === basename(dirname(resolved)) && basename(entryResolved, extname(entryResolved)) === basename(resolved, extname(resolved))) {
13837
+ if (basename4(dirname6(entryResolved)) === basename4(dirname6(resolved)) && basename4(entryResolved, extname(entryResolved)) === basename4(resolved, extname(resolved))) {
13546
13838
  return true;
13547
13839
  }
13548
13840
  }
@@ -13593,9 +13885,9 @@ function extractExports(source) {
13593
13885
  }
13594
13886
  function readGitVersion(filePath) {
13595
13887
  const resolved = resolveToProjectRoot(filePath);
13596
- const relPath = normalizePath2(relative(process.cwd(), resolved));
13888
+ const relPath = normalizePath2(relative18(process.cwd(), resolved));
13597
13889
  try {
13598
- const out = execFileSync("git", ["show", `HEAD:${relPath}`], {
13890
+ const out = execFileSync9("git", ["show", `HEAD:${relPath}`], {
13599
13891
  encoding: "utf-8",
13600
13892
  cwd: process.cwd(),
13601
13893
  stdio: ["pipe", "pipe", "pipe"]
@@ -13608,7 +13900,7 @@ function readGitVersion(filePath) {
13608
13900
  function readCurrentFile(filePath) {
13609
13901
  try {
13610
13902
  const resolved = resolveToProjectRoot(filePath);
13611
- return readFileSync(resolved, "utf-8");
13903
+ return readFileSync9(resolved, "utf-8");
13612
13904
  } catch {
13613
13905
  return null;
13614
13906
  }
@@ -13791,6 +14083,10 @@ var plugin42 = {
13791
14083
  }
13792
14084
  };
13793
14085
  var api_compatibility_gate_default = plugin42;
14086
+
14087
+ // src/auto-i18n-extractor/index.ts
14088
+ import { readFileSync as readFileSync10 } from "node:fs";
14089
+ import { isAbsolute as isAbsolute20, relative as relative19, resolve as resolve19 } from "node:path";
13794
14090
  var API_VERSION23 = "^0.1.10";
13795
14091
  var state40 = {
13796
14092
  filesScanned: 0,
@@ -13834,11 +14130,11 @@ function readConfig35(raw) {
13834
14130
  function withinProject11(p) {
13835
14131
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
13836
14132
  const root = process.cwd();
13837
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
13838
- const rel = relative(root, resolved);
14133
+ const resolved = isAbsolute20(p) ? resolve19(p) : resolve19(root, p);
14134
+ const rel = relative19(root, resolved);
13839
14135
  if (rel === "" || rel === ".") return true;
13840
14136
  if (rel.startsWith("..")) return false;
13841
- if (isAbsolute(rel)) return false;
14137
+ if (isAbsolute20(rel)) return false;
13842
14138
  return true;
13843
14139
  }
13844
14140
  function fileExtension(p) {
@@ -13873,8 +14169,7 @@ function extractStrings(content, cfg) {
13873
14169
  for (let i = 0; i < lines.length; i += 1) {
13874
14170
  const line = lines[i];
13875
14171
  stringRegex.lastIndex = 0;
13876
- let match;
13877
- while ((match = stringRegex.exec(line)) !== null) {
14172
+ for (const match of line.matchAll(stringRegex)) {
13878
14173
  const value = match[2] ?? "";
13879
14174
  const quoteIndex = match.index + (match[1]?.length ?? 1);
13880
14175
  if (!looksLikeUserText(value, cfg.minLength)) continue;
@@ -13886,7 +14181,7 @@ function extractStrings(content, cfg) {
13886
14181
  }
13887
14182
  function readSourceFile(filePath) {
13888
14183
  try {
13889
- return readFileSync(filePath, "utf-8");
14184
+ return readFileSync10(filePath, "utf-8");
13890
14185
  } catch {
13891
14186
  return null;
13892
14187
  }
@@ -14120,6 +14415,10 @@ ${lines.join("\n")}${more}`;
14120
14415
  }
14121
14416
  };
14122
14417
  var auto_i18n_extractor_default = plugin43;
14418
+
14419
+ // src/code-metrics/index.ts
14420
+ import { existsSync as existsSync10, readFileSync as readFileSync11, readdirSync as readdirSync4, statSync as statSync6 } from "node:fs";
14421
+ import { extname as extname2, isAbsolute as isAbsolute21, relative as relative20, resolve as resolve20 } from "node:path";
14123
14422
  var API_VERSION24 = "^0.1.10";
14124
14423
  var state41 = {
14125
14424
  measureCount: 0,
@@ -14145,23 +14444,23 @@ function readConfig36(raw) {
14145
14444
  function withinProject12(p) {
14146
14445
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
14147
14446
  const root = process.cwd();
14148
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
14149
- const rel = relative(root, resolved);
14447
+ const resolved = isAbsolute21(p) ? resolve20(p) : resolve20(root, p);
14448
+ const rel = relative20(root, resolved);
14150
14449
  if (rel === "" || rel === ".") return true;
14151
14450
  if (rel.startsWith("..")) return false;
14152
- if (isAbsolute(rel)) return false;
14451
+ if (isAbsolute21(rel)) return false;
14153
14452
  return true;
14154
14453
  }
14155
14454
  function normalizeExtensions2(exts) {
14156
14455
  return exts.map((e) => e.startsWith(".") ? e.toLowerCase() : `.${e.toLowerCase()}`);
14157
14456
  }
14158
14457
  function matchesExtension2(p, exts) {
14159
- return exts.includes(extname(p).toLowerCase());
14458
+ return exts.includes(extname2(p).toLowerCase());
14160
14459
  }
14161
14460
  function collectSourceFiles(root, exts) {
14162
14461
  const files = [];
14163
- if (!existsSync(root)) return files;
14164
- const s = statSync(root);
14462
+ if (!existsSync10(root)) return files;
14463
+ const s = statSync6(root);
14165
14464
  if (s.isFile()) {
14166
14465
  if (matchesExtension2(root, exts)) files.push(root);
14167
14466
  return files;
@@ -14170,16 +14469,16 @@ function collectSourceFiles(root, exts) {
14170
14469
  function walk(dir) {
14171
14470
  let entries;
14172
14471
  try {
14173
- entries = readdirSync(dir);
14472
+ entries = readdirSync4(dir);
14174
14473
  } catch {
14175
14474
  return;
14176
14475
  }
14177
14476
  for (const entry of entries) {
14178
14477
  if (entry === "node_modules" || entry === "dist" || entry === ".git" || entry === "coverage") continue;
14179
- const full = resolve(dir, entry);
14478
+ const full = resolve20(dir, entry);
14180
14479
  let st;
14181
14480
  try {
14182
- st = statSync(full);
14481
+ st = statSync6(full);
14183
14482
  } catch {
14184
14483
  continue;
14185
14484
  }
@@ -14197,40 +14496,38 @@ function toPosix(p) {
14197
14496
  return p.replace(/\\/g, "/");
14198
14497
  }
14199
14498
  function relativePath(p) {
14200
- return toPosix(relative(process.cwd(), p));
14499
+ return toPosix(relative20(process.cwd(), p));
14201
14500
  }
14202
14501
  function countFunctions(content) {
14203
14502
  let count = 0;
14204
14503
  const declRe = /\bfunction\s+[A-Za-z_$][A-Za-z0-9_$]*\s*\(/g;
14205
14504
  const methodRe = /\b[A-Za-z_$][A-Za-z0-9_$]*\s*\([^)]*\)\s*\{/g;
14206
14505
  const arrowRe = /=>\s*(?:\{|\(|[^\s;{}])/g;
14207
- let m;
14208
14506
  declRe.lastIndex = 0;
14209
- while ((m = declRe.exec(content)) !== null) count++;
14507
+ for (const _match of content.matchAll(declRe)) count++;
14210
14508
  methodRe.lastIndex = 0;
14211
- while ((m = methodRe.exec(content)) !== null) {
14212
- const prefix = content.slice(0, m.index).trimEnd();
14509
+ for (const match of content.matchAll(methodRe)) {
14510
+ const prefix = content.slice(0, match.index).trimEnd();
14213
14511
  if (/\bfunction\s*$/.test(prefix)) continue;
14214
14512
  count++;
14215
14513
  }
14216
14514
  arrowRe.lastIndex = 0;
14217
- while ((m = arrowRe.exec(content)) !== null) count++;
14515
+ for (const _match of content.matchAll(arrowRe)) count++;
14218
14516
  return count;
14219
14517
  }
14220
14518
  function countComplexity(content) {
14221
14519
  const controlRe = /\b(if|else\s+if|for|while|switch|catch)\b/g;
14222
14520
  const operatorRe = /[?&|]/g;
14223
14521
  let complexity = 0;
14224
- let m;
14225
14522
  controlRe.lastIndex = 0;
14226
- while ((m = controlRe.exec(content)) !== null) complexity++;
14523
+ for (const _match of content.matchAll(controlRe)) complexity++;
14227
14524
  operatorRe.lastIndex = 0;
14228
- while ((m = operatorRe.exec(content)) !== null) {
14229
- const ch = m[0];
14525
+ for (const match of content.matchAll(operatorRe)) {
14526
+ const ch = match[0];
14230
14527
  if (ch === "?") {
14231
14528
  complexity++;
14232
14529
  } else {
14233
- const next = content[m.index + 1];
14530
+ const next = content[match.index + 1];
14234
14531
  if (next === ch) complexity++;
14235
14532
  }
14236
14533
  }
@@ -14276,14 +14573,14 @@ function analyzeFile(filePath, content) {
14276
14573
  }
14277
14574
  function measurePath(rawPath, cfg) {
14278
14575
  const root = process.cwd();
14279
- const resolved = isAbsolute(rawPath) ? resolve(rawPath) : resolve(root, rawPath);
14576
+ const resolved = isAbsolute21(rawPath) ? resolve20(rawPath) : resolve20(root, rawPath);
14280
14577
  const exts = normalizeExtensions2(cfg.extensions);
14281
14578
  const allFiles = collectSourceFiles(resolved, exts);
14282
14579
  const files = allFiles.slice(0, cfg.maxFiles);
14283
14580
  const metrics = [];
14284
14581
  for (const p of files) {
14285
14582
  try {
14286
- const content = readFileSync(p, "utf-8");
14583
+ const content = readFileSync11(p, "utf-8");
14287
14584
  metrics.push(analyzeFile(p, content));
14288
14585
  } catch {
14289
14586
  }
@@ -14339,10 +14636,10 @@ var plugin44 = {
14339
14636
  const exts = normalizeExtensions2(cfg.extensions);
14340
14637
  if (!matchesExtension2(sourcePath, exts)) return;
14341
14638
  state41.hookInvocationCount += 1;
14342
- const resolved = resolve(process.cwd(), sourcePath);
14639
+ const resolved = resolve20(process.cwd(), sourcePath);
14343
14640
  let content;
14344
14641
  try {
14345
- content = readFileSync(resolved, "utf-8");
14642
+ content = readFileSync11(resolved, "utf-8");
14346
14643
  } catch {
14347
14644
  state41.errorCount += 1;
14348
14645
  return;
@@ -14383,7 +14680,7 @@ var plugin44 = {
14383
14680
  state41.fileCount += result.files.length;
14384
14681
  return {
14385
14682
  ok: true,
14386
- path: relativePath(resolve(process.cwd(), rawPath)),
14683
+ path: relativePath(resolve20(process.cwd(), rawPath)),
14387
14684
  files: result.files,
14388
14685
  totalFiles: result.totalFiles,
14389
14686
  capped: result.totalFiles > cfg.maxFiles
@@ -14452,6 +14749,10 @@ var plugin44 = {
14452
14749
  }
14453
14750
  };
14454
14751
  var code_metrics_default = plugin44;
14752
+
14753
+ // src/dead-code-detector/index.ts
14754
+ import { readdirSync as readdirSync5, readFileSync as readFileSync12, statSync as statSync7 } from "node:fs";
14755
+ import { extname as extname3, isAbsolute as isAbsolute22, join as join5, relative as relative21, resolve as resolve21 } from "node:path";
14455
14756
  var API_VERSION25 = "^0.1.10";
14456
14757
  var state42 = {
14457
14758
  scanCount: 0,
@@ -14485,24 +14786,24 @@ function gatherFiles(root, depth, cfg) {
14485
14786
  function walk(dir, remaining) {
14486
14787
  let entries;
14487
14788
  try {
14488
- entries = readdirSync(dir, { withFileTypes: true });
14789
+ entries = readdirSync5(dir, { withFileTypes: true });
14489
14790
  } catch {
14490
14791
  return;
14491
14792
  }
14492
14793
  for (const entry of entries) {
14493
14794
  if (entry.isDirectory()) {
14494
14795
  if (remaining > 0 && !cfg.excludeDirs.includes(entry.name)) {
14495
- walk(join(dir, entry.name), remaining - 1);
14796
+ walk(join5(dir, entry.name), remaining - 1);
14496
14797
  }
14497
14798
  } else if (entry.isFile()) {
14498
- const ext = extname(entry.name).toLowerCase();
14799
+ const ext = extname3(entry.name).toLowerCase();
14499
14800
  if (cfg.extensions.includes(ext)) {
14500
- files.push(join(dir, entry.name));
14801
+ files.push(join5(dir, entry.name));
14501
14802
  }
14502
14803
  }
14503
14804
  }
14504
14805
  }
14505
- walk(resolve(root), depth);
14806
+ walk(resolve21(root), depth);
14506
14807
  return files;
14507
14808
  }
14508
14809
  function stripNoise(content) {
@@ -14524,9 +14825,8 @@ var DECLARATION_EXPORT_RE = /export\s+(?:async\s+|abstract\s+)?(?:const|let|var|
14524
14825
  var NAMED_EXPORT_RE = /export\s*\{([^}]+)\}/g;
14525
14826
  function extractExports2(content, filePath) {
14526
14827
  const exports = [];
14527
- let match;
14528
14828
  DECLARATION_EXPORT_RE.lastIndex = 0;
14529
- while ((match = DECLARATION_EXPORT_RE.exec(content)) !== null) {
14829
+ for (const match of content.matchAll(DECLARATION_EXPORT_RE)) {
14530
14830
  exports.push({
14531
14831
  identifier: match[1],
14532
14832
  file: filePath,
@@ -14535,7 +14835,7 @@ function extractExports2(content, filePath) {
14535
14835
  });
14536
14836
  }
14537
14837
  NAMED_EXPORT_RE.lastIndex = 0;
14538
- while ((match = NAMED_EXPORT_RE.exec(content)) !== null) {
14838
+ for (const match of content.matchAll(NAMED_EXPORT_RE)) {
14539
14839
  const line = lineNumber(content, match.index);
14540
14840
  const names = match[1].split(",").map((s) => s.trim()).filter(Boolean);
14541
14841
  for (const name of names) {
@@ -14579,7 +14879,7 @@ function scan(root, depth, cfg) {
14579
14879
  const files = [];
14580
14880
  for (const p of filePaths) {
14581
14881
  try {
14582
- const content = readFileSync(p, "utf-8");
14882
+ const content = readFileSync12(p, "utf-8");
14583
14883
  files.push({ path: p, content, stripped: stripNoise(content) });
14584
14884
  } catch {
14585
14885
  }
@@ -14589,19 +14889,19 @@ function scan(root, depth, cfg) {
14589
14889
  function withinProject13(p) {
14590
14890
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
14591
14891
  const root = process.cwd();
14592
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
14593
- const rel = relative(root, resolved);
14892
+ const resolved = isAbsolute22(p) ? resolve21(p) : resolve21(root, p);
14893
+ const rel = relative21(root, resolved);
14594
14894
  if (rel === "" || rel === ".") return true;
14595
14895
  if (rel.startsWith("..")) return false;
14596
- if (isAbsolute(rel)) return false;
14896
+ if (isAbsolute22(rel)) return false;
14597
14897
  return true;
14598
14898
  }
14599
14899
  function resolveScanRoot(rawPath) {
14600
- const resolved = resolve(process.cwd(), rawPath);
14900
+ const resolved = resolve21(process.cwd(), rawPath);
14601
14901
  try {
14602
- const stats = statSync(resolved);
14902
+ const stats = statSync7(resolved);
14603
14903
  if (!stats.isDirectory()) {
14604
- return resolve(resolved, "..");
14904
+ return resolve21(resolved, "..");
14605
14905
  }
14606
14906
  } catch {
14607
14907
  }
@@ -14611,7 +14911,7 @@ function toPosix2(p) {
14611
14911
  return p.replace(/\\/g, "/");
14612
14912
  }
14613
14913
  function relativePath2(p) {
14614
- return toPosix2(relative(process.cwd(), p));
14914
+ return toPosix2(relative21(process.cwd(), p));
14615
14915
  }
14616
14916
  var plugin45 = {
14617
14917
  name: "dead-code-detector",
@@ -14678,12 +14978,12 @@ var plugin45 = {
14678
14978
  let result;
14679
14979
  try {
14680
14980
  result = scan(scanRoot, 1, cfg);
14681
- } catch (err) {
14981
+ } catch {
14682
14982
  state42.errorCount += 1;
14683
14983
  return;
14684
14984
  }
14685
- const changedFile = resolve(process.cwd(), sourcePath);
14686
- const relevant = result.findings.filter((f) => resolve(f.file) === changedFile);
14985
+ const changedFile = resolve21(process.cwd(), sourcePath);
14986
+ const relevant = result.findings.filter((f) => resolve21(f.file) === changedFile);
14687
14987
  if (relevant.length === 0) {
14688
14988
  state42.missCount += 1;
14689
14989
  return;
@@ -14800,6 +15100,10 @@ Consider removing the export if it is not part of the public API.`;
14800
15100
  }
14801
15101
  };
14802
15102
  var dead_code_detector_default = plugin45;
15103
+
15104
+ // src/dependency-vulnerability-gate/index.ts
15105
+ import { execFileSync as execFileSync10 } from "node:child_process";
15106
+ import { existsSync as existsSync11 } from "node:fs";
14803
15107
  var API_VERSION26 = "^0.1.10";
14804
15108
  var state43 = {
14805
15109
  invocations: 0,
@@ -14912,14 +15216,14 @@ function isInstallCommand(input) {
14912
15216
  return INSTALL_RE2.test(command);
14913
15217
  }
14914
15218
  function detectManager() {
14915
- return existsSync("pnpm-lock.yaml") ? "pnpm" : "npm";
15219
+ return existsSync11("pnpm-lock.yaml") ? "pnpm" : "npm";
14916
15220
  }
14917
15221
  function runAudit(cfg) {
14918
15222
  const manager = detectManager();
14919
15223
  const start = Date.now();
14920
15224
  let stdout = "";
14921
15225
  try {
14922
- stdout = execFileSync(manager, ["audit", "--json"], {
15226
+ stdout = execFileSync10(manager, ["audit", "--json"], {
14923
15227
  encoding: "utf-8",
14924
15228
  timeout: cfg.timeoutMs,
14925
15229
  cwd: process.cwd(),
@@ -15102,6 +15406,9 @@ Review the audit output or adjust the dependency choice.`;
15102
15406
  }
15103
15407
  };
15104
15408
  var dependency_vulnerability_gate_default = plugin46;
15409
+
15410
+ // src/doc-sync-guard/index.ts
15411
+ import { isAbsolute as isAbsolute23, relative as relative22, resolve as resolve22, basename as basename5, extname as extname4 } from "node:path";
15105
15412
  var API_VERSION27 = "^0.1.10";
15106
15413
  var state44 = {
15107
15414
  changedFiles: [],
@@ -15129,32 +15436,32 @@ function readConfig39(raw) {
15129
15436
  function withinProject14(p) {
15130
15437
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
15131
15438
  const root = process.cwd();
15132
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
15133
- const rel = relative(root, resolved);
15439
+ const resolved = isAbsolute23(p) ? resolve22(p) : resolve22(root, p);
15440
+ const rel = relative22(root, resolved);
15134
15441
  if (rel === "" || rel === ".") return true;
15135
15442
  if (rel.startsWith("..")) return false;
15136
- if (isAbsolute(rel)) return false;
15443
+ if (isAbsolute23(rel)) return false;
15137
15444
  return true;
15138
15445
  }
15139
15446
  function normalizeSlashes(p) {
15140
15447
  return p.replace(/\\/g, "/");
15141
15448
  }
15142
15449
  function isSourceFile(p, extensions) {
15143
- const ext = extname(p).toLowerCase();
15450
+ const ext = extname4(p).toLowerCase();
15144
15451
  return extensions.includes(ext);
15145
15452
  }
15146
15453
  function isPublicSource(p, extensions) {
15147
15454
  if (!isSourceFile(p, extensions)) return false;
15148
15455
  const norm = normalizeSlashes(p);
15149
15456
  if (norm.includes("/node_modules/") || norm.startsWith("node_modules/")) return false;
15150
- const base = basename(norm).toLowerCase();
15457
+ const base = basename5(norm).toLowerCase();
15151
15458
  if (/\.(test|spec)\./.test(base)) return false;
15152
15459
  if (base.startsWith("_")) return false;
15153
15460
  return true;
15154
15461
  }
15155
15462
  function isDocFile(p, docNames) {
15156
15463
  const norm = normalizeSlashes(p);
15157
- const base = basename(norm);
15464
+ const base = basename5(norm);
15158
15465
  const lowerBase = base.toLowerCase();
15159
15466
  if (docNames.some((name) => lowerBase === name.toLowerCase())) return true;
15160
15467
  if (norm.includes("/docs/") || norm.startsWith("docs/")) return true;
@@ -15172,7 +15479,7 @@ function extractDocContent(toolInput) {
15172
15479
  return void 0;
15173
15480
  }
15174
15481
  function referenceTokens(p) {
15175
- const base = basename(p);
15482
+ const base = basename5(p);
15176
15483
  const withoutExt = base.replace(/\.[^.]+$/, "");
15177
15484
  const tokens = [base];
15178
15485
  if (withoutExt && withoutExt !== base) tokens.push(withoutExt);
@@ -15320,6 +15627,10 @@ Consider mentioning these changes in the documentation.`;
15320
15627
  }
15321
15628
  };
15322
15629
  var doc_sync_guard_default = plugin47;
15630
+
15631
+ // src/duplicate-code-detector/index.ts
15632
+ import { existsSync as existsSync12, readFileSync as readFileSync13, readdirSync as readdirSync6, statSync as statSync8 } from "node:fs";
15633
+ import { extname as extname5, isAbsolute as isAbsolute24, relative as relative23, resolve as resolve23 } from "node:path";
15323
15634
  var API_VERSION28 = "^0.1.10";
15324
15635
  var state45 = {
15325
15636
  scanCount: 0,
@@ -15353,21 +15664,21 @@ function readConfig40(raw) {
15353
15664
  function withinProject15(p) {
15354
15665
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
15355
15666
  const root = process.cwd();
15356
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
15357
- const rel = relative(root, resolved);
15667
+ const resolved = isAbsolute24(p) ? resolve23(p) : resolve23(root, p);
15668
+ const rel = relative23(root, resolved);
15358
15669
  if (rel === "" || rel === ".") return true;
15359
15670
  if (rel.startsWith("..")) return false;
15360
- if (isAbsolute(rel)) return false;
15671
+ if (isAbsolute24(rel)) return false;
15361
15672
  return true;
15362
15673
  }
15363
15674
  function matchesExtension3(p, exts) {
15364
- const ext = extname(p).toLowerCase();
15675
+ const ext = extname5(p).toLowerCase();
15365
15676
  return exts.includes(ext);
15366
15677
  }
15367
15678
  function collectSourceFiles2(root, cfg) {
15368
15679
  const files = [];
15369
- if (!existsSync(root)) return files;
15370
- const s = statSync(root);
15680
+ if (!existsSync12(root)) return files;
15681
+ const s = statSync8(root);
15371
15682
  if (s.isFile()) {
15372
15683
  if (matchesExtension3(root, cfg.extensions)) files.push(root);
15373
15684
  return files;
@@ -15376,15 +15687,15 @@ function collectSourceFiles2(root, cfg) {
15376
15687
  function walk(dir) {
15377
15688
  let entries;
15378
15689
  try {
15379
- entries = readdirSync(dir);
15690
+ entries = readdirSync6(dir);
15380
15691
  } catch {
15381
15692
  return;
15382
15693
  }
15383
15694
  for (const entry of entries) {
15384
- const full = resolve(dir, entry);
15695
+ const full = resolve23(dir, entry);
15385
15696
  let st;
15386
15697
  try {
15387
- st = statSync(full);
15698
+ st = statSync8(full);
15388
15699
  } catch {
15389
15700
  continue;
15390
15701
  }
@@ -15402,7 +15713,7 @@ function toPosix3(p) {
15402
15713
  return p.replace(/\\/g, "/");
15403
15714
  }
15404
15715
  function relativePath3(p) {
15405
- return toPosix3(relative(process.cwd(), p));
15716
+ return toPosix3(relative23(process.cwd(), p));
15406
15717
  }
15407
15718
  function removeInlineComments(line) {
15408
15719
  return line.replace(/\/\/.*$/, "").replace(/\/\*[\s\S]*?\*\//, "");
@@ -15460,12 +15771,12 @@ function findDuplicates(files, minLines, maxFindings) {
15460
15771
  }
15461
15772
  function scanPath(rawPath, cfg) {
15462
15773
  const root = process.cwd();
15463
- const resolved = isAbsolute(rawPath) ? resolve(rawPath) : resolve(root, rawPath);
15774
+ const resolved = isAbsolute24(rawPath) ? resolve23(rawPath) : resolve23(root, rawPath);
15464
15775
  const filePaths = collectSourceFiles2(resolved, cfg);
15465
15776
  const files = /* @__PURE__ */ new Map();
15466
15777
  for (const p of filePaths) {
15467
15778
  try {
15468
- files.set(p, readFileSync(p, "utf-8"));
15779
+ files.set(p, readFileSync13(p, "utf-8"));
15469
15780
  } catch {
15470
15781
  }
15471
15782
  }
@@ -15545,24 +15856,24 @@ var plugin48 = {
15545
15856
  const now = Date.now();
15546
15857
  const lastWarning = state45.lastHookWarning.get(sourcePath);
15547
15858
  if (lastWarning !== void 0 && now - lastWarning < 6e4) return;
15548
- const changedFile = resolve(process.cwd(), sourcePath);
15859
+ const changedFile = resolve23(process.cwd(), sourcePath);
15549
15860
  let content;
15550
15861
  try {
15551
- content = readFileSync(changedFile, "utf-8");
15862
+ content = readFileSync13(changedFile, "utf-8");
15552
15863
  } catch {
15553
15864
  state45.errorCount += 1;
15554
15865
  return;
15555
15866
  }
15556
15867
  const changedWindows = extractWindows(changedFile, content, cfg.minLines);
15557
15868
  if (changedWindows.length === 0) return;
15558
- const projectRoot = resolve(process.cwd());
15869
+ const projectRoot = resolve23(process.cwd());
15559
15870
  let otherFiles;
15560
15871
  try {
15561
15872
  const filePaths = collectSourceFiles2(projectRoot, cfg).filter((p) => p !== changedFile);
15562
15873
  otherFiles = /* @__PURE__ */ new Map();
15563
15874
  for (const p of filePaths) {
15564
15875
  try {
15565
- otherFiles.set(p, readFileSync(p, "utf-8"));
15876
+ otherFiles.set(p, readFileSync13(p, "utf-8"));
15566
15877
  } catch {
15567
15878
  }
15568
15879
  }
@@ -15621,7 +15932,7 @@ var plugin48 = {
15621
15932
  state45.findingCount += result.findings.length;
15622
15933
  return {
15623
15934
  ok: true,
15624
- path: relativePath3(resolve(process.cwd(), rawPath)),
15935
+ path: relativePath3(resolve23(process.cwd(), rawPath)),
15625
15936
  scannedFiles: result.scannedFiles,
15626
15937
  minLines: cfg.minLines,
15627
15938
  findings: result.findings
@@ -15698,6 +16009,10 @@ var plugin48 = {
15698
16009
  }
15699
16010
  };
15700
16011
  var duplicate_code_detector_default = plugin48;
16012
+
16013
+ // src/feature-flag-tracker/index.ts
16014
+ import { existsSync as existsSync13, readFileSync as readFileSync14, readdirSync as readdirSync7, statSync as statSync9 } from "node:fs";
16015
+ import { extname as extname6, isAbsolute as isAbsolute25, relative as relative24, resolve as resolve24 } from "node:path";
15701
16016
  var API_VERSION29 = "^0.1.10";
15702
16017
  var state46 = {
15703
16018
  scanCount: 0,
@@ -15732,23 +16047,23 @@ function readConfig41(raw) {
15732
16047
  function withinProject16(p) {
15733
16048
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
15734
16049
  const root = process.cwd();
15735
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
15736
- const rel = relative(root, resolved);
16050
+ const resolved = isAbsolute25(p) ? resolve24(p) : resolve24(root, p);
16051
+ const rel = relative24(root, resolved);
15737
16052
  if (rel === "" || rel === ".") return true;
15738
16053
  if (rel.startsWith("..")) return false;
15739
- if (isAbsolute(rel)) return false;
16054
+ if (isAbsolute25(rel)) return false;
15740
16055
  return true;
15741
16056
  }
15742
16057
  function normalizeExtensions3(exts) {
15743
16058
  return exts.map((e) => e.startsWith(".") ? e.toLowerCase() : `.${e.toLowerCase()}`);
15744
16059
  }
15745
16060
  function matchesExtension4(p, exts) {
15746
- return exts.includes(extname(p).toLowerCase());
16061
+ return exts.includes(extname6(p).toLowerCase());
15747
16062
  }
15748
16063
  function collectSourceFiles3(root, exts) {
15749
16064
  const files = [];
15750
- if (!existsSync(root)) return files;
15751
- const s = statSync(root);
16065
+ if (!existsSync13(root)) return files;
16066
+ const s = statSync9(root);
15752
16067
  if (s.isFile()) {
15753
16068
  if (matchesExtension4(root, exts)) files.push(root);
15754
16069
  return files;
@@ -15757,16 +16072,16 @@ function collectSourceFiles3(root, exts) {
15757
16072
  function walk(dir) {
15758
16073
  let entries;
15759
16074
  try {
15760
- entries = readdirSync(dir);
16075
+ entries = readdirSync7(dir);
15761
16076
  } catch {
15762
16077
  return;
15763
16078
  }
15764
16079
  for (const entry of entries) {
15765
16080
  if (entry === "node_modules" || entry === "dist" || entry === ".git" || entry === "coverage") continue;
15766
- const full = resolve(dir, entry);
16081
+ const full = resolve24(dir, entry);
15767
16082
  let st;
15768
16083
  try {
15769
- st = statSync(full);
16084
+ st = statSync9(full);
15770
16085
  } catch {
15771
16086
  continue;
15772
16087
  }
@@ -15784,7 +16099,7 @@ function toPosix4(p) {
15784
16099
  return p.replace(/\\/g, "/");
15785
16100
  }
15786
16101
  function relativePath4(p) {
15787
- return toPosix4(relative(process.cwd(), p));
16102
+ return toPosix4(relative24(process.cwd(), p));
15788
16103
  }
15789
16104
  function compilePatterns(patterns) {
15790
16105
  const sources = [...DEFAULT_PATTERNS2, ...patterns];
@@ -15795,8 +16110,7 @@ function scanFile(filePath, content, patterns, maxFindings) {
15795
16110
  const lines = content.split(/\r?\n/);
15796
16111
  for (const re of patterns) {
15797
16112
  re.lastIndex = 0;
15798
- let m;
15799
- while ((m = re.exec(content)) !== null) {
16113
+ for (const m of content.matchAll(re)) {
15800
16114
  const flag = m[1] ?? m[0];
15801
16115
  const lineNo = content.slice(0, m.index).split(/\r?\n/).length;
15802
16116
  const context = (lines[lineNo - 1] ?? "").trim();
@@ -15815,14 +16129,14 @@ function scanFile(filePath, content, patterns, maxFindings) {
15815
16129
  }
15816
16130
  function scanPath2(rawPath, cfg) {
15817
16131
  const root = process.cwd();
15818
- const resolved = isAbsolute(rawPath) ? resolve(rawPath) : resolve(root, rawPath);
16132
+ const resolved = isAbsolute25(rawPath) ? resolve24(rawPath) : resolve24(root, rawPath);
15819
16133
  const exts = normalizeExtensions3(cfg.extensions);
15820
16134
  const files = collectSourceFiles3(resolved, exts);
15821
16135
  const patterns = compilePatterns(cfg.patterns);
15822
16136
  const usages = [];
15823
16137
  for (const p of files) {
15824
16138
  try {
15825
- const content = readFileSync(p, "utf-8");
16139
+ const content = readFileSync14(p, "utf-8");
15826
16140
  usages.push(...scanFile(p, content, patterns, cfg.maxFindings));
15827
16141
  if (usages.length >= cfg.maxFindings) break;
15828
16142
  } catch {
@@ -15886,10 +16200,10 @@ var plugin49 = {
15886
16200
  const exts = normalizeExtensions3(cfg.extensions);
15887
16201
  if (!matchesExtension4(sourcePath, exts)) return;
15888
16202
  state46.hookInvocationCount += 1;
15889
- const resolved = resolve(process.cwd(), sourcePath);
16203
+ const resolved = resolve24(process.cwd(), sourcePath);
15890
16204
  let content;
15891
16205
  try {
15892
- content = readFileSync(resolved, "utf-8");
16206
+ content = readFileSync14(resolved, "utf-8");
15893
16207
  } catch {
15894
16208
  state46.errorCount += 1;
15895
16209
  return;
@@ -15935,7 +16249,7 @@ Make sure flag behavior is intentional and consider updating flag inventory/docs
15935
16249
  state46.flagCount += result.usages.length;
15936
16250
  return {
15937
16251
  ok: true,
15938
- path: relativePath4(resolve(process.cwd(), rawPath)),
16252
+ path: relativePath4(resolve24(process.cwd(), rawPath)),
15939
16253
  scannedFiles: result.scannedFiles,
15940
16254
  usages: result.usages
15941
16255
  };
@@ -16008,6 +16322,10 @@ Make sure flag behavior is intentional and consider updating flag inventory/docs
16008
16322
  }
16009
16323
  };
16010
16324
  var feature_flag_tracker_default = plugin49;
16325
+
16326
+ // src/interface-contract-guard/index.ts
16327
+ import { existsSync as existsSync14, readFileSync as readFileSync15, readdirSync as readdirSync8, statSync as statSync10 } from "node:fs";
16328
+ import { extname as extname7, isAbsolute as isAbsolute26, relative as relative25, resolve as resolve25 } from "node:path";
16011
16329
  var API_VERSION30 = "^0.1.10";
16012
16330
  var state47 = {
16013
16331
  scanCount: 0,
@@ -16034,23 +16352,23 @@ function readConfig42(raw) {
16034
16352
  function withinProject17(p) {
16035
16353
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
16036
16354
  const root = process.cwd();
16037
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
16038
- const rel = relative(root, resolved);
16355
+ const resolved = isAbsolute26(p) ? resolve25(p) : resolve25(root, p);
16356
+ const rel = relative25(root, resolved);
16039
16357
  if (rel === "" || rel === ".") return true;
16040
16358
  if (rel.startsWith("..")) return false;
16041
- if (isAbsolute(rel)) return false;
16359
+ if (isAbsolute26(rel)) return false;
16042
16360
  return true;
16043
16361
  }
16044
16362
  function normalizeExtensions4(exts) {
16045
16363
  return exts.map((e) => e.startsWith(".") ? e.toLowerCase() : `.${e.toLowerCase()}`);
16046
16364
  }
16047
16365
  function matchesExtension5(p, exts) {
16048
- return exts.includes(extname(p).toLowerCase());
16366
+ return exts.includes(extname7(p).toLowerCase());
16049
16367
  }
16050
16368
  function collectSourceFiles4(root, exts) {
16051
16369
  const files = [];
16052
- if (!existsSync(root)) return files;
16053
- const s = statSync(root);
16370
+ if (!existsSync14(root)) return files;
16371
+ const s = statSync10(root);
16054
16372
  if (s.isFile()) {
16055
16373
  if (matchesExtension5(root, exts)) files.push(root);
16056
16374
  return files;
@@ -16059,16 +16377,16 @@ function collectSourceFiles4(root, exts) {
16059
16377
  function walk(dir) {
16060
16378
  let entries;
16061
16379
  try {
16062
- entries = readdirSync(dir);
16380
+ entries = readdirSync8(dir);
16063
16381
  } catch {
16064
16382
  return;
16065
16383
  }
16066
16384
  for (const entry of entries) {
16067
16385
  if (entry === "node_modules" || entry === "dist" || entry === ".git" || entry === "coverage") continue;
16068
- const full = resolve(dir, entry);
16386
+ const full = resolve25(dir, entry);
16069
16387
  let st;
16070
16388
  try {
16071
- st = statSync(full);
16389
+ st = statSync10(full);
16072
16390
  } catch {
16073
16391
  continue;
16074
16392
  }
@@ -16086,14 +16404,13 @@ function toPosix5(p) {
16086
16404
  return p.replace(/\\/g, "/");
16087
16405
  }
16088
16406
  function relativePath5(p) {
16089
- return toPosix5(relative(process.cwd(), p));
16407
+ return toPosix5(relative25(process.cwd(), p));
16090
16408
  }
16091
16409
  var INTERFACE_RE = /(?:export\s+)?interface\s+([A-Za-z_$][A-Za-z0-9_$]*)/g;
16092
16410
  function extractInterfaceNames(content) {
16093
16411
  const names = [];
16094
- let m;
16095
16412
  INTERFACE_RE.lastIndex = 0;
16096
- while ((m = INTERFACE_RE.exec(content)) !== null) {
16413
+ for (const m of content.matchAll(INTERFACE_RE)) {
16097
16414
  names.push({ name: m[1], line: content.slice(0, m.index).split(/\r?\n/).length });
16098
16415
  }
16099
16416
  return names;
@@ -16107,13 +16424,13 @@ function hasImplementer(name, contents) {
16107
16424
  }
16108
16425
  function scanPath3(rawPath, cfg) {
16109
16426
  const root = process.cwd();
16110
- const resolved = isAbsolute(rawPath) ? resolve(rawPath) : resolve(root, rawPath);
16427
+ const resolved = isAbsolute26(rawPath) ? resolve25(rawPath) : resolve25(root, rawPath);
16111
16428
  const exts = normalizeExtensions4(cfg.extensions);
16112
16429
  const files = collectSourceFiles4(resolved, exts);
16113
16430
  const contents = [];
16114
16431
  for (const p of files) {
16115
16432
  try {
16116
- contents.push({ path: p, content: readFileSync(p, "utf-8") });
16433
+ contents.push({ path: p, content: readFileSync15(p, "utf-8") });
16117
16434
  } catch {
16118
16435
  }
16119
16436
  }
@@ -16185,10 +16502,10 @@ var plugin50 = {
16185
16502
  const exts = normalizeExtensions4(cfg.extensions);
16186
16503
  if (!matchesExtension5(sourcePath, exts)) return;
16187
16504
  state47.hookInvocationCount += 1;
16188
- const resolved = resolve(process.cwd(), sourcePath);
16505
+ const resolved = resolve25(process.cwd(), sourcePath);
16189
16506
  let content;
16190
16507
  try {
16191
- content = readFileSync(resolved, "utf-8");
16508
+ content = readFileSync15(resolved, "utf-8");
16192
16509
  } catch {
16193
16510
  state47.errorCount += 1;
16194
16511
  return;
@@ -16233,7 +16550,7 @@ If you changed member shapes, search the project for implementers/\`satisfies\`/
16233
16550
  state47.findingCount += result.findings.length;
16234
16551
  return {
16235
16552
  ok: true,
16236
- path: relativePath5(resolve(process.cwd(), rawPath)),
16553
+ path: relativePath5(resolve25(process.cwd(), rawPath)),
16237
16554
  scannedFiles: result.scannedFiles,
16238
16555
  findings: result.findings
16239
16556
  };
@@ -16304,6 +16621,10 @@ If you changed member shapes, search the project for implementers/\`satisfies\`/
16304
16621
  }
16305
16622
  };
16306
16623
  var interface_contract_guard_default = plugin50;
16624
+
16625
+ // src/license-audit-gate/index.ts
16626
+ import { readFileSync as readFileSync16 } from "node:fs";
16627
+ import { resolve as resolve26 } from "node:path";
16307
16628
  var API_VERSION31 = "^0.1.10";
16308
16629
  var state48 = {
16309
16630
  invocations: 0,
@@ -16357,8 +16678,7 @@ var INSTALL_RE3 = /(?:^|[;&|]\s*)(npm|pnpm|yarn|bun)\s+(?:install|i|add)\s+([^;&
16357
16678
  function parsePackageNames(command) {
16358
16679
  const names = [];
16359
16680
  INSTALL_RE3.lastIndex = 0;
16360
- let m;
16361
- while ((m = INSTALL_RE3.exec(command)) !== null) {
16681
+ for (const m of command.matchAll(INSTALL_RE3)) {
16362
16682
  const argString = m[2] ?? "";
16363
16683
  for (const token of argString.split(/\s+/)) {
16364
16684
  if (!token || token.startsWith("-")) continue;
@@ -16380,8 +16700,8 @@ function auditPackages(names, allowedLicenses) {
16380
16700
  for (const name of names) {
16381
16701
  let licenses = [];
16382
16702
  try {
16383
- const pkgPath = resolve("node_modules", name, "package.json");
16384
- const raw = JSON.parse(readFileSync(pkgPath, "utf-8"));
16703
+ const pkgPath = resolve26("node_modules", name, "package.json");
16704
+ const raw = JSON.parse(readFileSync16(pkgPath, "utf-8"));
16385
16705
  licenses = extractLicenseStrings(raw);
16386
16706
  } catch {
16387
16707
  errors.push(name);
@@ -16558,6 +16878,10 @@ Allowed licenses: ${cfg.allowedLicenses.join(", ")}
16558
16878
  }
16559
16879
  };
16560
16880
  var license_audit_gate_default = plugin51;
16881
+
16882
+ // src/migration-planner/index.ts
16883
+ import { existsSync as existsSync15, readFileSync as readFileSync17 } from "node:fs";
16884
+ import { isAbsolute as isAbsolute27, relative as relative26, resolve as resolve27 } from "node:path";
16561
16885
  var API_VERSION32 = "^0.1.10";
16562
16886
  var state49 = {
16563
16887
  plansGenerated: 0,
@@ -16583,11 +16907,11 @@ function readConfig44(raw) {
16583
16907
  function withinProject18(p) {
16584
16908
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
16585
16909
  const root = process.cwd();
16586
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
16587
- const rel = relative(root, resolved);
16910
+ const resolved = isAbsolute27(p) ? resolve27(p) : resolve27(root, p);
16911
+ const rel = relative26(root, resolved);
16588
16912
  if (rel === "" || rel === ".") return true;
16589
16913
  if (rel.startsWith("..")) return false;
16590
- if (isAbsolute(rel)) return false;
16914
+ if (isAbsolute27(rel)) return false;
16591
16915
  return true;
16592
16916
  }
16593
16917
  function normalizeVersion(v) {
@@ -16599,9 +16923,9 @@ function readChangelog(packageName, cfg) {
16599
16923
  candidates.push(`node_modules/${packageName}/changelog.md`);
16600
16924
  for (const candidate of candidates) {
16601
16925
  if (!withinProject18(candidate)) continue;
16602
- if (existsSync(candidate)) {
16926
+ if (existsSync15(candidate)) {
16603
16927
  try {
16604
- const content = readFileSync(candidate, "utf-8");
16928
+ const content = readFileSync17(candidate, "utf-8");
16605
16929
  return { source: candidate, content: content.slice(0, cfg.maxChars) };
16606
16930
  } catch {
16607
16931
  }
@@ -16753,14 +17077,14 @@ var plugin52 = {
16753
17077
  const inp = input.toolInput ?? {};
16754
17078
  const path = inp["path"];
16755
17079
  if (!path) return;
16756
- const basename6 = path.split(/[/\\]/).pop() ?? "";
17080
+ const basename7 = path.split(/[/\\]/).pop() ?? "";
16757
17081
  if (!/^(package\.json|package-lock\.json|pnpm-lock\.yaml|yarn\.lock|bun\.lockb?)$/i.test(
16758
- basename6
17082
+ basename7
16759
17083
  )) {
16760
17084
  return;
16761
17085
  }
16762
17086
  return {
16763
- additionalContext: `Manifest file ${basename6} changed. Consider running migration_plan if a dependency version was updated.`
17087
+ additionalContext: `Manifest file ${basename7} changed. Consider running migration_plan if a dependency version was updated.`
16764
17088
  };
16765
17089
  };
16766
17090
  state49.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook);
@@ -16901,6 +17225,10 @@ var plugin52 = {
16901
17225
  }
16902
17226
  };
16903
17227
  var migration_planner_default = plugin52;
17228
+
17229
+ // src/performance-regression-gate/index.ts
17230
+ import { existsSync as existsSync16, readFileSync as readFileSync18 } from "node:fs";
17231
+ import { isAbsolute as isAbsolute28, relative as relative27, resolve as resolve28 } from "node:path";
16904
17232
  var API_VERSION33 = "^0.1.10";
16905
17233
  var state50 = {
16906
17234
  invocationCount: 0,
@@ -16925,18 +17253,18 @@ function readConfig45(raw) {
16925
17253
  }
16926
17254
  function withinProject19(p, cwd = process.cwd()) {
16927
17255
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
16928
- const root = resolve(cwd);
16929
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
16930
- const rel = relative(root, resolved);
17256
+ const root = resolve28(cwd);
17257
+ const resolved = isAbsolute28(p) ? resolve28(p) : resolve28(root, p);
17258
+ const rel = relative27(root, resolved);
16931
17259
  if (rel === "" || rel === ".") return true;
16932
17260
  if (rel.startsWith("..")) return false;
16933
- if (isAbsolute(rel)) return false;
17261
+ if (isAbsolute28(rel)) return false;
16934
17262
  return true;
16935
17263
  }
16936
17264
  function resolveProjectPath7(rawPath, cwd = process.cwd()) {
16937
17265
  if (typeof rawPath !== "string" || rawPath.length === 0) return null;
16938
- const root = resolve(cwd);
16939
- const resolved = isAbsolute(rawPath) ? resolve(rawPath) : resolve(root, rawPath);
17266
+ const root = resolve28(cwd);
17267
+ const resolved = isAbsolute28(rawPath) ? resolve28(rawPath) : resolve28(root, rawPath);
16940
17268
  if (!withinProject19(resolved, cwd)) return null;
16941
17269
  return resolved;
16942
17270
  }
@@ -16965,9 +17293,9 @@ function flattenResults(results) {
16965
17293
  return flat;
16966
17294
  }
16967
17295
  function loadResults(path) {
16968
- if (!path || !existsSync(path)) return null;
17296
+ if (!path || !existsSync16(path)) return null;
16969
17297
  try {
16970
- const raw = JSON.parse(readFileSync(path, "utf-8"));
17298
+ const raw = JSON.parse(readFileSync18(path, "utf-8"));
16971
17299
  return raw;
16972
17300
  } catch {
16973
17301
  return null;
@@ -17210,6 +17538,10 @@ var plugin53 = {
17210
17538
  }
17211
17539
  };
17212
17540
  var performance_regression_gate_default = plugin53;
17541
+
17542
+ // src/refactor-suggester/index.ts
17543
+ import { existsSync as existsSync17, readFileSync as readFileSync19, readdirSync as readdirSync9, statSync as statSync11 } from "node:fs";
17544
+ import { extname as extname8, isAbsolute as isAbsolute29, relative as relative28, resolve as resolve29 } from "node:path";
17213
17545
  var API_VERSION34 = "^0.1.10";
17214
17546
  var state51 = {
17215
17547
  scanCount: 0,
@@ -17248,23 +17580,23 @@ function readConfig46(raw) {
17248
17580
  function withinProject20(p) {
17249
17581
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
17250
17582
  const root = process.cwd();
17251
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
17252
- const rel = relative(root, resolved);
17583
+ const resolved = isAbsolute29(p) ? resolve29(p) : resolve29(root, p);
17584
+ const rel = relative28(root, resolved);
17253
17585
  if (rel === "" || rel === ".") return true;
17254
17586
  if (rel.startsWith("..")) return false;
17255
- if (isAbsolute(rel)) return false;
17587
+ if (isAbsolute29(rel)) return false;
17256
17588
  return true;
17257
17589
  }
17258
17590
  function normalizeExtensions5(exts) {
17259
17591
  return exts.map((e) => e.startsWith(".") ? e.toLowerCase() : `.${e.toLowerCase()}`);
17260
17592
  }
17261
17593
  function matchesExtension6(p, exts) {
17262
- return exts.includes(extname(p).toLowerCase());
17594
+ return exts.includes(extname8(p).toLowerCase());
17263
17595
  }
17264
17596
  function collectSourceFiles5(root, exts) {
17265
17597
  const files = [];
17266
- if (!existsSync(root)) return files;
17267
- const s = statSync(root);
17598
+ if (!existsSync17(root)) return files;
17599
+ const s = statSync11(root);
17268
17600
  if (s.isFile()) {
17269
17601
  if (matchesExtension6(root, exts)) files.push(root);
17270
17602
  return files;
@@ -17273,16 +17605,16 @@ function collectSourceFiles5(root, exts) {
17273
17605
  function walk(dir) {
17274
17606
  let entries;
17275
17607
  try {
17276
- entries = readdirSync(dir);
17608
+ entries = readdirSync9(dir);
17277
17609
  } catch {
17278
17610
  return;
17279
17611
  }
17280
17612
  for (const entry of entries) {
17281
17613
  if (entry === "node_modules" || entry === "dist" || entry === ".git" || entry === "coverage") continue;
17282
- const full = resolve(dir, entry);
17614
+ const full = resolve29(dir, entry);
17283
17615
  let st;
17284
17616
  try {
17285
- st = statSync(full);
17617
+ st = statSync11(full);
17286
17618
  } catch {
17287
17619
  continue;
17288
17620
  }
@@ -17300,7 +17632,7 @@ function toPosix6(p) {
17300
17632
  return p.replace(/\\/g, "/");
17301
17633
  }
17302
17634
  function relativePath6(p) {
17303
- return toPosix6(relative(process.cwd(), p));
17635
+ return toPosix6(relative28(process.cwd(), p));
17304
17636
  }
17305
17637
  function leadingIndentLevel(line) {
17306
17638
  const leading = line.match(/^(\s*)/)?.[1] ?? "";
@@ -17313,21 +17645,20 @@ function detectSmells(filePath, content, rules) {
17313
17645
  const lines = content.split(/\r?\n/);
17314
17646
  const stripped = content.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, " ");
17315
17647
  const functionLikeRe = /(?:export\s+)?(?:async\s+)?(?:function\s+)?([A-Za-z_$][A-Za-z0-9_$]*)\s*\(([^)]*)\)\s*\{/g;
17316
- let m;
17317
17648
  functionLikeRe.lastIndex = 0;
17318
- while ((m = functionLikeRe.exec(stripped)) !== null) {
17319
- const name = m[1];
17320
- const paramsRaw = m[2];
17649
+ for (const match of stripped.matchAll(functionLikeRe)) {
17650
+ const name = match[1];
17651
+ const paramsRaw = match[2];
17321
17652
  const params = paramsRaw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
17322
17653
  if (params.length > rules.maxParams) {
17323
17654
  suggestions.push({
17324
17655
  file: relativePath6(filePath),
17325
- line: content.slice(0, m.index).split(/\r?\n/).length,
17656
+ line: content.slice(0, match.index).split(/\r?\n/).length,
17326
17657
  type: "many-parameters",
17327
17658
  message: `${name} has ${params.length} parameters (limit ${rules.maxParams})`
17328
17659
  });
17329
17660
  }
17330
- const bodyStart = m.index + m[0].length;
17661
+ const bodyStart = match.index + match[0].length;
17331
17662
  let depth = 1;
17332
17663
  let lineEnd = bodyStart;
17333
17664
  for (let i = bodyStart; i < stripped.length && depth > 0; i++) {
@@ -17340,7 +17671,7 @@ function detectSmells(filePath, content, rules) {
17340
17671
  if (bodyLines > rules.longFunctionLines) {
17341
17672
  suggestions.push({
17342
17673
  file: relativePath6(filePath),
17343
- line: content.slice(0, m.index).split(/\r?\n/).length,
17674
+ line: content.slice(0, match.index).split(/\r?\n/).length,
17344
17675
  type: "long-function",
17345
17676
  message: `${name} spans ~${bodyLines} lines (limit ${rules.longFunctionLines})`
17346
17677
  });
@@ -17371,15 +17702,15 @@ function detectSmells(filePath, content, rules) {
17371
17702
  const magicRe = /\b-?\d+(?:\.\d+)?\b/g;
17372
17703
  const allowed = /* @__PURE__ */ new Set(["0", "1", "-1", "2"]);
17373
17704
  magicRe.lastIndex = 0;
17374
- while ((m = magicRe.exec(content)) !== null) {
17375
- const match = m[0];
17705
+ for (const magicNumberMatch of content.matchAll(magicRe)) {
17706
+ const match = magicNumberMatch[0];
17376
17707
  if (allowed.has(match)) continue;
17377
- const before = content[m.index - 1];
17378
- const after = content[m.index + match.length];
17708
+ const before = content[magicNumberMatch.index - 1];
17709
+ const after = content[magicNumberMatch.index + match.length];
17379
17710
  if (before === "[" && after === "]") continue;
17380
17711
  suggestions.push({
17381
17712
  file: relativePath6(filePath),
17382
- line: content.slice(0, m.index).split(/\r?\n/).length,
17713
+ line: content.slice(0, magicNumberMatch.index).split(/\r?\n/).length,
17383
17714
  type: "magic-number",
17384
17715
  message: `magic number ${match} should be a named constant`
17385
17716
  });
@@ -17388,13 +17719,13 @@ function detectSmells(filePath, content, rules) {
17388
17719
  }
17389
17720
  function scanPath4(rawPath, cfg) {
17390
17721
  const root = process.cwd();
17391
- const resolved = isAbsolute(rawPath) ? resolve(rawPath) : resolve(root, rawPath);
17722
+ const resolved = isAbsolute29(rawPath) ? resolve29(rawPath) : resolve29(root, rawPath);
17392
17723
  const exts = normalizeExtensions5(cfg.extensions);
17393
17724
  const files = collectSourceFiles5(resolved, exts);
17394
17725
  const suggestions = [];
17395
17726
  for (const p of files) {
17396
17727
  try {
17397
- const content = readFileSync(p, "utf-8");
17728
+ const content = readFileSync19(p, "utf-8");
17398
17729
  suggestions.push(...detectSmells(p, content, cfg.rules));
17399
17730
  if (suggestions.length >= cfg.maxSuggestions) break;
17400
17731
  } catch {
@@ -17464,10 +17795,10 @@ var plugin54 = {
17464
17795
  const now = Date.now();
17465
17796
  const lastWarning = state51.lastHookWarning.get(sourcePath);
17466
17797
  if (lastWarning !== void 0 && now - lastWarning < 6e4) return;
17467
- const resolved = resolve(process.cwd(), sourcePath);
17798
+ const resolved = resolve29(process.cwd(), sourcePath);
17468
17799
  let content;
17469
17800
  try {
17470
- content = readFileSync(resolved, "utf-8");
17801
+ content = readFileSync19(resolved, "utf-8");
17471
17802
  } catch {
17472
17803
  state51.errorCount += 1;
17473
17804
  return;
@@ -17511,7 +17842,7 @@ var plugin54 = {
17511
17842
  state51.suggestionCount += result.suggestions.length;
17512
17843
  return {
17513
17844
  ok: true,
17514
- path: relativePath6(resolve(process.cwd(), rawPath)),
17845
+ path: relativePath6(resolve29(process.cwd(), rawPath)),
17515
17846
  scannedFiles: result.scannedFiles,
17516
17847
  suggestions: result.suggestions,
17517
17848
  rules: cfg.rules
@@ -17586,6 +17917,9 @@ var plugin54 = {
17586
17917
  }
17587
17918
  };
17588
17919
  var refactor_suggester_default = plugin54;
17920
+
17921
+ // src/release-notes-generator/index.ts
17922
+ import { execFileSync as execFileSync11 } from "node:child_process";
17589
17923
  var API_VERSION35 = "^0.1.10";
17590
17924
  var state52 = {
17591
17925
  generateCount: 0,
@@ -17626,23 +17960,41 @@ function formatCommit(c, includeScope) {
17626
17960
  line += ` ${c.description}`;
17627
17961
  return line;
17628
17962
  }
17963
+ var GIT_OPTIONS = {
17964
+ encoding: "utf-8",
17965
+ stdio: ["pipe", "pipe", "ignore"],
17966
+ shell: false
17967
+ };
17629
17968
  function resolveFromRef(defaultFrom, inputFrom) {
17630
17969
  if (inputFrom) return inputFrom;
17631
17970
  if (defaultFrom === "latest-tag") {
17632
17971
  try {
17633
- return execSync("git describe --tags --abbrev=0", { encoding: "utf-8", stdio: ["pipe", "pipe", "ignore"] }).trim();
17972
+ return execFileSync11("git", ["describe", "--tags", "--abbrev=0"], GIT_OPTIONS).trim();
17634
17973
  } catch {
17635
17974
  return "";
17636
17975
  }
17637
17976
  }
17638
17977
  return defaultFrom;
17639
17978
  }
17979
+ function resolveCommit(ref) {
17980
+ const resolved = execFileSync11(
17981
+ "git",
17982
+ ["rev-parse", "--verify", "--end-of-options", `${ref}^{commit}`],
17983
+ GIT_OPTIONS
17984
+ ).trim();
17985
+ if (!/^[0-9a-f]{40,64}$/i.test(resolved)) {
17986
+ throw new Error(`git returned an invalid commit id for ref ${JSON.stringify(ref)}`);
17987
+ }
17988
+ return resolved;
17989
+ }
17640
17990
  function getCommits(from, to) {
17641
- const range = from ? `${from}..${to}` : to;
17642
- const output = execSync(`git log --pretty=format:'%H%x09%s' ${range}`, {
17643
- encoding: "utf-8",
17644
- stdio: ["pipe", "pipe", "ignore"]
17645
- });
17991
+ const toCommit = resolveCommit(to);
17992
+ const range = from ? `${resolveCommit(from)}..${toCommit}` : toCommit;
17993
+ const output = execFileSync11(
17994
+ "git",
17995
+ ["log", "--pretty=format:%H%x09%s", "--end-of-options", range],
17996
+ GIT_OPTIONS
17997
+ );
17646
17998
  if (!output.trim()) return [];
17647
17999
  const commits = [];
17648
18000
  for (const line of output.split(/\r?\n/)) {
@@ -17790,6 +18142,10 @@ var plugin55 = {
17790
18142
  }
17791
18143
  };
17792
18144
  var release_notes_generator_default = plugin55;
18145
+
18146
+ // src/schema-evolution-guard/index.ts
18147
+ import { readFileSync as readFileSync20 } from "node:fs";
18148
+ import { basename as basename6, isAbsolute as isAbsolute30, relative as relative29, resolve as resolve30 } from "node:path";
17793
18149
  var API_VERSION36 = "^0.1.10";
17794
18150
  var state53 = {
17795
18151
  invocationCount: 0,
@@ -17842,11 +18198,11 @@ function fileKind(fileName) {
17842
18198
  function withinProject21(p) {
17843
18199
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
17844
18200
  const root = process.cwd();
17845
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
17846
- const rel = relative(root, resolved);
18201
+ const resolved = isAbsolute30(p) ? resolve30(p) : resolve30(root, p);
18202
+ const rel = relative29(root, resolved);
17847
18203
  if (rel === "" || rel === ".") return true;
17848
18204
  if (rel.startsWith("..")) return false;
17849
- if (isAbsolute(rel)) return false;
18205
+ if (isAbsolute30(rel)) return false;
17850
18206
  return true;
17851
18207
  }
17852
18208
  function findIssues(content, kind, maxFindings) {
@@ -17986,7 +18342,7 @@ var plugin56 = {
17986
18342
  const filePath = typeof toolInput["path"] === "string" ? toolInput["path"] : void 0;
17987
18343
  if (!filePath) return;
17988
18344
  state53.invocationCount += 1;
17989
- const fileName = basename(filePath);
18345
+ const fileName = basename6(filePath);
17990
18346
  if (!matchesAnyPattern2(fileName, cfg.filePatterns)) {
17991
18347
  state53.skippedCount += 1;
17992
18348
  return;
@@ -18001,7 +18357,7 @@ var plugin56 = {
18001
18357
  content = toolInput["content"];
18002
18358
  } else if (withinProject21(filePath)) {
18003
18359
  try {
18004
- content = readFileSync(filePath, "utf-8");
18360
+ content = readFileSync20(filePath, "utf-8");
18005
18361
  } catch {
18006
18362
  content = void 0;
18007
18363
  }
@@ -18103,6 +18459,10 @@ ${body}${suffix}`;
18103
18459
  }
18104
18460
  };
18105
18461
  var schema_evolution_guard_default = plugin56;
18462
+
18463
+ // src/security-hotspot-scanner/index.ts
18464
+ import { readdirSync as readdirSync10, readFileSync as readFileSync21, statSync as statSync12 } from "node:fs";
18465
+ import { isAbsolute as isAbsolute31, relative as relative30, resolve as resolve31 } from "node:path";
18106
18466
  var API_VERSION37 = "^0.1.10";
18107
18467
  var state54 = {
18108
18468
  scanCount: 0,
@@ -18147,7 +18507,7 @@ var PATTERNS4 = [
18147
18507
  {
18148
18508
  type: "hardcoded_http",
18149
18509
  severity: "medium",
18150
- regex: /http:\/\/[a-zA-Z0-9][^\s'"\)\\]*/i
18510
+ regex: /http:\/\/[a-zA-Z0-9][^\s'")\\]*/i
18151
18511
  },
18152
18512
  {
18153
18513
  type: "console_log_credentials",
@@ -18187,17 +18547,17 @@ function isSourceFile2(filePath, extensions) {
18187
18547
  function withinProject22(p) {
18188
18548
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
18189
18549
  const root = process.cwd();
18190
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
18191
- const rel = relative(root, resolved);
18550
+ const resolved = isAbsolute31(p) ? resolve31(p) : resolve31(root, p);
18551
+ const rel = relative30(root, resolved);
18192
18552
  if (rel === "" || rel === ".") return true;
18193
18553
  if (rel.startsWith("..")) return false;
18194
- if (isAbsolute(rel)) return false;
18554
+ if (isAbsolute31(rel)) return false;
18195
18555
  return true;
18196
18556
  }
18197
18557
  function scanPath5(inputPath, cfg) {
18198
18558
  const start = Date.now();
18199
18559
  const root = process.cwd();
18200
- const resolved = isAbsolute(inputPath) ? resolve(inputPath) : resolve(root, inputPath);
18560
+ const resolved = isAbsolute31(inputPath) ? resolve31(inputPath) : resolve31(root, inputPath);
18201
18561
  if (!withinProject22(inputPath)) {
18202
18562
  return {
18203
18563
  path: inputPath,
@@ -18214,11 +18574,11 @@ function scanPath5(inputPath, cfg) {
18214
18574
  const scanFile2 = (filePath) => {
18215
18575
  if (!isSourceFile2(filePath, cfg.scanOnChange)) return;
18216
18576
  try {
18217
- const content = readFileSync(filePath, "utf-8");
18577
+ const content = readFileSync21(filePath, "utf-8");
18218
18578
  filesScanned += 1;
18219
18579
  const findings = scanSource(content, maxPerFile);
18220
18580
  for (const f of findings) {
18221
- allFindings.push({ ...f, snippet: `${relative(root, filePath)}:${f.line}: ${f.snippet}` });
18581
+ allFindings.push({ ...f, snippet: `${relative30(root, filePath)}:${f.line}: ${f.snippet}` });
18222
18582
  if (allFindings.length >= cfg.maxFindings) return;
18223
18583
  }
18224
18584
  } catch {
@@ -18227,15 +18587,15 @@ function scanPath5(inputPath, cfg) {
18227
18587
  const walk = (dir) => {
18228
18588
  let entries;
18229
18589
  try {
18230
- entries = readdirSync(dir);
18590
+ entries = readdirSync10(dir);
18231
18591
  } catch {
18232
18592
  return;
18233
18593
  }
18234
18594
  for (const entry of entries) {
18235
18595
  if (allFindings.length >= cfg.maxFindings) return;
18236
- const full = resolve(dir, entry);
18596
+ const full = resolve31(dir, entry);
18237
18597
  try {
18238
- const st = statSync(full);
18598
+ const st = statSync12(full);
18239
18599
  if (st.isDirectory()) {
18240
18600
  if (entry.startsWith(".") || entry === "node_modules" || entry === "dist" || entry === "coverage") {
18241
18601
  continue;
@@ -18249,7 +18609,7 @@ function scanPath5(inputPath, cfg) {
18249
18609
  }
18250
18610
  };
18251
18611
  try {
18252
- const st = statSync(resolved);
18612
+ const st = statSync12(resolved);
18253
18613
  if (st.isDirectory()) {
18254
18614
  walk(resolved);
18255
18615
  } else if (st.isFile()) {
@@ -18499,6 +18859,10 @@ Review or remove the risky pattern(s).`;
18499
18859
  }
18500
18860
  };
18501
18861
  var security_hotspot_scanner_default = plugin57;
18862
+
18863
+ // src/semantic-search-indexer/index.ts
18864
+ import * as fs2 from "node:fs/promises";
18865
+ import { isAbsolute as isAbsolute32, relative as relative31, resolve as resolve32 } from "node:path";
18502
18866
  var API_VERSION38 = "^0.1.10";
18503
18867
  var state55 = {
18504
18868
  index: null,
@@ -18509,7 +18873,9 @@ var state55 = {
18509
18873
  truncated: false,
18510
18874
  queryCount: 0,
18511
18875
  reindexCount: 0,
18512
- buildPromise: null};
18876
+ buildPromise: null,
18877
+ hookUnregister: null
18878
+ };
18513
18879
  var DEFAULTS47 = {
18514
18880
  enabled: true,
18515
18881
  includeExtensions: [
@@ -18571,18 +18937,18 @@ function normalizeSlashes2(p) {
18571
18937
  function withinProject23(p) {
18572
18938
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
18573
18939
  const root = normalizeSlashes2(process.cwd());
18574
- const resolved = normalizeSlashes2(isAbsolute(p) ? resolve(p) : resolve(root, p));
18575
- const rel = normalizeSlashes2(relative(root, resolved));
18940
+ const resolved = normalizeSlashes2(isAbsolute32(p) ? resolve32(p) : resolve32(root, p));
18941
+ const rel = normalizeSlashes2(relative31(root, resolved));
18576
18942
  if (rel === "" || rel === ".") return true;
18577
18943
  if (rel.startsWith("..")) return false;
18578
- if (isAbsolute(rel)) return false;
18944
+ if (isAbsolute32(rel)) return false;
18579
18945
  return true;
18580
18946
  }
18581
18947
  function resolveProjectPath8(p) {
18582
18948
  const raw = typeof p === "string" && p.length > 0 ? p : ".";
18583
18949
  if (!withinProject23(raw)) return null;
18584
18950
  const root = normalizeSlashes2(process.cwd());
18585
- return normalizeSlashes2(isAbsolute(raw) ? resolve(raw) : resolve(root, raw));
18951
+ return normalizeSlashes2(isAbsolute32(raw) ? resolve32(raw) : resolve32(root, raw));
18586
18952
  }
18587
18953
  function tokenize(text, minLength) {
18588
18954
  const tokens = [];
@@ -18612,7 +18978,7 @@ function shouldIndexFile(filePath, cfg) {
18612
18978
  var INDEX_BATCH_SIZE = 32;
18613
18979
  var YIELD_EVERY_FILES = 64;
18614
18980
  function yieldEventLoop() {
18615
- return new Promise((resolve34) => setImmediate(resolve34));
18981
+ return new Promise((resolve36) => setImmediate(resolve36));
18616
18982
  }
18617
18983
  function addFileToIndex(relPath, content, size, cfg) {
18618
18984
  if (!state55.index || content.includes("\0")) return;
@@ -18640,7 +19006,7 @@ async function indexFileFromStats(absPath, relPath, stats, cfg) {
18640
19006
  if (!shouldIndexFile(relPath, cfg) || !stats.isFile() || stats.size > cfg.maxFileBytes) return;
18641
19007
  let content;
18642
19008
  try {
18643
- content = await fsp.readFile(absPath, "utf-8");
19009
+ content = await fs2.readFile(absPath, "utf-8");
18644
19010
  } catch {
18645
19011
  return;
18646
19012
  }
@@ -18656,7 +19022,7 @@ async function flushFileBatch(batch, cfg) {
18656
19022
  async function walkDirectory(absPath, cfg, excludes, fileBatch) {
18657
19023
  let entries;
18658
19024
  try {
18659
- entries = await fsp.readdir(absPath, { withFileTypes: true });
19025
+ entries = await fs2.readdir(absPath, { withFileTypes: true });
18660
19026
  } catch {
18661
19027
  return;
18662
19028
  }
@@ -18666,8 +19032,8 @@ async function walkDirectory(absPath, cfg, excludes, fileBatch) {
18666
19032
  state55.truncated = true;
18667
19033
  return;
18668
19034
  }
18669
- const absChild = normalizeSlashes2(resolve(absPath, ent.name));
18670
- const relChild = normalizeSlashes2(relative(root, absChild));
19035
+ const absChild = normalizeSlashes2(resolve32(absPath, ent.name));
19036
+ const relChild = normalizeSlashes2(relative31(root, absChild));
18671
19037
  if (relChild === "" || relChild === ".") continue;
18672
19038
  if (excludes.some((re) => re.test(relChild))) continue;
18673
19039
  if (ent.isDirectory()) {
@@ -18678,7 +19044,7 @@ async function walkDirectory(absPath, cfg, excludes, fileBatch) {
18678
19044
  if (!shouldIndexFile(relChild, cfg)) continue;
18679
19045
  let stats;
18680
19046
  try {
18681
- stats = await fsp.stat(absChild);
19047
+ stats = await fs2.stat(absChild);
18682
19048
  } catch {
18683
19049
  continue;
18684
19050
  }
@@ -18703,13 +19069,13 @@ async function buildIndex(rootPath, cfg) {
18703
19069
  const excludes = compileExcludes(cfg.excludePatterns);
18704
19070
  let rootStats;
18705
19071
  try {
18706
- rootStats = await fsp.stat(rootPath);
19072
+ rootStats = await fs2.stat(rootPath);
18707
19073
  } catch {
18708
19074
  state55.termCount = 0;
18709
19075
  return;
18710
19076
  }
18711
19077
  if (rootStats.isFile()) {
18712
- const relPath = normalizeSlashes2(relative(normalizeSlashes2(process.cwd()), rootPath));
19078
+ const relPath = normalizeSlashes2(relative31(normalizeSlashes2(process.cwd()), rootPath));
18713
19079
  await indexFileFromStats(rootPath, relPath === "" ? "." : relPath, rootStats, cfg);
18714
19080
  state55.fileCount = state55.index.files.size;
18715
19081
  } else if (rootStats.isDirectory()) {
@@ -18869,6 +19235,13 @@ var plugin58 = {
18869
19235
  state55.queryCount = 0;
18870
19236
  state55.reindexCount = 0;
18871
19237
  state55.buildPromise = null;
19238
+ if (state55.hookUnregister) {
19239
+ try {
19240
+ state55.hookUnregister();
19241
+ } catch {
19242
+ }
19243
+ state55.hookUnregister = null;
19244
+ }
18872
19245
  const cfg = readConfig50(api.config.extensions?.["semantic-search-indexer"]);
18873
19246
  api.tools.register({
18874
19247
  name: "semantic_search",
@@ -18954,6 +19327,13 @@ var plugin58 = {
18954
19327
  });
18955
19328
  },
18956
19329
  teardown(api) {
19330
+ if (state55.hookUnregister) {
19331
+ try {
19332
+ state55.hookUnregister();
19333
+ } catch {
19334
+ }
19335
+ state55.hookUnregister = null;
19336
+ }
18957
19337
  const final = {
18958
19338
  fileCount: state55.fileCount,
18959
19339
  termCount: state55.termCount,
@@ -18986,6 +19366,10 @@ var plugin58 = {
18986
19366
  }
18987
19367
  };
18988
19368
  var semantic_search_indexer_default = plugin58;
19369
+
19370
+ // src/smart-rename/index.ts
19371
+ import { readFileSync as readFileSync22, writeFileSync as writeFileSync7 } from "node:fs";
19372
+ import { extname as extname9, isAbsolute as isAbsolute33, relative as relative32, resolve as resolve33 } from "node:path";
18989
19373
  var API_VERSION39 = "^0.1.10";
18990
19374
  var state56 = {
18991
19375
  renameCount: 0,
@@ -19007,18 +19391,18 @@ function readConfig51(raw) {
19007
19391
  function withinProject24(p) {
19008
19392
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
19009
19393
  const root = process.cwd();
19010
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
19011
- const rel = relative(root, resolved);
19394
+ const resolved = isAbsolute33(p) ? resolve33(p) : resolve33(root, p);
19395
+ const rel = relative32(root, resolved);
19012
19396
  if (rel === "" || rel === ".") return true;
19013
19397
  if (rel.startsWith("..")) return false;
19014
- if (isAbsolute(rel)) return false;
19398
+ if (isAbsolute33(rel)) return false;
19015
19399
  return true;
19016
19400
  }
19017
19401
  function toPosix7(p) {
19018
19402
  return p.replace(/\\/g, "/");
19019
19403
  }
19020
19404
  function relativePath7(p) {
19021
- return toPosix7(relative(process.cwd(), p));
19405
+ return toPosix7(relative32(process.cwd(), p));
19022
19406
  }
19023
19407
  function escapeRegex2(s) {
19024
19408
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -19089,14 +19473,14 @@ var plugin59 = {
19089
19473
  if (!withinProject24(rawPath)) {
19090
19474
  return { ok: false, error: "path is outside the project root" };
19091
19475
  }
19092
- const ext = extname(rawPath).toLowerCase();
19476
+ const ext = extname9(rawPath).toLowerCase();
19093
19477
  if (!cfg.extensions.includes(ext)) {
19094
19478
  return { ok: false, error: `extension ${ext} is not allowed for rename` };
19095
19479
  }
19096
- const resolved = resolve(process.cwd(), rawPath);
19480
+ const resolved = resolve33(process.cwd(), rawPath);
19097
19481
  let content;
19098
19482
  try {
19099
- content = readFileSync(resolved, "utf-8");
19483
+ content = readFileSync22(resolved, "utf-8");
19100
19484
  } catch (err) {
19101
19485
  state56.errorCount += 1;
19102
19486
  return { ok: false, error: String(err) };
@@ -19106,7 +19490,7 @@ var plugin59 = {
19106
19490
  state56.replacementCount += replacements;
19107
19491
  if (input.apply) {
19108
19492
  try {
19109
- writeFileSync(resolved, preview, "utf-8");
19493
+ writeFileSync7(resolved, preview, "utf-8");
19110
19494
  } catch (err) {
19111
19495
  state56.errorCount += 1;
19112
19496
  return { ok: false, error: String(err) };
@@ -19150,6 +19534,12 @@ var plugin59 = {
19150
19534
  }
19151
19535
  };
19152
19536
  var smart_rename_default = plugin59;
19537
+
19538
+ // src/test-flake-detector/index.ts
19539
+ import { execFileSync as execFileSync12 } from "node:child_process";
19540
+ import { readFileSync as readFileSync23 } from "node:fs";
19541
+ import { createRequire } from "node:module";
19542
+ import { dirname as dirname7, isAbsolute as isAbsolute34, relative as relative33, resolve as resolve34 } from "node:path";
19153
19543
  var API_VERSION40 = "^0.1.10";
19154
19544
  var state57 = {
19155
19545
  invocationCount: 0,
@@ -19209,19 +19599,95 @@ function parseTestOutput(output) {
19209
19599
  }
19210
19600
  return { passed, failed };
19211
19601
  }
19212
- function buildCommand(baseCommand, testPattern) {
19213
- const trimmedBase = baseCommand.trim();
19214
- if (!testPattern) return trimmedBase;
19215
- if (trimmedBase.includes(testPattern)) return trimmedBase;
19216
- return `${trimmedBase} ${testPattern}`;
19602
+ var TEST_RUNNERS = /* @__PURE__ */ new Set(["vitest", "jest", "mocha"]);
19603
+ var ALLOWED_RUNNER_FLAGS = /* @__PURE__ */ new Set([
19604
+ "run",
19605
+ "--run",
19606
+ "--runInBand",
19607
+ "--passWithNoTests",
19608
+ "--reporter=verbose",
19609
+ "--reporter=default"
19610
+ ]);
19611
+ function withinProject25(p) {
19612
+ if (p.length === 0 || p.length > 4096 || p.startsWith("-")) return false;
19613
+ const root = resolve34(process.cwd());
19614
+ const resolved = isAbsolute34(p) ? resolve34(p) : resolve34(root, p);
19615
+ const rel = relative33(root, resolved);
19616
+ return rel === "" || !rel.startsWith("..") && !isAbsolute34(rel);
19617
+ }
19618
+ function isInside(parent, child) {
19619
+ if (parent === child) return true;
19620
+ const rel = relative33(parent, child);
19621
+ return rel !== "" && !rel.startsWith("..") && !isAbsolute34(rel);
19622
+ }
19623
+ function tokenizeCommand(command) {
19624
+ const trimmed = command.trim();
19625
+ if (!trimmed || /["'`;&|<>\r\n]/.test(trimmed)) return null;
19626
+ return trimmed.split(/\s+/).filter(Boolean);
19627
+ }
19628
+ function resolveTestCommand(baseCommand, testPattern) {
19629
+ const tokens = tokenizeCommand(baseCommand);
19630
+ if (!tokens) return null;
19631
+ let runner;
19632
+ let runnerArgs;
19633
+ const [head, second, third, ...rest] = tokens;
19634
+ if (TEST_RUNNERS.has(head ?? "")) {
19635
+ runner = head;
19636
+ runnerArgs = tokens.slice(1);
19637
+ } else if (head === "npx" && TEST_RUNNERS.has(second ?? "")) {
19638
+ runner = second;
19639
+ runnerArgs = tokens.slice(2);
19640
+ } else if (head === "pnpm" && (second === "exec" || second === "dlx") && TEST_RUNNERS.has(third ?? "")) {
19641
+ runner = third;
19642
+ runnerArgs = rest;
19643
+ } else if (head === "pnpm" && TEST_RUNNERS.has(second ?? "")) {
19644
+ runner = second;
19645
+ runnerArgs = tokens.slice(2);
19646
+ } else if (head === "npm" && second === "exec" && TEST_RUNNERS.has(third ?? "")) {
19647
+ runner = third;
19648
+ runnerArgs = rest;
19649
+ } else if (head === "yarn" && TEST_RUNNERS.has(second ?? "")) {
19650
+ runner = second;
19651
+ runnerArgs = tokens.slice(2);
19652
+ } else {
19653
+ return null;
19654
+ }
19655
+ if (runnerArgs.some((arg) => !ALLOWED_RUNNER_FLAGS.has(arg))) return null;
19656
+ let resolvedEntry;
19657
+ try {
19658
+ const requireFromProject = createRequire(resolve34(process.cwd(), "package.json"));
19659
+ const packagePath = requireFromProject.resolve(`${runner}/package.json`);
19660
+ const packageJson = JSON.parse(readFileSync23(packagePath, "utf8"));
19661
+ const relativeBin = typeof packageJson.bin === "string" ? packageJson.bin : packageJson.bin?.[runner] ?? Object.values(packageJson.bin ?? {})[0];
19662
+ if (!relativeBin) return null;
19663
+ const packageDir = dirname7(packagePath);
19664
+ const candidate = resolve34(packageDir, relativeBin);
19665
+ if (isAbsolute34(relativeBin) || !isInside(packageDir, candidate)) {
19666
+ return null;
19667
+ }
19668
+ resolvedEntry = candidate;
19669
+ } catch {
19670
+ return null;
19671
+ }
19672
+ const args = [resolvedEntry, ...runnerArgs];
19673
+ if (testPattern) {
19674
+ if (!withinProject25(testPattern)) return null;
19675
+ args.push(testPattern);
19676
+ }
19677
+ return {
19678
+ cmd: process.execPath,
19679
+ args,
19680
+ display: [...tokens, ...testPattern ? [testPattern] : []].join(" ")
19681
+ };
19217
19682
  }
19218
19683
  function runOnce(command, timeoutMs) {
19219
19684
  try {
19220
- const output = execSync(command, {
19685
+ const output = execFileSync12(command.cmd, command.args, {
19221
19686
  encoding: "utf-8",
19222
19687
  timeout: timeoutMs,
19223
19688
  cwd: process.cwd(),
19224
- stdio: ["pipe", "pipe", "pipe"]
19689
+ stdio: ["pipe", "pipe", "pipe"],
19690
+ shell: false
19225
19691
  });
19226
19692
  return { output };
19227
19693
  } catch (err) {
@@ -19306,10 +19772,16 @@ var plugin60 = {
19306
19772
  return { ok: false, error: "test-flake-detector is disabled" };
19307
19773
  }
19308
19774
  const requestedRuns = typeof input.runs === "number" && input.runs >= 1 ? Math.min(Math.floor(input.runs), cfg.maxRuns) : 5;
19309
- const command = buildCommand(
19775
+ const command = resolveTestCommand(
19310
19776
  typeof input.command === "string" && input.command.trim().length > 0 ? input.command : cfg.defaultCommand,
19311
19777
  input.testPattern
19312
19778
  );
19779
+ if (!command) {
19780
+ return {
19781
+ ok: false,
19782
+ error: "Unsupported test command or unsafe testPattern. Use vitest, jest, or mocha through a supported package runner, and keep patterns inside the project."
19783
+ };
19784
+ }
19313
19785
  state57.invocationCount += 1;
19314
19786
  const start = Date.now();
19315
19787
  const records = /* @__PURE__ */ new Map();
@@ -19351,7 +19823,7 @@ var plugin60 = {
19351
19823
  };
19352
19824
  return {
19353
19825
  ok: true,
19354
- command,
19826
+ command: command.display,
19355
19827
  runsRequested: requestedRuns,
19356
19828
  runsCompleted,
19357
19829
  durationMs,
@@ -19419,6 +19891,10 @@ var plugin60 = {
19419
19891
  }
19420
19892
  };
19421
19893
  var test_flake_detector_default = plugin60;
19894
+
19895
+ // src/test-generator/index.ts
19896
+ import { readFileSync as readFileSync24 } from "node:fs";
19897
+ import { isAbsolute as isAbsolute35, relative as relative34, resolve as resolve35 } from "node:path";
19422
19898
  var API_VERSION41 = "^0.1.10";
19423
19899
  var state58 = {
19424
19900
  generateCount: 0,
@@ -19441,21 +19917,21 @@ function readConfig53(raw) {
19441
19917
  includeImports: r["includeImports"] !== false
19442
19918
  };
19443
19919
  }
19444
- function withinProject25(p) {
19920
+ function withinProject26(p) {
19445
19921
  if (typeof p !== "string" || p.length === 0 || p.length > 4096) return false;
19446
19922
  const root = process.cwd();
19447
- const resolved = isAbsolute(p) ? resolve(p) : resolve(root, p);
19448
- const rel = relative(root, resolved);
19923
+ const resolved = isAbsolute35(p) ? resolve35(p) : resolve35(root, p);
19924
+ const rel = relative34(root, resolved);
19449
19925
  if (rel === "" || rel === ".") return true;
19450
19926
  if (rel.startsWith("..")) return false;
19451
- if (isAbsolute(rel)) return false;
19927
+ if (isAbsolute35(rel)) return false;
19452
19928
  return true;
19453
19929
  }
19454
19930
  function toPosix8(p) {
19455
19931
  return p.replace(/\\/g, "/");
19456
19932
  }
19457
19933
  function relativePath8(p) {
19458
- return toPosix8(relative(process.cwd(), p));
19934
+ return toPosix8(relative34(process.cwd(), p));
19459
19935
  }
19460
19936
  function detectExports(content) {
19461
19937
  const exports = [];
@@ -19464,31 +19940,30 @@ function detectExports(content) {
19464
19940
  const arrowRe = /export\s+(?:const|let|var)\s+([A-Za-z_$][A-Za-z0-9_$]*)\s*=\s*(?:\([^)]*\)|[A-Za-z_$][\w$]*)\s*=>/g;
19465
19941
  const classRe = /export\s+(?:abstract\s+)?class\s+([A-Za-z_$][A-Za-z0-9_$]*)/g;
19466
19942
  const namedRe = /export\s*\{([^}]+)\}/g;
19467
- let m;
19468
19943
  functionRe.lastIndex = 0;
19469
- while ((m = functionRe.exec(content)) !== null) {
19470
- if (!seen.has(m[1])) {
19471
- seen.add(m[1]);
19472
- exports.push({ name: m[1], kind: "function" });
19944
+ for (const match of content.matchAll(functionRe)) {
19945
+ if (!seen.has(match[1])) {
19946
+ seen.add(match[1]);
19947
+ exports.push({ name: match[1], kind: "function" });
19473
19948
  }
19474
19949
  }
19475
19950
  arrowRe.lastIndex = 0;
19476
- while ((m = arrowRe.exec(content)) !== null) {
19477
- if (!seen.has(m[1])) {
19478
- seen.add(m[1]);
19479
- exports.push({ name: m[1], kind: "arrow" });
19951
+ for (const match of content.matchAll(arrowRe)) {
19952
+ if (!seen.has(match[1])) {
19953
+ seen.add(match[1]);
19954
+ exports.push({ name: match[1], kind: "arrow" });
19480
19955
  }
19481
19956
  }
19482
19957
  classRe.lastIndex = 0;
19483
- while ((m = classRe.exec(content)) !== null) {
19484
- if (!seen.has(m[1])) {
19485
- seen.add(m[1]);
19486
- exports.push({ name: m[1], kind: "class" });
19958
+ for (const match of content.matchAll(classRe)) {
19959
+ if (!seen.has(match[1])) {
19960
+ seen.add(match[1]);
19961
+ exports.push({ name: match[1], kind: "class" });
19487
19962
  }
19488
19963
  }
19489
19964
  namedRe.lastIndex = 0;
19490
- while ((m = namedRe.exec(content)) !== null) {
19491
- const names = m[1].split(",").map((s) => s.trim()).filter(Boolean);
19965
+ for (const match of content.matchAll(namedRe)) {
19966
+ const names = match[1].split(",").map((s) => s.trim()).filter(Boolean);
19492
19967
  for (const raw of names) {
19493
19968
  const parts = raw.split(/\s+as\s+/);
19494
19969
  const name = (parts.length > 1 ? parts[parts.length - 1] : raw).trim();
@@ -19536,7 +20011,7 @@ function generateTestContent(filePath, detected, cfg) {
19536
20011
  return lines.join("\n");
19537
20012
  }
19538
20013
  function generateForFile(filePath, cfg) {
19539
- const content = readFileSync(filePath, "utf-8");
20014
+ const content = readFileSync24(filePath, "utf-8");
19540
20015
  const detected = detectExports(content);
19541
20016
  const sourceName = relativePath8(filePath).split("/").pop();
19542
20017
  const baseName = sourceName.replace(/\.[^.]+$/, "");
@@ -19603,10 +20078,10 @@ var plugin61 = {
19603
20078
  if (!rawPath || typeof rawPath !== "string") {
19604
20079
  return { ok: false, error: "path is required" };
19605
20080
  }
19606
- if (!withinProject25(rawPath)) {
20081
+ if (!withinProject26(rawPath)) {
19607
20082
  return { ok: false, error: "path is outside the project root" };
19608
20083
  }
19609
- const resolved = resolve(process.cwd(), rawPath);
20084
+ const resolved = resolve35(process.cwd(), rawPath);
19610
20085
  state58.generateCount += 1;
19611
20086
  let result;
19612
20087
  try {
@@ -19936,9 +20411,9 @@ var plugin62 = {
19936
20411
  state59.postInvocations += 1;
19937
20412
  let content;
19938
20413
  try {
19939
- const stat4 = await fsp.stat(filePath);
20414
+ const stat4 = await fs3.stat(filePath);
19940
20415
  if (!stat4.isFile()) return;
19941
- content = await fsp.readFile(filePath, "utf-8");
20416
+ content = await fs3.readFile(filePath, "utf-8");
19942
20417
  } catch {
19943
20418
  state59.readErrorCount += 1;
19944
20419
  return;
@@ -20070,5 +20545,68 @@ ${lines}${overflowNote}`
20070
20545
  }
20071
20546
  };
20072
20547
  var spec_linker_default = plugin62;
20073
-
20074
- export { accessibility_auditor_default as accessibilityAuditorPlugin, agent_handoff_default as agentHandoffPlugin, api_compatibility_gate_default as apiCompatibilityGatePlugin, auto_doc_default as autoDocPlugin, auto_escalate_default as autoEscalatePlugin, auto_i18n_extractor_default as autoI18nExtractorPlugin, branch_guard_default as branchGuardPlugin, changelog_writer_default as changelogWriterPlugin, checkpoint_default as checkpointPlugin, code_metrics_default as codeMetricsPlugin, commit_validator_default as commitValidatorPlugin, config_validator_default as configValidatorPlugin, context_pins_default as contextPinsPlugin, cost_tracker_default as costTrackerPlugin, cron_default as cronPlugin, dead_code_detector_default as deadCodeDetectorPlugin, dep_guard_default as depGuardPlugin, dependency_vulnerability_gate_default as dependencyVulnerabilityGatePlugin, diff_summary_default as diffSummaryPlugin, doc_sync_guard_default as docSyncGuardPlugin, duplicate_code_detector_default as duplicateCodeDetectorPlugin, error_lens_default as errorLensPlugin, feature_flag_tracker_default as featureFlagTrackerPlugin, file_watcher_default as fileWatcherPlugin, format_on_save_default as formatOnSavePlugin, git_autocommit_default as gitAutocommitPlugin, import_organizer_default as importOrganizerPlugin, injection_shield_default as injectionShieldPlugin, interface_contract_guard_default as interfaceContractGuardPlugin, knowledge_graph_default as knowledgeGraphPlugin, license_audit_gate_default as licenseAuditGatePlugin, lint_gate_default as lintGatePlugin, llm_cache_default as llmCachePlugin, loop_breaker_default as loopBreakerPlugin, migration_planner_default as migrationPlannerPlugin, model_router_default as modelRouterPlugin, notify_hub_default as notifyHubPlugin, path_guard_default as pathGuardPlugin, performance_regression_gate_default as performanceRegressionGatePlugin, plugin_stack_observer_default as pluginStackObserverPlugin, pr_drafter_default as prDrafterPlugin, prompt_firewall_default as promptFirewallPlugin, refactor_suggester_default as refactorSuggesterPlugin, release_notes_generator_default as releaseNotesGeneratorPlugin, schema_evolution_guard_default as schemaEvolutionGuardPlugin, secret_scanner_default as secretScannerPlugin, security_hotspot_scanner_default as securityHotspotScannerPlugin, semantic_search_indexer_default as semanticSearchIndexerPlugin, semver_bump_default as semverBumpPlugin, session_recap_default as sessionRecapPlugin, shell_check_default as shellCheckPlugin, smart_rename_default as smartRenamePlugin, spec_linker_default as specLinkerPlugin, template_engine_default as templateEnginePlugin, test_coverage_gate_default as testCoverageGatePlugin, test_flake_detector_default as testFlakeDetectorPlugin, test_generator_default as testGeneratorPlugin, test_runner_gate_default as testRunnerGatePlugin, todo_listener_default as todoListenerPlugin, todo_tracker_default as todoTrackerPlugin, token_budget_default as tokenBudgetPlugin, token_throttle_default as tokenThrottlePlugin, type_gate_default as typeGatePlugin };
20548
+ export {
20549
+ accessibility_auditor_default as accessibilityAuditorPlugin,
20550
+ agent_handoff_default as agentHandoffPlugin,
20551
+ api_compatibility_gate_default as apiCompatibilityGatePlugin,
20552
+ auto_doc_default as autoDocPlugin,
20553
+ auto_escalate_default as autoEscalatePlugin,
20554
+ auto_i18n_extractor_default as autoI18nExtractorPlugin,
20555
+ branch_guard_default as branchGuardPlugin,
20556
+ changelog_writer_default as changelogWriterPlugin,
20557
+ checkpoint_default as checkpointPlugin,
20558
+ code_metrics_default as codeMetricsPlugin,
20559
+ commit_validator_default as commitValidatorPlugin,
20560
+ config_validator_default as configValidatorPlugin,
20561
+ context_pins_default as contextPinsPlugin,
20562
+ cost_tracker_default as costTrackerPlugin,
20563
+ cron_default as cronPlugin,
20564
+ dead_code_detector_default as deadCodeDetectorPlugin,
20565
+ dep_guard_default as depGuardPlugin,
20566
+ dependency_vulnerability_gate_default as dependencyVulnerabilityGatePlugin,
20567
+ diff_summary_default as diffSummaryPlugin,
20568
+ doc_sync_guard_default as docSyncGuardPlugin,
20569
+ duplicate_code_detector_default as duplicateCodeDetectorPlugin,
20570
+ error_lens_default as errorLensPlugin,
20571
+ feature_flag_tracker_default as featureFlagTrackerPlugin,
20572
+ file_watcher_default as fileWatcherPlugin,
20573
+ format_on_save_default as formatOnSavePlugin,
20574
+ git_autocommit_default as gitAutocommitPlugin,
20575
+ import_organizer_default as importOrganizerPlugin,
20576
+ injection_shield_default as injectionShieldPlugin,
20577
+ interface_contract_guard_default as interfaceContractGuardPlugin,
20578
+ knowledge_graph_default as knowledgeGraphPlugin,
20579
+ license_audit_gate_default as licenseAuditGatePlugin,
20580
+ lint_gate_default as lintGatePlugin,
20581
+ llm_cache_default as llmCachePlugin,
20582
+ loop_breaker_default as loopBreakerPlugin,
20583
+ migration_planner_default as migrationPlannerPlugin,
20584
+ model_router_default as modelRouterPlugin,
20585
+ notify_hub_default as notifyHubPlugin,
20586
+ path_guard_default as pathGuardPlugin,
20587
+ performance_regression_gate_default as performanceRegressionGatePlugin,
20588
+ plugin_stack_observer_default as pluginStackObserverPlugin,
20589
+ pr_drafter_default as prDrafterPlugin,
20590
+ prompt_firewall_default as promptFirewallPlugin,
20591
+ refactor_suggester_default as refactorSuggesterPlugin,
20592
+ release_notes_generator_default as releaseNotesGeneratorPlugin,
20593
+ schema_evolution_guard_default as schemaEvolutionGuardPlugin,
20594
+ secret_scanner_default as secretScannerPlugin,
20595
+ security_hotspot_scanner_default as securityHotspotScannerPlugin,
20596
+ semantic_search_indexer_default as semanticSearchIndexerPlugin,
20597
+ semver_bump_default as semverBumpPlugin,
20598
+ session_recap_default as sessionRecapPlugin,
20599
+ shell_check_default as shellCheckPlugin,
20600
+ smart_rename_default as smartRenamePlugin,
20601
+ spec_linker_default as specLinkerPlugin,
20602
+ template_engine_default as templateEnginePlugin,
20603
+ test_coverage_gate_default as testCoverageGatePlugin,
20604
+ test_flake_detector_default as testFlakeDetectorPlugin,
20605
+ test_generator_default as testGeneratorPlugin,
20606
+ test_runner_gate_default as testRunnerGatePlugin,
20607
+ todo_listener_default as todoListenerPlugin,
20608
+ todo_tracker_default as todoTrackerPlugin,
20609
+ token_budget_default as tokenBudgetPlugin,
20610
+ token_throttle_default as tokenThrottlePlugin,
20611
+ type_gate_default as typeGatePlugin
20612
+ };