Skip to content

fix: downgrade REQUEST_CHANGES→COMMENT on self-authored PRs in safe-outputs PR review#47400

Merged
pelikhan merged 5 commits into
mainfrom
copilot/aw-fixresolve-pr-review-safe-outputs
Jul 22, 2026
Merged

fix: downgrade REQUEST_CHANGES→COMMENT on self-authored PRs in safe-outputs PR review#47400
pelikhan merged 5 commits into
mainfrom
copilot/aw-fixresolve-pr-review-safe-outputs

Conversation

Copilot AI commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Reviewer workflows fail with 422 "Can not request changes on your own pull request" when running against *-miner or other bot-authored PRs where the reviewing identity matches the PR author. The existing own-PR retry logic was bypassed when the initial failure was "Line could not be resolved" — the body-only fallback then ran with REQUEST_CHANGES and also hit 422, causing all safe outputs to fail.

Changes (pr_review_buffer.cjs)

  • Proactive downgrade — before building requestParams, compare pullRequest.user.login against GITHUB_ACTOR; if they match, rewrite REQUEST_CHANGES/APPROVECOMMENT before any API call, preventing the 422 entirely:

    if (event !== "COMMENT" && pullRequest.user?.login) {
      const actor = (process.env.GITHUB_ACTOR || "").trim();
      if (actor && pullRequest.user.login === actor) {
        event = "COMMENT"; // avoid 422 on self-authored PR
      }
    }
  • Body-only fallback own-PR guard — the "Line could not be resolved" body-only fallback now catches own-PR 422 on the retry and re-submits as body-only COMMENT. This is the exact path that failed in runs 29946005059/29910168345.

  • Own-PR COMMENT retry → body-only COMMENT — if the reactive COMMENT retry (inline comments preserved) still fails with line-resolution errors, fall back to body-only COMMENT instead of hard-failing.

Tests

Six new tests in pr_review_buffer.test.cjs cover: proactive GITHUB_ACTOR match (REQUEST_CHANGES and APPROVE), no-downgrade when actors differ, own-PR retry → body-only COMMENT, body-only → own-PR 422 → COMMENT success, and body-only COMMENT failure propagation.


Run: https://github.com/github/gh-aw/actions/runs/29961275366

Generated by 👨‍🍳 PR Sous Chef · gpt54 14.3 AIC · ⌖ 7.21 AIC · ⊞ 7K ·
Comment /souschef to run again

…utputs PR review

Fixes 422 "Can not request changes on your own pull request" failures that
occur when the PR Code Quality Reviewer (or any reviewer workflow) runs
against a PR authored by the same bot identity (e.g. linter-miner branches).

Three complementary defences in pr_review_buffer.cjs:

1. Proactive check: before building requestParams, compare pullRequest.user.login
   against GITHUB_ACTOR. If they match, downgrade REQUEST_CHANGES/APPROVE → COMMENT
   immediately, avoiding the 422 entirely.

2. Own-PR COMMENT retry → body-only COMMENT fallback: when the own-PR COMMENT retry
   (reactive path) also fails with "Line could not be resolved" or "Path could not be
   resolved", fall back to a body-only COMMENT review instead of hard-failing.

3. Body-only fallback own-PR guard: when the "Line could not be resolved" body-only
   fallback itself gets a 422 "Can not request changes on your own pull request",
   downgrade the body-only event to COMMENT and retry — this is the exact scenario
   that caused the 4/4 safe-output failures in runs 29946005059 and 29910168345.

Six new tests cover all three paths.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix safe-outputs review for own PR submissions fix: downgrade REQUEST_CHANGES→COMMENT on self-authored PRs in safe-outputs PR review Jul 22, 2026
Copilot AI requested a review from pelikhan July 22, 2026 21:17
@pelikhan
pelikhan marked this pull request as ready for review July 22, 2026 21:55
Copilot AI review requested due to automatic review settings July 22, 2026 21:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes self-authored PR review failures by downgrading restricted review events and adding resilient body-only fallbacks.

Changes:

  • Adds proactive and reactive COMMENT fallbacks.
  • Preserves unresolvable inline feedback in review bodies.
  • Adds regression tests for fallback paths.
Show a summary per file
File Description
actions/setup/js/pr_review_buffer.cjs Implements self-review downgrade and fallback handling.
actions/setup/js/pr_review_buffer.test.cjs Tests proactive downgrade and body-only retries.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comments suppressed due to low confidence (1)

actions/setup/js/pr_review_buffer.test.cjs:1573

  • This test is environment-dependent: on a workflow triggered by linter-miner[bot], the new proactive check downgrades the initial request to COMMENT, so the mocked call sequence no longer reaches the body-only REQUEST_CHANGES rejection and the assertion fails. Set GITHUB_ACTOR to a known different value (or clear it) and restore it after the test.
        pullRequest: { head: { sha: "abc123" }, user: { login: "linter-miner[bot]" } },
  • Files reviewed: 2/2 changed files
  • Comments generated: 2
  • Review effort level: Medium

Comment thread actions/setup/js/pr_review_buffer.cjs Outdated
Comment on lines +305 to +315
// Proactively downgrade REQUEST_CHANGES/APPROVE → COMMENT on self-authored PRs.
// GITHUB_TOKEN lacks read:user scope for reliable identity pre-flight via the API, so
// compare the PR author login against GITHUB_ACTOR as a best-effort guard.
// The reactive 422 retry in the catch block is retained as a safety net for cases this misses.
if (event !== "COMMENT" && pullRequest.user?.login) {
const actor = (process.env.GITHUB_ACTOR || "").trim();
if (actor && pullRequest.user.login === actor) {
core.warning(`PR #${pullRequestNumber} is authored by the workflow actor ('${actor}'). ` + `Downgrading '${event}' → 'COMMENT' to avoid 422 "Can not request changes on your own pull request".`);
event = "COMMENT";
}
}
repo: "owner/repo",
repoParts: { owner: "owner", repo: "repo" },
pullRequestNumber: 42,
pullRequest: { head: { sha: "abc123" }, user: { login: "bot-user" } },
@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR #47400 does not have the 'implementation' label and has 0 new lines of code in business logic directories (threshold: 100).

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill, address unresolved review comments, and rerun checks once the branch is up to date.

Open unresolved review feedback (newest first):

Generated by 👨‍🍳 PR Sous Chef · gpt54 14.3 AIC · ⌖ 7.21 AIC · ⊞ 7K ·
Comment /souschef to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: fix: downgrade REQUEST_CHANGES→COMMENT on self-authored PRs

The fix is correct and well-structured. The three-layer defence (proactive GITHUB_ACTOR check, reactive 422 retry, body-only COMMENT fallback) covers the observed failure path cleanly.

No blocking issues. The two existing inline comments identify the non-blocking concerns worth tracking:

  • The GITHUB_ACTOR proactive guard is a best-effort heuristic when the review token identity differs from the workflow actor. The reactive 422 catch is retained as the true safety net, which is the right design.
  • The body-only fallback test at line 1044 could be fragile if CI happens to run under the same actor as the mocked PR author, but this is a test environment concern, not a production bug.

All changed code paths are covered by tests. LGTM.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 27.8 AIC · ⌖ 5.6 AIC · ⊞ 5K

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 90/100 — Excellent

Analyzed 6 test(s): 6 design, 0 implementation, 0 violation(s).

📊 Metrics (6 tests)
Metric Value
Analyzed 6 (Go: 0, JS: 6)
✅ Design 6 (100%)
⚠️ Implementation 0 (0%)
Edge/error coverage 6 (100%)
Duplicate clusters 0
Inflation YES (203 test lines / 47 net prod lines ≈ 4.3:1)
🚨 Violations 0
Test File Classification Issues
should retry with COMMENT when REQUEST_CHANGES is rejected on own PR pr_review_buffer.test.cjs:846 design_test ✅ none
should proactively downgrade REQUEST_CHANGES → COMMENT when PR author matches GITHUB_ACTOR pr_review_buffer.test.cjs:899 design_test ✅ none
should proactively downgrade APPROVE → COMMENT when PR author matches GITHUB_ACTOR pr_review_buffer.test.cjs:937 design_test ✅ none
should not downgrade when PR author does not match GITHUB_ACTOR pr_review_buffer.test.cjs:974 design_test ✅ none
should retry body-only as COMMENT when body-only REQUEST_CHANGES is rejected on own PR pr_review_buffer.test.cjs:1566 design_test ✅ none
should return failure when body-only COMMENT retry also fails on own PR pr_review_buffer.test.cjs:1601 design_test ✅ none
⚠️ Flagged Tests (1) — inflation only

pr_review_buffer.test.cjs — Test inflation ratio 4.3:1 (203 new test lines vs 47 net new production lines). While above the 2:1 threshold, the ratio is justified: the production fix is a compact proactive-downgrade guard, while the tests cover the reactive fallback path, proactive downgrade for two events (REQUEST_CHANGES and APPROVE), the negative non-matching actor case, and cascading body-only fallback paths. The breadth is appropriate.

Verdict

Passed. 0% implementation tests (threshold: 30%). All 6 new tests are design-level behavioral contracts verifying the proactive self-authored PR downgrade logic: REQUEST_CHANGES→COMMENT, APPROVE→COMMENT, non-matching actor negative case, and cascading error paths. The 4.3:1 inflation ratio is noted but the extra test coverage is warranted given the multiple edge cases tested.

🧪 Test quality analysis by Test Quality Sentinel · sonnet46 54 AIC · ⌖ 7.92 AIC · ⊞ 7K ·
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test Quality Sentinel: 90/100. 0% implementation tests (threshold: 30%). All 6 new tests are behavioral design contracts covering the proactive self-review downgrade logic.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skills-Based Review 🧠

Applied /diagnosing-bugs and /tdd — requesting changes on two correctness issues.

📋 Key Themes & Highlights

Key Themes

  • requestParams mutation — the reactive own-PR retry mutates requestParams.event = "COMMENT" in-place (line 628), diverging from the spread-based pattern used in the body-only path. A future reader or retry leg sees stale state.
  • Fragile error-string duplication — the "Line could not be resolved" check at line 637 is a second copy of the same predicate already at line ~720; extracting a shared helper would prevent drift.
  • Environment-sensitive tests — several new reactive-path tests don't pin GITHUB_ACTOR, so the proactive downgrade can silently fire and invalidate call-count assertions if CI runs under a matching actor name.

Positive Highlights

  • ✅ Six well-structured new tests covering both proactive and reactive paths
  • GITHUB_ACTOR is restored in finally in the proactive-downgrade tests — good hygiene
  • ✅ The proactive guard is a clean, low-risk approach; the comment explaining the GITHUB_TOKEN scope limitation is exactly the right level of documentation
  • ✅ Body-only COMMENT cascade handles all known error permutations of the original bug

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 40 AIC · ⌖ 4.86 AIC · ⊞ 6.7K
Comment /matt to run again

Comments that could not be inline-anchored

actions/setup/js/pr_review_buffer.cjs:628

[/diagnosing-bugs] requestParams.event is mutated in-place before the retry. If any later code path reads requestParams (logging, future retry leg), it sees COMMENT instead of the original event — a silent state corruption.

<details>
<summary>💡 Suggested fix</summary>

Use a spread to avoid mutation, consistent with how bodyOnlyParams is constructed at line 640:

const commentParams = { ...requestParams, event: &quot;COMMENT&quot; };
const { data: review } = await createReviewWithRetr…

</details>

<details><summary>actions/setup/js/pr_review_buffer.cjs:637</summary>

**[/diagnosing-bugs]** The line-resolution check only matches `&quot;Line could not be resolved&quot;` and `&quot;Path could not be resolved&quot;`. The GitHub API can also return `&quot;Pull request review thread not found&quot;` or similar for stale diffs  those errors fall through to the generic failure branch and lose the own-PR COMMENT context.

&lt;details&gt;
&lt;summary&gt;💡 Suggested fix&lt;/summary&gt;

Consider extracting a shared `isLineResolutionError(msg)` predicate (keeping it consistent with the check at line ~720) so both 

</details>

<details><summary>actions/setup/js/pr_review_buffer.test.cjs:1054</summary>

**[/tdd]** This test relies on the proactive downgrade *not* firing  but the test fixture sets `pullRequest.user.login = &quot;bot-user&quot;` with no control over `GITHUB_ACTOR`. If CI runs as `bot-user`, the proactive branch fires first, the mocked 422 is never hit, and the call-count assertion (`toHaveBeenCalledTimes(3)`) fails.

&lt;details&gt;
&lt;summary&gt;💡 Suggested fix&lt;/summary&gt;

Set `GITHUB_ACTOR` to a different value (e.g. `&quot;different-actor&quot;`) at the top of this test, restoring it in `finally`, so the 

</details>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two issues need fixing before merge, plus a minor accounting bug.

### Findings summary

Blocking

  1. bodyOnlyParams.event mutated in-place (line 740) — createReviewWithRetry uses withRetry internally; mutating the params object before the call means all retry iterations already see COMMENT, not the originally-intended event. Use { ...bodyOnlyParams, event: "COMMENT" } like the parallel path at line 640 does.

  2. No test for empty/absent GITHUB_ACTOR — The proactive downgrade guard if (actor && pullRequest.user.login === actor) has no test asserting that an unset or whitespace-only GITHUB_ACTOR leaves the event unchanged. The truthiness check is the only thing preventing every review from being silently downgraded if that guard is ever loosened.

Non-blocking

  1. comment_count: 0 hardcoded in the ownPrBodyOnlyParams success result (line 650) — the comments were embedded into the body by appendUnanchoredCommentsSection, so passing 0 misreports the number of comments actually delivered. Either pass comments.length or document the field as "anchored inline count only".

🔎 Code quality review by PR Code Quality Reviewer · sonnet46 53.8 AIC · ⌖ 4.97 AIC · ⊞ 5.7K
Comment /review to run again

Comments that could not be inline-anchored

actions/setup/js/pr_review_buffer.cjs:740

bodyOnlyParams.event mutated in-place, corrupting params for internal retries: createReviewWithRetry wraps calls in withRetry; mutating the shared object before the first attempt means all retries already see COMMENT before any attempt runs.

<details>
<summary>💡 Suggested fix</summary>

Use a shallow clone, consistent with the pattern at line 640:

// Instead of:
bodyOnlyParams.event = &quot;COMMENT&quot;;
const { data: review } = await createReviewWithRetry(bodyOnlyParams);

// Do:
c…

</details>

<details><summary>actions/setup/js/pr_review_buffer.test.cjs:108</summary>

**No test for empty/absent `GITHUB_ACTOR`  the guard can break silently**: the proactive downgrade is protected by `if (actor &amp;&amp; ...)`, but there is no test asserting that when `GITHUB_ACTOR` is unset or empty, the event is left unchanged. If someone accidentally removes that truthiness check, every review submission would be silently downgraded to `COMMENT` regardless of who authored the PR.

&lt;details&gt;
&lt;summary&gt;💡 Suggested fix&lt;/summary&gt;

Add a test case:

```js
it(&quot;should not downgrade when …

</details>

<details><summary>actions/setup/js/pr_review_buffer.cjs:650</summary>

**`comment_count: 0` in body-only fallback misreports how many comments were actually submitted**: `buildReviewSuccessResult(review, &quot;COMMENT&quot;, 0, afterState)` hard-codes 0 inline comments, but `appendUnanchoredCommentsSection` folded the real comments into the body. Any caller inspecting `result.comment_count` (e.g. for audit logging or safe-output metadata) will undercount submitted feedback.

&lt;details&gt;
&lt;summary&gt;💡 Suggested fix&lt;/summary&gt;

Pass the actual comment count:

```js
// Instead of:


</details>

Copilot AI and others added 2 commits July 22, 2026 22:19
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please run the pr-finisher skill, address unresolved review comments, and rerun checks once the branch is up to date.

Open unresolved review feedback (newest first):...

Addressed in bff72c7. I removed the GITHUB_ACTOR self-author heuristic, kept the API-driven own-PR 422/body-only COMMENT fallbacks, and cleaned up the test coverage around those paths. Local validation passed (npm run test:js -- pr_review_buffer.test.cjs and make agent-report-progress). CI on this new HEAD is still stale from the agent push and needs a human re-trigger.

Copilot AI requested a review from gh-aw-bot July 22, 2026 22:24
@pelikhan
pelikhan merged commit 30face3 into main Jul 22, 2026
8 checks passed
@pelikhan
pelikhan deleted the copilot/aw-fixresolve-pr-review-safe-outputs branch July 22, 2026 22:38
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.83.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

4 participants