From b05ce14f76cee30ead4619dfbb5293a33ff45c09 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Fri, 1 May 2026 07:17:14 -0700 Subject: [PATCH] PR dashboard: ignore merge-from-base commits made by non-authors The is_substantive() filter excluded "Update branch" merge commits from the latest-event determination, but treated all merge commits the same regardless of who made them, and the LLM-rendered context still surfaced them in the "Last N commits" listing and used their timestamp for "Last commit pushed". Refine the rule to only ignore merge commits authored by someone other than the PR author (e.g. an approver clicking "Update branch" on someone else's PR, as on #18090). Author-driven merges of base into the PR remain substantive. Apply the same rule to the rendered commit listing and last_commit_date. --- .github/scripts/pull-request-dashboard.py | 35 ++++++++++++++++++----- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/.github/scripts/pull-request-dashboard.py b/.github/scripts/pull-request-dashboard.py index d5cc0f1b321b..384b07f856ef 100644 --- a/.github/scripts/pull-request-dashboard.py +++ b/.github/scripts/pull-request-dashboard.py @@ -418,12 +418,14 @@ def fetch_pr_context( # Last substantive event = last event whose body is non-empty OR whose # kind is not "review:COMMENTED" (state changes always count). Merge - # commits (≥2 parents — e.g. "Update branch" merging base into the PR) - # don't count as substantive: they don't move the conversation forward. + # commits (≥2 parents) by someone *other* than the author — e.g. an + # approver clicking "Update branch" — don't count as substantive: they + # don't move the conversation forward and shouldn't be confused with + # the author addressing feedback. def is_substantive(e: dict[str, Any]) -> bool: if e["kind"].startswith("review:") and e["kind"] != "review:COMMENTED": return True - if e.get("is_merge"): + if e.get("is_merge") and (e.get("login") or "").lower() != author.lower(): return False return bool((e.get("body") or "").strip()) @@ -432,16 +434,34 @@ def is_substantive(e: dict[str, Any]) -> bool: # Commit summaries (subject only) for the brief table in the rendered # context. Full commit messages and diffs travel via timeline events. + # Merge commits authored by someone other than the PR author (e.g. an + # approver clicking "Update branch") are flagged so the model doesn't + # treat them as the author addressing feedback. commit_rows = [] for c in recent_commits: - sha = (c.get("sha") or "")[:7] + sha_full = c.get("sha") or "" + sha = sha_full[:7] msg = (c.get("commit") or {}).get("message", "").splitlines()[0] if c.get("commit") else "" a = c.get("author") or {} commit_login = a.get("login") or ((c.get("commit") or {}).get("author") or {}).get("name") or "?" commit_date = ((c.get("commit") or {}).get("author") or {}).get("date") or "" - commit_rows.append({"sha": sha, "msg": msg, "author": commit_login, "date": commit_date}) + is_non_author_merge = ( + sha_full in merge_shas + and (commit_login or "").lower() != author.lower() + ) + commit_rows.append({ + "sha": sha, + "msg": msg, + "author": commit_login, + "date": commit_date, + "is_non_author_merge": is_non_author_merge, + }) - last_commit_date = parse_ts(commit_rows[-1]["date"]) if commit_rows else None + # "Last commit pushed" is meant to surface real author activity, so + # skip non-author merge commits (e.g. approvers clicking "Update + # branch") when picking the timestamp. + real_rows = [r for r in commit_rows if not r["is_non_author_merge"]] + last_commit_date = parse_ts(real_rows[-1]["date"]) if real_rows else None # Checks summary. failing = [c for c in checks if (c.get("state") or "").upper() in ("FAILURE", "ERROR")] @@ -543,7 +563,8 @@ def render_context(ctx: dict[str, Any]) -> str: # Commits lines.append(f"Last {len(ctx['commits'])} commits (oldest first):") for c in ctx["commits"]: - lines.append(f" {c['sha']} {c['date'][:10]} @{c['author']}: {truncate(c['msg'], 120)}") + suffix = " [merge from base by non-author — not substantive activity]" if c.get("is_non_author_merge") else "" + lines.append(f" {c['sha']} {c['date'][:10]} @{c['author']}: {truncate(c['msg'], 120)}{suffix}") lines.append("") # Last substantive event highlight