@wrongstack/plugins 0.295.0 → 0.296.2

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 (110) hide show
  1. package/dist/accessibility-auditor/index.d.ts.map +1 -1
  2. package/dist/accessibility-auditor.js +31 -3
  3. package/dist/agent-handoff/index.d.ts.map +1 -1
  4. package/dist/agent-handoff.js +30 -1
  5. package/dist/auto-doc/index.d.ts.map +1 -1
  6. package/dist/auto-doc.js +3 -1
  7. package/dist/auto-i18n-extractor.js +5 -0
  8. package/dist/branch-guard/index.d.ts.map +1 -1
  9. package/dist/branch-guard.js +116 -3
  10. package/dist/changelog-writer/index.d.ts.map +1 -1
  11. package/dist/changelog-writer.js +137 -3
  12. package/dist/checkpoint/index.d.ts +2 -0
  13. package/dist/checkpoint/index.d.ts.map +1 -1
  14. package/dist/checkpoint.js +34 -8
  15. package/dist/code-metrics.js +5 -0
  16. package/dist/commit-validator/index.d.ts.map +1 -1
  17. package/dist/commit-validator.js +35 -8
  18. package/dist/context-pins/index.d.ts.map +1 -1
  19. package/dist/context-pins.js +6 -5
  20. package/dist/cost-tracker/index.d.ts.map +1 -1
  21. package/dist/cost-tracker.js +101 -1
  22. package/dist/cron/index.d.ts.map +1 -1
  23. package/dist/cron.js +1 -0
  24. package/dist/dead-code-detector/index.d.ts.map +1 -1
  25. package/dist/dead-code-detector.js +9 -1
  26. package/dist/dependency-vulnerability-gate/index.d.ts.map +1 -1
  27. package/dist/dependency-vulnerability-gate.js +43 -8
  28. package/dist/diff-summary/index.d.ts.map +1 -1
  29. package/dist/diff-summary.js +112 -2
  30. package/dist/doc-sync-guard.js +17 -1
  31. package/dist/duplicate-code-detector/index.d.ts.map +1 -1
  32. package/dist/duplicate-code-detector.js +102 -2
  33. package/dist/feature-flag-tracker/index.d.ts.map +1 -1
  34. package/dist/feature-flag-tracker.js +30 -4
  35. package/dist/file-watcher/index.d.ts.map +1 -1
  36. package/dist/file-watcher.js +6 -7
  37. package/dist/format-on-save/index.d.ts +2 -0
  38. package/dist/format-on-save/index.d.ts.map +1 -1
  39. package/dist/format-on-save.js +288 -59
  40. package/dist/git-autocommit/index.d.ts +12 -0
  41. package/dist/git-autocommit/index.d.ts.map +1 -1
  42. package/dist/git-autocommit.js +58 -4
  43. package/dist/import-organizer/index.d.ts.map +1 -1
  44. package/dist/import-organizer.js +152 -21
  45. package/dist/index.js +1413 -590
  46. package/dist/injection-shield/index.d.ts +16 -0
  47. package/dist/injection-shield/index.d.ts.map +1 -1
  48. package/dist/injection-shield.js +12 -4
  49. package/dist/interface-contract-guard/index.d.ts.map +1 -1
  50. package/dist/interface-contract-guard.js +60 -26
  51. package/dist/knowledge-graph/index.d.ts.map +1 -1
  52. package/dist/knowledge-graph.js +7 -6
  53. package/dist/lint-gate/index.d.ts.map +1 -1
  54. package/dist/lint-gate.js +115 -2
  55. package/dist/loop-breaker/index.d.ts.map +1 -1
  56. package/dist/loop-breaker.js +15 -5
  57. package/dist/migration-planner.js +15 -1
  58. package/dist/notify-hub/index.d.ts.map +1 -1
  59. package/dist/notify-hub.js +41 -4
  60. package/dist/pr-drafter/index.d.ts.map +1 -1
  61. package/dist/pr-drafter.js +20 -1
  62. package/dist/prompt-firewall/index.d.ts.map +1 -1
  63. package/dist/prompt-firewall.js +140 -11
  64. package/dist/refactor-suggester/index.d.ts.map +1 -1
  65. package/dist/refactor-suggester.js +119 -4
  66. package/dist/runtime/bounded-map.d.ts +86 -0
  67. package/dist/runtime/bounded-map.d.ts.map +1 -0
  68. package/dist/runtime/credential-patterns.d.ts +42 -0
  69. package/dist/runtime/credential-patterns.d.ts.map +1 -0
  70. package/dist/runtime/handles.d.ts +46 -0
  71. package/dist/runtime/handles.d.ts.map +1 -0
  72. package/dist/runtime/index.d.ts +4 -0
  73. package/dist/runtime/index.d.ts.map +1 -1
  74. package/dist/runtime/local-bin.d.ts +120 -0
  75. package/dist/runtime/local-bin.d.ts.map +1 -0
  76. package/dist/runtime/safe-json.d.ts +25 -0
  77. package/dist/runtime/safe-json.d.ts.map +1 -0
  78. package/dist/runtime.js +309 -22
  79. package/dist/schema-evolution-guard.js +5 -0
  80. package/dist/secret-scanner/index.d.ts.map +1 -1
  81. package/dist/secret-scanner.js +194 -50
  82. package/dist/security-hotspot-scanner/index.d.ts.map +1 -1
  83. package/dist/security-hotspot-scanner.js +132 -1
  84. package/dist/semantic-search-indexer/index.d.ts.map +1 -1
  85. package/dist/semantic-search-indexer.js +7 -1
  86. package/dist/semver-bump/index.d.ts.map +1 -1
  87. package/dist/semver-bump.js +21 -2
  88. package/dist/session-recap/index.d.ts.map +1 -1
  89. package/dist/session-recap.js +18 -1
  90. package/dist/smart-rename/index.d.ts +2 -0
  91. package/dist/smart-rename/index.d.ts.map +1 -1
  92. package/dist/smart-rename.js +16 -2
  93. package/dist/spec-linker/index.d.ts.map +1 -1
  94. package/dist/spec-linker.js +19 -2
  95. package/dist/template-engine/index.d.ts.map +1 -1
  96. package/dist/template-engine.js +45 -3
  97. package/dist/test-coverage-gate.js +17 -1
  98. package/dist/test-runner-gate/index.d.ts.map +1 -1
  99. package/dist/test-runner-gate.js +142 -9
  100. package/dist/todo-listener/index.d.ts.map +1 -1
  101. package/dist/todo-listener.js +42 -2
  102. package/dist/todo-tracker/index.d.ts.map +1 -1
  103. package/dist/todo-tracker.js +3 -4
  104. package/dist/token-budget/index.d.ts.map +1 -1
  105. package/dist/token-budget.js +31 -19
  106. package/dist/token-throttle/index.d.ts.map +1 -1
  107. package/dist/token-throttle.js +17 -2
  108. package/dist/type-gate/index.d.ts.map +1 -1
  109. package/dist/type-gate.js +108 -17
  110. package/package.json +3 -3
@@ -1,10 +1,83 @@
1
1
  // src/import-organizer/index.ts
2
2
  import { spawn } from "node:child_process";
3
3
  import { existsSync, statSync } from "node:fs";
4
- import { basename as basename2, isAbsolute as isAbsolute2 } from "node:path";
4
+ import { basename as basename2, isAbsolute as isAbsolute3 } from "node:path";
5
+
6
+ // src/runtime/index.ts
7
+ import { basename, extname as extname2, isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2 } from "node:path";
8
+
9
+ // src/runtime/local-bin.ts
10
+ import { createRequire } from "node:module";
11
+ import { delimiter, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
12
+ import { accessSync, constants, readFileSync } from "node:fs";
13
+ import { buildWin32CmdShimInvocation, resolveWin32Command } from "@wrongstack/tools/win32";
14
+ function resolveExecInvocation(command, args = []) {
15
+ const resolved = resolveWin32Command(command);
16
+ const normalizedResolved = resolved.toLowerCase();
17
+ const needsShell = process.platform === "win32" && (normalizedResolved.endsWith(".cmd") || normalizedResolved.endsWith(".bat"));
18
+ if (needsShell) {
19
+ const shim = buildWin32CmdShimInvocation(resolved, args);
20
+ return { cmd: shim.command, args: shim.args, windowsVerbatimArguments: true };
21
+ }
22
+ return { cmd: resolved, args: [...args], windowsVerbatimArguments: false };
23
+ }
24
+ function isInside(parent, candidate) {
25
+ const rel = relative(parent, candidate);
26
+ return rel === "" || !rel.startsWith(`..${sep}`) && rel !== ".." && !isAbsolute(rel);
27
+ }
28
+ var binCache = /* @__PURE__ */ new Map();
29
+ var BIN_CACHE_MAX = 64;
30
+ var NEGATIVE_BIN_CACHE_TTL_MS = 5e3;
31
+ function cachePut(key, value) {
32
+ while (binCache.size >= BIN_CACHE_MAX) {
33
+ const oldest = binCache.keys().next().value;
34
+ if (oldest === void 0) break;
35
+ binCache.delete(oldest);
36
+ }
37
+ binCache.set(key, { value, cachedAt: Date.now() });
38
+ return value;
39
+ }
40
+ function resolveNodeBin(packageName, binName, cwd, extraArgs = []) {
41
+ const key = `${packageName}|${binName}|${cwd}`;
42
+ const cached = binCache.get(key);
43
+ if (cached !== void 0) {
44
+ if (cached.value !== null || Date.now() - cached.cachedAt < NEGATIVE_BIN_CACHE_TTL_MS) {
45
+ return cached.value === null ? null : { ...cached.value, args: [cached.value.entry, ...extraArgs] };
46
+ }
47
+ binCache.delete(key);
48
+ }
49
+ let resolved = null;
50
+ try {
51
+ const requireFromProject = createRequire(resolve(cwd, "package.json"));
52
+ const packagePath = requireFromProject.resolve(`${packageName}/package.json`);
53
+ const packageJson = JSON.parse(readFileSync(packagePath, "utf-8"));
54
+ const relativeBin = typeof packageJson.bin === "string" ? packageJson.bin : packageJson.bin?.[binName] ?? Object.values(packageJson.bin ?? {})[0];
55
+ if (relativeBin && !isAbsolute(relativeBin)) {
56
+ const packageDir = dirname(packagePath);
57
+ const entry = resolve(packageDir, relativeBin);
58
+ if (isInside(packageDir, entry)) {
59
+ resolved = { cmd: process.execPath, args: [entry], entry };
60
+ }
61
+ }
62
+ } catch {
63
+ resolved = null;
64
+ }
65
+ cachePut(key, resolved);
66
+ return resolved === null ? null : { ...resolved, args: [resolved.entry, ...extraArgs] };
67
+ }
68
+
69
+ // src/runtime/handles.ts
70
+ function releaseHandle(off) {
71
+ if (off) {
72
+ try {
73
+ off();
74
+ } catch {
75
+ }
76
+ }
77
+ return null;
78
+ }
5
79
 
6
80
  // src/runtime/index.ts
7
- import { basename, extname, isAbsolute, relative, resolve } from "node:path";
8
81
  var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
9
82
  function hasLeadingDash(arg) {
10
83
  return arg.length > 0 && arg.startsWith("-");
@@ -12,13 +85,13 @@ function hasLeadingDash(arg) {
12
85
  function withinProjectPath(projectRoot, candidate) {
13
86
  if (candidate.length === 0 || candidate.length > 4096) return false;
14
87
  if (hasLeadingDash(candidate)) return false;
15
- const resolved = isAbsolute(candidate) ? resolve(candidate) : resolve(projectRoot, candidate);
16
- const rel = relative(projectRoot, resolved);
17
- return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
88
+ const resolved = isAbsolute2(candidate) ? resolve2(candidate) : resolve2(projectRoot, candidate);
89
+ const rel = relative2(projectRoot, resolved);
90
+ return rel === "" || !rel.startsWith("..") && !isAbsolute2(rel);
18
91
  }
19
92
  function withinProject(p) {
20
93
  const cwd = process.cwd();
21
- return withinProjectPath(cwd, p) || relative(cwd, p) === ".";
94
+ return withinProjectPath(cwd, p) || relative2(cwd, p) === ".";
22
95
  }
23
96
 
24
97
  // src/import-organizer/index.ts
@@ -30,23 +103,51 @@ var ALLOWED_FIRST_TOKENS = /* @__PURE__ */ new Set([
30
103
  "biome",
31
104
  "@biomejs/biome",
32
105
  "eslint",
106
+ "oxlint",
33
107
  "node"
34
108
  // Recognise a fully-qualified project-local path like
35
109
  // "./node_modules/.bin/biome"; basename check kicks in below.
36
110
  ]);
111
+ var PACKAGE_RUNNERS = /* @__PURE__ */ new Set(["npx", "pnpm", "npm", "yarn"]);
112
+ var LOCAL_BIN_PACKAGES = {
113
+ biome: { packageName: "@biomejs/biome", binName: "biome" },
114
+ "@biomejs/biome": { packageName: "@biomejs/biome", binName: "biome" },
115
+ eslint: { packageName: "eslint", binName: "eslint" },
116
+ oxlint: { packageName: "oxlint", binName: "oxlint" }
117
+ };
118
+ function resolveLocalToolCommand(tokens) {
119
+ if (tokens.length === 0) return null;
120
+ let i = 0;
121
+ if (PACKAGE_RUNNERS.has(tokens[i])) {
122
+ i++;
123
+ while (i < tokens.length && (tokens[i] === "exec" || tokens[i] === "dlx" || tokens[i] === "run")) {
124
+ i++;
125
+ }
126
+ }
127
+ const toolToken = tokens[i];
128
+ if (!toolToken) return null;
129
+ const rest = tokens.slice(i + 1);
130
+ const pkg = LOCAL_BIN_PACKAGES[toolToken];
131
+ if (!pkg) return null;
132
+ const local = resolveNodeBin(pkg.packageName, pkg.binName, process.cwd(), rest);
133
+ if (!local) return null;
134
+ return { cmd: local.cmd, args: local.args };
135
+ }
37
136
  function resolveAllowedCommand(command) {
38
137
  const tokens = command.split(/\s+/).filter(Boolean);
39
138
  if (tokens.length === 0) return null;
40
139
  const head = tokens[0];
140
+ const local = ALLOWED_FIRST_TOKENS.has(head) ? resolveLocalToolCommand(tokens) : null;
141
+ if (local) return local;
41
142
  if (ALLOWED_FIRST_TOKENS.has(head)) {
42
143
  return { cmd: head, args: tokens.slice(1) };
43
144
  }
44
- if (isAbsolute2(head)) {
145
+ if (isAbsolute3(head)) {
45
146
  if (!withinProject(head)) return null;
46
147
  const base = basename2(head);
47
148
  if (ALLOWED_FIRST_TOKENS.has(base)) return { cmd: head, args: tokens.slice(1) };
48
149
  }
49
- if (!isAbsolute2(head) && withinProject(head)) {
150
+ if (!isAbsolute3(head) && withinProject(head)) {
50
151
  const base = basename2(head);
51
152
  if (ALLOWED_FIRST_TOKENS.has(base)) return { cmd: head, args: tokens.slice(1) };
52
153
  }
@@ -81,40 +182,70 @@ function readConfig(raw) {
81
182
  notifyFormatOnSave: r["notifyFormatOnSave"] !== false
82
183
  };
83
184
  }
185
+ var MAX_CAPTURE_BYTES = 4 * 1024 * 1024;
84
186
  function runCommand(command, args, timeoutMs, cwd) {
85
- return new Promise((resolve2) => {
187
+ return new Promise((resolve3) => {
86
188
  let timedOut = false;
189
+ let settled = false;
190
+ const settle = (r) => {
191
+ if (settled) return;
192
+ settled = true;
193
+ resolve3(r);
194
+ };
87
195
  const stdoutChunks = [];
88
196
  const stderrChunks = [];
197
+ let stdoutBytes = 0;
198
+ let stderrBytes = 0;
199
+ const signal = AbortSignal.timeout(timeoutMs);
200
+ const onAbort = () => {
201
+ timedOut = true;
202
+ settle({ code: null, stdout: "", stderr: "", timedOut: true });
203
+ };
204
+ signal.addEventListener("abort", onAbort, { once: true });
89
205
  let child;
206
+ let invocation;
207
+ try {
208
+ invocation = resolveExecInvocation(command, args);
209
+ } catch {
210
+ signal.removeEventListener("abort", onAbort);
211
+ settle({ code: 127, stdout: "", stderr: "", timedOut: false });
212
+ return;
213
+ }
90
214
  try {
91
- child = spawn(command, args, {
215
+ child = spawn(invocation.cmd, invocation.args, {
92
216
  cwd,
93
217
  stdio: ["ignore", "pipe", "pipe"],
94
- signal: AbortSignal.timeout(timeoutMs)
218
+ signal,
219
+ windowsHide: true,
220
+ ...invocation.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}
95
221
  });
96
222
  } catch {
97
- resolve2({ code: 127, stdout: "", stderr: "", timedOut: false });
223
+ signal.removeEventListener("abort", onAbort);
224
+ settle({ code: 127, stdout: "", stderr: "", timedOut: false });
98
225
  return;
99
226
  }
100
- child.stdout?.on("data", (c) => stdoutChunks.push(c));
101
- child.stderr?.on("data", (c) => stderrChunks.push(c));
227
+ child.stdout?.on("data", (c) => {
228
+ stdoutBytes += c.length;
229
+ if (stdoutBytes <= MAX_CAPTURE_BYTES) stdoutChunks.push(c);
230
+ });
231
+ child.stderr?.on("data", (c) => {
232
+ stderrBytes += c.length;
233
+ if (stderrBytes <= MAX_CAPTURE_BYTES) stderrChunks.push(c);
234
+ });
102
235
  child.on("error", () => {
103
- resolve2({ code: 127, stdout: "", stderr: "", timedOut: false });
236
+ signal.removeEventListener("abort", onAbort);
237
+ settle({ code: 127, stdout: "", stderr: "", timedOut: false });
104
238
  });
105
239
  child.on("close", (code) => {
240
+ signal.removeEventListener("abort", onAbort);
106
241
  if (timedOut) return;
107
- resolve2({
242
+ settle({
108
243
  code,
109
244
  stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
110
245
  stderr: Buffer.concat(stderrChunks).toString("utf-8"),
111
246
  timedOut: false
112
247
  });
113
248
  });
114
- child.on("abort", () => {
115
- timedOut = true;
116
- resolve2({ code: null, stdout: "", stderr: "", timedOut: true });
117
- });
118
249
  });
119
250
  }
120
251
  async function organizeImports(filePath, cfg, cwd) {
@@ -198,7 +329,7 @@ var plugin = {
198
329
  state.organizedCount = 0;
199
330
  state.cleanCount = 0;
200
331
  state.errorCount = 0;
201
- state.hookUnregister = null;
332
+ state.hookUnregister = releaseHandle(state.hookUnregister);
202
333
  state.lastResult = null;
203
334
  state.probeComplete = false;
204
335
  state.linterAvailable = false;