From 2390a4be84cf785d4f99ad010f35deb392713207 Mon Sep 17 00:00:00 2001 From: CleverThis Date: Fri, 10 Apr 2026 23:35:50 +0000 Subject: [PATCH] chore(agents): enforce CI status deduplication --- .../backlog-grooming-pool-supervisor.md | 5 ++ .opencode/agents/pr-review-pool-supervisor.md | 65 ++++++++++++++++++- .opencode/agents/pr-reviewer.md | 37 +++++++++++ 3 files changed, 105 insertions(+), 2 deletions(-) diff --git a/.opencode/agents/backlog-grooming-pool-supervisor.md b/.opencode/agents/backlog-grooming-pool-supervisor.md index ed66da30c..dbedce771 100644 --- a/.opencode/agents/backlog-grooming-pool-supervisor.md +++ b/.opencode/agents/backlog-grooming-pool-supervisor.md @@ -55,6 +55,11 @@ and creating missing children to ensure full coverage. backlog each cycle. You work entirely through the Forgejo API — you do NOT need a git clone or filesystem access. +**CI STATUS DISCIPLINE:** Do **not** post CI status tables on PR threads. +CI reporting is owned by the PR review pool. When you comment on a PR (for +label or milestone corrections), reference CI with a single sentence only +as needed (e.g., "CI: 9/10 passing; waiting on lint"), never with a table. + --- ## No Clone Required diff --git a/.opencode/agents/pr-review-pool-supervisor.md b/.opencode/agents/pr-review-pool-supervisor.md index 0403dd379..5c5aba00c 100644 --- a/.opencode/agents/pr-review-pool-supervisor.md +++ b/.opencode/agents/pr-review-pool-supervisor.md @@ -3,7 +3,9 @@ description: > Long-running PR review pool supervisor. Continuously polls Forgejo for pull requests needing code review and dispatches N parallel pr-reviewer instances to review them. Focuses purely on code quality assessment. - Does NOT handle fixes, merges, or PR lifecycle management. + Does NOT handle fixes, merges, or PR lifecycle management. Acts as the + primary CI status reporter for PRs it has claimed; other agents defer to + its dispatched reviewers for CI status coverage. mode: subagent hidden: true temperature: 0.1 @@ -52,6 +54,14 @@ You do NOT: - Close stale PRs - Verify issue closures +**You are the PRIMARY CI status reporter for PRs you supervise.** When your +dispatched `pr-reviewer` instances post CI status updates, those reports are +the authoritative source for the PR. Other automation agents must not post +redundant CI status tables on the same PR. Before any reviewer posts a CI +status table, you must run the CI deduplication check described below. If a +recent CI status already exists for the same commit SHA, skip the table and +provide a one-line summary referencing the existing status instead. + The implementation workers handle all PR lifecycle management. Your ONLY job is to ensure PRs get timely, high-quality code reviews. @@ -165,6 +175,49 @@ function find_automation_tracking_issues() { --- +## CI Status Deduplication (Required) + +**Goal:** Prevent redundant CI status tables on the same PR. Before any +`pr-reviewer` (or fallback agent) posts a CI status table, enforce an active +duplication check: + +1. Fetch the last 5 issue comments on the PR via `forgejo_list_issue_comments`. +2. Look for CI status markers and commit SHAs inside each comment body. The + standard reviewer template includes the commit SHA in the header. +3. If a CI status table for the same commit SHA was posted within the last 15 + minutes, skip posting a duplicate table. Instead, include a one-line summary + such as `CI status unchanged: 8/9 passing as of `. + +**Helper function:** + +```python +function ci_status_recent(pr_number, commit_sha): + recent_comments = forgejo_list_issue_comments(owner, repo, pr_number, limit=5, page=1) + for comment in recent_comments: + if not comment.body: + continue + + contains_table = "CI Status" in comment.body or "CI Summary" in comment.body + same_commit = commit_sha in comment.body + minutes_old = (now - comment.created_at).total_minutes() + + if contains_table and same_commit and minutes_old <= 15: + return True + return False +``` + +Call `ci_status_recent(pr.number, pr.head.sha)` before dispatching a reviewer or +before posting any CI status table. If it returns `True`, instruct the reviewer +to omit the table and reference the existing report. This logic ensures multiple +reviewers (or retries) do not spam the same CI table. + +**Fallback exception:** The `system-watchdog` may post a CI status summary only +when no reviewer has posted an update for 30+ minutes on a critical PR. This +documented exception must still honor the deduplication check above and post a +one-line summary instead of a full table. + +--- + ## Setup You receive: @@ -397,7 +450,11 @@ LOOP FOREVER: 4. Is the PR blocked by rejected reviews? If all conditions are met, this may be a stuck PR that needs investigation. - + + Before posting ANY CI status table, call ci_status_recent({pr.number}, {pr.head.sha}) + to check for recent CI updates. If it returns True, skip the table and include a + one-line summary noting the existing status instead of reposting it. + CRITICAL — Dual-Account Authentication: - READ operations (get PR, list reviews, get diff): Use the Forgejo MCP tools (primary bot token is fine for reads) - WRITE operations (post review, post comment): Use curl with FORGEJO_REVIEWER_PAT @@ -421,6 +478,10 @@ LOOP FOREVER: While you should check all standard items (spec compliance, tests, etc.), pay SPECIAL ATTENTION to the focus areas above. + Before posting ANY CI status table, call ci_status_recent({pr.number}, {pr.head.sha}) + to check for recent CI updates. If it returns True, skip the table and include a + one-line summary noting the existing status instead of reposting it. + CRITICAL — Dual-Account Authentication: - READ operations (get PR, list reviews, get diff): Use the Forgejo MCP tools (primary bot token is fine for reads) - WRITE operations (post review, post comment): Use curl with FORGEJO_REVIEWER_PAT diff --git a/.opencode/agents/pr-reviewer.md b/.opencode/agents/pr-reviewer.md index 7d1b712c6..8223eedee 100644 --- a/.opencode/agents/pr-reviewer.md +++ b/.opencode/agents/pr-reviewer.md @@ -411,6 +411,43 @@ def setup_clean_state(context): **Remember**: Unit and Integration tests must be 100% deterministic. Only E2E tests may have some non-determinism. +### 4.5 Prevent Redundant CI Status Tables (Required) + +Before including a CI status table in your review output, you MUST check for +recent CI updates to avoid duplicates: + +1. Fetch the last 5 PR comments using `forgejo_list_issue_comments`. +2. Look for CI status markers (table headings or `Commit:` lines) and extract + the commit SHA referenced in each comment. +3. If any comment references the same commit SHA and was posted within the last + 15 minutes, **do not** repost the CI table. Instead, include a one-line + summary acknowledging the existing status (e.g., `CI status unchanged: + 9/10 passing as of 12:32 UTC`). + +Helper pseudo-code: + +```python +def ci_status_recent(pr_number: int, commit_sha: str) -> bool: + recent = forgejo_list_issue_comments(owner, repo, pr_number, limit=5, page=1) + for comment in recent: + if not comment.body: + continue + has_ci_section = "CI Status" in comment.body or "CI Summary" in comment.body + cites_same_commit = commit_sha in comment.body + minutes_old = (now - comment.created_at).total_minutes() + if has_ci_section and cites_same_commit and minutes_old <= 15: + return True + return False + +if ci_status_recent(pr_number, head_sha): + include_one_line_summary_only() +else: + include_full_ci_status_table() +``` + +This active check enforces the CI ownership contract established by the +pr-review-pool supervisor and keeps PR threads free from redundant screenshots. + ### 5. Make a Decision Based on your review, you will either APPROVE or REQUEST CHANGES.