projscan 2.2.0 → 2.8.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 +51 -21
- package/dist/cli/commands/agentBrief.d.ts +1 -0
- package/dist/cli/commands/agentBrief.js +68 -0
- package/dist/cli/commands/agentBrief.js.map +1 -0
- package/dist/cli/commands/bugHunt.d.ts +1 -0
- package/dist/cli/commands/bugHunt.js +59 -0
- package/dist/cli/commands/bugHunt.js.map +1 -0
- package/dist/cli/commands/evidencePack.d.ts +1 -0
- package/dist/cli/commands/evidencePack.js +70 -0
- package/dist/cli/commands/evidencePack.js.map +1 -0
- package/dist/cli/commands/qualityScorecard.d.ts +1 -0
- package/dist/cli/commands/qualityScorecard.js +61 -0
- package/dist/cli/commands/qualityScorecard.js.map +1 -0
- package/dist/cli/commands/regressionPlan.d.ts +1 -0
- package/dist/cli/commands/regressionPlan.js +77 -0
- package/dist/cli/commands/regressionPlan.js.map +1 -0
- package/dist/cli/commands/releaseTrain.d.ts +1 -0
- package/dist/cli/commands/releaseTrain.js +58 -0
- package/dist/cli/commands/releaseTrain.js.map +1 -0
- package/dist/cli/commands/workplan.d.ts +1 -0
- package/dist/cli/commands/workplan.js +136 -0
- package/dist/cli/commands/workplan.js.map +1 -0
- package/dist/cli/index.js +14 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/agentBrief.d.ts +6 -0
- package/dist/core/agentBrief.js +192 -0
- package/dist/core/agentBrief.js.map +1 -0
- package/dist/core/bugHunt.d.ts +6 -0
- package/dist/core/bugHunt.js +278 -0
- package/dist/core/bugHunt.js.map +1 -0
- package/dist/core/qualityScorecard.d.ts +6 -0
- package/dist/core/qualityScorecard.js +220 -0
- package/dist/core/qualityScorecard.js.map +1 -0
- package/dist/core/regressionPlan.d.ts +7 -0
- package/dist/core/regressionPlan.js +226 -0
- package/dist/core/regressionPlan.js.map +1 -0
- package/dist/core/releaseEvidence.d.ts +7 -0
- package/dist/core/releaseEvidence.js +174 -0
- package/dist/core/releaseEvidence.js.map +1 -0
- package/dist/core/releaseTrain.d.ts +5 -0
- package/dist/core/releaseTrain.js +348 -0
- package/dist/core/releaseTrain.js.map +1 -0
- package/dist/core/workplan.d.ts +12 -0
- package/dist/core/workplan.js +440 -0
- package/dist/core/workplan.js.map +1 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/tools/agentBrief.d.ts +2 -0
- package/dist/mcp/tools/agentBrief.js +39 -0
- package/dist/mcp/tools/agentBrief.js.map +1 -0
- package/dist/mcp/tools/bugHunt.d.ts +2 -0
- package/dist/mcp/tools/bugHunt.js +31 -0
- package/dist/mcp/tools/bugHunt.js.map +1 -0
- package/dist/mcp/tools/evidencePack.d.ts +2 -0
- package/dist/mcp/tools/evidencePack.js +39 -0
- package/dist/mcp/tools/evidencePack.js.map +1 -0
- package/dist/mcp/tools/qualityScorecard.d.ts +2 -0
- package/dist/mcp/tools/qualityScorecard.js +26 -0
- package/dist/mcp/tools/qualityScorecard.js.map +1 -0
- package/dist/mcp/tools/regressionPlan.d.ts +2 -0
- package/dist/mcp/tools/regressionPlan.js +47 -0
- package/dist/mcp/tools/regressionPlan.js.map +1 -0
- package/dist/mcp/tools/releaseTrain.d.ts +2 -0
- package/dist/mcp/tools/releaseTrain.js +27 -0
- package/dist/mcp/tools/releaseTrain.js.map +1 -0
- package/dist/mcp/tools/workplan.d.ts +2 -0
- package/dist/mcp/tools/workplan.js +70 -0
- package/dist/mcp/tools/workplan.js.map +1 -0
- package/dist/mcp/tools.js +14 -0
- package/dist/mcp/tools.js.map +1 -1
- package/dist/projscan-sbom.cdx.json +6 -6
- package/dist/tool-manifest.json +196 -3
- package/dist/types.d.ts +240 -0
- package/dist/utils/formatSupport.d.ts +8 -0
- package/dist/utils/formatSupport.js +8 -0
- package/dist/utils/formatSupport.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { analyzeHotspots } from './hotspotAnalyzer.js';
|
|
2
|
+
import { collectIssues } from './issueEngine.js';
|
|
3
|
+
import { computePreflight } from './preflight.js';
|
|
4
|
+
import { scanRepository } from './repositoryScanner.js';
|
|
5
|
+
import { buildRiskNow } from './sessionResources.js';
|
|
6
|
+
import { loadConfig, applyConfigToIssues } from '../utils/config.js';
|
|
7
|
+
import { calculateScore } from '../utils/scoreCalculator.js';
|
|
8
|
+
const DEFAULT_MAX_FINDINGS = 10;
|
|
9
|
+
export async function computeBugHunt(rootPath, options = {}) {
|
|
10
|
+
const maxFindings = normalizeMax(options.maxFindings);
|
|
11
|
+
const configResult = await loadConfig(rootPath).catch(() => ({ config: { ignore: [] } }));
|
|
12
|
+
const scan = await scanRepository(rootPath, { ignore: configResult.config.ignore });
|
|
13
|
+
const issues = applyConfigToIssues(await collectIssues(rootPath, scan.files), configResult.config);
|
|
14
|
+
const health = calculateScore(issues);
|
|
15
|
+
const preflight = await computePreflight(rootPath, { mode: 'before_commit' });
|
|
16
|
+
const actionablePreflightReasons = preflight.reasons.filter(isActionablePreflightReason);
|
|
17
|
+
const riskNow = await safeRiskNow(rootPath);
|
|
18
|
+
const hotspots = await analyzeHotspots(rootPath, scan.files, issues, {
|
|
19
|
+
limit: maxFindings,
|
|
20
|
+
since: options.since,
|
|
21
|
+
});
|
|
22
|
+
const findings = rankFindings([
|
|
23
|
+
...issues.map(issueToFinding),
|
|
24
|
+
...actionablePreflightReasons.map(preflightReasonToFinding),
|
|
25
|
+
...riskNow.conflicts.map(conflictToFinding),
|
|
26
|
+
...(hotspots.available ? hotspots.hotspots.map(hotspotToFinding) : []),
|
|
27
|
+
]);
|
|
28
|
+
const fixQueue = findings.length > 0
|
|
29
|
+
? findings.slice(0, maxFindings)
|
|
30
|
+
: [cleanVerificationFinding()];
|
|
31
|
+
const verdict = bugHuntVerdict(issues, findings, actionablePreflightReasons);
|
|
32
|
+
return {
|
|
33
|
+
schemaVersion: 1,
|
|
34
|
+
verdict,
|
|
35
|
+
summary: summarize(verdict, fixQueue.length),
|
|
36
|
+
health,
|
|
37
|
+
evidence: {
|
|
38
|
+
issueCounts: {
|
|
39
|
+
errors: health.errors,
|
|
40
|
+
warnings: health.warnings,
|
|
41
|
+
infos: health.infos,
|
|
42
|
+
},
|
|
43
|
+
hotspotCount: hotspots.available ? hotspots.hotspots.length : 0,
|
|
44
|
+
preflightVerdict: preflight.verdict,
|
|
45
|
+
touchedFiles: riskNow.touchedFiles,
|
|
46
|
+
conflicts: riskNow.conflicts.length,
|
|
47
|
+
},
|
|
48
|
+
topSuspects: fixQueue,
|
|
49
|
+
fixQueue,
|
|
50
|
+
verificationMatrix: buildVerificationMatrix(verdict),
|
|
51
|
+
...(findings.length > fixQueue.length ? { truncated: true } : {}),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function issueToFinding(issue) {
|
|
55
|
+
const files = filesFromIssue(issue);
|
|
56
|
+
return {
|
|
57
|
+
id: `bh-issue-${issue.id}`,
|
|
58
|
+
priority: severityPriority(issue.severity),
|
|
59
|
+
source: 'doctor',
|
|
60
|
+
title: issue.title,
|
|
61
|
+
why: issue.description,
|
|
62
|
+
files,
|
|
63
|
+
evidence: [
|
|
64
|
+
{
|
|
65
|
+
source: 'doctor',
|
|
66
|
+
severity: issue.severity,
|
|
67
|
+
issueId: issue.id,
|
|
68
|
+
message: issue.title,
|
|
69
|
+
...(files[0] ? { file: files[0] } : {}),
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
suggestedTools: issue.fixAvailable
|
|
73
|
+
? ['projscan_explain_issue', 'projscan_fix_suggest', 'projscan_apply_fix']
|
|
74
|
+
: ['projscan_explain_issue', 'projscan_doctor'],
|
|
75
|
+
verification: {
|
|
76
|
+
commands: ['projscan doctor --format json', 'npm test'],
|
|
77
|
+
expected: `Issue ${issue.id} no longer appears in projscan doctor and focused tests pass.`,
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function preflightReasonToFinding(reason, index) {
|
|
82
|
+
return {
|
|
83
|
+
id: `bh-preflight-${index + 1}`,
|
|
84
|
+
priority: severityPriority(reason.severity),
|
|
85
|
+
source: 'preflight',
|
|
86
|
+
title: `Resolve preflight ${reason.source} signal`,
|
|
87
|
+
why: reason.message,
|
|
88
|
+
files: reason.file ? [reason.file] : [],
|
|
89
|
+
evidence: [
|
|
90
|
+
{
|
|
91
|
+
source: reason.source,
|
|
92
|
+
severity: reason.severity,
|
|
93
|
+
message: reason.message,
|
|
94
|
+
...(reason.file ? { file: reason.file } : {}),
|
|
95
|
+
...(reason.issueId ? { issueId: reason.issueId } : {}),
|
|
96
|
+
...(reason.tool ? { tool: reason.tool } : {}),
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
suggestedTools: ['projscan_preflight', reason.tool ?? 'projscan_doctor'],
|
|
100
|
+
verification: {
|
|
101
|
+
commands: ['projscan preflight --mode before_commit --format json', 'projscan doctor --format json'],
|
|
102
|
+
expected: 'The preflight reason is gone or intentionally documented as accepted risk.',
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function conflictToFinding(conflict, index) {
|
|
107
|
+
return {
|
|
108
|
+
id: `bh-session-${index + 1}`,
|
|
109
|
+
priority: conflict.severity === 'error' ? 'p0' : 'p1',
|
|
110
|
+
source: 'session',
|
|
111
|
+
title: 'Resolve active coordination conflict',
|
|
112
|
+
why: conflict.message,
|
|
113
|
+
files: conflict.files,
|
|
114
|
+
evidence: [
|
|
115
|
+
{
|
|
116
|
+
source: 'coordination',
|
|
117
|
+
severity: conflict.severity,
|
|
118
|
+
message: conflict.message,
|
|
119
|
+
...(conflict.files[0] ? { file: conflict.files[0] } : {}),
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
suggestedTools: ['projscan_session', 'projscan_workplan'],
|
|
123
|
+
verification: {
|
|
124
|
+
commands: ['projscan session touched --format json', 'projscan bug-hunt --format json'],
|
|
125
|
+
expected: 'Touched-file overlap is understood and no coordination blocker remains.',
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function hotspotToFinding(hotspot) {
|
|
130
|
+
return {
|
|
131
|
+
id: `bh-hotspot-${slug(hotspot.relativePath)}`,
|
|
132
|
+
priority: hotspot.riskScore >= 70 ? 'p0' : hotspot.riskScore >= 30 ? 'p1' : 'p2',
|
|
133
|
+
source: 'hotspot',
|
|
134
|
+
title: `Inspect risky hotspot ${hotspot.relativePath}`,
|
|
135
|
+
why: hotspot.reasons[0] ?? `Risk score ${Math.round(hotspot.riskScore)} combines churn, complexity, and issue density.`,
|
|
136
|
+
files: [hotspot.relativePath],
|
|
137
|
+
evidence: [
|
|
138
|
+
{
|
|
139
|
+
source: 'hotspots',
|
|
140
|
+
message: `risk score ${Math.round(hotspot.riskScore)}`,
|
|
141
|
+
file: hotspot.relativePath,
|
|
142
|
+
},
|
|
143
|
+
...hotspot.issueIds.slice(0, 3).map((issueId) => ({
|
|
144
|
+
source: 'doctor',
|
|
145
|
+
message: `linked issue ${issueId}`,
|
|
146
|
+
issueId,
|
|
147
|
+
file: hotspot.relativePath,
|
|
148
|
+
})),
|
|
149
|
+
],
|
|
150
|
+
suggestedTools: ['projscan_file', 'projscan_hotspots', 'projscan_impact'],
|
|
151
|
+
verification: {
|
|
152
|
+
commands: [`projscan file ${hotspot.relativePath} --format json`, 'npm test'],
|
|
153
|
+
expected: 'The hotspot has either lower risk, added regression coverage, or an explicit owner for remaining risk.',
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function cleanVerificationFinding() {
|
|
158
|
+
return {
|
|
159
|
+
id: 'bh-verify-clean',
|
|
160
|
+
priority: 'p2',
|
|
161
|
+
source: 'verification',
|
|
162
|
+
title: 'Verify the clean bug-hunt baseline',
|
|
163
|
+
why: 'No immediate doctor, preflight, session, or hotspot findings were found. Preserve that state with repeatable verification.',
|
|
164
|
+
files: [],
|
|
165
|
+
evidence: [{ source: 'verification', message: 'bug hunt found no ranked suspects' }],
|
|
166
|
+
suggestedTools: ['projscan_doctor', 'projscan_preflight', 'projscan_workplan'],
|
|
167
|
+
verification: {
|
|
168
|
+
commands: ['projscan doctor --format json', 'projscan preflight --mode before_commit --format json', 'npm test'],
|
|
169
|
+
expected: 'The clean baseline remains reproducible before handoff.',
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function rankFindings(findings) {
|
|
174
|
+
const seen = new Set();
|
|
175
|
+
return findings
|
|
176
|
+
.filter((finding) => {
|
|
177
|
+
if (seen.has(finding.id))
|
|
178
|
+
return false;
|
|
179
|
+
seen.add(finding.id);
|
|
180
|
+
return true;
|
|
181
|
+
})
|
|
182
|
+
.sort((a, b) => {
|
|
183
|
+
const priority = priorityRank(a.priority) - priorityRank(b.priority);
|
|
184
|
+
if (priority !== 0)
|
|
185
|
+
return priority;
|
|
186
|
+
return sourceRank(a.source) - sourceRank(b.source) || a.id.localeCompare(b.id);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
function buildVerificationMatrix(verdict) {
|
|
190
|
+
return [
|
|
191
|
+
{
|
|
192
|
+
command: 'projscan doctor --format json',
|
|
193
|
+
reason: 'Confirms the issue queue after fixes.',
|
|
194
|
+
expected: 'No unresolved error-level issues and expected warning count is explained.',
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
command: 'projscan preflight --mode before_commit --format json',
|
|
198
|
+
reason: 'Checks whether an agent can safely hand off or commit.',
|
|
199
|
+
expected: verdict === 'block' ? 'Verdict improves from block after p0 fixes.' : 'Verdict is proceed or documented caution.',
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
command: 'npm test',
|
|
203
|
+
reason: 'Keeps the bug hunt tied to repeatable regression coverage.',
|
|
204
|
+
expected: 'Focused tests and the project test suite pass.',
|
|
205
|
+
},
|
|
206
|
+
];
|
|
207
|
+
}
|
|
208
|
+
function bugHuntVerdict(issues, findings, actionablePreflightReasons) {
|
|
209
|
+
if (issues.some((issue) => issue.severity === 'error') ||
|
|
210
|
+
actionablePreflightReasons.some((reason) => reason.severity === 'error')) {
|
|
211
|
+
return 'block';
|
|
212
|
+
}
|
|
213
|
+
if (findings.length > 0 || actionablePreflightReasons.length > 0)
|
|
214
|
+
return 'fix';
|
|
215
|
+
return 'clean';
|
|
216
|
+
}
|
|
217
|
+
function isActionablePreflightReason(reason) {
|
|
218
|
+
if (reason.source === 'review' && reason.message.startsWith('Review unavailable:'))
|
|
219
|
+
return false;
|
|
220
|
+
if ((reason.source === 'review' || reason.source === 'taint') && !reason.file && !reason.issueId) {
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
if (reason.severity === 'error')
|
|
224
|
+
return true;
|
|
225
|
+
return reason.source !== 'git' && reason.source !== 'changed-files';
|
|
226
|
+
}
|
|
227
|
+
async function safeRiskNow(rootPath) {
|
|
228
|
+
try {
|
|
229
|
+
return await buildRiskNow(rootPath);
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
return { touchedFiles: [], conflicts: [] };
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function summarize(verdict, queueLength) {
|
|
236
|
+
if (verdict === 'clean')
|
|
237
|
+
return 'clean: bug hunt found no immediate fix targets; verify the baseline';
|
|
238
|
+
if (verdict === 'block')
|
|
239
|
+
return `block: bug hunt found ${queueLength} high-priority fix target(s)`;
|
|
240
|
+
return `fix: bug hunt found ${queueLength} prioritized fix target(s)`;
|
|
241
|
+
}
|
|
242
|
+
function filesFromIssue(issue) {
|
|
243
|
+
return [...new Set((issue.locations ?? []).map((location) => location.file).filter(Boolean))];
|
|
244
|
+
}
|
|
245
|
+
function severityPriority(severity) {
|
|
246
|
+
if (severity === 'error')
|
|
247
|
+
return 'p0';
|
|
248
|
+
if (severity === 'warning')
|
|
249
|
+
return 'p1';
|
|
250
|
+
return 'p2';
|
|
251
|
+
}
|
|
252
|
+
function priorityRank(priority) {
|
|
253
|
+
if (priority === 'p0')
|
|
254
|
+
return 0;
|
|
255
|
+
if (priority === 'p1')
|
|
256
|
+
return 1;
|
|
257
|
+
return 2;
|
|
258
|
+
}
|
|
259
|
+
function sourceRank(source) {
|
|
260
|
+
if (source === 'doctor')
|
|
261
|
+
return 0;
|
|
262
|
+
if (source === 'preflight')
|
|
263
|
+
return 1;
|
|
264
|
+
if (source === 'session')
|
|
265
|
+
return 2;
|
|
266
|
+
if (source === 'hotspot')
|
|
267
|
+
return 3;
|
|
268
|
+
return 4;
|
|
269
|
+
}
|
|
270
|
+
function normalizeMax(value) {
|
|
271
|
+
if (typeof value !== 'number' || !Number.isFinite(value))
|
|
272
|
+
return DEFAULT_MAX_FINDINGS;
|
|
273
|
+
return Math.max(1, Math.min(25, Math.floor(value)));
|
|
274
|
+
}
|
|
275
|
+
function slug(value) {
|
|
276
|
+
return value.replace(/[^a-zA-Z0-9]+/g, '-').replace(/^-+|-+$/g, '').toLowerCase() || 'root';
|
|
277
|
+
}
|
|
278
|
+
//# sourceMappingURL=bugHunt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bugHunt.js","sourceRoot":"","sources":["../../src/core/bugHunt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { QualityScorecardDimension, QualityScorecardReport, QualityScorecardVerdict } from '../types.js';
|
|
2
|
+
export interface ComputeQualityScorecardOptions {
|
|
3
|
+
maxRisks?: number;
|
|
4
|
+
}
|
|
5
|
+
export declare function computeQualityScorecard(rootPath: string, options?: ComputeQualityScorecardOptions): Promise<QualityScorecardReport>;
|
|
6
|
+
export declare function deriveQualityScorecardVerdict(dimensions: QualityScorecardDimension[], healthScore: number): QualityScorecardVerdict;
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { analyzeHotspots } from './hotspotAnalyzer.js';
|
|
2
|
+
import { collectIssues } from './issueEngine.js';
|
|
3
|
+
import { scanRepository } from './repositoryScanner.js';
|
|
4
|
+
import { buildRiskNow } from './sessionResources.js';
|
|
5
|
+
import { applyConfigToIssues, loadConfig } from '../utils/config.js';
|
|
6
|
+
import { calculateScore } from '../utils/scoreCalculator.js';
|
|
7
|
+
const DEFAULT_MAX_RISKS = 8;
|
|
8
|
+
export async function computeQualityScorecard(rootPath, options = {}) {
|
|
9
|
+
const maxRisks = normalizeMax(options.maxRisks);
|
|
10
|
+
const configResult = await loadConfig(rootPath).catch(() => ({ config: { ignore: [] } }));
|
|
11
|
+
const scan = await scanRepository(rootPath, { ignore: configResult.config.ignore });
|
|
12
|
+
const issues = applyConfigToIssues(await collectIssues(rootPath, scan.files), configResult.config);
|
|
13
|
+
const health = calculateScore(issues);
|
|
14
|
+
const [riskNow, hotspots] = await Promise.all([
|
|
15
|
+
safeRiskNow(rootPath),
|
|
16
|
+
safeHotspots(rootPath, scan.files, issues, maxRisks),
|
|
17
|
+
]);
|
|
18
|
+
const dimensions = buildDimensions(issues, health, hotspots.hotspots, riskNow.conflicts);
|
|
19
|
+
const allRisks = rankRisks([
|
|
20
|
+
...issues.map(issueToRisk),
|
|
21
|
+
...(hotspots.available ? hotspots.hotspots.map(hotspotToRisk) : []),
|
|
22
|
+
...riskNow.conflicts.map(conflictToRisk),
|
|
23
|
+
]);
|
|
24
|
+
const topRisks = allRisks.slice(0, maxRisks);
|
|
25
|
+
const verdict = deriveQualityScorecardVerdict(dimensions, health.score);
|
|
26
|
+
return {
|
|
27
|
+
schemaVersion: 1,
|
|
28
|
+
verdict,
|
|
29
|
+
summary: summarize(verdict, dimensions, health.score),
|
|
30
|
+
health,
|
|
31
|
+
dimensions,
|
|
32
|
+
topRisks: topRisks.length > 0 ? topRisks : [baselineRisk()],
|
|
33
|
+
commands: buildCommands(verdict),
|
|
34
|
+
suggestedNextActions: suggestedActions(topRisks),
|
|
35
|
+
...(allRisks.length > topRisks.length ? { truncated: true } : {}),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
async function safeRiskNow(rootPath) {
|
|
39
|
+
try {
|
|
40
|
+
return await buildRiskNow(rootPath);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return { touchedFiles: [], conflicts: [] };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async function safeHotspots(rootPath, files, issues, limit) {
|
|
47
|
+
try {
|
|
48
|
+
const report = await analyzeHotspots(rootPath, files, issues, { limit });
|
|
49
|
+
return { available: report.available, hotspots: report.hotspots };
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return { available: false, hotspots: [] };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function buildDimensions(issues, health, hotspots, conflicts) {
|
|
56
|
+
const securityIssues = issues.filter((issue) => issue.category === 'security' || issue.category === 'supply-chain');
|
|
57
|
+
const testIssues = issues.filter((issue) => issue.id.includes('test') || issue.category === 'testing');
|
|
58
|
+
const maintainabilityIssues = issues.filter((issue) => !securityIssues.includes(issue) && !testIssues.includes(issue));
|
|
59
|
+
return [
|
|
60
|
+
{
|
|
61
|
+
id: 'health',
|
|
62
|
+
label: 'Project health',
|
|
63
|
+
status: health.errors > 0 ? 'fail' : health.warnings > 0 ? 'watch' : 'pass',
|
|
64
|
+
score: health.score,
|
|
65
|
+
summary: `${health.grade} (${health.score}) with ${health.errors} error(s), ${health.warnings} warning(s), ${health.infos} info item(s)`,
|
|
66
|
+
evidence: [`${issues.length} issue(s)`],
|
|
67
|
+
commands: ['projscan doctor --format json'],
|
|
68
|
+
},
|
|
69
|
+
issueDimension('security', 'Security posture', securityIssues, ['projscan doctor --format json', 'projscan preflight --mode before_edit --format json']),
|
|
70
|
+
issueDimension('tests', 'Test readiness', testIssues, ['projscan doctor --format json', 'npm test']),
|
|
71
|
+
{
|
|
72
|
+
id: 'maintainability',
|
|
73
|
+
label: 'Maintainability',
|
|
74
|
+
status: maintainabilityIssues.some((issue) => issue.severity === 'error') ? 'fail' : hotspots.length > 0 || maintainabilityIssues.length > 0 ? 'watch' : 'pass',
|
|
75
|
+
score: clampScore(100 - maintainabilityIssues.length * 10 - hotspots.filter((hotspot) => hotspot.riskScore >= 70).length * 12),
|
|
76
|
+
summary: `${maintainabilityIssues.length} maintainability issue(s), ${hotspots.length} hotspot(s)`,
|
|
77
|
+
evidence: [
|
|
78
|
+
...maintainabilityIssues.slice(0, 3).map((issue) => issue.title),
|
|
79
|
+
...hotspots.slice(0, 3).map((hotspot) => `${hotspot.relativePath}: risk ${Math.round(hotspot.riskScore)}`),
|
|
80
|
+
],
|
|
81
|
+
commands: ['projscan hotspots --format json', 'projscan quality-scorecard --format json'],
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
id: 'coordination',
|
|
85
|
+
label: 'Coordination',
|
|
86
|
+
status: conflicts.some((conflict) => conflict.severity === 'error') ? 'fail' : conflicts.length > 0 ? 'watch' : 'pass',
|
|
87
|
+
score: clampScore(100 - conflicts.filter((conflict) => conflict.severity === 'error').length * 25 - conflicts.filter((conflict) => conflict.severity === 'warning').length * 10),
|
|
88
|
+
summary: `${conflicts.length} coordination signal(s)`,
|
|
89
|
+
evidence: conflicts.slice(0, 4).map((conflict) => conflict.message),
|
|
90
|
+
commands: ['projscan session touched --format json', 'projscan agent-brief --format json'],
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
function issueDimension(id, label, issues, commands) {
|
|
95
|
+
return {
|
|
96
|
+
id,
|
|
97
|
+
label,
|
|
98
|
+
status: issues.some((issue) => issue.severity === 'error') ? 'fail' : issues.length > 0 ? 'watch' : 'pass',
|
|
99
|
+
score: clampScore(100 - issues.filter((issue) => issue.severity === 'error').length * 25 - issues.filter((issue) => issue.severity === 'warning').length * 12 - issues.filter((issue) => issue.severity === 'info').length * 4),
|
|
100
|
+
summary: issues.length === 0 ? 'No open signals' : `${issues.length} signal(s)`,
|
|
101
|
+
evidence: issues.slice(0, 4).map((issue) => issue.title),
|
|
102
|
+
commands,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function issueToRisk(issue) {
|
|
106
|
+
return {
|
|
107
|
+
id: `qs-issue-${issue.id}`,
|
|
108
|
+
priority: severityPriority(issue.severity),
|
|
109
|
+
title: issue.title,
|
|
110
|
+
files: issueFiles(issue),
|
|
111
|
+
source: 'issue',
|
|
112
|
+
command: 'projscan doctor --format json',
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function hotspotToRisk(hotspot) {
|
|
116
|
+
return {
|
|
117
|
+
id: `qs-hotspot-${slug(hotspot.relativePath)}`,
|
|
118
|
+
priority: hotspot.riskScore >= 70 ? 'p0' : hotspot.riskScore >= 30 ? 'p1' : 'p2',
|
|
119
|
+
title: `Hotspot ${hotspot.relativePath}`,
|
|
120
|
+
files: [hotspot.relativePath],
|
|
121
|
+
source: 'hotspot',
|
|
122
|
+
command: `projscan file ${hotspot.relativePath} --format json`,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function conflictToRisk(conflict, index) {
|
|
126
|
+
return {
|
|
127
|
+
id: `qs-conflict-${index + 1}`,
|
|
128
|
+
priority: conflict.severity === 'error' ? 'p0' : 'p1',
|
|
129
|
+
title: conflict.message,
|
|
130
|
+
files: conflict.files,
|
|
131
|
+
source: 'coordination',
|
|
132
|
+
command: 'projscan session touched --format json',
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function baselineRisk() {
|
|
136
|
+
return {
|
|
137
|
+
id: 'qs-baseline',
|
|
138
|
+
priority: 'p2',
|
|
139
|
+
title: 'Preserve the clean quality baseline',
|
|
140
|
+
files: [],
|
|
141
|
+
source: 'issue',
|
|
142
|
+
command: 'projscan quality-scorecard --format json',
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function rankRisks(risks) {
|
|
146
|
+
const seen = new Set();
|
|
147
|
+
return risks
|
|
148
|
+
.filter((risk) => {
|
|
149
|
+
if (seen.has(risk.id))
|
|
150
|
+
return false;
|
|
151
|
+
seen.add(risk.id);
|
|
152
|
+
return true;
|
|
153
|
+
})
|
|
154
|
+
.sort((a, b) => priorityRank(a.priority) - priorityRank(b.priority) || sourceRank(a.source) - sourceRank(b.source) || a.id.localeCompare(b.id));
|
|
155
|
+
}
|
|
156
|
+
export function deriveQualityScorecardVerdict(dimensions, healthScore) {
|
|
157
|
+
if (dimensions.some((dimension) => dimension.status === 'fail'))
|
|
158
|
+
return 'blocked';
|
|
159
|
+
if (dimensions.some((dimension) => dimension.status === 'watch' && dimension.score < 70))
|
|
160
|
+
return 'needs_attention';
|
|
161
|
+
if (healthScore >= 95 && dimensions.every((dimension) => dimension.status === 'pass'))
|
|
162
|
+
return 'excellent';
|
|
163
|
+
if (healthScore >= 80)
|
|
164
|
+
return 'healthy';
|
|
165
|
+
return 'needs_attention';
|
|
166
|
+
}
|
|
167
|
+
function buildCommands(verdict) {
|
|
168
|
+
const commands = ['projscan quality-scorecard --format json', 'projscan doctor --format json'];
|
|
169
|
+
if (verdict === 'blocked' || verdict === 'needs_attention')
|
|
170
|
+
commands.push('projscan agent-brief --intent bug_hunt --format json');
|
|
171
|
+
commands.push('npm test');
|
|
172
|
+
return [...new Set(commands)];
|
|
173
|
+
}
|
|
174
|
+
function suggestedActions(risks) {
|
|
175
|
+
return risks.slice(0, 8).map((risk) => ({
|
|
176
|
+
label: risk.title,
|
|
177
|
+
command: risk.command,
|
|
178
|
+
}));
|
|
179
|
+
}
|
|
180
|
+
function summarize(verdict, dimensions, score) {
|
|
181
|
+
const failing = dimensions.filter((dimension) => dimension.status === 'fail').length;
|
|
182
|
+
const watching = dimensions.filter((dimension) => dimension.status === 'watch').length;
|
|
183
|
+
return `${verdict}: quality scorecard ${score}/100 with ${failing} failing and ${watching} watch dimension(s)`;
|
|
184
|
+
}
|
|
185
|
+
function issueFiles(issue) {
|
|
186
|
+
return [...new Set((issue.locations ?? []).map((location) => location.file).filter(Boolean))];
|
|
187
|
+
}
|
|
188
|
+
function severityPriority(severity) {
|
|
189
|
+
if (severity === 'error')
|
|
190
|
+
return 'p0';
|
|
191
|
+
if (severity === 'warning')
|
|
192
|
+
return 'p1';
|
|
193
|
+
return 'p2';
|
|
194
|
+
}
|
|
195
|
+
function priorityRank(priority) {
|
|
196
|
+
if (priority === 'p0')
|
|
197
|
+
return 0;
|
|
198
|
+
if (priority === 'p1')
|
|
199
|
+
return 1;
|
|
200
|
+
return 2;
|
|
201
|
+
}
|
|
202
|
+
function sourceRank(source) {
|
|
203
|
+
if (source === 'issue')
|
|
204
|
+
return 0;
|
|
205
|
+
if (source === 'hotspot')
|
|
206
|
+
return 1;
|
|
207
|
+
return 2;
|
|
208
|
+
}
|
|
209
|
+
function clampScore(score) {
|
|
210
|
+
return Math.max(0, Math.min(100, Math.round(score)));
|
|
211
|
+
}
|
|
212
|
+
function normalizeMax(value) {
|
|
213
|
+
if (typeof value !== 'number' || !Number.isFinite(value))
|
|
214
|
+
return DEFAULT_MAX_RISKS;
|
|
215
|
+
return Math.max(1, Math.min(25, Math.floor(value)));
|
|
216
|
+
}
|
|
217
|
+
function slug(value) {
|
|
218
|
+
return value.replace(/[^a-zA-Z0-9]+/g, '-').replace(/^-+|-+$/g, '').toLowerCase() || 'root';
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=qualityScorecard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qualityScorecard.js","sourceRoot":"","sources":["../../src/core/qualityScorecard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RegressionPlanLevel, RegressionPlanReport } from '../types.js';
|
|
2
|
+
export interface ComputeRegressionPlanOptions {
|
|
3
|
+
level?: RegressionPlanLevel;
|
|
4
|
+
lines?: string[];
|
|
5
|
+
maxTargets?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function computeRegressionPlan(rootPath: string, options?: ComputeRegressionPlanOptions): Promise<RegressionPlanReport>;
|