@wrongstack/plugins 0.286.0 → 0.289.0
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/README.md +20 -11
- package/dist/accessibility-auditor/index.d.ts.map +1 -1
- package/dist/accessibility-auditor.js +67 -55
- package/dist/api-compatibility-gate.js +1 -1
- package/dist/auto-doc.js +1 -1
- package/dist/auto-i18n-extractor/index.d.ts.map +1 -1
- package/dist/auto-i18n-extractor.js +20 -12
- package/dist/changelog-writer.js +1 -1
- package/dist/code-metrics/index.d.ts.map +1 -1
- package/dist/code-metrics.js +63 -50
- package/dist/commit-validator.js +1 -1
- package/dist/config-validator.js +1 -1
- package/dist/cost-tracker/index.d.ts.map +1 -1
- package/dist/cost-tracker.js +4 -2
- package/dist/cron/index.d.ts.map +1 -1
- package/dist/cron.js +29 -0
- package/dist/dead-code-detector/index.d.ts.map +1 -1
- package/dist/dead-code-detector.js +28 -19
- package/dist/dep-guard.js +1 -1
- package/dist/diff-summary/index.d.ts.map +1 -1
- package/dist/diff-summary.js +19 -11
- package/dist/doc-sync-guard/index.d.ts.map +1 -1
- package/dist/doc-sync-guard.js +25 -16
- package/dist/duplicate-code-detector/index.d.ts.map +1 -1
- package/dist/duplicate-code-detector.js +70 -57
- package/dist/error-lens.js +1 -1
- package/dist/feature-flag-tracker/index.d.ts.map +1 -1
- package/dist/feature-flag-tracker.js +69 -56
- package/dist/file-watcher/index.d.ts.map +1 -1
- package/dist/file-watcher.js +21 -4
- package/dist/format-on-save/index.d.ts.map +1 -1
- package/dist/format-on-save.js +19 -11
- package/dist/git-autocommit.js +1 -1
- package/dist/import-organizer/index.d.ts.map +1 -1
- package/dist/import-organizer.js +23 -14
- package/dist/index.d.ts +4 -4
- package/dist/index.js +1167 -1048
- package/dist/interface-contract-guard/index.d.ts.map +1 -1
- package/dist/interface-contract-guard.js +64 -51
- package/dist/lint-gate/index.d.ts.map +1 -1
- package/dist/lint-gate.js +61 -30
- package/dist/migration-planner/index.d.ts +12 -2
- package/dist/migration-planner/index.d.ts.map +1 -1
- package/dist/migration-planner.js +210 -28
- package/dist/pr-drafter.js +1 -1
- package/dist/prompt-firewall/index.d.ts +14 -6
- package/dist/prompt-firewall/index.d.ts.map +1 -1
- package/dist/prompt-firewall.js +7 -6
- package/dist/refactor-suggester/index.d.ts.map +1 -1
- package/dist/refactor-suggester.js +69 -56
- package/dist/release-notes-generator/index.d.ts +3 -1
- package/dist/release-notes-generator/index.d.ts.map +1 -1
- package/dist/release-notes-generator.js +152 -12
- package/dist/runtime/index.d.ts +36 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/llm.d.ts +33 -0
- package/dist/runtime/llm.d.ts.map +1 -0
- package/dist/runtime.js +119 -25
- package/dist/schema-evolution-guard/index.d.ts.map +1 -1
- package/dist/schema-evolution-guard.js +22 -13
- package/dist/secret-scanner/index.d.ts.map +1 -1
- package/dist/secret-scanner.js +17 -6
- package/dist/security-hotspot-scanner/index.d.ts.map +1 -1
- package/dist/security-hotspot-scanner.js +24 -15
- package/dist/session-recap.js +1 -1
- package/dist/spec-linker.js +1167 -1048
- package/dist/test-generator/index.d.ts +5 -3
- package/dist/test-generator/index.d.ts.map +1 -1
- package/dist/test-generator.js +169 -26
- package/dist/test-runner-gate/index.d.ts.map +1 -1
- package/dist/test-runner-gate.js +65 -43
- package/dist/type-gate/index.d.ts.map +1 -1
- package/dist/type-gate.js +23 -35
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/interface-contract-guard/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/interface-contract-guard/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAS/C,MAAM,WAAW,wBAAwB;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAqID,QAAA,MAAM,MAAM,EAAE,MAuMb,CAAC;eAEa,MAAM"}
|
|
@@ -1,55 +1,37 @@
|
|
|
1
1
|
// src/interface-contract-guard/index.ts
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
hookUnregister: null
|
|
12
|
-
};
|
|
13
|
-
var DEFAULTS = {
|
|
14
|
-
enabled: false,
|
|
15
|
-
extensions: [".ts", ".tsx"],
|
|
16
|
-
maxFindings: 50
|
|
17
|
-
};
|
|
18
|
-
function readConfig(raw) {
|
|
19
|
-
if (!raw || typeof raw !== "object") return { ...DEFAULTS };
|
|
20
|
-
const r = raw;
|
|
21
|
-
return {
|
|
22
|
-
enabled: r["enabled"] !== false,
|
|
23
|
-
extensions: Array.isArray(r["extensions"]) ? r["extensions"].filter((x) => typeof x === "string") : DEFAULTS.extensions,
|
|
24
|
-
maxFindings: typeof r["maxFindings"] === "number" && r["maxFindings"] >= 1 && r["maxFindings"] <= 500 ? r["maxFindings"] : DEFAULTS.maxFindings
|
|
25
|
-
};
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve2 } from "node:path";
|
|
4
|
+
|
|
5
|
+
// src/runtime/index.ts
|
|
6
|
+
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
7
|
+
import { basename, extname, isAbsolute, relative, resolve } from "node:path";
|
|
8
|
+
var MAX_BUFFER_BYTES = 16 * 1024 * 1024;
|
|
9
|
+
function hasLeadingDash(arg) {
|
|
10
|
+
return arg.length > 0 && arg.startsWith("-");
|
|
26
11
|
}
|
|
27
|
-
function
|
|
28
|
-
if (
|
|
29
|
-
|
|
30
|
-
const resolved = isAbsolute(
|
|
31
|
-
const rel = relative(
|
|
32
|
-
|
|
33
|
-
if (rel.startsWith("..")) return false;
|
|
34
|
-
if (isAbsolute(rel)) return false;
|
|
35
|
-
return true;
|
|
36
|
-
}
|
|
37
|
-
function normalizeExtensions(exts) {
|
|
38
|
-
return exts.map((e) => e.startsWith(".") ? e.toLowerCase() : `.${e.toLowerCase()}`);
|
|
12
|
+
function withinProjectPath(projectRoot, candidate) {
|
|
13
|
+
if (candidate.length === 0 || candidate.length > 4096) return false;
|
|
14
|
+
if (hasLeadingDash(candidate)) return false;
|
|
15
|
+
const resolved = isAbsolute(candidate) ? resolve(candidate) : resolve(projectRoot, candidate);
|
|
16
|
+
const rel = relative(projectRoot, resolved);
|
|
17
|
+
return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
|
|
39
18
|
}
|
|
40
|
-
function
|
|
41
|
-
return
|
|
19
|
+
function withinProject(p) {
|
|
20
|
+
return withinProjectPath(process.cwd(), p) || relative(process.cwd(), p) === ".";
|
|
42
21
|
}
|
|
43
|
-
|
|
22
|
+
var DEFAULT_EXCLUDE_DIRS = ["node_modules", "dist", ".git", "coverage"];
|
|
23
|
+
function collectSourceFiles(root, opts) {
|
|
44
24
|
const files = [];
|
|
45
25
|
if (!existsSync(root)) return files;
|
|
46
26
|
const s = statSync(root);
|
|
47
27
|
if (s.isFile()) {
|
|
48
|
-
if (matchesExtension(root,
|
|
28
|
+
if (matchesExtension(root, opts.extensions)) files.push(root);
|
|
49
29
|
return files;
|
|
50
30
|
}
|
|
51
31
|
if (!s.isDirectory()) return files;
|
|
52
|
-
|
|
32
|
+
const exclude = opts.excludeDirs ?? DEFAULT_EXCLUDE_DIRS;
|
|
33
|
+
function walk(dir, depth) {
|
|
34
|
+
if (opts.maxDepth !== void 0 && depth > opts.maxDepth) return;
|
|
53
35
|
let entries;
|
|
54
36
|
try {
|
|
55
37
|
entries = readdirSync(dir);
|
|
@@ -57,7 +39,7 @@ function collectSourceFiles(root, exts) {
|
|
|
57
39
|
return;
|
|
58
40
|
}
|
|
59
41
|
for (const entry of entries) {
|
|
60
|
-
if (
|
|
42
|
+
if (exclude.includes(entry)) continue;
|
|
61
43
|
const full = resolve(dir, entry);
|
|
62
44
|
let st;
|
|
63
45
|
try {
|
|
@@ -66,20 +48,51 @@ function collectSourceFiles(root, exts) {
|
|
|
66
48
|
continue;
|
|
67
49
|
}
|
|
68
50
|
if (st.isDirectory()) {
|
|
69
|
-
walk(full);
|
|
70
|
-
} else if (st.isFile() && matchesExtension(full,
|
|
51
|
+
walk(full, depth + 1);
|
|
52
|
+
} else if (st.isFile() && matchesExtension(full, opts.extensions)) {
|
|
71
53
|
files.push(full);
|
|
72
54
|
}
|
|
73
55
|
}
|
|
74
56
|
}
|
|
75
|
-
walk(root);
|
|
57
|
+
walk(root, 0);
|
|
76
58
|
return files;
|
|
77
59
|
}
|
|
60
|
+
function matchesExtension(p, exts) {
|
|
61
|
+
return exts.includes(extname(p).toLowerCase());
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// src/interface-contract-guard/index.ts
|
|
65
|
+
var API_VERSION = "^0.1.10";
|
|
66
|
+
var state = {
|
|
67
|
+
scanCount: 0,
|
|
68
|
+
findingCount: 0,
|
|
69
|
+
hookInvocationCount: 0,
|
|
70
|
+
warningCount: 0,
|
|
71
|
+
errorCount: 0,
|
|
72
|
+
hookUnregister: null
|
|
73
|
+
};
|
|
74
|
+
var DEFAULTS = {
|
|
75
|
+
enabled: false,
|
|
76
|
+
extensions: [".ts", ".tsx"],
|
|
77
|
+
maxFindings: 50
|
|
78
|
+
};
|
|
79
|
+
function readConfig(raw) {
|
|
80
|
+
if (!raw || typeof raw !== "object") return { ...DEFAULTS };
|
|
81
|
+
const r = raw;
|
|
82
|
+
return {
|
|
83
|
+
enabled: r["enabled"] !== false,
|
|
84
|
+
extensions: Array.isArray(r["extensions"]) ? r["extensions"].filter((x) => typeof x === "string") : DEFAULTS.extensions,
|
|
85
|
+
maxFindings: typeof r["maxFindings"] === "number" && r["maxFindings"] >= 1 && r["maxFindings"] <= 500 ? r["maxFindings"] : DEFAULTS.maxFindings
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function normalizeExtensions(exts) {
|
|
89
|
+
return exts.map((e) => e.startsWith(".") ? e.toLowerCase() : `.${e.toLowerCase()}`);
|
|
90
|
+
}
|
|
78
91
|
function toPosix(p) {
|
|
79
92
|
return p.replace(/\\/g, "/");
|
|
80
93
|
}
|
|
81
94
|
function relativePath(p) {
|
|
82
|
-
return toPosix(
|
|
95
|
+
return toPosix(relative2(process.cwd(), p));
|
|
83
96
|
}
|
|
84
97
|
var INTERFACE_RE = /(?:export\s+)?interface\s+([A-Za-z_$][A-Za-z0-9_$]*)/g;
|
|
85
98
|
function extractInterfaceNames(content) {
|
|
@@ -99,9 +112,9 @@ function hasImplementer(name, contents) {
|
|
|
99
112
|
}
|
|
100
113
|
function scanPath(rawPath, cfg) {
|
|
101
114
|
const root = process.cwd();
|
|
102
|
-
const resolved =
|
|
115
|
+
const resolved = isAbsolute2(rawPath) ? resolve2(rawPath) : resolve2(root, rawPath);
|
|
103
116
|
const exts = normalizeExtensions(cfg.extensions);
|
|
104
|
-
const files = collectSourceFiles(resolved, exts);
|
|
117
|
+
const files = collectSourceFiles(resolved, { extensions: exts });
|
|
105
118
|
const contents = [];
|
|
106
119
|
for (const p of files) {
|
|
107
120
|
try {
|
|
@@ -177,7 +190,7 @@ var plugin = {
|
|
|
177
190
|
const exts = normalizeExtensions(cfg.extensions);
|
|
178
191
|
if (!matchesExtension(sourcePath, exts)) return;
|
|
179
192
|
state.hookInvocationCount += 1;
|
|
180
|
-
const resolved =
|
|
193
|
+
const resolved = resolve2(process.cwd(), sourcePath);
|
|
181
194
|
let content;
|
|
182
195
|
try {
|
|
183
196
|
content = readFileSync(resolved, "utf-8");
|
|
@@ -195,7 +208,7 @@ var plugin = {
|
|
|
195
208
|
If you changed member shapes, search the project for implementers/\`satisfies\`/\`as\` usages and update them accordingly.`
|
|
196
209
|
};
|
|
197
210
|
};
|
|
198
|
-
state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook);
|
|
211
|
+
state.hookUnregister = api.registerHook("PostToolUse", "write|edit", hook, { background: true });
|
|
199
212
|
api.tools.register({
|
|
200
213
|
name: "check_interface_contracts",
|
|
201
214
|
description: "Scan TypeScript files for interface declarations that have no visible implementer (implements / as / satisfies).",
|
|
@@ -225,7 +238,7 @@ If you changed member shapes, search the project for implementers/\`satisfies\`/
|
|
|
225
238
|
state.findingCount += result.findings.length;
|
|
226
239
|
return {
|
|
227
240
|
ok: true,
|
|
228
|
-
path: relativePath(
|
|
241
|
+
path: relativePath(resolve2(process.cwd(), rawPath)),
|
|
229
242
|
scannedFiles: result.scannedFiles,
|
|
230
243
|
findings: result.findings
|
|
231
244
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lint-gate/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lint-gate/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAQH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAwU/C,QAAA,MAAM,MAAM,EAAE,MAwWb,CAAC;eAEa,MAAM"}
|
package/dist/lint-gate.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// src/lint-gate/index.ts
|
|
2
2
|
import { execFile } from "node:child_process";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
3
4
|
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
5
|
+
import { createRequire } from "node:module";
|
|
4
6
|
import { tmpdir } from "node:os";
|
|
5
|
-
import { join } from "node:path";
|
|
7
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
6
8
|
var API_VERSION = "^0.1.10";
|
|
7
9
|
var state = {
|
|
8
10
|
/** Total PreToolUse invocations. */
|
|
@@ -36,55 +38,74 @@ function readConfig(raw) {
|
|
|
36
38
|
fixRules: Array.isArray(r["fixRules"]) ? r["fixRules"].filter((x) => typeof x === "string") : []
|
|
37
39
|
};
|
|
38
40
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
var LINTER_PACKAGES = {
|
|
42
|
+
biome: "@biomejs/biome",
|
|
43
|
+
eslint: "eslint"
|
|
44
|
+
};
|
|
45
|
+
function isInside(parent, candidate) {
|
|
46
|
+
const rel = relative(parent, candidate);
|
|
47
|
+
return rel === "" || !rel.startsWith(`..${sep}`) && rel !== ".." && !isAbsolute(rel);
|
|
48
|
+
}
|
|
49
|
+
function resolveLocalLinter(name, cwd) {
|
|
50
|
+
try {
|
|
51
|
+
const packageName = LINTER_PACKAGES[name];
|
|
52
|
+
const requireFromProject = createRequire(resolve(cwd, "package.json"));
|
|
53
|
+
const packagePath = requireFromProject.resolve(`${packageName}/package.json`);
|
|
54
|
+
const packageJson = JSON.parse(readFileSync(packagePath, "utf-8"));
|
|
55
|
+
const relativeBin = typeof packageJson.bin === "string" ? packageJson.bin : packageJson.bin?.[name] ?? Object.values(packageJson.bin ?? {})[0];
|
|
56
|
+
if (!relativeBin || isAbsolute(relativeBin)) return null;
|
|
57
|
+
const packageDir = dirname(packagePath);
|
|
58
|
+
const entry = resolve(packageDir, relativeBin);
|
|
59
|
+
if (!isInside(packageDir, entry)) return null;
|
|
60
|
+
return {
|
|
61
|
+
cmd: process.execPath,
|
|
62
|
+
args: name === "biome" ? [entry, "check", "--reporter=json"] : [entry, "--format=json"],
|
|
63
|
+
name
|
|
64
|
+
};
|
|
65
|
+
} catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
41
68
|
}
|
|
42
|
-
function runCommand(command, args, timeoutMs, signal) {
|
|
43
|
-
return new Promise((
|
|
69
|
+
function runCommand(command, args, timeoutMs, cwd, signal) {
|
|
70
|
+
return new Promise((resolveResult) => {
|
|
44
71
|
try {
|
|
45
72
|
execFile(
|
|
46
|
-
|
|
73
|
+
command,
|
|
47
74
|
args,
|
|
48
75
|
{
|
|
49
76
|
encoding: "utf-8",
|
|
50
77
|
timeout: timeoutMs,
|
|
51
|
-
cwd
|
|
78
|
+
cwd,
|
|
52
79
|
windowsHide: true,
|
|
80
|
+
shell: false,
|
|
53
81
|
maxBuffer: 2 * 1024 * 1024,
|
|
54
82
|
...signal ? { signal } : {}
|
|
55
83
|
},
|
|
56
|
-
(error, stdout) =>
|
|
84
|
+
(error, stdout) => resolveResult({ stdout, error })
|
|
57
85
|
);
|
|
58
86
|
} catch (err) {
|
|
59
|
-
|
|
87
|
+
resolveResult({ stdout: "", error: err instanceof Error ? err : new Error(String(err)) });
|
|
60
88
|
}
|
|
61
89
|
});
|
|
62
90
|
}
|
|
63
|
-
async function detectLinter(requested) {
|
|
64
|
-
const
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
if (tryEslint) {
|
|
73
|
-
const probe = await runCommand("npx", ["eslint", "--version"], 5e3);
|
|
74
|
-
if (!probe.error) {
|
|
75
|
-
return { cmd: "npx", args: ["eslint", "--format=json"], name: "eslint" };
|
|
76
|
-
}
|
|
91
|
+
async function detectLinter(requested, cwd) {
|
|
92
|
+
const candidates = requested === "auto" ? ["biome", "eslint"] : [requested];
|
|
93
|
+
for (const name of candidates) {
|
|
94
|
+
const linter = resolveLocalLinter(name, cwd);
|
|
95
|
+
if (!linter) continue;
|
|
96
|
+
const probe = await runCommand(linter.cmd, [linter.args[0], "--version"], 5e3, cwd);
|
|
97
|
+
if (!probe.error) return linter;
|
|
77
98
|
}
|
|
78
99
|
return null;
|
|
79
100
|
}
|
|
80
|
-
async function lintContent(content, filePath, linter, timeoutMs, signal) {
|
|
101
|
+
async function lintContent(content, filePath, linter, timeoutMs, cwd, signal) {
|
|
81
102
|
const ext = filePath.includes(".") ? filePath.slice(filePath.lastIndexOf(".")) : ".ts";
|
|
82
103
|
const tmpDir = await mkdtemp(join(tmpdir(), "lint-gate-"));
|
|
83
104
|
const tmpFile = join(tmpDir, `input${ext}`);
|
|
84
105
|
try {
|
|
85
106
|
await writeFile(tmpFile, content, "utf-8");
|
|
86
107
|
const fullArgs = [...linter.args, tmpFile];
|
|
87
|
-
const result = await runCommand(linter.cmd, fullArgs, timeoutMs, signal);
|
|
108
|
+
const result = await runCommand(linter.cmd, fullArgs, timeoutMs, cwd, signal);
|
|
88
109
|
if (signal.aborted) throw signal.reason;
|
|
89
110
|
if (result.error && !result.stdout) return null;
|
|
90
111
|
return parseLinterOutput(result.stdout, linter.name);
|
|
@@ -95,14 +116,14 @@ async function lintContent(content, filePath, linter, timeoutMs, signal) {
|
|
|
95
116
|
await rm(tmpDir, { recursive: true, force: true }).catch(() => void 0);
|
|
96
117
|
}
|
|
97
118
|
}
|
|
98
|
-
async function lintAndFix(content, filePath, linter, timeoutMs, signal) {
|
|
119
|
+
async function lintAndFix(content, filePath, linter, timeoutMs, cwd, signal) {
|
|
99
120
|
const ext = filePath.includes(".") ? filePath.slice(filePath.lastIndexOf(".")) : ".ts";
|
|
100
121
|
const tmpDir = await mkdtemp(join(tmpdir(), "lint-gate-fix-"));
|
|
101
122
|
const tmpFile = join(tmpDir, `input${ext}`);
|
|
102
123
|
try {
|
|
103
124
|
await writeFile(tmpFile, content, "utf-8");
|
|
104
|
-
const fixArgs = linter.name === "biome" ? [
|
|
105
|
-
await runCommand(linter.cmd, fixArgs, timeoutMs, signal);
|
|
125
|
+
const fixArgs = linter.name === "biome" ? [linter.args[0], "check", "--write", tmpFile] : [linter.args[0], "--fix", tmpFile];
|
|
126
|
+
await runCommand(linter.cmd, fixArgs, timeoutMs, cwd, signal);
|
|
106
127
|
if (signal.aborted) throw signal.reason;
|
|
107
128
|
return await readFile(tmpFile, "utf-8");
|
|
108
129
|
} catch {
|
|
@@ -203,7 +224,8 @@ var plugin = {
|
|
|
203
224
|
state.hookUnregister = null;
|
|
204
225
|
state.lastResult = null;
|
|
205
226
|
const cfg = readConfig(api.config.extensions?.["lint-gate"]);
|
|
206
|
-
const
|
|
227
|
+
const cwd = resolve(api.config.cwd ?? process.cwd());
|
|
228
|
+
const linterReady = detectLinter(cfg.linter, cwd).then((linter) => {
|
|
207
229
|
if (!linter) {
|
|
208
230
|
api.log.warn("lint-gate: no linter found (biome or eslint) \u2014 hook will be a no-op", {
|
|
209
231
|
requested: cfg.linter
|
|
@@ -240,7 +262,14 @@ var plugin = {
|
|
|
240
262
|
} else {
|
|
241
263
|
return;
|
|
242
264
|
}
|
|
243
|
-
const issues = await lintContent(
|
|
265
|
+
const issues = await lintContent(
|
|
266
|
+
content,
|
|
267
|
+
filePath,
|
|
268
|
+
linter,
|
|
269
|
+
cfg.timeoutMs,
|
|
270
|
+
cwd,
|
|
271
|
+
runtime.signal
|
|
272
|
+
);
|
|
244
273
|
if (issues === null) {
|
|
245
274
|
state.linterErrorCount += 1;
|
|
246
275
|
return;
|
|
@@ -280,6 +309,7 @@ ${summary}${truncated}`
|
|
|
280
309
|
filePath,
|
|
281
310
|
linter,
|
|
282
311
|
cfg.timeoutMs,
|
|
312
|
+
cwd,
|
|
283
313
|
runtime.signal
|
|
284
314
|
);
|
|
285
315
|
if (fixedContent !== content) {
|
|
@@ -318,6 +348,7 @@ ${remainingSummary}` : "")
|
|
|
318
348
|
filePath,
|
|
319
349
|
linter,
|
|
320
350
|
cfg.timeoutMs,
|
|
351
|
+
cwd,
|
|
321
352
|
runtime.signal
|
|
322
353
|
);
|
|
323
354
|
if (fixedNewStr !== newStr) {
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* The plugin reads a package CHANGELOG (project root or node_modules) and
|
|
5
5
|
* produces a migration checklist with breaking changes and recommended steps
|
|
6
6
|
* between two versions. If no changelog is available it returns a generic
|
|
7
|
-
* migration guide.
|
|
7
|
+
* migration guide. Optional `api.llm` analysis stays separate from the
|
|
8
|
+
* deterministic facts and falls back to them on any invalid response.
|
|
8
9
|
*
|
|
9
10
|
* Tools registered:
|
|
10
11
|
* - migration_plan — produce a migration checklist for a package/version range
|
|
@@ -16,13 +17,22 @@
|
|
|
16
17
|
* {
|
|
17
18
|
* "enabled": true,
|
|
18
19
|
* "changelogPaths": ["CHANGELOG.md"],
|
|
19
|
-
* "maxChars": 100_000
|
|
20
|
+
* "maxChars": 100_000,
|
|
21
|
+
* "useLlm": false,
|
|
22
|
+
* "maxLlmChars": 20_000
|
|
20
23
|
* }
|
|
21
24
|
* ```
|
|
22
25
|
*
|
|
23
26
|
* @public
|
|
24
27
|
*/
|
|
25
28
|
import type { Plugin } from '@wrongstack/core';
|
|
29
|
+
export interface MigrationAiAnalysis {
|
|
30
|
+
summary: string;
|
|
31
|
+
riskLevel: 'low' | 'medium' | 'high' | 'unknown';
|
|
32
|
+
risks: string[];
|
|
33
|
+
additionalSteps: string[];
|
|
34
|
+
verificationSteps: string[];
|
|
35
|
+
}
|
|
26
36
|
declare const plugin: Plugin;
|
|
27
37
|
export default plugin;
|
|
28
38
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migration-planner/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migration-planner/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAwP/C,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;IACjD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAwED,QAAA,MAAM,MAAM,EAAE,MA+Sb,CAAC;eAEa,MAAM"}
|