@wrongstack/plugins 0.319.0 → 0.319.1

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.
package/dist/index.js CHANGED
@@ -175,7 +175,12 @@ async function auditFile(filePath, projectRoot) {
175
175
  );
176
176
  }
177
177
  if (!hasPrimaryLabel && ATTR_PLACEHOLDER.test(tag)) {
178
- add(lineNo, "low-contrast-placeholder", "warning", "<input> uses placeholder text (often low contrast and disappears on input)");
178
+ add(
179
+ lineNo,
180
+ "low-contrast-placeholder",
181
+ "warning",
182
+ "<input> uses placeholder text (often low contrast and disappears on input)"
183
+ );
179
184
  }
180
185
  }
181
186
  TAG_INPUT.lastIndex = 0;
@@ -186,14 +191,24 @@ async function auditFile(filePath, projectRoot) {
186
191
  const hasAriaLabel = ATTR_ARIA_LABEL.test(tag);
187
192
  const hasTitle = ATTR_TITLE.test(tag);
188
193
  if (!hasText && !hasAriaLabel && !hasTitle) {
189
- add(lineNo, "missing-button-text", "error", "<button> has no visible text or accessible label");
194
+ add(
195
+ lineNo,
196
+ "missing-button-text",
197
+ "error",
198
+ "<button> has no visible text or accessible label"
199
+ );
190
200
  }
191
201
  }
192
202
  TAG_BUTTON.lastIndex = 0;
193
203
  for (const inputButtonMatch of line.matchAll(INPUT_BUTTON)) {
194
204
  const tag = inputButtonMatch[0];
195
205
  if (!ATTR_VALUE.test(tag) && !ATTR_ARIA_LABEL.test(tag) && !ATTR_TITLE.test(tag)) {
196
- add(lineNo, "missing-button-text", "error", `<input type="${inputButtonMatch[1]}"> is missing value/aria-label/title`);
206
+ add(
207
+ lineNo,
208
+ "missing-button-text",
209
+ "error",
210
+ `<input type="${inputButtonMatch[1]}"> is missing value/aria-label/title`
211
+ );
197
212
  }
198
213
  }
199
214
  INPUT_BUTTON.lastIndex = 0;
@@ -328,7 +343,9 @@ var plugin = {
328
343
  }
329
344
  return { additionalContext: summary };
330
345
  };
331
- state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
346
+ state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, {
347
+ background: true
348
+ });
332
349
  api.tools.register({
333
350
  name: "a11y_audit",
334
351
  description: "Audit a file or directory for accessibility issues. Scans .tsx/.jsx/.html/.vue files for missing alt text, missing labels, low-contrast placeholders, missing button text, and duplicate ids.",
@@ -1058,7 +1075,9 @@ var plugin3 = {
1058
1075
  }
1059
1076
  return { additionalContext: message };
1060
1077
  };
1061
- state3.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
1078
+ state3.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, {
1079
+ background: true
1080
+ });
1062
1081
  api.tools.register({
1063
1082
  name: "api_compat_status",
1064
1083
  description: "Reports api-compatibility-gate state: severity, entry-point patterns, and per-session counters.",
@@ -1760,7 +1779,9 @@ function looksLikeUserText(value, minLength) {
1760
1779
  if (value.length < minLength) return false;
1761
1780
  if (/^\s*$/.test(value)) return false;
1762
1781
  if (/^[0-9\s\W_]+$/.test(value)) return false;
1763
- if (/^(https?:|ftp:|www\.|\/|\.\/|@|#[0-9a-f]{3,8}$|\.?(jsx?|tsx?|vue|css|scss|json|png|svg|jpg)$)/i.test(value)) {
1782
+ if (/^(https?:|ftp:|www\.|\/|\.\/|@|#[0-9a-f]{3,8}$|\.?(jsx?|tsx?|vue|css|scss|json|png|svg|jpg)$)/i.test(
1783
+ value
1784
+ )) {
1764
1785
  return false;
1765
1786
  }
1766
1787
  return true;
@@ -1768,7 +1789,9 @@ function looksLikeUserText(value, minLength) {
1768
1789
  function isExcludedContext(line, quoteIndex, excludeAttributes) {
1769
1790
  const before = line.slice(0, quoteIndex);
1770
1791
  for (const attr of excludeAttributes) {
1771
- const re = new RegExp(`\\b${attr.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*=\\s*(?:\\{\\s*)?["']?$`);
1792
+ const re = new RegExp(
1793
+ `\\b${attr.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*=\\s*(?:\\{\\s*)?["']?$`
1794
+ );
1772
1795
  if (re.test(before)) return true;
1773
1796
  }
1774
1797
  return false;
@@ -1900,7 +1923,9 @@ var plugin6 = {
1900
1923
  ${lines.join("\n")}${more}`;
1901
1924
  return { additionalContext: context };
1902
1925
  };
1903
- state6.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
1926
+ state6.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, {
1927
+ background: true
1928
+ });
1904
1929
  api.tools.register({
1905
1930
  name: "i18n_extract",
1906
1931
  description: "Scan a UI source file (.tsx/.jsx/.vue) for hardcoded user-facing string literals and return suggested i18n keys.",
@@ -2710,10 +2735,7 @@ var plugin8 = {
2710
2735
  }
2711
2736
  const rawInput = input ?? {};
2712
2737
  const shouldPolish = input.polish === true || rawInput["use_llm"] === true || rawInput["useLlm"] === true || rawInput["ai"] === true || rawInput["use_ai"] === true;
2713
- const block = await maybePolish(
2714
- renderUnreleasedBlock(state8.entries),
2715
- shouldPolish
2716
- );
2738
+ const block = await maybePolish(renderUnreleasedBlock(state8.entries), shouldPolish);
2717
2739
  let existing = null;
2718
2740
  try {
2719
2741
  existing = readFileSync3(cfg.filePath, "utf-8");
@@ -3403,7 +3425,9 @@ var plugin10 = {
3403
3425
  \u{1F4CA} code-metrics: ${relativePath(resolved)} \u2014 ${metrics.lines} lines (${metrics.codeLines} code, ${metrics.commentLines} comments, ${metrics.blankLines} blank), ${metrics.functionCount} function(s), complexity ${metrics.complexity}.`
3404
3426
  };
3405
3427
  };
3406
- state10.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
3428
+ state10.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, {
3429
+ background: true
3430
+ });
3407
3431
  api.tools.register({
3408
3432
  name: "measure_code_metrics",
3409
3433
  description: "Measure lines, comments, blank lines, function count, and cyclomatic-complexity-like score for a source file or directory.",
@@ -3920,7 +3944,9 @@ function readConfig11(raw) {
3920
3944
  const rawMax = r["maxFileBytes"] ?? r["max_file_bytes"] ?? r["maxBytes"] ?? r["max_bytes"];
3921
3945
  return {
3922
3946
  enabled: r["enabled"] !== false,
3923
- extensions: Array.isArray(rawExts) ? rawExts.filter((e) => typeof e === "string" && e.trim().length > 0).map((e) => e.trim().startsWith(".") ? e.trim().toLowerCase() : `.${e.trim().toLowerCase()}`) : [...DEFAULT_EXTENSIONS],
3947
+ extensions: Array.isArray(rawExts) ? rawExts.filter((e) => typeof e === "string" && e.trim().length > 0).map(
3948
+ (e) => e.trim().startsWith(".") ? e.trim().toLowerCase() : `.${e.trim().toLowerCase()}`
3949
+ ) : [...DEFAULT_EXTENSIONS],
3924
3950
  maxFileBytes: typeof rawMax === "number" && rawMax >= 1024 ? rawMax : DEFAULTS11.maxFileBytes
3925
3951
  };
3926
3952
  }
@@ -4214,7 +4240,9 @@ var plugin12 = {
4214
4240
  \u2026 and ${problems.length - 10} more` : "") + "\nFix these before moving on \u2014 downstream tools will fail on this file."
4215
4241
  };
4216
4242
  };
4217
- state12.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
4243
+ state12.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, {
4244
+ background: true
4245
+ });
4218
4246
  api.tools.register({
4219
4247
  name: "config_validator_status",
4220
4248
  description: "Reports config-validator state: watched extensions and counters (files checked, problems found).",
@@ -4335,7 +4363,10 @@ async function persistPins(filePath) {
4335
4363
  if (!filePath) return true;
4336
4364
  try {
4337
4365
  await ensureDir(dirname3(filePath));
4338
- await atomicWrite(filePath, JSON.stringify({ pins: state13.pins, nextId: state13.nextId }, null, 2));
4366
+ await atomicWrite(
4367
+ filePath,
4368
+ JSON.stringify({ pins: state13.pins, nextId: state13.nextId }, null, 2)
4369
+ );
4339
4370
  return true;
4340
4371
  } catch {
4341
4372
  state13.persistErrors += 1;
@@ -4707,7 +4738,9 @@ var plugin14 = {
4707
4738
  const rawCacheWrite = Number(u["cacheWrite"] ?? u["cache_creation_input_tokens"] ?? 0) || 0;
4708
4739
  const freshTokens = rawInput + rawCacheWrite;
4709
4740
  const promptTokens = freshTokens + cachedTokens;
4710
- const completionTokens = Number(u["output"] ?? u["completion_tokens"] ?? u["outputTokens"] ?? u["completionTokens"] ?? 0) || 0;
4741
+ const completionTokens = Number(
4742
+ u["output"] ?? u["completion_tokens"] ?? u["outputTokens"] ?? u["completionTokens"] ?? 0
4743
+ ) || 0;
4711
4744
  const totalTokens = promptTokens + completionTokens;
4712
4745
  const costUsd = estimateCost(model, freshTokens, completionTokens, cachedTokens);
4713
4746
  const record = {
@@ -5073,8 +5106,14 @@ var plugin15 = {
5073
5106
  type: "object",
5074
5107
  properties: {
5075
5108
  name: { type: "string", description: "Unique name for this cron job" },
5076
- intervalMs: { type: "number", description: "Interval between runs in milliseconds (minimum 1000)" },
5077
- action: { type: "string", description: "Action identifier or description of what to run" },
5109
+ intervalMs: {
5110
+ type: "number",
5111
+ description: "Interval between runs in milliseconds (minimum 1000)"
5112
+ },
5113
+ action: {
5114
+ type: "string",
5115
+ description: "Action identifier or description of what to run"
5116
+ },
5078
5117
  enabled: { type: "boolean", default: true }
5079
5118
  },
5080
5119
  required: ["name", "intervalMs", "action"]
@@ -5602,7 +5641,9 @@ function parseInstallCommands(command) {
5602
5641
  if (!cleaned) continue;
5603
5642
  let name = cleaned;
5604
5643
  let version = null;
5605
- const pipMatch = /^([A-Za-z0-9_.-]+(?:\[[^\]]+\])?)\s*(==|>=|<=|~=|!=|>|<)\s*(.+)$/.exec(cleaned);
5644
+ const pipMatch = /^([A-Za-z0-9_.-]+(?:\[[^\]]+\])?)\s*(==|>=|<=|~=|!=|>|<)\s*(.+)$/.exec(
5645
+ cleaned
5646
+ );
5606
5647
  if (pipMatch?.[1]) {
5607
5648
  name = pipMatch[1];
5608
5649
  const op = pipMatch[2] ?? "";
@@ -6520,8 +6561,12 @@ var plugin19 = {
6520
6561
  return;
6521
6562
  }
6522
6563
  const oldStr = String(inp["old_string"] ?? inp["TargetContent"] ?? inp["oldContent"] ?? "");
6523
- const newStr = String(inp["new_string"] ?? inp["ReplacementContent"] ?? inp["newContent"] ?? "");
6524
- const contentStr = String(inp["content"] ?? inp["CodeContent"] ?? inp["code"] ?? inp["text"] ?? inp["contents"] ?? inp["body"] ?? "");
6564
+ const newStr = String(
6565
+ inp["new_string"] ?? inp["ReplacementContent"] ?? inp["newContent"] ?? ""
6566
+ );
6567
+ const contentStr = String(
6568
+ inp["content"] ?? inp["CodeContent"] ?? inp["code"] ?? inp["text"] ?? inp["contents"] ?? inp["body"] ?? ""
6569
+ );
6525
6570
  const toolInputForHash = oldStr || newStr ? `${oldStr}:::${newStr}` : contentStr;
6526
6571
  const now = Date.now();
6527
6572
  const memo = pathMemo.get(filePath);
@@ -6576,7 +6621,9 @@ var plugin19 = {
6576
6621
  additionalContext: header + summary
6577
6622
  };
6578
6623
  };
6579
- state18.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
6624
+ state18.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, {
6625
+ background: true
6626
+ });
6580
6627
  api.tools.register({
6581
6628
  name: "diff_summary_status",
6582
6629
  description: "Reports diff-summary state: mode, maxLines, and per-session invocation/injected/fallback counters.",
@@ -6804,7 +6851,9 @@ var plugin20 = {
6804
6851
  }
6805
6852
  }
6806
6853
  if (!content || state19.changedFiles.length === 0) return;
6807
- const missing = state19.changedFiles.filter((changedPath) => !isReferenced(changedPath, content));
6854
+ const missing = state19.changedFiles.filter(
6855
+ (changedPath) => !isReferenced(changedPath, content)
6856
+ );
6808
6857
  if (missing.length === 0) return;
6809
6858
  state19.warningsIssued += 1;
6810
6859
  const missingList = missing.map((p) => ` - ${p}`).join("\n");
@@ -6815,7 +6864,9 @@ Consider mentioning these changes in the documentation.`;
6815
6864
  return { additionalContext: message };
6816
6865
  }
6817
6866
  };
6818
- state19.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
6867
+ state19.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, {
6868
+ background: true
6869
+ });
6819
6870
  api.tools.register({
6820
6871
  name: "doc_sync_status",
6821
6872
  description: "Reports doc-sync-guard state: tracked changed files, doc-write count, and warning count.",
@@ -7908,7 +7959,9 @@ var plugin23 = {
7908
7959
  Make sure flag behavior is intentional and consider updating flag inventory/docs.`
7909
7960
  };
7910
7961
  };
7911
- state22.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
7962
+ state22.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, {
7963
+ background: true
7964
+ });
7912
7965
  api.tools.register({
7913
7966
  name: "scan_feature_flags",
7914
7967
  description: "Scan source files for feature-flag-like expressions (isFeatureEnabled, featureFlags.*, useFeatureFlag, flags.*, plus custom patterns).",
@@ -8678,7 +8731,9 @@ var plugin25 = {
8678
8731
  state23.cleanCount += 1;
8679
8732
  return;
8680
8733
  };
8681
- state23.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
8734
+ state23.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, {
8735
+ background: true
8736
+ });
8682
8737
  state23.patternUnregister = api.onPattern(
8683
8738
  "import-organizer:done",
8684
8739
  (_eventName, payload) => {
@@ -10187,7 +10242,9 @@ ${result.stderr.trim()}`
10187
10242
  }
10188
10243
  return;
10189
10244
  };
10190
- state25.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
10245
+ state25.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, {
10246
+ background: true
10247
+ });
10191
10248
  api.tools.register({
10192
10249
  name: "import_organizer_status",
10193
10250
  description: "Reports import-organizer state: linter availability, config, and per-session organized/clean/error counters.",
@@ -10678,7 +10735,9 @@ var plugin30 = {
10678
10735
  If you changed member shapes, search the project for implementers/\`satisfies\`/\`as\` usages and update them accordingly.`
10679
10736
  };
10680
10737
  };
10681
- state27.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
10738
+ state27.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, {
10739
+ background: true
10740
+ });
10682
10741
  api.tools.register({
10683
10742
  name: "check_interface_contracts",
10684
10743
  description: "Scan TypeScript files for interface declarations that have no visible implementer (implements / as / satisfies).",
@@ -11030,9 +11089,12 @@ var plugin31 = {
11030
11089
  const hasMatch = f.subject.toLowerCase().includes(q) || f.relation.toLowerCase().includes(q) || f.object.toLowerCase().includes(q);
11031
11090
  if (!hasMatch) return false;
11032
11091
  }
11033
- if (input.subject && !f.subject.toLowerCase().includes(input.subject.toLowerCase())) return false;
11034
- if (input.relation && !f.relation.toLowerCase().includes(input.relation.toLowerCase())) return false;
11035
- if (input.object && !f.object.toLowerCase().includes(input.object.toLowerCase())) return false;
11092
+ if (input.subject && !f.subject.toLowerCase().includes(input.subject.toLowerCase()))
11093
+ return false;
11094
+ if (input.relation && !f.relation.toLowerCase().includes(input.relation.toLowerCase()))
11095
+ return false;
11096
+ if (input.object && !f.object.toLowerCase().includes(input.object.toLowerCase()))
11097
+ return false;
11036
11098
  if (filterConf && f.confidence.toLowerCase() !== filterConf) return false;
11037
11099
  return true;
11038
11100
  });
@@ -11064,7 +11126,9 @@ var plugin31 = {
11064
11126
  const raw = input ?? {};
11065
11127
  const rawId = String(input.id ?? raw["factId"] ?? raw["fact_id"] ?? "").trim();
11066
11128
  const normalized = rawId.toLowerCase().startsWith("kg-") ? rawId.toLowerCase() : `kg-${rawId.toLowerCase()}`;
11067
- state28.facts = state28.facts.filter((f) => f.id.toLowerCase() !== normalized && f.id !== rawId);
11129
+ state28.facts = state28.facts.filter(
11130
+ (f) => f.id.toLowerCase() !== normalized && f.id !== rawId
11131
+ );
11068
11132
  const removed = before - state28.facts.length;
11069
11133
  if (removed === 0) return { ok: false, error: `no fact matches "${input.id ?? rawId}"` };
11070
11134
  state28.removals += removed;
@@ -11160,7 +11224,15 @@ var state29 = {
11160
11224
  };
11161
11225
  var DEFAULTS27 = {
11162
11226
  enabled: true,
11163
- allowedLicenses: ["MIT", "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", "ISC", "0BSD", "Unlicense"],
11227
+ allowedLicenses: [
11228
+ "MIT",
11229
+ "Apache-2.0",
11230
+ "BSD-2-Clause",
11231
+ "BSD-3-Clause",
11232
+ "ISC",
11233
+ "0BSD",
11234
+ "Unlicense"
11235
+ ],
11164
11236
  block: true
11165
11237
  };
11166
11238
  function normalizeStrings(v) {
@@ -11199,7 +11271,9 @@ function extractLicenseStrings(pkg) {
11199
11271
  }
11200
11272
  function parsePackageNames(command) {
11201
11273
  return [
11202
- ...new Set(parseInstallCommands(command).flatMap((entry) => entry.packages.map((pkg) => pkg.name)))
11274
+ ...new Set(
11275
+ parseInstallCommands(command).flatMap((entry) => entry.packages.map((pkg) => pkg.name))
11276
+ )
11203
11277
  ];
11204
11278
  }
11205
11279
  function splitTopLevel(expr, separator) {
@@ -15409,9 +15483,15 @@ var plugin39 = {
15409
15483
  kind: isRootPathScope(path) && deletesImplicitScope || isUnresolvedPathScope(path) || recursivelyDeletes && (isDirectoryAmbiguousPath(path) || hasConfiguredProtectedDescendant(path, cfg.protect)) ? "deletion-scope" : "file"
15410
15484
  };
15411
15485
  if (targetFullyAllowed(target, cfg.allow, allowRes)) return null;
15412
- const protectedShellTarget = await targetIntersectsPatternsGuarded(target, cfg.protect, protectRes, { onTimeout: bumpRedos }) || await matchesAnyGuarded(`${target.path.replace(/\/$/, "")}/.path-guard-probe`, protectRes, {
15486
+ const protectedShellTarget = await targetIntersectsPatternsGuarded(target, cfg.protect, protectRes, {
15413
15487
  onTimeout: bumpRedos
15414
- });
15488
+ }) || await matchesAnyGuarded(
15489
+ `${target.path.replace(/\/$/, "")}/.path-guard-probe`,
15490
+ protectRes,
15491
+ {
15492
+ onTimeout: bumpRedos
15493
+ }
15494
+ );
15415
15495
  return protectedShellTarget ? target : null;
15416
15496
  })
15417
15497
  );
@@ -16257,7 +16337,9 @@ var plugin41 = {
16257
16337
  async execute(input = {}) {
16258
16338
  if (!cfg.enabled) return { ok: false, error: "pr-drafter is disabled" };
16259
16339
  const raw = input ?? {};
16260
- const preview = Boolean(input?.preview ?? raw["dryRun"] ?? raw["dry_run"] ?? raw["dry"] ?? raw["previewOnly"]);
16340
+ const preview = Boolean(
16341
+ input?.preview ?? raw["dryRun"] ?? raw["dry_run"] ?? raw["dry"] ?? raw["previewOnly"]
16342
+ );
16261
16343
  const rawOutputPath = raw["outputPath"] ?? raw["output_path"] ?? raw["path"] ?? raw["filePath"] ?? raw["file"] ?? raw["TargetFile"] ?? raw["targetFile"] ?? cfg.outputPath;
16262
16344
  const outputPathStr = typeof rawOutputPath === "string" && rawOutputPath.trim().length > 0 ? rawOutputPath.trim() : cfg.outputPath;
16263
16345
  const draft = await buildDraft(cfg, api.llm);
@@ -16406,7 +16488,9 @@ var plugin42 = {
16406
16488
  const rawCmd = ti["command"] ?? ti["CommandLine"] ?? ti["cmd"] ?? ti["script"] ?? ti["input"];
16407
16489
  const command = typeof rawCmd === "string" ? rawCmd : "";
16408
16490
  if (!command) return;
16409
- const isKillRelated = /\b(?:kill|taskkill|stop-process|tskill|pkill|killall|wmic)\b/i.test(command);
16491
+ const isKillRelated = /\b(?:kill|taskkill|stop-process|tskill|pkill|killall|wmic)\b/i.test(
16492
+ command
16493
+ );
16410
16494
  if (!isKillRelated) return;
16411
16495
  state39.detections += 1;
16412
16496
  state39.lastDetection = {
@@ -16772,9 +16856,12 @@ function surfaceScanTrips(api, tripped) {
16772
16856
  }
16773
16857
  state40.timeoutCount += 1;
16774
16858
  api.metrics.counter("redos_skips", 1);
16775
- api.log.warn("prompt-firewall: scan-pass budget exceeded \u2014 patterns skipped mid-pass (issue #370)", {
16776
- skipped: [...tripped]
16777
- });
16859
+ api.log.warn(
16860
+ "prompt-firewall: scan-pass budget exceeded \u2014 patterns skipped mid-pass (issue #370)",
16861
+ {
16862
+ skipped: [...tripped]
16863
+ }
16864
+ );
16778
16865
  }
16779
16866
  var plugin43 = {
16780
16867
  name: "prompt-firewall",
@@ -16876,7 +16963,14 @@ var plugin43 = {
16876
16963
  if (cfg.mode === "redact") {
16877
16964
  const counter = { n: 0 };
16878
16965
  const deadline = createScanDeadline();
16879
- const redactedReq = redactDeep(req, cfg.allow, counter, skipSet, void 0, deadline);
16966
+ const redactedReq = redactDeep(
16967
+ req,
16968
+ cfg.allow,
16969
+ counter,
16970
+ skipSet,
16971
+ void 0,
16972
+ deadline
16973
+ );
16880
16974
  state40.requestRedactions += counter.n;
16881
16975
  api.metrics.counter("request_redactions", counter.n);
16882
16976
  if (deadline.tripped.size > 0) surfaceScanTrips(api, deadline.tripped);
@@ -17273,7 +17367,9 @@ var plugin44 = {
17273
17367
  contextAs: "separate"
17274
17368
  };
17275
17369
  };
17276
- state41.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
17370
+ state41.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, {
17371
+ background: true
17372
+ });
17277
17373
  api.tools.register({
17278
17374
  name: "suggest_refactors",
17279
17375
  description: "Scan source files for refactoring smells: long functions, deep nesting, many parameters, magic numbers, and console logging.",
@@ -18600,7 +18696,19 @@ var DEFAULTS42 = {
18600
18696
  enabled: false,
18601
18697
  severity: "warn",
18602
18698
  maxFindings: 10,
18603
- scanOnChange: [".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs", ".py", ".java", ".go", ".rb", ".php"]
18699
+ scanOnChange: [
18700
+ ".js",
18701
+ ".jsx",
18702
+ ".ts",
18703
+ ".tsx",
18704
+ ".mjs",
18705
+ ".cjs",
18706
+ ".py",
18707
+ ".java",
18708
+ ".go",
18709
+ ".rb",
18710
+ ".php"
18711
+ ]
18604
18712
  };
18605
18713
  var scanOnChangeSet = new Set(DEFAULTS42.scanOnChange);
18606
18714
  function readConfig44(raw) {
@@ -18623,7 +18731,11 @@ function readConfig44(raw) {
18623
18731
  }
18624
18732
  var PATTERNS4 = [
18625
18733
  { type: "eval_call", severity: "high", regex: /\beval\s*\(/i },
18626
- { type: "function_constructor", severity: "high", regex: /\bnew\s+Function\s*\(|\bFunction\s*\(/i },
18734
+ {
18735
+ type: "function_constructor",
18736
+ severity: "high",
18737
+ regex: /\bnew\s+Function\s*\(|\bFunction\s*\(/i
18738
+ },
18627
18739
  {
18628
18740
  type: "unsafe_html",
18629
18741
  severity: "high",
@@ -18861,7 +18973,9 @@ Review or remove the risky pattern(s).`;
18861
18973
  }
18862
18974
  return { additionalContext: message };
18863
18975
  };
18864
- state44.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
18976
+ state44.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, {
18977
+ background: true
18978
+ });
18865
18979
  api.tools.register({
18866
18980
  name: "security_hotspot_scan",
18867
18981
  description: "Scan a file or directory for security anti-patterns (eval, Function constructor, innerHTML, SQL concatenation, http URLs, credential logging, variable exec commands).",
@@ -19036,11 +19150,7 @@ var DEFAULTS43 = {
19036
19150
  ".scss",
19037
19151
  ".html"
19038
19152
  ],
19039
- excludePatterns: [
19040
- ...DEFAULT_WALK_IGNORE_DIRS.map(escapeRegex),
19041
- "\\.wrongstack",
19042
- "\\.temp_files"
19043
- ],
19153
+ excludePatterns: [...DEFAULT_WALK_IGNORE_DIRS.map(escapeRegex), "\\.wrongstack", "\\.temp_files"],
19044
19154
  maxFileBytes: 1e6,
19045
19155
  defaultLimit: 10,
19046
19156
  minTokenLength: 2,
@@ -19048,7 +19158,12 @@ var DEFAULTS43 = {
19048
19158
  maxFiles: 5e3
19049
19159
  };
19050
19160
  function readConfig45(raw) {
19051
- if (!raw || typeof raw !== "object") return { ...DEFAULTS43, includeExtensions: [...DEFAULTS43.includeExtensions], excludePatterns: [...DEFAULTS43.excludePatterns] };
19161
+ if (!raw || typeof raw !== "object")
19162
+ return {
19163
+ ...DEFAULTS43,
19164
+ includeExtensions: [...DEFAULTS43.includeExtensions],
19165
+ excludePatterns: [...DEFAULTS43.excludePatterns]
19166
+ };
19052
19167
  const r = raw;
19053
19168
  const rawExts = r["includeExtensions"] ?? r["include_extensions"] ?? r["extensions"] ?? r["file_extensions"];
19054
19169
  const includeExtensions = Array.isArray(rawExts) ? rawExts.filter((x) => typeof x === "string") : [...DEFAULTS43.includeExtensions];
@@ -19359,7 +19474,11 @@ var plugin49 = {
19359
19474
  description: "Builds an in-memory keyword index over project source files and answers ranked search queries",
19360
19475
  apiVersion: API_VERSION32,
19361
19476
  capabilities: { tools: true },
19362
- defaultConfig: { ...DEFAULTS43, includeExtensions: [...DEFAULTS43.includeExtensions], excludePatterns: [...DEFAULTS43.excludePatterns] },
19477
+ defaultConfig: {
19478
+ ...DEFAULTS43,
19479
+ includeExtensions: [...DEFAULTS43.includeExtensions],
19480
+ excludePatterns: [...DEFAULTS43.excludePatterns]
19481
+ },
19363
19482
  configSchema: {
19364
19483
  type: "object",
19365
19484
  properties: {
@@ -19644,19 +19763,24 @@ var state46 = {
19644
19763
  };
19645
19764
  function runCommand3(command, args, cwd) {
19646
19765
  return new Promise((resolve28, reject) => {
19647
- execFile11(command, args, {
19648
- encoding: "utf-8",
19649
- cwd,
19650
- timeout: 3e4,
19651
- windowsHide: true
19652
- }, (err, stdout, stderr) => {
19653
- if (!err) {
19654
- resolve28(stdout.trim());
19655
- return;
19766
+ execFile11(
19767
+ command,
19768
+ args,
19769
+ {
19770
+ encoding: "utf-8",
19771
+ cwd,
19772
+ timeout: 3e4,
19773
+ windowsHide: true
19774
+ },
19775
+ (err, stdout, stderr) => {
19776
+ if (!err) {
19777
+ resolve28(stdout.trim());
19778
+ return;
19779
+ }
19780
+ const failure = err;
19781
+ reject(Object.assign(failure, { stderr: stderr || void 0 }));
19656
19782
  }
19657
- const failure = err;
19658
- reject(Object.assign(failure, { stderr: stderr || void 0 }));
19659
- });
19783
+ );
19660
19784
  });
19661
19785
  }
19662
19786
  async function runGit6(args, cwd) {
@@ -20704,15 +20828,10 @@ var state48 = {
20704
20828
  async function runShellCheck(files, severity, cwd) {
20705
20829
  try {
20706
20830
  await new Promise((resolvePromise, rejectPromise) => {
20707
- execFile12(
20708
- "shellcheck",
20709
- ["--version"],
20710
- { encoding: "utf-8", windowsHide: true },
20711
- (err) => {
20712
- if (err) rejectPromise(err);
20713
- else resolvePromise();
20714
- }
20715
- );
20831
+ execFile12("shellcheck", ["--version"], { encoding: "utf-8", windowsHide: true }, (err) => {
20832
+ if (err) rejectPromise(err);
20833
+ else resolvePromise();
20834
+ });
20716
20835
  });
20717
20836
  } catch {
20718
20837
  throw new Error(
@@ -20873,7 +20992,9 @@ var plugin52 = {
20873
20992
  if (typeof rawFiles === "string" && rawFiles.trim().length > 0) {
20874
20993
  files = [rawFiles.trim()];
20875
20994
  } else if (Array.isArray(rawFiles)) {
20876
- files = rawFiles.filter((f) => typeof f === "string" && f.trim().length > 0);
20995
+ files = rawFiles.filter(
20996
+ (f) => typeof f === "string" && f.trim().length > 0
20997
+ );
20877
20998
  }
20878
20999
  }
20879
21000
  const rawDirectory = inp.directory ?? input["dir"] ?? input["SearchDirectory"];
@@ -21018,7 +21139,8 @@ function normalizeExtensions6(exts) {
21018
21139
  return exts.map((e) => e.startsWith(".") ? e.toLowerCase() : `.${e.toLowerCase()}`);
21019
21140
  }
21020
21141
  function readConfig47(raw) {
21021
- if (!raw || typeof raw !== "object") return { ...DEFAULTS45, extensions: normalizeExtensions6(DEFAULTS45.extensions) };
21142
+ if (!raw || typeof raw !== "object")
21143
+ return { ...DEFAULTS45, extensions: normalizeExtensions6(DEFAULTS45.extensions) };
21022
21144
  const r = raw;
21023
21145
  const rawExts = r["extensions"] ?? r["file_extensions"] ?? r["fileExtensions"];
21024
21146
  const exts = Array.isArray(rawExts) ? rawExts.filter((x) => typeof x === "string") : DEFAULTS45.extensions;
@@ -21051,10 +21173,7 @@ function isIdentifier(name) {
21051
21173
  return IDENTIFIER_RE2.test(name);
21052
21174
  }
21053
21175
  function renameInContent(content, oldName, newName) {
21054
- const re = new RegExp(
21055
- `(?<![A-Za-z0-9_$])${escapeRegex2(oldName)}(?![A-Za-z0-9_$])`,
21056
- "g"
21057
- );
21176
+ const re = new RegExp(`(?<![A-Za-z0-9_$])${escapeRegex2(oldName)}(?![A-Za-z0-9_$])`, "g");
21058
21177
  let replacements = 0;
21059
21178
  const preview = content.replace(re, () => {
21060
21179
  replacements++;
@@ -21095,7 +21214,11 @@ var plugin53 = {
21095
21214
  path: { type: "string", description: "Source file path (relative to project root)." },
21096
21215
  oldName: { type: "string", description: "Identifier to replace." },
21097
21216
  newName: { type: "string", description: "New identifier." },
21098
- apply: { type: "boolean", default: false, description: "When true, write the preview back to disk." }
21217
+ apply: {
21218
+ type: "boolean",
21219
+ default: false,
21220
+ description: "When true, write the preview back to disk."
21221
+ }
21099
21222
  },
21100
21223
  required: ["path", "oldName", "newName"]
21101
21224
  },
@@ -21612,7 +21735,9 @@ var plugin54 = {
21612
21735
  ${lines}${overflowNote}`
21613
21736
  };
21614
21737
  };
21615
- state50.postHookUnregister = api.registerHook("PostToolUse", "write|edit", postHook, { background: true });
21738
+ state50.postHookUnregister = api.registerHook("PostToolUse", "write|edit", postHook, {
21739
+ background: true
21740
+ });
21616
21741
  if (cfg.autoFix) {
21617
21742
  const preHook = async (input) => {
21618
21743
  if (!cfg.enabled) return;
@@ -21756,21 +21881,27 @@ function expandTemplate(template, variables) {
21756
21881
  return result;
21757
21882
  }
21758
21883
  function expandConditionals(template, variables) {
21759
- return template.replace(/\{\{#if\s+([\w.-]+)\s*\}\}([\s\S]*?)\{\{\/if\}\}/g, (_, key, content) => {
21760
- const val = variables[key];
21761
- return val !== void 0 && val !== "" && val !== "false" && val !== "0" ? content : "";
21762
- });
21884
+ return template.replace(
21885
+ /\{\{#if\s+([\w.-]+)\s*\}\}([\s\S]*?)\{\{\/if\}\}/g,
21886
+ (_, key, content) => {
21887
+ const val = variables[key];
21888
+ return val !== void 0 && val !== "" && val !== "false" && val !== "0" ? content : "";
21889
+ }
21890
+ );
21763
21891
  }
21764
21892
  function expandLoops(template, variables) {
21765
- return template.replace(/\{\{#each\s+([\w.-]+)\s*\}\}([\s\S]*?)\{\{\/each\}\}/g, (_, key, content) => {
21766
- const val = variables[key];
21767
- if (!val) return "";
21768
- if (typeof val === "string" && val.includes(",")) {
21769
- const items = val.split(",").map((s) => s.trim());
21770
- return items.map((item) => expandTemplate(content, { ...variables, [key]: item, item })).join("\n");
21771
- }
21772
- return expandTemplate(content, variables);
21773
- });
21893
+ return template.replace(
21894
+ /\{\{#each\s+([\w.-]+)\s*\}\}([\s\S]*?)\{\{\/each\}\}/g,
21895
+ (_, key, content) => {
21896
+ const val = variables[key];
21897
+ if (!val) return "";
21898
+ if (typeof val === "string" && val.includes(",")) {
21899
+ const items = val.split(",").map((s) => s.trim());
21900
+ return items.map((item) => expandTemplate(content, { ...variables, [key]: item, item })).join("\n");
21901
+ }
21902
+ return expandTemplate(content, variables);
21903
+ }
21904
+ );
21774
21905
  }
21775
21906
  function renderTemplate(template, variables, escapeHtml = true) {
21776
21907
  let result = template;
@@ -22661,10 +22792,7 @@ var plugin57 = {
22661
22792
  const commandString = typeof rawCommand === "string" && rawCommand.trim().length > 0 ? rawCommand.trim() : cfg.defaultCommand;
22662
22793
  const rawRuns = input.runs ?? raw["runsRequested"] ?? raw["count"] ?? raw["repeat"] ?? raw["times"];
22663
22794
  const requestedRuns = typeof rawRuns === "number" && rawRuns >= 1 ? Math.min(Math.floor(rawRuns), cfg.maxRuns) : 5;
22664
- const command = resolveTestCommand(
22665
- commandString,
22666
- testPattern
22667
- );
22795
+ const command = resolveTestCommand(commandString, testPattern);
22668
22796
  if (!command) {
22669
22797
  return {
22670
22798
  ok: false,
@@ -22953,7 +23081,9 @@ function generateTestContent(sourcePath, sourceModule, detected, cfg) {
22953
23081
  }
22954
23082
  if (detected.length === 0) {
22955
23083
  lines.push(` it('has no exported symbols to test', () => {`);
22956
- lines.push(cfg.framework === "node:test" ? ` assert.ok(true);` : ` expect(true).toBe(true);`);
23084
+ lines.push(
23085
+ cfg.framework === "node:test" ? ` assert.ok(true);` : ` expect(true).toBe(true);`
23086
+ );
22957
23087
  lines.push(` });`);
22958
23088
  }
22959
23089
  lines.push(`});`);
@@ -23311,13 +23441,18 @@ async function detectRunner(requested) {
23311
23441
  try {
23312
23442
  await new Promise((resolve28, reject) => {
23313
23443
  const ex = resolveExec("npx", [`${match.name}`, "--version"]);
23314
- execFile14(ex.cmd, ex.args, {
23315
- encoding: "utf-8",
23316
- timeout: 5e3,
23317
- cwd: process.cwd(),
23318
- windowsHide: true,
23319
- ...ex.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}
23320
- }, (err) => err ? reject(err) : resolve28());
23444
+ execFile14(
23445
+ ex.cmd,
23446
+ ex.args,
23447
+ {
23448
+ encoding: "utf-8",
23449
+ timeout: 5e3,
23450
+ cwd: process.cwd(),
23451
+ windowsHide: true,
23452
+ ...ex.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}
23453
+ },
23454
+ (err) => err ? reject(err) : resolve28()
23455
+ );
23321
23456
  });
23322
23457
  return match;
23323
23458
  } catch {
@@ -23328,13 +23463,18 @@ async function detectRunner(requested) {
23328
23463
  try {
23329
23464
  await new Promise((resolve28, reject) => {
23330
23465
  const ex = resolveExec("npx", [`${candidate.name}`, "--version"]);
23331
- execFile14(ex.cmd, ex.args, {
23332
- encoding: "utf-8",
23333
- timeout: 5e3,
23334
- cwd: process.cwd(),
23335
- windowsHide: true,
23336
- ...ex.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}
23337
- }, (err) => err ? reject(err) : resolve28());
23466
+ execFile14(
23467
+ ex.cmd,
23468
+ ex.args,
23469
+ {
23470
+ encoding: "utf-8",
23471
+ timeout: 5e3,
23472
+ cwd: process.cwd(),
23473
+ windowsHide: true,
23474
+ ...ex.windowsVerbatimArguments ? { windowsVerbatimArguments: true } : {}
23475
+ },
23476
+ (err) => err ? reject(err) : resolve28()
23477
+ );
23338
23478
  });
23339
23479
  return candidate;
23340
23480
  } catch {
@@ -23602,7 +23742,9 @@ var plugin59 = {
23602
23742
  Fix the failing tests or revert the change if it broke something.`
23603
23743
  };
23604
23744
  };
23605
- state54.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
23745
+ state54.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, {
23746
+ background: true
23747
+ });
23606
23748
  api.tools.register({
23607
23749
  name: "test_gate_status",
23608
23750
  description: "Reports test-runner-gate state: command, patterns, and per-session pass/fail/error/no-test counters.",
@@ -25070,7 +25212,9 @@ Fix the type error(s) or adjust the change.`;
25070
25212
  }
25071
25213
  return { additionalContext: message };
25072
25214
  };
25073
- state59.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
25215
+ state59.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, {
25216
+ background: true
25217
+ });
25074
25218
  api.tools.register({
25075
25219
  name: "type_gate_status",
25076
25220
  description: "Reports type-gate state: command, tsconfig, severity, and per-session pass/fail/error counters.",