@kernlang/review 2.0.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/LICENSE +661 -0
- package/dist/differ.d.ts +11 -0
- package/dist/differ.js +132 -0
- package/dist/differ.js.map +1 -0
- package/dist/external-tools.d.ts +32 -0
- package/dist/external-tools.js +173 -0
- package/dist/external-tools.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +98 -0
- package/dist/index.js.map +1 -0
- package/dist/inferrer.d.ts +15 -0
- package/dist/inferrer.js +502 -0
- package/dist/inferrer.js.map +1 -0
- package/dist/llm-review.d.ts +24 -0
- package/dist/llm-review.js +197 -0
- package/dist/llm-review.js.map +1 -0
- package/dist/quality-rules.d.ts +12 -0
- package/dist/quality-rules.js +28 -0
- package/dist/quality-rules.js.map +1 -0
- package/dist/reporter.d.ts +15 -0
- package/dist/reporter.js +217 -0
- package/dist/reporter.js.map +1 -0
- package/dist/rules/base.d.ts +10 -0
- package/dist/rules/base.js +556 -0
- package/dist/rules/base.js.map +1 -0
- package/dist/rules/express.d.ts +9 -0
- package/dist/rules/express.js +107 -0
- package/dist/rules/express.js.map +1 -0
- package/dist/rules/index.d.ts +16 -0
- package/dist/rules/index.js +38 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/nextjs.d.ts +9 -0
- package/dist/rules/nextjs.js +128 -0
- package/dist/rules/nextjs.js.map +1 -0
- package/dist/rules/react.d.ts +9 -0
- package/dist/rules/react.js +252 -0
- package/dist/rules/react.js.map +1 -0
- package/dist/rules/vue.d.ts +9 -0
- package/dist/rules/vue.js +198 -0
- package/dist/rules/vue.js.map +1 -0
- package/dist/template-detector.d.ts +12 -0
- package/dist/template-detector.js +225 -0
- package/dist/template-detector.js.map +1 -0
- package/dist/types.d.ts +152 -0
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -0
- package/package.json +23 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM Review — structured prompt builder and response parser.
|
|
3
|
+
*
|
|
4
|
+
* Builds a KERN IR prompt with short aliases (N1, N2, ...) for LLM review.
|
|
5
|
+
* Parses strict JSON schema responses, validates nodeIds, rejects unknowns.
|
|
6
|
+
*
|
|
7
|
+
* Phase 4 of the review pipeline.
|
|
8
|
+
*/
|
|
9
|
+
import { createFingerprint } from './types.js';
|
|
10
|
+
// ── Export KERN IR (v1 compat + v2 enhanced) ─────────────────────────────
|
|
11
|
+
/**
|
|
12
|
+
* Export KERN IR with prompt aliases for AI review.
|
|
13
|
+
* v2: Includes nodeId aliases and handler bodies.
|
|
14
|
+
*/
|
|
15
|
+
export function exportKernIR(inferred, templateMatches) {
|
|
16
|
+
const lines = [];
|
|
17
|
+
lines.push('// KERN IR — inferred from TypeScript source');
|
|
18
|
+
lines.push('// Send this to AI for structural review (5x smaller than original TS)');
|
|
19
|
+
lines.push('');
|
|
20
|
+
for (const r of inferred) {
|
|
21
|
+
if (r.node.type === 'import')
|
|
22
|
+
continue; // skip imports for brevity
|
|
23
|
+
lines.push(`// [${r.promptAlias}] L${r.startLine}-${r.endLine} (${r.confidencePct}% confidence)`);
|
|
24
|
+
lines.push(serializeNode(r.node, ''));
|
|
25
|
+
lines.push('');
|
|
26
|
+
}
|
|
27
|
+
for (const t of templateMatches) {
|
|
28
|
+
if (t.suggestedKern) {
|
|
29
|
+
lines.push(`// L${t.startLine}-${t.endLine} — ${t.libraryName} (${t.confidencePct}%)`);
|
|
30
|
+
lines.push(t.suggestedKern);
|
|
31
|
+
lines.push('');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return lines.join('\n');
|
|
35
|
+
}
|
|
36
|
+
// ── LLM Prompt Builder ───────────────────────────────────────────────────
|
|
37
|
+
/**
|
|
38
|
+
* Build a structured prompt with short aliases for LLM code review.
|
|
39
|
+
* Handler bodies are included so the LLM can review actual logic.
|
|
40
|
+
*/
|
|
41
|
+
export function buildLLMPrompt(inferred, templateMatches) {
|
|
42
|
+
const lines = [];
|
|
43
|
+
// Valid aliases list (for the LLM to reference)
|
|
44
|
+
const aliases = inferred
|
|
45
|
+
.filter(r => r.node.type !== 'import')
|
|
46
|
+
.map(r => r.promptAlias);
|
|
47
|
+
lines.push('Review this KERN IR. Return ONLY a JSON array of findings.');
|
|
48
|
+
lines.push(`Schema: [{"nodeAlias":"N3","severity":"warning","category":"structure","message":"...","evidence":"..."}]`);
|
|
49
|
+
lines.push('');
|
|
50
|
+
lines.push(`Valid aliases: ${aliases.join(', ')}`);
|
|
51
|
+
lines.push('Any alias not in this list will be rejected.');
|
|
52
|
+
lines.push('');
|
|
53
|
+
lines.push('Categories: bug, type, pattern, style, structure');
|
|
54
|
+
lines.push('Severities: error, warning, info');
|
|
55
|
+
lines.push('');
|
|
56
|
+
lines.push('KERN IR:');
|
|
57
|
+
for (const r of inferred) {
|
|
58
|
+
if (r.node.type === 'import')
|
|
59
|
+
continue;
|
|
60
|
+
lines.push(`[${r.promptAlias}] ${serializeNodeWithBody(r.node, '')}`);
|
|
61
|
+
}
|
|
62
|
+
for (const t of templateMatches) {
|
|
63
|
+
if (t.suggestedKern) {
|
|
64
|
+
lines.push(`// template: ${t.suggestedKern}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return lines.join('\n');
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Parse strict JSON response from LLM, validate nodeIds, reject unknowns.
|
|
71
|
+
* Returns unified ReviewFinding[] mapped back to TS source spans.
|
|
72
|
+
*/
|
|
73
|
+
export function parseLLMResponse(response, inferred) {
|
|
74
|
+
// Build alias → InferResult lookup
|
|
75
|
+
const aliasMap = new Map();
|
|
76
|
+
for (const r of inferred) {
|
|
77
|
+
aliasMap.set(r.promptAlias, r);
|
|
78
|
+
}
|
|
79
|
+
const validAliases = new Set(aliasMap.keys());
|
|
80
|
+
// Extract JSON array from response (might be wrapped in markdown code blocks)
|
|
81
|
+
let jsonStr = response.trim();
|
|
82
|
+
// Strip markdown code fences
|
|
83
|
+
if (jsonStr.startsWith('```')) {
|
|
84
|
+
jsonStr = jsonStr.replace(/^```(?:json)?\s*\n?/, '').replace(/\n?```\s*$/, '');
|
|
85
|
+
}
|
|
86
|
+
let parsed;
|
|
87
|
+
try {
|
|
88
|
+
parsed = JSON.parse(jsonStr);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return [{
|
|
92
|
+
source: 'llm',
|
|
93
|
+
ruleId: 'parse-error',
|
|
94
|
+
severity: 'error',
|
|
95
|
+
category: 'bug',
|
|
96
|
+
message: `Failed to parse LLM response as JSON: ${jsonStr.substring(0, 100)}...`,
|
|
97
|
+
primarySpan: { file: '', startLine: 0, startCol: 0, endLine: 0, endCol: 0 },
|
|
98
|
+
fingerprint: createFingerprint('parse-error', 0, 0),
|
|
99
|
+
}];
|
|
100
|
+
}
|
|
101
|
+
if (!Array.isArray(parsed)) {
|
|
102
|
+
return [{
|
|
103
|
+
source: 'llm',
|
|
104
|
+
ruleId: 'parse-error',
|
|
105
|
+
severity: 'error',
|
|
106
|
+
category: 'bug',
|
|
107
|
+
message: 'LLM response is not a JSON array',
|
|
108
|
+
primarySpan: { file: '', startLine: 0, startCol: 0, endLine: 0, endCol: 0 },
|
|
109
|
+
fingerprint: createFingerprint('parse-error', 0, 1),
|
|
110
|
+
}];
|
|
111
|
+
}
|
|
112
|
+
const findings = [];
|
|
113
|
+
const validSeverities = new Set(['error', 'warning', 'info']);
|
|
114
|
+
const validCategories = new Set(['bug', 'type', 'pattern', 'style', 'structure']);
|
|
115
|
+
for (const item of parsed) {
|
|
116
|
+
// Validate nodeAlias
|
|
117
|
+
if (!item.nodeAlias || !validAliases.has(item.nodeAlias)) {
|
|
118
|
+
continue; // reject unknown aliases silently
|
|
119
|
+
}
|
|
120
|
+
// Validate severity and category
|
|
121
|
+
if (!validSeverities.has(item.severity))
|
|
122
|
+
continue;
|
|
123
|
+
if (!validCategories.has(item.category))
|
|
124
|
+
continue;
|
|
125
|
+
if (!item.message || typeof item.message !== 'string')
|
|
126
|
+
continue;
|
|
127
|
+
// Sanitize message: strip ANSI escape codes and control characters
|
|
128
|
+
const message = item.message
|
|
129
|
+
.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '') // ANSI escape sequences
|
|
130
|
+
.replace(/\x1b\][^\x07]*\x07/g, '') // OSC sequences (title bar injection)
|
|
131
|
+
.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f]/g, ''); // control chars (keep \t \n \r)
|
|
132
|
+
const node = aliasMap.get(item.nodeAlias);
|
|
133
|
+
const primarySpan = node.sourceSpans[0] || {
|
|
134
|
+
file: '',
|
|
135
|
+
startLine: node.startLine,
|
|
136
|
+
startCol: 1,
|
|
137
|
+
endLine: node.endLine,
|
|
138
|
+
endCol: 1,
|
|
139
|
+
};
|
|
140
|
+
findings.push({
|
|
141
|
+
source: 'llm',
|
|
142
|
+
ruleId: `llm-${item.category}`,
|
|
143
|
+
severity: item.severity,
|
|
144
|
+
category: item.category,
|
|
145
|
+
message,
|
|
146
|
+
primarySpan,
|
|
147
|
+
nodeIds: [node.nodeId],
|
|
148
|
+
confidence: 0.7, // LLM findings get lower confidence
|
|
149
|
+
fingerprint: createFingerprint(`llm-${item.category}`, primarySpan.startLine, primarySpan.startCol),
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
return findings;
|
|
153
|
+
}
|
|
154
|
+
// ── Node Serialization ───────────────────────────────────────────────────
|
|
155
|
+
function serializeNode(node, indent) {
|
|
156
|
+
const parts = [node.type];
|
|
157
|
+
if (node.props) {
|
|
158
|
+
for (const [k, v] of Object.entries(node.props)) {
|
|
159
|
+
if (k === 'code')
|
|
160
|
+
continue; // skip handler bodies for brevity in export mode
|
|
161
|
+
if (typeof v === 'string') {
|
|
162
|
+
parts.push(v.includes(' ') ? `${k}="${v}"` : `${k}=${v}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
let result = indent + parts.join(' ');
|
|
167
|
+
if (node.children) {
|
|
168
|
+
for (const child of node.children) {
|
|
169
|
+
result += '\n' + serializeNode(child, indent + ' ');
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return result;
|
|
173
|
+
}
|
|
174
|
+
function serializeNodeWithBody(node, indent) {
|
|
175
|
+
const parts = [node.type];
|
|
176
|
+
if (node.props) {
|
|
177
|
+
for (const [k, v] of Object.entries(node.props)) {
|
|
178
|
+
if (typeof v === 'string') {
|
|
179
|
+
if (k === 'code') {
|
|
180
|
+
// Include handler bodies in LLM prompt (wrapped in <<<>>>)
|
|
181
|
+
parts.push(`<<<\n${v}\n>>>`);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
parts.push(v.includes(' ') ? `${k}="${v}"` : `${k}=${v}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
let result = indent + parts.join(' ');
|
|
190
|
+
if (node.children) {
|
|
191
|
+
for (const child of node.children) {
|
|
192
|
+
result += '\n' + serializeNodeWithBody(child, indent + ' ');
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return result;
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=llm-review.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-review.js","sourceRoot":"","sources":["../src/llm-review.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quality Rules — delegates to rule layers based on config.target.
|
|
3
|
+
*
|
|
4
|
+
* v2: Thin orchestrator. Actual rules live in ./rules/*.ts
|
|
5
|
+
*/
|
|
6
|
+
import type { SourceFile } from 'ts-morph';
|
|
7
|
+
import type { InferResult, TemplateMatch, ReviewConfig, ReviewFinding } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Run all active quality rules against a source file.
|
|
10
|
+
* Returns unified ReviewFinding[] sorted by severity then line.
|
|
11
|
+
*/
|
|
12
|
+
export declare function runQualityRules(sourceFile: SourceFile, inferred: InferResult[], templateMatches: TemplateMatch[], config?: ReviewConfig): ReviewFinding[];
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quality Rules — delegates to rule layers based on config.target.
|
|
3
|
+
*
|
|
4
|
+
* v2: Thin orchestrator. Actual rules live in ./rules/*.ts
|
|
5
|
+
*/
|
|
6
|
+
import { getActiveRules } from './rules/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* Run all active quality rules against a source file.
|
|
9
|
+
* Returns unified ReviewFinding[] sorted by severity then line.
|
|
10
|
+
*/
|
|
11
|
+
export function runQualityRules(sourceFile, inferred, templateMatches, config) {
|
|
12
|
+
const filePath = sourceFile.getFilePath() || 'input.ts';
|
|
13
|
+
const rules = getActiveRules(config?.target);
|
|
14
|
+
const findings = [];
|
|
15
|
+
for (const rule of rules) {
|
|
16
|
+
findings.push(...rule({ sourceFile, inferred, templateMatches, config, filePath }));
|
|
17
|
+
}
|
|
18
|
+
// Sort by severity (error > warning > info), then by line
|
|
19
|
+
const severityOrder = { error: 0, warning: 1, info: 2 };
|
|
20
|
+
findings.sort((a, b) => {
|
|
21
|
+
const sd = severityOrder[a.severity] - severityOrder[b.severity];
|
|
22
|
+
if (sd !== 0)
|
|
23
|
+
return sd;
|
|
24
|
+
return a.primarySpan.startLine - b.primarySpan.startLine;
|
|
25
|
+
});
|
|
26
|
+
return findings;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=quality-rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality-rules.js","sourceRoot":"","sources":["../src/quality-rules.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,UAAsB,EACtB,QAAuB,EACvB,eAAgC,EAChC,MAAqB;IAErB,MAAM,QAAQ,GAAG,UAAU,CAAC,WAAW,EAAE,IAAI,UAAU,CAAC;IACxD,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE7C,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IACtF,CAAC;IAED,0DAA0D;IAC1D,MAAM,aAAa,GAA2B,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAChF,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACrB,MAAM,EAAE,GAAG,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QACjE,IAAI,EAAE,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACxB,OAAO,CAAC,CAAC,WAAW,CAAC,SAAS,GAAG,CAAC,CAAC,WAAW,CAAC,SAAS,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reporter — formats review reports for CLI output, JSON, and enforcement.
|
|
3
|
+
*
|
|
4
|
+
* v2: Unified multi-source report with source tags [kern] [eslint] [tsc] [llm].
|
|
5
|
+
* Dedup across sources. Fingerprint-based cross-run stability.
|
|
6
|
+
*/
|
|
7
|
+
import type { ReviewReport, ReviewStats, ReviewFinding, InferResult, TemplateMatch, EnforceResult, ReviewConfig } from './types.js';
|
|
8
|
+
export declare function calculateStats(inferred: InferResult[], templateMatches: TemplateMatch[], findings: ReviewFinding[], totalLines: number): ReviewStats;
|
|
9
|
+
/** Deduplicate findings: same line + similar message from different sources → collapse */
|
|
10
|
+
export declare function dedup(findings: ReviewFinding[]): ReviewFinding[];
|
|
11
|
+
export declare function checkEnforcement(report: ReviewReport, config: ReviewConfig): EnforceResult;
|
|
12
|
+
export declare function formatReport(report: ReviewReport): string;
|
|
13
|
+
export declare function formatEnforcement(result: EnforceResult): string;
|
|
14
|
+
export declare function formatReportJSON(report: ReviewReport): string;
|
|
15
|
+
export declare function formatSummary(reports: ReviewReport[]): string;
|
package/dist/reporter.js
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reporter — formats review reports for CLI output, JSON, and enforcement.
|
|
3
|
+
*
|
|
4
|
+
* v2: Unified multi-source report with source tags [kern] [eslint] [tsc] [llm].
|
|
5
|
+
* Dedup across sources. Fingerprint-based cross-run stability.
|
|
6
|
+
*/
|
|
7
|
+
// ── Stats Calculation ────────────────────────────────────────────────────
|
|
8
|
+
export function calculateStats(inferred, templateMatches, findings, totalLines) {
|
|
9
|
+
const coveredLineSet = new Set();
|
|
10
|
+
for (const r of inferred) {
|
|
11
|
+
for (let i = r.startLine; i <= r.endLine; i++) {
|
|
12
|
+
coveredLineSet.add(i);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
// Also count template match coverage (the library code bodies)
|
|
16
|
+
for (const t of templateMatches) {
|
|
17
|
+
if (t.suggestedKern) {
|
|
18
|
+
for (let i = t.startLine; i <= t.endLine; i++) {
|
|
19
|
+
coveredLineSet.add(i);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const coveredLines = coveredLineSet.size;
|
|
24
|
+
const coveragePct = totalLines > 0 ? Math.round((coveredLines / totalLines) * 100) : 0;
|
|
25
|
+
let totalTsTokens = inferred.reduce((sum, r) => sum + r.tsTokens, 0);
|
|
26
|
+
let totalKernTokens = inferred.reduce((sum, r) => sum + r.kernTokens, 0);
|
|
27
|
+
// Add template match token savings
|
|
28
|
+
for (const t of templateMatches) {
|
|
29
|
+
if (t.suggestedKern && t.kernTokens && t.tsTokens) {
|
|
30
|
+
totalTsTokens += t.tsTokens;
|
|
31
|
+
totalKernTokens += t.kernTokens;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const reductionPct = totalTsTokens > 0
|
|
35
|
+
? Math.round((1 - totalKernTokens / totalTsTokens) * 100)
|
|
36
|
+
: 0;
|
|
37
|
+
return {
|
|
38
|
+
totalLines,
|
|
39
|
+
coveredLines,
|
|
40
|
+
coveragePct,
|
|
41
|
+
totalTsTokens,
|
|
42
|
+
totalKernTokens,
|
|
43
|
+
reductionPct,
|
|
44
|
+
constructCount: inferred.length + templateMatches.filter(t => t.suggestedKern).length,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// ── Dedup ────────────────────────────────────────────────────────────────
|
|
48
|
+
/** Deduplicate findings: same line + similar message from different sources → collapse */
|
|
49
|
+
export function dedup(findings) {
|
|
50
|
+
const seen = new Map();
|
|
51
|
+
for (const f of findings) {
|
|
52
|
+
// Dedup key: line + message prefix (collapses same message from different sources,
|
|
53
|
+
// but keeps different findings at the same line separate)
|
|
54
|
+
const key = `${f.primarySpan.startLine}:${f.message.substring(0, 60)}`;
|
|
55
|
+
const existing = seen.get(key);
|
|
56
|
+
if (existing) {
|
|
57
|
+
// Keep the higher-severity finding
|
|
58
|
+
const order = { error: 0, warning: 1, info: 2 };
|
|
59
|
+
if (order[f.severity] < order[existing.severity]) {
|
|
60
|
+
seen.set(key, f);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
seen.set(key, f);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return [...seen.values()];
|
|
68
|
+
}
|
|
69
|
+
// ── Enforcement ──────────────────────────────────────────────────────────
|
|
70
|
+
export function checkEnforcement(report, config) {
|
|
71
|
+
const minCoverage = config.minCoverage ?? 0;
|
|
72
|
+
const actualCoverage = report.stats.coveragePct;
|
|
73
|
+
const templateViolations = [];
|
|
74
|
+
if (config.enforceTemplates) {
|
|
75
|
+
const registeredSet = new Set(config.registeredTemplates || []);
|
|
76
|
+
for (const t of report.templateMatches) {
|
|
77
|
+
if (registeredSet.has(t.templateName) && !t.suggestedKern) {
|
|
78
|
+
templateViolations.push(`${t.libraryName} pattern detected but not using KERN template '${t.templateName}'`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const passed = actualCoverage >= minCoverage && templateViolations.length === 0;
|
|
83
|
+
return { passed, minCoverage, actualCoverage, templateViolations };
|
|
84
|
+
}
|
|
85
|
+
// ── CLI Format ───────────────────────────────────────────────────────────
|
|
86
|
+
const SOURCE_TAGS = {
|
|
87
|
+
kern: '[kern]',
|
|
88
|
+
eslint: '[eslint]',
|
|
89
|
+
tsc: '[tsc]',
|
|
90
|
+
llm: '[llm]',
|
|
91
|
+
};
|
|
92
|
+
export function formatReport(report) {
|
|
93
|
+
const lines = [];
|
|
94
|
+
lines.push(` @kernlang/review — analyzing ${report.filePath}`);
|
|
95
|
+
lines.push('');
|
|
96
|
+
if (report.inferred.length > 0) {
|
|
97
|
+
lines.push(` KERN-expressible (${report.inferred.length} constructs):`);
|
|
98
|
+
for (const r of report.inferred) {
|
|
99
|
+
const loc = r.startLine === r.endLine
|
|
100
|
+
? `L${r.startLine}`
|
|
101
|
+
: `L${r.startLine}-${r.endLine}`;
|
|
102
|
+
const padLoc = loc.padEnd(12);
|
|
103
|
+
const padSummary = r.summary.substring(0, 50).padEnd(50);
|
|
104
|
+
const conf = `(${r.confidencePct}%)`;
|
|
105
|
+
lines.push(` ${padLoc}${padSummary} ${conf}`);
|
|
106
|
+
}
|
|
107
|
+
lines.push('');
|
|
108
|
+
}
|
|
109
|
+
if (report.templateMatches.length > 0) {
|
|
110
|
+
const withSuggestions = report.templateMatches.filter(t => t.suggestedKern);
|
|
111
|
+
const withoutSuggestions = report.templateMatches.filter(t => !t.suggestedKern);
|
|
112
|
+
if (withSuggestions.length > 0) {
|
|
113
|
+
lines.push(` Suggested .kern rewrites (${withSuggestions.length}):`);
|
|
114
|
+
for (const t of withSuggestions) {
|
|
115
|
+
const savings = t.tsTokens && t.kernTokens
|
|
116
|
+
? ` (${t.tsTokens} → ${t.kernTokens} tokens)`
|
|
117
|
+
: '';
|
|
118
|
+
lines.push(` ${t.templateName.padEnd(25)} → ${t.suggestedKern}${savings}`);
|
|
119
|
+
}
|
|
120
|
+
lines.push('');
|
|
121
|
+
}
|
|
122
|
+
if (withoutSuggestions.length > 0) {
|
|
123
|
+
lines.push(` Template matches (${withoutSuggestions.length}):`);
|
|
124
|
+
for (const t of withoutSuggestions) {
|
|
125
|
+
lines.push(` ${t.templateName.padEnd(25)} ${t.libraryName.padEnd(20)} (${t.confidencePct}%)`);
|
|
126
|
+
}
|
|
127
|
+
lines.push('');
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Unified findings — sorted by severity, with source tags
|
|
131
|
+
const allFindings = dedup(report.findings);
|
|
132
|
+
if (allFindings.length > 0) {
|
|
133
|
+
const errors = allFindings.filter(f => f.severity === 'error');
|
|
134
|
+
const warnings = allFindings.filter(f => f.severity === 'warning');
|
|
135
|
+
const infos = allFindings.filter(f => f.severity === 'info');
|
|
136
|
+
if (errors.length > 0) {
|
|
137
|
+
lines.push(` BUGS (${errors.length}):`);
|
|
138
|
+
for (const f of errors) {
|
|
139
|
+
const tag = SOURCE_TAGS[f.source] || '';
|
|
140
|
+
lines.push(` ! L${f.primarySpan.startLine}: ${tag} [${f.ruleId}] ${f.message}`);
|
|
141
|
+
if (f.suggestion)
|
|
142
|
+
lines.push(` Fix: ${f.suggestion}`);
|
|
143
|
+
}
|
|
144
|
+
lines.push('');
|
|
145
|
+
}
|
|
146
|
+
if (warnings.length > 0) {
|
|
147
|
+
lines.push(` WARNINGS (${warnings.length}):`);
|
|
148
|
+
for (const f of warnings) {
|
|
149
|
+
const tag = SOURCE_TAGS[f.source] || '';
|
|
150
|
+
lines.push(` ~ L${f.primarySpan.startLine}: ${tag} [${f.ruleId}] ${f.message}`);
|
|
151
|
+
if (f.suggestion)
|
|
152
|
+
lines.push(` Suggestion: ${f.suggestion}`);
|
|
153
|
+
}
|
|
154
|
+
lines.push('');
|
|
155
|
+
}
|
|
156
|
+
if (infos.length > 0) {
|
|
157
|
+
lines.push(` INFO (${infos.length}):`);
|
|
158
|
+
for (const f of infos) {
|
|
159
|
+
const tag = SOURCE_TAGS[f.source] || '';
|
|
160
|
+
lines.push(` - L${f.primarySpan.startLine}: ${tag} [${f.ruleId}] ${f.message}`);
|
|
161
|
+
}
|
|
162
|
+
lines.push('');
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const s = report.stats;
|
|
166
|
+
lines.push(` Summary: ${s.coveragePct}% KERN coverage, ~${s.totalTsTokens} → ${s.totalKernTokens} KERN tokens (${s.reductionPct}% reduction)`);
|
|
167
|
+
return lines.join('\n');
|
|
168
|
+
}
|
|
169
|
+
// ── Enforcement Format ───────────────────────────────────────────────────
|
|
170
|
+
export function formatEnforcement(result) {
|
|
171
|
+
const lines = [];
|
|
172
|
+
if (result.passed) {
|
|
173
|
+
lines.push(` Enforcement: PASS (${result.actualCoverage}% >= ${result.minCoverage}% min)`);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
lines.push(` Enforcement: FAIL`);
|
|
177
|
+
if (result.actualCoverage < result.minCoverage) {
|
|
178
|
+
lines.push(` Coverage ${result.actualCoverage}% < ${result.minCoverage}% minimum`);
|
|
179
|
+
}
|
|
180
|
+
for (const v of result.templateViolations) {
|
|
181
|
+
lines.push(` Template: ${v}`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return lines.join('\n');
|
|
185
|
+
}
|
|
186
|
+
// ── JSON Format ──────────────────────────────────────────────────────────
|
|
187
|
+
export function formatReportJSON(report) {
|
|
188
|
+
return JSON.stringify(report, null, 2);
|
|
189
|
+
}
|
|
190
|
+
// ── Multi-file Summary ───────────────────────────────────────────────────
|
|
191
|
+
export function formatSummary(reports) {
|
|
192
|
+
const lines = [];
|
|
193
|
+
let totalConstructs = 0;
|
|
194
|
+
let totalTsTokens = 0;
|
|
195
|
+
let totalKernTokens = 0;
|
|
196
|
+
let totalLines = 0;
|
|
197
|
+
let coveredLines = 0;
|
|
198
|
+
let totalFindings = 0;
|
|
199
|
+
for (const r of reports) {
|
|
200
|
+
totalConstructs += r.stats.constructCount;
|
|
201
|
+
totalTsTokens += r.stats.totalTsTokens;
|
|
202
|
+
totalKernTokens += r.stats.totalKernTokens;
|
|
203
|
+
totalLines += r.stats.totalLines;
|
|
204
|
+
coveredLines += r.stats.coveredLines;
|
|
205
|
+
totalFindings += r.findings.length;
|
|
206
|
+
}
|
|
207
|
+
const coveragePct = totalLines > 0 ? Math.round((coveredLines / totalLines) * 100) : 0;
|
|
208
|
+
const reductionPct = totalTsTokens > 0 ? Math.round((1 - totalKernTokens / totalTsTokens) * 100) : 0;
|
|
209
|
+
lines.push(` @kernlang/review — ${reports.length} files analyzed`);
|
|
210
|
+
lines.push('');
|
|
211
|
+
lines.push(` Total constructs: ${totalConstructs}`);
|
|
212
|
+
lines.push(` Coverage: ${coveragePct}%`);
|
|
213
|
+
lines.push(` Token reduction: ${reductionPct}% (~${totalTsTokens} → ${totalKernTokens} KERN tokens)`);
|
|
214
|
+
lines.push(` Findings: ${totalFindings}`);
|
|
215
|
+
return lines.join('\n');
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.js","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base review rules — always active, universal TS/KERN rules.
|
|
3
|
+
*
|
|
4
|
+
* These rules leverage the KERN IR for structural analysis.
|
|
5
|
+
* AST-level rules that duplicate ESLint are excluded.
|
|
6
|
+
*/
|
|
7
|
+
import type { ReviewFinding, RuleContext } from '../types.js';
|
|
8
|
+
declare function floatingPromise(ctx: RuleContext): ReviewFinding[];
|
|
9
|
+
export declare const baseRules: (typeof floatingPromise)[];
|
|
10
|
+
export {};
|