Skip to content

feat: support robust inline PR review comments#39

Merged
menny merged 17 commits intomainfrom
feature/inline-comments
Apr 11, 2026
Merged

feat: support robust inline PR review comments#39
menny merged 17 commits intomainfrom
feature/inline-comments

Conversation

@menny
Copy link
Copy Markdown
Owner

@menny menny commented Apr 11, 2026

Implement support for posting inline comments to GitHub PRs based on structured AI review output.

This PR provides a hardened implementation of inline reviews:

  • Separated Feedback: Distinguishes between 'main' architectural comments and 'atomic' inline line-level feedback.
  • Robust Tagging: Uses unique tags for different comment types to ensure accurate deduplication and identification.
  • Resilience: Includes a 422 error fallback to prevent lost reviews due to LLM line hallucinations.
  • Safety: Validates review actions and author identity before performing updates.
  • Configurable: Controllable via use_inline_comments and submit_review_action flags in action.yml.

Fixes #26

menny added 6 commits April 11, 2026 09:17
Introduce 'use_inline_comments' action input to toggle between a single
summary comment and a full GitHub PR Review with inline file comments.
- Update StructuredReview schema to include 'action' (APPROVE/REQUEST_CHANGES/COMMENT).
- Implement 'post-structured-review' in the GitHub utility to parse JSON
  findings and post them as atomic review comments.
- Add deduplication logic to avoid repeating the same comment at the
  same location.
- Enhance extraction prompt to guide the LLM on sentiment-to-action mapping.
- Set 'submit_review_action: true' in the Cassandra Review workflow to
  allow actual APPROVE/REQUEST_CHANGES submissions.
- Verified 'allowReviewAction' logic with TestPostStructuredReview_OverrideAction
  in cmd/github/main_test.go.
- Verified that the GITHUB_TOKEN needs 'pull-requests: write' permission
  for these actions (already present in the workflow).
Update postStructuredReview to post the non-specific review as its own
standalone comment, while using Approval.Rationale exclusively as the
body of the GitHub Pull Request Review. This aligns with the original
requirement for a 'main (non-specific) comment' and an 'atomic review'.
- Use a 'comment-' prefix for inline review comment tags to fix deduplication.
- Update postCommentText to only update comments authored by the bot.
- Update getMetadata to correctly identify 'self' comments for both main and inline types.
- Ensure unit tests cover the new tag distinguishing logic and author checks.
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Rejected due to a critical crash risk with the GitHub Actions default GITHUB_TOKEN on the /user endpoint and silently ignored metadata read errors.

Comment thread cmd/github/main.go
Comment on lines +172 to 175
}
selfLogin := self.GetLogin()

// Find existing comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The GET /user endpoint (client.Users.Get(ctx, "")) fails with a 403 Resource not accessible by integration when called using the standard GitHub Actions GITHUB_TOKEN (which acts as an installation access token). Because this error is returned directly, it will crash the entire action for users relying on default permissions. You must handle this error gracefully (e.g., logging a warning and falling back to relying solely on the unique tag for identification) or remove the user lookup entirely.

Comment thread cmd/github/main.go
Comment on lines +318 to +322
var metadata core.PRMetadata
if metadataFile != "" {
metadataBytes, err := os.ReadFile(metadataFile)
if err == nil {
if err := json.Unmarshal(metadataBytes, &metadata); err != nil {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

If metadataFile is provided but os.ReadFile fails, the error is silently ignored because of the if err == nil branch. If this file fails to read (due to missing paths or permissions), the process continues with an empty metadata object, which will silently break the comment deduplication logic. We should explicitly check if err != nil and log a warning to make it auditable.

- Gracefully handle 403 errors when calling /user with default GITHUB_TOKEN.
- Log warning and fallback to tag-only identification for comment updates.
- Explicitly log warning if metadata file read fails.
- Add unit test for GetUser error scenario.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 11, 2026

Regarding the structured review posting logic: if needsRetry == false, the unconditional CreateReview is called and fails, causing errRetry != nil to be true. It then enters the block, strips comments, and retries. Making an extra HTTP request that is guaranteed to fail is inefficient and presents a clear logic flaw.

@github-actions github-actions Bot dismissed their stale review April 11, 2026 18:12

Superseded by a new AI review.

- Add specific fallback for 'GitHub Actions is not permitted to approve pull requests' error.
- Refine multi-level 422 fallback logic to handle both permissions and line hallucinations.
- Ensure postCommentText only updates comments authored by the current bot user.
- Mock missing endpoints in tests to avoid 405 errors and verify new resilience logic.
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Identified a logic flaw in the retry mechanism causing inefficient HTTP requests, though core review types are consistent.

  • core/review_types.go (file-level): The Approval type and JSON schema definitions are fully consistent.

- Implement location-based inline comment syncing (Update existing vs Create new).
- Distinguish comment types with unique tag prefixes (main vs inline).
- Automatically cleanup redundant architecture comments in postCommentText.
- Defer review dismissal until after successful submission of the new review.
- Add 'outdated' detection for inline comments to prevent stale updates.
- Hardened unit tests for all new state management and syncing logic.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 11, 2026

[Observation]: The PR description states "Validates review actions and author identity before performing updates." However, author identity verification is missing from getMetadata, dismissPreviousReviews, and postStructuredReview. The implementation does not fully align with this claim. This is a fantastic and highly resilient implementation overall! The multi-stage fallback logic for 422 errors and permission downgrades is exceptionally solid, and the updated parsing logic is well-tested. Once the sequence of operations and author validations are corrected, this will be ready to merge.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

The PR provides an excellent and hardened implementation of inline comments with robust fallback mechanics. Previous PR comments are well addressed and edge-cases are explicitly tested. Only minor observations regarding fallback logic logging and formatting were noted.

- Dismiss previous reviews BEFORE posting new ones.
- Support optional deletion of old inline comments via 'delete_old_comments' flag.
- Simplify and fix the 422 fallback logic for both permissions and hallucinations.
- Ensure only one persistent architecture comment exists by cleaning duplicates.
- Added comprehensive unit tests for deletion and dismissal logic.
@github-actions github-actions Bot dismissed their stale review April 11, 2026 19:55

Superseded by a new AI review.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

The PR establishes a highly resilient foundation for inline PR reviews but requires security fixes for workflow inputs to prevent command injection.

- Use environment variables for all shell script arguments in action.yml to prevent command injection.
- Optimize 422 fallback in cmd/github/main.go to skip redundant retries when no request changes are made.
- Verified with unit tests and formatting.
@github-actions github-actions Bot dismissed their stale review April 11, 2026 20:20

Superseded by a new AI review.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

The reviewer noted that the use of DismissReview instead of DeleteReview is appropriate and accepted behavior for managing old AI reviews without cluttering the timeline.

Detailed Inline Feedback (Fallback)

  • cmd/github/main.go (43): postCommentText updates the same issue comment, so it only takes up one slot in the timeline. Wait, if the AI leaves a review with reviewRationale, that text will be posted 5 times, cluttering the timeline. However, PR reviews can be deleted. Can they? The GitHub API has DeletePendingReview, but not for submitted reviews. Actually, you can delete a Pull Request Review? Let's check. Is there a client.PullRequests.DeleteReview()? Yes, DELETE /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}. Wait, that only deletes pending reviews. Submitted reviews cannot be deleted via the API. Wait, I am an AI, I should be skeptical of my internal knowledge. Let's use read_file to check cmd/github/main.go or mock library to see if DeleteReview is used. Wait, the author uses DismissReview, not DeleteReview. This is the standard way to handle old reviews. So it's fine. It's an accepted behavior.

- Document 'post-structured-review' action and improved 'post-comment' logic.
- Add 'Review Resilience & State Management' section to DESIGN.md.
- Highlight Inline PR Reviews in README.md features.
- Update GitHub Action inputs table with new configuration flags.
- Updated JSON schema documentation.
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

The PR establishes a strong foundation but requires logic fixes for the fallback flow and tag formatting.

menny added 3 commits April 11, 2026 16:33
- Introduce wrapTag helper to safely wrap and sanitize tag slugs.
- Remove global tag wrapping in main() to prevent brittle string replacements.
- Ensure consistent use of type-specific tag prefixes.
- Added sanitization to prevent HTML comment breakout.
- Updated all unit tests to verify new tagging and sanitization logic.
…ion errors

- Implement multi-stage 422 fallback logic.
- Try downgrading to 'COMMENT' while keeping inline comments if APPROVE is not permitted.
- Only strip inline comments if the 422 error persists (likely due to line hallucinations).
- Updated unit tests to verify the prioritized preservation of inline feedback.
Ensure that pagination logic in postCommentText is verified alongside the
new cleanup redundant comments logic.
@github-actions github-actions Bot dismissed their stale review April 11, 2026 20:38

Superseded by a new AI review.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

The approach to deduplication and edge cases is robust, but there is a critical logical flow issue in the 422 fallback handler that strips inline comments incorrectly due to permission errors.

@github-actions github-actions Bot dismissed their stale review April 11, 2026 20:40

Superseded by a new AI review.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

The PR establishes a highly resilient foundation for inline PR reviews, but requires a few logic fixes for the fallback flow and test coverage before it can be merged.

@github-actions github-actions Bot dismissed their stale review April 11, 2026 20:40

Superseded by a new AI review.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

The implementation is highly resilient and addresses previous feedback perfectly, but is rejected because the new parsing logic lacks a corresponding test file.

Add core/review_types_test.go to verify:
- Empty strings and file-level comments.
- Single line parsing.
- Valid range parsing (10-20).
- Inverted range parsing (swapping 20-10 to 10-20).
- Whitespace handling within range strings.
- Malformed inputs and extra hyphens.
@github-actions github-actions Bot dismissed their stale review April 11, 2026 20:46

Superseded by a new AI review.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

There are unresolved issues related to duplicate comments during 422 fallback, missing author verification before dismissing reviews, and dismissing previous reviews before creating a new one.

- Filter fallback inline feedback to skip already-appended file-level comments.
- Update TestPostStructuredReview_422Fallback to verify no duplicate feedback.
- Ensured all tests correctly verify the multi-stage fallback logic.
@github-actions github-actions Bot dismissed their stale review April 11, 2026 20:53

Superseded by a new AI review.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

The implementation needs correction in the sequence of operations (posting the new review before dismissing previous ones) and requires author identity verification to prevent deleting or dismissing human users' comments.

Detailed Inline Feedback (Fallback)

  • cmd/github/main.go (368-384): The dismissPreviousReviews and deleteOldComments operations are executed before attempting client.PullRequests.CreateReview. If the API fails to create the new review (e.g., due to a network error or an unhandled 422), all previous review state is permanently lost. This violates the principle of resilience. We must post the new review first. If it succeeds, we can then pass its ID to dismissPreviousReviews as the skipReviewID, and safely perform the comment cleanup. Be mindful that when you move this logic to the end of the function, you must ensure the early returns in the 422 fallback block (e.g., line 459) do not accidentally bypass the cleanup.
  • cmd/github/main.go (277-315): IsSelf is determined solely by checking for the presence of the tag. If a human user replies to the bot and quotes its inline comment, their comment will be erroneously marked IsSelf: true. Because postStructuredReview unconditionally deletes IsSelf inline comments, the human user's comment will be silently deleted. We must fetch the bot's selfLogin (gracefully handling the 403 fallback, just like in postCommentText) and verify c.GetUser().GetLogin() == selfLogin before marking a comment as IsSelf.
  • cmd/github/main.go (501-526): As noted in the previous PR feedback, dismissPreviousReviews still dismisses any review containing the tag without checking the author. A human user manually using the tag or quoting the bot's review will have their review inappropriately dismissed, causing noise or permission errors. We should pass the fetched selfLogin to this function and verify the review author before dismissing.

@menny menny merged commit 91d7ca0 into main Apr 11, 2026
2 checks passed
@menny menny deleted the feature/inline-comments branch April 11, 2026 20:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

comment on files+lines where review specifies those

1 participant