feat: surface sub-threshold findings in review summary with web app link (#1571)

Instead of silently swallowing findings below the severity threshold,
the review summary now mentions them with a count and links to the
web app where they can be viewed. For example, if 2 low-severity
findings are filtered out, the PR comment says "No issues found" and
"2 additional findings can be viewed in the web app." with the
existing [Open in Web] link.

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
This commit is contained in:
Johannes du Plessis 2026-06-18 11:15:42 -07:00 • committed by GitHub
parent 2df0eabd35
commit 055b83e723
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 107 additions and 4 deletions

View file

@ -284,9 +284,16 @@ def render_review_body(
trace_url: str | None = None,
ui_url: str | None = None,
out_of_diff_findings: list[Finding] | None = None,
additional_findings_count: int = 0,
) -> str:
"""Compose the top-level review body."""
"""Compose the top-level review body.
When ``surfaced_count`` is 0 but ``additional_findings_count`` is > 0,
the headline says "No issues found" and a second line directs the reader
to the web app for the remaining sub-threshold findings.
"""
out_of_diff_findings = out_of_diff_findings or []
has_additional = additional_findings_count > 0
if surfaced_count == 0 and not out_of_diff_findings:
headline = (
"## ✅ Open SWE Review: No issues found\n\n"
@ -299,6 +306,9 @@ def render_review_body(
headline = f"**Open SWE Review** found {surfaced_count} potential {issue_word}."
parts = [headline]
if has_additional:
noun = "finding" if additional_findings_count == 1 else "findings"
parts.append(f"{additional_findings_count} additional {noun} can be viewed in the web app.")
if out_of_diff_findings:
parts.append(render_out_of_diff_section(out_of_diff_findings))
links = []

View file

@ -10,6 +10,7 @@ from langgraph.config import get_config
from ..dashboard.team_settings import get_team_review_trace_links_enabled
from ..reviewer_diff import compute_diff_line_set, fetch_pr_diff, is_range_in_diff
from ..reviewer_findings import (
SEVERITY_ORDER,
Finding,
ReviewerThreadMissingError,
Severity,
@ -72,9 +73,10 @@ def publish_review(
GitHub Review but still resolves fixed threads and updates reviewer state.
Args:
severity_threshold: Lowest severity to surface to GitHub (default
``medium``). Lower-severity findings stay in state and surface in
the future UI but not on the PR.
severity_threshold: Lowest severity to surface as inline GitHub comments
(default ``medium``). Lower-severity findings stay in state and are
mentioned in the review summary with a link to the web app, but are
not posted as inline PR comments.
cap: Maximum number of inline comments to publish (default 4).
Returns:
@ -268,6 +270,16 @@ async def _publish_review_async(
in_diff_unpublished, severity_threshold=severity_threshold, cap=cap
)
severity_rank = SEVERITY_ORDER[severity_threshold]
eligible_ids = {f.get("id") for f in eligible}
additional_findings_count = sum(
1
for f in in_diff_unpublished
if f.get("id") not in eligible_ids
and f.get("status", "open") == "open"
and SEVERITY_ORDER.get(f.get("severity", "low"), 0) < severity_rank
)
inline_comments: list[dict[str, Any]] = []
eligible_with_payload: list[tuple[dict[str, Any], dict[str, Any]]] = []
for finding in eligible:
@ -328,6 +340,7 @@ async def _publish_review_async(
surfaced_count=len(inline_comments),
trace_url=review_trace_url,
ui_url=review_ui_url,
additional_findings_count=additional_findings_count,
)
review_response = await post_pull_request_review(
@ -362,6 +375,7 @@ async def _publish_review_async(
surfaced_count=len(retry_inline),
trace_url=review_trace_url,
ui_url=review_ui_url,
additional_findings_count=additional_findings_count,
)
retry_response = await post_pull_request_review(
owner=owner,

View file

@ -212,6 +212,40 @@ def test_render_review_body_no_findings_message() -> None:
body = render_review_body(pr_number=99, surfaced_count=0)
assert "## ✅ Open SWE Review: No issues found" in body
assert "Open SWE reviewed this PR and found no potential bugs to report." in body
assert "additional" not in body
def test_render_review_body_with_additional_findings_and_ui_link() -> None:
body = render_review_body(
pr_number=99,
surfaced_count=0,
additional_findings_count=2,
ui_url="https://dash.example/agents/reviews/o/r/99",
)
assert "## ✅ Open SWE Review: No issues found" in body
assert "2 additional findings can be viewed in the web app." in body
assert "[Open in Web](https://dash.example/agents/reviews/o/r/99)" in body
def test_render_review_body_with_single_additional_finding_uses_singular() -> None:
body = render_review_body(pr_number=99, surfaced_count=0, additional_findings_count=1)
assert "1 additional finding can be viewed in the web app." in body
def test_render_review_body_with_surfaced_and_additional_findings() -> None:
body = render_review_body(
pr_number=99,
surfaced_count=3,
additional_findings_count=2,
ui_url="https://dash.example/agents/reviews/o/r/99",
)
assert "found 3 potential issues." in body
assert "2 additional findings can be viewed in the web app." in body
def test_render_review_body_additional_findings_zero_omits_line() -> None:
body = render_review_body(pr_number=99, surfaced_count=0, additional_findings_count=0)
assert "additional" not in body
def test_render_status_comment_reviewing_includes_ui_link(monkeypatch: Any) -> None:
@ -387,6 +421,51 @@ def test_publish_review_eval_mode_does_not_call_github() -> None:
set_meta.assert_awaited_once_with("tid", last_reviewed_sha="sha")
@pytest.mark.asyncio
async def test_publish_review_surfaces_additional_findings_count_in_body() -> None:
"""When all surfaced findings are above threshold but sub-threshold findings
exist, the review body must mention how many additional findings are in the
web app."""
from agent.tools.publish_review import _publish_review_async
findings = [
_f(id="f_low_1", severity="low", file="a.py", start_line=1, end_line=1),
_f(id="f_low_2", severity="low", file="b.py", start_line=2, end_line=2),
]
post_review = AsyncMock(return_value={"id": 555})
fetch_comments = AsyncMock(return_value=[])
with (
patch("agent.tools.publish_review.get_thread_id_from_runtime", return_value="tid"),
patch("agent.tools.publish_review.list_findings_async", AsyncMock(return_value=findings)),
patch("agent.tools.publish_review.post_pull_request_review", post_review),
patch("agent.tools.publish_review.fetch_review_comments", fetch_comments),
patch(
"agent.tools.publish_review._resolve_threads_for_resolved_findings",
new_callable=AsyncMock,
return_value=0,
),
patch("agent.tools.publish_review.set_reviewer_thread_metadata", AsyncMock()),
patch("agent.tools.publish_review._maybe_post_slack_completion_reply", AsyncMock()),
):
result = await _publish_review_async(
owner="o",
repo="r",
pr_number=7,
head_sha="sha",
token="t",
severity_threshold="medium",
cap=15,
is_re_review=False,
)
assert result["success"] is True
assert result["surfaced_count"] == 0
posted_body = post_review.await_args.kwargs["body"]
assert "No issues found" in posted_body
assert "2 additional findings can be viewed in the web app." in posted_body
def test_publish_review_forwards_trace_link_config_override() -> None:
from agent.tools.publish_review import publish_review