@lbroth/rothunter 1.0.0-rc.1
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 +141 -0
- package/dist/adapters/llm.d.ts +68 -0
- package/dist/adapters/llm.d.ts.map +1 -0
- package/dist/adapters/llm.js +189 -0
- package/dist/adapters/llm.js.map +1 -0
- package/dist/config.d.ts +37 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +81 -0
- package/dist/config.js.map +1 -0
- package/dist/detector-registry.d.ts +32 -0
- package/dist/detector-registry.d.ts.map +1 -0
- package/dist/detector-registry.js +74 -0
- package/dist/detector-registry.js.map +1 -0
- package/dist/detectors/api-race.d.ts +6 -0
- package/dist/detectors/api-race.d.ts.map +1 -0
- package/dist/detectors/api-race.js +222 -0
- package/dist/detectors/api-race.js.map +1 -0
- package/dist/detectors/bad-config.d.ts +6 -0
- package/dist/detectors/bad-config.d.ts.map +1 -0
- package/dist/detectors/bad-config.js +529 -0
- package/dist/detectors/bad-config.js.map +1 -0
- package/dist/detectors/console-log-prod.d.ts +6 -0
- package/dist/detectors/console-log-prod.d.ts.map +1 -0
- package/dist/detectors/console-log-prod.js +72 -0
- package/dist/detectors/console-log-prod.js.map +1 -0
- package/dist/detectors/dead-api.d.ts +10 -0
- package/dist/detectors/dead-api.d.ts.map +1 -0
- package/dist/detectors/dead-api.js +115 -0
- package/dist/detectors/dead-api.js.map +1 -0
- package/dist/detectors/dead-export.d.ts +12 -0
- package/dist/detectors/dead-export.d.ts.map +1 -0
- package/dist/detectors/dead-export.js +140 -0
- package/dist/detectors/dead-export.js.map +1 -0
- package/dist/detectors/dead-handler.d.ts +12 -0
- package/dist/detectors/dead-handler.d.ts.map +1 -0
- package/dist/detectors/dead-handler.js +40 -0
- package/dist/detectors/dead-handler.js.map +1 -0
- package/dist/detectors/dead-module.d.ts +14 -0
- package/dist/detectors/dead-module.d.ts.map +1 -0
- package/dist/detectors/dead-module.js +50 -0
- package/dist/detectors/dead-module.js.map +1 -0
- package/dist/detectors/deep-nesting.d.ts +12 -0
- package/dist/detectors/deep-nesting.d.ts.map +1 -0
- package/dist/detectors/deep-nesting.js +133 -0
- package/dist/detectors/deep-nesting.js.map +1 -0
- package/dist/detectors/duplicate-function.d.ts +9 -0
- package/dist/detectors/duplicate-function.d.ts.map +1 -0
- package/dist/detectors/duplicate-function.js +199 -0
- package/dist/detectors/duplicate-function.js.map +1 -0
- package/dist/detectors/duplicate-type.d.ts +9 -0
- package/dist/detectors/duplicate-type.d.ts.map +1 -0
- package/dist/detectors/duplicate-type.js +166 -0
- package/dist/detectors/duplicate-type.js.map +1 -0
- package/dist/detectors/hot-hub-file.d.ts +11 -0
- package/dist/detectors/hot-hub-file.d.ts.map +1 -0
- package/dist/detectors/hot-hub-file.js +42 -0
- package/dist/detectors/hot-hub-file.js.map +1 -0
- package/dist/detectors/long-file.d.ts +12 -0
- package/dist/detectors/long-file.d.ts.map +1 -0
- package/dist/detectors/long-file.js +82 -0
- package/dist/detectors/long-file.js.map +1 -0
- package/dist/detectors/long-function.d.ts +12 -0
- package/dist/detectors/long-function.d.ts.map +1 -0
- package/dist/detectors/long-function.js +45 -0
- package/dist/detectors/long-function.js.map +1 -0
- package/dist/detectors/magic-numbers.d.ts +10 -0
- package/dist/detectors/magic-numbers.d.ts.map +1 -0
- package/dist/detectors/magic-numbers.js +332 -0
- package/dist/detectors/magic-numbers.js.map +1 -0
- package/dist/detectors/mutable-globals.d.ts +6 -0
- package/dist/detectors/mutable-globals.d.ts.map +1 -0
- package/dist/detectors/mutable-globals.js +95 -0
- package/dist/detectors/mutable-globals.js.map +1 -0
- package/dist/detectors/mutation.d.ts +11 -0
- package/dist/detectors/mutation.d.ts.map +1 -0
- package/dist/detectors/mutation.js +397 -0
- package/dist/detectors/mutation.js.map +1 -0
- package/dist/detectors/public-any.d.ts +6 -0
- package/dist/detectors/public-any.d.ts.map +1 -0
- package/dist/detectors/public-any.js +52 -0
- package/dist/detectors/public-any.js.map +1 -0
- package/dist/detectors/race-condition.d.ts +6 -0
- package/dist/detectors/race-condition.d.ts.map +1 -0
- package/dist/detectors/race-condition.js +608 -0
- package/dist/detectors/race-condition.js.map +1 -0
- package/dist/detectors/shared-db-write.d.ts +6 -0
- package/dist/detectors/shared-db-write.d.ts.map +1 -0
- package/dist/detectors/shared-db-write.js +656 -0
- package/dist/detectors/shared-db-write.js.map +1 -0
- package/dist/detectors/silent-catch.d.ts +6 -0
- package/dist/detectors/silent-catch.d.ts.map +1 -0
- package/dist/detectors/silent-catch.js +167 -0
- package/dist/detectors/silent-catch.js.map +1 -0
- package/dist/detectors/similar-functions.d.ts +15 -0
- package/dist/detectors/similar-functions.d.ts.map +1 -0
- package/dist/detectors/similar-functions.js +334 -0
- package/dist/detectors/similar-functions.js.map +1 -0
- package/dist/detectors/skip-tests.d.ts +6 -0
- package/dist/detectors/skip-tests.d.ts.map +1 -0
- package/dist/detectors/skip-tests.js +69 -0
- package/dist/detectors/skip-tests.js.map +1 -0
- package/dist/detectors/todo-comments.d.ts +29 -0
- package/dist/detectors/todo-comments.d.ts.map +1 -0
- package/dist/detectors/todo-comments.js +154 -0
- package/dist/detectors/todo-comments.js.map +1 -0
- package/dist/detectors/unused-deps.d.ts +8 -0
- package/dist/detectors/unused-deps.d.ts.map +1 -0
- package/dist/detectors/unused-deps.js +115 -0
- package/dist/detectors/unused-deps.js.map +1 -0
- package/dist/extraction/api-race-confirmer.d.ts +31 -0
- package/dist/extraction/api-race-confirmer.d.ts.map +1 -0
- package/dist/extraction/api-race-confirmer.js +110 -0
- package/dist/extraction/api-race-confirmer.js.map +1 -0
- package/dist/extraction/llm-confirmer.d.ts +25 -0
- package/dist/extraction/llm-confirmer.d.ts.map +1 -0
- package/dist/extraction/llm-confirmer.js +118 -0
- package/dist/extraction/llm-confirmer.js.map +1 -0
- package/dist/extraction/mutation-confirmer.d.ts +30 -0
- package/dist/extraction/mutation-confirmer.d.ts.map +1 -0
- package/dist/extraction/mutation-confirmer.js +73 -0
- package/dist/extraction/mutation-confirmer.js.map +1 -0
- package/dist/extraction/prompt-chunking.d.ts +37 -0
- package/dist/extraction/prompt-chunking.d.ts.map +1 -0
- package/dist/extraction/prompt-chunking.js +61 -0
- package/dist/extraction/prompt-chunking.js.map +1 -0
- package/dist/extraction/race-confirmer.d.ts +28 -0
- package/dist/extraction/race-confirmer.d.ts.map +1 -0
- package/dist/extraction/race-confirmer.js +68 -0
- package/dist/extraction/race-confirmer.js.map +1 -0
- package/dist/extraction/shared-db-write-confirmer.d.ts +31 -0
- package/dist/extraction/shared-db-write-confirmer.d.ts.map +1 -0
- package/dist/extraction/shared-db-write-confirmer.js +141 -0
- package/dist/extraction/shared-db-write-confirmer.js.map +1 -0
- package/dist/extraction/triage-confirmer.d.ts +59 -0
- package/dist/extraction/triage-confirmer.d.ts.map +1 -0
- package/dist/extraction/triage-confirmer.js +104 -0
- package/dist/extraction/triage-confirmer.js.map +1 -0
- package/dist/graph/cfg.d.ts +45 -0
- package/dist/graph/cfg.d.ts.map +1 -0
- package/dist/graph/cfg.js +198 -0
- package/dist/graph/cfg.js.map +1 -0
- package/dist/graph/decorator-entries.d.ts +2 -0
- package/dist/graph/decorator-entries.d.ts.map +1 -0
- package/dist/graph/decorator-entries.js +89 -0
- package/dist/graph/decorator-entries.js.map +1 -0
- package/dist/graph/entry-points.d.ts +12 -0
- package/dist/graph/entry-points.d.ts.map +1 -0
- package/dist/graph/entry-points.js +282 -0
- package/dist/graph/entry-points.js.map +1 -0
- package/dist/graph/handler-conventions.d.ts +2 -0
- package/dist/graph/handler-conventions.d.ts.map +1 -0
- package/dist/graph/handler-conventions.js +26 -0
- package/dist/graph/handler-conventions.js.map +1 -0
- package/dist/graph/iac-entries.d.ts +2 -0
- package/dist/graph/iac-entries.d.ts.map +1 -0
- package/dist/graph/iac-entries.js +123 -0
- package/dist/graph/iac-entries.js.map +1 -0
- package/dist/graph/import-graph.d.ts +48 -0
- package/dist/graph/import-graph.d.ts.map +1 -0
- package/dist/graph/import-graph.js +86 -0
- package/dist/graph/import-graph.js.map +1 -0
- package/dist/graph/monorepo-detect.d.ts +3 -0
- package/dist/graph/monorepo-detect.d.ts.map +1 -0
- package/dist/graph/monorepo-detect.js +166 -0
- package/dist/graph/monorepo-detect.js.map +1 -0
- package/dist/graph/tsconfig-paths.d.ts +23 -0
- package/dist/graph/tsconfig-paths.d.ts.map +1 -0
- package/dist/graph/tsconfig-paths.js +217 -0
- package/dist/graph/tsconfig-paths.js.map +1 -0
- package/dist/multi-workspace-scanner.d.ts +13 -0
- package/dist/multi-workspace-scanner.d.ts.map +1 -0
- package/dist/multi-workspace-scanner.js +130 -0
- package/dist/multi-workspace-scanner.js.map +1 -0
- package/dist/normalizers/type-normalizer.d.ts +16 -0
- package/dist/normalizers/type-normalizer.d.ts.map +1 -0
- package/dist/normalizers/type-normalizer.js +189 -0
- package/dist/normalizers/type-normalizer.js.map +1 -0
- package/dist/parsers/typescript-parser.d.ts +57 -0
- package/dist/parsers/typescript-parser.d.ts.map +1 -0
- package/dist/parsers/typescript-parser.js +502 -0
- package/dist/parsers/typescript-parser.js.map +1 -0
- package/dist/reporter/json-reporter.d.ts +12 -0
- package/dist/reporter/json-reporter.d.ts.map +1 -0
- package/dist/reporter/json-reporter.js +28 -0
- package/dist/reporter/json-reporter.js.map +1 -0
- package/dist/reporter/markdown-reporter.d.ts +11 -0
- package/dist/reporter/markdown-reporter.d.ts.map +1 -0
- package/dist/reporter/markdown-reporter.js +77 -0
- package/dist/reporter/markdown-reporter.js.map +1 -0
- package/dist/rothunter.d.ts +125 -0
- package/dist/rothunter.d.ts.map +1 -0
- package/dist/rothunter.js +1038 -0
- package/dist/rothunter.js.map +1 -0
- package/dist/server/false-positives.d.ts +34 -0
- package/dist/server/false-positives.d.ts.map +1 -0
- package/dist/server/false-positives.js +85 -0
- package/dist/server/false-positives.js.map +1 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +1529 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/marked-to-fix.d.ts +16 -0
- package/dist/server/marked-to-fix.d.ts.map +1 -0
- package/dist/server/marked-to-fix.js +36 -0
- package/dist/server/marked-to-fix.js.map +1 -0
- package/dist/server/scan-store.d.ts +147 -0
- package/dist/server/scan-store.d.ts.map +1 -0
- package/dist/server/scan-store.js +291 -0
- package/dist/server/scan-store.js.map +1 -0
- package/dist/server/settings-store.d.ts +28 -0
- package/dist/server/settings-store.d.ts.map +1 -0
- package/dist/server/settings-store.js +46 -0
- package/dist/server/settings-store.js.map +1 -0
- package/dist/server/workspace-store.d.ts +39 -0
- package/dist/server/workspace-store.d.ts.map +1 -0
- package/dist/server/workspace-store.js +108 -0
- package/dist/server/workspace-store.js.map +1 -0
- package/dist/types/detector-input.d.ts +37 -0
- package/dist/types/detector-input.d.ts.map +1 -0
- package/dist/types/detector-input.js +2 -0
- package/dist/types/detector-input.js.map +1 -0
- package/dist/types.d.ts +110 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/clustering.d.ts +14 -0
- package/dist/utils/clustering.d.ts.map +1 -0
- package/dist/utils/clustering.js +56 -0
- package/dist/utils/clustering.js.map +1 -0
- package/dist/utils/gitignore.d.ts +32 -0
- package/dist/utils/gitignore.d.ts.map +1 -0
- package/dist/utils/gitignore.js +122 -0
- package/dist/utils/gitignore.js.map +1 -0
- package/dist/utils/hash.d.ts +11 -0
- package/dist/utils/hash.d.ts.map +1 -0
- package/dist/utils/hash.js +14 -0
- package/dist/utils/hash.js.map +1 -0
- package/dist/utils/ignore-annotation.d.ts +28 -0
- package/dist/utils/ignore-annotation.d.ts.map +1 -0
- package/dist/utils/ignore-annotation.js +46 -0
- package/dist/utils/ignore-annotation.js.map +1 -0
- package/dist/utils/llm-json.d.ts +2 -0
- package/dist/utils/llm-json.d.ts.map +1 -0
- package/dist/utils/llm-json.js +53 -0
- package/dist/utils/llm-json.js.map +1 -0
- package/dist/utils/logger.d.ts +3 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +4 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/project-conventions.d.ts +2 -0
- package/dist/utils/project-conventions.d.ts.map +1 -0
- package/dist/utils/project-conventions.js +108 -0
- package/dist/utils/project-conventions.js.map +1 -0
- package/dist/utils/regex.d.ts +9 -0
- package/dist/utils/regex.d.ts.map +1 -0
- package/dist/utils/regex.js +11 -0
- package/dist/utils/regex.js.map +1 -0
- package/dist/utils/snippet.d.ts +20 -0
- package/dist/utils/snippet.d.ts.map +1 -0
- package/dist/utils/snippet.js +28 -0
- package/dist/utils/snippet.js.map +1 -0
- package/dist/utils/source-reader.d.ts +19 -0
- package/dist/utils/source-reader.d.ts.map +1 -0
- package/dist/utils/source-reader.js +32 -0
- package/dist/utils/source-reader.js.map +1 -0
- package/logo.png +0 -0
- package/package.json +92 -0
- package/scripts/start-llm.mjs +161 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const SEVERITY_ORDER = { high: 3, medium: 2, low: 1 };
|
|
2
|
+
export function renderMarkdownReport(findings, opts) {
|
|
3
|
+
const visible = findings.filter((f) => f.confidence >= opts.minConfidence);
|
|
4
|
+
const hidden = findings.length - visible.length;
|
|
5
|
+
visible.sort((a, b) => {
|
|
6
|
+
const sev = SEVERITY_ORDER[b.severity] - SEVERITY_ORDER[a.severity];
|
|
7
|
+
if (sev !== 0)
|
|
8
|
+
return sev;
|
|
9
|
+
return b.confidence - a.confidence;
|
|
10
|
+
});
|
|
11
|
+
const lines = [];
|
|
12
|
+
lines.push('# RotHunter audit');
|
|
13
|
+
lines.push('');
|
|
14
|
+
lines.push(`- Workspace: \`${opts.workspaceRoot}\``);
|
|
15
|
+
lines.push(`- Generated: ${opts.generatedAt.toISOString()}`);
|
|
16
|
+
lines.push(`- Symbols scanned: ${opts.symbolCount}`);
|
|
17
|
+
lines.push(`- Duration: ${(opts.durationMs / 1000).toFixed(1)}s`);
|
|
18
|
+
lines.push(`- Findings: ${visible.length} (shown) / ${findings.length} (total)`);
|
|
19
|
+
lines.push(`- Min confidence: ${opts.minConfidence}`);
|
|
20
|
+
if (hidden > 0) {
|
|
21
|
+
lines.push(`- Hidden by confidence threshold: ${hidden}`);
|
|
22
|
+
}
|
|
23
|
+
lines.push('');
|
|
24
|
+
if (visible.length === 0) {
|
|
25
|
+
lines.push('_No findings above the confidence threshold._');
|
|
26
|
+
return lines.join('\n');
|
|
27
|
+
}
|
|
28
|
+
const byDetector = new Map();
|
|
29
|
+
for (const f of visible) {
|
|
30
|
+
const list = byDetector.get(f.detectorId) ?? [];
|
|
31
|
+
list.push(f);
|
|
32
|
+
byDetector.set(f.detectorId, list);
|
|
33
|
+
}
|
|
34
|
+
for (const [detectorId, list] of byDetector) {
|
|
35
|
+
lines.push(`## ${detectorId} (${list.length})`);
|
|
36
|
+
lines.push('');
|
|
37
|
+
for (const f of list) {
|
|
38
|
+
lines.push(`### ${severityIcon(f.severity)} ${f.title}`);
|
|
39
|
+
lines.push('');
|
|
40
|
+
lines.push(`> confidence ${f.confidence.toFixed(2)} · layer ${f.layer} · fingerprint \`${f.fingerprint}\``);
|
|
41
|
+
lines.push('');
|
|
42
|
+
lines.push(f.description);
|
|
43
|
+
lines.push('');
|
|
44
|
+
if (f.evidence.length > 0) {
|
|
45
|
+
lines.push('**Evidence:**');
|
|
46
|
+
lines.push('');
|
|
47
|
+
for (const ev of f.evidence) {
|
|
48
|
+
lines.push(`- \`${ev.file}:${ev.range.startLine}\``);
|
|
49
|
+
lines.push(' ```typescript');
|
|
50
|
+
for (const line of ev.snippet.split('\n')) {
|
|
51
|
+
lines.push(` ${line}`);
|
|
52
|
+
}
|
|
53
|
+
lines.push(' ```');
|
|
54
|
+
}
|
|
55
|
+
lines.push('');
|
|
56
|
+
}
|
|
57
|
+
if (f.suggestion) {
|
|
58
|
+
lines.push(`**Suggestion:** ${f.suggestion}`);
|
|
59
|
+
lines.push('');
|
|
60
|
+
}
|
|
61
|
+
lines.push('---');
|
|
62
|
+
lines.push('');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return lines.join('\n');
|
|
66
|
+
}
|
|
67
|
+
function severityIcon(s) {
|
|
68
|
+
switch (s) {
|
|
69
|
+
case 'high':
|
|
70
|
+
return '[high]';
|
|
71
|
+
case 'medium':
|
|
72
|
+
return '[med]';
|
|
73
|
+
case 'low':
|
|
74
|
+
return '[low]';
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=markdown-reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-reporter.js","sourceRoot":"","sources":["../../src/reporter/markdown-reporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { type ParseOptions } from './parsers/typescript-parser.js';
|
|
2
|
+
import type { Finding, SymbolRecord } from './types.js';
|
|
3
|
+
import type { LlmClient } from './adapters/llm.js';
|
|
4
|
+
export interface RotHunterRunOptions extends ParseOptions {
|
|
5
|
+
/** Drop a finding below `severity:'low'` when post-LLM confidence falls under this threshold. */
|
|
6
|
+
llmRejectionThreshold?: number;
|
|
7
|
+
/** Override the LLM client (tests, alternative model pools). Production uses the default LlmClient. */
|
|
8
|
+
llm?: LlmClient;
|
|
9
|
+
/**
|
|
10
|
+
* Optional allow-list of detector ids. When set, findings from detectors
|
|
11
|
+
* outside this list are dropped BEFORE the LLM confirmation pass — the
|
|
12
|
+
* caller will never see them in the report, so the LLM cost is wasted.
|
|
13
|
+
* Mirrors the `--detectors` CLI flag.
|
|
14
|
+
*/
|
|
15
|
+
detectorsAllow?: Set<string>;
|
|
16
|
+
/** Optional deny-list of detector ids — mirrors `--no-detectors`. */
|
|
17
|
+
detectorsDeny?: Set<string>;
|
|
18
|
+
/**
|
|
19
|
+
* Number of LLM verdicts in flight at once. 1 = sequential
|
|
20
|
+
* (original behaviour, safe). 4-8 is a good default on llama.cpp run
|
|
21
|
+
* with `--parallel N -cb` (continuous batching) or on vLLM (dynamic
|
|
22
|
+
* batching is on by default).
|
|
23
|
+
*
|
|
24
|
+
* Defaults to `ROTHUNTER_LLM_CONCURRENCY` env var, then 1.
|
|
25
|
+
*/
|
|
26
|
+
llmConcurrency?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Confidence floor at which a negative LLM verdict routes a finding
|
|
29
|
+
* into the auto-FP bucket. Defaults to `LLM_FP_THRESHOLD` (0.6) — set
|
|
30
|
+
* lower to be more aggressive (almost every "intentional" LLM call
|
|
31
|
+
* auto-FPs) or higher (only very-confident verdicts route, the rest
|
|
32
|
+
* stay open at degraded confidence).
|
|
33
|
+
*/
|
|
34
|
+
llmAutoFpThreshold?: number;
|
|
35
|
+
/**
|
|
36
|
+
* Optional callback invoked at scan checkpoints. Used by the rothunter
|
|
37
|
+
* HTTP server to stream live progress over SSE. Never throws — exceptions
|
|
38
|
+
* inside the callback are caught and logged.
|
|
39
|
+
*/
|
|
40
|
+
onProgress?: (event: ScanProgressEvent) => void;
|
|
41
|
+
/**
|
|
42
|
+
* Optional cooperative cancellation. The orchestrator checks
|
|
43
|
+
* `abortSignal.aborted` between LLM verdict tasks and aborts the
|
|
44
|
+
* worker pool when the signal fires. Used by the HTTP server's
|
|
45
|
+
* /api/scans/:scanId/cancel endpoint to free the scan slot promptly
|
|
46
|
+
* instead of relying on the (lossy) "throw inside onProgress" path.
|
|
47
|
+
*/
|
|
48
|
+
abortSignal?: AbortSignal;
|
|
49
|
+
}
|
|
50
|
+
export type ScanProgressEvent = {
|
|
51
|
+
state: 'parsing';
|
|
52
|
+
files?: number;
|
|
53
|
+
symbols?: number;
|
|
54
|
+
} | {
|
|
55
|
+
state: 'detecting';
|
|
56
|
+
detector: string;
|
|
57
|
+
} | {
|
|
58
|
+
state: 'llm-start';
|
|
59
|
+
total: number;
|
|
60
|
+
} | {
|
|
61
|
+
state: 'llm-verdict';
|
|
62
|
+
done: number;
|
|
63
|
+
total: number;
|
|
64
|
+
detectorId: string;
|
|
65
|
+
race: boolean;
|
|
66
|
+
confidence: number;
|
|
67
|
+
reason: string;
|
|
68
|
+
latencyMs: number;
|
|
69
|
+
cluster?: string;
|
|
70
|
+
} | {
|
|
71
|
+
state: 'done';
|
|
72
|
+
findings: number;
|
|
73
|
+
durationMs: number;
|
|
74
|
+
};
|
|
75
|
+
export interface RotHunterResult {
|
|
76
|
+
symbols: SymbolRecord[];
|
|
77
|
+
findings: Finding[];
|
|
78
|
+
durationMs: number;
|
|
79
|
+
}
|
|
80
|
+
export declare class RotHunter {
|
|
81
|
+
private parser;
|
|
82
|
+
private normalizer;
|
|
83
|
+
private detectors;
|
|
84
|
+
run(opts: RotHunterRunOptions): Promise<RotHunterResult>;
|
|
85
|
+
private runLlmConfirmation;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Apply a "cluster-style" LLM verdict to a finding. Used for the four
|
|
89
|
+
* detectors whose LLM confirmer returns a positive/negative boolean
|
|
90
|
+
* with a confidence: api-race / shared-db-write / race-condition (race
|
|
91
|
+
* vs safe) and mutation (bug-shaped vs intentional — caller maps
|
|
92
|
+
* `!intentional` to `positive`). Shared body keeps the score/severity/
|
|
93
|
+
* description bookkeeping in one place. Duplicate-type / duplicate-
|
|
94
|
+
* function use a different formula (1 - conf) and stay inline.
|
|
95
|
+
*/
|
|
96
|
+
export declare function applyClusterVerdict(finding: Finding, verdict: {
|
|
97
|
+
positive: boolean;
|
|
98
|
+
confidence: number;
|
|
99
|
+
reason: string;
|
|
100
|
+
}, opts: {
|
|
101
|
+
threshold: number;
|
|
102
|
+
positiveLabel: string;
|
|
103
|
+
negativeLabel: string;
|
|
104
|
+
/** Auto-FP routing floor. Defaults to LLM_FP_THRESHOLD (0.6). */
|
|
105
|
+
autoFpThreshold?: number;
|
|
106
|
+
}): void;
|
|
107
|
+
/**
|
|
108
|
+
* Verdict-confidence floor at which a negative LLM verdict moves a
|
|
109
|
+
* finding into the auto-FP bucket. Set low (0.6) so any reasonably
|
|
110
|
+
* confident "intentional / FP" verdict routes the finding out of the
|
|
111
|
+
* open list — the operator's stated preference is "if the LLM says
|
|
112
|
+
* FP, treat it as auto FP, I'll un-mark if it's wrong". Below 0.6 the
|
|
113
|
+
* LLM is genuinely undecided and the deterministic finding stays in
|
|
114
|
+
* the open list at degraded confidence.
|
|
115
|
+
*/
|
|
116
|
+
export declare const LLM_FP_THRESHOLD = 0.6;
|
|
117
|
+
/**
|
|
118
|
+
* Build per-detector structural context to attach to a TriageConfirmer
|
|
119
|
+
* call. The shape is free-form text — the LLM reads it alongside the
|
|
120
|
+
* primary evidence snippet — so we can evolve enrichment without
|
|
121
|
+
* version-coupling the triage schema. Returns `undefined` when no
|
|
122
|
+
* useful context is available so the prompt stays compact.
|
|
123
|
+
*/
|
|
124
|
+
export declare function buildTriageContext(finding: Finding, symbolById: Map<string, SymbolRecord>, workspaceRoot?: string): string | undefined;
|
|
125
|
+
//# sourceMappingURL=rothunter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rothunter.d.ts","sourceRoot":"","sources":["../src/rothunter.ts"],"names":[],"mappings":"AA2BA,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAOrF,OAAO,KAAK,EAAY,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAKnD,MAAM,WAAW,mBAAoB,SAAQ,YAAY;IACvD,iGAAiG;IACjG,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,uGAAuG;IACvG,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,qEAAqE;IACrE,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5B;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAChD;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAGD,MAAM,MAAM,iBAAiB,GACzB;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,KAAK,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACjK;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5D,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,UAAU,CAAwB;IAC1C,OAAO,CAAC,SAAS,CAGf;IAEI,GAAG,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,eAAe,CAAC;YAoOhD,kBAAkB;CAsTjC;AAgMD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAClE,IAAI,EAAE;IACJ,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GACA,IAAI,CA2BN;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EACrC,aAAa,CAAC,EAAE,MAAM,GACrB,MAAM,GAAG,SAAS,CAuBpB"}
|