Skip to content

feat(#106): reconcile findings maintainers have already declined - #709

Open
ralphbean wants to merge 1 commit into
mainfrom
agent/106-trusted-maintainer-declines
Open

feat(#106): reconcile findings maintainers have already declined#709
ralphbean wants to merge 1 commit into
mainfrom
agent/106-trusted-maintainer-declines

Conversation

@ralphbean

Copy link
Copy Markdown
Member

Summary

Addresses #106: the review agent re-raises a finding on every subsequent push even after a maintainer explicitly replied declining it (e.g. "pre-existing pattern, out of scope for this PR").

  • New step 2a-1 in the pr-review orchestrator: on re-review, fetch reply threads on the agent's own prior inline findings via gh api pulls/{pr}/comments, and identify explicit declines.
  • Trust boundary: a decline only counts when the replying user's author_association is OWNER/MEMBER/COLLABORATOR (falling back to the collaborator permission API for write+ access) — the same tier .github/scripts/check-e2e-authorization.sh already uses elsewhere in this repo. Replies from anyone else, including a PR author without maintainer status, are inert. This is specifically to prevent an untrusted commenter from forging a "not a bug, dismissing this" reply to suppress a real finding.
  • New check in step 6e: a finding matching a trusted decline, on code unchanged since the decline, is downgraded to info severity with a note rather than dropped — stays visible for transparency, doesn't re-inflate the verdict, and reverts to full re-evaluation the moment the code changes.

This is explicitly marked experimental in the skill doc. It only covers the "declined via an explicit reply" case from #106 — not findings silently dropped across rounds, not self-contradictory reconciliation, not non-reply dismissals (e.g. a wontfix label). The intent is to try this narrower behavior, see whether it actually improves the review experience in practice, and use that to decide whether/how to broaden it. #106 should stay open until the fuller picture is addressed.

Test plan

SKILL.md is a prompt document with no automated test harness (unlike scripts/*.sh, which have *-test.sh counterparts), so this can't be exercised with a unit test.

  • pre-commit run --files skills/pr-review/SKILL.md passes
  • Observe behavior on a real PR where a maintainer declines a finding via reply, across 2+ subsequent pushes, and confirm the finding is downgraded rather than re-raised at its original severity
  • Confirm a decline reply from a non-maintainer (e.g. external contributor) is not honored

🤖 Generated with Claude Code

Adds an experimental step to the pr-review orchestrator: on re-review,
fetch reply threads on the agent's own prior inline findings and check
whether a repo maintainer explicitly declined one as out of scope.
Declines are trusted only from users with OWNER/MEMBER/COLLABORATOR
association (or write+ via the collaborator permission API) — the same
tier .github/scripts/check-e2e-authorization.sh already uses — so an
untrusted commenter cannot forge a dismissal to suppress a real
finding. Matched, unchanged findings are downgraded to info with a
note rather than dropped, so they stay visible without re-inflating
the verdict on every push.

This narrows one specific case of #106 (declined-via-reply) and is
explicitly marked experimental in the skill doc — it doesn't address
findings dropped silently or non-reply dismissals. Intended as a first
iteration to observe before deciding whether to expand it.

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
@ralphbean
ralphbean requested a review from a team as a code owner August 6, 2026 18:56
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Honor maintainer-declined prior findings on re-review (experimental)

✨ Enhancement 📝 Documentation 🕐 20-40 Minutes

Grey Divider

AI Description

• Add an experimental re-review step to detect maintainer replies declining prior findings.
• Define a maintainer-only trust boundary using author association / collaborator permissions.
• Downgrade unchanged, declined findings to info to avoid re-inflating verdicts.
Diagram

graph TD
  A["Re-review run"] --> B{"Prior review\napp-verified?"} --> C["Fetch inline threads\n(gh api comments)"] --> D{"Root comment\nfrom review app?"} --> E{"Reply by\nmaintainer?"} --> F[("DECLINED_FINDINGS")]
  B -->|"No"| Z["Skip decline logic"]
  D -->|"No"| Z
  E -->|"No"| Z
  F --> G{"Finding matches\nfile+line & unchanged?"} --> H["Downgrade to info\n(actionable=false)"]
  G -->|"No"| I["Normal re-evaluation"]

  subgraph Legend
    direction LR
    _proc["Process"] ~~~ _dec{"Decision"} ~~~ _data[("Recorded state")]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Use GitHub thread resolution state as the signal
  • ➕ Leverages a first-class GitHub concept (resolved/unresolved) instead of parsing reply text
  • ➕ Doesn’t require inferring intent from natural language decline phrases
  • ➖ Resolution can be toggled by people other than maintainers depending on repo settings
  • ➖ Resolution doesn’t necessarily mean “declined”; it can mean “fixed” or “acknowledged”
2. Persist decline decisions in a machine-readable store (labels/check-run artifact)
  • ➕ More deterministic than NLP over reply bodies; easier to test and audit
  • ➕ Can encode richer policy (scope, expiration, owner) without guessing intent
  • ➖ Adds operational overhead (maintainers must apply labels or interact with a bot UI)
  • ➖ Requires additional plumbing/state management outside the PR comment stream

Recommendation: The PR’s approach is a good first iteration because it targets a narrow, high-friction case (#106) while keeping a clear trust boundary (maintainer-only) and preserving transparency (downgrade to info rather than suppress). If false positives/negatives from reply-text interpretation become a problem, consider moving to a more explicit, machine-readable signal (e.g., label/artifact) while retaining the same maintainer trust gating.

Files changed (1) +92 / -0

Enhancement (1) +92 / -0
SKILL.mdDocument experimental maintainer-decline reconciliation for re-reviews +92/-0

Document experimental maintainer-decline reconciliation for re-reviews

• Adds step 2a-1 describing how to fetch inline review comment threads, verify they originated from the review app, and detect explicit maintainer declines using a strict trust boundary. Extends step 6e to downgrade unchanged findings that match a trusted decline to info severity (actionable: false) while re-evaluating normally once code changes.

skills/pr-review/SKILL.md

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📜 Skill insights (1)

Grey Divider


Action required

1. Decline key too broad 🐞 Bug ≡ Correctness
Description
Step 6e downgrades findings based only on file/line membership in DECLINED_FINDINGS, which can
incorrectly downgrade a different-category finding at the same location even though step 6c
explicitly preserves distinct-category findings at the same file/line. This can suppress legitimate
medium/high findings on re-review and distort the final verdict.
Code

skills/pr-review/SKILL.md[R1130-1133]

+- If the file is unchanged and the finding's `file`/`line` matches an
+  entry in `DECLINED_FINDINGS` (step 2a-1), downgrade the finding to
+  `info` severity and prepend to its description: "Previously raised
+  and declined as out of scope by @<login> (<author_association>) —
Relevance

●●● Strong

Clear correctness inconsistency: decline matching should include category/description as earlier
step states.

PR-#49

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The workflow records declines with file/line but then applies them to any matching
file/line, while the doc explicitly supports multiple findings with different categories at the
same location; this creates an over-broad match that can downgrade the wrong finding.

skills/pr-review/SKILL.md[874-904]
skills/pr-review/SKILL.md[306-312]
skills/pr-review/SKILL.md[1122-1136]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The new trusted-decline mechanism records declines without a stable discriminator (it stores only `file`/`line` + decliner metadata), but later applies the decline to any finding at the same `file`/`line`. This is incorrect because the orchestrator explicitly allows multiple distinct findings (different categories) at the same location.

### Issue Context
- Step 6c keeps different-category findings separate even when they reference the same code.
- Step 2a-1 says to identify the corresponding prior finding using “matching category/description”, but the recorded `DECLINED_FINDINGS` entry does not retain category/identity.
- Step 6e applies the downgrade using only `file`/`line` equality.

### Fix Focus Areas
- skills/pr-review/SKILL.md[306-312]
- skills/pr-review/SKILL.md[1122-1136]
- skills/pr-review/SKILL.md[895-904]

### Concrete fix
- Extend `DECLINED_FINDINGS` entries to include at least `category` (and ideally a stable identifier such as the root comment `id`, plus a short hash of the prior finding’s description).
- In step 6e, require `file` + `line` + `category` (and/or the stable identifier) to match before downgrading.
- If multiple prior findings exist at the same location, only downgrade the one(s) explicitly declined.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Protected skills file modified 📜 Skill insight § Compliance
Description
This PR modifies skills/pr-review/SKILL.md, which is a protected governance/infrastructure path
and must not be auto-approved. Ensure explicit human review/approval is required before merge.
Code

skills/pr-review/SKILL.md[R253-256]

+### 2a-1. Trusted dismissals of prior findings (re-reviews)
+
+**Status: experimental.** This step narrows one specific case of
+[agents#106](https://github.com/fullsend-ai/agents/issues/106) — a
Relevance

●● Moderate

Protected-path gating is policy-like; prior similar notes exist but outcomes were undetermined.

PR-#59
PR-#157

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The compliance checklist requires raising a finding whenever protected governance/infrastructure
paths (including skills/) are modified to ensure the PR is not auto-approved. The diff shows new
content added to skills/pr-review/SKILL.md, which is under the protected skills/ path.

skills/pr-review/SKILL.md[253-256]
Skill: pr-review

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
This PR modifies a protected path (`skills/`), which must not be auto-approved.

## Issue Context
Protected governance/infrastructure paths require explicit human review/approval before merge.

## Fix Focus Areas
- skills/pr-review/SKILL.md[253-256]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Unbounded comments fetch 🐞 Bug ☼ Reliability
Description
Step 2a-1 aggregates all PR review comments across all pages into a single JSON blob and suggests
per-user permission fallback checks without any deduping/caching guidance. On PRs with large
review-comment histories or many replies requiring fallback checks, this can significantly increase
API calls and payload size, making re-reviews slower and more failure-prone.
Code

skills/pr-review/SKILL.md[R271-273]

+REVIEW_COMMENTS=$(gh api "repos/${REPO_FULL_NAME}/pulls/${PR_NUMBER}/comments?per_page=100" \
+  --paginate | jq -s 'add // []')
+```
Relevance

●● Moderate

Perf/scaling guidance for paginated gh api fetch is plausible but no close accepted/rejected
precedent.

PR-#172

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new instructions explicitly fetch all review comments with pagination and then introduce a
collaborator-permission fallback path; without guidance to filter fields or dedupe calls, this can
scale poorly on PRs with many comments/replies.

skills/pr-review/SKILL.md[268-273]
skills/pr-review/SKILL.md[285-293]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The new step fetches the full review-comment payload for the entire PR (`--paginate` + `jq -s 'add'`), which can be large, and it introduces potential repeated collaborator-permission lookups for multiple replies from the same user.

### Issue Context
This is an orchestrator/runtime reliability concern: large API payloads and redundant follow-up API calls can increase latency and raise the chance of hitting rate limits or tool/output constraints in long-lived PRs.

### Fix Focus Areas
- skills/pr-review/SKILL.md[268-273]
- skills/pr-review/SKILL.md[285-293]

### Concrete fix
- Reduce payload size by using `--jq` (or a `jq` projection) to keep only the needed fields (e.g., `id`, `in_reply_to_id`, `path`, `line`, `user.login`, `author_association`, `body`, `performed_via_github_app.slug`).
- Ensure you only consider replies whose thread root is from the app before doing any collaborator-permission API calls.
- Cache/dedupe collaborator-permission lookups per `login` (one call per unique user per run).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context used
✅ Compliance rules (platform): 55 rules
✅ Skills: 4 invoked
  code-review
  code-implementation
  pr-review
  docs-review

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread skills/pr-review/SKILL.md
Comment on lines +253 to +256
### 2a-1. Trusted dismissals of prior findings (re-reviews)

**Status: experimental.** This step narrows one specific case of
[agents#106](https://github.com/fullsend-ai/agents/issues/106) — a

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Protected skills file modified 📜 Skill insight § Compliance

This PR modifies skills/pr-review/SKILL.md, which is a protected governance/infrastructure path
and must not be auto-approved. Ensure explicit human review/approval is required before merge.
Agent Prompt
## Issue description
This PR modifies a protected path (`skills/`), which must not be auto-approved.

## Issue Context
Protected governance/infrastructure paths require explicit human review/approval before merge.

## Fix Focus Areas
- skills/pr-review/SKILL.md[253-256]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread skills/pr-review/SKILL.md
Comment on lines +1130 to +1133
- If the file is unchanged and the finding's `file`/`line` matches an
entry in `DECLINED_FINDINGS` (step 2a-1), downgrade the finding to
`info` severity and prepend to its description: "Previously raised
and declined as out of scope by @<login> (<author_association>) —

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. Decline key too broad 🐞 Bug ≡ Correctness

Step 6e downgrades findings based only on file/line membership in DECLINED_FINDINGS, which can
incorrectly downgrade a different-category finding at the same location even though step 6c
explicitly preserves distinct-category findings at the same file/line. This can suppress legitimate
medium/high findings on re-review and distort the final verdict.
Agent Prompt
### Issue description
The new trusted-decline mechanism records declines without a stable discriminator (it stores only `file`/`line` + decliner metadata), but later applies the decline to any finding at the same `file`/`line`. This is incorrect because the orchestrator explicitly allows multiple distinct findings (different categories) at the same location.

### Issue Context
- Step 6c keeps different-category findings separate even when they reference the same code.
- Step 2a-1 says to identify the corresponding prior finding using “matching category/description”, but the recorded `DECLINED_FINDINGS` entry does not retain category/identity.
- Step 6e applies the downgrade using only `file`/`line` equality.

### Fix Focus Areas
- skills/pr-review/SKILL.md[306-312]
- skills/pr-review/SKILL.md[1122-1136]
- skills/pr-review/SKILL.md[895-904]

### Concrete fix
- Extend `DECLINED_FINDINGS` entries to include at least `category` (and ideally a stable identifier such as the root comment `id`, plus a short hash of the prior finding’s description).
- In step 6e, require `file` + `line` + `category` (and/or the stable identifier) to match before downgrading.
- If multiple prior findings exist at the same location, only downgrade the one(s) explicitly declined.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread skills/pr-review/SKILL.md
Comment on lines +271 to +273
REVIEW_COMMENTS=$(gh api "repos/${REPO_FULL_NAME}/pulls/${PR_NUMBER}/comments?per_page=100" \
--paginate | jq -s 'add // []')
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

3. Unbounded comments fetch 🐞 Bug ☼ Reliability

Step 2a-1 aggregates all PR review comments across all pages into a single JSON blob and suggests
per-user permission fallback checks without any deduping/caching guidance. On PRs with large
review-comment histories or many replies requiring fallback checks, this can significantly increase
API calls and payload size, making re-reviews slower and more failure-prone.
Agent Prompt
### Issue description
The new step fetches the full review-comment payload for the entire PR (`--paginate` + `jq -s 'add'`), which can be large, and it introduces potential repeated collaborator-permission lookups for multiple replies from the same user.

### Issue Context
This is an orchestrator/runtime reliability concern: large API payloads and redundant follow-up API calls can increase latency and raise the chance of hitting rate limits or tool/output constraints in long-lived PRs.

### Fix Focus Areas
- skills/pr-review/SKILL.md[268-273]
- skills/pr-review/SKILL.md[285-293]

### Concrete fix
- Reduce payload size by using `--jq` (or a `jq` projection) to keep only the needed fields (e.g., `id`, `in_reply_to_id`, `path`, `line`, `user.login`, `author_association`, `body`, `performed_via_github_app.slug`).
- Ensure you only consider replies whose thread root is from the app before doing any collaborator-permission API calls.
- Cache/dedupe collaborator-permission lookups per `login` (one call per unique user per run).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@waynesun09 waynesun09 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Review sweep: 9 findings from an independent review pass (1 critical, 2 high, 6 medium), verified against live GitHub API data and the PR's own cited motivating example (agents PR #90). None overlap in substance with the existing qodo-code-review bot comments on this PR (protected-path, decline-key category collision, unbounded comments fetch) — see inline comments for details.

Comment thread skills/pr-review/SKILL.md
its reply chain — follow `in_reply_to_id` links (via a lookup keyed by
`id`, built from `REVIEW_COMMENTS`) until reaching a comment with no
`in_reply_to_id`. Skip the thread unless the root comment's
`performed_via_github_app.slug` is `fullsend-ai-review`. This field is

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

CRITICAL: performed_via_github_app is absent on pulls/{pr}/comments, so DECLINED_FINDINGS can never populate

Step 2a-1 gates "is this thread rooted in one of the review bot's own findings" on root_comment.performed_via_github_app.slug == 'fullsend-ai-review' (lines 278-283), but the pulls/{pr}/comments endpoint this step queries does not return a performed_via_github_app key at all.

Verified live: gh api repos/fullsend-ai/agents/pulls/comments/3554494103 (the exact fullsend-ai-review[bot] finding on PR #90 that issue #106 cites as the motivating example) returns a JSON object whose key list has no performed_via_github_app entry; the identical check against this PR's own review comments also shows the field absent/null. Since every thread root fails the slug check, DECLINED_FINDINGS will always be empty and the entire step 2a-1 / step 6e mechanism this PR adds never activates against real PRs.

Suggestion: confirm (as done above) that performed_via_github_app is never populated on pulls/{pr}/comments for this app's installation-token usage, then switch the provenance check to a signal that endpoint actually returns -- e.g. user.login == 'fullsend-ai-review[bot]' plus a stable machine-readable marker embedded in the finding body -- rather than a field this endpoint never sets.

Comment thread skills/pr-review/SKILL.md
review at the same file and line (matched via `prior_findings`, step
3a):

- If the file is in `changed_since_prior` (step 2a) — the code changed

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

HIGH: File-level changed_since_prior gate plus exact-line matching would still re-raise the PR's own cited motivating example

Step 6e only applies a decline when the file is unchanged since PRIOR_REVIEW_SHA (file-granular, step 2a) and the finding's file/line exactly matches the DECLINED_FINDINGS entry. Replaying the real inline-comment history of PR #90 (gh api repos/fullsend-ai/agents/pulls/90/comments) -- the exact PR issue #106 cites as motivation -- shows the same github-env-injection finding raised at line 188 and declined by a MEMBER ("pre-existing pattern, out of scope for this PR"), raised again at line 187 in a later round and declined again nearly verbatim, then raised yet again at line 178 in a further round. Because the file changed between every round (that's why the line drifted 188->187->178), changed_since_prior would include the file every time, so step 6e's own guard refuses to apply the decline regardless of DECLINED_FINDINGS -- and the drifting line number would fail the file/line match anyway. The feature as designed does not fix the case it cites as its own motivating example.

Suggestion: match declined findings by something more stable than exact file:line on a byte-unmodified file -- e.g. anchor on the diff hunk context or a normalized snippet of surrounding code -- rather than requiring the whole file to be unchanged since the decline.

Comment thread skills/pr-review/SKILL.md
review at the same file and line (matched via `prior_findings`, step
3a):

- If the file is in `changed_since_prior` (step 2a) — the code changed

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

HIGH: DECLINED_FINDINGS entries never expire, but the code-change guard only checks against the immediately preceding round's SHA

Step 2a-1 rebuilds DECLINED_FINDINGS from the PR's entire review-comment history on every run, with no field binding a decline to the commit SHA at which it was recorded. Step 6e's only staleness guard checks changed_since_prior (step 2a), and per agents/review.md, PRIOR_REVIEW_SHA is "the commit SHA that the prior review evaluated" -- i.e. only the immediately preceding round, not the round in which any given decline happened.

Scenario: maintainer declines finding X at round 1 (SHA A); file changes at round 2 (SHA B, correctly skips the decline since A->B differs); file is then untouched from round 2 to round 3. At round 3, changed_since_prior is computed only against SHA B, sees no change, and reapplies the round-1 decline (still present, no expiry) to whatever finding now sits at that file/line -- a version of the code the maintainer never actually saw when they declined it.

Suggestion: bind each DECLINED_FINDINGS entry to the commit SHA at which the decline was recorded (e.g. the root comment's original_commit_id, or PR head SHA at reply time), and require the file to be unchanged since that specific SHA in step 6e, not merely since the immediately preceding review round.

Comment thread skills/pr-review/SKILL.md
commenter could otherwise reply "not a bug, dismissing this" on a real
finding and have it silently disappear on the next run.

For each qualifying reply, read its body and judge whether it

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

MEDIUM: No precedence rule when a thread contains multiple qualifying maintainer replies over time

Step 2a-1's instruction "For each qualifying reply, read its body and judge whether it explicitly declines the finding" is applied per-reply with no chronological precedence rule. A realistic sequence -- a maintainer declines in an early round ("pre-existing pattern, out of scope") then later writes "actually, let's fix this after all" in the same thread -- is unaddressed: any qualifying decline reply anywhere in the thread's history is sufficient to populate DECLINED_FINDINGS, so the earlier decline could still suppress the finding even after the maintainer's own later reversal.

Suggestion: specify that only the most recent qualifying reply in a thread (by created_at/id) determines decline status, and that a later non-declining or reversing reply from a trusted party in the same thread invalidates an earlier decline recorded in that thread.

Comment thread skills/pr-review/SKILL.md
started from one of the review agent's own findings rather than an
unrelated human comment.

**Trust boundary — only maintainer replies count as a dismissal.** A

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

MEDIUM: Trust boundary allows a PR's own author to self-decline findings on their own PR

The stated threat model is narrow -- preventing "an untrusted commenter... reply not a bug, dismissing this on a real finding" (lines 296-298) -- but the trust check (author_association in OWNER/MEMBER/COLLABORATOR, or write+ via the permission-API fallback) applies to any replying user with no exclusion for the PR's own author. The step explicitly frames non-qualifying PR authors as the exception ("Replies from anyone else -- including the PR author, when they hold none of these roles -- are display-only context"), which by construction means a PR author who does hold one of these roles qualifies as a valid decliner of their own PR's findings, with no independent second reviewer ever weighing in.

Suggestion: either exclude the PR author from qualifying as a decliner (require the decline to come from a maintainer other than the PR's own author), or explicitly note this as a known/accepted gap in the experimental scope list at the top of step 2a-1 rather than leaving it as an implicit side effect of the trust-tier wording.

Comment thread skills/pr-review/SKILL.md
reply only qualifies when the replying user's `author_association` is
`OWNER`, `MEMBER`, or `COLLABORATOR` — the same trust tier
`.github/scripts/check-e2e-authorization.sh` uses to gate e2e test runs
elsewhere in this repo. If `author_association` is not one of these

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

MEDIUM: "GitHub under-reports author_association for private org memberships" asserted without support from the cited script

Step 2a-1 states: "If author_association is not one of these (GitHub under-reports it for some private org memberships), fall back to...". The actual cited script on this PR's branch, .github/scripts/check-e2e-authorization.sh, documents the equivalent fallback only as resolving "correctly regardless of membership visibility" -- it never describes author_association as under-reporting or buggy. SKILL.md asserts a specific, uncited claim about GitHub's API behavior as settled fact, when the source it points to for justification documents a defense-in-depth design choice, not a known API limitation.

Suggestion: either cite an actual GitHub-documented limitation describing this under-reporting behavior, or soften the language to describe the fallback as defense-in-depth for membership-visibility edge cases (matching what check-e2e-authorization.sh actually documents), not a fix for an under-reporting bug.

Comment thread skills/pr-review/SKILL.md
for this PR," "won't fix," "not a bug"). A question, a partial fix, or
an acknowledgment that does not decline the finding does not qualify.

For each finding a maintainer explicitly declined, cross-reference the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

MEDIUM: No fallback to original_line when GitHub nulls out line on outdated review comments

Step 2a-1's cross-reference of the thread root against prior findings reads path/line off the root comment with no mention of original_line. GitHub's review-comments API returns line: null (original_line retains the value) once a comment's diff position is marked outdated. Verified with live data: PR #90's comment 3554472931 has line: null, original_line: 165 -- a comment that went stale within the very first round considered. Whenever this happens to a thread this step needs to identify, the cross-reference has no line value to match against prior findings, and the mechanism silently fails to recognize an otherwise-legitimate decline.

Suggestion: when the thread root's line (or start_line) is null, fall back to original_line/original_start_line both for the step 2a-1 cross-reference and for the DECLINED_FINDINGS record.

Comment thread skills/pr-review/SKILL.md
`DECLINED_FINDINGS` is non-empty, so it has no effect until a
maintainer has actually declined a prior finding via a reply.

For each finding in the merged set that also appeared in the prior

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

MEDIUM: Step 6e cites step 3a for file/line matching that step 3a never defines

Step 6e's "Declined findings" check requires a finding to have "also appeared in the prior review at the same file and line (matched via prior_findings, step 3a)". Step 3a only describes grouping prior findings by review dimension using category as the key -- it defines no file/line matching procedure at all. An executing agent has no concrete, previously-established rule for "same file and line" (exact equality, or within step 6a's 5-line grouping tolerance?), leaving matching behavior to ad hoc interpretation -- exactly the kind of imprecision that lets the category-collision issue (already flagged elsewhere on this PR) go unnoticed.

Suggestion: either add an explicit file/line matching rule to step 3a (or a new sub-step) and reference it correctly from step 6e, or spell out the matching rule directly in the "Declined findings" section instead of citing a step that doesn't define it.

Comment thread skills/pr-review/SKILL.md
silently truncates file lists at 300 files), treat all files as
changed — no anchoring for this run.

### 2a-1. Trusted dismissals of prior findings (re-reviews)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

MEDIUM: Experimental decline-detection heuristics merge into the live pipeline with the PR's own manual-verification checkboxes unchecked

The PR's test plan states SKILL.md has no automated test harness and lists two unchecked, manual-only items: "Observe behavior on a real PR where a maintainer declines a finding via reply, across 2+ subsequent pushes..." and "Confirm a decline reply from a non-maintainer... is not honored." Both boxes remain unchecked on the current PR body. This step merges directly into SKILL.md, which every future pr-review invocation on every repo executes live, with no feature flag or dry-run gate beyond the "experimental" prose label. Notably, the first unchecked item -- observing behavior on a real PR -- is exactly the kind of manual check that would have surfaced the performed_via_github_app bug identified in this same review before merge.

Suggestion: hold this PR until at least one real-world round-trip is observed and documented (which would likely have caught the performed_via_github_app issue), or land it behind an explicit opt-in/kill-switch so a bad decline-classification can be disabled without reverting the whole change.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants