mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 03:49:26 +00:00
benchmarks/valid/hunter_arm.py runs the shipped deep-mode tool hunter (tool_hunter.run_tool_hunter via resolve_hunter_client) over each frozen change off-cluster: detached worktree at head with git hooks disabled, hotspots scoped to the changed files, instrument rule on every hotspot (bytes read printed, empty or unreadable fails the change loudly), model id from the config resolver, family from the taxonomy, never from the label. Records land in the exact shape score.py reads (push.admission.defects with locations), resumable per change. `combine` joins arm (a) replay records with arm (b) hunter records per change id, dedupes defects by (path, line, family), keeps (a)'s instrument, records which arms were present, and writes a file score.py loads directly. 9 offline tests (stub hunter, real scorer), 53 green with the benchmark tests. No network, no key handling, no live run. Co-Authored-By: Claude Fable 5.1 <[email protected]>
5.0 KiB
5.0 KiB
Tasks: valid detection benchmark
Order is dependency order. Each task is small enough to review on its own. New code under
benchmarks/valid/. Implementation goes through Codex, gated here.
Group 1 - positive catalog (fix-site, no SZZ)
- 1.1
benchmarks/valid/catalog.py: given sourced advisories (reusesource.py/draft.pyoutput), build candidate positive cases by fix site. Wrapextract.fix_sites()+pairs/materialize.py; read the pre-fix function atparentand the post-fix function atcommit. Must not callintroducingorlast_touch. Emit the[[case]]catalog in the design schema. (R1) - 1.2 Filter to Python and JS/TS only; attach
languageandfamily/cwe. (scope decision) - 1.3 Offline test: a fixture commit yields one case with the correct pre/post functions and
method = "fix_site"; assert SZZ methods are never invoked.
Group 2 - LLM verification driver
- 2.1
benchmarks/valid/verify.py: one DeepSeek call per case via the shipped provider (off-cluster). Confirm vulnerable-pre-fix, fix-addresses-it, reachable-in-repo; name the entry point; return confidence. Print bytes read per function before the call; reject a verdict on an empty read. (R3, instrument rule) - 2.2 Emit the verification record (design schema) to
verification.json;verdict = "accepted"only when all three checks pass. Reachability here is the app-shaped filter. (R2, R3) - 2.3 Human spot-check hook: a small CLI to record accept/reject + reviewer + date per case into the same record. (R3)
- 2.4 Offline test with a stub model: a case with all three true and a human accept becomes
accepted; any false, or a human reject, does not.
Group 3 - negatives and assembly
- 3.1
benchmarks/valid/assemble.py: draw negatives withextract.draw_ordinary()from the accepted positives' repos, at least 20x, excluding the fix. (R4) - 3.2 Freeze accepted positives + negatives into a
pool.toml-shaped manifest +freeze-valid.jsondigest; run the held-out guard viaeligibility.normalize. (R5, R8) - 3.3 Offline test: freeze is deterministic (same source -> same digest); held-out guard drops any repo in the used set.
Group 4 - metrics
- 4.1
benchmarks/valid/metrics.py: precision (PPV) with Wilson 95% over positives+negatives. (R7) - 4.2 False alarms per 100 pushes as the presentation of
score.py's false-alarm rate. (R7) - 4.3 Exploit-verified rate: join flagged positives with a search-with-proof run by case
id; report "not yet proved" where absent. (R7) - 4.4 Build the headline string (recall + FP/100 + precision + exploit-verified). (R7)
- 4.5 Offline test on a tiny hand-made record set: all four metrics and intervals match hand calcs.
Group 5 - pilot run (research, local)
- 5.1 Source Python/JS advisories; run
catalog.pyto ~25 candidates. (deliberate, rate-aware) - 5.2 Run
verify.py+ human spot-check to land ~12 accepted positives. - 5.3
assemble.pyfreezes the pilot manifest + negatives (>=20x) + held-out guard. - 5.4
replay.pyon the Docker lane, arm (a): the push hook as shipped (quick + engine, 300 s). Running overnight 2026-10-12; records under~/ousast-results/valid/pilot/long_deadline. - 5.5
score.py+metrics.pyon arm (a): recall, precision, FP/100, exploit-verified, intervals, and the headline, labelled "push hook as shipped". Freeze the run underbenchmarks/measurements/. - 5.6 Write up the pilot: the four numbers for (a), what they mean, the engine-covered rate, and the
target set size from
required_nfor the full ~40-positive benchmark.
Group 6 - hunter arm (the LLM tier required on pre-push)
- 6.1
benchmarks/valid/hunter_arm.py: for each change in the frozen manifest, check outheadin the local clone (detached worktree), build hotspots for the changed files, run the shipped deep-mode armtool_hunter.run_tool_hunterwithresolve_hunter_client()(the hunter that beat overlay 12/14; wiring incli.py_attach_tool_hunter), and emit a recordscore.pycan read: findings go underpush.admission.defectswithfamilyandlocations = [[path, line]](the alerts stream), keyed by change id. Runs off-cluster; the model key never enters a replay container. Honors the instrument rule (bytes read per hotspot, fail loudly on an empty read). - 6.2 Combine arm (a) and arm (b) records per change id and rescore: this is the number the tool is held to (R6). Report (a), (a)+(b), and the difference as the pre-push product gap.
- 6.3 Offline test with a stub hunter: a flagged change joins the (a) record; a missing (b) record leaves (a) unchanged; duplicate ids are rejected.
Out of this spec
- Growing beyond the pilot to the full set (follow-up, once the pipeline is proven).
- Running on kube
ax(blocked on gVisor; Docker lane is enough here). - Any new detection capability, including wiring the hunter into the pre-push hook. That is product
work in
pre-push-safety-net; this spec measures the push path with and without it.