@mmnto/cli 1.5.4 → 1.5.6
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/assets/compiled-baseline.js +2 -2
- package/dist/assets/compiled-baseline.js.map +1 -1
- package/dist/commands/add-secret.d.ts.map +1 -1
- package/dist/commands/add-secret.js +6 -0
- package/dist/commands/add-secret.js.map +1 -1
- package/dist/commands/add-secret.test.js +14 -0
- package/dist/commands/add-secret.test.js.map +1 -1
- package/dist/commands/doctor.d.ts +10 -2
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +159 -6
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/doctor.test.js +232 -34
- package/dist/commands/doctor.test.js.map +1 -1
- package/dist/commands/install-hooks.test.js +4 -6
- package/dist/commands/install-hooks.test.js.map +1 -1
- package/dist/commands/ledger-analyzer.d.ts +24 -0
- package/dist/commands/ledger-analyzer.d.ts.map +1 -0
- package/dist/commands/ledger-analyzer.js +64 -0
- package/dist/commands/ledger-analyzer.js.map +1 -0
- package/dist/commands/ledger-analyzer.test.d.ts +2 -0
- package/dist/commands/ledger-analyzer.test.d.ts.map +1 -0
- package/dist/commands/ledger-analyzer.test.js +163 -0
- package/dist/commands/ledger-analyzer.test.js.map +1 -0
- package/dist/commands/rule-mutator.d.ts +17 -0
- package/dist/commands/rule-mutator.d.ts.map +1 -0
- package/dist/commands/rule-mutator.js +33 -0
- package/dist/commands/rule-mutator.js.map +1 -0
- package/dist/commands/rule-mutator.test.d.ts +2 -0
- package/dist/commands/rule-mutator.test.d.ts.map +1 -0
- package/dist/commands/rule-mutator.test.js +104 -0
- package/dist/commands/rule-mutator.test.js.map +1 -0
- package/dist/commands/run-compiled-rules.d.ts +3 -1
- package/dist/commands/run-compiled-rules.d.ts.map +1 -1
- package/dist/commands/run-compiled-rules.js +5 -1
- package/dist/commands/run-compiled-rules.js.map +1 -1
- package/dist/commands/shield-hints.d.ts.map +1 -1
- package/dist/commands/shield-hints.js +5 -4
- package/dist/commands/shield-hints.js.map +1 -1
- package/dist/commands/shield.js +2 -2
- package/dist/commands/shield.js.map +1 -1
- package/dist/commands/triage-pr.d.ts +21 -0
- package/dist/commands/triage-pr.d.ts.map +1 -0
- package/dist/commands/triage-pr.js +231 -0
- package/dist/commands/triage-pr.js.map +1 -0
- package/dist/commands/triage-pr.test.d.ts +2 -0
- package/dist/commands/triage-pr.test.d.ts.map +1 -0
- package/dist/commands/triage-pr.test.js +163 -0
- package/dist/commands/triage-pr.test.js.map +1 -0
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +3 -0
- package/dist/git.js.map +1 -1
- package/dist/index.js +17 -3
- package/dist/index.js.map +1 -1
- package/dist/parsers/triage-dedup.d.ts +8 -0
- package/dist/parsers/triage-dedup.d.ts.map +1 -0
- package/dist/parsers/triage-dedup.js +134 -0
- package/dist/parsers/triage-dedup.js.map +1 -0
- package/dist/parsers/triage-dedup.test.d.ts +2 -0
- package/dist/parsers/triage-dedup.test.d.ts.map +1 -0
- package/dist/parsers/triage-dedup.test.js +209 -0
- package/dist/parsers/triage-dedup.test.js.map +1 -0
- package/dist/parsers/triage-severity-mapper.d.ts +9 -0
- package/dist/parsers/triage-severity-mapper.d.ts.map +1 -0
- package/dist/parsers/triage-severity-mapper.js +86 -0
- package/dist/parsers/triage-severity-mapper.js.map +1 -0
- package/dist/parsers/triage-severity-mapper.test.d.ts +2 -0
- package/dist/parsers/triage-severity-mapper.test.d.ts.map +1 -0
- package/dist/parsers/triage-severity-mapper.test.js +62 -0
- package/dist/parsers/triage-severity-mapper.test.js.map +1 -0
- package/dist/parsers/triage-types.d.ts +12 -0
- package/dist/parsers/triage-types.d.ts.map +1 -0
- package/dist/parsers/triage-types.js +2 -0
- package/dist/parsers/triage-types.js.map +1 -0
- package/dist/pr-comment.d.ts +10 -4
- package/dist/pr-comment.d.ts.map +1 -1
- package/dist/pr-comment.js +29 -20
- package/dist/pr-comment.js.map +1 -1
- package/dist/pr-comment.test.js +58 -13
- package/dist/pr-comment.test.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { deduplicateFindings, extractKeywords, jaccardSimilarity } from './triage-dedup.js';
|
|
3
|
+
// ─── Helpers ─────────────────────────────────────────
|
|
4
|
+
function makeFinding(overrides = {}) {
|
|
5
|
+
return {
|
|
6
|
+
tool: 'coderabbit',
|
|
7
|
+
severity: 'info',
|
|
8
|
+
file: 'src/foo.ts',
|
|
9
|
+
body: 'Some finding body',
|
|
10
|
+
...overrides,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
// ─── extractKeywords ─────────────────────────────────
|
|
14
|
+
describe('extractKeywords', () => {
|
|
15
|
+
it('extracts significant words and strips stopwords', () => {
|
|
16
|
+
const kw = extractKeywords('The quick brown fox jumps over the lazy dog');
|
|
17
|
+
expect(kw.has('the')).toBe(false);
|
|
18
|
+
expect(kw.has('quick')).toBe(true);
|
|
19
|
+
expect(kw.has('brown')).toBe(true);
|
|
20
|
+
expect(kw.has('over')).toBe(true); // 4 chars, not a stopword, included
|
|
21
|
+
});
|
|
22
|
+
it('filters words shorter than 3 characters', () => {
|
|
23
|
+
const kw = extractKeywords('I am a big fan of it');
|
|
24
|
+
expect(kw.has('am')).toBe(false);
|
|
25
|
+
expect(kw.has('big')).toBe(true);
|
|
26
|
+
expect(kw.has('fan')).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
// ─── jaccardSimilarity ──────────────────────────────
|
|
30
|
+
describe('jaccardSimilarity', () => {
|
|
31
|
+
it('returns 0 for two empty sets', () => {
|
|
32
|
+
expect(jaccardSimilarity(new Set(), new Set())).toBe(0);
|
|
33
|
+
});
|
|
34
|
+
it('returns 1 for identical sets', () => {
|
|
35
|
+
const s = new Set(['foo', 'bar']);
|
|
36
|
+
expect(jaccardSimilarity(s, s)).toBe(1);
|
|
37
|
+
});
|
|
38
|
+
it('returns 0 for disjoint sets', () => {
|
|
39
|
+
const a = new Set(['foo', 'bar']);
|
|
40
|
+
const b = new Set(['baz', 'qux']);
|
|
41
|
+
expect(jaccardSimilarity(a, b)).toBe(0);
|
|
42
|
+
});
|
|
43
|
+
it('returns correct value for partial overlap', () => {
|
|
44
|
+
const a = new Set(['foo', 'bar', 'baz']);
|
|
45
|
+
const b = new Set(['bar', 'baz', 'qux']);
|
|
46
|
+
// intersection = {bar, baz} = 2, union = {foo, bar, baz, qux} = 4
|
|
47
|
+
expect(jaccardSimilarity(a, b)).toBeCloseTo(0.5);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
// ─── deduplicateFindings ─────────────────────────────
|
|
51
|
+
describe('deduplicateFindings', () => {
|
|
52
|
+
it('merges findings from different bots on same file+line with same category', () => {
|
|
53
|
+
const findings = [
|
|
54
|
+
makeFinding({
|
|
55
|
+
tool: 'coderabbit',
|
|
56
|
+
file: 'src/auth.ts',
|
|
57
|
+
line: 10,
|
|
58
|
+
body: 'SQL injection risk in query builder',
|
|
59
|
+
}),
|
|
60
|
+
makeFinding({
|
|
61
|
+
tool: 'gca',
|
|
62
|
+
file: 'src/auth.ts',
|
|
63
|
+
line: 10,
|
|
64
|
+
body: 'Potential injection vulnerability in SQL query',
|
|
65
|
+
}),
|
|
66
|
+
];
|
|
67
|
+
const result = deduplicateFindings(findings);
|
|
68
|
+
expect(result).toHaveLength(1);
|
|
69
|
+
expect(result[0].mergedWith).toHaveLength(1);
|
|
70
|
+
expect(result[0].mergedWith[0].tool).toBe('gca');
|
|
71
|
+
});
|
|
72
|
+
it('refuses to merge findings on the same line if triageCategory differs', () => {
|
|
73
|
+
const findings = [
|
|
74
|
+
makeFinding({
|
|
75
|
+
file: 'src/foo.ts',
|
|
76
|
+
line: 10,
|
|
77
|
+
body: 'SQL injection risk via exec call',
|
|
78
|
+
}),
|
|
79
|
+
makeFinding({
|
|
80
|
+
file: 'src/foo.ts',
|
|
81
|
+
line: 10,
|
|
82
|
+
body: 'Trailing whitespace on this line is a typo',
|
|
83
|
+
}),
|
|
84
|
+
];
|
|
85
|
+
const result = deduplicateFindings(findings);
|
|
86
|
+
// security vs nit — should NOT merge
|
|
87
|
+
expect(result).toHaveLength(2);
|
|
88
|
+
expect(result[0].mergedWith).toBeUndefined();
|
|
89
|
+
expect(result[1].mergedWith).toBeUndefined();
|
|
90
|
+
});
|
|
91
|
+
it('merges findings within +/-3 line proximity', () => {
|
|
92
|
+
const findings = [
|
|
93
|
+
makeFinding({
|
|
94
|
+
file: 'src/auth.ts',
|
|
95
|
+
line: 10,
|
|
96
|
+
body: 'Credential leak risk in secret handling code',
|
|
97
|
+
}),
|
|
98
|
+
makeFinding({
|
|
99
|
+
file: 'src/auth.ts',
|
|
100
|
+
line: 13,
|
|
101
|
+
body: 'Secret credential leak risk detected in code',
|
|
102
|
+
}),
|
|
103
|
+
];
|
|
104
|
+
const result = deduplicateFindings(findings);
|
|
105
|
+
expect(result).toHaveLength(1);
|
|
106
|
+
expect(result[0].mergedWith).toHaveLength(1);
|
|
107
|
+
});
|
|
108
|
+
it('does not merge findings more than 3 lines apart', () => {
|
|
109
|
+
const findings = [
|
|
110
|
+
makeFinding({
|
|
111
|
+
file: 'src/auth.ts',
|
|
112
|
+
line: 10,
|
|
113
|
+
body: 'Credential leak risk in this function',
|
|
114
|
+
}),
|
|
115
|
+
makeFinding({
|
|
116
|
+
file: 'src/auth.ts',
|
|
117
|
+
line: 14,
|
|
118
|
+
body: 'Secret credential exposed in this block',
|
|
119
|
+
}),
|
|
120
|
+
];
|
|
121
|
+
const result = deduplicateFindings(findings);
|
|
122
|
+
expect(result).toHaveLength(2);
|
|
123
|
+
});
|
|
124
|
+
it('does not merge findings in different files', () => {
|
|
125
|
+
const findings = [
|
|
126
|
+
makeFinding({
|
|
127
|
+
file: 'src/auth.ts',
|
|
128
|
+
line: 10,
|
|
129
|
+
body: 'SQL injection risk via exec call',
|
|
130
|
+
}),
|
|
131
|
+
makeFinding({
|
|
132
|
+
file: 'src/db.ts',
|
|
133
|
+
line: 10,
|
|
134
|
+
body: 'SQL injection risk via exec call',
|
|
135
|
+
}),
|
|
136
|
+
];
|
|
137
|
+
const result = deduplicateFindings(findings);
|
|
138
|
+
expect(result).toHaveLength(2);
|
|
139
|
+
});
|
|
140
|
+
it('handles file-level comments (no line) with high body similarity', () => {
|
|
141
|
+
const findings = [
|
|
142
|
+
makeFinding({
|
|
143
|
+
file: 'src/auth.ts',
|
|
144
|
+
line: undefined,
|
|
145
|
+
body: 'This module has security vulnerabilities in the authentication flow',
|
|
146
|
+
}),
|
|
147
|
+
makeFinding({
|
|
148
|
+
file: 'src/auth.ts',
|
|
149
|
+
line: undefined,
|
|
150
|
+
body: 'Security vulnerabilities detected in the authentication flow of this module',
|
|
151
|
+
}),
|
|
152
|
+
];
|
|
153
|
+
const result = deduplicateFindings(findings);
|
|
154
|
+
expect(result).toHaveLength(1);
|
|
155
|
+
expect(result[0].mergedWith).toHaveLength(1);
|
|
156
|
+
});
|
|
157
|
+
it('preserves all findings when no duplicates exist', () => {
|
|
158
|
+
const findings = [
|
|
159
|
+
makeFinding({
|
|
160
|
+
file: 'src/auth.ts',
|
|
161
|
+
line: 10,
|
|
162
|
+
body: 'SQL injection risk via exec call',
|
|
163
|
+
}),
|
|
164
|
+
makeFinding({
|
|
165
|
+
file: 'src/utils.ts',
|
|
166
|
+
line: 50,
|
|
167
|
+
body: 'Trailing whitespace is a cosmetic nit',
|
|
168
|
+
}),
|
|
169
|
+
makeFinding({
|
|
170
|
+
file: 'src/config.ts',
|
|
171
|
+
line: 5,
|
|
172
|
+
body: 'Missing null check on boundary parameter',
|
|
173
|
+
}),
|
|
174
|
+
];
|
|
175
|
+
const result = deduplicateFindings(findings);
|
|
176
|
+
expect(result).toHaveLength(3);
|
|
177
|
+
for (const r of result) {
|
|
178
|
+
expect(r.mergedWith).toBeUndefined();
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
it('populates mergedWith on the primary finding', () => {
|
|
182
|
+
const findings = [
|
|
183
|
+
makeFinding({
|
|
184
|
+
tool: 'coderabbit',
|
|
185
|
+
file: 'src/auth.ts',
|
|
186
|
+
line: 10,
|
|
187
|
+
body: 'Credential leak risk in secret handling',
|
|
188
|
+
}),
|
|
189
|
+
makeFinding({
|
|
190
|
+
tool: 'gca',
|
|
191
|
+
file: 'src/auth.ts',
|
|
192
|
+
line: 11,
|
|
193
|
+
body: 'Secret credential leak detected here',
|
|
194
|
+
}),
|
|
195
|
+
makeFinding({
|
|
196
|
+
tool: 'unknown',
|
|
197
|
+
file: 'src/auth.ts',
|
|
198
|
+
line: 12,
|
|
199
|
+
body: 'Credential secret leak in this block',
|
|
200
|
+
}),
|
|
201
|
+
];
|
|
202
|
+
const result = deduplicateFindings(findings);
|
|
203
|
+
expect(result).toHaveLength(1);
|
|
204
|
+
expect(result[0].tool).toBe('coderabbit'); // primary is the first one
|
|
205
|
+
expect(result[0].mergedWith).toHaveLength(2);
|
|
206
|
+
expect(result[0].dedupKey).toContain('merged:');
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
//# sourceMappingURL=triage-dedup.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"triage-dedup.test.js","sourceRoot":"","sources":["../../src/parsers/triage-dedup.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NormalizedBotFinding } from './bot-review-parser.js';
|
|
2
|
+
import type { TriageCategory } from './triage-types.js';
|
|
3
|
+
/** Keyword dictionaries for severity mapping */
|
|
4
|
+
export declare const SECURITY_KEYWORDS: string[];
|
|
5
|
+
export declare const ARCHITECTURE_KEYWORDS: string[];
|
|
6
|
+
export declare const CONVENTION_KEYWORDS: string[];
|
|
7
|
+
export declare const NIT_KEYWORDS: string[];
|
|
8
|
+
export declare function mapToTriageCategory(finding: NormalizedBotFinding): TriageCategory;
|
|
9
|
+
//# sourceMappingURL=triage-severity-mapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"triage-severity-mapper.d.ts","sourceRoot":"","sources":["../../src/parsers/triage-severity-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,gDAAgD;AAChD,eAAO,MAAM,iBAAiB,UAkB7B,CAAC;AAEF,eAAO,MAAM,qBAAqB,UAcjC,CAAC;AAEF,eAAO,MAAM,mBAAmB,UAY/B,CAAC;AAEF,eAAO,MAAM,YAAY,UAcxB,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,cAAc,CAiBjF"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/** Keyword dictionaries for severity mapping */
|
|
2
|
+
export const SECURITY_KEYWORDS = [
|
|
3
|
+
'injection',
|
|
4
|
+
'xss',
|
|
5
|
+
'csrf',
|
|
6
|
+
'redos',
|
|
7
|
+
'shell',
|
|
8
|
+
'exec',
|
|
9
|
+
'spawn',
|
|
10
|
+
'credential',
|
|
11
|
+
'secret',
|
|
12
|
+
'leak',
|
|
13
|
+
'vulnerability',
|
|
14
|
+
'cwe-',
|
|
15
|
+
'security',
|
|
16
|
+
'sanitiz',
|
|
17
|
+
'escap',
|
|
18
|
+
'authori',
|
|
19
|
+
'authenticat',
|
|
20
|
+
];
|
|
21
|
+
export const ARCHITECTURE_KEYWORDS = [
|
|
22
|
+
'empty catch',
|
|
23
|
+
'validation',
|
|
24
|
+
'zod',
|
|
25
|
+
'type safety',
|
|
26
|
+
'static import',
|
|
27
|
+
'dynamic import',
|
|
28
|
+
'race condition',
|
|
29
|
+
'missing guard',
|
|
30
|
+
'null check',
|
|
31
|
+
'error handling',
|
|
32
|
+
'boundary',
|
|
33
|
+
'coupling',
|
|
34
|
+
'abstraction',
|
|
35
|
+
];
|
|
36
|
+
export const CONVENTION_KEYWORDS = [
|
|
37
|
+
'tag',
|
|
38
|
+
'log.error',
|
|
39
|
+
'naming',
|
|
40
|
+
'style guide',
|
|
41
|
+
'rule #',
|
|
42
|
+
'convention',
|
|
43
|
+
'formatting',
|
|
44
|
+
'casing',
|
|
45
|
+
'prefix',
|
|
46
|
+
'totem error',
|
|
47
|
+
'styleguide',
|
|
48
|
+
];
|
|
49
|
+
export const NIT_KEYWORDS = [
|
|
50
|
+
'marketing',
|
|
51
|
+
'copy',
|
|
52
|
+
'rephrase',
|
|
53
|
+
'consider',
|
|
54
|
+
'optional',
|
|
55
|
+
'nitpick',
|
|
56
|
+
'nit',
|
|
57
|
+
'minor',
|
|
58
|
+
'cosmetic',
|
|
59
|
+
'typo',
|
|
60
|
+
'spelling',
|
|
61
|
+
'whitespace',
|
|
62
|
+
'trailing',
|
|
63
|
+
];
|
|
64
|
+
export function mapToTriageCategory(finding) {
|
|
65
|
+
// Only search the body for keywords — NOT severity, which would cause
|
|
66
|
+
// 'minor' severity to match NIT_KEYWORDS and misbucket
|
|
67
|
+
const text = finding.body.toLowerCase();
|
|
68
|
+
// Check in priority order — security first
|
|
69
|
+
if (SECURITY_KEYWORDS.some((kw) => text.includes(kw)))
|
|
70
|
+
return 'security';
|
|
71
|
+
if (ARCHITECTURE_KEYWORDS.some((kw) => text.includes(kw)))
|
|
72
|
+
return 'architecture';
|
|
73
|
+
if (CONVENTION_KEYWORDS.some((kw) => text.includes(kw)))
|
|
74
|
+
return 'convention';
|
|
75
|
+
if (NIT_KEYWORDS.some((kw) => text.includes(kw)))
|
|
76
|
+
return 'nit';
|
|
77
|
+
// Fall back to bot-assigned severity
|
|
78
|
+
if (finding.severity === 'critical' || finding.severity === 'high')
|
|
79
|
+
return 'security';
|
|
80
|
+
if (finding.severity === 'major' || finding.severity === 'medium')
|
|
81
|
+
return 'architecture';
|
|
82
|
+
if (finding.severity === 'minor' || finding.severity === 'low')
|
|
83
|
+
return 'convention';
|
|
84
|
+
return 'architecture'; // default to architecture (better safe than sorry)
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=triage-severity-mapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"triage-severity-mapper.js","sourceRoot":"","sources":["../../src/parsers/triage-severity-mapper.ts"],"names":[],"mappings":"AAGA,gDAAgD;AAChD,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,WAAW;IACX,KAAK;IACL,MAAM;IACN,OAAO;IACP,OAAO;IACP,MAAM;IACN,OAAO;IACP,YAAY;IACZ,QAAQ;IACR,MAAM;IACN,eAAe;IACf,MAAM;IACN,UAAU;IACV,SAAS;IACT,OAAO;IACP,SAAS;IACT,aAAa;CACd,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,aAAa;IACb,YAAY;IACZ,KAAK;IACL,aAAa;IACb,eAAe;IACf,gBAAgB;IAChB,gBAAgB;IAChB,eAAe;IACf,YAAY;IACZ,gBAAgB;IAChB,UAAU;IACV,UAAU;IACV,aAAa;CACd,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,KAAK;IACL,WAAW;IACX,QAAQ;IACR,aAAa;IACb,QAAQ;IACR,YAAY;IACZ,YAAY;IACZ,QAAQ;IACR,QAAQ;IACR,aAAa;IACb,YAAY;CACb,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,WAAW;IACX,MAAM;IACN,UAAU;IACV,UAAU;IACV,UAAU;IACV,SAAS;IACT,KAAK;IACL,OAAO;IACP,UAAU;IACV,MAAM;IACN,UAAU;IACV,YAAY;IACZ,UAAU;CACX,CAAC;AAEF,MAAM,UAAU,mBAAmB,CAAC,OAA6B;IAC/D,sEAAsE;IACtE,uDAAuD;IACvD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;IAExC,2CAA2C;IAC3C,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAAE,OAAO,UAAU,CAAC;IACzE,IAAI,qBAAqB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAAE,OAAO,cAAc,CAAC;IACjF,IAAI,mBAAmB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAAE,OAAO,YAAY,CAAC;IAC7E,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAE/D,qCAAqC;IACrC,IAAI,OAAO,CAAC,QAAQ,KAAK,UAAU,IAAI,OAAO,CAAC,QAAQ,KAAK,MAAM;QAAE,OAAO,UAAU,CAAC;IACtF,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,cAAc,CAAC;IACzF,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK;QAAE,OAAO,YAAY,CAAC;IAEpF,OAAO,cAAc,CAAC,CAAC,mDAAmD;AAC5E,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"triage-severity-mapper.test.d.ts","sourceRoot":"","sources":["../../src/parsers/triage-severity-mapper.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { mapToTriageCategory } from './triage-severity-mapper.js';
|
|
3
|
+
// ─── Helpers ─────────────────────────────────────────
|
|
4
|
+
function makeFinding(overrides = {}) {
|
|
5
|
+
return {
|
|
6
|
+
tool: 'coderabbit',
|
|
7
|
+
severity: 'info',
|
|
8
|
+
file: 'src/foo.ts',
|
|
9
|
+
body: 'Some finding body',
|
|
10
|
+
...overrides,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
// ─── mapToTriageCategory ─────────────────────────────
|
|
14
|
+
describe('mapToTriageCategory', () => {
|
|
15
|
+
it('maps shell injection finding to security', () => {
|
|
16
|
+
const finding = makeFinding({ body: 'Avoid shell injection via exec() call' });
|
|
17
|
+
expect(mapToTriageCategory(finding)).toBe('security');
|
|
18
|
+
});
|
|
19
|
+
it('maps ReDoS finding to security', () => {
|
|
20
|
+
const finding = makeFinding({ body: 'This regex is vulnerable to ReDoS attacks' });
|
|
21
|
+
expect(mapToTriageCategory(finding)).toBe('security');
|
|
22
|
+
});
|
|
23
|
+
it('maps empty catch finding to architecture', () => {
|
|
24
|
+
const finding = makeFinding({ body: 'Empty catch block silently swallows errors' });
|
|
25
|
+
expect(mapToTriageCategory(finding)).toBe('architecture');
|
|
26
|
+
});
|
|
27
|
+
it('maps static import finding to architecture', () => {
|
|
28
|
+
const finding = makeFinding({
|
|
29
|
+
body: 'Convert static import to dynamic import for startup perf',
|
|
30
|
+
});
|
|
31
|
+
expect(mapToTriageCategory(finding)).toBe('architecture');
|
|
32
|
+
});
|
|
33
|
+
it('maps log.error tag finding to convention', () => {
|
|
34
|
+
const finding = makeFinding({ body: 'Missing [Totem Error] tag on log.error call' });
|
|
35
|
+
expect(mapToTriageCategory(finding)).toBe('convention');
|
|
36
|
+
});
|
|
37
|
+
it('maps styleguide rule reference to convention', () => {
|
|
38
|
+
const finding = makeFinding({ body: 'Violates styleguide naming convention' });
|
|
39
|
+
expect(mapToTriageCategory(finding)).toBe('convention');
|
|
40
|
+
});
|
|
41
|
+
it('maps nitpick finding to nit', () => {
|
|
42
|
+
const finding = makeFinding({ body: 'Nitpick: maybe rename this variable' });
|
|
43
|
+
expect(mapToTriageCategory(finding)).toBe('nit');
|
|
44
|
+
});
|
|
45
|
+
it('maps whitespace finding to nit', () => {
|
|
46
|
+
const finding = makeFinding({ body: 'Trailing whitespace on line 42' });
|
|
47
|
+
expect(mapToTriageCategory(finding)).toBe('nit');
|
|
48
|
+
});
|
|
49
|
+
it('falls back to architecture for unknown findings', () => {
|
|
50
|
+
const finding = makeFinding({ body: 'Something unusual happened here' });
|
|
51
|
+
expect(mapToTriageCategory(finding)).toBe('architecture');
|
|
52
|
+
});
|
|
53
|
+
it('uses bot severity as fallback (critical -> security)', () => {
|
|
54
|
+
const finding = makeFinding({ body: 'Something unusual happened here', severity: 'critical' });
|
|
55
|
+
expect(mapToTriageCategory(finding)).toBe('security');
|
|
56
|
+
});
|
|
57
|
+
it('assigns nit category to findings with nitpick keywords regardless of case', () => {
|
|
58
|
+
const finding = makeFinding({ body: 'NITPICK: This could be cleaner' });
|
|
59
|
+
expect(mapToTriageCategory(finding)).toBe('nit');
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
//# sourceMappingURL=triage-severity-mapper.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"triage-severity-mapper.test.js","sourceRoot":"","sources":["../../src/parsers/triage-severity-mapper.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { NormalizedBotFinding } from './bot-review-parser.js';
|
|
2
|
+
/** Triage categories ordered by blast radius */
|
|
3
|
+
export type TriageCategory = 'security' | 'architecture' | 'convention' | 'nit';
|
|
4
|
+
/** A finding with heuristic category assignment and dedup info */
|
|
5
|
+
export interface CategorizedFinding extends NormalizedBotFinding {
|
|
6
|
+
triageCategory: TriageCategory;
|
|
7
|
+
/** Unique ID for dedup grouping */
|
|
8
|
+
dedupKey: string;
|
|
9
|
+
/** Other findings merged into this one during dedup */
|
|
10
|
+
mergedWith?: NormalizedBotFinding[];
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=triage-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"triage-types.d.ts","sourceRoot":"","sources":["../../src/parsers/triage-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEnE,gDAAgD;AAChD,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,cAAc,GAAG,YAAY,GAAG,KAAK,CAAC;AAEhF,kEAAkE;AAClE,MAAM,WAAW,kBAAmB,SAAQ,oBAAoB;IAC9D,cAAc,EAAE,cAAc,CAAC;IAC/B,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,UAAU,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACrC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"triage-types.js","sourceRoot":"","sources":["../../src/parsers/triage-types.ts"],"names":[],"mappings":""}
|
package/dist/pr-comment.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* PR summary comment for totem lint — single managed comment per PR.
|
|
3
3
|
* Implements #923: deduplicates violations, builds markdown, upserts via gh CLI.
|
|
4
4
|
*/
|
|
5
|
-
import type { CompiledRule, Violation } from '@mmnto/totem';
|
|
5
|
+
import type { CompiledRule, TotemFinding, Violation } from '@mmnto/totem';
|
|
6
6
|
export interface DedupedFinding {
|
|
7
7
|
file: string;
|
|
8
8
|
line: number;
|
|
@@ -19,10 +19,16 @@ export interface PRSummaryData {
|
|
|
19
19
|
durationMs: number;
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
|
-
* Deduplicate
|
|
23
|
-
* location collapse into one
|
|
22
|
+
* Deduplicate unified findings by file + line. Multiple findings at the same
|
|
23
|
+
* location collapse into one with the highest severity and a rule count.
|
|
24
|
+
* Canonical dedup implementation (ADR-071).
|
|
24
25
|
*/
|
|
25
|
-
export declare function
|
|
26
|
+
export declare function deduplicateFindings(input: TotemFinding[]): DedupedFinding[];
|
|
27
|
+
/**
|
|
28
|
+
* Deduplicate violations by file + line. Converts to unified findings
|
|
29
|
+
* and delegates to deduplicateFindings.
|
|
30
|
+
*/
|
|
31
|
+
export declare function deduplicateViolations(violations: Violation[]): Promise<DedupedFinding[]>;
|
|
26
32
|
/**
|
|
27
33
|
* Build the managed PR comment markdown from summary data.
|
|
28
34
|
*/
|
package/dist/pr-comment.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pr-comment.d.ts","sourceRoot":"","sources":["../src/pr-comment.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"pr-comment.d.ts","sourceRoot":"","sources":["../src/pr-comment.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAI1E,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AASD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,cAAc,EAAE,CAqC3E;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAG9F;AAID;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CA6ClE;AAID,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+DlF;AAID,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBhF"}
|
package/dist/pr-comment.js
CHANGED
|
@@ -7,44 +7,53 @@ const COMMENT_MARKER = '<!-- totem-lint -->';
|
|
|
7
7
|
const MAX_TABLE_ROWS = 50;
|
|
8
8
|
// ─── Deduplication ──────────────────────────────────
|
|
9
9
|
/**
|
|
10
|
-
* Deduplicate
|
|
11
|
-
* location collapse into one
|
|
10
|
+
* Deduplicate unified findings by file + line. Multiple findings at the same
|
|
11
|
+
* location collapse into one with the highest severity and a rule count.
|
|
12
|
+
* Canonical dedup implementation (ADR-071).
|
|
12
13
|
*/
|
|
13
|
-
export function
|
|
14
|
+
export function deduplicateFindings(input) {
|
|
14
15
|
const groups = new Map();
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
let unlocatedIdx = 0;
|
|
17
|
+
for (const f of input) {
|
|
18
|
+
// Findings without file/line get unique keys to avoid incorrect grouping
|
|
19
|
+
const key = f.file && f.line ? `${f.file}:${f.line}` : `__unlocated__${unlocatedIdx++}`;
|
|
17
20
|
const existing = groups.get(key);
|
|
18
21
|
if (existing) {
|
|
19
|
-
existing.
|
|
22
|
+
existing.findings.push(f);
|
|
20
23
|
}
|
|
21
24
|
else {
|
|
22
|
-
groups.set(key, {
|
|
25
|
+
groups.set(key, { findings: [f] });
|
|
23
26
|
}
|
|
24
27
|
}
|
|
25
|
-
const
|
|
26
|
-
for (const {
|
|
27
|
-
|
|
28
|
-
group.sort((a, b) => a.rule.lessonHash.localeCompare(b.rule.lessonHash));
|
|
28
|
+
const deduped = [];
|
|
29
|
+
for (const { findings: group } of groups.values()) {
|
|
30
|
+
group.sort((a, b) => a.id.localeCompare(b.id));
|
|
29
31
|
const first = group[0];
|
|
30
|
-
const hasError = group.some((
|
|
31
|
-
|
|
32
|
-
file: first.file,
|
|
33
|
-
line: first.
|
|
34
|
-
message: first.
|
|
32
|
+
const hasError = group.some((f) => f.severity === 'error');
|
|
33
|
+
deduped.push({
|
|
34
|
+
file: first.file ?? '',
|
|
35
|
+
line: first.line ?? 0,
|
|
36
|
+
message: first.message,
|
|
35
37
|
severity: hasError ? 'error' : 'warning',
|
|
36
38
|
ruleCount: group.length,
|
|
37
39
|
});
|
|
38
40
|
}
|
|
39
|
-
|
|
40
|
-
findings.sort((a, b) => {
|
|
41
|
+
deduped.sort((a, b) => {
|
|
41
42
|
if (a.severity !== b.severity)
|
|
42
43
|
return a.severity === 'error' ? -1 : 1;
|
|
43
44
|
if (a.file !== b.file)
|
|
44
45
|
return a.file.localeCompare(b.file);
|
|
45
46
|
return a.line - b.line;
|
|
46
47
|
});
|
|
47
|
-
return
|
|
48
|
+
return deduped;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Deduplicate violations by file + line. Converts to unified findings
|
|
52
|
+
* and delegates to deduplicateFindings.
|
|
53
|
+
*/
|
|
54
|
+
export async function deduplicateViolations(violations) {
|
|
55
|
+
const { violationToFinding } = await import('@mmnto/totem');
|
|
56
|
+
return deduplicateFindings(violations.map(violationToFinding));
|
|
48
57
|
}
|
|
49
58
|
// ─── Markdown builder ───────────────────────────────
|
|
50
59
|
/**
|
|
@@ -150,7 +159,7 @@ export async function upsertPRComment(options) {
|
|
|
150
159
|
*/
|
|
151
160
|
export async function postPRComment(options) {
|
|
152
161
|
const { violations, rules, prNumber, commitSha, durationMs, cwd } = options;
|
|
153
|
-
const findings = deduplicateViolations(violations);
|
|
162
|
+
const findings = await deduplicateViolations(violations);
|
|
154
163
|
const errors = findings.filter((f) => f.severity === 'error').length;
|
|
155
164
|
const warnings = findings.filter((f) => f.severity === 'warning').length;
|
|
156
165
|
const markdown = buildPRCommentMarkdown({
|
package/dist/pr-comment.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pr-comment.js","sourceRoot":"","sources":["../src/pr-comment.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAuBH,uDAAuD;AAEvD,MAAM,cAAc,GAAG,qBAAqB,CAAC;AAC7C,MAAM,cAAc,GAAG,EAAE,CAAC;AAE1B,uDAAuD;AAEvD
|
|
1
|
+
{"version":3,"file":"pr-comment.js","sourceRoot":"","sources":["../src/pr-comment.ts"],"names":[],"mappings":"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"}
|