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.
- package/README.md +18 -13
- package/dist/analyzers/crossPackageImportCheck.d.ts +13 -0
- package/dist/analyzers/crossPackageImportCheck.js +136 -0
- package/dist/analyzers/crossPackageImportCheck.js.map +1 -0
- package/dist/analyzers/cycleCheck.d.ts +12 -0
- package/dist/analyzers/cycleCheck.js +65 -0
- package/dist/analyzers/cycleCheck.js.map +1 -0
- package/dist/cli/commands/audit.js +8 -2
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/dependencies.js +4 -3
- package/dist/cli/commands/dependencies.js.map +1 -1
- package/dist/cli/commands/explainIssue.d.ts +1 -0
- package/dist/cli/commands/explainIssue.js +49 -0
- package/dist/cli/commands/explainIssue.js.map +1 -0
- package/dist/cli/commands/fixSuggest.d.ts +1 -0
- package/dist/cli/commands/fixSuggest.js +71 -0
- package/dist/cli/commands/fixSuggest.js.map +1 -0
- package/dist/cli/commands/review.d.ts +1 -0
- package/dist/cli/commands/review.js +66 -0
- package/dist/cli/commands/review.js.map +1 -0
- package/dist/cli/index.js +6 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/ast.d.ts +20 -0
- package/dist/core/ast.js +190 -0
- package/dist/core/ast.js.map +1 -1
- package/dist/core/auditRunner.d.ts +8 -0
- package/dist/core/auditRunner.js +50 -1
- package/dist/core/auditRunner.js.map +1 -1
- package/dist/core/codeGraph.d.ts +7 -1
- package/dist/core/codeGraph.js +2 -0
- package/dist/core/codeGraph.js.map +1 -1
- package/dist/core/dependencyAnalyzer.d.ts +15 -1
- package/dist/core/dependencyAnalyzer.js +115 -18
- package/dist/core/dependencyAnalyzer.js.map +1 -1
- package/dist/core/explainIssue.d.ts +9 -0
- package/dist/core/explainIssue.js +106 -0
- package/dist/core/explainIssue.js.map +1 -0
- package/dist/core/fileInspector.js +12 -0
- package/dist/core/fileInspector.js.map +1 -1
- package/dist/core/fixSuggest.d.ts +41 -0
- package/dist/core/fixSuggest.js +327 -0
- package/dist/core/fixSuggest.js.map +1 -0
- package/dist/core/indexCache.js +5 -1
- package/dist/core/indexCache.js.map +1 -1
- package/dist/core/issueEngine.js +18 -0
- package/dist/core/issueEngine.js.map +1 -1
- package/dist/core/languages/goAdapter.js +5 -0
- package/dist/core/languages/goAdapter.js.map +1 -1
- package/dist/core/languages/goFunctions.d.ts +24 -0
- package/dist/core/languages/goFunctions.js +99 -0
- package/dist/core/languages/goFunctions.js.map +1 -0
- package/dist/core/languages/javaAdapter.js +5 -0
- package/dist/core/languages/javaAdapter.js.map +1 -1
- package/dist/core/languages/javaFunctions.d.ts +22 -0
- package/dist/core/languages/javaFunctions.js +87 -0
- package/dist/core/languages/javaFunctions.js.map +1 -0
- package/dist/core/languages/pythonAdapter.js +5 -0
- package/dist/core/languages/pythonAdapter.js.map +1 -1
- package/dist/core/languages/pythonFunctions.d.ts +23 -0
- package/dist/core/languages/pythonFunctions.js +87 -0
- package/dist/core/languages/pythonFunctions.js.map +1 -0
- package/dist/core/languages/rubyAdapter.js +5 -0
- package/dist/core/languages/rubyAdapter.js.map +1 -1
- package/dist/core/languages/rubyFunctions.d.ts +22 -0
- package/dist/core/languages/rubyFunctions.js +91 -0
- package/dist/core/languages/rubyFunctions.js.map +1 -0
- package/dist/core/review.d.ts +21 -0
- package/dist/core/review.js +457 -0
- package/dist/core/review.js.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/tools/audit.js +7 -2
- package/dist/mcp/tools/audit.js.map +1 -1
- package/dist/mcp/tools/dependencies.js +11 -5
- package/dist/mcp/tools/dependencies.js.map +1 -1
- package/dist/mcp/tools/explainIssue.d.ts +2 -0
- package/dist/mcp/tools/explainIssue.js +30 -0
- package/dist/mcp/tools/explainIssue.js.map +1 -0
- package/dist/mcp/tools/file.js +1 -1
- package/dist/mcp/tools/file.js.map +1 -1
- package/dist/mcp/tools/fixSuggest.d.ts +2 -0
- package/dist/mcp/tools/fixSuggest.js +57 -0
- package/dist/mcp/tools/fixSuggest.js.map +1 -0
- package/dist/mcp/tools/hotspots.js +40 -1
- package/dist/mcp/tools/hotspots.js.map +1 -1
- package/dist/mcp/tools/review.d.ts +2 -0
- package/dist/mcp/tools/review.js +54 -0
- package/dist/mcp/tools/review.js.map +1 -0
- package/dist/mcp/tools.js +6 -0
- package/dist/mcp/tools.js.map +1 -1
- package/dist/reporters/consoleReporter.d.ts +9 -1
- package/dist/reporters/consoleReporter.js +177 -0
- package/dist/reporters/consoleReporter.js.map +1 -1
- package/dist/reporters/jsonReporter.d.ts +9 -1
- package/dist/reporters/jsonReporter.js +9 -0
- package/dist/reporters/jsonReporter.js.map +1 -1
- package/dist/reporters/markdownReporter.d.ts +9 -1
- package/dist/reporters/markdownReporter.js +141 -0
- package/dist/reporters/markdownReporter.js.map +1 -1
- package/dist/tool-manifest.json +96 -8
- package/dist/types.d.ts +228 -0
- package/dist/utils/config.js +27 -0
- package/dist/utils/config.js.map +1 -1
- package/package.json +4 -2
package/dist/tool-manifest.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projscan",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"mcpProtocolVersion": "2025-03-26",
|
|
5
|
-
"generatedAt": "2026-04-
|
|
6
|
-
"toolCount":
|
|
5
|
+
"generatedAt": "2026-04-26T14:13:37.446Z",
|
|
6
|
+
"toolCount": 19,
|
|
7
7
|
"tools": [
|
|
8
8
|
{
|
|
9
9
|
"name": "projscan_analyze",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
"name": "projscan_hotspots",
|
|
36
|
-
"description": "Rank files by risk using git churn × AST cyclomatic complexity × open issues. Returns the most dangerous files to touch. Each hotspot includes `cyclomaticComplexity` (null for non-AST languages, where line count is used as fallback). Supports cursor-based pagination: pass the `nextCursor` from a previous response back as `cursor` to fetch the next page.",
|
|
36
|
+
"description": "Rank files by risk using git churn × AST cyclomatic complexity × open issues. Returns the most dangerous files to touch. Each hotspot includes `cyclomaticComplexity` (null for non-AST languages, where line count is used as fallback). Supports cursor-based pagination: pass the `nextCursor` from a previous response back as `cursor` to fetch the next page. Pass `view: \"functions\"` to flatten results into the top-N riskiest individual functions across all hotspots, ranked by per-function CC.",
|
|
37
37
|
"inputSchema": {
|
|
38
38
|
"type": "object",
|
|
39
39
|
"properties": {
|
|
@@ -60,6 +60,14 @@
|
|
|
60
60
|
"package": {
|
|
61
61
|
"type": "string",
|
|
62
62
|
"description": "Optional. Workspace package name (from projscan_workspaces) to scope hotspots to one package only."
|
|
63
|
+
},
|
|
64
|
+
"view": {
|
|
65
|
+
"type": "string",
|
|
66
|
+
"enum": [
|
|
67
|
+
"files",
|
|
68
|
+
"functions"
|
|
69
|
+
],
|
|
70
|
+
"description": "Output shape. \"files\" (default) returns ranked hotspot files. \"functions\" returns the top-N individual functions across all hotspots, sorted by per-function CC desc."
|
|
63
71
|
}
|
|
64
72
|
}
|
|
65
73
|
}
|
|
@@ -82,7 +90,7 @@
|
|
|
82
90
|
},
|
|
83
91
|
{
|
|
84
92
|
"name": "projscan_file",
|
|
85
|
-
"description": "Drill into a single file: purpose, imports, exports, churn/risk/ownership, related health issues, AST cyclomatic complexity,
|
|
93
|
+
"description": "Drill into a single file: purpose, imports, exports, churn/risk/ownership, related health issues, AST cyclomatic complexity, coupling (fan-in / fan-out), and per-function CC ranked by complexity. Use this after projscan_hotspots when deciding how to approach a specific risky file.",
|
|
86
94
|
"inputSchema": {
|
|
87
95
|
"type": "object",
|
|
88
96
|
"properties": {
|
|
@@ -111,10 +119,15 @@
|
|
|
111
119
|
},
|
|
112
120
|
{
|
|
113
121
|
"name": "projscan_dependencies",
|
|
114
|
-
"description": "Analyze package.json dependencies and return counts and risks (deprecated packages, wildcard versions, etc.).",
|
|
122
|
+
"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.",
|
|
115
123
|
"inputSchema": {
|
|
116
124
|
"type": "object",
|
|
117
|
-
"properties": {
|
|
125
|
+
"properties": {
|
|
126
|
+
"package": {
|
|
127
|
+
"type": "string",
|
|
128
|
+
"description": "Optional. Workspace package name to scope analysis to one workspace only."
|
|
129
|
+
}
|
|
130
|
+
}
|
|
118
131
|
}
|
|
119
132
|
},
|
|
120
133
|
{
|
|
@@ -144,7 +157,7 @@
|
|
|
144
157
|
},
|
|
145
158
|
{
|
|
146
159
|
"name": "projscan_audit",
|
|
147
|
-
"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.",
|
|
160
|
+
"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.",
|
|
148
161
|
"inputSchema": {
|
|
149
162
|
"type": "object",
|
|
150
163
|
"properties": {
|
|
@@ -159,6 +172,10 @@
|
|
|
159
172
|
"max_tokens": {
|
|
160
173
|
"type": "number",
|
|
161
174
|
"description": "Cap response size."
|
|
175
|
+
},
|
|
176
|
+
"package": {
|
|
177
|
+
"type": "string",
|
|
178
|
+
"description": "Optional. Workspace package name to scope audit findings to one workspace only."
|
|
162
179
|
}
|
|
163
180
|
}
|
|
164
181
|
}
|
|
@@ -307,6 +324,77 @@
|
|
|
307
324
|
}
|
|
308
325
|
}
|
|
309
326
|
},
|
|
327
|
+
{
|
|
328
|
+
"name": "projscan_review",
|
|
329
|
+
"description": "One-call PR review. Combines projscan_pr_diff + per-changed-file risk score + new/expanded import cycles + risky function additions + dependency changes, plus a verdict (\"ok\" | \"review\" | \"block\") with a one-line summary. Use when an agent is asked \"is this PR safe to merge?\" Defaults: base=origin/main (falls back to main/master/HEAD~1), head=HEAD.",
|
|
330
|
+
"inputSchema": {
|
|
331
|
+
"type": "object",
|
|
332
|
+
"properties": {
|
|
333
|
+
"base": {
|
|
334
|
+
"type": "string",
|
|
335
|
+
"description": "Base ref (branch, tag, sha). Default: origin/main, falling back to main/master/HEAD~1."
|
|
336
|
+
},
|
|
337
|
+
"head": {
|
|
338
|
+
"type": "string",
|
|
339
|
+
"description": "Head ref. Default: HEAD."
|
|
340
|
+
},
|
|
341
|
+
"max_tokens": {
|
|
342
|
+
"type": "number",
|
|
343
|
+
"description": "Cap the response to roughly this many tokens."
|
|
344
|
+
},
|
|
345
|
+
"package": {
|
|
346
|
+
"type": "string",
|
|
347
|
+
"description": "Optional. Workspace package name to scope all sections of the review to a single package."
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
"name": "projscan_fix_suggest",
|
|
354
|
+
"description": "Given an issue id (from projscan_doctor / projscan_analyze) OR a file + rule pair, return a structured action prompt: headline, why it matters, where to change, one-paragraph instruction the agent can execute, optional suggested test. Rule-driven; no LLM inside projscan. Use this to close the diagnose -> fix loop.",
|
|
355
|
+
"inputSchema": {
|
|
356
|
+
"type": "object",
|
|
357
|
+
"properties": {
|
|
358
|
+
"issue_id": {
|
|
359
|
+
"type": "string",
|
|
360
|
+
"description": "Issue id from a previous projscan_doctor / projscan_analyze response."
|
|
361
|
+
},
|
|
362
|
+
"file": {
|
|
363
|
+
"type": "string",
|
|
364
|
+
"description": "File path (repo-relative). Required when no `issue_id` is given - combined with `rule` to synthesize a fix request."
|
|
365
|
+
},
|
|
366
|
+
"rule": {
|
|
367
|
+
"type": "string",
|
|
368
|
+
"description": "Rule / issue-id prefix (e.g. \"unused-dependency\", \"cycle-detected\"). Required when no `issue_id` is given."
|
|
369
|
+
},
|
|
370
|
+
"severity": {
|
|
371
|
+
"type": "string",
|
|
372
|
+
"enum": [
|
|
373
|
+
"info",
|
|
374
|
+
"warning",
|
|
375
|
+
"error"
|
|
376
|
+
],
|
|
377
|
+
"description": "Optional. When synthesizing via file+rule, sets the severity for the suggestion. Default: warning."
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
"name": "projscan_explain_issue",
|
|
384
|
+
"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.",
|
|
385
|
+
"inputSchema": {
|
|
386
|
+
"type": "object",
|
|
387
|
+
"properties": {
|
|
388
|
+
"issue_id": {
|
|
389
|
+
"type": "string",
|
|
390
|
+
"description": "Issue id from a previous projscan_doctor / projscan_analyze response."
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
"required": [
|
|
394
|
+
"issue_id"
|
|
395
|
+
]
|
|
396
|
+
}
|
|
397
|
+
},
|
|
310
398
|
{
|
|
311
399
|
"name": "projscan_search",
|
|
312
400
|
"description": "Ranked search across the project. Lexical (BM25) by default; optional semantic (vector) and hybrid (RRF fusion) modes available when the @xenova/transformers peer dependency is installed. Scope controls what to search: \"auto\"/\"content\" (ranked content matches with excerpts), \"symbols\" (exported names), \"files\" (path substring).",
|
package/dist/types.d.ts
CHANGED
|
@@ -47,11 +47,28 @@ export interface DependencyReport {
|
|
|
47
47
|
dependencies: Record<string, string>;
|
|
48
48
|
devDependencies: Record<string, string>;
|
|
49
49
|
risks: DependencyRisk[];
|
|
50
|
+
/**
|
|
51
|
+
* Per-workspace breakdown when scanning a monorepo (0.13.0+). Absent for
|
|
52
|
+
* single-package repos. The top-level `totalDependencies`,
|
|
53
|
+
* `totalDevDependencies`, `dependencies`, `devDependencies`, and `risks`
|
|
54
|
+
* fields aggregate across all workspaces (root manifest + each package).
|
|
55
|
+
* For per-package detail, read this array.
|
|
56
|
+
*/
|
|
57
|
+
byWorkspace?: Array<{
|
|
58
|
+
workspace: string;
|
|
59
|
+
relativePath: string;
|
|
60
|
+
isRoot: boolean;
|
|
61
|
+
totalDependencies: number;
|
|
62
|
+
totalDevDependencies: number;
|
|
63
|
+
risks: DependencyRisk[];
|
|
64
|
+
}>;
|
|
50
65
|
}
|
|
51
66
|
export interface DependencyRisk {
|
|
52
67
|
name: string;
|
|
53
68
|
reason: string;
|
|
54
69
|
severity: 'low' | 'medium' | 'high';
|
|
70
|
+
/** Workspace package name when found in a monorepo workspace manifest. Absent for the root. */
|
|
71
|
+
workspace?: string;
|
|
55
72
|
}
|
|
56
73
|
export type IssueSeverity = 'info' | 'warning' | 'error';
|
|
57
74
|
export interface IssueLocation {
|
|
@@ -70,6 +87,77 @@ export interface Issue {
|
|
|
70
87
|
fixAvailable: boolean;
|
|
71
88
|
fixId?: string;
|
|
72
89
|
locations?: IssueLocation[];
|
|
90
|
+
/**
|
|
91
|
+
* One-line hint shown inline in projscan_doctor output (0.14.0+). Points
|
|
92
|
+
* at the fix-suggest pipeline. Absent when no template matches the issue.
|
|
93
|
+
*/
|
|
94
|
+
suggestedAction?: {
|
|
95
|
+
summary: string;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Structured action prompt the agent can paste into its plan. Returned by
|
|
100
|
+
* projscan_fix_suggest. projscan does not run an LLM - this is rule-driven
|
|
101
|
+
* guidance with the issue, the location, and a one-paragraph instruction
|
|
102
|
+
* the agent (LLM) is expected to act on.
|
|
103
|
+
*/
|
|
104
|
+
export interface FixSuggestion {
|
|
105
|
+
/** Echoes the input issue id when matched. */
|
|
106
|
+
issueId: string;
|
|
107
|
+
/** Severity level passed through from the source issue. */
|
|
108
|
+
severity: IssueSeverity;
|
|
109
|
+
/** Issue category passed through. */
|
|
110
|
+
category: string;
|
|
111
|
+
/** One-line "what is wrong". */
|
|
112
|
+
headline: string;
|
|
113
|
+
/** 2-4 sentences of why this matters. Severity-anchored. */
|
|
114
|
+
why: string;
|
|
115
|
+
/** Affected locations (mirrors Issue.locations when known). */
|
|
116
|
+
where: IssueLocation[];
|
|
117
|
+
/** One-paragraph instruction for the driving agent. */
|
|
118
|
+
instruction: string;
|
|
119
|
+
/** Optional "verify the fix by..." note. */
|
|
120
|
+
suggestedTest?: string;
|
|
121
|
+
/** Optional related files (importers, peer rules) for context. */
|
|
122
|
+
relatedFiles?: string[];
|
|
123
|
+
/** Optional documentation links. */
|
|
124
|
+
references?: string[];
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Markdown-rendered deep dive for a single issue. Returned by
|
|
128
|
+
* projscan_explain_issue. Includes the surrounding code excerpt and any
|
|
129
|
+
* git-log evidence of similar fixes already merged in this repo.
|
|
130
|
+
*/
|
|
131
|
+
export interface IssueExplanation {
|
|
132
|
+
issueId: string;
|
|
133
|
+
title: string;
|
|
134
|
+
severity: IssueSeverity;
|
|
135
|
+
category: string;
|
|
136
|
+
headline: string;
|
|
137
|
+
/** Source-code excerpt around the primary location. Empty when no location. */
|
|
138
|
+
excerpt: {
|
|
139
|
+
file: string;
|
|
140
|
+
startLine: number;
|
|
141
|
+
endLine: number;
|
|
142
|
+
lines: string[];
|
|
143
|
+
} | null;
|
|
144
|
+
/** Other open issues touching the same file (id + title pairs). */
|
|
145
|
+
relatedIssues: Array<{
|
|
146
|
+
id: string;
|
|
147
|
+
title: string;
|
|
148
|
+
}>;
|
|
149
|
+
/**
|
|
150
|
+
* Git log references where this issue id (or its rule prefix) appears in a
|
|
151
|
+
* commit message - hints at how teammates have addressed it before.
|
|
152
|
+
* Empty when none found or git history unavailable.
|
|
153
|
+
*/
|
|
154
|
+
similarFixes: Array<{
|
|
155
|
+
sha: string;
|
|
156
|
+
subject: string;
|
|
157
|
+
date: string;
|
|
158
|
+
}>;
|
|
159
|
+
/** The full FixSuggestion if a template matched; null otherwise. */
|
|
160
|
+
fix: FixSuggestion | null;
|
|
73
161
|
}
|
|
74
162
|
export interface Fix {
|
|
75
163
|
id: string;
|
|
@@ -253,6 +341,29 @@ export interface ProjscanConfig {
|
|
|
253
341
|
ignore?: string[];
|
|
254
342
|
disableRules?: string[];
|
|
255
343
|
severityOverrides?: Record<string, IssueSeverity>;
|
|
344
|
+
/**
|
|
345
|
+
* Monorepo-specific configuration (0.14.0+). Currently scopes the
|
|
346
|
+
* cross-package import policy: each entry says "package P may only import
|
|
347
|
+
* from these listed packages, or specifically may NOT import from these
|
|
348
|
+
* listed packages." Edges that violate become `cross-package-violation-*`
|
|
349
|
+
* issues in projscan_doctor.
|
|
350
|
+
*/
|
|
351
|
+
monorepo?: {
|
|
352
|
+
importPolicy?: ImportPolicyRule[];
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* One cross-package import rule. `from` is the package name (matches
|
|
357
|
+
* WorkspacePackage.name). Exactly one of `allow` / `deny` is required. Both
|
|
358
|
+
* lists are package-name globs - a leading `!` negates a single entry, and a
|
|
359
|
+
* single `*` is the wildcard. When both `allow` and `deny` are set, allow
|
|
360
|
+
* is checked first and a hit short-circuits as ALLOWED; otherwise deny is
|
|
361
|
+
* checked.
|
|
362
|
+
*/
|
|
363
|
+
export interface ImportPolicyRule {
|
|
364
|
+
from: string;
|
|
365
|
+
allow?: string[];
|
|
366
|
+
deny?: string[];
|
|
256
367
|
}
|
|
257
368
|
export interface LoadedConfig {
|
|
258
369
|
config: ProjscanConfig;
|
|
@@ -391,6 +502,105 @@ export interface PrDiffReport {
|
|
|
391
502
|
filesModified: FileAstDiff[];
|
|
392
503
|
totalFilesChanged: number;
|
|
393
504
|
}
|
|
505
|
+
/**
|
|
506
|
+
* One changed file enriched with risk signals. The agent calling
|
|
507
|
+
* projscan_review uses these to decide which files need careful review.
|
|
508
|
+
*/
|
|
509
|
+
export interface ReviewFile {
|
|
510
|
+
relativePath: string;
|
|
511
|
+
status: 'added' | 'removed' | 'modified';
|
|
512
|
+
/** Hotspot risk score for the head version. null when file isn't in the hotspot scope. */
|
|
513
|
+
riskScore: number | null;
|
|
514
|
+
/** Cyclomatic complexity at head. null when no AST adapter parsed it. */
|
|
515
|
+
cyclomaticComplexity: number | null;
|
|
516
|
+
/** Delta from the structural diff (mirrors FileAstDiff.cyclomaticDelta). null when file was added/removed. */
|
|
517
|
+
cyclomaticDelta: number | null;
|
|
518
|
+
/** Number of exports added in this PR. */
|
|
519
|
+
exportsAdded: number;
|
|
520
|
+
/** Number of exports removed in this PR. */
|
|
521
|
+
exportsRemoved: number;
|
|
522
|
+
/** Number of imports added. */
|
|
523
|
+
importsAdded: number;
|
|
524
|
+
/** Number of imports removed. */
|
|
525
|
+
importsRemoved: number;
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* A circular import that exists at head and either didn't exist at base or
|
|
529
|
+
* grew. Surfaced separately from the file list so reviewers see at-a-glance
|
|
530
|
+
* whether the PR introduces new architectural debt.
|
|
531
|
+
*/
|
|
532
|
+
export interface ReviewCycle {
|
|
533
|
+
files: string[];
|
|
534
|
+
size: number;
|
|
535
|
+
/**
|
|
536
|
+
* 'new' = no overlap with any base cycle; 'expanded' = at least one new
|
|
537
|
+
* file added to an existing cycle.
|
|
538
|
+
*/
|
|
539
|
+
classification: 'new' | 'expanded';
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* A function whose CC newly crossed a worry threshold (>= 10) at head, or
|
|
543
|
+
* was added with high CC, or jumped by 5+ since base.
|
|
544
|
+
*/
|
|
545
|
+
export interface ReviewFunction {
|
|
546
|
+
file: string;
|
|
547
|
+
name: string;
|
|
548
|
+
line: number;
|
|
549
|
+
endLine: number;
|
|
550
|
+
cyclomaticComplexity: number;
|
|
551
|
+
/** CC at base. null when the function did not exist at base. */
|
|
552
|
+
baseCc: number | null;
|
|
553
|
+
/** Why this function shows up. */
|
|
554
|
+
reason: 'added' | 'jumped' | 'crossed-threshold';
|
|
555
|
+
}
|
|
556
|
+
/** Workspace-package-scoped dependency change. Aggregates root + workspaces. */
|
|
557
|
+
export interface ReviewDependencyChange {
|
|
558
|
+
/** Workspace name; '' for the root manifest. */
|
|
559
|
+
workspace: string;
|
|
560
|
+
manifestFile: string;
|
|
561
|
+
added: Array<{
|
|
562
|
+
name: string;
|
|
563
|
+
version: string;
|
|
564
|
+
kind: 'dep' | 'dev';
|
|
565
|
+
}>;
|
|
566
|
+
removed: Array<{
|
|
567
|
+
name: string;
|
|
568
|
+
version: string;
|
|
569
|
+
kind: 'dep' | 'dev';
|
|
570
|
+
}>;
|
|
571
|
+
bumped: Array<{
|
|
572
|
+
name: string;
|
|
573
|
+
from: string;
|
|
574
|
+
to: string;
|
|
575
|
+
kind: 'dep' | 'dev';
|
|
576
|
+
}>;
|
|
577
|
+
}
|
|
578
|
+
export interface ReviewReport {
|
|
579
|
+
available: boolean;
|
|
580
|
+
reason?: string;
|
|
581
|
+
base: {
|
|
582
|
+
ref: string;
|
|
583
|
+
resolvedSha: string | null;
|
|
584
|
+
};
|
|
585
|
+
head: {
|
|
586
|
+
ref: string;
|
|
587
|
+
resolvedSha: string | null;
|
|
588
|
+
};
|
|
589
|
+
/** The structural diff (same shape as projscan_pr_diff). */
|
|
590
|
+
prDiff: PrDiffReport;
|
|
591
|
+
/** Each changed file annotated with risk + CC + delta. Sorted by risk desc. */
|
|
592
|
+
changedFiles: ReviewFile[];
|
|
593
|
+
/** Cycles introduced or expanded by this PR. Empty when none. */
|
|
594
|
+
newCycles: ReviewCycle[];
|
|
595
|
+
/** Functions that meaningfully grew or were added with high CC. Sorted by CC desc. */
|
|
596
|
+
riskyFunctions: ReviewFunction[];
|
|
597
|
+
/** package.json deltas across root + workspaces. */
|
|
598
|
+
dependencyChanges: ReviewDependencyChange[];
|
|
599
|
+
/** 'ok' = ship it; 'review' = needs careful look; 'block' = strongly suggests rework. */
|
|
600
|
+
verdict: 'ok' | 'review' | 'block';
|
|
601
|
+
/** One-line bullets explaining the verdict. */
|
|
602
|
+
summary: string[];
|
|
603
|
+
}
|
|
394
604
|
export interface FileInspection {
|
|
395
605
|
relativePath: string;
|
|
396
606
|
exists: boolean;
|
|
@@ -411,6 +621,24 @@ export interface FileInspection {
|
|
|
411
621
|
fanOut?: number | null;
|
|
412
622
|
/** Adapter id (e.g. 'javascript', 'python'). Set when the graph was available. */
|
|
413
623
|
language?: string;
|
|
624
|
+
/**
|
|
625
|
+
* Per-function McCabe CC (0.13.0+). Sorted by cyclomaticComplexity desc.
|
|
626
|
+
* Empty array when the file has no functions or the adapter doesn't yet
|
|
627
|
+
* support per-function granularity.
|
|
628
|
+
*/
|
|
629
|
+
functions?: FunctionDetail[];
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Per-function CC entry exposed via projscan_file. Mirrors the internal
|
|
633
|
+
* `FunctionInfo` from `core/ast.ts` but is part of the stable API surface.
|
|
634
|
+
*/
|
|
635
|
+
export interface FunctionDetail {
|
|
636
|
+
name: string;
|
|
637
|
+
/** 1-based start line. */
|
|
638
|
+
line: number;
|
|
639
|
+
/** 1-based end line. */
|
|
640
|
+
endLine: number;
|
|
641
|
+
cyclomaticComplexity: number;
|
|
414
642
|
}
|
|
415
643
|
export interface McpToolDefinition {
|
|
416
644
|
name: string;
|
package/dist/utils/config.js
CHANGED
|
@@ -89,6 +89,33 @@ function normalize(input) {
|
|
|
89
89
|
if (Object.keys(overrides).length)
|
|
90
90
|
out.severityOverrides = overrides;
|
|
91
91
|
}
|
|
92
|
+
if (obj.monorepo && typeof obj.monorepo === 'object') {
|
|
93
|
+
const m = obj.monorepo;
|
|
94
|
+
const monorepo = {};
|
|
95
|
+
if (Array.isArray(m.importPolicy)) {
|
|
96
|
+
const rules = [];
|
|
97
|
+
for (const entry of m.importPolicy) {
|
|
98
|
+
if (!entry || typeof entry !== 'object')
|
|
99
|
+
continue;
|
|
100
|
+
const e = entry;
|
|
101
|
+
if (typeof e.from !== 'string' || !e.from)
|
|
102
|
+
continue;
|
|
103
|
+
const rule = { from: e.from };
|
|
104
|
+
if (Array.isArray(e.allow)) {
|
|
105
|
+
rule.allow = e.allow.filter((v) => typeof v === 'string');
|
|
106
|
+
}
|
|
107
|
+
if (Array.isArray(e.deny)) {
|
|
108
|
+
rule.deny = e.deny.filter((v) => typeof v === 'string');
|
|
109
|
+
}
|
|
110
|
+
if (rule.allow || rule.deny)
|
|
111
|
+
rules.push(rule);
|
|
112
|
+
}
|
|
113
|
+
if (rules.length > 0)
|
|
114
|
+
monorepo.importPolicy = rules;
|
|
115
|
+
}
|
|
116
|
+
if (Object.keys(monorepo).length)
|
|
117
|
+
out.monorepo = monorepo;
|
|
118
|
+
}
|
|
92
119
|
return out;
|
|
93
120
|
}
|
|
94
121
|
/**
|
package/dist/utils/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projscan",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Agent-first code intelligence. MCP server (2025-03-26) with AST parsing for JavaScript, TypeScript, Python, Go, Java, and Ruby; code graph, AST cyclomatic complexity, coupling + cycle detection, structural PR diff, monorepo workspace awareness with per-package outdated, BM25 + optional semantic search, cursor pagination, progress notifications,
|
|
3
|
+
"version": "0.14.0",
|
|
4
|
+
"description": "Agent-first code intelligence. MCP server (2025-03-26) with AST parsing for JavaScript, TypeScript, Python, Go, Java, and Ruby; code graph, file + per-function AST cyclomatic complexity, coupling + cycle detection, structural PR diff, one-call PR review (projscan_review), rule-driven fix suggestions (projscan_fix_suggest, projscan_explain_issue) closing the diagnose-fix loop, monorepo workspace awareness with cross-package import policy + per-package dependencies / outdated / audit, BM25 + optional semantic search, cursor pagination, progress notifications, context-budgeted output, and a stable-surface CI guard. CLI on the side.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
"lint": "eslint src/",
|
|
21
21
|
"format": "prettier --write .",
|
|
22
22
|
"bench": "node scripts/bench.mjs",
|
|
23
|
+
"bench:references": "node scripts/bench-references.mjs",
|
|
24
|
+
"check:stability": "node scripts/check-stability.mjs",
|
|
23
25
|
"prepare": "npm run build"
|
|
24
26
|
},
|
|
25
27
|
"keywords": [
|