utilities

Manage Pr Comments

Review open GitHub PR comments, propose accept/reject/defer decisions, implement accepted changes, post replies, and resolve threads with resilient, project-agnostic execution.

Manage PR Comments

Purpose

Use this skill to run an end-to-end PR comment handling workflow:

  1. Discover open PR feedback
  2. Classify and prioritize actionable comments
  3. Propose decisions (accept, reject, defer, needs-split)
  4. Get user confirmation before write actions
  5. Implement accepted code changes
  6. Reply to comments with evidence
  7. Resolve review threads when appropriate

This skill is designed to be universal across company repositories and must not rely on project-specific build/test commands.

Non-Goals

  • Do not commit, push, merge, or force-push.
  • Do not assume one language/framework/toolchain.
  • Do not auto-accept low-confidence or ambiguous requests.

Run Modes

  • analyze-only: discover + classify + summarize, no writes.
  • propose: include decision proposals and draft replies, no writes.
  • execute: perform approved changes/replies/resolutions.

Default mode: propose.

Inputs

Required

  • PR target:
    • Default: active/current PR context
    • Optional override: {owner, repo, prNumber}
  • Explicit user confirmation for any write operation in execute mode

Optional

  • Decision map (pre-approved dispositions per comment)
  • Verification strictness (minimal, standard, strict)
  • Max retries, timeout budget

Outputs

  • Comment inventory (open/actionable/skipped)
  • Decision table (proposed + confirmed)
  • Execution report (implemented, replied, resolved, deferred, failed)
  • Verification summary (detected checks run + results)
  • Handoff note that developer handles commit/push/merge

Capability & Permission Preflight (Mandatory)

Before discovery, detect and record:

  1. API/tool capabilities (fetch comments, reply, resolve thread)
  2. Auth scopes and write permissions
  3. PR topology constraints:
    • same-repo vs fork
    • branch protection constraints
    • whether source branch is writable
  4. Integration path selection:
    • Prefer native PR management tools when available
    • Fall back to GitHub CLI/API only for unsupported operations
    • Record which operation uses which path

If write capability is missing, downgrade to propose and return actionable instructions.

GitHub Integration (gh CLI + GraphQL)

Use gh as the command surface and prefer GraphQL for thread-centric operations.

Command Discipline

  • Execute one command at a time.
  • Avoid shell chaining (&&, ;) to keep failures isolated.
  • Log every mutating operation with: timestamp, operation name, target id, result.

Non-Interactive Shell Hardening (Pager Safety)

Before running any gh command, force non-interactive output in the shell session:

export GH_PAGER=cat
export PAGER=cat
export LESS=FRX

Additional safeguards:

  • Prefer JSON mode (--json / gh api) for machine-readable output.
  • For long API responses, pipe through jq or write to a temp file instead of opening a pager.
  • If a command still enters alternate buffer, stop and rerun with explicit env prefix:
GH_PAGER=cat PAGER=cat gh <command>
  • Treat pager entry as a recoverable integration error and record it in the run report.

Auth and Access Preflight

Run these checks before any read/write workflow:

gh auth status
gh repo view OWNER/REPO
gh pr view PR_NUMBER --repo OWNER/REPO --json number,state,isDraft,headRefName,headRepositoryOwner,maintainerCanModify

If any command fails due to permissions, downgrade to propose mode and provide a handoff plan.

Data Retrieval (GraphQL Preferred)

Schema-Safe Query Strategy (Mandatory)

Do not assume GraphQL fields exist across all GitHub environments/versions.

  1. Start with a conservative base query (only widely available fields).
  2. If additional fields are needed, add them incrementally in small query edits.
  3. On undefinedField errors, remove unsupported fields and retry immediately.
  4. Record unsupported fields in the run report and continue with degraded metadata.

Known variable fields that may be unavailable and must be optional in the workflow:

  • PullRequestReviewThread.updatedAt
  • PullRequestReviewComment.diffSide

If those fields are absent, use fallback fields already in the base model (comments.nodes.updatedAt, position, originalPosition, line, originalLine).

Optional Schema Probe

When a run repeatedly fails due to schema mismatch, probe schema support before building full queries:

gh api graphql -f query='query { __type(name:"PullRequestReviewThread") { fields { name } } __type(name:"PullRequestReviewComment") { fields { name } } }'

Then construct the query using only available fields.

Fetch PR metadata + review threads + thread comments in one query where possible.

gh api graphql -f query='\
query($owner:String!, $repo:String!, $number:Int!, $threadsCursor:String) {\
	repository(owner:$owner, name:$repo) {\
		pullRequest(number:$number) {\
			id\
			number\
			url\
			state\
			isDraft\
			headRefOid\
			reviewThreads(first: 100, after: $threadsCursor) {\
				pageInfo { hasNextPage endCursor }\
				nodes {\
					id\
					isResolved\
					isOutdated\
					updatedAt\
					comments(first: 100) {\
						nodes {\
							id\
							databaseId\
							body\
							createdAt\
							updatedAt\
							path\
							line\
							originalLine\
							diffSide\
							author { login }\
							url\
						}\
					}\
				}\
			}\
			comments(first: 100) {\
				nodes {\
					id\
					databaseId\
					body\
					createdAt\
					updatedAt\
					author { login }\
					url\
				}\
			}\
		}\
	}\
}' -F owner='OWNER' -F repo='REPO' -F number=PR_NUMBER

Notes:

  • Paginate reviewThreads and comments until hasNextPage=false.
  • Keep both GraphQL node ids (id) and REST ids (databaseId) for fallback operations.
  • Prefer this base field set for maximum portability: id, isResolved, isOutdated, isCollapsed, body, createdAt, updatedAt, path, line, originalLine, position, originalPosition.

Error-Driven Query Downgrade

If GraphQL responds with field errors (for example, undefinedField):

  1. Parse the error and extract typeName.fieldName.
  2. Remove only the failing fields from the query template.
  3. Retry with the reduced query.
  4. If still failing after two downgrades, switch to REST fallbacks for discovery and replies.

Example fallback trigger patterns:

  • Field '\''<name>'\'' doesn't exist on type '\''<type>'\''
  • GraphQL validation errors for selected comment/thread fields

REST Fallbacks via gh api

Use REST endpoints when GraphQL operation is unavailable or fails:

  • List review comments: GET /repos/{owner}/{repo}/pulls/{pull_number}/comments
  • Reply to review comment (portable primary): POST /repos/{owner}/{repo}/pulls/{pull_number}/comments with in_reply_to=<comment_id>
  • Add PR conversation comment: POST /repos/{owner}/{repo}/issues/{issue_number}/comments

Optional variant (may be unavailable depending on environment/API behavior):

  • POST /repos/{owner}/{repo}/pulls/comments/{comment_id}/replies

Example reply to review comment:

gh api repos/OWNER/REPO/pulls/PR_NUMBER/comments -f body='REPLY_TEXT' -F in_reply_to=COMMENT_ID

Example PR conversation response:

gh api repos/OWNER/REPO/issues/PR_NUMBER/comments -f body='REPLY_TEXT'

Thread Resolution (GraphQL)

Resolve review thread:

gh api graphql -f query='\
mutation($threadId:ID!) {\
	resolveReviewThread(input:{threadId:$threadId}) {\
		thread { id isResolved }\
	}\
}' -F threadId='THREAD_NODE_ID'

Unresolve (for compensation/recovery):

gh api graphql -f query='\
mutation($threadId:ID!) {\
	unresolveReviewThread(input:{threadId:$threadId}) {\
		thread { id isResolved }\
	}\
}' -F threadId='THREAD_NODE_ID'

Posting Replies (Decision-Aware)

  • accept: include concrete change summary + verification evidence.
  • reject: include rationale + alternative when possible.
  • defer: include explicit blocker and requested follow-up.

If thread reply mutation path is unavailable, reply to the latest review comment via REST fallback using databaseId and in_reply_to.

Concurrency Guards Before Mutations

Immediately before posting reply or resolving:

  1. Re-fetch the specific thread/comment by id.
  2. Compare updatedAt with manifest snapshot.
  3. If drift detected, transition item to stale-retriage.

Suggested Operation Order Per Accepted Review Item

  1. Apply code changes locally
  2. Run discovered verification checks
  3. Post reply (gh api GraphQL or REST fallback)
  4. Resolve thread (GraphQL)
  5. Record state transition

For PR conversation comments, step 4 is not applicable.

Rate Limits and Retries

  • On HTTP 403 with rate-limit signals: exponential backoff + jitter.
  • On HTTP 5xx: bounded retries.
  • On HTTP 401/permission failures: stop mutations, downgrade to propose.

Canonical Data Model

Normalize every feedback item into a single schema:

  • itemKey: stable unique key (source + id)
  • sourceType: review-thread | pr-conversation
  • commentId / threadId
  • author, authorRole, isBot
  • state: open/closed/outdated
  • filePath, line, side, commitSha (if present)
  • body, createdAt, updatedAt
  • classification, confidence
  • proposedDecision, confirmedDecision
  • executionState (state machine below)

If source IDs are unstable/unavailable for an item, derive a fallback key from {sourceType, filePath, line, author, createdAt, normalizedBodyHash}.

Lifecycle

Phase 0: Build Immutable Run Manifest

Capture a snapshot of PR/comment/thread/head SHA state and create a manifest hash. All actions in this run must reference this manifest.

Phase 1: Discover and Normalize

  • Fetch review-thread comments + PR conversation comments
  • Handle pagination
  • Deduplicate repeats
  • Exclude already closed/resolved items unless explicitly requested
  • Mark outdated comments using source metadata

Phase 2: Classify and Triage

Classify each item as:

  • actionable
  • informational
  • duplicate
  • blocked (missing context or permissions)

If confidence is below threshold, force defer and request user input.

Outdated review comments default to defer unless explicitly reconfirmed by the user.

Phase 3: Propose Decisions (No Writes)

For each actionable item, propose one of:

  • accept: implement change and resolve when complete
  • reject: reply with rationale, do not resolve by default
  • defer: reply with blocker/context needed
  • needs-split: feedback bundles multiple concerns; split into sub-items first

Phase 4: Confirmation Gate (Mandatory)

Require explicit user approval of decisions (per-item or batch) before any write action.

Phase 5: Two-Stage Execution (Per Item)

For each confirmed item, run:

Stage A: Prepare

  • Re-check item freshness against current PR state
  • Re-check head SHA and thread/comment open state
  • Build implementation + reply + resolution intent

If drift is detected, move item to stale-retriage.

Stage B: Execute (Transactional Order)

  1. Apply code change (for accepted items)
  2. Run verification checks relevant to changed scope
  3. Post reply with concrete evidence
  4. Resolve thread only if source supports it and acceptance criteria are met

Use atomic per-item transitions. Do not continue silently past failed transitions.

For PR conversation comments (non-thread), do not emulate thread resolution; mark as handled via reply + report status.

Execution State Machine

Allowed states:

  • queued
  • prepared
  • implemented
  • verified
  • replied
  • resolved
  • reply_posted_resolve_pending
  • deferred
  • failed
  • stale-retriage
  • skipped

Transition rules:

  • resolved is allowed only after replied and successful verification for accepted items
  • if verification fails after implementation, transition to failed and post defer-style response
  • if reply succeeds and resolve fails, transition to reply_posted_resolve_pending
  • if a newer reviewer follow-up appears in the same thread after prepare phase, transition to stale-retriage before resolve

Compensation rules:

  • implementation succeeded, verification failed: keep changes local, do not resolve, post deferred response
  • reply posted, resolve failed: keep reply_posted_resolve_pending and include explicit retry instructions
  • resolve posted but later drift detected: mark stale-retriage and warn that thread state may need manual review

Conflict, Dependency, and Concurrency Handling

  • Detect overlapping file/hunk edits across accepted items
  • Serialize conflicting items, parallelize independent items
  • Revalidate item state before each write (optimistic concurrency check)
  • If new comments appear mid-run, add them to next-run queue unless user opts in to refresh manifest
  • Re-check thread/comment ETag or updated timestamp immediately before write operations when available

Universal Verification Strategy

Never hardcode project-specific commands. Use discovery-based checks:

  1. Run smallest scoped checks first (changed-file lint/type/unit if detectable)
  2. Run repository-declared checks (from workspace config/scripts/CI metadata when available)
  3. If no checks are discoverable, mark manual-verification-required

If checks are discoverable but execution environment cannot run them, mark verification-blocked with reason and required human action.

Verification level behavior:

  • minimal: syntax/static checks only where available
  • standard: lint + relevant tests where available
  • strict: broader project test/build checks where available

Reply Quality Contract

Every posted reply must include:

  1. Disposition (accepted, rejected, deferred)
  2. What was changed (or why it was not changed)
  3. Evidence (file/behavior/check result)
  4. Any remaining limitation or follow-up

Avoid vague replies like "fixed" without evidence.

Retry, Timeout, and Resumability

  • Bounded retries with exponential backoff + jitter
  • Per-item timeout budget
  • Global circuit breaker for repeated platform failures
  • Persist checkpoints after each item transition so reruns can resume safely
  • Ensure idempotency: rerun with same manifest must not duplicate replies/resolutions

Security and Safety Guardrails

  • Do not include secrets/tokens/internal credentials in replies or logs
  • Treat bot comments as informational by default unless explicitly actionable
  • Escalate security-sensitive requests for explicit human approval
  • Never claim resolution when no verifiable action was completed
  • Never post replies that imply policy approval/compliance signoff unless explicitly provided by humans

Recommended Execution Script

  1. Preflight capability and permission matrix
  2. Build immutable run manifest
  3. Discover + normalize comments
  4. Classify and propose decisions
  5. Get explicit user approval
  6. Execute per-item transactional flow
  7. Produce audit report + handoff

Final Report Format

Include:

  • Run mode and manifest hash
  • Totals by status (accepted, rejected, deferred, failed, resolved, pending)
  • Per-item summary with current state and blockers
  • Files touched and verification outcomes
  • Items queued for next run (stale-retriage, new comments)
  • Clear handoff: developer performs commit/push/merge

Examples

Example A: Mixed Decisions

  • 8 open items discovered
  • Proposed: 4 accept, 2 reject, 1 defer, 1 needs-split
  • User confirms all except 1 reject (changed to defer)
  • Execution result: 4 implemented, 5 replied, 3 resolved, 1 pending due to permission

Example B: Fork PR with No Write Access

  • Preflight detects read-only constraints
  • Skill auto-downgrades to propose
  • Outputs patch plan + reply drafts + explicit maintainer handoff steps

Example C: Mid-Run Drift

  • Manifest SHA no longer matches current head during item 3
  • Item transitions to stale-retriage
  • Remaining independent items continue
  • Final report flags rerun needed for stale item