@kernlang/review 3.3.8 → 3.4.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/dist/cache.js +1 -1
- package/dist/call-graph.d.ts +10 -0
- package/dist/call-graph.js +138 -9
- package/dist/call-graph.js.map +1 -1
- package/dist/concept-rules/auth-drift.js +2 -0
- package/dist/concept-rules/auth-drift.js.map +1 -1
- package/dist/concept-rules/auth-propagation-drift.d.ts +10 -0
- package/dist/concept-rules/auth-propagation-drift.js +85 -0
- package/dist/concept-rules/auth-propagation-drift.js.map +1 -0
- package/dist/concept-rules/body-shape-drift.d.ts +32 -0
- package/dist/concept-rules/body-shape-drift.js +98 -0
- package/dist/concept-rules/body-shape-drift.js.map +1 -0
- package/dist/concept-rules/contract-drift.js +3 -1
- package/dist/concept-rules/contract-drift.js.map +1 -1
- package/dist/concept-rules/contract-method-drift.js +2 -0
- package/dist/concept-rules/contract-method-drift.js.map +1 -1
- package/dist/concept-rules/cross-stack-utils.d.ts +24 -0
- package/dist/concept-rules/cross-stack-utils.js +123 -29
- package/dist/concept-rules/cross-stack-utils.js.map +1 -1
- package/dist/concept-rules/index.d.ts +4 -2
- package/dist/concept-rules/index.js +22 -3
- package/dist/concept-rules/index.js.map +1 -1
- package/dist/concept-rules/mutation-without-idempotency.d.ts +10 -0
- package/dist/concept-rules/mutation-without-idempotency.js +47 -0
- package/dist/concept-rules/mutation-without-idempotency.js.map +1 -0
- package/dist/concept-rules/request-validation-drift.d.ts +11 -0
- package/dist/concept-rules/request-validation-drift.js +99 -0
- package/dist/concept-rules/request-validation-drift.js.map +1 -0
- package/dist/concept-rules/root-cause.d.ts +4 -0
- package/dist/concept-rules/root-cause.js +31 -0
- package/dist/concept-rules/root-cause.js.map +1 -0
- package/dist/concept-rules/unbounded-collection-query.d.ts +10 -0
- package/dist/concept-rules/unbounded-collection-query.js +58 -0
- package/dist/concept-rules/unbounded-collection-query.js.map +1 -0
- package/dist/concept-rules/unhandled-api-error-shape.d.ts +10 -0
- package/dist/concept-rules/unhandled-api-error-shape.js +59 -0
- package/dist/concept-rules/unhandled-api-error-shape.js.map +1 -0
- package/dist/default-export.d.ts +41 -0
- package/dist/default-export.js +76 -0
- package/dist/default-export.js.map +1 -0
- package/dist/eval.d.ts +67 -0
- package/dist/eval.js +177 -0
- package/dist/eval.js.map +1 -0
- package/dist/external-tools.js +52 -3
- package/dist/external-tools.js.map +1 -1
- package/dist/file-context.js +32 -13
- package/dist/file-context.js.map +1 -1
- package/dist/file-role.d.ts +6 -0
- package/dist/file-role.js +27 -0
- package/dist/file-role.js.map +1 -1
- package/dist/framework-seeds.d.ts +46 -0
- package/dist/framework-seeds.js +245 -0
- package/dist/framework-seeds.js.map +1 -0
- package/dist/git-env.d.ts +1 -0
- package/dist/git-env.js +25 -0
- package/dist/git-env.js.map +1 -0
- package/dist/graph.js +246 -21
- package/dist/graph.js.map +1 -1
- package/dist/index.d.ts +12 -3
- package/dist/index.js +314 -96
- package/dist/index.js.map +1 -1
- package/dist/mappers/ts-concepts.js +730 -1
- package/dist/mappers/ts-concepts.js.map +1 -1
- package/dist/path-canonical.d.ts +34 -0
- package/dist/path-canonical.js +85 -0
- package/dist/path-canonical.js.map +1 -0
- package/dist/policy.d.ts +22 -0
- package/dist/policy.js +47 -0
- package/dist/policy.js.map +1 -0
- package/dist/project-context.d.ts +135 -0
- package/dist/project-context.js +563 -0
- package/dist/project-context.js.map +1 -0
- package/dist/public-api.d.ts +21 -0
- package/dist/public-api.js +17 -2
- package/dist/public-api.js.map +1 -1
- package/dist/python-fallback.d.ts +2 -0
- package/dist/python-fallback.js +506 -0
- package/dist/python-fallback.js.map +1 -0
- package/dist/reporter.js +106 -1
- package/dist/reporter.js.map +1 -1
- package/dist/rule-quality.d.ts +58 -0
- package/dist/rule-quality.js +357 -0
- package/dist/rule-quality.js.map +1 -0
- package/dist/rules/base.js +21 -3
- package/dist/rules/base.js.map +1 -1
- package/dist/rules/dead-code.d.ts +2 -2
- package/dist/rules/dead-code.js +88 -4
- package/dist/rules/dead-code.js.map +1 -1
- package/dist/rules/index.d.ts +22 -0
- package/dist/rules/index.js +72 -0
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/kern-source.d.ts +4 -0
- package/dist/rules/kern-source.js +184 -0
- package/dist/rules/kern-source.js.map +1 -1
- package/dist/rules/react.js +52 -3
- package/dist/rules/react.js.map +1 -1
- package/dist/rules/suggest-kern-primitive.js +0 -1
- package/dist/rules/suggest-kern-primitive.js.map +1 -1
- package/dist/semantic-diff.js +2 -0
- package/dist/semantic-diff.js.map +1 -1
- package/dist/suppression/apply-suppression.js +2 -0
- package/dist/suppression/apply-suppression.js.map +1 -1
- package/dist/suppression/parse-directives.d.ts +13 -5
- package/dist/suppression/parse-directives.js +62 -8
- package/dist/suppression/parse-directives.js.map +1 -1
- package/dist/suppression/types.d.ts +9 -0
- package/dist/suppression/types.js +6 -1
- package/dist/suppression/types.js.map +1 -1
- package/dist/taint-crossfile.js +15 -8
- package/dist/taint-crossfile.js.map +1 -1
- package/dist/telemetry.d.ts +126 -0
- package/dist/telemetry.js +303 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/types.d.ts +172 -2
- package/dist/types.js.map +1 -1
- package/package.json +4 -3
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
|
+
import { appendFileSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
3
|
+
import { dirname, resolve } from 'path';
|
|
4
|
+
import { inferReviewPolicy } from './policy.js';
|
|
5
|
+
import { getRuleQualityProfile } from './rule-quality.js';
|
|
6
|
+
export function buildReviewTelemetry(reports, options = {}) {
|
|
7
|
+
const findings = reports.flatMap((report) => report.findings);
|
|
8
|
+
const suppressed = reports.flatMap((report) => report.suppressedFindings ?? []);
|
|
9
|
+
const allForRuleCounts = [...findings, ...suppressed];
|
|
10
|
+
const rootCauseKeys = new Set(findings.map((finding) => finding.rootCause?.key).filter(Boolean));
|
|
11
|
+
const healthEntries = reports.flatMap((report) => report.health?.entries ?? []);
|
|
12
|
+
const rules = buildRuleTelemetry(allForRuleCounts, suppressed);
|
|
13
|
+
return {
|
|
14
|
+
schemaVersion: 1,
|
|
15
|
+
generatedAt: options.generatedAt ?? new Date().toISOString(),
|
|
16
|
+
policy: options.policy ?? inferReviewPolicy(),
|
|
17
|
+
files: reports.length,
|
|
18
|
+
findings: {
|
|
19
|
+
total: findings.length,
|
|
20
|
+
errors: findings.filter((finding) => finding.severity === 'error').length,
|
|
21
|
+
warnings: findings.filter((finding) => finding.severity === 'warning').length,
|
|
22
|
+
notes: findings.filter((finding) => finding.severity === 'info').length,
|
|
23
|
+
},
|
|
24
|
+
suppressed: {
|
|
25
|
+
total: suppressed.length,
|
|
26
|
+
},
|
|
27
|
+
rootCauses: rootCauseKeys.size,
|
|
28
|
+
health: {
|
|
29
|
+
status: healthEntries.some((entry) => entry.kind === 'error')
|
|
30
|
+
? 'partial'
|
|
31
|
+
: healthEntries.length > 0
|
|
32
|
+
? 'degraded'
|
|
33
|
+
: 'ok',
|
|
34
|
+
errors: healthEntries.filter((entry) => entry.kind === 'error').length,
|
|
35
|
+
fallbacks: healthEntries.filter((entry) => entry.kind === 'fallback').length,
|
|
36
|
+
skipped: healthEntries.filter((entry) => entry.kind === 'skipped').length,
|
|
37
|
+
},
|
|
38
|
+
rules,
|
|
39
|
+
...(options.durationMs !== undefined ? { performance: { durationMs: options.durationMs } } : {}),
|
|
40
|
+
...(options.includeFindings
|
|
41
|
+
? {
|
|
42
|
+
findingRows: findings.map((f) => toFindingRow(f, options.policy ?? inferReviewPolicy(), options.redactPaths ?? false)),
|
|
43
|
+
}
|
|
44
|
+
: {}),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export function writeReviewTelemetrySnapshot(reports, options = {}) {
|
|
48
|
+
const outputPath = resolve(options.outputPath ?? '.kern/cache/review-telemetry.jsonl');
|
|
49
|
+
const snapshot = buildReviewTelemetry(reports, options);
|
|
50
|
+
mkdirSync(dirname(outputPath), { recursive: true });
|
|
51
|
+
const line = `${JSON.stringify(snapshot)}\n`;
|
|
52
|
+
if (options.append === false) {
|
|
53
|
+
writeFileSync(outputPath, line, 'utf-8');
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
appendFileSync(outputPath, line, 'utf-8');
|
|
57
|
+
}
|
|
58
|
+
return { outputPath, snapshot };
|
|
59
|
+
}
|
|
60
|
+
export function parseReviewTelemetryJsonl(source) {
|
|
61
|
+
const snapshots = [];
|
|
62
|
+
const lines = source.split(/\r?\n/);
|
|
63
|
+
for (let i = 0; i < lines.length; i++) {
|
|
64
|
+
const line = lines[i].trim();
|
|
65
|
+
if (!line)
|
|
66
|
+
continue;
|
|
67
|
+
let parsed;
|
|
68
|
+
try {
|
|
69
|
+
parsed = JSON.parse(line);
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
throw new Error(`telemetry line ${i + 1} is not valid JSON: ${err.message}`);
|
|
73
|
+
}
|
|
74
|
+
if (!isTelemetrySnapshot(parsed)) {
|
|
75
|
+
throw new Error(`telemetry line ${i + 1} is not a KERN review telemetry snapshot`);
|
|
76
|
+
}
|
|
77
|
+
snapshots.push(parsed);
|
|
78
|
+
}
|
|
79
|
+
return snapshots;
|
|
80
|
+
}
|
|
81
|
+
export function readReviewTelemetrySnapshots(path) {
|
|
82
|
+
return parseReviewTelemetryJsonl(readFileSync(path, 'utf-8'));
|
|
83
|
+
}
|
|
84
|
+
export function summarizeReviewTelemetry(snapshots) {
|
|
85
|
+
const ruleMap = new Map();
|
|
86
|
+
const durations = snapshots.map((snapshot) => snapshot.performance?.durationMs).filter(isNumber);
|
|
87
|
+
const sortedDates = snapshots.map((snapshot) => snapshot.generatedAt).sort();
|
|
88
|
+
for (const snapshot of snapshots) {
|
|
89
|
+
for (const rule of snapshot.rules) {
|
|
90
|
+
const existing = ruleMap.get(rule.ruleId) ??
|
|
91
|
+
{
|
|
92
|
+
ruleId: rule.ruleId,
|
|
93
|
+
findings: 0,
|
|
94
|
+
suppressed: 0,
|
|
95
|
+
errors: 0,
|
|
96
|
+
warnings: 0,
|
|
97
|
+
notes: 0,
|
|
98
|
+
rootCauses: 0,
|
|
99
|
+
runs: 0,
|
|
100
|
+
suppressionRate: 0,
|
|
101
|
+
averageFindingsPerRun: 0,
|
|
102
|
+
...(rule.precision ? { precision: rule.precision } : {}),
|
|
103
|
+
...(rule.lifecycle ? { lifecycle: rule.lifecycle } : {}),
|
|
104
|
+
...(rule.ciDefault ? { ciDefault: rule.ciDefault } : {}),
|
|
105
|
+
};
|
|
106
|
+
existing.findings += rule.findings;
|
|
107
|
+
existing.suppressed += rule.suppressed;
|
|
108
|
+
existing.errors += rule.errors;
|
|
109
|
+
existing.warnings += rule.warnings;
|
|
110
|
+
existing.notes += rule.notes;
|
|
111
|
+
existing.rootCauses += rule.rootCauses;
|
|
112
|
+
existing.runs++;
|
|
113
|
+
ruleMap.set(rule.ruleId, existing);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const rules = Array.from(ruleMap.values())
|
|
117
|
+
.map((rule) => {
|
|
118
|
+
const totalObserved = rule.findings + rule.suppressed;
|
|
119
|
+
return {
|
|
120
|
+
...rule,
|
|
121
|
+
suppressionRate: totalObserved > 0 ? rule.suppressed / totalObserved : 0,
|
|
122
|
+
averageFindingsPerRun: snapshots.length > 0 ? rule.findings / snapshots.length : 0,
|
|
123
|
+
};
|
|
124
|
+
})
|
|
125
|
+
.sort((a, b) => b.findings + b.suppressed - (a.findings + a.suppressed) || a.ruleId.localeCompare(b.ruleId));
|
|
126
|
+
return {
|
|
127
|
+
runs: snapshots.length,
|
|
128
|
+
...(sortedDates[0] ? { firstRun: sortedDates[0] } : {}),
|
|
129
|
+
...(sortedDates[sortedDates.length - 1] ? { lastRun: sortedDates[sortedDates.length - 1] } : {}),
|
|
130
|
+
files: snapshots.reduce((sum, snapshot) => sum + snapshot.files, 0),
|
|
131
|
+
findings: {
|
|
132
|
+
total: snapshots.reduce((sum, snapshot) => sum + snapshot.findings.total, 0),
|
|
133
|
+
errors: snapshots.reduce((sum, snapshot) => sum + snapshot.findings.errors, 0),
|
|
134
|
+
warnings: snapshots.reduce((sum, snapshot) => sum + snapshot.findings.warnings, 0),
|
|
135
|
+
notes: snapshots.reduce((sum, snapshot) => sum + snapshot.findings.notes, 0),
|
|
136
|
+
},
|
|
137
|
+
suppressed: {
|
|
138
|
+
total: snapshots.reduce((sum, snapshot) => sum + snapshot.suppressed.total, 0),
|
|
139
|
+
},
|
|
140
|
+
rootCauses: snapshots.reduce((sum, snapshot) => sum + snapshot.rootCauses, 0),
|
|
141
|
+
health: {
|
|
142
|
+
partial: snapshots.filter((snapshot) => snapshot.health.status === 'partial').length,
|
|
143
|
+
degraded: snapshots.filter((snapshot) => snapshot.health.status === 'degraded').length,
|
|
144
|
+
ok: snapshots.filter((snapshot) => snapshot.health.status === 'ok').length,
|
|
145
|
+
errors: snapshots.reduce((sum, snapshot) => sum + snapshot.health.errors, 0),
|
|
146
|
+
fallbacks: snapshots.reduce((sum, snapshot) => sum + snapshot.health.fallbacks, 0),
|
|
147
|
+
skipped: snapshots.reduce((sum, snapshot) => sum + snapshot.health.skipped, 0),
|
|
148
|
+
},
|
|
149
|
+
performance: {
|
|
150
|
+
...(durations.length > 0
|
|
151
|
+
? {
|
|
152
|
+
averageDurationMs: Math.round(durations.reduce((sum, duration) => sum + duration, 0) / durations.length),
|
|
153
|
+
maxDurationMs: Math.max(...durations),
|
|
154
|
+
}
|
|
155
|
+
: {}),
|
|
156
|
+
},
|
|
157
|
+
rules,
|
|
158
|
+
noisyRules: rules.filter((rule) => rule.suppressed >= 3 && rule.suppressionRate >= 0.5),
|
|
159
|
+
promotionCandidates: rules.filter((rule) => rule.precision === 'high' &&
|
|
160
|
+
rule.lifecycle === 'stable' &&
|
|
161
|
+
rule.ciDefault !== 'on' &&
|
|
162
|
+
rule.findings > 0 &&
|
|
163
|
+
rule.suppressionRate <= 0.1),
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
export function formatReviewTelemetrySummary(summary) {
|
|
167
|
+
const lines = [
|
|
168
|
+
'KERN Review Telemetry',
|
|
169
|
+
'',
|
|
170
|
+
`Runs: ${summary.runs}`,
|
|
171
|
+
`Files: ${summary.files}`,
|
|
172
|
+
`Findings: ${summary.findings.total} (${summary.findings.errors} errors, ${summary.findings.warnings} warnings, ${summary.findings.notes} notes)`,
|
|
173
|
+
`Suppressed: ${summary.suppressed.total}`,
|
|
174
|
+
`Root causes: ${summary.rootCauses}`,
|
|
175
|
+
`Health: ${summary.health.ok} ok, ${summary.health.degraded} degraded, ${summary.health.partial} partial`,
|
|
176
|
+
];
|
|
177
|
+
if (summary.performance.averageDurationMs !== undefined) {
|
|
178
|
+
lines.push(`Duration: avg ${summary.performance.averageDurationMs}ms, max ${summary.performance.maxDurationMs ?? 0}ms`);
|
|
179
|
+
}
|
|
180
|
+
lines.push('', 'Top Rules:');
|
|
181
|
+
for (const rule of summary.rules.slice(0, 10)) {
|
|
182
|
+
const suppressionPct = `${Math.round(rule.suppressionRate * 100)}%`;
|
|
183
|
+
lines.push(` ${rule.ruleId}: ${rule.findings} findings, ${rule.suppressed} suppressed (${suppressionPct} suppressed)`);
|
|
184
|
+
}
|
|
185
|
+
if (summary.noisyRules.length > 0) {
|
|
186
|
+
lines.push('', 'Noisy Rules:');
|
|
187
|
+
for (const rule of summary.noisyRules.slice(0, 10)) {
|
|
188
|
+
lines.push(` ${rule.ruleId}: ${Math.round(rule.suppressionRate * 100)}% suppression rate`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (summary.promotionCandidates.length > 0) {
|
|
192
|
+
lines.push('', 'Promotion Candidates:');
|
|
193
|
+
for (const rule of summary.promotionCandidates.slice(0, 10)) {
|
|
194
|
+
lines.push(` ${rule.ruleId}: high/stable with low suppression`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return lines.join('\n');
|
|
198
|
+
}
|
|
199
|
+
function buildRuleTelemetry(findings, suppressedFindings) {
|
|
200
|
+
const suppressedKeys = new Set(suppressedFindings.map((finding) => `${finding.ruleId}:${finding.fingerprint}`));
|
|
201
|
+
const byRule = new Map();
|
|
202
|
+
for (const finding of findings) {
|
|
203
|
+
const existing = byRule.get(finding.ruleId) ?? makeRuleTelemetry(finding.ruleId);
|
|
204
|
+
const isSuppressed = suppressedKeys.has(`${finding.ruleId}:${finding.fingerprint}`);
|
|
205
|
+
if (isSuppressed) {
|
|
206
|
+
existing.suppressed++;
|
|
207
|
+
switch (finding.suppressionReason) {
|
|
208
|
+
case 'false-positive':
|
|
209
|
+
existing.suppressedAsFalsePositive = (existing.suppressedAsFalsePositive ?? 0) + 1;
|
|
210
|
+
break;
|
|
211
|
+
case 'wont-fix':
|
|
212
|
+
existing.suppressedAsWontFix = (existing.suppressedAsWontFix ?? 0) + 1;
|
|
213
|
+
break;
|
|
214
|
+
case 'intentional':
|
|
215
|
+
existing.suppressedAsIntentional = (existing.suppressedAsIntentional ?? 0) + 1;
|
|
216
|
+
break;
|
|
217
|
+
case 'not-applicable':
|
|
218
|
+
existing.suppressedAsNotApplicable = (existing.suppressedAsNotApplicable ?? 0) + 1;
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
existing.findings++;
|
|
224
|
+
if (finding.severity === 'error')
|
|
225
|
+
existing.errors++;
|
|
226
|
+
else if (finding.severity === 'warning')
|
|
227
|
+
existing.warnings++;
|
|
228
|
+
else
|
|
229
|
+
existing.notes++;
|
|
230
|
+
if (finding.rootCause?.key)
|
|
231
|
+
existing.rootCauseKeys.add(finding.rootCause.key);
|
|
232
|
+
}
|
|
233
|
+
byRule.set(finding.ruleId, existing);
|
|
234
|
+
}
|
|
235
|
+
return Array.from(byRule.values())
|
|
236
|
+
.map(({ rootCauseKeys, ...rule }) => {
|
|
237
|
+
const fp = rule.suppressedAsFalsePositive ?? 0;
|
|
238
|
+
const denom = rule.findings + fp;
|
|
239
|
+
const fpRateEstimate = denom > 0 && fp > 0 ? fp / denom : undefined;
|
|
240
|
+
return {
|
|
241
|
+
...rule,
|
|
242
|
+
rootCauses: rootCauseKeys.size,
|
|
243
|
+
...(fpRateEstimate !== undefined ? { fpRateEstimate } : {}),
|
|
244
|
+
};
|
|
245
|
+
})
|
|
246
|
+
.sort((a, b) => b.findings - a.findings || a.ruleId.localeCompare(b.ruleId));
|
|
247
|
+
}
|
|
248
|
+
function makeRuleTelemetry(ruleId) {
|
|
249
|
+
const profile = getRuleQualityProfile(ruleId);
|
|
250
|
+
return {
|
|
251
|
+
ruleId,
|
|
252
|
+
findings: 0,
|
|
253
|
+
suppressed: 0,
|
|
254
|
+
errors: 0,
|
|
255
|
+
warnings: 0,
|
|
256
|
+
notes: 0,
|
|
257
|
+
rootCauses: 0,
|
|
258
|
+
rootCauseKeys: new Set(),
|
|
259
|
+
...(profile
|
|
260
|
+
? {
|
|
261
|
+
precision: profile.precision,
|
|
262
|
+
lifecycle: profile.lifecycle,
|
|
263
|
+
ciDefault: profile.ciDefault,
|
|
264
|
+
}
|
|
265
|
+
: {}),
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
function toFindingRow(finding, policy, redactPaths) {
|
|
269
|
+
return {
|
|
270
|
+
file: redactPaths ? hashPath(finding.primarySpan.file) : finding.primarySpan.file,
|
|
271
|
+
ruleId: finding.ruleId,
|
|
272
|
+
severity: finding.severity,
|
|
273
|
+
...(finding.confidence !== undefined ? { confidence: finding.confidence } : {}),
|
|
274
|
+
...(finding.rootCause?.key ? { rootCauseKey: finding.rootCause.key } : {}),
|
|
275
|
+
...(policy === 'audit' && finding.calibrationTrail && finding.calibrationTrail.length > 0
|
|
276
|
+
? { calibrationTrail: finding.calibrationTrail }
|
|
277
|
+
: {}),
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Stable, prefix-truncated hash of a file path. 16 hex chars = 64 bits of
|
|
282
|
+
* entropy — collision-resistant within any single project, while opaque to
|
|
283
|
+
* a multi-tenant telemetry consumer.
|
|
284
|
+
*/
|
|
285
|
+
function hashPath(p) {
|
|
286
|
+
return `path:${createHash('sha256').update(p).digest('hex').slice(0, 16)}`;
|
|
287
|
+
}
|
|
288
|
+
function isTelemetrySnapshot(value) {
|
|
289
|
+
if (!value || typeof value !== 'object')
|
|
290
|
+
return false;
|
|
291
|
+
const candidate = value;
|
|
292
|
+
return (candidate.schemaVersion === 1 &&
|
|
293
|
+
typeof candidate.generatedAt === 'string' &&
|
|
294
|
+
typeof candidate.policy === 'string' &&
|
|
295
|
+
typeof candidate.files === 'number' &&
|
|
296
|
+
Boolean(candidate.findings) &&
|
|
297
|
+
Boolean(candidate.suppressed) &&
|
|
298
|
+
Array.isArray(candidate.rules));
|
|
299
|
+
}
|
|
300
|
+
function isNumber(value) {
|
|
301
|
+
return typeof value === 'number' && Number.isFinite(value);
|
|
302
|
+
}
|
|
303
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -50,6 +50,15 @@ export interface ProvenanceChain {
|
|
|
50
50
|
/** Optional one-line summary shown before expanding the chain */
|
|
51
51
|
summary?: string;
|
|
52
52
|
}
|
|
53
|
+
/** Semantic root cause used to group findings that describe the same underlying issue. */
|
|
54
|
+
export interface RootCause {
|
|
55
|
+
/** Stable grouping key. Prefer graph/concept IDs over raw line numbers. */
|
|
56
|
+
key: string;
|
|
57
|
+
/** Coarse class of the underlying issue source. */
|
|
58
|
+
kind: 'api-call' | 'route' | 'data-flow' | 'symbol' | 'file' | 'unknown';
|
|
59
|
+
/** Optional structured facets for dashboards and future explainers. */
|
|
60
|
+
facets?: Record<string, string>;
|
|
61
|
+
}
|
|
53
62
|
/** Unified finding from any review layer */
|
|
54
63
|
export interface ReviewFinding {
|
|
55
64
|
/** Which layer produced this finding */
|
|
@@ -82,6 +91,44 @@ export interface ReviewFinding {
|
|
|
82
91
|
distance?: number;
|
|
83
92
|
/** Evidence chain explaining WHY the finding fired (taint path, boundary walk, etc.) */
|
|
84
93
|
provenance?: ProvenanceChain;
|
|
94
|
+
/** Semantic grouping key for cross-rule/root-cause ownership. */
|
|
95
|
+
rootCause?: RootCause;
|
|
96
|
+
/**
|
|
97
|
+
* Per-stage calibration record. Populated by applyRuleQualityCalibration when a
|
|
98
|
+
* factor actually changes severity or confidence. Lets audit policy show why a
|
|
99
|
+
* finding was demoted/dropped without recomputing the chain.
|
|
100
|
+
*/
|
|
101
|
+
calibrationTrail?: CalibrationStage[];
|
|
102
|
+
/**
|
|
103
|
+
* Set true after applyRuleQualityCalibration runs over this finding so that
|
|
104
|
+
* subsequent calls (e.g. graph-mode rerun after cross-file injection) skip it.
|
|
105
|
+
* Prevents compounding multipliers when Phase 1 role/overlap factors land.
|
|
106
|
+
*/
|
|
107
|
+
calibrated?: boolean;
|
|
108
|
+
/**
|
|
109
|
+
* If this finding was suppressed by a `// kern-ignore [reason: …]` directive,
|
|
110
|
+
* the closed-enum reason is propagated here so telemetry can compute per-rule
|
|
111
|
+
* FP/intent rates without scanning source again. Closed-enum: any free text
|
|
112
|
+
* is rejected at parse time.
|
|
113
|
+
*/
|
|
114
|
+
suppressionReason?: import('./suppression/types.js').SuppressionReason;
|
|
115
|
+
}
|
|
116
|
+
/** One step of calibration applied to a finding. */
|
|
117
|
+
export interface CalibrationStage {
|
|
118
|
+
/** Identifier for the stage that ran (e.g. 'rule-quality:demote-advisory'). */
|
|
119
|
+
stage: string;
|
|
120
|
+
/** Multiplicative factor applied to confidence (1.0 = no change). */
|
|
121
|
+
factor: number;
|
|
122
|
+
/** Why this stage acted on this finding. */
|
|
123
|
+
reason: string;
|
|
124
|
+
/** Confidence before this stage (undefined if confidence was unset). */
|
|
125
|
+
beforeConfidence?: number;
|
|
126
|
+
/** Confidence after this stage. */
|
|
127
|
+
afterConfidence?: number;
|
|
128
|
+
/** Severity before this stage, if changed. */
|
|
129
|
+
beforeSeverity?: ReviewFinding['severity'];
|
|
130
|
+
/** Severity after this stage, if changed. */
|
|
131
|
+
afterSeverity?: ReviewFinding['severity'];
|
|
85
132
|
}
|
|
86
133
|
/** Confidence level for an inference match */
|
|
87
134
|
export type Confidence = 'high' | 'medium' | 'low';
|
|
@@ -216,6 +263,18 @@ export interface ReviewStats {
|
|
|
216
263
|
/** Number of KERN-expressible constructs */
|
|
217
264
|
constructCount: number;
|
|
218
265
|
}
|
|
266
|
+
/** Named review posture. Guard is low-noise default, CI is strict, audit is broad. */
|
|
267
|
+
export type ReviewPolicy = 'guard' | 'ci' | 'audit';
|
|
268
|
+
export interface ReviewTelemetryConfig {
|
|
269
|
+
/** When true, persist a machine-readable telemetry snapshot for this review run. */
|
|
270
|
+
enabled?: boolean;
|
|
271
|
+
/** Output file. Defaults to .kern/cache/review-telemetry.jsonl when telemetry is enabled. */
|
|
272
|
+
outputPath?: string;
|
|
273
|
+
/** Append JSONL snapshots instead of replacing the file. Defaults to true. */
|
|
274
|
+
append?: boolean;
|
|
275
|
+
/** Include per-finding rows in addition to aggregate counts. Defaults to false. */
|
|
276
|
+
includeFindings?: boolean;
|
|
277
|
+
}
|
|
219
278
|
/** Enforcement result for CI */
|
|
220
279
|
export interface EnforceResult {
|
|
221
280
|
/** Whether enforcement passed */
|
|
@@ -262,6 +321,16 @@ export interface ReviewConfig {
|
|
|
262
321
|
format?: 'text' | 'json' | 'sarif';
|
|
263
322
|
/** Build target — activates framework-specific rules */
|
|
264
323
|
target?: string;
|
|
324
|
+
/**
|
|
325
|
+
* Cross-stack review precision mode.
|
|
326
|
+
* guard — default, high precision / low noise for KERN Guard and CI.
|
|
327
|
+
* audit — broader exploratory findings for local investigations.
|
|
328
|
+
*/
|
|
329
|
+
crossStackMode?: 'guard' | 'audit';
|
|
330
|
+
/** Explicit review policy. Used by CLI/defaulting/telemetry to distinguish CI, guard, and audit runs. */
|
|
331
|
+
policy?: ReviewPolicy;
|
|
332
|
+
/** Optional persistent telemetry for rule/noise calibration. */
|
|
333
|
+
telemetry?: ReviewTelemetryConfig;
|
|
265
334
|
/** Minimum confidence for findings to count in enforcement (default: 0) */
|
|
266
335
|
minConfidence?: number;
|
|
267
336
|
/** Show confidence scores in output */
|
|
@@ -311,7 +380,7 @@ export interface ReviewConfig {
|
|
|
311
380
|
* names (`src/routes.ts`) never collide. Rules that consult
|
|
312
381
|
* `ctx.allConcepts` treat the keys opaquely.
|
|
313
382
|
*/
|
|
314
|
-
externalConcepts?:
|
|
383
|
+
externalConcepts?: ReadonlyMap<string, unknown>;
|
|
315
384
|
}
|
|
316
385
|
/** Runtime boundary determined by position in the import tree */
|
|
317
386
|
export type RuntimeBoundary = 'server' | 'client' | 'api' | 'middleware' | 'shared' | 'unknown';
|
|
@@ -350,7 +419,24 @@ export interface RuleContext {
|
|
|
350
419
|
}
|
|
351
420
|
/** A review rule function */
|
|
352
421
|
export type ReviewRule = (ctx: RuleContext) => ReviewFinding[];
|
|
353
|
-
export type GraphEdgeKind = 'side-effect-import' | 'default-import' | 'named-import' | 'namespace-import' | 'named-reexport' | 'export-all'
|
|
422
|
+
export type GraphEdgeKind = 'side-effect-import' | 'default-import' | 'named-import' | 'namespace-import' | 'named-reexport' | 'export-all'
|
|
423
|
+
/**
|
|
424
|
+
* `export * as ns from './m'` — distinct from bare `export *` because the
|
|
425
|
+
* namespace alias gives us a concrete local name (`ns`) that Producer 1
|
|
426
|
+
* can attach a symbol-scoped blocker to when the target fails to resolve.
|
|
427
|
+
* Bare `export *` stays under `'export-all'` and produces no blocker
|
|
428
|
+
* (no symbol to pin).
|
|
429
|
+
*/
|
|
430
|
+
| 'namespace-reexport'
|
|
431
|
+
/**
|
|
432
|
+
* Literal `import('./mod')` — emitted by the graph walker when the argument
|
|
433
|
+
* is a StringLiteral or NoSubstitutionTemplateLiteral. Distinct from the
|
|
434
|
+
* static-import variants so a strongest-path traversal can prefer a static
|
|
435
|
+
* (full-confidence) edge over a dynamic (capped) edge to the same target.
|
|
436
|
+
* Non-literal `import(expr)` does NOT produce an edge — it produces a
|
|
437
|
+
* `ReachabilityBlocker` instead (see step 9b).
|
|
438
|
+
*/
|
|
439
|
+
| 'dynamic-import';
|
|
354
440
|
export interface GraphEdge {
|
|
355
441
|
from: string;
|
|
356
442
|
to: string;
|
|
@@ -365,7 +451,26 @@ export interface GraphEdge {
|
|
|
365
451
|
}
|
|
366
452
|
/** A file node in the import graph */
|
|
367
453
|
export interface GraphFile {
|
|
454
|
+
/**
|
|
455
|
+
* Display path — caller-facing (whatever the user passed in for entry
|
|
456
|
+
* files; whatever ts-morph reports for BFS-reached files). Use this
|
|
457
|
+
* for `report.filePath`, finding `primarySpan.file`, and any UI
|
|
458
|
+
* surface. NEVER use this as a Map key for cross-file resolution —
|
|
459
|
+
* symlinks (pnpm, macOS /var → /private/var) cause the same physical
|
|
460
|
+
* file to have multiple display paths and would silently produce
|
|
461
|
+
* twin entries (red-team #9).
|
|
462
|
+
*/
|
|
368
463
|
path: string;
|
|
464
|
+
/**
|
|
465
|
+
* Internal identity key — `realpathSync(path)` with a graceful fallback
|
|
466
|
+
* for paths that don't exist on disk. ALL Map keys, ts-morph
|
|
467
|
+
* `addSourceFileAtPath` calls, and cross-file binding lookups MUST use
|
|
468
|
+
* this form so two display paths pointing at the same physical file
|
|
469
|
+
* collapse to a single entry. The two forms are equal for normal
|
|
470
|
+
* projects without symlinks, so this is a no-op there. See
|
|
471
|
+
* `path-canonical.ts` for the canonicaliser invariant.
|
|
472
|
+
*/
|
|
473
|
+
canonicalPath: string;
|
|
369
474
|
distance: number;
|
|
370
475
|
imports: string[];
|
|
371
476
|
importedBy: string[];
|
|
@@ -381,12 +486,77 @@ export interface GraphResult {
|
|
|
381
486
|
/** ts-morph Project used to resolve the graph. Exposed so downstream
|
|
382
487
|
* analyses (call graph, cross-file taint) can reuse it without re-parsing. */
|
|
383
488
|
project?: import('ts-morph').Project;
|
|
489
|
+
/**
|
|
490
|
+
* Symbol-scoped reachability blockers discovered during graph resolution.
|
|
491
|
+
* Currently fed by Producer 1 (named re-export with unresolved relative
|
|
492
|
+
* target). Consumed by deadExportRule to cap finding confidence at 0.4
|
|
493
|
+
* with severity=info instead of emitting at full strength. Empty when
|
|
494
|
+
* every re-export resolved cleanly. NEVER file-scope — see jsdoc on
|
|
495
|
+
* ReachabilityBlocker.
|
|
496
|
+
*/
|
|
497
|
+
blockers?: ReachabilityBlocker[];
|
|
498
|
+
/**
|
|
499
|
+
* Telemetry-only counter: number of `import(expr)` call sites where the
|
|
500
|
+
* specifier is non-literal. Cannot derive a target file or export name
|
|
501
|
+
* from these, so they NEVER produce a blocker (would re-introduce the
|
|
502
|
+
* red-team CRITICAL #1 file-scope silencer). Reported via review-health
|
|
503
|
+
* so consumers know dead-export findings on files containing such
|
|
504
|
+
* dynamic dispatch may include FPs that the cap mechanism cannot reach.
|
|
505
|
+
*/
|
|
506
|
+
unmappedDynamicImports?: number;
|
|
507
|
+
/**
|
|
508
|
+
* Telemetry-only counter: number of static import declarations that
|
|
509
|
+
* threw when ts-morph tried to read them (malformed AST, transient FS
|
|
510
|
+
* error, etc.). Surfaced via review-health so a silent catch never
|
|
511
|
+
* hides a category of failures from operators. Set KERN_DEBUG to also
|
|
512
|
+
* log the underlying error per occurrence.
|
|
513
|
+
*/
|
|
514
|
+
malformedImports?: number;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* A reachability blocker — recorded when the call-graph cannot resolve an
|
|
518
|
+
* edge to a single concrete target (filePath, exportName) and so cannot
|
|
519
|
+
* prove a candidate dead export is unreachable.
|
|
520
|
+
*
|
|
521
|
+
* Blockers are SYMBOL-SCOPED. A non-literal dynamic import inside one
|
|
522
|
+
* function must NEVER suppress findings on unrelated exports in the same
|
|
523
|
+
* file — that was the killing red-team finding against Plan v3 ("one
|
|
524
|
+
* dynamic import silenced 50 unrelated symbols"). Each blocker carries the
|
|
525
|
+
* exact `(filePath, exportName)` it applies to. When the resolver cannot
|
|
526
|
+
* derive an exportName (e.g. fully non-literal `import(expr)`), it must
|
|
527
|
+
* NOT fall back to file scope; emit health/telemetry instead.
|
|
528
|
+
*
|
|
529
|
+
* Blockers do NOT hard-suppress. They cap finding confidence at 0.4 (see
|
|
530
|
+
* step 9b) and append a `CalibrationStage` to the finding's audit trail.
|
|
531
|
+
* Telemetry still sees the finding so `fpRateEstimate` stays honest.
|
|
532
|
+
*/
|
|
533
|
+
export type ReachabilityBlockerReason =
|
|
534
|
+
/** `import(expr)` where `expr` is not a string literal — target unknown. */
|
|
535
|
+
'non-literal-dynamic-import'
|
|
536
|
+
/** A re-export (`export * from`, `export { x } from`) whose target file
|
|
537
|
+
* resolved but the symbol couldn't be tied to a concrete declaration. */
|
|
538
|
+
| 'unresolved-re-export'
|
|
539
|
+
/** A public-API seed (package.json `exports`, framework convention) that
|
|
540
|
+
* pointed at a symbol the call graph never observed declaring. */
|
|
541
|
+
| 'unmapped-public-surface';
|
|
542
|
+
export interface ReachabilityBlocker {
|
|
543
|
+
reason: ReachabilityBlockerReason;
|
|
544
|
+
/** The candidate export this blocker applies to. SYMBOL scope, not file. */
|
|
545
|
+
filePath: string;
|
|
546
|
+
exportName: string;
|
|
547
|
+
/** Where the blocker decision was made — for the audit trail. */
|
|
548
|
+
site: {
|
|
549
|
+
file: string;
|
|
550
|
+
line: number;
|
|
551
|
+
};
|
|
384
552
|
}
|
|
385
553
|
/** Options for resolveImportGraph */
|
|
386
554
|
export interface GraphOptions {
|
|
387
555
|
maxDepth?: number;
|
|
388
556
|
tsConfigFilePath?: string;
|
|
389
557
|
project?: import('ts-morph').Project;
|
|
558
|
+
/** Optional graph already resolved by the caller, used to avoid duplicate resolution in CLI/watch flows. */
|
|
559
|
+
precomputedGraph?: GraphResult;
|
|
390
560
|
}
|
|
391
561
|
/** Create a stable fingerprint for dedup across sources and runs.
|
|
392
562
|
* Returns the raw composite key — collision-free by construction. */
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAwmBH,4EAA4E;AAE5E;sEACsE;AACtE,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,SAAiB,EAAE,QAAgB;IACnF,OAAO,GAAG,MAAM,IAAI,SAAS,IAAI,QAAQ,EAAE,CAAC;AAC9C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kernlang/review",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "Kern Review — scan TS, infer .kern IR, roundtrip diff, report",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -26,10 +26,11 @@
|
|
|
26
26
|
"license": "AGPL-3.0",
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"ts-morph": "^28.0.0",
|
|
29
|
-
"@kernlang/core": "3.
|
|
29
|
+
"@kernlang/core": "3.4.0"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"build": "tsc -b",
|
|
33
|
-
"test": "node --experimental-vm-modules ../../node_modules/jest/bin/jest.js --config jest.config.js"
|
|
33
|
+
"test": "node --experimental-vm-modules ../../node_modules/jest/bin/jest.js --config jest.config.js",
|
|
34
|
+
"test:handles": "node --experimental-vm-modules ../../node_modules/jest/bin/jest.js --config jest.config.js --detectOpenHandles --runInBand"
|
|
34
35
|
}
|
|
35
36
|
}
|