@wrongstack/plugins 0.287.0 → 0.289.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/accessibility-auditor/index.d.ts.map +1 -1
  2. package/dist/accessibility-auditor.js +45 -42
  3. package/dist/auto-i18n-extractor.js +1 -1
  4. package/dist/code-metrics/index.d.ts.map +1 -1
  5. package/dist/code-metrics.js +46 -42
  6. package/dist/cost-tracker/index.d.ts.map +1 -1
  7. package/dist/cost-tracker.js +4 -2
  8. package/dist/dead-code-detector.js +3 -3
  9. package/dist/diff-summary.js +1 -1
  10. package/dist/doc-sync-guard.js +3 -3
  11. package/dist/duplicate-code-detector/index.d.ts.map +1 -1
  12. package/dist/duplicate-code-detector.js +47 -43
  13. package/dist/feature-flag-tracker/index.d.ts.map +1 -1
  14. package/dist/feature-flag-tracker.js +46 -42
  15. package/dist/file-watcher/index.d.ts.map +1 -1
  16. package/dist/file-watcher.js +6 -2
  17. package/dist/format-on-save.js +1 -1
  18. package/dist/import-organizer.js +1 -1
  19. package/dist/index.js +396 -539
  20. package/dist/interface-contract-guard/index.d.ts.map +1 -1
  21. package/dist/interface-contract-guard.js +46 -42
  22. package/dist/lint-gate/index.d.ts.map +1 -1
  23. package/dist/lint-gate.js +61 -30
  24. package/dist/migration-planner.js +1 -1
  25. package/dist/prompt-firewall/index.d.ts +14 -6
  26. package/dist/prompt-firewall/index.d.ts.map +1 -1
  27. package/dist/prompt-firewall.js +7 -6
  28. package/dist/refactor-suggester/index.d.ts.map +1 -1
  29. package/dist/refactor-suggester.js +46 -42
  30. package/dist/runtime/index.d.ts +24 -0
  31. package/dist/runtime/index.d.ts.map +1 -1
  32. package/dist/runtime.js +63 -24
  33. package/dist/schema-evolution-guard.js +1 -1
  34. package/dist/secret-scanner/index.d.ts.map +1 -1
  35. package/dist/secret-scanner.js +17 -6
  36. package/dist/security-hotspot-scanner.js +1 -1
  37. package/dist/spec-linker.js +396 -539
  38. package/dist/test-runner-gate.js +1 -1
  39. package/dist/type-gate.js +19 -23
  40. package/package.json +3 -3
package/dist/runtime.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/runtime/index.ts
2
2
  import { execFile } from "node:child_process";
3
- import { existsSync } from "node:fs";
4
- import { basename, isAbsolute, relative, resolve } from "node:path";
3
+ import { existsSync, readdirSync, statSync } from "node:fs";
4
+ import { basename, extname, isAbsolute, relative, resolve } from "node:path";
5
5
 
6
6
  // src/runtime/llm.ts
7
7
  function stripOuterMarkdownFence(text) {
@@ -148,12 +148,15 @@ function runRunnerCommand(argv, options) {
148
148
  });
149
149
  return;
150
150
  }
151
- const timedOut = false;
151
+ let timedOut = false;
152
152
  let spawnErrored = false;
153
153
  const stdoutChunks = [];
154
154
  const stderrChunks = [];
155
155
  let stdoutBytes = 0;
156
156
  let stderrBytes = 0;
157
+ options.signal?.addEventListener("abort", () => {
158
+ timedOut = true;
159
+ }, { once: true });
157
160
  const child = execFile(
158
161
  argv[0],
159
162
  argv.slice(1),
@@ -165,12 +168,12 @@ function runRunnerCommand(argv, options) {
165
168
  windowsHide: true,
166
169
  shell: false
167
170
  },
168
- (err, stdout, stderr) => {
171
+ (err) => {
169
172
  if (timedOut) {
170
173
  resolvePromise({
171
174
  code: null,
172
- stdout: Buffer.concat([...stdoutChunks, ...Buffer.isBuffer(stdout) ? [stdout] : [Buffer.from(stdout)]]).toString("utf8"),
173
- stderr: Buffer.concat([...stderrChunks, ...Buffer.isBuffer(stderr) ? [stderr] : [Buffer.from(stderr)]]).toString("utf8"),
175
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
176
+ stderr: Buffer.concat(stderrChunks).toString("utf8"),
174
177
  timedOut: true,
175
178
  spawnError: false
176
179
  });
@@ -179,8 +182,8 @@ function runRunnerCommand(argv, options) {
179
182
  if (spawnErrored) {
180
183
  resolvePromise({
181
184
  code: 127,
182
- stdout: Buffer.concat([...stdoutChunks, ...Buffer.isBuffer(stdout) ? [stdout] : [Buffer.from(stdout)]]).toString("utf8"),
183
- stderr: Buffer.concat([...stderrChunks, ...Buffer.isBuffer(stderr) ? [stderr] : [Buffer.from(stderr)]]).toString("utf8"),
185
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
186
+ stderr: Buffer.concat(stderrChunks).toString("utf8"),
184
187
  timedOut: false,
185
188
  spawnError: true
186
189
  });
@@ -191,14 +194,8 @@ function runRunnerCommand(argv, options) {
191
194
  const code = typeof anyErr.code === "number" ? anyErr.code : 1;
192
195
  resolvePromise({
193
196
  code,
194
- stdout: Buffer.concat([
195
- ...stdoutChunks,
196
- ...anyErr.stdout ? [Buffer.isBuffer(anyErr.stdout) ? anyErr.stdout : Buffer.from(anyErr.stdout)] : []
197
- ]).toString("utf8"),
198
- stderr: Buffer.concat([
199
- ...stderrChunks,
200
- ...anyErr.stderr ? [Buffer.isBuffer(anyErr.stderr) ? anyErr.stderr : Buffer.from(anyErr.stderr)] : []
201
- ]).toString("utf8"),
197
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
198
+ stderr: Buffer.concat(stderrChunks).toString("utf8"),
202
199
  timedOut: false,
203
200
  spawnError: false
204
201
  });
@@ -206,19 +203,18 @@ function runRunnerCommand(argv, options) {
206
203
  }
207
204
  resolvePromise({
208
205
  code: 0,
209
- stdout: Buffer.concat([
210
- ...stdoutChunks,
211
- ...Buffer.isBuffer(stdout) ? [stdout] : [Buffer.from(stdout)]
212
- ]).toString("utf8"),
213
- stderr: Buffer.concat([
214
- ...stderrChunks,
215
- ...Buffer.isBuffer(stderr) ? [stderr] : [Buffer.from(stderr)]
216
- ]).toString("utf8"),
206
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
207
+ stderr: Buffer.concat(stderrChunks).toString("utf8"),
217
208
  timedOut: false,
218
209
  spawnError: false
219
210
  });
220
211
  }
221
212
  );
213
+ child.on("exit", (_code, signal) => {
214
+ if (signal !== null) {
215
+ timedOut = true;
216
+ }
217
+ });
222
218
  child.stdout?.on("data", (chunk) => {
223
219
  stdoutBytes += chunk.length;
224
220
  if (stdoutBytes <= MAX_BUFFER_BYTES) stdoutChunks.push(chunk);
@@ -258,8 +254,51 @@ function locateRunnerEntry(runtime, projectRoot) {
258
254
  }
259
255
  return null;
260
256
  }
257
+ var DEFAULT_EXCLUDE_DIRS = ["node_modules", "dist", ".git", "coverage"];
258
+ function collectSourceFiles(root, opts) {
259
+ const files = [];
260
+ if (!existsSync(root)) return files;
261
+ const s = statSync(root);
262
+ if (s.isFile()) {
263
+ if (matchesExtension(root, opts.extensions)) files.push(root);
264
+ return files;
265
+ }
266
+ if (!s.isDirectory()) return files;
267
+ const exclude = opts.excludeDirs ?? DEFAULT_EXCLUDE_DIRS;
268
+ function walk(dir, depth) {
269
+ if (opts.maxDepth !== void 0 && depth > opts.maxDepth) return;
270
+ let entries;
271
+ try {
272
+ entries = readdirSync(dir);
273
+ } catch {
274
+ return;
275
+ }
276
+ for (const entry of entries) {
277
+ if (exclude.includes(entry)) continue;
278
+ const full = resolve(dir, entry);
279
+ let st;
280
+ try {
281
+ st = statSync(full);
282
+ } catch {
283
+ continue;
284
+ }
285
+ if (st.isDirectory()) {
286
+ walk(full, depth + 1);
287
+ } else if (st.isFile() && matchesExtension(full, opts.extensions)) {
288
+ files.push(full);
289
+ }
290
+ }
291
+ }
292
+ walk(root, 0);
293
+ return files;
294
+ }
295
+ function matchesExtension(p, exts) {
296
+ return exts.includes(extname(p).toLowerCase());
297
+ }
261
298
  export {
299
+ collectSourceFiles,
262
300
  locateRunnerEntry,
301
+ matchesExtension,
263
302
  parseLlmJsonObject,
264
303
  probeRunner,
265
304
  resolveRunnerCommand,
@@ -3,7 +3,7 @@ import { readFileSync } from "node:fs";
3
3
  import { basename as basename2 } from "node:path";
4
4
 
5
5
  // src/runtime/index.ts
6
- import { basename, isAbsolute, relative, resolve } from "node:path";
6
+ import { basename, extname, isAbsolute, relative, resolve } from "node:path";
7
7
  var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
8
8
  function hasLeadingDash(arg) {
9
9
  return arg.length > 0 && arg.startsWith("-");
@@ -1 +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
+ {"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;AAqd/C,QAAA,MAAM,MAAM,EAAE,MAgOb,CAAC;eAEa,MAAM"}
@@ -55,6 +55,8 @@ var BASE_PATTERNS = [
55
55
  ];
56
56
  var PATTERNS = [...BASE_PATTERNS];
57
57
  var COMBINED_REGEX = buildCombinedRegex(PATTERNS);
58
+ var RE_DOS_MAX_SCAN_LENGTH = 1e5;
59
+ var RE_DOS_TIMEOUT_MS = 100;
58
60
  function buildCombinedRegex(patterns) {
59
61
  return new RegExp(patterns.map((p) => `(${p.regex.source})`).join("|"), "g");
60
62
  }
@@ -75,10 +77,17 @@ var state = {
75
77
  };
76
78
  function findMatches(text) {
77
79
  if (!text) return [];
80
+ if (text.length > RE_DOS_MAX_SCAN_LENGTH) return [];
78
81
  const found = /* @__PURE__ */ new Set();
79
82
  COMBINED_REGEX.lastIndex = 0;
80
83
  let m;
84
+ const startTime = performance.now();
81
85
  while ((m = COMBINED_REGEX.exec(text)) !== null) {
86
+ if (performance.now() - startTime > RE_DOS_TIMEOUT_MS) {
87
+ throw new Error(
88
+ `secret-scanner: ReDoS timeout \u2014 regex scan exceeded ${RE_DOS_TIMEOUT_MS}ms on ${text.length}-char input`
89
+ );
90
+ }
82
91
  for (let i = 0; i < PATTERNS.length; i++) {
83
92
  if (m[i + 1] !== void 0) {
84
93
  found.add(PATTERNS[i].type);
@@ -91,30 +100,32 @@ function findMatches(text) {
91
100
  }
92
101
  return Array.from(found);
93
102
  }
94
- function scanInput(input) {
103
+ function scanInput(input, depth = 0) {
95
104
  if (input === null || input === void 0) return null;
105
+ if (depth > 50) return null;
96
106
  if (typeof input === "string") {
97
107
  const found = findMatches(input);
98
108
  return found.length > 0 ? found : null;
99
109
  }
100
110
  if (Array.isArray(input)) {
101
111
  for (const item of input) {
102
- const found = scanInput(item);
112
+ const found = scanInput(item, depth + 1);
103
113
  if (found) return found;
104
114
  }
105
115
  return null;
106
116
  }
107
117
  if (typeof input === "object") {
108
118
  for (const value of Object.values(input)) {
109
- const found = scanInput(value);
119
+ const found = scanInput(value, depth + 1);
110
120
  if (found) return found;
111
121
  }
112
122
  return null;
113
123
  }
114
124
  return null;
115
125
  }
116
- function redactInput(input) {
126
+ function redactInput(input, depth = 0) {
117
127
  if (input === null || input === void 0) return input;
128
+ if (depth > 50) return input;
118
129
  if (typeof input === "string") {
119
130
  return input.replace(COMBINED_REGEX, (_match, ...groups) => {
120
131
  for (let i = 0; i < PATTERNS.length; i++) {
@@ -126,12 +137,12 @@ function redactInput(input) {
126
137
  });
127
138
  }
128
139
  if (Array.isArray(input)) {
129
- return input.map((item) => redactInput(item));
140
+ return input.map((item) => redactInput(item, depth + 1));
130
141
  }
131
142
  if (typeof input === "object") {
132
143
  const out = {};
133
144
  for (const [k, v] of Object.entries(input)) {
134
- out[k] = redactInput(v);
145
+ out[k] = redactInput(v, depth + 1);
135
146
  }
136
147
  return out;
137
148
  }
@@ -3,7 +3,7 @@ import { readdirSync, readFileSync, statSync } from "node:fs";
3
3
  import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2 } from "node:path";
4
4
 
5
5
  // src/runtime/index.ts
6
- import { basename, isAbsolute, relative, resolve } from "node:path";
6
+ import { basename, extname, isAbsolute, relative, resolve } from "node:path";
7
7
  var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
8
8
  function hasLeadingDash(arg) {
9
9
  return arg.length > 0 && arg.startsWith("-");