@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
@@ -1,39 +1,24 @@
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 });
10
+ }
11
+ return to;
12
+ };
13
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
14
+
1
15
  // src/test-coverage-gate/index.ts
2
16
  import { readFileSync } from "node:fs";
3
17
 
4
18
  // src/runtime/index.ts
5
- import { basename, extname, isAbsolute, relative, resolve } from "node:path";
6
-
7
- // src/runtime/local-bin.ts
8
- import { buildWin32CmdShimInvocation, resolveWin32Command } from "@wrongstack/tools/win32";
9
-
10
- // src/runtime/handles.ts
11
- function releaseHandle(off) {
12
- if (off) {
13
- try {
14
- off();
15
- } catch {
16
- }
17
- }
18
- return null;
19
- }
20
-
21
- // src/runtime/index.ts
22
- var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
23
- function hasLeadingDash(arg) {
24
- return arg.length > 0 && arg.startsWith("-");
25
- }
26
- function withinProjectPath(projectRoot, candidate) {
27
- if (candidate.length === 0 || candidate.length > 4096) return false;
28
- if (hasLeadingDash(candidate)) return false;
29
- const resolved = isAbsolute(candidate) ? resolve(candidate) : resolve(projectRoot, candidate);
30
- const rel = relative(projectRoot, resolved);
31
- return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
32
- }
33
- function withinProject(p) {
34
- const cwd = process.cwd();
35
- return withinProjectPath(cwd, p) || relative(cwd, p) === ".";
36
- }
19
+ var runtime_exports = {};
20
+ __reExport(runtime_exports, runtime_star);
21
+ import * as runtime_star from "@wrongstack/plugin-sdk/runtime";
37
22
 
38
23
  // src/test-coverage-gate/index.ts
39
24
  var API_VERSION = "^0.1.10";
@@ -146,7 +131,7 @@ var plugin = {
146
131
  state.skippedCount = 0;
147
132
  state.lastOverallPct = null;
148
133
  state.lastResult = null;
149
- state.hookUnregister = releaseHandle(state.hookUnregister);
134
+ state.hookUnregister = (0, runtime_exports.releaseHandle)(state.hookUnregister);
150
135
  const cfg = readConfig(api.config.extensions?.["test-coverage-gate"]);
151
136
  const hook = (input) => {
152
137
  if (!cfg.enabled) return;
@@ -154,7 +139,7 @@ var plugin = {
154
139
  const inp = input.toolInput ?? {};
155
140
  const sourcePath = inp["path"];
156
141
  if (!sourcePath || typeof sourcePath !== "string") return;
157
- if (!withinProject(sourcePath)) return;
142
+ if (!(0, runtime_exports.withinProject)(sourcePath)) return;
158
143
  const ext = sourcePath.includes(".") ? sourcePath.slice(sourcePath.lastIndexOf(".")).toLowerCase() : "";
159
144
  if (!runOnChangeSet.has(ext)) {
160
145
  state.skippedCount += 1;
@@ -3,41 +3,12 @@ import { readFileSync } from "node:fs";
3
3
  import { isAbsolute, relative, resolve } from "node:path";
4
4
 
5
5
  // src/runtime/llm.ts
6
- function stripOuterMarkdownFence(text) {
7
- const trimmed = text.trim();
8
- const match = trimmed.match(/^```(?:[a-z0-9_-]+)?\s*\r?\n([\s\S]*?)\r?\n```$/i);
9
- return (match?.[1] ?? trimmed).trim();
10
- }
11
- async function runOptionalPluginLlm(request) {
12
- if (!request.requested) {
13
- return { used: false, value: null, fallbackReason: "not-requested" };
14
- }
15
- if (!request.api.llm) {
16
- return { used: false, value: null, fallbackReason: "unavailable" };
17
- }
18
- if (request.options?.signal?.aborted) {
19
- return { used: false, value: null, fallbackReason: "cancelled" };
20
- }
21
- try {
22
- const response = await request.api.llm.complete(request.prompt, request.options);
23
- const parsed = request.parse(response.text);
24
- if (parsed === null) {
25
- request.api.log.warn(`${request.label}: ignored invalid LLM response`);
26
- return { used: false, value: null, fallbackReason: "invalid-response" };
27
- }
28
- return { used: true, value: parsed, fallbackReason: null };
29
- } catch (error) {
30
- const cancelled = request.options?.signal?.aborted === true;
31
- request.api.log.warn(`${request.label}: LLM enrichment failed; using deterministic fallback`, {
32
- error: error instanceof Error ? error.message : String(error)
33
- });
34
- return {
35
- used: false,
36
- value: null,
37
- fallbackReason: cancelled ? "cancelled" : "provider-error"
38
- };
39
- }
40
- }
6
+ import {
7
+ parseLlmJsonObject,
8
+ runOptionalPluginCouncil,
9
+ runOptionalPluginLlm,
10
+ stripOuterMarkdownFence
11
+ } from "@wrongstack/plugin-sdk/runtime";
41
12
 
42
13
  // src/test-generator/index.ts
43
14
  var API_VERSION = "^0.1.10";
@@ -1,143 +1,34 @@
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 });
10
+ }
11
+ return to;
12
+ };
13
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
14
+
1
15
  // src/test-runner-gate/index.ts
2
16
  import { execFile } from "node:child_process";
3
17
  import { access } from "node:fs/promises";
4
- import { basename as basename2, dirname, isAbsolute as isAbsolute2, join } from "node:path";
5
- import { buildWin32CmdShimInvocation as buildWin32CmdShimInvocation2, resolveWin32Command as resolveWin32Command2 } from "@wrongstack/tools/win32";
6
-
7
- // src/runtime/index.ts
8
- import { basename, extname, isAbsolute, relative, resolve } from "node:path";
9
-
10
- // src/runtime/local-bin.ts
18
+ import { basename, dirname, isAbsolute, join } from "node:path";
11
19
  import { buildWin32CmdShimInvocation, resolveWin32Command } from "@wrongstack/tools/win32";
12
20
 
13
- // src/runtime/bounded-map.ts
14
- var BoundedMap = class {
15
- map = /* @__PURE__ */ new Map();
16
- max;
17
- ttlMs;
18
- now;
19
- /** Entries dropped to stay under `max`. Surfaced by plugin health(). */
20
- evictions = 0;
21
- constructor(options) {
22
- const normalizedMax = Math.floor(options.max);
23
- this.max = Number.isSafeInteger(normalizedMax) ? Math.max(1, normalizedMax) : 1;
24
- this.ttlMs = options.ttlMs;
25
- this.now = options.now ?? Date.now;
26
- }
27
- expired(entry) {
28
- return this.ttlMs !== void 0 && this.now() - entry.storedAt > this.ttlMs;
29
- }
30
- get(key) {
31
- const entry = this.map.get(key);
32
- if (entry === void 0) return void 0;
33
- if (this.expired(entry)) {
34
- this.map.delete(key);
35
- return void 0;
36
- }
37
- this.map.delete(key);
38
- this.map.set(key, entry);
39
- return entry.value;
40
- }
41
- /**
42
- * Read without promoting the key to most-recently-used. Use for
43
- * diagnostics that must not perturb the eviction order.
44
- */
45
- peek(key) {
46
- const entry = this.map.get(key);
47
- if (entry === void 0 || this.expired(entry)) return void 0;
48
- return entry.value;
49
- }
50
- has(key) {
51
- const entry = this.map.get(key);
52
- if (entry === void 0) return false;
53
- if (this.expired(entry)) {
54
- this.map.delete(key);
55
- return false;
56
- }
57
- return true;
58
- }
59
- set(key, value) {
60
- this.map.delete(key);
61
- this.map.set(key, { value, storedAt: this.now() });
62
- while (this.map.size > this.max) {
63
- const coldest = this.map.keys().next().value;
64
- if (coldest === void 0) break;
65
- this.map.delete(coldest);
66
- this.evictions += 1;
67
- }
68
- return this;
69
- }
70
- delete(key) {
71
- return this.map.delete(key);
72
- }
73
- clear() {
74
- this.map.clear();
75
- this.evictions = 0;
76
- }
77
- get size() {
78
- return this.map.size;
79
- }
80
- /** How many entries have been dropped to respect `max`, since the last clear. */
81
- get evictionCount() {
82
- return this.evictions;
83
- }
84
- /** Drop every expired entry. Cheap enough to call from a status tool. */
85
- prune() {
86
- if (this.ttlMs === void 0) return 0;
87
- let removed = 0;
88
- for (const [key, entry] of this.map) {
89
- if (this.expired(entry)) {
90
- this.map.delete(key);
91
- removed += 1;
92
- }
93
- }
94
- return removed;
95
- }
96
- /** Live (non-expired) entries, coldest first. */
97
- *entries() {
98
- for (const [key, entry] of this.map) {
99
- if (!this.expired(entry)) yield [key, entry.value];
100
- }
101
- }
102
- [Symbol.iterator]() {
103
- return this.entries();
104
- }
105
- };
106
-
107
- // src/runtime/handles.ts
108
- function releaseHandle(off) {
109
- if (off) {
110
- try {
111
- off();
112
- } catch {
113
- }
114
- }
115
- return null;
116
- }
117
-
118
21
  // src/runtime/index.ts
119
- var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
120
- function hasLeadingDash(arg) {
121
- return arg.length > 0 && arg.startsWith("-");
122
- }
123
- function withinProjectPath(projectRoot, candidate) {
124
- if (candidate.length === 0 || candidate.length > 4096) return false;
125
- if (hasLeadingDash(candidate)) return false;
126
- const resolved = isAbsolute(candidate) ? resolve(candidate) : resolve(projectRoot, candidate);
127
- const rel = relative(projectRoot, resolved);
128
- return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
129
- }
130
- function withinProject(p) {
131
- const cwd = process.cwd();
132
- return withinProjectPath(cwd, p) || relative(cwd, p) === ".";
133
- }
22
+ var runtime_exports = {};
23
+ __reExport(runtime_exports, runtime_star);
24
+ import * as runtime_star from "@wrongstack/plugin-sdk/runtime";
134
25
 
135
26
  // src/test-runner-gate/index.ts
136
27
  function resolveExec(command, args) {
137
- const resolved = resolveWin32Command2(command);
28
+ const resolved = resolveWin32Command(command);
138
29
  const needsShell = process.platform === "win32" && (resolved.endsWith(".cmd") || resolved.endsWith(".bat"));
139
30
  if (needsShell) {
140
- const shim = buildWin32CmdShimInvocation2(resolved, args);
31
+ const shim = buildWin32CmdShimInvocation(resolved, args);
141
32
  return { cmd: shim.command, args: shim.args, windowsVerbatimArguments: true };
142
33
  }
143
34
  return { cmd: resolved, args: [...args], windowsVerbatimArguments: false };
@@ -206,7 +97,7 @@ function pathContentHash(content) {
206
97
  }
207
98
  return h >>> 0;
208
99
  }
209
- var lastPassedHash = new BoundedMap({ max: 1024 });
100
+ var lastPassedHash = new runtime_exports.BoundedMap({ max: 1024 });
210
101
  var ALLOWED_COMMAND_TOKENS = /* @__PURE__ */ new Set([
211
102
  "npx",
212
103
  "pnpm",
@@ -222,7 +113,7 @@ var ALLOWED_COMMAND_TOKENS = /* @__PURE__ */ new Set([
222
113
  // by basename in resolveAllowedCommand().
223
114
  ]);
224
115
  function resolveTestFiles(sourcePath, patterns) {
225
- const name = basename2(sourcePath).replace(/\.[^.]+$/, "");
116
+ const name = basename(sourcePath).replace(/\.[^.]+$/, "");
226
117
  const pathNoExt = sourcePath.replace(/\.[^.]+$/, "");
227
118
  const dir = dirname(sourcePath);
228
119
  const candidates = [];
@@ -260,7 +151,7 @@ async function detectRunner(requested) {
260
151
  const match = candidates.find((c) => c.name === requested);
261
152
  if (!match) return null;
262
153
  try {
263
- await new Promise((resolve2, reject) => {
154
+ await new Promise((resolve, reject) => {
264
155
  const ex = resolveExec("npx", [`${match.name}`, "--version"]);
265
156
  execFile(ex.cmd, ex.args, {
266
157
  encoding: "utf-8",
@@ -268,7 +159,7 @@ async function detectRunner(requested) {
268
159
  cwd: process.cwd(),
269
160
  windowsHide: true,
270
161
  ...ex.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}
271
- }, (err) => err ? reject(err) : resolve2());
162
+ }, (err) => err ? reject(err) : resolve());
272
163
  });
273
164
  return match;
274
165
  } catch {
@@ -277,7 +168,7 @@ async function detectRunner(requested) {
277
168
  }
278
169
  for (const candidate of candidates) {
279
170
  try {
280
- await new Promise((resolve2, reject) => {
171
+ await new Promise((resolve, reject) => {
281
172
  const ex = resolveExec("npx", [`${candidate.name}`, "--version"]);
282
173
  execFile(ex.cmd, ex.args, {
283
174
  encoding: "utf-8",
@@ -285,7 +176,7 @@ async function detectRunner(requested) {
285
176
  cwd: process.cwd(),
286
177
  windowsHide: true,
287
178
  ...ex.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}
288
- }, (err) => err ? reject(err) : resolve2());
179
+ }, (err) => err ? reject(err) : resolve());
289
180
  });
290
181
  return candidate;
291
182
  } catch {
@@ -300,9 +191,9 @@ function resolveAllowedCommand(customCommand) {
300
191
  if (ALLOWED_COMMAND_TOKENS.has(head)) {
301
192
  return { cmd: head, args: tokens.slice(1) };
302
193
  }
303
- if (isAbsolute2(head)) {
304
- if (!withinProject(head)) return null;
305
- const base = basename2(head);
194
+ if (isAbsolute(head)) {
195
+ if (!(0, runtime_exports.withinProject)(head)) return null;
196
+ const base = basename(head);
306
197
  if (ALLOWED_COMMAND_TOKENS.has(base)) {
307
198
  return { cmd: head, args: tokens.slice(1) };
308
199
  }
@@ -310,7 +201,7 @@ function resolveAllowedCommand(customCommand) {
310
201
  return null;
311
202
  }
312
203
  async function runTests(testFile, runner, customCommand, timeoutMs) {
313
- if (!withinProject(testFile)) return null;
204
+ if (!(0, runtime_exports.withinProject)(testFile)) return null;
314
205
  let cmd;
315
206
  let cmdArgs;
316
207
  let trailingFlag;
@@ -331,7 +222,7 @@ async function runTests(testFile, runner, customCommand, timeoutMs) {
331
222
  let stdout = "";
332
223
  try {
333
224
  const { stdout: out } = await new Promise(
334
- (resolve2, reject) => {
225
+ (resolve, reject) => {
335
226
  const ex = resolveExec(cmd, fullArgs);
336
227
  execFile(
337
228
  ex.cmd,
@@ -345,7 +236,7 @@ async function runTests(testFile, runner, customCommand, timeoutMs) {
345
236
  },
346
237
  (err, out2, stderr) => {
347
238
  if (err) reject(Object.assign(err, { stdout: out2, stderr }));
348
- else resolve2({ stdout: out2, stderr });
239
+ else resolve({ stdout: out2, stderr });
349
240
  }
350
241
  );
351
242
  }
@@ -462,7 +353,7 @@ var plugin = {
462
353
  state.errorCount = 0;
463
354
  state.extensionSkippedCount = 0;
464
355
  state.cachedSkipCount = 0;
465
- state.hookUnregister = releaseHandle(state.hookUnregister);
356
+ state.hookUnregister = (0, runtime_exports.releaseHandle)(state.hookUnregister);
466
357
  state.lastResult = null;
467
358
  lastPassedHash.clear();
468
359
  const cfg = readConfig(api.config.extensions?.["test-runner-gate"]);
@@ -483,7 +374,7 @@ var plugin = {
483
374
  const inp = input.toolInput ?? {};
484
375
  const sourcePath = inp["path"];
485
376
  if (!sourcePath || typeof sourcePath !== "string") return;
486
- if (!withinProject(sourcePath)) return;
377
+ if (!(0, runtime_exports.withinProject)(sourcePath)) return;
487
378
  if (sourcePath.includes(".test.") || sourcePath.includes(".spec.")) return;
488
379
  if (cfg.enableExtensionFilter) {
489
380
  const ext = sourcePath.includes(".") ? sourcePath.slice(sourcePath.lastIndexOf(".")).toLowerCase() : "";
@@ -1,42 +1,21 @@
1
- // src/runtime/local-bin.ts
2
- import { buildWin32CmdShimInvocation, resolveWin32Command } from "@wrongstack/tools/win32";
3
-
4
- // src/runtime/safe-json.ts
5
- var UNSERIALIZABLE = "[unserializable]";
6
- function safeJsonStringify(value, indent) {
7
- try {
8
- const stack = [];
9
- const out = JSON.stringify(
10
- value,
11
- function replacer(_key, val) {
12
- if (typeof val === "bigint") return `${val.toString()}n`;
13
- if (val === null || typeof val !== "object") return val;
14
- while (stack.length > 0 && stack[stack.length - 1] !== this) stack.pop();
15
- if (stack.includes(val)) return "[circular]";
16
- stack.push(val);
17
- return val;
18
- },
19
- indent
20
- );
21
- return out ?? String(value);
22
- } catch {
23
- return UNSERIALIZABLE;
24
- }
25
- }
26
-
27
- // src/runtime/handles.ts
28
- function releaseHandle(off) {
29
- if (off) {
30
- try {
31
- off();
32
- } catch {
33
- }
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 });
34
10
  }
35
- return null;
36
- }
11
+ return to;
12
+ };
13
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
37
14
 
38
15
  // src/runtime/index.ts
39
- var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
16
+ var runtime_exports = {};
17
+ __reExport(runtime_exports, runtime_star);
18
+ import * as runtime_star from "@wrongstack/plugin-sdk/runtime";
40
19
 
41
20
  // src/todo-listener/index.ts
42
21
  var state = {
@@ -111,7 +90,7 @@ var plugin = {
111
90
  state.lastMessageId = null;
112
91
  state.lastPayloadHash = "";
113
92
  state.lastBroadcastAt = 0;
114
- state.hookUnregister = releaseHandle(state.hookUnregister);
93
+ state.hookUnregister = (0, runtime_exports.releaseHandle)(state.hookUnregister);
115
94
  const cfg = readConfig(api.config.extensions?.["todo-listener"]);
116
95
  const mailbox = api.mailbox;
117
96
  const hook = async (input) => {
@@ -152,7 +131,7 @@ var plugin = {
152
131
  0,
153
132
  200
154
133
  );
155
- const body = safeJsonStringify(payload, 2);
134
+ const body = (0, runtime_exports.safeJsonStringify)(payload, 2);
156
135
  const sendInput = {
157
136
  from: `plugin:todo-listener`,
158
137
  to: "*",