@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/accessibility-auditor.js +21 -4
- package/dist/api-compatibility-gate.js +3 -1
- package/dist/auto-i18n-extractor.js +9 -3
- package/dist/changelog-writer.js +1 -4
- package/dist/code-metrics.js +3 -1
- package/dist/config-validator.js +6 -2
- package/dist/context-pins.js +4 -1
- package/dist/cost-tracker.js +3 -1
- package/dist/cron.js +8 -2
- package/dist/dep-guard.js +3 -1
- package/dist/dependency-vulnerability-gate.js +3 -1
- package/dist/diff-summary.js +9 -3
- package/dist/doc-sync-guard.js +6 -2
- package/dist/feature-flag-tracker.js +3 -1
- package/dist/format-on-save.js +3 -1
- package/dist/import-organizer.js +3 -1
- package/dist/index.js +261 -117
- package/dist/interface-contract-guard.js +3 -1
- package/dist/knowledge-graph.js +9 -4
- package/dist/license-audit-gate.js +15 -3
- package/dist/path-guard.js +8 -2
- package/dist/pr-drafter.js +3 -1
- package/dist/process-guard.js +3 -1
- package/dist/prompt-firewall.js +14 -4
- package/dist/refactor-suggester.js +3 -1
- package/dist/security-hotspot-scanner.js +21 -3
- package/dist/semantic-search-indexer.js +12 -7
- package/dist/semver-bump.js +17 -12
- package/dist/shell-check.js +7 -10
- package/dist/smart-rename.js +8 -6
- package/dist/spec-linker.js +3 -1
- package/dist/template-engine.js +18 -12
- package/dist/test-flake-detector.js +1 -4
- package/dist/test-generator.js +3 -1
- package/dist/test-runner-gate.js +27 -15
- package/dist/type-gate.js +3 -1
- package/package.json +5 -5
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(
|
|
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(
|
|
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(
|
|
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, {
|
|
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, {
|
|
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(
|
|
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(
|
|
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, {
|
|
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, {
|
|
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(
|
|
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, {
|
|
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(
|
|
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(
|
|
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: {
|
|
5077
|
-
|
|
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(
|
|
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(
|
|
6524
|
-
|
|
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, {
|
|
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(
|
|
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, {
|
|
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, {
|
|
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, {
|
|
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, {
|
|
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, {
|
|
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()))
|
|
11034
|
-
|
|
11035
|
-
if (input.
|
|
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(
|
|
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: [
|
|
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(
|
|
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, {
|
|
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(
|
|
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(
|
|
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(
|
|
16776
|
-
|
|
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(
|
|
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, {
|
|
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: [
|
|
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
|
-
{
|
|
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, {
|
|
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")
|
|
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: {
|
|
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(
|
|
19648
|
-
|
|
19649
|
-
|
|
19650
|
-
|
|
19651
|
-
|
|
19652
|
-
|
|
19653
|
-
|
|
19654
|
-
|
|
19655
|
-
|
|
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
|
-
|
|
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
|
-
|
|
20709
|
-
|
|
20710
|
-
|
|
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(
|
|
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")
|
|
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: {
|
|
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, {
|
|
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(
|
|
21760
|
-
|
|
21761
|
-
|
|
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(
|
|
21766
|
-
|
|
21767
|
-
|
|
21768
|
-
|
|
21769
|
-
|
|
21770
|
-
|
|
21771
|
-
|
|
21772
|
-
|
|
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(
|
|
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(
|
|
23315
|
-
|
|
23316
|
-
|
|
23317
|
-
|
|
23318
|
-
|
|
23319
|
-
|
|
23320
|
-
|
|
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(
|
|
23332
|
-
|
|
23333
|
-
|
|
23334
|
-
|
|
23335
|
-
|
|
23336
|
-
|
|
23337
|
-
|
|
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, {
|
|
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, {
|
|
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.",
|