@wrongstack/plugins 0.284.1 → 0.285.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 +5 -5
  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 +5 -5
  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 +5 -5
  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 +5 -5
  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 +5 -5
  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 +946 -394
  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 +5 -5
  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 +5 -5
  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 +5 -5
  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 +5 -5
  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 +20100 -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 +5 -5
  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
@@ -0,0 +1,216 @@
1
+ // src/runtime/index.ts
2
+ import { execFile } from "node:child_process";
3
+ import { existsSync } from "node:fs";
4
+ import { basename, isAbsolute, relative, resolve } from "node:path";
5
+ var META_CHARS = /["'`;&|<>\r\n]/;
6
+ var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
7
+ function hasLeadingDash(arg) {
8
+ return arg.length > 0 && arg.startsWith("-");
9
+ }
10
+ function safeSplit(command) {
11
+ const trimmed = command.trim();
12
+ if (!trimmed || META_CHARS.test(trimmed)) return null;
13
+ return trimmed.split(/\s+/).filter(Boolean);
14
+ }
15
+ function withinProjectPath(projectRoot, candidate) {
16
+ if (candidate.length === 0 || candidate.length > 4096) return false;
17
+ if (hasLeadingDash(candidate)) return false;
18
+ const resolved = isAbsolute(candidate) ? resolve(candidate) : resolve(projectRoot, candidate);
19
+ const rel = relative(projectRoot, resolved);
20
+ return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
21
+ }
22
+ function everyFlagAllowed(allowed, args) {
23
+ for (const arg of args) {
24
+ if (!hasLeadingDash(arg)) continue;
25
+ if (allowed === null) return false;
26
+ if (!allowed.has(arg)) return false;
27
+ }
28
+ return true;
29
+ }
30
+ function sanitizeRunnerPath(value, options = {}) {
31
+ if (!value || hasLeadingDash(value)) return null;
32
+ const projectRoot = resolve(options.projectRoot ?? process.cwd());
33
+ if (!withinProjectPath(projectRoot, value)) return null;
34
+ return isAbsolute(value) ? resolve(value) : resolve(projectRoot, value);
35
+ }
36
+ function resolveRunnerCommand(runtime, command, options = {}) {
37
+ const tokens = safeSplit(command);
38
+ if (!tokens || tokens.length === 0) return null;
39
+ const projectRoot = resolve(options.projectRoot ?? process.cwd());
40
+ const launcher = runtime.packageManager;
41
+ const [head, second, ...rest] = tokens;
42
+ if (!head) return null;
43
+ const display = tokens.join(" ");
44
+ if (launcher !== "none" && tokens.length === 1 && head === launcher) {
45
+ return null;
46
+ }
47
+ if (head === runtime.executable) {
48
+ if (!everyFlagAllowed(runtime.allowedFlags, [second, ...rest].filter((v) => Boolean(v)))) {
49
+ return null;
50
+ }
51
+ return {
52
+ cmd: head,
53
+ args: [second, ...rest].filter((v) => Boolean(v)),
54
+ display
55
+ };
56
+ }
57
+ if (launcher !== "none" && head === launcher && runtime.subcommands.length === 0 && second === runtime.executable) {
58
+ if (!everyFlagAllowed(runtime.allowedFlags, rest)) return null;
59
+ return { cmd: head, args: [second, ...rest], display };
60
+ }
61
+ if (launcher !== "none" && head === launcher && runtime.subcommands.length > 0) {
62
+ const subcommand = runtime.subcommands[0];
63
+ const exe = rest[0];
64
+ if (second === subcommand && exe === runtime.executable) {
65
+ const tail = rest.slice(1);
66
+ if (!everyFlagAllowed(runtime.allowedFlags, tail)) return null;
67
+ return { cmd: head, args: [second, exe, ...tail], display };
68
+ }
69
+ }
70
+ if (isAbsolute(head)) {
71
+ if (!withinProjectPath(projectRoot, head)) return null;
72
+ const base = basename(head);
73
+ if (base !== runtime.executable && base !== launcher) return null;
74
+ if (second !== runtime.executable) return null;
75
+ if (!everyFlagAllowed(runtime.allowedFlags, rest)) return null;
76
+ return { cmd: head, args: [second, ...rest], display };
77
+ }
78
+ return null;
79
+ }
80
+ function runRunnerCommand(argv, options) {
81
+ if (argv.length === 0) {
82
+ return Promise.resolve({
83
+ code: null,
84
+ stdout: "",
85
+ stderr: "runtime helper: empty argv",
86
+ timedOut: false,
87
+ spawnError: true
88
+ });
89
+ }
90
+ return new Promise((resolvePromise) => {
91
+ const projectRoot = resolve(options.projectRoot ?? process.cwd());
92
+ const trimmedCwd = options.cwd.trim();
93
+ if (!withinProjectPath(projectRoot, trimmedCwd)) {
94
+ resolvePromise({
95
+ code: null,
96
+ stdout: "",
97
+ stderr: "runtime helper: cwd outside project",
98
+ timedOut: false,
99
+ spawnError: true
100
+ });
101
+ return;
102
+ }
103
+ let timedOut = false;
104
+ let spawnErrored = false;
105
+ const stdoutChunks = [];
106
+ const stderrChunks = [];
107
+ let stdoutBytes = 0;
108
+ let stderrBytes = 0;
109
+ const child = execFile(
110
+ argv[0],
111
+ argv.slice(1),
112
+ {
113
+ cwd: trimmedCwd,
114
+ timeout: options.timeoutMs,
115
+ signal: options.signal,
116
+ maxBuffer: MAX_BUFFER_BYTES,
117
+ windowsHide: true,
118
+ shell: false
119
+ },
120
+ (err, stdout, stderr) => {
121
+ if (timedOut) {
122
+ resolvePromise({
123
+ code: null,
124
+ stdout: Buffer.concat([...stdoutChunks, ...Buffer.isBuffer(stdout) ? [stdout] : [Buffer.from(stdout)]]).toString("utf8"),
125
+ stderr: Buffer.concat([...stderrChunks, ...Buffer.isBuffer(stderr) ? [stderr] : [Buffer.from(stderr)]]).toString("utf8"),
126
+ timedOut: true,
127
+ spawnError: false
128
+ });
129
+ return;
130
+ }
131
+ if (spawnErrored) {
132
+ resolvePromise({
133
+ code: 127,
134
+ stdout: Buffer.concat([...stdoutChunks, ...Buffer.isBuffer(stdout) ? [stdout] : [Buffer.from(stdout)]]).toString("utf8"),
135
+ stderr: Buffer.concat([...stderrChunks, ...Buffer.isBuffer(stderr) ? [stderr] : [Buffer.from(stderr)]]).toString("utf8"),
136
+ timedOut: false,
137
+ spawnError: true
138
+ });
139
+ return;
140
+ }
141
+ if (err) {
142
+ const anyErr = err;
143
+ const code = typeof anyErr.code === "number" ? anyErr.code : 1;
144
+ resolvePromise({
145
+ code,
146
+ stdout: Buffer.concat([
147
+ ...stdoutChunks,
148
+ ...anyErr.stdout ? [Buffer.isBuffer(anyErr.stdout) ? anyErr.stdout : Buffer.from(anyErr.stdout)] : []
149
+ ]).toString("utf8"),
150
+ stderr: Buffer.concat([
151
+ ...stderrChunks,
152
+ ...anyErr.stderr ? [Buffer.isBuffer(anyErr.stderr) ? anyErr.stderr : Buffer.from(anyErr.stderr)] : []
153
+ ]).toString("utf8"),
154
+ timedOut: false,
155
+ spawnError: false
156
+ });
157
+ return;
158
+ }
159
+ resolvePromise({
160
+ code: 0,
161
+ stdout: Buffer.concat([
162
+ ...stdoutChunks,
163
+ ...Buffer.isBuffer(stdout) ? [stdout] : [Buffer.from(stdout)]
164
+ ]).toString("utf8"),
165
+ stderr: Buffer.concat([
166
+ ...stderrChunks,
167
+ ...Buffer.isBuffer(stderr) ? [stderr] : [Buffer.from(stderr)]
168
+ ]).toString("utf8"),
169
+ timedOut: false,
170
+ spawnError: false
171
+ });
172
+ }
173
+ );
174
+ child.stdout?.on("data", (chunk) => {
175
+ stdoutBytes += chunk.length;
176
+ if (stdoutBytes <= MAX_BUFFER_BYTES) stdoutChunks.push(chunk);
177
+ });
178
+ child.stderr?.on("data", (chunk) => {
179
+ stderrBytes += chunk.length;
180
+ if (stderrBytes <= MAX_BUFFER_BYTES) stderrChunks.push(chunk);
181
+ });
182
+ child.on("error", (err) => {
183
+ if (err.code === "ENOENT" || err.code === "EPERM" || err.code === "EACCES") {
184
+ spawnErrored = true;
185
+ }
186
+ });
187
+ });
188
+ }
189
+ async function probeRunner(runtime, probeArg = "--version", options) {
190
+ const resolved = resolveRunnerCommand(runtime, `${runtime.executable} ${probeArg}`, options);
191
+ if (!resolved) return false;
192
+ const result = await runRunnerCommand([resolved.cmd, ...resolved.args], {
193
+ ...options,
194
+ timeoutMs: Math.min(options.timeoutMs, 5e3)
195
+ });
196
+ return result.code === 0;
197
+ }
198
+ function locateRunnerEntry(runtime, projectRoot) {
199
+ const root = resolve(projectRoot);
200
+ const candidates = [
201
+ resolve(root, "node_modules", ".bin", runtime.executable),
202
+ resolve(root, "node_modules", ".bin", `${runtime.executable}.cmd`),
203
+ resolve(root, "node_modules", ".bin", `${runtime.executable}.ps1`)
204
+ ];
205
+ for (const c of candidates) {
206
+ if (existsSync(c)) return c;
207
+ }
208
+ return null;
209
+ }
210
+ export {
211
+ locateRunnerEntry,
212
+ probeRunner,
213
+ resolveRunnerCommand,
214
+ runRunnerCommand,
215
+ sanitizeRunnerPath
216
+ };
@@ -0,0 +1,40 @@
1
+ /**
2
+ * schema-evolution-guard plugin — guards database/API schema changes.
3
+ *
4
+ * Registers a `PostToolUse` hook on `write|edit` that scans files matching
5
+ * schema-related patterns for destructive changes:
6
+ *
7
+ * - DROP TABLE / DROP COLUMN (Prisma migrations, raw SQL)
8
+ * - NOT NULL added without a default (SQL)
9
+ * - Required field without a default (Prisma, TypeScript schema files)
10
+ * - Required field added to an OpenAPI schema (YAML/JSON)
11
+ *
12
+ * When a destructive pattern is found the plugin either injects an
13
+ * `additionalContext` warning or blocks the tool, depending on `failSeverity`.
14
+ *
15
+ * Tools registered:
16
+ * - schema_evolution_status : counters + config snapshot.
17
+ *
18
+ * Config (`config.extensions['schema-evolution-guard']`):
19
+ *
20
+ * ```jsonc
21
+ * {
22
+ * "enabled": true,
23
+ * "failSeverity": "warn", // "warn" | "block"
24
+ * "maxFindings": 5,
25
+ * "filePatterns": [
26
+ * "*.prisma",
27
+ * "*migration*.sql",
28
+ * "*openapi*.yaml",
29
+ * "*openapi*.json",
30
+ * "*schema*.ts"
31
+ * ]
32
+ * }
33
+ * ```
34
+ *
35
+ * @public
36
+ */
37
+ import type { Plugin } from '@wrongstack/core';
38
+ declare const plugin: Plugin;
39
+ export default plugin;
40
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schema-evolution-guard/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAkN/C,QAAA,MAAM,MAAM,EAAE,MAgNb,CAAC;eAEa,MAAM"}
@@ -1,42 +1,2 @@
1
- import { Plugin } from '@wrongstack/core';
2
-
3
- /**
4
- * schema-evolution-guard plugin — guards database/API schema changes.
5
- *
6
- * Registers a `PostToolUse` hook on `write|edit` that scans files matching
7
- * schema-related patterns for destructive changes:
8
- *
9
- * - DROP TABLE / DROP COLUMN (Prisma migrations, raw SQL)
10
- * - NOT NULL added without a default (SQL)
11
- * - Required field without a default (Prisma, TypeScript schema files)
12
- * - Required field added to an OpenAPI schema (YAML/JSON)
13
- *
14
- * When a destructive pattern is found the plugin either injects an
15
- * `additionalContext` warning or blocks the tool, depending on `failSeverity`.
16
- *
17
- * Tools registered:
18
- * - schema_evolution_status : counters + config snapshot.
19
- *
20
- * Config (`config.extensions['schema-evolution-guard']`):
21
- *
22
- * ```jsonc
23
- * {
24
- * "enabled": true,
25
- * "failSeverity": "warn", // "warn" | "block"
26
- * "maxFindings": 5,
27
- * "filePatterns": [
28
- * "*.prisma",
29
- * "*migration*.sql",
30
- * "*openapi*.yaml",
31
- * "*openapi*.json",
32
- * "*schema*.ts"
33
- * ]
34
- * }
35
- * ```
36
- *
37
- * @public
38
- */
39
-
40
- declare const plugin: Plugin;
41
-
42
- export { plugin as default };
1
+ export * from './schema-evolution-guard/index.js';
2
+ export { default } from './schema-evolution-guard/index.js';
@@ -1,7 +1,6 @@
1
- import { readFileSync } from 'fs';
2
- import { basename, isAbsolute, resolve, relative } from 'path';
3
-
4
1
  // src/schema-evolution-guard/index.ts
2
+ import { readFileSync } from "node:fs";
3
+ import { basename, isAbsolute, relative, resolve } from "node:path";
5
4
  var API_VERSION = "^0.1.10";
6
5
  var state = {
7
6
  invocationCount: 0,
@@ -315,5 +314,6 @@ ${body}${suffix}`;
315
314
  }
316
315
  };
317
316
  var schema_evolution_guard_default = plugin;
318
-
319
- export { schema_evolution_guard_default as default };
317
+ export {
318
+ schema_evolution_guard_default as default
319
+ };
@@ -0,0 +1,32 @@
1
+ /**
2
+ * secret-scanner plugin — Pre-tool and post-tool hooks that block, redact,
3
+ * or warn about plaintext credentials flowing into or out of tools.
4
+ *
5
+ * Tools registered:
6
+ * - secret_scanner_status : Show which patterns are active, recent
7
+ * blocks/leaks, and current mode.
8
+ * - secret_scanner_test : Run the scanner against a user-supplied
9
+ * string and report which patterns matched.
10
+ *
11
+ * Hooks registered:
12
+ * - PreToolUse with matcher `bash|write|edit` (configurable). Default
13
+ * action is to BLOCK; the plugin can also auto-redact the offending
14
+ * fields via `HookOutcome.modifiedInput`.
15
+ * - PostToolUse with matcher `*` (configurable via `postToolUseMatcher`).
16
+ * Scans tool OUTPUT for secrets that leaked through. Since the tool
17
+ * has already run, the hook cannot block — instead it injects an
18
+ * `additionalContext` warning so the LLM knows the output contains
19
+ * a secret and should NOT echo it, store it, or commit it.
20
+ *
21
+ * Why a separate plugin from the built-in `DefaultSecretScrubber`?
22
+ * The scrubber is *output* sanitization (replace secrets with
23
+ * `[REDACTED:type]` before they leave the system). The scanner is
24
+ * *prevention* (stop the tool from running with a secret in the first
25
+ * place) + *detection* (flag secrets that leaked through the output).
26
+ * They share the same threat model but act at different points in the
27
+ * pipeline.
28
+ */
29
+ import type { Plugin } from '@wrongstack/core';
30
+ declare const plugin: Plugin;
31
+ export default plugin;
32
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/secret-scanner/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAua/C,QAAA,MAAM,MAAM,EAAE,MAgOb,CAAC;eAEa,MAAM"}
@@ -1,34 +1,2 @@
1
- import { Plugin } from '@wrongstack/core';
2
-
3
- /**
4
- * secret-scanner plugin — Pre-tool and post-tool hooks that block, redact,
5
- * or warn about plaintext credentials flowing into or out of tools.
6
- *
7
- * Tools registered:
8
- * - secret_scanner_status : Show which patterns are active, recent
9
- * blocks/leaks, and current mode.
10
- * - secret_scanner_test : Run the scanner against a user-supplied
11
- * string and report which patterns matched.
12
- *
13
- * Hooks registered:
14
- * - PreToolUse with matcher `bash|write|edit` (configurable). Default
15
- * action is to BLOCK; the plugin can also auto-redact the offending
16
- * fields via `HookOutcome.modifiedInput`.
17
- * - PostToolUse with matcher `*` (configurable via `postToolUseMatcher`).
18
- * Scans tool OUTPUT for secrets that leaked through. Since the tool
19
- * has already run, the hook cannot block — instead it injects an
20
- * `additionalContext` warning so the LLM knows the output contains
21
- * a secret and should NOT echo it, store it, or commit it.
22
- *
23
- * Why a separate plugin from the built-in `DefaultSecretScrubber`?
24
- * The scrubber is *output* sanitization (replace secrets with
25
- * `[REDACTED:type]` before they leave the system). The scanner is
26
- * *prevention* (stop the tool from running with a secret in the first
27
- * place) + *detection* (flag secrets that leaked through the output).
28
- * They share the same threat model but act at different points in the
29
- * pipeline.
30
- */
31
-
32
- declare const plugin: Plugin;
33
-
34
- export { plugin as default };
1
+ export * from './secret-scanner/index.js';
2
+ export { default } from './secret-scanner/index.js';
@@ -420,5 +420,6 @@ var plugin = {
420
420
  }
421
421
  };
422
422
  var secret_scanner_default = plugin;
423
-
424
- export { secret_scanner_default as default };
423
+ export {
424
+ secret_scanner_default as default
425
+ };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * security-hotspot-scanner plugin — scans source code for common security
3
+ * anti-patterns and reports them via tools + a PostToolUse hook.
4
+ *
5
+ * Tools registered:
6
+ * - security_hotspot_scan : scan a file or directory for security hotspots
7
+ * - security_hotspot_status : config + per-session counters
8
+ *
9
+ * Hooks registered:
10
+ * - PostToolUse with matcher `write|edit` to warn about newly introduced hotspots.
11
+ *
12
+ * Config (`config.extensions['security-hotspot-scanner']`):
13
+ *
14
+ * ```jsonc
15
+ * {
16
+ * "enabled": true,
17
+ * "severity": "warn", // "warn" | "block"
18
+ * "maxFindings": 10,
19
+ * "scanOnChange": [".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs", ".py"]
20
+ * }
21
+ * ```
22
+ *
23
+ * @public
24
+ */
25
+ import type { Plugin } from '@wrongstack/core';
26
+ declare const plugin: Plugin;
27
+ export default plugin;
28
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/security-hotspot-scanner/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAwQ/C,QAAA,MAAM,MAAM,EAAE,MAiQb,CAAC;eAEa,MAAM"}
@@ -1,30 +1,2 @@
1
- import { Plugin } from '@wrongstack/core';
2
-
3
- /**
4
- * security-hotspot-scanner plugin — scans source code for common security
5
- * anti-patterns and reports them via tools + a PostToolUse hook.
6
- *
7
- * Tools registered:
8
- * - security_hotspot_scan : scan a file or directory for security hotspots
9
- * - security_hotspot_status : config + per-session counters
10
- *
11
- * Hooks registered:
12
- * - PostToolUse with matcher `write|edit` to warn about newly introduced hotspots.
13
- *
14
- * Config (`config.extensions['security-hotspot-scanner']`):
15
- *
16
- * ```jsonc
17
- * {
18
- * "enabled": true,
19
- * "severity": "warn", // "warn" | "block"
20
- * "maxFindings": 10,
21
- * "scanOnChange": [".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs", ".py"]
22
- * }
23
- * ```
24
- *
25
- * @public
26
- */
27
-
28
- declare const plugin: Plugin;
29
-
30
- export { plugin as default };
1
+ export * from './security-hotspot-scanner/index.js';
2
+ export { default } from './security-hotspot-scanner/index.js';
@@ -1,7 +1,6 @@
1
- import { statSync, readdirSync, readFileSync } from 'fs';
2
- import { isAbsolute, resolve, relative } from 'path';
3
-
4
1
  // src/security-hotspot-scanner/index.ts
2
+ import { readdirSync, readFileSync, statSync } from "node:fs";
3
+ import { isAbsolute, relative, resolve } from "node:path";
5
4
  var API_VERSION = "^0.1.10";
6
5
  var state = {
7
6
  scanCount: 0,
@@ -398,5 +397,6 @@ Review or remove the risky pattern(s).`;
398
397
  }
399
398
  };
400
399
  var security_hotspot_scanner_default = plugin;
401
-
402
- export { security_hotspot_scanner_default as default };
400
+ export {
401
+ security_hotspot_scanner_default as default
402
+ };
@@ -0,0 +1,36 @@
1
+ /**
2
+ * semantic-search-indexer plugin — lightweight keyword-based search over
3
+ * project source files.
4
+ *
5
+ * The plugin builds an in-memory inverted index (no persistence, no
6
+ * embeddings) and exposes two tools:
7
+ *
8
+ * - `semantic_search` — ranked keyword search with TF scoring
9
+ * - `semantic_index_status` — index counters and configuration
10
+ *
11
+ * Files are tokenized into lowercase alphanumeric terms and indexed with
12
+ * per-document term frequencies. Queries are scored by summing the TF of
13
+ * each matched query token, then results are returned with the matching
14
+ * file path, score, and a handful of matched lines.
15
+ *
16
+ * Config (`config.extensions['semantic-search-indexer']`):
17
+ *
18
+ * ```jsonc
19
+ * {
20
+ * "enabled": true,
21
+ * "includeExtensions": [".ts", ".tsx", ".js", ".jsx"],
22
+ * "excludePatterns": ["node_modules", "\\.git", "dist"],
23
+ * "maxFileBytes": 1_000_000,
24
+ * "defaultLimit": 10,
25
+ * "minTokenLength": 2,
26
+ * "maxMatchesPerFile": 10,
27
+ * "maxFiles": 5000
28
+ * }
29
+ * ```
30
+ *
31
+ * @public
32
+ */
33
+ import type { Plugin } from '@wrongstack/core';
34
+ declare const plugin: Plugin;
35
+ export default plugin;
36
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/semantic-search-indexer/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AA6b/C,QAAA,MAAM,MAAM,EAAE,MA6Nb,CAAC;eAEa,MAAM"}
@@ -1,38 +1,2 @@
1
- import { Plugin } from '@wrongstack/core';
2
-
3
- /**
4
- * semantic-search-indexer plugin — lightweight keyword-based search over
5
- * project source files.
6
- *
7
- * The plugin builds an in-memory inverted index (no persistence, no
8
- * embeddings) and exposes two tools:
9
- *
10
- * - `semantic_search` — ranked keyword search with TF scoring
11
- * - `semantic_index_status` — index counters and configuration
12
- *
13
- * Files are tokenized into lowercase alphanumeric terms and indexed with
14
- * per-document term frequencies. Queries are scored by summing the TF of
15
- * each matched query token, then results are returned with the matching
16
- * file path, score, and a handful of matched lines.
17
- *
18
- * Config (`config.extensions['semantic-search-indexer']`):
19
- *
20
- * ```jsonc
21
- * {
22
- * "enabled": true,
23
- * "includeExtensions": [".ts", ".tsx", ".js", ".jsx"],
24
- * "excludePatterns": ["node_modules", "\\.git", "dist"],
25
- * "maxFileBytes": 1_000_000,
26
- * "defaultLimit": 10,
27
- * "minTokenLength": 2,
28
- * "maxMatchesPerFile": 10,
29
- * "maxFiles": 5000
30
- * }
31
- * ```
32
- *
33
- * @public
34
- */
35
-
36
- declare const plugin: Plugin;
37
-
38
- export { plugin as default };
1
+ export * from './semantic-search-indexer/index.js';
2
+ export { default } from './semantic-search-indexer/index.js';
@@ -1,7 +1,6 @@
1
- import * as fs from 'fs/promises';
2
- import { isAbsolute, resolve, relative } from 'path';
3
-
4
1
  // src/semantic-search-indexer/index.ts
2
+ import * as fs from "node:fs/promises";
3
+ import { isAbsolute, relative, resolve } from "node:path";
5
4
  var API_VERSION = "^0.1.10";
6
5
  var state = {
7
6
  index: null,
@@ -12,7 +11,9 @@ var state = {
12
11
  truncated: false,
13
12
  queryCount: 0,
14
13
  reindexCount: 0,
15
- buildPromise: null};
14
+ buildPromise: null,
15
+ hookUnregister: null
16
+ };
16
17
  var DEFAULTS = {
17
18
  enabled: true,
18
19
  includeExtensions: [
@@ -372,6 +373,13 @@ var plugin = {
372
373
  state.queryCount = 0;
373
374
  state.reindexCount = 0;
374
375
  state.buildPromise = null;
376
+ if (state.hookUnregister) {
377
+ try {
378
+ state.hookUnregister();
379
+ } catch {
380
+ }
381
+ state.hookUnregister = null;
382
+ }
375
383
  const cfg = readConfig(api.config.extensions?.["semantic-search-indexer"]);
376
384
  api.tools.register({
377
385
  name: "semantic_search",
@@ -457,6 +465,13 @@ var plugin = {
457
465
  });
458
466
  },
459
467
  teardown(api) {
468
+ if (state.hookUnregister) {
469
+ try {
470
+ state.hookUnregister();
471
+ } catch {
472
+ }
473
+ state.hookUnregister = null;
474
+ }
460
475
  const final = {
461
476
  fileCount: state.fileCount,
462
477
  termCount: state.termCount,
@@ -489,5 +504,6 @@ var plugin = {
489
504
  }
490
505
  };
491
506
  var semantic_search_indexer_default = plugin;
492
-
493
- export { semantic_search_indexer_default as default };
507
+ export {
508
+ semantic_search_indexer_default as default
509
+ };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * semver-bump plugin — Conventional-commit-driven semver version bumps.
3
+ *
4
+ * Tools registered:
5
+ * - semver_bump: Determine and apply the next version bump
6
+ * - semver_current: Show the current version from package.json
7
+ * - semver_changelog: Generate a changelog between two versions
8
+ */
9
+ import type { Plugin } from '@wrongstack/core';
10
+ type BumpType = 'major' | 'minor' | 'patch' | 'auto';
11
+ interface ConventionalCommit {
12
+ hash: string;
13
+ type: string;
14
+ scope?: string | undefined;
15
+ message: string;
16
+ breaking: boolean;
17
+ }
18
+ /** Parse a conventional-commit subject line. Accepts the breaking `!` both
19
+ * before and after the scope (`feat!: x`, `feat(api)!: x`). */
20
+ export declare function parseConventional(subject: string): Omit<ConventionalCommit, 'hash'>;
21
+ export declare function determineBump(commits: ConventionalCommit[]): BumpType;
22
+ declare const plugin: Plugin;
23
+ export default plugin;
24
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/semver-bump/index.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAuC/C,KAAK,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;AAErD,UAAU,kBAAkB;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAoFD;+DAC+D;AAC/D,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAQnF;AAmBD,wBAAgB,aAAa,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,QAAQ,CAIrE;AAmED,QAAA,MAAM,MAAM,EAAE,MA6bb,CAAC;eAEa,MAAM"}