fix(confidence): pass multi_lens_observed kwarg to merge_confidence

This commit is contained in:
claude
2026-08-22 00:29:28 +00:00
parent f3a125666b
commit 72b77a96e0
2 changed files with 42 additions and 8 deletions
+23 -6
View File
@@ -234,7 +234,7 @@ def _int_env(name: str, default: int) -> int:
_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.
Tier drops driven by the most severe finding present:
@@ -243,9 +243,14 @@ def merge_confidence(findings: list[dict]) -> int:
- medium → 4
- else → 5 (low / trivial / info / unknown → no drop)
An extra -1 when ANY finding carries ``_multi_lens`` (cross-lens agreement
bumps confidence in the signal — penalise harder). The final score is
clamped to [1, 5] so a critical + multi_lens combo doesn't go negative.
An extra -1 when cross-lens agreement was observed on any finding
(``multi_lens_observed``). The flag is passed in explicitly because the
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:
return 5
@@ -258,7 +263,7 @@ def merge_confidence(findings: list[dict]) -> int:
score = 4
else:
score = 5
if any(f.get("_multi_lens") for f in findings):
if multi_lens_observed:
score -= 1
return max(1, min(5, score))
@@ -2065,6 +2070,15 @@ def review_pr(
})
except Exception:
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)
findings = kept
if _dropped:
@@ -2111,7 +2125,10 @@ def review_pr(
# anchoring so the verdict reflects what the operator sees (a critical
# finding that fails to anchor is still a critical finding). The
# 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(
"\n\n".join(summary_parts), model, sha,
summary=review_summary,
+19 -2
View File
@@ -1855,8 +1855,25 @@ def test_merge_confidence_critical_drops_to_one():
def test_merge_confidence_multi_lens_drops_extra():
f = {"severity": "low", "_multi_lens": True}
assert merge_confidence([f]) == 4
# The flag has moved to a kwarg; passing `_multi_lens` on the dict is no
# 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():