triage-ai 1.0.2
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 +21 -0
- package/README.md +209 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +633 -0
- package/dist/cli.js.map +1 -0
- package/dist/mcp-server.d.ts +24 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +411 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/memory.d.ts +40 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +241 -0
- package/dist/memory.js.map +1 -0
- package/dist/merge.d.ts +32 -0
- package/dist/merge.d.ts.map +1 -0
- package/dist/merge.js +251 -0
- package/dist/merge.js.map +1 -0
- package/dist/models/base.d.ts +72 -0
- package/dist/models/base.d.ts.map +1 -0
- package/dist/models/base.js +342 -0
- package/dist/models/base.js.map +1 -0
- package/dist/models/claude.d.ts +23 -0
- package/dist/models/claude.d.ts.map +1 -0
- package/dist/models/claude.js +30 -0
- package/dist/models/claude.js.map +1 -0
- package/dist/models/codex.d.ts +25 -0
- package/dist/models/codex.d.ts.map +1 -0
- package/dist/models/codex.js +34 -0
- package/dist/models/codex.js.map +1 -0
- package/dist/models/gemini.d.ts +23 -0
- package/dist/models/gemini.d.ts.map +1 -0
- package/dist/models/gemini.js +32 -0
- package/dist/models/gemini.js.map +1 -0
- package/dist/patch.d.ts +40 -0
- package/dist/patch.d.ts.map +1 -0
- package/dist/patch.js +183 -0
- package/dist/patch.js.map +1 -0
- package/dist/progress.d.ts +71 -0
- package/dist/progress.d.ts.map +1 -0
- package/dist/progress.js +268 -0
- package/dist/progress.js.map +1 -0
- package/dist/report.d.ts +19 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +245 -0
- package/dist/report.js.map +1 -0
- package/dist/scanner.d.ts +64 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +645 -0
- package/dist/scanner.js.map +1 -0
- package/dist/setup.d.ts +52 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +252 -0
- package/dist/setup.js.map +1 -0
- package/dist/types.d.ts +153 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +203 -0
- package/dist/types.js.map +1 -0
- package/examples/claude-code-skill.md +22 -0
- package/examples/mcp-config.json +9 -0
- package/package.json +77 -0
package/dist/memory.js
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory writer — saves triage findings to AI model memory files.
|
|
3
|
+
*
|
|
4
|
+
* After triage runs, findings are written to model-specific memory files
|
|
5
|
+
* so that Claude, Gemini and Codex remember issues in future sessions.
|
|
6
|
+
*
|
|
7
|
+
* Supported memory files:
|
|
8
|
+
* - CLAUDE.md — Claude Code project instructions
|
|
9
|
+
* - GEMINI.md — Gemini CLI project context
|
|
10
|
+
* - AGENTS.md — Codex/OpenAI agent instructions
|
|
11
|
+
*/
|
|
12
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
13
|
+
import { existsSync } from 'node:fs';
|
|
14
|
+
import { join } from 'node:path';
|
|
15
|
+
import { clusterRepresentative, isConsensus } from './types.js';
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Constants
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
export const MEMORY_START = '<!-- triage:start -->';
|
|
20
|
+
export const MEMORY_END = '<!-- triage:end -->';
|
|
21
|
+
export const MEMORY_FILES = {
|
|
22
|
+
claude: 'CLAUDE.md',
|
|
23
|
+
gemini: 'GEMINI.md',
|
|
24
|
+
codex: 'AGENTS.md',
|
|
25
|
+
};
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Public API
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
/**
|
|
30
|
+
* Write triage findings to AI model memory files.
|
|
31
|
+
*
|
|
32
|
+
* Replaces any existing triage section (between markers) or appends
|
|
33
|
+
* a new one. This keeps memory current — old findings are replaced by
|
|
34
|
+
* the latest run, not accumulated forever.
|
|
35
|
+
*/
|
|
36
|
+
export async function writeMemory(merged, prompt, root, models) {
|
|
37
|
+
const rootDir = root ?? process.cwd();
|
|
38
|
+
const targetModels = models ?? Object.keys(MEMORY_FILES);
|
|
39
|
+
const content = _buildMemoryContent(merged, prompt);
|
|
40
|
+
if (!content) {
|
|
41
|
+
// No findings — clear any stale triage blocks
|
|
42
|
+
return clearMemory(rootDir, targetModels);
|
|
43
|
+
}
|
|
44
|
+
const results = {};
|
|
45
|
+
for (const model of targetModels) {
|
|
46
|
+
const filename = MEMORY_FILES[model];
|
|
47
|
+
if (!filename)
|
|
48
|
+
continue;
|
|
49
|
+
const filepath = join(rootDir, filename);
|
|
50
|
+
const success = await _updateMemoryFile(filepath, content);
|
|
51
|
+
results[filename] = success;
|
|
52
|
+
if (success) {
|
|
53
|
+
console.log(` Updated ${filename} with triage findings`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return results;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Remove triage sections from AI model memory files.
|
|
60
|
+
*/
|
|
61
|
+
export async function clearMemory(root, models) {
|
|
62
|
+
const rootDir = root ?? process.cwd();
|
|
63
|
+
const targetModels = models ?? Object.keys(MEMORY_FILES);
|
|
64
|
+
const results = {};
|
|
65
|
+
for (const model of targetModels) {
|
|
66
|
+
const filename = MEMORY_FILES[model];
|
|
67
|
+
if (!filename)
|
|
68
|
+
continue;
|
|
69
|
+
const filepath = join(rootDir, filename);
|
|
70
|
+
if (!existsSync(filepath))
|
|
71
|
+
continue;
|
|
72
|
+
try {
|
|
73
|
+
const existing = await readFile(filepath, 'utf-8');
|
|
74
|
+
if (!existing.includes(MEMORY_START))
|
|
75
|
+
continue;
|
|
76
|
+
if (!existing.includes(MEMORY_END)) {
|
|
77
|
+
console.log(` Warning: ${filename} has start marker but no end marker — skipping`);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
// Remove the triage section
|
|
81
|
+
const before = existing.slice(0, existing.indexOf(MEMORY_START)).trimEnd();
|
|
82
|
+
const afterIdx = existing.indexOf(MEMORY_END) + MEMORY_END.length;
|
|
83
|
+
const after = existing.slice(afterIdx).replace(/^\n+/, '');
|
|
84
|
+
let newContent = before;
|
|
85
|
+
if (after) {
|
|
86
|
+
newContent += '\n\n' + after;
|
|
87
|
+
}
|
|
88
|
+
newContent = newContent.trimEnd() + '\n';
|
|
89
|
+
await writeFile(filepath, newContent, 'utf-8');
|
|
90
|
+
results[filename] = true;
|
|
91
|
+
console.log(` Cleared triage section from ${filename}`);
|
|
92
|
+
}
|
|
93
|
+
catch (e) {
|
|
94
|
+
console.log(` Failed to clear ${filename}: ${e}`);
|
|
95
|
+
results[filename] = false;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return results;
|
|
99
|
+
}
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
// Internal helpers
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
/** Build the memory content block from merged results. */
|
|
104
|
+
export function _buildMemoryContent(merged, prompt) {
|
|
105
|
+
const total = merged.blockers.length +
|
|
106
|
+
merged.high.length +
|
|
107
|
+
merged.medium.length +
|
|
108
|
+
merged.low.length;
|
|
109
|
+
if (total === 0)
|
|
110
|
+
return '';
|
|
111
|
+
const now = new Date();
|
|
112
|
+
const timestamp = now.getFullYear() +
|
|
113
|
+
'-' +
|
|
114
|
+
String(now.getMonth() + 1).padStart(2, '0') +
|
|
115
|
+
'-' +
|
|
116
|
+
String(now.getDate()).padStart(2, '0') +
|
|
117
|
+
' ' +
|
|
118
|
+
String(now.getHours()).padStart(2, '0') +
|
|
119
|
+
':' +
|
|
120
|
+
String(now.getMinutes()).padStart(2, '0');
|
|
121
|
+
const lines = [];
|
|
122
|
+
lines.push(MEMORY_START);
|
|
123
|
+
lines.push('');
|
|
124
|
+
lines.push('## Triage Findings');
|
|
125
|
+
lines.push('');
|
|
126
|
+
lines.push(`*Last run: ${timestamp} — ${total} issues found, ${merged.consensus.length} consensus*`);
|
|
127
|
+
lines.push('');
|
|
128
|
+
if (prompt) {
|
|
129
|
+
lines.push(`> **Scope:** ${prompt}`);
|
|
130
|
+
lines.push('');
|
|
131
|
+
}
|
|
132
|
+
// Blockers — full detail
|
|
133
|
+
if (merged.blockers.length > 0) {
|
|
134
|
+
lines.push('### Blockers (must fix)');
|
|
135
|
+
lines.push('');
|
|
136
|
+
for (const cluster of merged.blockers) {
|
|
137
|
+
lines.push(..._formatCluster(cluster));
|
|
138
|
+
}
|
|
139
|
+
lines.push('');
|
|
140
|
+
}
|
|
141
|
+
// High priority — full detail
|
|
142
|
+
if (merged.high.length > 0) {
|
|
143
|
+
lines.push('### High Priority');
|
|
144
|
+
lines.push('');
|
|
145
|
+
for (const cluster of merged.high) {
|
|
146
|
+
lines.push(..._formatCluster(cluster));
|
|
147
|
+
}
|
|
148
|
+
lines.push('');
|
|
149
|
+
}
|
|
150
|
+
// Medium — summary only to keep memory concise
|
|
151
|
+
if (merged.medium.length > 0) {
|
|
152
|
+
lines.push('### Medium Priority');
|
|
153
|
+
lines.push('');
|
|
154
|
+
for (const cluster of merged.medium) {
|
|
155
|
+
const f = clusterRepresentative(cluster);
|
|
156
|
+
const consensusTag = isConsensus(cluster) ? ' **(consensus)**' : '';
|
|
157
|
+
lines.push(`- [${f.severity}] ${f.title} — \`${f.location.path}:${f.location.start_line}\`${consensusTag}`);
|
|
158
|
+
}
|
|
159
|
+
lines.push('');
|
|
160
|
+
}
|
|
161
|
+
// Low — just a count
|
|
162
|
+
if (merged.low.length > 0) {
|
|
163
|
+
lines.push(`*Plus ${merged.low.length} low-priority items (S3).*`);
|
|
164
|
+
lines.push('');
|
|
165
|
+
}
|
|
166
|
+
// Patterns to watch from consensus
|
|
167
|
+
if (merged.consensus.length > 0) {
|
|
168
|
+
lines.push('### Patterns to Watch');
|
|
169
|
+
lines.push('');
|
|
170
|
+
lines.push('These issues were flagged by multiple models — avoid introducing similar patterns:');
|
|
171
|
+
lines.push('');
|
|
172
|
+
for (const cluster of merged.consensus) {
|
|
173
|
+
const f = clusterRepresentative(cluster);
|
|
174
|
+
lines.push(`- **${f.title}**: ${f.recommendation}`);
|
|
175
|
+
}
|
|
176
|
+
lines.push('');
|
|
177
|
+
}
|
|
178
|
+
lines.push(MEMORY_END);
|
|
179
|
+
return lines.join('\n');
|
|
180
|
+
}
|
|
181
|
+
/** Format a finding cluster for memory output. */
|
|
182
|
+
export function _formatCluster(cluster) {
|
|
183
|
+
const lines = [];
|
|
184
|
+
const f = clusterRepresentative(cluster);
|
|
185
|
+
const consensusTag = isConsensus(cluster) ? ' **(consensus)**' : '';
|
|
186
|
+
const models = [...cluster.models].sort().join(', ');
|
|
187
|
+
lines.push(`- **[${f.severity}] ${f.title}**${consensusTag}`);
|
|
188
|
+
lines.push(` - Location: \`${f.location.path}:${f.location.start_line}-${f.location.end_line}\``);
|
|
189
|
+
lines.push(` - Models: ${models}`);
|
|
190
|
+
if (f.recommendation) {
|
|
191
|
+
let rec = f.recommendation.slice(0, 200);
|
|
192
|
+
if (f.recommendation.length > 200)
|
|
193
|
+
rec += '...';
|
|
194
|
+
lines.push(` - Fix: ${rec}`);
|
|
195
|
+
}
|
|
196
|
+
return lines;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Update a memory file with triage content.
|
|
200
|
+
*
|
|
201
|
+
* - If the file has an existing triage section, replace it.
|
|
202
|
+
* - If the file exists without a triage section, append.
|
|
203
|
+
* - If the file does not exist, create it with a minimal header.
|
|
204
|
+
*/
|
|
205
|
+
export async function _updateMemoryFile(filepath, content) {
|
|
206
|
+
try {
|
|
207
|
+
if (existsSync(filepath)) {
|
|
208
|
+
const existing = await readFile(filepath, 'utf-8');
|
|
209
|
+
let newContent;
|
|
210
|
+
if (existing.includes(MEMORY_START) && existing.includes(MEMORY_END)) {
|
|
211
|
+
// Replace existing triage section
|
|
212
|
+
const before = existing.slice(0, existing.indexOf(MEMORY_START)).trimEnd();
|
|
213
|
+
const afterIdx = existing.indexOf(MEMORY_END) + MEMORY_END.length;
|
|
214
|
+
const after = existing.slice(afterIdx).replace(/^\n+/, '');
|
|
215
|
+
newContent = before + '\n\n' + content;
|
|
216
|
+
if (after) {
|
|
217
|
+
newContent += '\n\n' + after;
|
|
218
|
+
}
|
|
219
|
+
newContent = newContent.trimEnd() + '\n';
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
// Append triage section
|
|
223
|
+
newContent = existing.trimEnd() + '\n\n' + content + '\n';
|
|
224
|
+
}
|
|
225
|
+
await writeFile(filepath, newContent, 'utf-8');
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
// Create new file with minimal header
|
|
229
|
+
const filename = filepath.split('/').pop()?.replace('.md', '') ?? 'Memory';
|
|
230
|
+
const newContent = `# ${filename}\n\n${content}\n`;
|
|
231
|
+
await writeFile(filepath, newContent, 'utf-8');
|
|
232
|
+
}
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
catch (e) {
|
|
236
|
+
const filename = filepath.split('/').pop() ?? filepath;
|
|
237
|
+
console.log(` Failed to write ${filename}: ${e}`);
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"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"}
|
package/dist/merge.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge and deduplicate findings from multiple models.
|
|
3
|
+
*
|
|
4
|
+
* Handles:
|
|
5
|
+
* - Clustering similar findings
|
|
6
|
+
* - Identifying consensus (2+ models agree)
|
|
7
|
+
* - Detecting conflicts/disagreements
|
|
8
|
+
* - Aggregating patches
|
|
9
|
+
*/
|
|
10
|
+
import { type Finding, type Patch, type ModelResult, type FindingCluster, type Conflict, type MergedResult } from './types.js';
|
|
11
|
+
export declare class MergeEngine {
|
|
12
|
+
private similarityThreshold;
|
|
13
|
+
constructor(similarityThreshold?: number);
|
|
14
|
+
/**
|
|
15
|
+
* Merge results from multiple models.
|
|
16
|
+
*/
|
|
17
|
+
merge(results: ModelResult[]): MergedResult;
|
|
18
|
+
/** Cluster similar findings together using greedy linear clustering. */
|
|
19
|
+
_clusterFindings(findings: Finding[]): FindingCluster[];
|
|
20
|
+
/** Check if a finding should be added to a cluster. */
|
|
21
|
+
_shouldCluster(finding: Finding, cluster: FindingCluster): boolean;
|
|
22
|
+
/** Detect disagreements between models (severity disagreements >= 2 levels). */
|
|
23
|
+
_detectConflicts(clusters: FindingCluster[]): Conflict[];
|
|
24
|
+
/** Aggregate unique patches from all clusters, prioritizing consensus. */
|
|
25
|
+
_aggregatePatches(clusters: FindingCluster[]): Patch[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Convert a MergedResult to a plain JSON-serializable object.
|
|
29
|
+
* Sets are converted to arrays.
|
|
30
|
+
*/
|
|
31
|
+
export declare function mergedResultToDict(merged: MergedResult): Record<string, unknown>;
|
|
32
|
+
//# sourceMappingURL=merge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,KAAK,EACV,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,YAAY,EAMlB,MAAM,YAAY,CAAC;AAMpB,qBAAa,WAAW;IACtB,OAAO,CAAC,mBAAmB,CAAS;gBAExB,mBAAmB,SAAM;IAIrC;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,YAAY;IA0E3C,wEAAwE;IACxE,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE;IA2BvD,uDAAuD;IACvD,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO;IASlE,gFAAgF;IAChF,gBAAgB,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,QAAQ,EAAE;IAyBxD,0EAA0E;IAC1E,iBAAiB,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,KAAK,EAAE;CAmBvD;AA4CD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgDhF"}
|
package/dist/merge.js
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge and deduplicate findings from multiple models.
|
|
3
|
+
*
|
|
4
|
+
* Handles:
|
|
5
|
+
* - Clustering similar findings
|
|
6
|
+
* - Identifying consensus (2+ models agree)
|
|
7
|
+
* - Detecting conflicts/disagreements
|
|
8
|
+
* - Aggregating patches
|
|
9
|
+
*/
|
|
10
|
+
import { findingsMatch, clusterSeverity, clusterRepresentative, clusterPatches, isConsensus, } from './types.js';
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// MergeEngine
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
export class MergeEngine {
|
|
15
|
+
similarityThreshold;
|
|
16
|
+
constructor(similarityThreshold = 0.6) {
|
|
17
|
+
this.similarityThreshold = similarityThreshold;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Merge results from multiple models.
|
|
21
|
+
*/
|
|
22
|
+
merge(results) {
|
|
23
|
+
const merged = {
|
|
24
|
+
blockers: [],
|
|
25
|
+
high: [],
|
|
26
|
+
medium: [],
|
|
27
|
+
low: [],
|
|
28
|
+
consensus: [],
|
|
29
|
+
unique_by_model: {},
|
|
30
|
+
conflicts: [],
|
|
31
|
+
patches: [],
|
|
32
|
+
questions: [],
|
|
33
|
+
summaries: {},
|
|
34
|
+
};
|
|
35
|
+
// Collect all findings
|
|
36
|
+
const allFindings = [];
|
|
37
|
+
for (const result of results) {
|
|
38
|
+
merged.summaries[result.model] = result.summary;
|
|
39
|
+
merged.questions.push(...result.questions);
|
|
40
|
+
for (const finding of result.findings) {
|
|
41
|
+
// Ensure model is set on each finding
|
|
42
|
+
const f = { ...finding, model: result.model };
|
|
43
|
+
allFindings.push(f);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Cluster similar findings
|
|
47
|
+
const clusters = this._clusterFindings(allFindings);
|
|
48
|
+
// Categorize by severity and consensus
|
|
49
|
+
for (const cluster of clusters) {
|
|
50
|
+
const severity = clusterSeverity(cluster);
|
|
51
|
+
if (severity === 'S0') {
|
|
52
|
+
merged.blockers.push(cluster);
|
|
53
|
+
}
|
|
54
|
+
else if (severity === 'S1') {
|
|
55
|
+
merged.high.push(cluster);
|
|
56
|
+
}
|
|
57
|
+
else if (severity === 'S2') {
|
|
58
|
+
merged.medium.push(cluster);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
merged.low.push(cluster);
|
|
62
|
+
}
|
|
63
|
+
if (isConsensus(cluster)) {
|
|
64
|
+
merged.consensus.push(cluster);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
// Single model finding
|
|
68
|
+
const model = [...cluster.models][0];
|
|
69
|
+
if (!merged.unique_by_model[model]) {
|
|
70
|
+
merged.unique_by_model[model] = [];
|
|
71
|
+
}
|
|
72
|
+
merged.unique_by_model[model].push(...cluster.findings);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Detect conflicts
|
|
76
|
+
merged.conflicts = this._detectConflicts(clusters);
|
|
77
|
+
// Aggregate patches
|
|
78
|
+
merged.patches = this._aggregatePatches(clusters);
|
|
79
|
+
// Sort by model count (descending) within each category
|
|
80
|
+
const byModelCount = (a, b) => b.models.size - a.models.size;
|
|
81
|
+
merged.blockers.sort(byModelCount);
|
|
82
|
+
merged.high.sort(byModelCount);
|
|
83
|
+
merged.medium.sort(byModelCount);
|
|
84
|
+
merged.low.sort(byModelCount);
|
|
85
|
+
return merged;
|
|
86
|
+
}
|
|
87
|
+
/** Cluster similar findings together using greedy linear clustering. */
|
|
88
|
+
_clusterFindings(findings) {
|
|
89
|
+
const clusters = [];
|
|
90
|
+
for (const finding of findings) {
|
|
91
|
+
let added = false;
|
|
92
|
+
for (const cluster of clusters) {
|
|
93
|
+
if (this._shouldCluster(finding, cluster)) {
|
|
94
|
+
cluster.findings.push(finding);
|
|
95
|
+
cluster.models.add(finding.model);
|
|
96
|
+
added = true;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (!added) {
|
|
101
|
+
const cluster = {
|
|
102
|
+
findings: [finding],
|
|
103
|
+
models: new Set([finding.model]),
|
|
104
|
+
};
|
|
105
|
+
clusters.push(cluster);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return clusters;
|
|
109
|
+
}
|
|
110
|
+
/** Check if a finding should be added to a cluster. */
|
|
111
|
+
_shouldCluster(finding, cluster) {
|
|
112
|
+
for (const existing of cluster.findings) {
|
|
113
|
+
if (findingsMatch(finding, existing, this.similarityThreshold)) {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
/** Detect disagreements between models (severity disagreements >= 2 levels). */
|
|
120
|
+
_detectConflicts(clusters) {
|
|
121
|
+
const conflicts = [];
|
|
122
|
+
const sevValues = { S0: 0, S1: 1, S2: 2, S3: 3 };
|
|
123
|
+
for (const cluster of clusters) {
|
|
124
|
+
if (cluster.findings.length < 2)
|
|
125
|
+
continue;
|
|
126
|
+
const severities = new Set(cluster.findings.map((f) => f.severity));
|
|
127
|
+
if (severities.size > 1) {
|
|
128
|
+
const sevNums = [...severities].map((s) => sevValues[s] ?? 3);
|
|
129
|
+
if (Math.max(...sevNums) - Math.min(...sevNums) >= 2) {
|
|
130
|
+
const rep = clusterRepresentative(cluster);
|
|
131
|
+
conflicts.push({
|
|
132
|
+
title: rep.title,
|
|
133
|
+
findings: cluster.findings,
|
|
134
|
+
conflict_type: 'severity',
|
|
135
|
+
details: `Models disagree on severity: ${JSON.stringify([...severities])}`,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return conflicts;
|
|
141
|
+
}
|
|
142
|
+
/** Aggregate unique patches from all clusters, prioritizing consensus. */
|
|
143
|
+
_aggregatePatches(clusters) {
|
|
144
|
+
const patches = [];
|
|
145
|
+
const seen = new Set();
|
|
146
|
+
// Sort clusters by model count descending (consensus first)
|
|
147
|
+
const sorted = [...clusters].sort((a, b) => b.models.size - a.models.size);
|
|
148
|
+
for (const cluster of sorted) {
|
|
149
|
+
for (const patch of clusterPatches(cluster)) {
|
|
150
|
+
const key = `${patch.path}|${patch.diff.slice(0, 100)}`;
|
|
151
|
+
if (!seen.has(key)) {
|
|
152
|
+
seen.add(key);
|
|
153
|
+
patches.push(patch);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return patches;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// ---------------------------------------------------------------------------
|
|
161
|
+
// Serialisation helper
|
|
162
|
+
// ---------------------------------------------------------------------------
|
|
163
|
+
/** Serialize a FindingCluster to a plain JSON-safe object. */
|
|
164
|
+
function clusterToDict(cluster) {
|
|
165
|
+
const rep = clusterRepresentative(cluster);
|
|
166
|
+
return {
|
|
167
|
+
is_consensus: isConsensus(cluster),
|
|
168
|
+
models: [...cluster.models],
|
|
169
|
+
severity: clusterSeverity(cluster),
|
|
170
|
+
representative: {
|
|
171
|
+
title: rep.title,
|
|
172
|
+
severity: rep.severity,
|
|
173
|
+
confidence: rep.confidence,
|
|
174
|
+
category: rep.category,
|
|
175
|
+
location: rep.location,
|
|
176
|
+
evidence: rep.evidence,
|
|
177
|
+
recommendation: rep.recommendation,
|
|
178
|
+
model: rep.model,
|
|
179
|
+
patch: rep.patch ?? null,
|
|
180
|
+
},
|
|
181
|
+
all_findings: cluster.findings.map((f) => ({
|
|
182
|
+
title: f.title,
|
|
183
|
+
severity: f.severity,
|
|
184
|
+
confidence: f.confidence,
|
|
185
|
+
category: f.category,
|
|
186
|
+
location: f.location,
|
|
187
|
+
evidence: f.evidence,
|
|
188
|
+
recommendation: f.recommendation,
|
|
189
|
+
model: f.model,
|
|
190
|
+
patch: f.patch ?? null,
|
|
191
|
+
})),
|
|
192
|
+
patches: clusterPatches(cluster).map((p) => ({
|
|
193
|
+
path: p.path,
|
|
194
|
+
diff: p.diff,
|
|
195
|
+
description: p.description,
|
|
196
|
+
model: p.model,
|
|
197
|
+
})),
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Convert a MergedResult to a plain JSON-serializable object.
|
|
202
|
+
* Sets are converted to arrays.
|
|
203
|
+
*/
|
|
204
|
+
export function mergedResultToDict(merged) {
|
|
205
|
+
return {
|
|
206
|
+
blockers: merged.blockers.map(clusterToDict),
|
|
207
|
+
high: merged.high.map(clusterToDict),
|
|
208
|
+
medium: merged.medium.map(clusterToDict),
|
|
209
|
+
low: merged.low.map(clusterToDict),
|
|
210
|
+
consensus: merged.consensus.map(clusterToDict),
|
|
211
|
+
unique_by_model: Object.fromEntries(Object.entries(merged.unique_by_model).map(([model, findings]) => [
|
|
212
|
+
model,
|
|
213
|
+
findings.map((f) => ({
|
|
214
|
+
title: f.title,
|
|
215
|
+
severity: f.severity,
|
|
216
|
+
confidence: f.confidence,
|
|
217
|
+
category: f.category,
|
|
218
|
+
location: f.location,
|
|
219
|
+
evidence: f.evidence,
|
|
220
|
+
recommendation: f.recommendation,
|
|
221
|
+
model: f.model,
|
|
222
|
+
patch: f.patch ?? null,
|
|
223
|
+
})),
|
|
224
|
+
])),
|
|
225
|
+
conflicts: merged.conflicts.map((c) => ({
|
|
226
|
+
title: c.title,
|
|
227
|
+
type: c.conflict_type,
|
|
228
|
+
details: c.details,
|
|
229
|
+
findings: c.findings.map((f) => ({
|
|
230
|
+
title: f.title,
|
|
231
|
+
severity: f.severity,
|
|
232
|
+
confidence: f.confidence,
|
|
233
|
+
category: f.category,
|
|
234
|
+
location: f.location,
|
|
235
|
+
evidence: f.evidence,
|
|
236
|
+
recommendation: f.recommendation,
|
|
237
|
+
model: f.model,
|
|
238
|
+
patch: f.patch ?? null,
|
|
239
|
+
})),
|
|
240
|
+
})),
|
|
241
|
+
patches: merged.patches.map((p) => ({
|
|
242
|
+
path: p.path,
|
|
243
|
+
diff: p.diff,
|
|
244
|
+
description: p.description,
|
|
245
|
+
model: p.model,
|
|
246
|
+
})),
|
|
247
|
+
questions: merged.questions,
|
|
248
|
+
summaries: merged.summaries,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=merge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base model interface and subprocess runner.
|
|
3
|
+
*
|
|
4
|
+
* Ported from triage_cli/models/base.py
|
|
5
|
+
*/
|
|
6
|
+
import { type ModelResult, type ScanContext } from '../types.js';
|
|
7
|
+
export declare abstract class BaseModel {
|
|
8
|
+
name: string;
|
|
9
|
+
cmdEnvVar: string;
|
|
10
|
+
defaultCmd: string[];
|
|
11
|
+
constructor();
|
|
12
|
+
/** Get the command to use for this model (env override > default). */
|
|
13
|
+
get command(): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Run analysis using this model.
|
|
16
|
+
*
|
|
17
|
+
* Builds prompt, saves it for debugging, calls _runModel, parses the
|
|
18
|
+
* result, saves parsed JSON to resultsDir, returns ModelResult.
|
|
19
|
+
*/
|
|
20
|
+
analyze(prompt: string, context: ScanContext, resultsDir: string, timeout?: number, nice?: number): Promise<ModelResult>;
|
|
21
|
+
/** Build the full prompt string from the template and scan context. */
|
|
22
|
+
buildPrompt(prompt: string, context: ScanContext): string;
|
|
23
|
+
/**
|
|
24
|
+
* Parse raw model output into a ModelResult.
|
|
25
|
+
*
|
|
26
|
+
* Tries in order:
|
|
27
|
+
* 1. JSON inside ```json ... ``` blocks
|
|
28
|
+
* 2. JSON inside ``` ... ``` blocks
|
|
29
|
+
* 3. Raw JSON parse of entire output
|
|
30
|
+
* 4. First `{...}` match in the string
|
|
31
|
+
*/
|
|
32
|
+
parseOutput(output: string): ModelResult;
|
|
33
|
+
/** Serialize a ModelResult to a plain object for JSON saving. */
|
|
34
|
+
private _resultToDict;
|
|
35
|
+
/** Run the model and return raw string output. Subclasses implement this. */
|
|
36
|
+
abstract _runModel(prompt: string, timeout: number, nice: number): Promise<string>;
|
|
37
|
+
}
|
|
38
|
+
export declare abstract class SubprocessModel extends BaseModel {
|
|
39
|
+
/**
|
|
40
|
+
* Run model via subprocess.
|
|
41
|
+
*
|
|
42
|
+
* - Writes prompt to a temp file (for debugging / codex adapter)
|
|
43
|
+
* - Builds command via _buildCommand()
|
|
44
|
+
* - Applies env overrides (undefined value = delete key)
|
|
45
|
+
* - Spawns with detached:true so we can kill the whole process group
|
|
46
|
+
* - Passes prompt via stdin
|
|
47
|
+
* - Detects auth/quota errors in stderr
|
|
48
|
+
* - Kills process group on error or cancellation
|
|
49
|
+
* - Cleans up temp file in finally
|
|
50
|
+
*/
|
|
51
|
+
_runModel(prompt: string, timeout: number, nice: number): Promise<string>;
|
|
52
|
+
/**
|
|
53
|
+
* Safely kill the process group that was created with detached:true.
|
|
54
|
+
* Because detached:true guarantees PGID == proc.pid, we negate the PID.
|
|
55
|
+
* Never targets PID <= 1 (init / our own group).
|
|
56
|
+
*/
|
|
57
|
+
private _killProcessGroup;
|
|
58
|
+
/**
|
|
59
|
+
* Build the command and env overrides for this model.
|
|
60
|
+
*
|
|
61
|
+
* @param promptFile Path to temp file containing the prompt text.
|
|
62
|
+
* Most adapters ignore this (they use stdin).
|
|
63
|
+
* The Codex adapter reads it and passes the text as an arg.
|
|
64
|
+
* @returns `cmd` — argument list (no shell, no bash -c);
|
|
65
|
+
* `env` — overrides (undefined value = delete from env)
|
|
66
|
+
*/
|
|
67
|
+
abstract _buildCommand(promptFile: string): {
|
|
68
|
+
cmd: string[];
|
|
69
|
+
env: Record<string, string | undefined>;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/models/base.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,WAAW,EAGjB,MAAM,aAAa,CAAC;AA6CrB,8BAAsB,SAAS;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;;IAQrB,sEAAsE;IACtE,IAAI,OAAO,IAAI,MAAM,EAAE,CAItB;IAED;;;;;OAKG;IACG,OAAO,CACX,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,EACpB,UAAU,EAAE,MAAM,EAClB,OAAO,SAAM,EACb,IAAI,SAAK,GACR,OAAO,CAAC,WAAW,CAAC;IAsCvB,uEAAuE;IACvE,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,MAAM;IAqDzD;;;;;;;;OAQG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW;IAwCxC,iEAAiE;IACjE,OAAO,CAAC,aAAa;IAWrB,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CACnF;AAMD,8BAAsB,eAAgB,SAAQ,SAAS;IACrD;;;;;;;;;;;OAWG;IACY,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA2GxF;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAczB;;;;;;;;OAQG;IACH,QAAQ,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG;QAC1C,GAAG,EAAE,MAAM,EAAE,CAAC;QACd,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;KACzC;CACF"}
|