Shared reference for fetching, filtering, and classifying Greptile review comments on GitHub PRs. Used by both /review and /ship skills. Includes parallel API fetching, suppressions check, classification logic, reply APIs, and history file writes.
4.3 KiB
Greptile Comment Triage
Shared reference for fetching, filtering, and classifying Greptile review comments on GitHub PRs. Both /review (Step 2.5) and /ship (Step 3.75) reference this document.
Fetch
Run these commands to detect the PR and fetch comments. Both API calls run in parallel.
REPO=$(gh repo view --json nameWithOwner --jq '.nameWithOwner' 2>/dev/null)
PR_NUMBER=$(gh pr view --json number --jq '.number' 2>/dev/null)
If either fails or is empty: Skip Greptile triage silently. This integration is additive — the workflow works without it.
# Fetch line-level review comments AND top-level PR comments in parallel
gh api repos/$REPO/pulls/$PR_NUMBER/comments \
--jq '.[] | select(.user.login == "greptile-apps[bot]") | select(.position != null) | {id: .id, path: .path, line: .line, body: .body, html_url: .html_url, source: "line-level"}' > /tmp/greptile_line.json &
gh api repos/$REPO/issues/$PR_NUMBER/comments \
--jq '.[] | select(.user.login == "greptile-apps[bot]") | {id: .id, body: .body, html_url: .html_url, source: "top-level"}' > /tmp/greptile_top.json &
wait
If API errors or zero Greptile comments across both endpoints: Skip silently.
The position != null filter on line-level comments automatically skips outdated comments from force-pushed code.
Suppressions Check
Read ~/.gstack/greptile-history.md if it exists. Each line records a previous triage outcome:
<date> | <repo> | <type:fp|fix|already-fixed> | <file-pattern> | <category>
Categories (fixed set): race-condition, null-check, error-handling, style, type-safety, security, performance, correctness, other
Match each fetched comment against entries where:
type == fp(only suppress known false positives, not previously fixed real issues)repomatches the current repofile-patternmatches the comment's file pathcategorymatches the issue type in the comment
Skip matched comments as SUPPRESSED.
If the history file doesn't exist or has unparseable lines, skip those lines and continue — never fail on a malformed history file.
Classify
For each non-suppressed comment:
- Line-level comments: Read the file at the indicated
path:lineand surrounding context (±10 lines) - Top-level comments: Read the full comment body
- Cross-reference the comment against the full diff (
git diff origin/main) and the review checklist - Classify:
- VALID & ACTIONABLE — a real bug, race condition, security issue, or correctness problem that exists in the current code
- VALID BUT ALREADY FIXED — a real issue that was addressed in a subsequent commit on the branch. Identify the fixing commit SHA.
- FALSE POSITIVE — the comment misunderstands the code, flags something handled elsewhere, or is stylistic noise
- SUPPRESSED — already filtered in the suppressions check above
Reply APIs
When replying to Greptile comments, use the correct endpoint based on comment source:
Line-level comments (from pulls/$PR/comments):
gh api repos/$REPO/pulls/$PR_NUMBER/comments/$COMMENT_ID/replies \
-f body="<reply text>"
Top-level comments (from issues/$PR/comments):
gh api repos/$REPO/issues/$PR_NUMBER/comments \
-f body="<reply text>"
If a reply POST fails (e.g., PR was closed, no write permission): warn and continue. Do not stop the workflow for a failed reply.
History File Writes
Before writing, ensure the directory exists:
mkdir -p ~/.gstack
Append one line per triage outcome to ~/.gstack/greptile-history.md:
<YYYY-MM-DD> | <owner/repo> | <type> | <file-pattern> | <category>
Example entries:
2026-03-13 | garrytan/myapp | fp | app/services/auth_service.rb | race-condition
2026-03-13 | garrytan/myapp | fix | app/models/user.rb | null-check
2026-03-13 | garrytan/myapp | already-fixed | lib/payments.rb | error-handling
Output Format
Include a Greptile summary in the output header:
+ N Greptile comments (X valid, Y fixed, Z FP)
For each classified comment, show:
- Classification tag:
[VALID],[FIXED],[FALSE POSITIVE],[SUPPRESSED] - File:line reference (for line-level) or
[top-level](for top-level) - One-line body summary
- Permalink URL (the
html_urlfield)