| name | corvus-review-extras |
| description | Shared schemas, Conventional Comments spec, config schema, and common templates for Corvus PR Review |
Corvus Review — Shared References
SUBAGENT REFERENCE
| Phase | Subagent | Purpose | Parallel? |
|---|
| R0 | (Corvus-Review direct) | Intake, triage, config | N/A |
| R1 | @pr-context-gatherer | Read changed files, trace deps, find tests, detect conventions | Yes (with researcher) |
| R1 | @researcher | Fetch linked issues, dependency advisories, CI failures, related PRs | Yes (with pr-context-gatherer) |
| R2 Pass 1 | @ux-dx-quality | Architecture & Design review | Yes (with Pass 2, 3) |
| R2 Pass 2 | @code-quality | Logic & Correctness review | Yes (with Pass 1, 3) |
| R2 Pass 3 | @security-reviewer | Security review | Yes (with Pass 1, 2) |
| R2 Pass 4 | (Corvus-Review direct) | Conventions & Polish | Sequential (after 1-3) |
| R3 | (Corvus-Review direct) | Comment synthesis | N/A |
| R4 | (Corvus-Review direct) | User gate / auto-proceed | N/A |
| R5 | @pr-comment-writer | GitHub posting | N/A |
Invoking Subagents
Use the Task tool with subagent_type parameter:
task(
subagent_type: "pr-context-gatherer",
description: "Gather PR context: changed files and dependencies",
prompt: "**TASK**: Analyze all changed files in PR #NNN..."
)
Parallel Invocation
When subagents are independent (R1, R2 Passes 1-3), invoke them in the same message:
task(subagent_type: "pr-context-gatherer", description: "PR file analysis", prompt: "...")
task(subagent_type: "researcher", description: "PR external context", prompt: "...")
REVIEW CONFIG SCHEMA
File: .opencode/review-config.yaml
severity_threshold: "nitpick"
max_nits: 3
passes:
architecture: true
correctness: true
security: true
conventions: true
path_rules:
- pattern: "**/*.generated.*"
suppress_below: "major"
- pattern: "src/auth/**"
elevate_security: true
- pattern: "vendor/**"
skip_passes: ["conventions"]
custom_rules:
- id: "todo-no-issue"
pattern: "TODO(?!.*#\\d+)"
severity: "minor"
message: "TODO comment without linked issue"
include: ["*.ts", "*.js"]
exclude: ["*.test.*"]
suppressions:
- id: "no-console-log"
paths: ["src/debug/**"]
- message_pattern: "unused import"
reason: "Auto-imports will be cleaned by CI"
autonomous: false
action_override: null
large_pr_threshold: 20
large_pr_strategy: "warn"
Config Validation Rules
severity_threshold must be one of: blocker, critical, major, minor, nitpick
max_nits must be a non-negative integer
passes keys must be from: architecture, correctness, security, conventions
path_rules[].pattern must be valid glob syntax
custom_rules[].pattern must be valid regex
custom_rules[].severity must be a valid severity level
suppressions[].message_pattern must be valid regex (if present)
large_pr_threshold must be a positive integer
- Unknown keys produce a warning but do not fail loading
Config Loading Priority
.opencode/review-config.yaml (project-level)
- Built-in defaults (for any missing fields)
CONVENTIONAL COMMENTS SPECIFICATION
All review findings use the Conventional Comments format.
Labels
| Label | Meaning | Blocks Merge? |
|---|
blocker | Must fix before merge. Correctness, security, or data-loss issue. | YES |
critical | Strongly recommended fix. Significant design, performance, or reliability issue. | YES (when action = REQUEST_CHANGES) |
major | Should fix. Logic error, missing edge case, poor abstraction. | Depends on threshold |
minor | Consider fixing. Style, naming, small improvement. | No |
nitpick | Optional polish. Cosmetic, subjective preference. | No |
praise | Positive feedback. Highlight good patterns. | No |
thought | Open question or suggestion for discussion. | No |
note | Informational context. Not actionable. | No |
Severity Mapping
| Severity Level | Label | Numeric Weight |
|---|
| 5 (highest) | blocker | 50 |
| 4 | critical | 40 |
| 3 | major | 30 |
| 2 | minor | 20 |
| 1 (lowest) | nitpick | 10 |
| 0 (special) | praise / thought / note | 0 |
Finding Structure
Each review finding MUST conform to this structure:
- id: "<pass>-<sequence>"
pass: "<pass_name>"
label: "<conventional_label>"
severity: <1-5>
file: "<file_path>"
line_start: <number>
line_end: <number|null>
title: "<short_title>"
body: "<markdown_body>"
suggestion: "<code|null>"
confidence: <0.0-1.0>
related_to: ["<finding_id>"]
suppressed: false
Comment Rendering Format
When posting to GitHub, each finding renders as:
For inline comments (file + line):
**<label>** (<pass>): <title>
<body>
[suggestion block if present]
For the review summary body:
**<label>**: <title>
<body>
Nit Budget Enforcement
- Maximum nits per review:
config.max_nits (default: 3)
- When findings exceed the nit budget, drop lowest-confidence nits first
- Dropped nits are noted in the review summary: "N additional nitpicks suppressed"
praise, thought, and note labels do NOT count toward nit budget
DATA OBJECT SCHEMAS
PR_CONTEXT (produced by R0)
PR_CONTEXT:
pr_number: <number>
pr_url: "<url>"
repo: "<owner/repo>"
base_branch: "<branch>"
head_branch: "<branch>"
author: "<username>"
title: "<string>"
description: "<string|null>"
labels: ["<label>"]
reviewers_requested: ["<username>"]
linked_issues: ["<issue_ref>"]
is_draft: <boolean>
mergeable: <boolean|null>
ci_status: "pass" | "fail" | "pending" | "none"
ci_checks:
- name: "<check_name>"
status: "pass" | "fail" | "pending"
url: "<url|null>"
files_changed: <number>
additions: <number>
deletions: <number>
changed_files: ["<file_path>"]
flags:
is_large_pr: <boolean>
missing_description: <boolean>
has_ci_failures: <boolean>
is_draft: <boolean>
has_breaking_labels: <boolean>
config: <ReviewConfig>
REVIEW_CONTEXT (produced by R1)
REVIEW_CONTEXT:
file_map:
"<file_path>":
full_content: "<string>"
diff_hunks: ["<hunk>"]
language: "<lang>"
imports: ["<import>"]
exports: ["<export>"]
callers: ["<file:function>"]
test_files: ["<file_path>"]
git_history:
last_modified: "<date>"
recent_authors: ["<username>"]
change_frequency: "high" | "medium" | "low"
dependency_graph:
"<file_path>":
depends_on: ["<file_path>"]
depended_by: ["<file_path>"]
conventions:
naming: "<pattern_description>"
file_structure: "<description>"
error_handling: "<pattern>"
test_patterns: "<description>"
import_order: "<convention>"
test_coverage:
has_tests: <boolean>
test_files_for_changes: ["<file_path>"]
untested_files: ["<file_path>"]
linked_issues_detail: [<IssueDetail>]
dependency_advisories: [<Advisory>]
ci_failure_analysis: [<CIFailure>]
related_prs: [<RelatedPR>]
REVIEW_FINDINGS (produced by R2)
REVIEW_FINDINGS:
pass_results:
architecture:
status: "completed" | "skipped" | "error"
findings: [<Finding>]
summary: "<string>"
correctness:
status: "completed" | "skipped" | "error"
findings: [<Finding>]
summary: "<string>"
security:
status: "completed" | "skipped" | "error"
findings: [<Finding>]
summary: "<string>"
conventions:
status: "completed" | "skipped" | "error"
findings: [<Finding>]
summary: "<string>"
totals:
blocker: <count>
critical: <count>
major: <count>
minor: <count>
nitpick: <count>
praise: <count>
thought: <count>
note: <count>
REVIEW_DOCUMENT (produced by R3)
REVIEW_DOCUMENT:
summary:
title: "<one-line summary>"
body: "<markdown>"
stats:
total_findings: <count>
blockers: <count>
criticals: <count>
majors: <count>
minors: <count>
nits_shown: <count>
nits_suppressed: <count>
praises: <count>
action: "APPROVE" | "REQUEST_CHANGES" | "COMMENT_ONLY"
action_reasoning: "<string>"
findings: [<Finding>]
inline_comments:
- path: "<file_path>"
line: <number>
start_line: <number|null>
side: "RIGHT"
body: "<rendered_comment>"
review_body: "<rendered_markdown>"
dedup_log: [<DedupEntry>]
filtered_log: [<FilterEntry>]
REVIEW_ACTION (produced by R4)
REVIEW_ACTION:
decision: "post" | "edit" | "local_only" | "rerun" | "auto_post"
edits: [<Finding>]
rerun_scope: ["<pass_name>"]
TODO TRACKING PATTERNS
todowrite([
{ id: "r0-intake", content: "R0: Parse PR and load config", status: "in_progress", priority: "high" },
{ id: "r1-context", content: "R1: Gather context", status: "pending", priority: "high" },
{ id: "r2-review", content: "R2: Multi-pass review", status: "pending", priority: "high" },
{ id: "r3-synthesis", content: "R3: Synthesize comments", status: "pending", priority: "high" },
{ id: "r4-gate", content: "R4: User gate", status: "pending", priority: "medium" },
{ id: "r5-post", content: "R5: Post review", status: "pending", priority: "medium" },
])
ERROR HANDLING
PR Not Found
## Review Aborted
**Reason**: PR #[number] not found in [repo].
**Action**: Verify the PR number and repository.
CI Still Running
Do NOT abort. Note ci_status: "pending" in PR_CONTEXT.
R3 adds a note: "CI checks were still running at review time."
Empty Diff
## Review Skipped
**Reason**: PR #[number] has no file changes. No code review needed.
Config Parse Error
Log warning, fall back to all defaults, add note to review summary.
Subagent Failure
- R1 workstream fails: proceed with partial context, note gap
- R2 pass fails: mark as "error", proceed with remaining passes
- R3 fails: escalate to user (cannot produce review without synthesis)
- R5 fails (posting): show rendered review locally, offer retry