mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 03:49:26 +00:00
DSPy baseline: 2/5 pushes, 4/48 locations, 14 of 90 ordinary pushes flagged, 25 suspicions (3 true), 11 invalid-request failures in shopper and trigger.dev, $6.13. Pilot hunter: 2/5 pushes, 4/48 locations, 99 of 100 ordinary pushes flagged, 594 findings (3 true). Different pushes caught; nothing in trigger.dev. The runner booked usd 0.0 per change so --budget-usd never stopped a run; it now prices every LM call of the change at the registered prices and writes usd into the record. Co-Authored-By: Claude Fable 5.1 <[email protected]>
4.3 KiB
4.3 KiB
Both arms over the frozen access-control training pool, one run each (2026-10-13/14)
Setup
- Pool:
benchmarks/valid/train/pool-train.toml, digest 53f9f364. 5 fix pushes with 48 verified locations (reviewer mc, all accepted), 100 ordinary pushes, 20 per fix, from the same 5 repositories: three Jenkins plugins (Java), shopper (PHP), trigger.dev (TypeScript). - Arm DSPy:
python -m openultrasast.hunt.cli run, the baseline instruction, every annotation on, ReAct over the repository tools,--max-iters 8, own empty response cache. Program id e79db45f. The producers were version 1 (before537b61e): the hunks annotation did not show where a push removed lines. - Arm hunter:
benchmarks/valid/hunter_arm.py, classifier on, as in the pilot. - Runs: DSPy 21:39 to 00:29, hunter 00:29 to 01:08, one after the other on the training clones.
- Analysis:
analyse.pyin this folder; a push is caught when any verified location of its fix is caught (benchmarks.unseen.score.catcheson the per-location view, asbenchmarks/valid/metrics.pyscores), a location when its own view is caught. Instrument failures and unparsed hunts stay in the denominators.benchmarks.valid.metricsrefused the DSPy run (more than 5% instrument failures);metrics_hunter.jsonis its output for the hunter arm.
Results
| DSPy baseline | Pilot hunter | |
|---|---|---|
| Pushes caught | 2 of 5 (Wilson 12-77%) | 2 of 5 (Wilson 12-77%) |
| Locations caught | 4 of 48 (Wilson 3-20%) | 4 of 48 (Wilson 3-20%) |
| Per repository (locations) | dependency-track 0/3, job-import 2/2, p4 2/5, shopper 0/31, trigger.dev 0/7 | dependency-track 2/3, job-import 0/2, p4 0/5, shopper 2/31, trigger.dev 0/7 |
| Ordinary pushes flagged | 14 of 90 scanned = 15.6 per 100 (Wilson 9-24) | 99 of 100 = 99 per 100 (Wilson 95-100) |
| Suspicions raised, true | 25, 3 true (12%) | 594, 3 true (0.5%) |
| Instrument failures | 11 of 105 (10.5%), all LMInvalidRequestError |
0 |
| Unparseable final answer / loop step | 2 / 12 (the loop fix of 455637b kept those 12 hunts) |
0 / 0 |
| Cost | $6.13 at the registered deepseek-flash prices: 28.9M prompt tokens (61% cached), 0.70M completion | engine only |
- The two arms catch different pushes. DSPy: job-import and p4. Hunter: dependency-track and shopper. Together 4 of 5; nothing in trigger.dev from either. Every true suspicion of both arms is in the access_control family.
- The pilot hunter is not a hook on this pool. It flags 99 of 100 ordinary pushes with 594 findings, 3 of them
true. 348 of its findings carry the family
unknown. - The DSPy baseline is far quieter (25 suspicions, 15.6 flagged ordinary pushes per 100) at the same recall, but
its 11 failed hunts sit entirely in shopper and trigger.dev, the two repositories where 38 of the 48 locations
are. The exception class is
LMInvalidRequestError, not its subclassContextWindowExceededError, so the request was rejected for another reason; the message is never recorded (it can carry a key), so the next check is one re-run of a failed change that records the provider's error code field only. - Nothing here is a comparison with intervals that separate the arms: 5 positive pushes. The location-level numbers (48) are the ones to read, and they say both arms miss more than 90% of the verified locations of this class.
Instrument findings recorded along the way
--budget-usddid not stop the DSPy run at 5 dollars: the runner booked 0.0 per change. Fixed after this run (the ledger now prices every LM call of the change at the registered prices; the record carriesusd).- The diff producer the model saw was blind to removed lines (
537b61e); the hunter arm did not undo the sparse checkout of training clones (c01e61c, fixed before it ran); an empty product file failed the source producer on every row of a change (fcb43fd). Seebenchmarks/measurements/2026-10-13-access-control-screen/NOTES.md.
Files
analysis.json: the numbers above, per arm.suspicions.jsonl: every suspicion of both arms with repo, push, path, line, family, confidence and a true/false label against the verified locations (619 rows, 6 true).metrics_hunter.json:benchmarks.valid.metricsfor the hunter arm.- Raw records:
~/ousast-results/hunt/ac-train/{dspy-1,hunter-1}(not in the repository).