mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-18 12:39:28 +00:00
fix(learning-harness): the round-4 review findings
Three defects, two of them the same shape as ones already rejected once: - The meta-agent proposer still could not propose. `MetaAgent(inner_model=)` takes a ModelConfig; it was handed a model name, a `# type: ignore` hid that from mypy, and a bare `except Exception` turned the resulting AttributeError into `meta_agent_failed` -- which reads exactly like the model declining. The composition is now a seam a test can pin, and a construction error is re-raised rather than reported as a quiet round. - `ousast pairs --hunter` crashed in its documented form: the K floor landed with `--k-runs` still defaulting to 1. The covering test always passed `--k-runs 4`, which is why nothing noticed. - 28 rows (12% of the corpus) resolved a span on the vulnerable side and none on the fixed side, so every fixed-side finding read as outside the labeled function and the pair scored as silence whatever the detector said. `fix_function` now reaches the catalog and the scorer, and the generator derives it from the fixed excerpt for the 25 trap rows that never declared one. Measured after: 0 rows. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
This commit is contained in:
co-authored by
Claude Opus 5
parent
75ae9ee47b
commit
2dad25d312
@@ -457,11 +457,13 @@ def _pairs_named_by(proposal: Proposal, cases: Sequence[PairCase]) -> tuple[str,
|
||||
A memory entry that quotes a held-out pair is the loop learning the answer instead of the shape, and it looks
|
||||
exactly like a legitimate hard negative until the holdout number is read as if it meant something."""
|
||||
haystack = "\n".join([*proposal.predicted_affected, *proposal.predicted_at_risk, *proposal.change.values()])
|
||||
named = []
|
||||
for case in cases:
|
||||
name = str(getattr(case, "name", ""))
|
||||
if name and re.search(rf"(?<![\w-]){re.escape(name)}(?![\w-])", haystack):
|
||||
named.append(name)
|
||||
# Substring first, regex only for the handful that survive it: the corpus is a few hundred rows and a round
|
||||
# runs this once, but a per-round sweep of one regex per row is the kind of thing that stops being free.
|
||||
named = [
|
||||
name
|
||||
for case in cases
|
||||
if (name := str(getattr(case, "name", ""))) and name in haystack and re.search(rf"(?<![\w-]){re.escape(name)}(?![\w-])", haystack)
|
||||
]
|
||||
return tuple(sorted(set(named)))
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user