projscan 0.12.0 → 0.14.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.
Files changed (105) hide show
  1. package/README.md +18 -13
  2. package/dist/analyzers/crossPackageImportCheck.d.ts +13 -0
  3. package/dist/analyzers/crossPackageImportCheck.js +136 -0
  4. package/dist/analyzers/crossPackageImportCheck.js.map +1 -0
  5. package/dist/analyzers/cycleCheck.d.ts +12 -0
  6. package/dist/analyzers/cycleCheck.js +65 -0
  7. package/dist/analyzers/cycleCheck.js.map +1 -0
  8. package/dist/cli/commands/audit.js +8 -2
  9. package/dist/cli/commands/audit.js.map +1 -1
  10. package/dist/cli/commands/dependencies.js +4 -3
  11. package/dist/cli/commands/dependencies.js.map +1 -1
  12. package/dist/cli/commands/explainIssue.d.ts +1 -0
  13. package/dist/cli/commands/explainIssue.js +49 -0
  14. package/dist/cli/commands/explainIssue.js.map +1 -0
  15. package/dist/cli/commands/fixSuggest.d.ts +1 -0
  16. package/dist/cli/commands/fixSuggest.js +71 -0
  17. package/dist/cli/commands/fixSuggest.js.map +1 -0
  18. package/dist/cli/commands/review.d.ts +1 -0
  19. package/dist/cli/commands/review.js +66 -0
  20. package/dist/cli/commands/review.js.map +1 -0
  21. package/dist/cli/index.js +6 -0
  22. package/dist/cli/index.js.map +1 -1
  23. package/dist/core/ast.d.ts +20 -0
  24. package/dist/core/ast.js +190 -0
  25. package/dist/core/ast.js.map +1 -1
  26. package/dist/core/auditRunner.d.ts +8 -0
  27. package/dist/core/auditRunner.js +50 -1
  28. package/dist/core/auditRunner.js.map +1 -1
  29. package/dist/core/codeGraph.d.ts +7 -1
  30. package/dist/core/codeGraph.js +2 -0
  31. package/dist/core/codeGraph.js.map +1 -1
  32. package/dist/core/dependencyAnalyzer.d.ts +15 -1
  33. package/dist/core/dependencyAnalyzer.js +115 -18
  34. package/dist/core/dependencyAnalyzer.js.map +1 -1
  35. package/dist/core/explainIssue.d.ts +9 -0
  36. package/dist/core/explainIssue.js +106 -0
  37. package/dist/core/explainIssue.js.map +1 -0
  38. package/dist/core/fileInspector.js +12 -0
  39. package/dist/core/fileInspector.js.map +1 -1
  40. package/dist/core/fixSuggest.d.ts +41 -0
  41. package/dist/core/fixSuggest.js +327 -0
  42. package/dist/core/fixSuggest.js.map +1 -0
  43. package/dist/core/indexCache.js +5 -1
  44. package/dist/core/indexCache.js.map +1 -1
  45. package/dist/core/issueEngine.js +18 -0
  46. package/dist/core/issueEngine.js.map +1 -1
  47. package/dist/core/languages/goAdapter.js +5 -0
  48. package/dist/core/languages/goAdapter.js.map +1 -1
  49. package/dist/core/languages/goFunctions.d.ts +24 -0
  50. package/dist/core/languages/goFunctions.js +99 -0
  51. package/dist/core/languages/goFunctions.js.map +1 -0
  52. package/dist/core/languages/javaAdapter.js +5 -0
  53. package/dist/core/languages/javaAdapter.js.map +1 -1
  54. package/dist/core/languages/javaFunctions.d.ts +22 -0
  55. package/dist/core/languages/javaFunctions.js +87 -0
  56. package/dist/core/languages/javaFunctions.js.map +1 -0
  57. package/dist/core/languages/pythonAdapter.js +5 -0
  58. package/dist/core/languages/pythonAdapter.js.map +1 -1
  59. package/dist/core/languages/pythonFunctions.d.ts +23 -0
  60. package/dist/core/languages/pythonFunctions.js +87 -0
  61. package/dist/core/languages/pythonFunctions.js.map +1 -0
  62. package/dist/core/languages/rubyAdapter.js +5 -0
  63. package/dist/core/languages/rubyAdapter.js.map +1 -1
  64. package/dist/core/languages/rubyFunctions.d.ts +22 -0
  65. package/dist/core/languages/rubyFunctions.js +91 -0
  66. package/dist/core/languages/rubyFunctions.js.map +1 -0
  67. package/dist/core/review.d.ts +21 -0
  68. package/dist/core/review.js +457 -0
  69. package/dist/core/review.js.map +1 -0
  70. package/dist/index.d.ts +5 -1
  71. package/dist/index.js +3 -0
  72. package/dist/index.js.map +1 -1
  73. package/dist/mcp/tools/audit.js +7 -2
  74. package/dist/mcp/tools/audit.js.map +1 -1
  75. package/dist/mcp/tools/dependencies.js +11 -5
  76. package/dist/mcp/tools/dependencies.js.map +1 -1
  77. package/dist/mcp/tools/explainIssue.d.ts +2 -0
  78. package/dist/mcp/tools/explainIssue.js +30 -0
  79. package/dist/mcp/tools/explainIssue.js.map +1 -0
  80. package/dist/mcp/tools/file.js +1 -1
  81. package/dist/mcp/tools/file.js.map +1 -1
  82. package/dist/mcp/tools/fixSuggest.d.ts +2 -0
  83. package/dist/mcp/tools/fixSuggest.js +57 -0
  84. package/dist/mcp/tools/fixSuggest.js.map +1 -0
  85. package/dist/mcp/tools/hotspots.js +40 -1
  86. package/dist/mcp/tools/hotspots.js.map +1 -1
  87. package/dist/mcp/tools/review.d.ts +2 -0
  88. package/dist/mcp/tools/review.js +54 -0
  89. package/dist/mcp/tools/review.js.map +1 -0
  90. package/dist/mcp/tools.js +6 -0
  91. package/dist/mcp/tools.js.map +1 -1
  92. package/dist/reporters/consoleReporter.d.ts +9 -1
  93. package/dist/reporters/consoleReporter.js +177 -0
  94. package/dist/reporters/consoleReporter.js.map +1 -1
  95. package/dist/reporters/jsonReporter.d.ts +9 -1
  96. package/dist/reporters/jsonReporter.js +9 -0
  97. package/dist/reporters/jsonReporter.js.map +1 -1
  98. package/dist/reporters/markdownReporter.d.ts +9 -1
  99. package/dist/reporters/markdownReporter.js +141 -0
  100. package/dist/reporters/markdownReporter.js.map +1 -1
  101. package/dist/tool-manifest.json +96 -8
  102. package/dist/types.d.ts +228 -0
  103. package/dist/utils/config.js +27 -0
  104. package/dist/utils/config.js.map +1 -1
  105. package/package.json +4 -2
@@ -0,0 +1,457 @@
1
+ import { spawn } from 'node:child_process';
2
+ import fs from 'node:fs/promises';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { scanRepository } from './repositoryScanner.js';
6
+ import { collectIssues } from './issueEngine.js';
7
+ import { buildCodeGraph } from './codeGraph.js';
8
+ import { analyzeHotspots } from './hotspotAnalyzer.js';
9
+ import { computeCoupling } from './couplingAnalyzer.js';
10
+ import { diffGraphs } from './prDiff.js';
11
+ const HIGH_CC_THRESHOLD = 10;
12
+ const CC_JUMP_THRESHOLD = 5;
13
+ const RISK_VERDICT_BLOCK_SCORE = 80;
14
+ const RISK_VERDICT_REVIEW_SCORE = 40;
15
+ /**
16
+ * Compose a one-shot PR review. Builds head + base graphs (worktree dance),
17
+ * joins the structural diff with hotspot risk scores, surfaces cycles
18
+ * introduced by the PR, flags newly-risky functions, and reports
19
+ * package.json deltas. Output is shaped for an agent to read once and decide
20
+ * whether to merge, request changes, or escalate.
21
+ *
22
+ * Verdict heuristic (rough; tune with usage):
23
+ * block - max changed-file risk >= 80 OR a new cycle includes added files
24
+ * review - max changed-file risk >= 40 OR new high-CC functions OR
25
+ * major-dep-bump
26
+ * ok - otherwise
27
+ */
28
+ export async function computeReview(rootPath, options = {}) {
29
+ const isRepo = await isGitRepository(rootPath);
30
+ if (!isRepo) {
31
+ return unavailable('Not a git repository - PR review requires git history.', options);
32
+ }
33
+ const headRef = options.head ?? 'HEAD';
34
+ const baseRef = options.base ?? (await pickDefaultBase(rootPath));
35
+ const headSha = await resolveSha(rootPath, headRef);
36
+ const baseSha = await resolveSha(rootPath, baseRef);
37
+ if (!baseSha) {
38
+ return unavailable(`Could not resolve base ref "${baseRef}".`, options, baseRef, headRef, headSha);
39
+ }
40
+ // Head-side data: scan + graph + issues + hotspots.
41
+ const headScan = await scanRepository(rootPath);
42
+ const headGraph = await buildCodeGraph(rootPath, headScan.files);
43
+ const headIssues = await collectIssues(rootPath, headScan.files);
44
+ const headHotspots = await analyzeHotspots(rootPath, headScan.files, headIssues, {
45
+ limit: 200,
46
+ graph: headGraph,
47
+ });
48
+ // Base-side: spin up a worktree, scan, build graph. Best-effort cleanup.
49
+ const worktreeDir = await mkTempWorktreeDir();
50
+ let baseGraph;
51
+ let basePackageManifests;
52
+ try {
53
+ await runGit(rootPath, ['worktree', 'add', '--detach', worktreeDir, baseSha]);
54
+ const baseScan = await scanRepository(worktreeDir);
55
+ baseGraph = await buildCodeGraph(worktreeDir, baseScan.files);
56
+ basePackageManifests = await readManifests(worktreeDir);
57
+ }
58
+ finally {
59
+ await runGit(rootPath, ['worktree', 'remove', '--force', worktreeDir]).catch(() => { });
60
+ await fs.rm(worktreeDir, { recursive: true, force: true }).catch(() => { });
61
+ }
62
+ const headPackageManifests = await readManifests(rootPath);
63
+ const prDiff = diffGraphs(baseRef, baseSha, headRef, headSha, baseGraph, headGraph);
64
+ // Build the per-file enriched view. Index head hotspots by path for O(1) lookup.
65
+ const hotspotByPath = new Map();
66
+ for (const h of headHotspots.hotspots)
67
+ hotspotByPath.set(h.relativePath, h.riskScore);
68
+ const changedFiles = [];
69
+ for (const f of prDiff.filesAdded) {
70
+ const headFile = headGraph.files.get(f);
71
+ changedFiles.push({
72
+ relativePath: f,
73
+ status: 'added',
74
+ riskScore: hotspotByPath.get(f) ?? null,
75
+ cyclomaticComplexity: headFile?.parseOk ? headFile.cyclomaticComplexity : null,
76
+ cyclomaticDelta: null,
77
+ exportsAdded: headFile?.exports.length ?? 0,
78
+ exportsRemoved: 0,
79
+ importsAdded: headFile?.imports.length ?? 0,
80
+ importsRemoved: 0,
81
+ });
82
+ }
83
+ for (const f of prDiff.filesRemoved) {
84
+ const baseFile = baseGraph.files.get(f);
85
+ changedFiles.push({
86
+ relativePath: f,
87
+ status: 'removed',
88
+ riskScore: null,
89
+ cyclomaticComplexity: null,
90
+ cyclomaticDelta: null,
91
+ exportsAdded: 0,
92
+ exportsRemoved: baseFile?.exports.length ?? 0,
93
+ importsAdded: 0,
94
+ importsRemoved: baseFile?.imports.length ?? 0,
95
+ });
96
+ }
97
+ for (const f of prDiff.filesModified) {
98
+ const headFile = headGraph.files.get(f.relativePath);
99
+ changedFiles.push({
100
+ relativePath: f.relativePath,
101
+ status: 'modified',
102
+ riskScore: hotspotByPath.get(f.relativePath) ?? null,
103
+ cyclomaticComplexity: headFile?.parseOk ? headFile.cyclomaticComplexity : null,
104
+ cyclomaticDelta: f.cyclomaticDelta,
105
+ exportsAdded: f.exportsAdded.length,
106
+ exportsRemoved: f.exportsRemoved.length,
107
+ importsAdded: f.importsAdded.length,
108
+ importsRemoved: f.importsRemoved.length,
109
+ });
110
+ }
111
+ changedFiles.sort((a, b) => (b.riskScore ?? 0) - (a.riskScore ?? 0));
112
+ // Cycles: compute on both sides; classify head cycles as new/expanded based
113
+ // on overlap with base cycles.
114
+ const headCoupling = computeCoupling(headGraph);
115
+ const baseCoupling = computeCoupling(baseGraph);
116
+ const newCycles = classifyNewCycles(baseCoupling.cycles, headCoupling.cycles, prDiff.filesAdded);
117
+ // Risky functions: compare per-file function lists between base and head.
118
+ const riskyFunctions = findRiskyFunctions(baseGraph, headGraph, prDiff);
119
+ // Dependency changes across root + workspaces.
120
+ const dependencyChanges = diffManifests(basePackageManifests, headPackageManifests);
121
+ // Verdict.
122
+ const { verdict, summary } = decideVerdict(changedFiles, newCycles, riskyFunctions, dependencyChanges);
123
+ return {
124
+ available: true,
125
+ base: { ref: baseRef, resolvedSha: baseSha },
126
+ head: { ref: headRef, resolvedSha: headSha },
127
+ prDiff,
128
+ changedFiles,
129
+ newCycles,
130
+ riskyFunctions,
131
+ dependencyChanges,
132
+ verdict,
133
+ summary,
134
+ };
135
+ }
136
+ // ── cycle classification ──────────────────────────────────
137
+ function classifyNewCycles(baseCycles, headCycles, filesAddedInPr) {
138
+ const added = new Set(filesAddedInPr);
139
+ const out = [];
140
+ for (const head of headCycles) {
141
+ const headSet = new Set(head.files);
142
+ let bestOverlap = 0;
143
+ for (const base of baseCycles) {
144
+ let overlap = 0;
145
+ for (const f of base.files)
146
+ if (headSet.has(f))
147
+ overlap++;
148
+ if (overlap > bestOverlap)
149
+ bestOverlap = overlap;
150
+ }
151
+ if (bestOverlap === 0) {
152
+ out.push({ files: [...head.files].sort(), size: head.files.length, classification: 'new' });
153
+ }
154
+ else if (bestOverlap < head.files.length) {
155
+ // cycle existed but grew
156
+ out.push({
157
+ files: [...head.files].sort(),
158
+ size: head.files.length,
159
+ classification: 'expanded',
160
+ });
161
+ }
162
+ // bestOverlap === head.files.length means the cycle is identical at base.
163
+ }
164
+ // Bump cycles where any file is newly added to the very front.
165
+ out.sort((a, b) => {
166
+ const aTouchesAdded = a.files.some((f) => added.has(f)) ? 0 : 1;
167
+ const bTouchesAdded = b.files.some((f) => added.has(f)) ? 0 : 1;
168
+ if (aTouchesAdded !== bTouchesAdded)
169
+ return aTouchesAdded - bTouchesAdded;
170
+ return b.size - a.size;
171
+ });
172
+ return out;
173
+ }
174
+ // ── risky function detection ──────────────────────────────
175
+ function findRiskyFunctions(baseGraph, headGraph, prDiff) {
176
+ const out = [];
177
+ for (const file of prDiff.filesAdded) {
178
+ const head = headGraph.files.get(file);
179
+ if (!head)
180
+ continue;
181
+ for (const fn of head.functions ?? []) {
182
+ if (fn.cyclomaticComplexity >= HIGH_CC_THRESHOLD) {
183
+ out.push({
184
+ file,
185
+ name: fn.name,
186
+ line: fn.line,
187
+ endLine: fn.endLine,
188
+ cyclomaticComplexity: fn.cyclomaticComplexity,
189
+ baseCc: null,
190
+ reason: 'added',
191
+ });
192
+ }
193
+ }
194
+ }
195
+ for (const f of prDiff.filesModified) {
196
+ const head = headGraph.files.get(f.relativePath);
197
+ const base = baseGraph.files.get(f.relativePath);
198
+ if (!head || !base)
199
+ continue;
200
+ const baseByName = new Map();
201
+ for (const fn of base.functions ?? [])
202
+ baseByName.set(fn.name, fn.cyclomaticComplexity);
203
+ for (const fn of head.functions ?? []) {
204
+ const baseCc = baseByName.get(fn.name);
205
+ if (baseCc === undefined) {
206
+ // Newly added function. Flag if high CC.
207
+ if (fn.cyclomaticComplexity >= HIGH_CC_THRESHOLD) {
208
+ out.push({
209
+ file: f.relativePath,
210
+ name: fn.name,
211
+ line: fn.line,
212
+ endLine: fn.endLine,
213
+ cyclomaticComplexity: fn.cyclomaticComplexity,
214
+ baseCc: null,
215
+ reason: 'added',
216
+ });
217
+ }
218
+ continue;
219
+ }
220
+ // Existed: flag if it newly crossed the threshold.
221
+ if (baseCc < HIGH_CC_THRESHOLD &&
222
+ fn.cyclomaticComplexity >= HIGH_CC_THRESHOLD) {
223
+ out.push({
224
+ file: f.relativePath,
225
+ name: fn.name,
226
+ line: fn.line,
227
+ endLine: fn.endLine,
228
+ cyclomaticComplexity: fn.cyclomaticComplexity,
229
+ baseCc,
230
+ reason: 'crossed-threshold',
231
+ });
232
+ continue;
233
+ }
234
+ // Or: jumped by JUMP threshold even if both sides under HIGH_CC_THRESHOLD.
235
+ if (fn.cyclomaticComplexity - baseCc >= CC_JUMP_THRESHOLD) {
236
+ out.push({
237
+ file: f.relativePath,
238
+ name: fn.name,
239
+ line: fn.line,
240
+ endLine: fn.endLine,
241
+ cyclomaticComplexity: fn.cyclomaticComplexity,
242
+ baseCc,
243
+ reason: 'jumped',
244
+ });
245
+ }
246
+ }
247
+ }
248
+ out.sort((a, b) => b.cyclomaticComplexity - a.cyclomaticComplexity);
249
+ return out;
250
+ }
251
+ async function readManifests(rootPath) {
252
+ // Use detectWorkspaces to enumerate; if no workspaces just read the root.
253
+ const { detectWorkspaces } = await import('./monorepo.js');
254
+ const ws = await detectWorkspaces(rootPath);
255
+ const out = new Map();
256
+ const all = ws.kind === 'none' ? [] : ws.packages;
257
+ if (all.length === 0) {
258
+ const root = await readOneManifest(rootPath, 'package.json', '');
259
+ if (root)
260
+ out.set('package.json', root);
261
+ return out;
262
+ }
263
+ for (const p of all) {
264
+ const manifestRel = p.relativePath ? `${p.relativePath}/package.json` : 'package.json';
265
+ const dir = path.join(rootPath, p.relativePath);
266
+ const m = await readOneManifest(dir, manifestRel, p.name);
267
+ if (m)
268
+ out.set(manifestRel, m);
269
+ }
270
+ return out;
271
+ }
272
+ async function readOneManifest(dir, manifestFile, workspaceName) {
273
+ const p = path.join(dir, 'package.json');
274
+ let raw;
275
+ try {
276
+ raw = await fs.readFile(p, 'utf-8');
277
+ }
278
+ catch {
279
+ return null;
280
+ }
281
+ let parsed;
282
+ try {
283
+ parsed = JSON.parse(raw);
284
+ }
285
+ catch {
286
+ return null;
287
+ }
288
+ return {
289
+ workspace: workspaceName,
290
+ manifestFile,
291
+ dependencies: parsed.dependencies ?? {},
292
+ devDependencies: parsed.devDependencies ?? {},
293
+ };
294
+ }
295
+ function diffManifests(base, head) {
296
+ const out = [];
297
+ const allManifests = new Set([...base.keys(), ...head.keys()]);
298
+ for (const manifestFile of allManifests) {
299
+ const b = base.get(manifestFile);
300
+ const h = head.get(manifestFile);
301
+ if (!b && !h)
302
+ continue;
303
+ const change = diffOneManifest(b, h, manifestFile);
304
+ if (change.added.length || change.removed.length || change.bumped.length) {
305
+ out.push(change);
306
+ }
307
+ }
308
+ out.sort((a, b) => a.manifestFile.localeCompare(b.manifestFile));
309
+ return out;
310
+ }
311
+ function diffOneManifest(base, head, manifestFile) {
312
+ const workspace = head?.workspace ?? base?.workspace ?? '';
313
+ const baseDeps = base?.dependencies ?? {};
314
+ const baseDev = base?.devDependencies ?? {};
315
+ const headDeps = head?.dependencies ?? {};
316
+ const headDev = head?.devDependencies ?? {};
317
+ const added = [];
318
+ const removed = [];
319
+ const bumped = [];
320
+ for (const [name, version] of Object.entries(headDeps)) {
321
+ if (!(name in baseDeps))
322
+ added.push({ name, version, kind: 'dep' });
323
+ else if (baseDeps[name] !== version)
324
+ bumped.push({ name, from: baseDeps[name], to: version, kind: 'dep' });
325
+ }
326
+ for (const [name, version] of Object.entries(baseDeps)) {
327
+ if (!(name in headDeps))
328
+ removed.push({ name, version, kind: 'dep' });
329
+ }
330
+ for (const [name, version] of Object.entries(headDev)) {
331
+ if (!(name in baseDev))
332
+ added.push({ name, version, kind: 'dev' });
333
+ else if (baseDev[name] !== version)
334
+ bumped.push({ name, from: baseDev[name], to: version, kind: 'dev' });
335
+ }
336
+ for (const [name, version] of Object.entries(baseDev)) {
337
+ if (!(name in headDev))
338
+ removed.push({ name, version, kind: 'dev' });
339
+ }
340
+ added.sort((a, b) => a.name.localeCompare(b.name));
341
+ removed.sort((a, b) => a.name.localeCompare(b.name));
342
+ bumped.sort((a, b) => a.name.localeCompare(b.name));
343
+ return { workspace, manifestFile, added, removed, bumped };
344
+ }
345
+ // ── verdict ───────────────────────────────────────────────
346
+ function decideVerdict(changedFiles, newCycles, riskyFunctions, depChanges) {
347
+ const summary = [];
348
+ let verdict = 'ok';
349
+ const maxRisk = Math.max(0, ...changedFiles.map((f) => f.riskScore ?? 0));
350
+ if (maxRisk >= RISK_VERDICT_BLOCK_SCORE) {
351
+ verdict = 'block';
352
+ summary.push(`Maximum changed-file risk score is ${maxRisk.toFixed(1)} (>= ${RISK_VERDICT_BLOCK_SCORE}).`);
353
+ }
354
+ else if (maxRisk >= RISK_VERDICT_REVIEW_SCORE) {
355
+ verdict = bumpTo(verdict, 'review');
356
+ summary.push(`Maximum changed-file risk score is ${maxRisk.toFixed(1)} (>= ${RISK_VERDICT_REVIEW_SCORE}).`);
357
+ }
358
+ if (newCycles.length > 0) {
359
+ const newOnly = newCycles.filter((c) => c.classification === 'new');
360
+ if (newOnly.length > 0) {
361
+ verdict = 'block';
362
+ summary.push(`${newOnly.length} new import cycle(s) introduced.`);
363
+ }
364
+ else {
365
+ verdict = bumpTo(verdict, 'review');
366
+ summary.push(`${newCycles.length} cycle(s) expanded.`);
367
+ }
368
+ }
369
+ if (riskyFunctions.length > 0) {
370
+ verdict = bumpTo(verdict, 'review');
371
+ summary.push(`${riskyFunctions.length} function(s) flagged: high CC added or jumped.`);
372
+ }
373
+ if (depChanges.length > 0) {
374
+ const totals = depChanges.reduce((acc, d) => {
375
+ acc.added += d.added.length;
376
+ acc.removed += d.removed.length;
377
+ acc.bumped += d.bumped.length;
378
+ return acc;
379
+ }, { added: 0, removed: 0, bumped: 0 });
380
+ if (totals.added + totals.removed + totals.bumped > 0) {
381
+ summary.push(`Dependency changes: +${totals.added} -${totals.removed} ~${totals.bumped}.`);
382
+ }
383
+ }
384
+ if (changedFiles.length === 0 && summary.length === 0) {
385
+ summary.push('No structural changes detected between base and head.');
386
+ }
387
+ else if (verdict === 'ok' && summary.length === 0) {
388
+ summary.push(`${changedFiles.length} file(s) changed; no risk signals.`);
389
+ }
390
+ return { verdict, summary };
391
+ }
392
+ function bumpTo(current, target) {
393
+ const order = { ok: 0, review: 1, block: 2 };
394
+ return order[target] > order[current] ? target : current;
395
+ }
396
+ // ── git helpers (mirror prDiff.ts; kept private to keep coupling low) ──
397
+ function unavailable(reason, options, baseRef = options.base ?? '', headRef = options.head ?? 'HEAD', headSha = null) {
398
+ return {
399
+ available: false,
400
+ reason,
401
+ base: { ref: baseRef, resolvedSha: null },
402
+ head: { ref: headRef, resolvedSha: headSha },
403
+ prDiff: {
404
+ available: false,
405
+ reason,
406
+ base: { ref: baseRef, resolvedSha: null },
407
+ head: { ref: headRef, resolvedSha: headSha },
408
+ filesAdded: [],
409
+ filesRemoved: [],
410
+ filesModified: [],
411
+ totalFilesChanged: 0,
412
+ },
413
+ changedFiles: [],
414
+ newCycles: [],
415
+ riskyFunctions: [],
416
+ dependencyChanges: [],
417
+ verdict: 'ok',
418
+ summary: [reason],
419
+ };
420
+ }
421
+ async function isGitRepository(rootPath) {
422
+ const { code } = await runGit(rootPath, ['rev-parse', '--is-inside-work-tree']).catch(() => ({
423
+ code: 1,
424
+ stdout: '',
425
+ stderr: '',
426
+ }));
427
+ return code === 0;
428
+ }
429
+ async function resolveSha(rootPath, ref) {
430
+ const { code, stdout } = await runGit(rootPath, ['rev-parse', '--verify', `${ref}^{commit}`]).catch(() => ({ code: 1, stdout: '', stderr: '' }));
431
+ if (code !== 0)
432
+ return null;
433
+ const sha = stdout.trim();
434
+ return sha || null;
435
+ }
436
+ async function pickDefaultBase(rootPath) {
437
+ for (const candidate of ['origin/main', 'main', 'origin/master', 'master']) {
438
+ if (await resolveSha(rootPath, candidate))
439
+ return candidate;
440
+ }
441
+ return 'HEAD~1';
442
+ }
443
+ async function mkTempWorktreeDir() {
444
+ return fs.mkdtemp(path.join(os.tmpdir(), 'projscan-review-'));
445
+ }
446
+ function runGit(cwd, args) {
447
+ return new Promise((resolve, reject) => {
448
+ const child = spawn('git', args, { cwd, env: process.env });
449
+ let stdout = '';
450
+ let stderr = '';
451
+ child.stdout.on('data', (d) => (stdout += d.toString()));
452
+ child.stderr.on('data', (d) => (stderr += d.toString()));
453
+ child.on('error', reject);
454
+ child.on('close', (code) => resolve({ code: code ?? 1, stdout, stderr }));
455
+ });
456
+ }
457
+ //# sourceMappingURL=review.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.js","sourceRoot":"","sources":["../../src/core/review.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -12,6 +12,7 @@ export { previewUpgrade, isValidPackageName } from './core/upgradePreview.js';
12
12
  export { parseCoverage, coverageMap } from './core/coverageParser.js';
13
13
  export { joinCoverageWithHotspots } from './core/coverageJoin.js';
14
14
  export { parseSource, isParseable } from './core/ast.js';
15
+ export type { FunctionInfo } from './core/ast.js';
15
16
  export { buildCodeGraph, filesImportingFile, filesImportingPackage, filesDefiningSymbol, exportsOf, importsOf, importersOf, } from './core/codeGraph.js';
16
17
  export { loadCachedGraph, saveCachedGraph, invalidateCache } from './core/indexCache.js';
17
18
  export { applyBudget, estimateTokens } from './mcp/tokenBudget.js';
@@ -27,8 +28,11 @@ export { walkFiles } from './utils/fileWalker.js';
27
28
  export { loadConfig, applyConfigToIssues } from './utils/config.js';
28
29
  export { getChangedFiles } from './utils/changedFiles.js';
29
30
  export { issuesToSarif } from './reporters/sarifReporter.js';
31
+ export { computeReview } from './core/review.js';
32
+ export { suggestFixForIssue, previewSuggestionForIssue, syntheticIssue, findIssue } from './core/fixSuggest.js';
33
+ export { explainIssue } from './core/explainIssue.js';
30
34
  export { createMcpServer, runMcpServer } from './mcp/server.js';
31
35
  export { getToolDefinitions } from './mcp/tools.js';
32
36
  export { getPromptDefinitions } from './mcp/prompts.js';
33
37
  export { getResourceDefinitions } from './mcp/resources.js';
34
- export type { ScanResult, FileEntry, DirectoryNode, LanguageBreakdown, LanguageStat, FrameworkResult, DetectedFramework, DependencyReport, DependencyRisk, Issue, IssueLocation, IssueSeverity, Fix, FixResult, FileExplanation, FileInspection, ImportInfo, ExportInfo, ArchitectureLayer, AnalysisReport, ReportFormat, FileHotspot, HotspotReport, AuthorShare, BaselineHotspot, HotspotDelta, HotspotDiffSummary, McpToolDefinition, McpPromptDefinition, McpResourceDefinition, ProjscanConfig, LoadedConfig, SemverDrift, OutdatedPackage, OutdatedReport, AuditSeverity, AuditFinding, AuditReport, UpgradePreview, CoverageSource, FileCoverage, CoverageReport, CoverageJoinedHotspot, CoverageJoinedReport, } from './types.js';
38
+ export type { ScanResult, FileEntry, DirectoryNode, LanguageBreakdown, LanguageStat, FrameworkResult, DetectedFramework, DependencyReport, DependencyRisk, Issue, IssueLocation, IssueSeverity, Fix, FixResult, FileExplanation, FileInspection, FunctionDetail, ImportInfo, ExportInfo, ArchitectureLayer, AnalysisReport, ReportFormat, FileHotspot, HotspotReport, AuthorShare, BaselineHotspot, HotspotDelta, HotspotDiffSummary, McpToolDefinition, McpPromptDefinition, McpResourceDefinition, ProjscanConfig, LoadedConfig, SemverDrift, OutdatedPackage, OutdatedReport, AuditSeverity, AuditFinding, AuditReport, UpgradePreview, CoverageSource, FileCoverage, CoverageReport, CoverageJoinedHotspot, CoverageJoinedReport, ReviewReport, ReviewFile, ReviewCycle, ReviewFunction, ReviewDependencyChange, FixSuggestion, IssueExplanation, ImportPolicyRule, } from './types.js';
package/dist/index.js CHANGED
@@ -27,6 +27,9 @@ export { walkFiles } from './utils/fileWalker.js';
27
27
  export { loadConfig, applyConfigToIssues } from './utils/config.js';
28
28
  export { getChangedFiles } from './utils/changedFiles.js';
29
29
  export { issuesToSarif } from './reporters/sarifReporter.js';
30
+ export { computeReview } from './core/review.js';
31
+ export { suggestFixForIssue, previewSuggestionForIssue, syntheticIssue, findIssue } from './core/fixSuggest.js';
32
+ export { explainIssue } from './core/explainIssue.js';
30
33
  export { createMcpServer, runMcpServer } from './mcp/server.js';
31
34
  export { getToolDefinitions } from './mcp/tools.js';
32
35
  export { getPromptDefinitions } from './mcp/prompts.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvG,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,SAAS,EACT,SAAS,EACT,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACzG,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EACL,gBAAgB,EAChB,MAAM,EACN,QAAQ,EACR,WAAW,EACX,cAAc,GACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,mBAAmB,EACnB,SAAS,EACT,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,aAAa,GACd,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,oBAAoB,GACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,KAAK,IAAI,WAAW,EAAE,OAAO,IAAI,aAAa,EAAE,KAAK,IAAI,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACzG,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -3,18 +3,23 @@ import { paginate, listChecksum, readPageParams } from '../pagination.js';
3
3
  import { emitProgress } from '../progress.js';
4
4
  export const auditTool = {
5
5
  name: 'projscan_audit',
6
- description: 'Run `npm audit` and return a normalized summary of vulnerabilities (critical / high / moderate / low / info). Requires package-lock.json. Supports cursor pagination on the findings array.',
6
+ description: 'Run `npm audit` and return a normalized summary of vulnerabilities (critical / high / moderate / low / info). Requires package-lock.json. Supports cursor pagination on the findings array. Pass `package` in a monorepo to scope findings to direct deps of one workspace package.',
7
7
  inputSchema: {
8
8
  type: 'object',
9
9
  properties: {
10
10
  cursor: { type: 'string', description: 'Opaque cursor from a previous response.' },
11
11
  page_size: { type: 'number', description: 'Items per page (default 50).' },
12
12
  max_tokens: { type: 'number', description: 'Cap response size.' },
13
+ package: {
14
+ type: 'string',
15
+ description: 'Optional. Workspace package name to scope audit findings to one workspace only.',
16
+ },
13
17
  },
14
18
  },
15
19
  handler: async (args, rootPath) => {
16
20
  emitProgress(0, 2, 'running npm audit');
17
- const report = await runAudit(rootPath);
21
+ const filter = typeof args.package === 'string' && args.package.length > 0 ? args.package : undefined;
22
+ const report = await runAudit(rootPath, filter ? { packageFilter: filter } : {});
18
23
  if (!report.available)
19
24
  return report;
20
25
  emitProgress(1, 2, 'normalizing findings');
@@ -1 +1 @@
1
- {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../../src/mcp/tools/audit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,MAAM,CAAC,MAAM,SAAS,GAAY;IAChC,IAAI,EAAE,gBAAgB;IACtB,WAAW,EACT,6LAA6L;IAC/L,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yCAAyC,EAAE;YAClF,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,8BAA8B,EAAE;YAC1E,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oBAAoB,EAAE;SAClE;KACF;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QAChC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,mBAAmB,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,SAAS;YAAE,OAAO,MAAM,CAAC;QACrC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC5F,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QAC3B,OAAO;YACL,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,QAAQ,EAAE,IAAI,CAAC,KAAK;YACpB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC;IACJ,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../../../src/mcp/tools/audit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,MAAM,CAAC,MAAM,SAAS,GAAY;IAChC,IAAI,EAAE,gBAAgB;IACtB,WAAW,EACT,qRAAqR;IACvR,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yCAAyC,EAAE;YAClF,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,8BAA8B,EAAE;YAC1E,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oBAAoB,EAAE;YACjE,OAAO,EAAE;gBACP,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,iFAAiF;aAC/F;SACF;KACF;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QAChC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,mBAAmB,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QACtG,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACjF,IAAI,CAAC,MAAM,CAAC,SAAS;YAAE,OAAO,MAAM,CAAC;QACrC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC5F,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QAC3B,OAAO;YACL,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,QAAQ,EAAE,IAAI,CAAC,KAAK;YACpB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -1,15 +1,21 @@
1
1
  import { analyzeDependencies } from '../../core/dependencyAnalyzer.js';
2
2
  export const dependenciesTool = {
3
3
  name: 'projscan_dependencies',
4
- description: 'Analyze package.json dependencies and return counts and risks (deprecated packages, wildcard versions, etc.).',
4
+ description: 'Analyze package.json dependencies and return counts and risks (deprecated packages, wildcard versions, etc.). In a monorepo, returns aggregated totals plus a `byWorkspace` breakdown; pass `package` to scope to one workspace.',
5
5
  inputSchema: {
6
6
  type: 'object',
7
- properties: {},
7
+ properties: {
8
+ package: {
9
+ type: 'string',
10
+ description: 'Optional. Workspace package name to scope analysis to one workspace only.',
11
+ },
12
+ },
8
13
  },
9
- handler: async (_args, rootPath) => {
10
- const report = await analyzeDependencies(rootPath);
14
+ handler: async (args, rootPath) => {
15
+ const filter = typeof args.package === 'string' && args.package.length > 0 ? args.package : undefined;
16
+ const report = await analyzeDependencies(rootPath, { packageFilter: filter });
11
17
  if (!report)
12
- return { available: false, reason: 'No package.json found' };
18
+ return { available: false, reason: filter ? `Workspace not found: ${filter}` : 'No package.json found' };
13
19
  return { available: true, ...report };
14
20
  },
15
21
  };
@@ -1 +1 @@
1
- {"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../../../src/mcp/tools/dependencies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAGvE,MAAM,CAAC,MAAM,gBAAgB,GAAY;IACvC,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EAAE,+GAA+G;IAC5H,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,EAAE;KACf;IACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;QACjC,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAC;QAC1E,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC;IACxC,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../../../src/mcp/tools/dependencies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAGvE,MAAM,CAAC,MAAM,gBAAgB,GAAY;IACvC,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EACT,kOAAkO;IACpO,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,OAAO,EAAE;gBACP,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,2EAA2E;aACzF;SACF;KACF;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QAChC,MAAM,MAAM,GAAG,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QACtG,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC;QAC9E,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,wBAAwB,MAAM,EAAE,CAAC,CAAC,CAAC,uBAAuB,EAAE,CAAC;QACtH,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC;IACxC,CAAC;CACF,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { McpTool } from './_shared.js';
2
+ export declare const explainIssueTool: McpTool;
@@ -0,0 +1,30 @@
1
+ import { scanRepository } from '../../core/repositoryScanner.js';
2
+ import { collectIssues } from '../../core/issueEngine.js';
3
+ import { explainIssue } from '../../core/explainIssue.js';
4
+ export const explainIssueTool = {
5
+ name: 'projscan_explain_issue',
6
+ description: 'Deep-dive on a single open issue: severity, surrounding code excerpt, other issues touching the same file, similar fixes from git log (commit messages that mention this rule), and the structured fix-action prompt. Use when an agent needs more context than projscan_doctor gives - typically before applying a fix.',
7
+ inputSchema: {
8
+ type: 'object',
9
+ properties: {
10
+ issue_id: {
11
+ type: 'string',
12
+ description: 'Issue id from a previous projscan_doctor / projscan_analyze response.',
13
+ },
14
+ },
15
+ required: ['issue_id'],
16
+ },
17
+ handler: async (args, rootPath) => {
18
+ const issueId = typeof args.issue_id === 'string' ? args.issue_id : '';
19
+ if (!issueId)
20
+ throw new Error('issue_id is required');
21
+ const scan = await scanRepository(rootPath);
22
+ const issues = await collectIssues(rootPath, scan.files);
23
+ const explanation = await explainIssue(rootPath, issues, issueId);
24
+ if (!explanation) {
25
+ return { matched: false, reason: `No open issue with id "${issueId}" in current doctor run.` };
26
+ }
27
+ return { matched: true, explanation };
28
+ },
29
+ };
30
+ //# sourceMappingURL=explainIssue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explainIssue.js","sourceRoot":"","sources":["../../../src/mcp/tools/explainIssue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG1D,MAAM,CAAC,MAAM,gBAAgB,GAAY;IACvC,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EACT,0TAA0T;IAC5T,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,uEAAuE;aACrF;SACF;QACD,QAAQ,EAAE,CAAC,UAAU,CAAC;KACvB;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;QAChC,MAAM,OAAO,GAAG,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACzD,MAAM,WAAW,GAAG,MAAM,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QAClE,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,0BAA0B,OAAO,0BAA0B,EAAE,CAAC;QACjG,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IACxC,CAAC;CACF,CAAC"}