@wrongstack/plugins 0.308.6 → 0.308.7

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 (51) hide show
  1. package/dist/accessibility-auditor.js +26 -82
  2. package/dist/agent-handoff.js +16 -26
  3. package/dist/auto-i18n-extractor.js +19 -23
  4. package/dist/branch-guard.js +19 -111
  5. package/dist/changelog-writer.js +20 -133
  6. package/dist/code-metrics.js +26 -71
  7. package/dist/commit-validator.js +16 -14
  8. package/dist/config-validator.js +18 -22
  9. package/dist/cost-tracker.js +15 -96
  10. package/dist/dead-code-detector.js +27 -31
  11. package/dist/dependency-vulnerability-gate.js +18 -15
  12. package/dist/diff-summary.js +19 -128
  13. package/dist/doc-sync-guard.js +24 -39
  14. package/dist/duplicate-code-detector.js +30 -169
  15. package/dist/feature-flag-tracker.js +26 -71
  16. package/dist/file-watcher.js +19 -23
  17. package/dist/format-on-save.js +25 -214
  18. package/dist/import-organizer.js +31 -106
  19. package/dist/index.js +452 -1236
  20. package/dist/interface-contract-guard.js +26 -71
  21. package/dist/lint-gate.js +19 -111
  22. package/dist/migration-planner.js +28 -120
  23. package/dist/notify-hub.js +18 -28
  24. package/dist/path-guard.js +27 -102
  25. package/dist/pr-drafter.js +18 -16
  26. package/dist/prompt-firewall.js +8 -205
  27. package/dist/refactor-suggester.js +27 -166
  28. package/dist/release-notes-generator.js +6 -35
  29. package/dist/runtime/bounded-map.d.ts +2 -85
  30. package/dist/runtime/credential-patterns.d.ts +2 -41
  31. package/dist/runtime/h1-state.d.ts +2 -61
  32. package/dist/runtime/handles.d.ts +2 -45
  33. package/dist/runtime/index.d.ts +8 -180
  34. package/dist/runtime/llm.d.ts +2 -43
  35. package/dist/runtime/local-bin.d.ts +2 -119
  36. package/dist/runtime/redos-guard.d.ts +2 -68
  37. package/dist/runtime/safe-json.d.ts +2 -24
  38. package/dist/runtime/sandbox.d.ts +2 -58
  39. package/dist/runtime.js +1 -868
  40. package/dist/schema-evolution-guard.js +20 -24
  41. package/dist/secret-scanner.js +22 -146
  42. package/dist/security-hotspot-scanner.js +24 -154
  43. package/dist/session-recap.js +16 -14
  44. package/dist/spec-linker.js +19 -17
  45. package/dist/template-engine.js +22 -37
  46. package/dist/test-coverage-gate.js +19 -34
  47. package/dist/test-generator.js +6 -35
  48. package/dist/test-runner-gate.js +34 -143
  49. package/dist/todo-listener.js +17 -38
  50. package/dist/type-gate.js +23 -311
  51. package/package.json +4 -3
package/dist/type-gate.js CHANGED
@@ -1,312 +1,24 @@
1
- // src/type-gate/index.ts
2
- import { existsSync } from "node:fs";
3
-
4
- // src/runtime/index.ts
5
- import { execFile } from "node:child_process";
6
- import { basename, extname as extname2, isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2 } from "node:path";
7
-
8
- // src/runtime/local-bin.ts
9
- import { createRequire } from "node:module";
10
- import { delimiter, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
11
- import { accessSync, constants, readFileSync } from "node:fs";
12
- import { buildWin32CmdShimInvocation, resolveWin32Command } from "@wrongstack/tools/win32";
13
- function resolveExecInvocation(command, args = []) {
14
- const resolved = resolveWin32Command(command);
15
- const normalizedResolved = resolved.toLowerCase();
16
- const needsShell = process.platform === "win32" && (normalizedResolved.endsWith(".cmd") || normalizedResolved.endsWith(".bat"));
17
- if (needsShell) {
18
- const shim = buildWin32CmdShimInvocation(resolved, args);
19
- return { cmd: shim.command, args: shim.args, windowsVerbatimArguments: true };
20
- }
21
- return { cmd: resolved, args: [...args], windowsVerbatimArguments: false };
22
- }
23
- function isInside(parent, candidate) {
24
- const rel = relative(parent, candidate);
25
- return rel === "" || !rel.startsWith(`..${sep}`) && rel !== ".." && !isAbsolute(rel);
26
- }
27
- var binCache = /* @__PURE__ */ new Map();
28
- var BIN_CACHE_MAX = 64;
29
- var NEGATIVE_BIN_CACHE_TTL_MS = 5e3;
30
- function cachePut(key, value) {
31
- while (binCache.size >= BIN_CACHE_MAX) {
32
- const oldest = binCache.keys().next().value;
33
- if (oldest === void 0) break;
34
- binCache.delete(oldest);
35
- }
36
- binCache.set(key, { value, cachedAt: Date.now() });
37
- return value;
38
- }
39
- function resolveNodeBin(packageName, binName, cwd, extraArgs = []) {
40
- const key = `${packageName}|${binName}|${cwd}`;
41
- const cached = binCache.get(key);
42
- if (cached !== void 0) {
43
- if (cached.value !== null || Date.now() - cached.cachedAt < NEGATIVE_BIN_CACHE_TTL_MS) {
44
- return cached.value === null ? null : { ...cached.value, args: [cached.value.entry, ...extraArgs] };
45
- }
46
- binCache.delete(key);
47
- }
48
- let resolved = null;
49
- try {
50
- const requireFromProject = createRequire(resolve(cwd, "package.json"));
51
- const packagePath = requireFromProject.resolve(`${packageName}/package.json`);
52
- const packageJson = JSON.parse(readFileSync(packagePath, "utf-8"));
53
- const relativeBin = typeof packageJson.bin === "string" ? packageJson.bin : packageJson.bin?.[binName] ?? Object.values(packageJson.bin ?? {})[0];
54
- if (relativeBin && !isAbsolute(relativeBin)) {
55
- const packageDir = dirname(packagePath);
56
- const entry = resolve(packageDir, relativeBin);
57
- if (isInside(packageDir, entry)) {
58
- resolved = { cmd: process.execPath, args: [entry], entry };
59
- }
60
- }
61
- } catch {
62
- resolved = null;
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __copyProps = (to, from, except, desc) => {
6
+ if (from && typeof from === "object" || typeof from === "function") {
7
+ for (let key of __getOwnPropNames(from))
8
+ if (!__hasOwnProp.call(to, key) && key !== except)
9
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
63
10
  }
64
- cachePut(key, resolved);
65
- return resolved === null ? null : { ...resolved, args: [resolved.entry, ...extraArgs] };
66
- }
11
+ return to;
12
+ };
13
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
67
14
 
68
- // src/runtime/handles.ts
69
- function releaseHandle(off) {
70
- if (off) {
71
- try {
72
- off();
73
- } catch {
74
- }
75
- }
76
- return null;
77
- }
15
+ // src/type-gate/index.ts
16
+ import { existsSync } from "node:fs";
78
17
 
79
18
  // src/runtime/index.ts
80
- var META_CHARS = /["'`;&|<>\r\n]/;
81
- var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
82
- function hasLeadingDash(arg) {
83
- return arg.length > 0 && arg.startsWith("-");
84
- }
85
- function safeSplit(command) {
86
- const trimmed = command.trim();
87
- if (!trimmed || META_CHARS.test(trimmed)) return null;
88
- return trimmed.split(/\s+/).filter(Boolean);
89
- }
90
- function withinProjectPath(projectRoot, candidate) {
91
- if (candidate.length === 0 || candidate.length > 4096) return false;
92
- if (hasLeadingDash(candidate)) return false;
93
- const resolved = isAbsolute2(candidate) ? resolve2(candidate) : resolve2(projectRoot, candidate);
94
- const rel = relative2(projectRoot, resolved);
95
- return rel === "" || !rel.startsWith("..") && !isAbsolute2(rel);
96
- }
97
- function everyFlagAllowed(allowed, args) {
98
- for (const arg of args) {
99
- if (!hasLeadingDash(arg)) continue;
100
- if (allowed === null) return false;
101
- if (!allowed.has(arg)) return false;
102
- }
103
- return true;
104
- }
105
- function sanitizeRunnerPath(value, options = {}) {
106
- if (!value || hasLeadingDash(value)) return null;
107
- const projectRoot = resolve2(options.projectRoot ?? process.cwd());
108
- if (!withinProjectPath(projectRoot, value)) return null;
109
- return isAbsolute2(value) ? resolve2(value) : resolve2(projectRoot, value);
110
- }
111
- function resolveRunnerCommand(runtime, command, options = {}) {
112
- const tokens = safeSplit(command);
113
- if (!tokens || tokens.length === 0) return null;
114
- const projectRoot = resolve2(options.projectRoot ?? process.cwd());
115
- const launcher = runtime.packageManager;
116
- const [head, second, ...rest] = tokens;
117
- if (!head) return null;
118
- const display = tokens.join(" ");
119
- if (launcher !== "none" && tokens.length === 1 && head === launcher) {
120
- return null;
121
- }
122
- if (head === runtime.executable) {
123
- if (!everyFlagAllowed(runtime.allowedFlags, [second, ...rest].filter((v) => Boolean(v)))) {
124
- return null;
125
- }
126
- return {
127
- cmd: head,
128
- args: [second, ...rest].filter((v) => Boolean(v)),
129
- display
130
- };
131
- }
132
- if (launcher !== "none" && head === launcher && runtime.subcommands.length === 0 && second === runtime.executable) {
133
- if (!everyFlagAllowed(runtime.allowedFlags, rest)) return null;
134
- return { cmd: head, args: [second, ...rest], display };
135
- }
136
- if (launcher !== "none" && head === launcher && runtime.subcommands.length > 0) {
137
- const subcommand = runtime.subcommands[0];
138
- const exe = rest[0];
139
- if (second === subcommand && exe === runtime.executable) {
140
- const tail = rest.slice(1);
141
- if (!everyFlagAllowed(runtime.allowedFlags, tail)) return null;
142
- return { cmd: head, args: [second, exe, ...tail], display };
143
- }
144
- }
145
- if (isAbsolute2(head)) {
146
- if (!withinProjectPath(projectRoot, head)) return null;
147
- const base = basename(head);
148
- if (base !== runtime.executable && base !== launcher) return null;
149
- if (second !== runtime.executable) return null;
150
- if (!everyFlagAllowed(runtime.allowedFlags, rest)) return null;
151
- return { cmd: head, args: [second, ...rest], display };
152
- }
153
- return null;
154
- }
155
- function runRunnerCommand(argv, options) {
156
- if (argv.length === 0) {
157
- return Promise.resolve({
158
- code: null,
159
- stdout: "",
160
- stderr: "runtime helper: empty argv",
161
- timedOut: false,
162
- spawnError: true
163
- });
164
- }
165
- return new Promise((resolvePromise) => {
166
- const projectRoot = resolve2(options.projectRoot ?? process.cwd());
167
- const trimmedCwd = options.cwd.trim();
168
- if (!withinProjectPath(projectRoot, trimmedCwd)) {
169
- resolvePromise({
170
- code: null,
171
- stdout: "",
172
- stderr: "runtime helper: cwd outside project",
173
- timedOut: false,
174
- spawnError: true
175
- });
176
- return;
177
- }
178
- let timedOut = false;
179
- let spawnErrored = false;
180
- const start = Date.now();
181
- const stdoutChunks = [];
182
- const stderrChunks = [];
183
- let stdoutBytes = 0;
184
- let stderrBytes = 0;
185
- const onAbort = () => {
186
- timedOut = true;
187
- };
188
- let invocation;
189
- try {
190
- invocation = resolveExecInvocation(argv[0], argv.slice(1));
191
- } catch (err) {
192
- resolvePromise({
193
- code: null,
194
- stdout: "",
195
- stderr: `runtime helper: ${err instanceof Error ? err.message : String(err)}`,
196
- timedOut: false,
197
- spawnError: true
198
- });
199
- return;
200
- }
201
- options.signal?.addEventListener("abort", onAbort, { once: true });
202
- const child = execFile(
203
- invocation.cmd,
204
- invocation.args,
205
- {
206
- cwd: trimmedCwd,
207
- timeout: options.timeoutMs,
208
- signal: options.signal,
209
- maxBuffer: MAX_BUFFER_BYTES,
210
- // execFile defaults `encoding` to 'utf8', which makes the
211
- // stdout/stderr `data` events emit *strings*. The chunk arrays
212
- // below are typed Buffer[] and every consumer runs them through
213
- // Buffer.concat(...).toString('utf8'), which throws
214
- // ERR_INVALID_ARG_TYPE on any non-empty string output. Pin the
215
- // streams to buffers so the declared contract holds (regression:
216
- // runRunnerCommand crashed on any child that actually wrote
217
- // output; only the maxBuffer fixture exercised this path).
218
- encoding: "buffer",
219
- windowsHide: true,
220
- shell: false,
221
- ...invocation.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}
222
- },
223
- (err) => {
224
- options.signal?.removeEventListener("abort", onAbort);
225
- if (timedOut) {
226
- resolvePromise({
227
- code: null,
228
- stdout: Buffer.concat(stdoutChunks).toString("utf8"),
229
- stderr: Buffer.concat(stderrChunks).toString("utf8"),
230
- timedOut: true,
231
- spawnError: false
232
- });
233
- return;
234
- }
235
- if (spawnErrored) {
236
- resolvePromise({
237
- code: 127,
238
- stdout: Buffer.concat(stdoutChunks).toString("utf8"),
239
- stderr: Buffer.concat(stderrChunks).toString("utf8"),
240
- timedOut: false,
241
- spawnError: true
242
- });
243
- return;
244
- }
245
- if (err) {
246
- const anyErr = err;
247
- if ((anyErr.killed === true || anyErr.signal === "SIGTERM") && // maxBuffer overflow must NOT be misreported as a timeout
248
- // — it's a real failure (the child wrote too much) and
249
- // downstream callers (type-gate/index.ts:227) return
250
- // null on timedOut=true, which would silently swallow
251
- // maxBuffer overflow into a confusing empty-output
252
- // result. Skip the timeout resolve when the err shape
253
- // names maxBuffer explicitly.
254
- !/maxBuffer length exceeded/i.test(anyErr.message ?? "") && // And only count it as a timeout if the wall clock has
255
- // actually elapsed past the budget. External SIGTERMs and
256
- // races against the exit handler don't satisfy this.
257
- Date.now() - start >= options.timeoutMs) {
258
- resolvePromise({
259
- code: null,
260
- stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
261
- stderr: Buffer.concat(stderrChunks).toString("utf-8"),
262
- timedOut: true,
263
- spawnError: false
264
- });
265
- return;
266
- }
267
- const code = typeof anyErr.code === "number" ? anyErr.code : 1;
268
- resolvePromise({
269
- code,
270
- stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
271
- stderr: Buffer.concat(stderrChunks).toString("utf-8"),
272
- timedOut: false,
273
- spawnError: false
274
- });
275
- return;
276
- }
277
- resolvePromise({
278
- code: 0,
279
- stdout: Buffer.concat(stdoutChunks).toString("utf8"),
280
- stderr: Buffer.concat(stderrChunks).toString("utf8"),
281
- timedOut: false,
282
- spawnError: false
283
- });
284
- }
285
- );
286
- child.on("exit", (_code, signal) => {
287
- if (signal !== null && Date.now() - start >= options.timeoutMs) {
288
- timedOut = true;
289
- }
290
- });
291
- child.stdout?.on("data", (chunk) => {
292
- stdoutBytes += chunk.length;
293
- if (stdoutBytes <= MAX_BUFFER_BYTES) stdoutChunks.push(chunk);
294
- });
295
- child.stderr?.on("data", (chunk) => {
296
- stderrBytes += chunk.length;
297
- if (stderrBytes <= MAX_BUFFER_BYTES) stderrChunks.push(chunk);
298
- });
299
- child.on("error", (err) => {
300
- if (err.code === "ENOENT" || err.code === "EPERM" || err.code === "EACCES") {
301
- spawnErrored = true;
302
- }
303
- });
304
- });
305
- }
306
- function withinProject(p) {
307
- const cwd = process.cwd();
308
- return withinProjectPath(cwd, p) || relative2(cwd, p) === ".";
309
- }
19
+ var runtime_exports = {};
20
+ __reExport(runtime_exports, runtime_star);
21
+ import * as runtime_star from "@wrongstack/plugin-sdk/runtime";
310
22
 
311
23
  // src/type-gate/index.ts
312
24
  var API_VERSION = "^0.1.10";
@@ -365,7 +77,7 @@ var TSC_RUNTIME = {
365
77
  defaultCommand: "pnpm exec tsc --noEmit"
366
78
  };
367
79
  function validateTsConfigPath(p) {
368
- const sanitized = sanitizeRunnerPath(p);
80
+ const sanitized = (0, runtime_exports.sanitizeRunnerPath)(p);
369
81
  return sanitized;
370
82
  }
371
83
  async function runTypeCheck(cfg) {
@@ -378,12 +90,12 @@ async function runTypeCheck(cfg) {
378
90
  const tsConfig = validTsConfig ?? (rawTsConfig || "tsconfig.json");
379
91
  let argv;
380
92
  if (cfg.command) {
381
- const resolved = resolveRunnerCommand(TSC_RUNTIME, cfg.command);
93
+ const resolved = (0, runtime_exports.resolveRunnerCommand)(TSC_RUNTIME, cfg.command);
382
94
  if (!resolved) return null;
383
95
  argv = [resolved.cmd, ...resolved.args];
384
96
  } else {
385
97
  const tscFlags = ["--noEmit", "--incremental"];
386
- const localTsc = resolveNodeBin("typescript", "tsc", process.cwd(), tscFlags);
98
+ const localTsc = (0, runtime_exports.resolveNodeBin)("typescript", "tsc", process.cwd(), tscFlags);
387
99
  argv = localTsc ? [localTsc.cmd, ...localTsc.args] : ["npx", "tsc", ...tscFlags];
388
100
  if (tsConfig && tsConfig !== "tsconfig.json") {
389
101
  argv = [...argv, "-p", tsConfig];
@@ -392,7 +104,7 @@ async function runTypeCheck(cfg) {
392
104
  if (!cfg.command && tsConfig && !existsSync(tsConfig)) {
393
105
  return null;
394
106
  }
395
- const result = await runRunnerCommand([argv[0], ...argv.slice(1)], {
107
+ const result = await (0, runtime_exports.runRunnerCommand)([argv[0], ...argv.slice(1)], {
396
108
  cwd: process.cwd(),
397
109
  timeoutMs: cfg.timeoutMs
398
110
  });
@@ -480,7 +192,7 @@ var plugin = {
480
192
  state.errorCount = 0;
481
193
  state.skippedCount = 0;
482
194
  state.lastResult = null;
483
- state.hookUnregister = releaseHandle(state.hookUnregister);
195
+ state.hookUnregister = (0, runtime_exports.releaseHandle)(state.hookUnregister);
484
196
  const cfg = readConfig(api.config.extensions?.["type-gate"]);
485
197
  const hook = async (input) => {
486
198
  if (!cfg.enabled) return;
@@ -488,7 +200,7 @@ var plugin = {
488
200
  const inp = input.toolInput ?? {};
489
201
  const sourcePath = inp["path"];
490
202
  if (!sourcePath || typeof sourcePath !== "string") return;
491
- if (!withinProject(sourcePath)) return;
203
+ if (!(0, runtime_exports.withinProject)(sourcePath)) return;
492
204
  const ext = sourcePath.includes(".") ? sourcePath.slice(sourcePath.lastIndexOf(".")).toLowerCase() : "";
493
205
  if (!runOnChangeSet.has(ext)) {
494
206
  state.skippedCount += 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/plugins",
3
- "version": "0.308.6",
3
+ "version": "0.308.7",
4
4
  "description": "Official WrongStack collection of focused plugins for code quality, security, observability, planning, and agent coordination",
5
5
  "license": "MIT",
6
6
  "author": "ECOSTACK TECHNOLOGY OÜ",
@@ -303,8 +303,9 @@
303
303
  "vitest": "^4.1.10"
304
304
  },
305
305
  "dependencies": {
306
- "@wrongstack/core": "0.308.6",
307
- "@wrongstack/tools": "0.308.6"
306
+ "@wrongstack/core": "0.308.7",
307
+ "@wrongstack/tools": "0.308.7",
308
+ "@wrongstack/plugin-sdk": "0.308.7"
308
309
  },
309
310
  "scripts": {
310
311
  "build": "node ../../scripts/build-package.mjs",