fix(confidence): pass multi_lens_observed kwarg to merge_confidence
This commit is contained in:
+23
-6
@@ -234,7 +234,7 @@ def _int_env(name: str, default: int) -> int:
|
|||||||
_CONFIDENCE_BADGE = {5: "🟢", 4: "🟢", 3: "🟡", 2: "🟠", 1: "🔴"}
|
_CONFIDENCE_BADGE = {5: "🟢", 4: "🟢", 3: "🟡", 2: "🟠", 1: "🔴"}
|
||||||
|
|
||||||
|
|
||||||
def merge_confidence(findings: list[dict]) -> int:
|
def merge_confidence(findings: list[dict], *, multi_lens_observed: bool = False) -> int:
|
||||||
"""1-5 merge verdict: higher = safer.
|
"""1-5 merge verdict: higher = safer.
|
||||||
|
|
||||||
Tier drops driven by the most severe finding present:
|
Tier drops driven by the most severe finding present:
|
||||||
@@ -243,9 +243,14 @@ def merge_confidence(findings: list[dict]) -> int:
|
|||||||
- medium → 4
|
- medium → 4
|
||||||
- else → 5 (low / trivial / info / unknown → no drop)
|
- else → 5 (low / trivial / info / unknown → no drop)
|
||||||
|
|
||||||
An extra -1 when ANY finding carries ``_multi_lens`` (cross-lens agreement
|
An extra -1 when cross-lens agreement was observed on any finding
|
||||||
bumps confidence in the signal — penalise harder). The final score is
|
(``multi_lens_observed``). The flag is passed in explicitly because the
|
||||||
clamped to [1, 5] so a critical + multi_lens combo doesn't go negative.
|
raw ``_multi_lens`` marker is stripped from findings by the time they
|
||||||
|
reach this function — first by ``opencode_review.run_lenses_review``
|
||||||
|
(the ``_``-prefix scrub) and again by ``_normalize_finding`` (the
|
||||||
|
7-key schema rebuild). The caller (``review_pr``) must capture the
|
||||||
|
signal before those strips fire. Final score is clamped to [1, 5] so
|
||||||
|
a critical + multi_lens combo doesn't go negative.
|
||||||
"""
|
"""
|
||||||
if not findings:
|
if not findings:
|
||||||
return 5
|
return 5
|
||||||
@@ -258,7 +263,7 @@ def merge_confidence(findings: list[dict]) -> int:
|
|||||||
score = 4
|
score = 4
|
||||||
else:
|
else:
|
||||||
score = 5
|
score = 5
|
||||||
if any(f.get("_multi_lens") for f in findings):
|
if multi_lens_observed:
|
||||||
score -= 1
|
score -= 1
|
||||||
return max(1, min(5, score))
|
return max(1, min(5, score))
|
||||||
|
|
||||||
@@ -2065,6 +2070,15 @@ def review_pr(
|
|||||||
})
|
})
|
||||||
except Exception:
|
except Exception:
|
||||||
changed_paths = []
|
changed_paths = []
|
||||||
|
# Capture cross-lens agreement BEFORE apply_repo_config — by the time
|
||||||
|
# findings land in `review_pr` the `_multi_lens` marker has already
|
||||||
|
# been scrubbed (once by `opencode_review.run_lenses_review`'s
|
||||||
|
# `_`-prefix strip, again by `_normalize_finding`'s 7-key rebuild),
|
||||||
|
# so `merge_confidence` cannot read it off the dict. We scan here as
|
||||||
|
# the convergence point for both engine paths; in practice the kwarg
|
||||||
|
# currently always passes False, but the structural plumbing is
|
||||||
|
# correct for any future code path that preserves the flag.
|
||||||
|
multi_lens = any(f.get("_multi_lens") for f in findings)
|
||||||
kept, _dropped = apply_repo_config(findings, config, changed_paths=changed_paths)
|
kept, _dropped = apply_repo_config(findings, config, changed_paths=changed_paths)
|
||||||
findings = kept
|
findings = kept
|
||||||
if _dropped:
|
if _dropped:
|
||||||
@@ -2111,7 +2125,10 @@ def review_pr(
|
|||||||
# anchoring so the verdict reflects what the operator sees (a critical
|
# anchoring so the verdict reflects what the operator sees (a critical
|
||||||
# finding that fails to anchor is still a critical finding). The
|
# finding that fails to anchor is still a critical finding). The
|
||||||
# default 5 keeps any failure path (e.g. empty findings) green.
|
# default 5 keeps any failure path (e.g. empty findings) green.
|
||||||
confidence = merge_confidence(findings)
|
# Cross-lens agreement is passed in via kwarg (see multi_lens scan
|
||||||
|
# above) because the `_multi_lens` flag is stripped before findings
|
||||||
|
# reach this call.
|
||||||
|
confidence = merge_confidence(findings, multi_lens_observed=multi_lens)
|
||||||
summary_body = format_review_body(
|
summary_body = format_review_body(
|
||||||
"\n\n".join(summary_parts), model, sha,
|
"\n\n".join(summary_parts), model, sha,
|
||||||
summary=review_summary,
|
summary=review_summary,
|
||||||
|
|||||||
@@ -1855,8 +1855,25 @@ def test_merge_confidence_critical_drops_to_one():
|
|||||||
|
|
||||||
|
|
||||||
def test_merge_confidence_multi_lens_drops_extra():
|
def test_merge_confidence_multi_lens_drops_extra():
|
||||||
f = {"severity": "low", "_multi_lens": True}
|
# The flag has moved to a kwarg; passing `_multi_lens` on the dict is no
|
||||||
assert merge_confidence([f]) == 4
|
# longer enough — the kwarg is the only path that drops the score.
|
||||||
|
f = {"severity": "low"}
|
||||||
|
assert merge_confidence([f], multi_lens_observed=True) == 4
|
||||||
|
|
||||||
|
|
||||||
|
def test_merge_confidence_multi_lens_survives_normalization():
|
||||||
|
"""Real flow: `_multi_lens` is set on the raw finding, but stripped by
|
||||||
|
`_normalize_finding`. `merge_confidence(...)` with only the kwarg sees a
|
||||||
|
normalized finding; the dedup must be triggered by `multi_lens_observed=`
|
||||||
|
being true, not by reading `_multi_lens` off the dict."""
|
||||||
|
raw = {"_multi_lens": True, "severity": "low", "path": "x", "line": 1,
|
||||||
|
"problem": "p", "fix": "", "suggestion": "", "reference": ""}
|
||||||
|
normalized = _normalize_finding(raw)
|
||||||
|
assert "_multi_lens" not in normalized # confirms the strip
|
||||||
|
# Now call merge_confidence the way review_pr will:
|
||||||
|
assert merge_confidence([normalized], multi_lens_observed=True) == 4
|
||||||
|
# And without the kwarg, the flag-on-dict path is gone:
|
||||||
|
assert merge_confidence([normalized]) == 5
|
||||||
|
|
||||||
|
|
||||||
def test_merge_confidence_clamped():
|
def test_merge_confidence_clamped():
|
||||||
|
|||||||
Reference in New Issue
Block a user