docs/book/src/maintainers/reviewer-playbook.md
The operating model for reviewing PRs and triaging issues. Sized to keep review quality high under heavy volume; routes by risk so high-stakes paths get the attention they need without dragging every small change through the same gate.
For the actual fetch sequence and review verdict mechanics, see PR Review Protocol. This page is the operating model; the protocol is the procedure.
Use this section to route a review before reading deeper. Each row links to the section that elaborates.
Use PR lanes for routing expectations; use this playbook's risk matrix for review depth.
| Situation | Action | Section |
|---|---|---|
| Intake fails in the first 5 minutes | Leave one actionable checklist comment, stop deep review | Five-minute intake |
| Risk is high or unclear | Treat as risk:high until proven otherwise | Review depth matrix |
| Automation output is wrong or noisy | Apply the override protocol | Automation override |
| Need to hand off to another maintainer | Use the handoff template | Handoff |
| Risk label | Typical paths | Minimum depth | Required evidence |
|---|---|---|---|
risk:low | Docs, tests, chore, isolated non-runtime | 1 reviewer + CI gate | Coherent local validation, no behavior ambiguity |
risk:medium | crates/zeroclaw-providers/, crates/zeroclaw-channels/, crates/zeroclaw-memory/, crates/zeroclaw-config/ | 1 subsystem-aware reviewer + behavior verification | Focused scenario proof, explicit side effects |
risk:high | The canonical high-risk path set (runtime, gateway, tools, security, .github/workflows/) | Fast triage + deep review + rollback readiness | Security and failure-mode checks, rollback clarity |
When uncertain, treat as higher risk.
Risk labels are currently manual. If future risk automation is restored, follow the labels automation contract: apply risk:manual when a maintainer correction should not be overwritten on the next pushed update.
Labels are maintainer metadata. If the correct label is obvious and you have permission, fix it yourself before finalizing the review. Ask the author only when the right label choice is ambiguous or nobody with label permissions is available.
For every new PR, before reading any code:
size:*, risk:*, scope labels, contributor tier where applicable.CI Required Gate signal status.If any intake check fails, leave one actionable checklist comment and stop. Don't deep-review a PR that hasn't passed intake: the back-and-forth is cheaper at this layer than after the diff has been reasoned about.
AGENTS.md, Extension examples).For risk:high PRs, verify a concrete example in each category. One concrete instance beats five generic claims.
Prefer checklist-style comments with one explicit outcome:
Vague comments create avoidable round trips. If you find yourself writing "this might be a problem", invest 30 more seconds and turn it into a specific scenario or pull the comment.
The same risk-routing principle applies to issues, but the labels and signals are different.
Issue risk:* labels describe likely fix blast radius from the report. PR risk:* labels describe the actual diff under review. Reassess risk when an issue becomes a PR instead of carrying the issue label forward automatically.
| Label | When to use |
|---|---|
r:needs-repro | Bug report missing a deterministic repro. Block deeper triage on this. |
r:support | Usage or help question better routed outside the bug backlog. |
status:accepted | The team has accepted the RFC or work item. Add status:no-stale only when the issue also needs stale protection. |
status:blocked | Valid work is waiting on an external dependency, maintainer decision, or linked prerequisite. Record the blocker; this is stale protection only while that blocker remains unresolved. |
status:in-progress | An open PR is actively targeting the issue. Re-check live PR state before relying on it during stale passes. |
status:no-stale | Accepted or otherwise long-lived work should stay open and is not already protected by another stale exclusion. Record the reason and routing evidence using the contributor-visible sources in the Project board contract. Active release trackers and active RFC or design trackers may use the tracker itself as the visible reason and routing surface while they remain active. |
good first issue | XS/S, self-contained, documented work with clear acceptance criteria, relevant code or docs links, a named mentor or contact, and low onboarding risk. |
help wanted | Actionable, unblocked work maintainers want external help on and can review. Do not use it as a generic valid/unowned marker. |
Assignee means active work. Routing evidence records why an issue needs special stale protection, tracker treatment, or a deferred maintainer decision. status:blocked only needs the recorded unresolved blocker unless it also needs separate status:no-stale protection. The Project board contract defines the accepted evidence sources and routing outcomes. Labels can identify the likely area, but labels alone are not ownership or stale protection.
Use resolution labels only when closing or removing an item from the active queue. They explain the terminal outcome; they do not replace status:* lifecycle labels on work that should stay open. The labels guide is the source of truth for current resolution-label definitions and migration holdbacks.
For duplicates, link the canonical target before closing or redirecting discussion. For invalid reports, explain what makes the report unactionable or where it should go instead. For work we are explicitly choosing not to pursue, use the board-level Won't Do / live wontfix path and leave a brief rationale.
For replaced PRs or issue paths, use Superseding PRs and preserve contributor attribution when relevant.
If logs or payloads in the report contain personal identifiers or sensitive data, request redaction before deeper triage. The triage process must not propagate the exposure.
Discussions are a maintained community surface only when a steward or review cadence exists. The default cadence is a weekly maintainer pass over new and recently active threads. A named steward may own that surface pass, but the steward maintains the surface; they do not become the owner of every question, idea, or implementation that appears there.
During each Discussions pass:
If Discussions are not being reviewed on the documented cadence, do not present them as a required intake path. Treat them as a passive archive until a steward or cadence is restored.
When review demand exceeds capacity:
size:XS or size:S) at the top of the queue.stale-candidate before stale closure window starts.Use this when automation output creates review side effects:
risk:* label. If future risk automation is active, also follow the labels automation contract for risk:manual.When passing review to another maintainer or agent mid-flight, include:
This keeps context loss low and avoids the next reviewer redoing the same fetches you already did.
status:no-stale only under the rules in the Project board contract: when accepted or otherwise long-lived work has a recorded reason to stay open, contributor-visible routing evidence, and no other stale exclusion already applies. Active release trackers and active RFC or design trackers may keep stale protection by default when the issue itself clearly identifies the active coordination or decision surface; revisit them when the milestone closes, the tracker drifts from live state, the RFC reaches a decision, is superseded, or closes, or the issue stops representing an active project decision surface. Until the stale-exemption audit lands, treat existing status:no-stale issues missing those facts as audit findings rather than automatic stale candidates.size:XS or size:S bug and security PRs first.The goal is a queue where every open PR is either being actively reviewed, blocked on the author, or blocked on something external, never just sitting because nobody got to it.