@wrongstack/plugins 0.316.2 → 0.317.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 (72) hide show
  1. package/dist/accessibility-auditor.js +12 -10
  2. package/dist/agent-handoff.js +30 -10
  3. package/dist/auto-doc.js +22 -9
  4. package/dist/auto-escalate.js +17 -7
  5. package/dist/auto-i18n-extractor.js +19 -9
  6. package/dist/branch-guard.js +12 -9
  7. package/dist/changelog-writer/index.d.ts +3 -3
  8. package/dist/changelog-writer.js +59 -14
  9. package/dist/checkpoint.js +18 -7
  10. package/dist/code-metrics.js +17 -9
  11. package/dist/commit-validator.js +18 -11
  12. package/dist/config-validator.js +5 -3
  13. package/dist/context-pins.js +21 -9
  14. package/dist/cost-tracker.js +24 -16
  15. package/dist/cron.js +17 -13
  16. package/dist/dead-code-detector.js +5 -4
  17. package/dist/dep-guard.js +5 -4
  18. package/dist/dependency-vulnerability-gate.js +64 -24
  19. package/dist/diff-summary.js +6 -2
  20. package/dist/doc-sync-guard.js +12 -2
  21. package/dist/duplicate-code-detector.js +87 -15
  22. package/dist/error-lens.js +6 -5
  23. package/dist/feature-flag-tracker.js +43 -9
  24. package/dist/file-watcher.js +26 -3
  25. package/dist/format-on-save.js +9 -5
  26. package/dist/git-autocommit.js +20 -12
  27. package/dist/gitignore-guard.js +7 -4
  28. package/dist/import-organizer.js +9 -5
  29. package/dist/index.js +1684 -751
  30. package/dist/injection-shield/index.d.ts +1 -0
  31. package/dist/injection-shield.js +30 -5
  32. package/dist/interface-contract-guard.js +4 -2
  33. package/dist/knowledge-graph.js +43 -16
  34. package/dist/license-audit-gate.js +61 -8
  35. package/dist/lint-gate.js +13 -5
  36. package/dist/llm-cache.js +20 -6
  37. package/dist/loop-breaker.js +16 -8
  38. package/dist/migration-planner.js +80 -11
  39. package/dist/model-router.js +16 -9
  40. package/dist/notify-hub.js +14 -5
  41. package/dist/path-guard.js +7 -3
  42. package/dist/performance-regression-gate.js +12 -6
  43. package/dist/plugin-stack-observer.js +25 -3
  44. package/dist/pr-drafter.js +16 -7
  45. package/dist/process-guard.js +2 -1
  46. package/dist/prompt-firewall.js +9 -7
  47. package/dist/refactor-suggester.js +37 -8
  48. package/dist/release-notes-generator/index.d.ts +9 -0
  49. package/dist/release-notes-generator.js +50 -12
  50. package/dist/schema-evolution-guard.js +33 -6
  51. package/dist/secret-scanner.js +10 -7
  52. package/dist/security-hotspot-scanner.js +13 -8
  53. package/dist/semantic-search-indexer/index.d.ts +11 -0
  54. package/dist/semantic-search-indexer.js +67 -19
  55. package/dist/semver-bump/index.d.ts +3 -3
  56. package/dist/semver-bump.js +30 -15
  57. package/dist/session-recap/index.d.ts +16 -0
  58. package/dist/session-recap.js +18 -9
  59. package/dist/shell-check.js +29 -7
  60. package/dist/smart-rename.js +18 -9
  61. package/dist/spec-linker.js +70 -19
  62. package/dist/template-engine.js +24 -14
  63. package/dist/test-coverage-gate.js +1 -1
  64. package/dist/test-flake-detector.js +28 -5
  65. package/dist/test-generator/index.d.ts +10 -0
  66. package/dist/test-generator.js +35 -13
  67. package/dist/todo-listener.js +2 -2
  68. package/dist/todo-tracker.js +19 -11
  69. package/dist/token-budget.js +14 -9
  70. package/dist/token-throttle.js +8 -3
  71. package/dist/type-gate.js +9 -5
  72. package/package.json +5 -5
@@ -58,6 +58,7 @@ import type { Plugin } from '@wrongstack/core/types';
58
58
  */
59
59
  export declare function stripInvisible(text: string): string;
60
60
  export declare function scanForInjection(text: string): string[];
61
+ export declare function extractToolContent(toolResult: unknown): string;
61
62
  declare const plugin: Plugin;
62
63
  export default plugin;
63
64
  //# sourceMappingURL=index.d.ts.map
@@ -15,11 +15,14 @@ var DEFAULTS = {
15
15
  function readConfig(raw) {
16
16
  if (!raw || typeof raw !== "object") return { ...DEFAULTS };
17
17
  const r = raw;
18
+ const rawTools = r["tools"] ?? r["matcher"] ?? r["toolMatcher"] ?? r["tool_matcher"];
19
+ const rawMin = r["minMatches"] ?? r["min_matches"] ?? r["min"];
20
+ const rawMax = r["maxScanChars"] ?? r["max_scan_chars"] ?? r["maxChars"] ?? r["max_chars"];
18
21
  return {
19
22
  enabled: r["enabled"] !== false,
20
- tools: typeof r["tools"] === "string" && r["tools"].length > 0 ? r["tools"] : DEFAULTS.tools,
21
- minMatches: typeof r["minMatches"] === "number" && r["minMatches"] >= 1 && r["minMatches"] <= 10 ? r["minMatches"] : DEFAULTS.minMatches,
22
- maxScanChars: typeof r["maxScanChars"] === "number" && r["maxScanChars"] >= 1024 ? r["maxScanChars"] : DEFAULTS.maxScanChars
23
+ tools: typeof rawTools === "string" && rawTools.length > 0 ? rawTools : DEFAULTS.tools,
24
+ minMatches: typeof rawMin === "number" && rawMin >= 1 && rawMin <= 10 ? rawMin : DEFAULTS.minMatches,
25
+ maxScanChars: typeof rawMax === "number" && rawMax >= 1024 ? rawMax : DEFAULTS.maxScanChars
23
26
  };
24
27
  }
25
28
  var PATTERNS = [
@@ -78,6 +81,27 @@ function scanForInjection(text) {
78
81
  }
79
82
  return [...hits];
80
83
  }
84
+ function extractToolContent(toolResult) {
85
+ if (!toolResult) return "";
86
+ if (typeof toolResult === "string") return toolResult;
87
+ if (typeof toolResult === "object") {
88
+ const tr = toolResult;
89
+ if (typeof tr["content"] === "string") return tr["content"];
90
+ if (Array.isArray(tr["content"])) {
91
+ return tr["content"].map(
92
+ (item) => typeof item === "string" ? item : typeof item === "object" && item && typeof item["text"] === "string" ? item["text"] : ""
93
+ ).filter(Boolean).join("\n");
94
+ }
95
+ if (typeof tr["output"] === "string") return tr["output"];
96
+ if (typeof tr["stdout"] === "string") return tr["stdout"];
97
+ if (typeof tr["text"] === "string") return tr["text"];
98
+ if (typeof tr["result"] === "string") return tr["result"];
99
+ if (typeof tr["body"] === "string") return tr["body"];
100
+ if (typeof tr["contents"] === "string") return tr["contents"];
101
+ if (typeof tr["data"] === "string") return tr["data"];
102
+ }
103
+ return "";
104
+ }
81
105
  var plugin = {
82
106
  name: "injection-shield",
83
107
  version: "0.1.0",
@@ -125,8 +149,8 @@ var plugin = {
125
149
  const hook = (input) => {
126
150
  if (!cfg.enabled) return;
127
151
  state.invocations += 1;
128
- const content = input.toolResult?.content;
129
- if (typeof content !== "string" || content.length === 0) return;
152
+ const content = extractToolContent(input.toolResult);
153
+ if (content.length === 0) return;
130
154
  state.scans += 1;
131
155
  const hits = scanForInjection(content.slice(0, cfg.maxScanChars));
132
156
  if (hits.length < cfg.minMatches) return;
@@ -211,6 +235,7 @@ var plugin = {
211
235
  var injection_shield_default = plugin;
212
236
  export {
213
237
  injection_shield_default as default,
238
+ extractToolContent,
214
239
  scanForInjection,
215
240
  stripInvisible
216
241
  };
@@ -175,7 +175,8 @@ var plugin = {
175
175
  if (!cfg.enabled) return;
176
176
  if (input.toolResult?.isError) return;
177
177
  const inp = input.toolInput ?? {};
178
- const sourcePath = inp["path"];
178
+ const rawPath = inp["path"] ?? inp["TargetFile"] ?? inp["filePath"] ?? inp["targetFile"] ?? inp["file_path"] ?? inp["file"];
179
+ const sourcePath = typeof rawPath === "string" && rawPath.trim() ? rawPath.trim() : void 0;
179
180
  if (!sourcePath || typeof sourcePath !== "string") return;
180
181
  if (!(0, runtime_exports.withinProject)(sourcePath)) return;
181
182
  const exts = normalizeExtensions(cfg.extensions);
@@ -214,7 +215,8 @@ If you changed member shapes, search the project for implementers/\`satisfies\`/
214
215
  mutating: false,
215
216
  async execute(input) {
216
217
  if (!cfg.enabled) return { ok: false, error: "interface-contract-guard is disabled" };
217
- const rawPath = typeof input.path === "string" ? input.path : ".";
218
+ const raw = input ?? {};
219
+ const rawPath = (typeof input.path === "string" && input.path.trim().length > 0 ? input.path.trim() : void 0) ?? (typeof raw["directory"] === "string" ? raw["directory"] : void 0) ?? (typeof raw["dir"] === "string" ? raw["dir"] : void 0) ?? (typeof raw["SearchDirectory"] === "string" ? raw["SearchDirectory"] : void 0) ?? (typeof raw["TargetFile"] === "string" ? raw["TargetFile"] : void 0) ?? (typeof raw["filePath"] === "string" ? raw["filePath"] : void 0) ?? (typeof raw["targetFile"] === "string" ? raw["targetFile"] : void 0) ?? (typeof raw["file"] === "string" ? raw["file"] : void 0) ?? ".";
218
220
  if (!(0, runtime_exports.withinProject)(rawPath)) {
219
221
  return { ok: false, error: "path is outside the project root" };
220
222
  }
@@ -25,19 +25,24 @@ function resolveProjectPath(rawPath, cwd = process.cwd()) {
25
25
  const root = resolve(cwd);
26
26
  const resolved = isAbsolute(rawPath) ? resolve(rawPath) : resolve(root, rawPath);
27
27
  const rel = relative(root, resolved);
28
- if (rel === "" || !rel.startsWith("..") && !isAbsolute(rel)) return resolved;
29
- return null;
28
+ if (rel === "" || rel.startsWith("..") || isAbsolute(rel)) return null;
29
+ return resolved;
30
30
  }
31
31
  function readConfig(raw) {
32
32
  if (!raw || typeof raw !== "object") return { ...DEFAULTS };
33
33
  const r = raw;
34
+ const rawPath = typeof r["filePath"] === "string" ? r["filePath"] : typeof r["file_path"] === "string" ? r["file_path"] : typeof r["path"] === "string" ? r["path"] : typeof r["file"] === "string" ? r["file"] : DEFAULTS.filePath;
35
+ const rawMaxFacts = r["maxFacts"] ?? r["max_facts"] ?? r["limit"];
36
+ const rawMaxFactChars = r["maxFactChars"] ?? r["max_fact_chars"] ?? r["maxChars"] ?? r["max_chars"];
37
+ const rawContribute = r["contributeToSystemPrompt"] ?? r["contribute_to_system_prompt"] ?? r["contribute"];
38
+ const rawContributeMax = r["contributeMaxChars"] ?? r["contribute_max_chars"];
34
39
  return {
35
40
  enabled: r["enabled"] !== false,
36
- filePath: typeof r["filePath"] === "string" ? r["filePath"] : DEFAULTS.filePath,
37
- maxFacts: typeof r["maxFacts"] === "number" && r["maxFacts"] >= 1 && r["maxFacts"] <= 2e3 ? r["maxFacts"] : DEFAULTS.maxFacts,
38
- maxFactChars: typeof r["maxFactChars"] === "number" && r["maxFactChars"] >= 20 ? r["maxFactChars"] : DEFAULTS.maxFactChars,
39
- contributeToSystemPrompt: r["contributeToSystemPrompt"] !== false,
40
- contributeMaxChars: typeof r["contributeMaxChars"] === "number" && r["contributeMaxChars"] >= 100 ? r["contributeMaxChars"] : DEFAULTS.contributeMaxChars
41
+ filePath: typeof rawPath === "string" ? rawPath : DEFAULTS.filePath,
42
+ maxFacts: typeof rawMaxFacts === "number" && rawMaxFacts >= 1 && rawMaxFacts <= 2e3 ? rawMaxFacts : DEFAULTS.maxFacts,
43
+ maxFactChars: typeof rawMaxFactChars === "number" && rawMaxFactChars >= 20 ? rawMaxFactChars : DEFAULTS.maxFactChars,
44
+ contributeToSystemPrompt: rawContribute !== false,
45
+ contributeMaxChars: typeof rawContributeMax === "number" && rawContributeMax >= 100 ? rawContributeMax : DEFAULTS.contributeMaxChars
41
46
  };
42
47
  }
43
48
  function loadFacts(filePath) {
@@ -174,19 +179,28 @@ var plugin = {
174
179
  };
175
180
  }
176
181
  const trim = (s) => String(s ?? "").trim().slice(0, cfg.maxFactChars);
177
- const subject = trim(input.subject);
178
- const relation = trim(input.relation);
179
- const object = trim(input.object);
182
+ const raw = input;
183
+ const subject = trim(
184
+ input.subject ?? raw["entity"] ?? raw["topic"] ?? raw["sub"] ?? raw["name"] ?? raw["sourceEntity"]
185
+ );
186
+ const relation = trim(
187
+ input.relation ?? raw["predicate"] ?? raw["rel"] ?? raw["verb"] ?? raw["relationship"] ?? raw["action"]
188
+ );
189
+ const object = trim(
190
+ input.object ?? raw["target"] ?? raw["val"] ?? raw["value"] ?? raw["obj"] ?? raw["targetEntity"]
191
+ );
180
192
  if (!subject || !relation || !object) {
181
193
  return { ok: false, error: "subject, relation, and object are required" };
182
194
  }
195
+ const rawConf = typeof input.confidence === "string" ? input.confidence.trim().toLowerCase() : "";
196
+ const confidence = rawConf === "low" || rawConf === "high" || rawConf === "medium" ? rawConf : "medium";
183
197
  const fact = {
184
198
  id: `kg-${state.nextId++}`,
185
199
  subject,
186
200
  relation,
187
201
  object,
188
202
  source: input.source ? String(input.source).slice(0, cfg.maxFactChars) : null,
189
- confidence: input.confidence ?? "medium",
203
+ confidence,
190
204
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
191
205
  };
192
206
  state.facts.push(fact);
@@ -215,19 +229,29 @@ var plugin = {
215
229
  async execute(input) {
216
230
  if (!cfg.enabled) return { ok: false, error: "knowledge-graph is disabled" };
217
231
  state.queries += 1;
232
+ const raw = input;
233
+ const rawQ = (typeof raw["query"] === "string" ? raw["query"] : void 0) ?? (typeof raw["q"] === "string" ? raw["q"] : void 0);
234
+ const q = rawQ?.toLowerCase();
235
+ const rawFilterConf = typeof input.confidence === "string" ? input.confidence.trim().toLowerCase() : void 0;
236
+ const filterConf = rawFilterConf === "low" || rawFilterConf === "medium" || rawFilterConf === "high" ? rawFilterConf : void 0;
218
237
  const limit = typeof input.limit === "number" && input.limit >= 1 ? Math.floor(input.limit) : 20;
219
238
  const matches = state.facts.filter((f) => {
239
+ if (q) {
240
+ const hasMatch = f.subject.toLowerCase().includes(q) || f.relation.toLowerCase().includes(q) || f.object.toLowerCase().includes(q);
241
+ if (!hasMatch) return false;
242
+ }
220
243
  if (input.subject && !f.subject.toLowerCase().includes(input.subject.toLowerCase())) return false;
221
244
  if (input.relation && !f.relation.toLowerCase().includes(input.relation.toLowerCase())) return false;
222
245
  if (input.object && !f.object.toLowerCase().includes(input.object.toLowerCase())) return false;
223
- if (input.confidence && f.confidence !== input.confidence) return false;
246
+ if (filterConf && f.confidence.toLowerCase() !== filterConf) return false;
224
247
  return true;
225
248
  });
249
+ const returnedFacts = matches.slice(-limit);
226
250
  return {
227
251
  ok: true,
228
252
  totalFacts: state.facts.length,
229
- returned: Math.min(matches.length, limit),
230
- facts: matches.slice(-limit)
253
+ returned: returnedFacts.length,
254
+ facts: returnedFacts
231
255
  };
232
256
  }
233
257
  });
@@ -247,9 +271,12 @@ var plugin = {
247
271
  async execute(input) {
248
272
  if (!cfg.enabled) return { ok: false, error: "knowledge-graph is disabled" };
249
273
  const before = state.facts.length;
250
- state.facts = state.facts.filter((f) => f.id !== input.id);
274
+ const raw = input ?? {};
275
+ const rawId = String(input.id ?? raw["factId"] ?? raw["fact_id"] ?? "").trim();
276
+ const normalized = rawId.toLowerCase().startsWith("kg-") ? rawId.toLowerCase() : `kg-${rawId.toLowerCase()}`;
277
+ state.facts = state.facts.filter((f) => f.id.toLowerCase() !== normalized && f.id !== rawId);
251
278
  const removed = before - state.facts.length;
252
- if (removed === 0) return { ok: false, error: `no fact matches "${input.id}"` };
279
+ if (removed === 0) return { ok: false, error: `no fact matches "${input.id ?? rawId}"` };
253
280
  state.removals += removed;
254
281
  api.metrics.counter("removals", removed);
255
282
  const persisted = await persistFacts(resolved);
@@ -36,14 +36,14 @@ function readConfig(raw) {
36
36
  confirmTyposquatsWithLlm: r["confirmTyposquatsWithLlm"] === true
37
37
  };
38
38
  }
39
- var INSTALL_RE = /(?:^|[;&|]\s*)(npm|pnpm|yarn|bun)\s+(?:install|i|add)\s+([^;&|]+)|(?:^|[;&|]\s*)(pip3?|uv)\s+(?:pip\s+)?install\s+([^;&|]+)|(?:^|[;&|]\s*)(cargo)\s+add\s+([^;&|]+)/gi;
39
+ var INSTALL_RE = /(?:^|[;&|]\s*)(npm|pnpm|yarn|bun)\s+(?:install|i|add)\s+([^;&|]+)|(?:^|[;&|]\s*)(pip3?|uv)\s+(?:pip\s+)?install\s+([^;&|]+)|(?:^|[;&|]\s*)(uv)\s+add\s+([^;&|]+)|(?:^|[;&|]\s*)(cargo)\s+add\s+([^;&|]+)/gi;
40
40
  function parseInstallCommands(command) {
41
41
  const out = [];
42
42
  INSTALL_RE.lastIndex = 0;
43
43
  let m = INSTALL_RE.exec(command);
44
44
  while (m !== null) {
45
- const manager = (m[1] ?? m[3] ?? m[5] ?? "").toLowerCase();
46
- const argString = m[2] ?? m[4] ?? m[6] ?? "";
45
+ const manager = (m[1] ?? m[3] ?? m[5] ?? m[7] ?? "").toLowerCase();
46
+ const argString = m[2] ?? m[4] ?? m[6] ?? m[8] ?? "";
47
47
  const packages = [];
48
48
  for (const token of argString.split(/\s+/)) {
49
49
  if (!token || token.startsWith("-")) continue;
@@ -205,7 +205,8 @@ var plugin = {
205
205
  if (!cfg.enabled) return;
206
206
  state.invocations += 1;
207
207
  const ti = input.toolInput ?? {};
208
- const command = typeof ti["command"] === "string" ? ti["command"] : "";
208
+ const rawCmd = ti["command"] ?? ti["CommandLine"] ?? ti["cmd"] ?? ti["script"] ?? ti["input"];
209
+ const command = typeof rawCmd === "string" ? rawCmd : "";
209
210
  if (!command) return;
210
211
  const installs = parseInstallCommands(command);
211
212
  const packages = installs.flatMap((i) => i.packages);
@@ -400,11 +401,13 @@ function normalizeStrings(v) {
400
401
  function readConfig2(raw) {
401
402
  if (!raw || typeof raw !== "object") return { ...DEFAULTS2 };
402
403
  const r = raw;
403
- const allowed = normalizeStrings(r["allowedLicenses"]);
404
+ const rawLicenses = r["allowedLicenses"] ?? r["allowed_licenses"] ?? r["licenses"];
405
+ const allowed = normalizeStrings(rawLicenses);
406
+ const rawBlock = r["block"] ?? r["fail_on_violation"] ?? r["failOnViolation"];
404
407
  return {
405
408
  enabled: r["enabled"] !== false,
406
409
  allowedLicenses: allowed.length > 0 ? allowed : [...DEFAULTS2.allowedLicenses],
407
- block: r["block"] !== false
410
+ block: rawBlock !== false
408
411
  };
409
412
  }
410
413
  function extractLicenseStrings(pkg) {
@@ -430,6 +433,56 @@ function parsePackageNames(command) {
430
433
  ...new Set(parseInstallCommands(command).flatMap((entry) => entry.packages.map((pkg) => pkg.name)))
431
434
  ];
432
435
  }
436
+ function splitTopLevel(expr, separator) {
437
+ const parts = [];
438
+ let depth = 0;
439
+ let start = 0;
440
+ for (let i = 0; i < expr.length; i++) {
441
+ const ch = expr[i];
442
+ if (ch === "(") depth++;
443
+ else if (ch === ")") depth = Math.max(0, depth - 1);
444
+ else if (depth === 0) {
445
+ const match = separator.exec(expr.slice(i));
446
+ if (match && match.index === 0) {
447
+ parts.push(expr.slice(start, i).trim());
448
+ i += match[0].length - 1;
449
+ start = i + 1;
450
+ }
451
+ }
452
+ }
453
+ parts.push(expr.slice(start).trim());
454
+ return parts;
455
+ }
456
+ function isLicenseAllowed(licenseStr, normalizedAllowed) {
457
+ let expr = licenseStr.trim();
458
+ if (!expr) return false;
459
+ if (normalizedAllowed.has(expr.toLowerCase())) return true;
460
+ while (expr.startsWith("(")) {
461
+ let depth = 0;
462
+ let close = -1;
463
+ for (let i = 0; i < expr.length; i++) {
464
+ if (expr[i] === "(") depth++;
465
+ else if (expr[i] === ")") {
466
+ depth--;
467
+ if (depth === 0) {
468
+ close = i;
469
+ break;
470
+ }
471
+ }
472
+ }
473
+ if (close !== expr.length - 1) break;
474
+ expr = expr.slice(1, -1).trim();
475
+ }
476
+ const orParts = splitTopLevel(expr, /\s+OR\s+/i);
477
+ if (orParts.length > 1) {
478
+ return orParts.some((p) => isLicenseAllowed(p, normalizedAllowed));
479
+ }
480
+ const andParts = splitTopLevel(expr, /\s+AND\s+/i);
481
+ if (andParts.length > 1) {
482
+ return andParts.every((p) => isLicenseAllowed(p, normalizedAllowed));
483
+ }
484
+ return normalizedAllowed.has(expr.toLowerCase());
485
+ }
433
486
  function auditPackages(names, allowedLicenses) {
434
487
  const results = [];
435
488
  const errors = [];
@@ -443,7 +496,7 @@ function auditPackages(names, allowedLicenses) {
443
496
  } catch {
444
497
  errors.push(name);
445
498
  }
446
- const allowed = licenses.length > 0 && licenses.every((l) => normalizedAllowed.has(l.toLowerCase()));
499
+ const allowed = licenses.length > 0 && licenses.every((l) => isLicenseAllowed(l, normalizedAllowed));
447
500
  results.push({ name, licenses, allowed });
448
501
  }
449
502
  const ok = errors.length === 0 && results.every((r) => r.allowed);
@@ -498,7 +551,7 @@ var plugin2 = {
498
551
  if (!cfg.enabled) return;
499
552
  if (input.toolResult?.isError) return;
500
553
  const ti = input.toolInput ?? {};
501
- const command = typeof ti["command"] === "string" ? ti["command"] : "";
554
+ const command = (typeof ti["command"] === "string" ? ti["command"] : void 0) ?? (typeof ti["CommandLine"] === "string" ? ti["CommandLine"] : void 0) ?? (typeof ti["cmd"] === "string" ? ti["cmd"] : void 0) ?? (typeof ti["script"] === "string" ? ti["script"] : void 0) ?? "";
502
555
  if (!command) return;
503
556
  state2.invocations += 1;
504
557
  const names = parsePackageNames(command);
package/dist/lint-gate.js CHANGED
@@ -51,12 +51,20 @@ var DEFAULTS = {
51
51
  function readConfig(raw) {
52
52
  if (!raw || typeof raw !== "object") return { ...DEFAULTS };
53
53
  const r = raw;
54
+ const rawLinter = typeof r["linter"] === "string" ? r["linter"].trim().toLowerCase() : void 0;
55
+ const linter = rawLinter === "biome" || rawLinter === "eslint" ? rawLinter : "auto";
56
+ const rawMode = typeof (r["mode"] ?? r["action"] ?? r["behavior"]) === "string" ? String(r["mode"] ?? r["action"] ?? r["behavior"]).trim().toLowerCase() : void 0;
57
+ const mode = rawMode === "block" ? "block" : rawMode === "fix" ? "fix" : "warn";
58
+ const rawSeverity = typeof r["severity"] === "string" ? r["severity"].trim().toLowerCase() : void 0;
59
+ const severity = rawSeverity === "warning" ? "warning" : "error";
60
+ const rawTimeout = r["timeoutMs"] ?? r["timeout_ms"] ?? r["timeout"];
61
+ const rawRules = r["fixRules"] ?? r["fix_rules"] ?? r["rules"];
54
62
  return {
55
- linter: r["linter"] === "biome" || r["linter"] === "eslint" ? r["linter"] : "auto",
56
- mode: r["mode"] === "block" ? "block" : r["mode"] === "fix" ? "fix" : "warn",
57
- severity: r["severity"] === "warning" ? "warning" : "error",
58
- timeoutMs: typeof r["timeoutMs"] === "number" ? r["timeoutMs"] : DEFAULTS.timeoutMs,
59
- fixRules: Array.isArray(r["fixRules"]) ? r["fixRules"].filter((x) => typeof x === "string") : []
63
+ linter,
64
+ mode,
65
+ severity,
66
+ timeoutMs: typeof rawTimeout === "number" && rawTimeout > 0 ? rawTimeout : DEFAULTS.timeoutMs,
67
+ fixRules: Array.isArray(rawRules) ? rawRules.filter((x) => typeof x === "string") : []
60
68
  };
61
69
  }
62
70
  var LINTER_PACKAGES = {
package/dist/llm-cache.js CHANGED
@@ -20,12 +20,16 @@ var DEFAULTS = {
20
20
  function readConfig(raw) {
21
21
  if (!raw || typeof raw !== "object") return { ...DEFAULTS };
22
22
  const r = raw;
23
+ const rawMax = r["maxEntries"] ?? r["max_entries"] ?? r["limit"];
24
+ const rawTtl = r["ttlMs"] ?? r["ttl_ms"] ?? r["ttl"];
25
+ const rawDet = r["onlyDeterministic"] ?? r["only_deterministic"];
26
+ const rawZero = r["zeroUsageOnHit"] ?? r["zero_usage_on_hit"] ?? r["zeroUsage"] ?? r["zero_usage"];
23
27
  return {
24
28
  enabled: r["enabled"] === true,
25
- maxEntries: typeof r["maxEntries"] === "number" && r["maxEntries"] >= 1 ? Math.floor(r["maxEntries"]) : DEFAULTS.maxEntries,
26
- ttlMs: typeof r["ttlMs"] === "number" && r["ttlMs"] >= 0 ? r["ttlMs"] : DEFAULTS.ttlMs,
27
- onlyDeterministic: r["onlyDeterministic"] !== false,
28
- zeroUsageOnHit: r["zeroUsageOnHit"] === true
29
+ maxEntries: typeof rawMax === "number" && rawMax >= 1 ? Math.floor(rawMax) : DEFAULTS.maxEntries,
30
+ ttlMs: typeof rawTtl === "number" && rawTtl >= 0 ? rawTtl : DEFAULTS.ttlMs,
31
+ onlyDeterministic: rawDet !== false,
32
+ zeroUsageOnHit: rawZero === true
29
33
  };
30
34
  }
31
35
  function isDeterministic(request) {
@@ -36,6 +40,7 @@ var fingerprintCache = /* @__PURE__ */ new WeakMap();
36
40
  function fingerprintRequest(request) {
37
41
  const cached = fingerprintCache.get(request);
38
42
  if (cached) return cached;
43
+ const rawTools = request["tools"] ?? request["tool_definitions"] ?? request["toolDefinitions"] ?? request["functions"];
39
44
  const subset = {
40
45
  maxTokens: request["maxTokens"] ?? null,
41
46
  messages: request["messages"] ?? null,
@@ -45,7 +50,7 @@ function fingerprintRequest(request) {
45
50
  stopSequences: request["stopSequences"] ?? null,
46
51
  system: request["system"] ?? null,
47
52
  temperature: request["temperature"] ?? null,
48
- tools: Array.isArray(request["tools"]) ? request["tools"].map((t) => t?.name ?? t) : null,
53
+ tools: Array.isArray(rawTools) ? rawTools.map((t) => t?.name ?? t) : null,
49
54
  topK: request["topK"] ?? null,
50
55
  topP: request["topP"] ?? null
51
56
  };
@@ -173,7 +178,16 @@ var plugin = {
173
178
  api.metrics.counter("misses");
174
179
  const response = await inner(_ctx, request);
175
180
  const sr = response && typeof response === "object" ? response.stopReason : void 0;
176
- if (response && typeof response === "object" && (sr === "end_turn" || sr === "stop" || sr === "tool_use")) {
181
+ const normSr = typeof sr === "string" ? sr.toLowerCase() : "";
182
+ const validStopReasons = /* @__PURE__ */ new Set([
183
+ "end_turn",
184
+ "stop",
185
+ "tool_use",
186
+ "tool_calls",
187
+ "function_call",
188
+ "stop_sequence"
189
+ ]);
190
+ if (response && typeof response === "object" && validStopReasons.has(normSr)) {
177
191
  lruSet(key, response, cfg.maxEntries);
178
192
  }
179
193
  return response;
@@ -42,17 +42,24 @@ function readConfig(raw) {
42
42
  return { ...DEFAULTS };
43
43
  }
44
44
  const r = raw;
45
- const warnAfter = typeof r["warnAfter"] === "number" && r["warnAfter"] >= 2 ? r["warnAfter"] : DEFAULTS.warnAfter;
46
- const blockAfter = typeof r["blockAfter"] === "number" && r["blockAfter"] > warnAfter ? r["blockAfter"] : Math.max(DEFAULTS.blockAfter, warnAfter + 1);
47
- const ignoreTools = Array.isArray(r["ignoreTools"]) ? r["ignoreTools"].filter((t) => typeof t === "string") : [];
45
+ const rawWarn = r["warnAfter"] ?? r["warn_after"] ?? r["warnThreshold"] ?? r["warn_threshold"];
46
+ const warnAfter = typeof rawWarn === "number" && rawWarn >= 2 ? rawWarn : DEFAULTS.warnAfter;
47
+ const rawBlock = r["blockAfter"] ?? r["block_after"] ?? r["blockThreshold"] ?? r["block_threshold"];
48
+ const blockAfter = typeof rawBlock === "number" && rawBlock > warnAfter ? rawBlock : Math.max(DEFAULTS.blockAfter, warnAfter + 1);
49
+ const rawIgnore = r["ignoreTools"] ?? r["ignore_tools"] ?? r["ignore"] ?? r["ignoredTools"];
50
+ const ignoreTools = Array.isArray(rawIgnore) ? rawIgnore.filter((t) => typeof t === "string") : [];
48
51
  ignoreToolsSet = new Set(ignoreTools);
52
+ const rawMode = typeof (r["mode"] ?? r["action"] ?? r["behavior"]) === "string" ? String(r["mode"] ?? r["action"] ?? r["behavior"]).trim().toLowerCase() : void 0;
53
+ const mode = rawMode === "warn" ? "warn" : "block";
54
+ const rawOsc = r["oscillationWindow"] ?? r["oscillation_window"] ?? r["window"];
55
+ const rawMaxSteps = r["maxSteps"] ?? r["max_steps"] ?? r["stepLimit"] ?? r["step_limit"];
49
56
  return {
50
57
  enabled: r["enabled"] !== false,
51
- mode: r["mode"] === "warn" ? "warn" : "block",
58
+ mode,
52
59
  warnAfter,
53
60
  blockAfter,
54
- oscillationWindow: typeof r["oscillationWindow"] === "number" && r["oscillationWindow"] >= 4 ? r["oscillationWindow"] : DEFAULTS.oscillationWindow,
55
- maxSteps: typeof r["maxSteps"] === "number" && r["maxSteps"] >= 0 ? Math.floor(r["maxSteps"]) : DEFAULTS.maxSteps,
61
+ oscillationWindow: typeof rawOsc === "number" && rawOsc >= 4 ? rawOsc : DEFAULTS.oscillationWindow,
62
+ maxSteps: typeof rawMaxSteps === "number" && rawMaxSteps >= 0 ? Math.floor(rawMaxSteps) : DEFAULTS.maxSteps,
56
63
  noDiffWarnAfter: typeof r["noDiffWarnAfter"] === "number" && r["noDiffWarnAfter"] >= 1 ? Math.floor(r["noDiffWarnAfter"]) : DEFAULTS.noDiffWarnAfter,
57
64
  noDiffBlockAfter: typeof r["noDiffBlockAfter"] === "number" && r["noDiffBlockAfter"] >= 0 ? Math.floor(r["noDiffBlockAfter"]) : DEFAULTS.noDiffBlockAfter,
58
65
  repeatedErrorWarnAfter: typeof r["repeatedErrorWarnAfter"] === "number" && r["repeatedErrorWarnAfter"] >= 1 ? Math.floor(r["repeatedErrorWarnAfter"]) : DEFAULTS.repeatedErrorWarnAfter,
@@ -101,7 +108,7 @@ function isOscillating(recent, windowSize) {
101
108
  }
102
109
  return window[0] !== window[1];
103
110
  }
104
- var MUTATING_TOOLS = /* @__PURE__ */ new Set(["edit", "write"]);
111
+ var MUTATING_TOOLS = /* @__PURE__ */ new Set(["edit", "write", "write_to_file", "replace_file_content"]);
105
112
  function hashString(value) {
106
113
  let h = 5381;
107
114
  const cap = Math.min(value.length, 1e6);
@@ -339,7 +346,8 @@ var plugin = {
339
346
  state.repeatedErrorStreak = 0;
340
347
  if (!MUTATING_TOOLS.has(toolName)) return;
341
348
  const toolInput = input.toolInput ?? {};
342
- const targetPath = toolInput["path"];
349
+ const rawTarget = toolInput["path"] ?? toolInput["TargetFile"] ?? toolInput["filePath"] ?? toolInput["targetFile"] ?? toolInput["file_path"] ?? toolInput["destination"] ?? toolInput["file"];
350
+ const targetPath = typeof rawTarget === "string" ? rawTarget : void 0;
343
351
  if (typeof targetPath !== "string" || targetPath.length === 0) return;
344
352
  const diffFingerprint = await gitDiffFingerprint(
345
353
  input.cwd ?? process.cwd(),
@@ -49,12 +49,16 @@ var DEFAULTS = {
49
49
  function readConfig(raw) {
50
50
  if (!raw || typeof raw !== "object") return { ...DEFAULTS };
51
51
  const r = raw;
52
+ const rawPaths = r["changelogPaths"] ?? r["changelog_paths"] ?? r["paths"];
53
+ const rawMax = r["maxChars"] ?? r["max_chars"] ?? r["limit"];
54
+ const rawUseLlm = r["useLlm"] ?? r["use_llm"];
55
+ const rawMaxLlm = r["maxLlmChars"] ?? r["max_llm_chars"];
52
56
  return {
53
57
  enabled: r["enabled"] !== false,
54
- changelogPaths: Array.isArray(r["changelogPaths"]) ? r["changelogPaths"].filter((x) => typeof x === "string") : DEFAULTS.changelogPaths,
55
- maxChars: typeof r["maxChars"] === "number" && r["maxChars"] >= 1e3 && r["maxChars"] <= 1e6 ? r["maxChars"] : DEFAULTS.maxChars,
56
- useLlm: r["useLlm"] === true,
57
- maxLlmChars: typeof r["maxLlmChars"] === "number" && r["maxLlmChars"] >= 1e3 && r["maxLlmChars"] <= 1e5 ? r["maxLlmChars"] : DEFAULTS.maxLlmChars
58
+ changelogPaths: Array.isArray(rawPaths) ? rawPaths.filter((x) => typeof x === "string") : DEFAULTS.changelogPaths,
59
+ maxChars: typeof rawMax === "number" && rawMax >= 1e3 && rawMax <= 1e6 ? rawMax : DEFAULTS.maxChars,
60
+ useLlm: rawUseLlm === true,
61
+ maxLlmChars: typeof rawMaxLlm === "number" && rawMaxLlm >= 1e3 && rawMaxLlm <= 1e5 ? rawMaxLlm : DEFAULTS.maxLlmChars
58
62
  };
59
63
  }
60
64
  function normalizeVersion(v) {
@@ -280,7 +284,8 @@ var plugin = {
280
284
  if (!cfg.enabled) return;
281
285
  if (input.toolResult?.isError) return;
282
286
  const inp = input.toolInput ?? {};
283
- const path = inp["path"];
287
+ const rawPath = inp["path"] ?? inp["TargetFile"] ?? inp["filePath"] ?? inp["targetFile"] ?? inp["file_path"] ?? inp["file"];
288
+ const path = typeof rawPath === "string" ? rawPath : void 0;
284
289
  if (!path) return;
285
290
  const basename = path.split(/[/\\]/).pop() ?? "";
286
291
  if (!/^(package\.json|package-lock\.json|pnpm-lock\.yaml|yarn\.lock|bun\.lockb?)$/i.test(
@@ -305,14 +310,31 @@ var plugin = {
305
310
  type: "string",
306
311
  description: "Name of the npm package or framework."
307
312
  },
313
+ package: { type: "string", description: "Alias for packageName." },
314
+ pkg: { type: "string", description: "Alias for packageName." },
315
+ name: { type: "string", description: "Alias for packageName." },
316
+ package_name: { type: "string", description: "Alias for packageName." },
317
+ dependency: { type: "string", description: "Alias for packageName." },
318
+ dep: { type: "string", description: "Alias for packageName." },
319
+ module: { type: "string", description: "Alias for packageName." },
308
320
  fromVersion: {
309
321
  type: "string",
310
322
  description: 'Current version, e.g. "1.2.3".'
311
323
  },
324
+ from: { type: "string", description: "Alias for fromVersion." },
325
+ from_version: { type: "string", description: "Alias for fromVersion." },
326
+ currentVersion: { type: "string", description: "Alias for fromVersion." },
327
+ since: { type: "string", description: "Alias for fromVersion." },
328
+ start: { type: "string", description: "Alias for fromVersion." },
312
329
  toVersion: {
313
330
  type: "string",
314
331
  description: 'Target version, e.g. "2.0.0".'
315
332
  },
333
+ to: { type: "string", description: "Alias for toVersion." },
334
+ to_version: { type: "string", description: "Alias for toVersion." },
335
+ targetVersion: { type: "string", description: "Alias for toVersion." },
336
+ until: { type: "string", description: "Alias for toVersion." },
337
+ end: { type: "string", description: "Alias for toVersion." },
316
338
  scope: {
317
339
  type: "string",
318
340
  description: "Optional scope describing which parts of the project use the package."
@@ -320,9 +342,51 @@ var plugin = {
320
342
  use_llm: {
321
343
  type: "boolean",
322
344
  description: "Add evidence-bounded Council risk analysis with One Shot fallback. Overrides useLlm for this call."
323
- }
345
+ },
346
+ useLlm: { type: "boolean", description: "Alias for use_llm." },
347
+ use_ai: { type: "boolean", description: "Alias for use_llm." },
348
+ useAi: { type: "boolean", description: "Alias for use_llm." }
324
349
  },
325
- required: ["packageName", "fromVersion", "toVersion"]
350
+ // One name from each required field group must be sufficient for
351
+ // raw-schema validation. Note: the tool-wire flattener strips
352
+ // top-level combinators (docs/tool-author-guide.md), so wire-level
353
+ // guidance loses these required markers by design — the executor
354
+ // remains the authoritative validator and reports missing canonical
355
+ // fields with a clear error.
356
+ allOf: [
357
+ {
358
+ anyOf: [
359
+ { required: ["packageName"] },
360
+ { required: ["package"] },
361
+ { required: ["pkg"] },
362
+ { required: ["name"] },
363
+ { required: ["package_name"] },
364
+ { required: ["dependency"] },
365
+ { required: ["dep"] },
366
+ { required: ["module"] }
367
+ ]
368
+ },
369
+ {
370
+ anyOf: [
371
+ { required: ["fromVersion"] },
372
+ { required: ["from"] },
373
+ { required: ["from_version"] },
374
+ { required: ["currentVersion"] },
375
+ { required: ["since"] },
376
+ { required: ["start"] }
377
+ ]
378
+ },
379
+ {
380
+ anyOf: [
381
+ { required: ["toVersion"] },
382
+ { required: ["to"] },
383
+ { required: ["to_version"] },
384
+ { required: ["targetVersion"] },
385
+ { required: ["until"] },
386
+ { required: ["end"] }
387
+ ]
388
+ }
389
+ ]
326
390
  },
327
391
  permission: "auto",
328
392
  category: "Planning",
@@ -330,9 +394,14 @@ var plugin = {
330
394
  async execute(input, _ctx, execOpts) {
331
395
  if (!cfg.enabled) return { ok: false, error: "migration-planner is disabled" };
332
396
  execOpts?.signal?.throwIfAborted();
333
- const packageName = String(input.packageName ?? "").trim();
334
- const fromVersion = String(input.fromVersion ?? "").trim();
335
- const toVersion = String(input.toVersion ?? "").trim();
397
+ const raw = input ?? {};
398
+ const rawPackage = input.packageName || raw["package"] || raw["pkg"] || raw["name"] || raw["package_name"] || raw["packageName"] || raw["dependency"] || raw["dep"] || raw["module"];
399
+ const rawFrom = input.fromVersion || raw["from"] || raw["from_version"] || raw["fromVersion"] || raw["currentVersion"] || raw["since"] || raw["start"];
400
+ const rawTo = input.toVersion || raw["to"] || raw["to_version"] || raw["toVersion"] || raw["targetVersion"] || raw["until"] || raw["end"];
401
+ const rawUseLlm = input.use_llm ?? raw["useLlm"] ?? raw["use_ai"] ?? raw["useAi"];
402
+ const packageName = String(rawPackage ?? "").trim();
403
+ const fromVersion = String(rawFrom ?? "").trim();
404
+ const toVersion = String(rawTo ?? "").trim();
336
405
  if (!packageName || !fromVersion || !toVersion) {
337
406
  return { ok: false, error: "packageName, fromVersion, and toVersion are required" };
338
407
  }
@@ -357,7 +426,7 @@ var plugin = {
357
426
  evidence = `No local changelog was found for ${packageName}.`;
358
427
  }
359
428
  execOpts?.signal?.throwIfAborted();
360
- const requested = input.use_llm ?? cfg.useLlm;
429
+ const requested = typeof rawUseLlm === "boolean" ? rawUseLlm : cfg.useLlm;
361
430
  const llm = await runOptionalPluginCouncil({
362
431
  requested,
363
432
  api,