name: corvus-review-r0 description: PR Review Phase R0 - Intake, triage, PR metadata fetching, config loading
Phase R0: INTAKE & TRIAGE
Goal: Parse PR reference, fetch metadata, load config, run triage checks.
Executor: Corvus-Review direct (no subagent delegation).
Input: User-provided PR reference (URL, #number, or owner/repo#number).
Output: PR_CONTEXT object (see corvus-review-extras for schema).
STEP 0: PARSE PR REFERENCE
Extract the PR identifier from the user's input. Supported formats:
| Format | Example | Parsing |
|---|---|---|
| Full URL | https://github.com/owner/repo/pull/123 |
Extract owner, repo, number from URL |
| Hash-number | #123 |
Use current repo (from gh repo view --json nameWithOwner) |
| Repo#number | owner/repo#123 |
Extract owner, repo, number |
| Just a number | 123 |
Use current repo |
If no PR reference is provided:
## PR Reference Required
Please provide a PR to review. Supported formats:
- `#123` (current repo)
- `owner/repo#123`
- `https://github.com/owner/repo/pull/123`
- Or just the number: `123`
Validation: After parsing, verify the PR exists:
gh pr view <number> --repo <owner/repo> --json number,title --jq '.number' 2>&1
If this fails, abort with a clear error (see corvus-review-extras error handling).
STEP 1: FETCH PR METADATA
Run the following gh commands to populate PR_CONTEXT fields:
1a. Core Metadata
gh pr view <number> --repo <owner/repo> --json \
number,url,title,body,author,baseRefName,headRefName,\
labels,reviewRequests,isDraft,mergeable,\
additions,deletions,changedFiles,files
Field Mapping:
pr_number←numberpr_url←urltitle←titledescription←body(set tonullif empty string or missing)author←author.loginbase_branch←baseRefNamehead_branch←headRefNamelabels←labels[].namereviewers_requested←reviewRequests[].loginis_draft←isDraftmergeable←mergeable(map:"MERGEABLE"→ true,"CONFLICTING"→ false, else → null)additions←additionsdeletions←deletionsfiles_changed←changedFileschanged_files←files[].path
1b. CI Status
gh pr checks <number> --repo <owner/repo> --json name,state,detailsUrl 2>&1
Field Mapping:
- For each check:
{ name, status: state_to_status(state), url: detailsUrl } state_to_status:"SUCCESS"/"NEUTRAL"/"SKIPPED"→"pass","FAILURE"/"ERROR"→"fail","PENDING"/"QUEUED"/"IN_PROGRESS"→"pending"ci_status(aggregate): if any"fail"→"fail", else if any"pending"→"pending", else if all"pass"→"pass", else"none"(no checks)
1c. Linked Issues
Parse linked issues from:
- PR body: scan for
fixes #N,closes #N,resolves #N(case-insensitive) - PR metadata:
gh pr view --json closingIssuesReferences
Deduplicate and store as linked_issues: ["#N", "#M"].
1d. Repo Identification
gh repo view --json nameWithOwner --jq '.nameWithOwner'
Store as repo.
STEP 2: LOAD REVIEW CONFIG
2a. Attempt Config Load
cat .opencode/review-config.yaml 2>/dev/null
2b. Parse and Validate
If the file exists:
- Parse YAML
- Validate each field against the schema (see
corvus-review-extras) - For invalid fields: log a warning, use the default for that field
- For unknown keys: log a warning, ignore
- Merge with defaults for any missing fields
If the file does not exist:
- Use all defaults (see
corvus-review-extrasfor default values) - This is normal and expected — config is optional
If the file has a YAML parse error:
- Log the error with line number
- Fall back to all defaults
- Set a flag:
config_parse_error: true(included in review summary later)
2c. Apply Config
Store the validated config as PR_CONTEXT.config.
STEP 3: TRIAGE
Evaluate the PR against triage checks and set flags in PR_CONTEXT.flags:
3a. Draft Check
flags.is_draft = PR_CONTEXT.is_draft
If draft:
## Draft PR Detected
PR #[number] is marked as draft. Proceeding with review, but findings
will be posted as COMMENT_ONLY (not REQUEST_CHANGES) regardless of severity.
Set config.action_override = "COMMENT_ONLY" if draft and no explicit override exists.
3b. Large PR Check
flags.is_large_pr = (PR_CONTEXT.files_changed > config.large_pr_threshold)
If large PR, apply config.large_pr_strategy:
| Strategy | Action |
|---|---|
"warn" |
Add warning to review output, proceed normally |
"split-suggestion" |
Suggest splitting PR, then proceed with full review |
"proceed" |
No special handling |
For "warn" and "split-suggestion", display:
## Large PR Warning
This PR changes **[N] files** (threshold: [T]).
[If split-suggestion: Consider splitting this into smaller, focused PRs for easier review.]
Proceeding with review.
3c. Missing Description Check
flags.missing_description = (PR_CONTEXT.description == null or PR_CONTEXT.description.trim() == "")
If missing:
- Add a
notefinding to be included in the review: "PR has no description. Consider adding context for reviewers." - Do NOT abort — this is a finding, not a blocker.
3d. CI Failure Check
flags.has_ci_failures = (PR_CONTEXT.ci_status == "fail")
If CI is failing:
- Note in context for R1's @researcher to analyze
- Do NOT abort — CI failures are analyzed and reported as part of the review
3e. Breaking Label Check
flags.has_breaking_labels = labels.any(l =>
["breaking-change", "breaking", "semver-major"].includes(l.toLowerCase())
)
If breaking labels found:
- Note for R2 passes: "PR has breaking-change label. Evaluate backward compatibility."
STEP 4: PRODUCE PR_CONTEXT
Assemble the complete PR_CONTEXT object from all gathered data.
Output Format
Present a summary to the user:
## PR Review: #[number] — [title]
| Field | Value |
|-------|-------|
| Author | @[author] |
| Branch | [head_branch] → [base_branch] |
| Changes | +[additions] / -[deletions] across [files_changed] files |
| CI | [ci_status_emoji] [ci_status] |
| Draft | [yes/no] |
### Triage Flags
[List any active flags with their implications]
### Config
- Severity threshold: [threshold]
- Max nits: [max_nits]
- Passes enabled: [list]
- Autonomous: [yes/no]
**Proceeding to context gathering (R1)...**
Status emojis for CI: pass = [PASS], fail = [FAIL], pending = [PENDING], none = [NONE]
GATE ENFORCEMENT
PR_CONTEXT is VALID when ALL of the following are true:
- pr_number is a positive integer
- changed_files is a non-empty array (or review is skipped for empty diff)
- config is loaded (defaults are acceptable)
- All triage flags are set (boolean values, not undefined)
If PR_CONTEXT cannot be produced (PR not found, auth error): → ABORT with clear error message. Do NOT proceed to R1.
If PR has empty diff: → SKIP review entirely. Display "Review Skipped" message.
EDGE CASES
Fork PRs
gh pr viewworks for fork PRs. No special handling needed.- Note: some CI checks may not run on fork PRs. Handle
ci_status: "none"gracefully.
Closed/Merged PRs
- Allow reviewing closed/merged PRs (useful for post-merge review).
- Add note: "This PR is already [closed/merged]. Review is informational only."
- Force
config.action_override = "COMMENT_ONLY"for merged PRs.
Very Large Diffs (1000+ files)
- If
files_changed > 100, warn that review quality may degrade. - The
changed_fileslist fromgh pr viewmay be truncated. Usegh pr diff --name-onlyas fallback:gh pr diff <number> --repo <owner/repo> --name-only
Rate Limiting
- If
ghcommands fail with rate limiting errors, wait and retry once. - If retry fails, abort with: "GitHub API rate limit exceeded. Try again later."