Principal Engineer Review
Overview
Dispatches five independent principal-engineer-persona subagents against the same diff — one each for maintainability, performance, security, regressions, and best-practices/over-engineering — then synthesizes their findings into one ranked report. Independence is the point: no reviewer sees another's prompt or output, so findings aren't anchored on each other and a shallow miss in one lens isn't masked by another lens covering it "well enough."
When to use
- Before merging a PR, retargeting a base, or finishing a branch, or when the user wants a second opinion beyond a single code-reviewer pass. Free, in-session alternative to
code-review:code-review ultra(cloud, billed). - Not a substitute for
pr-review-toolkit:review-pr's test/comment/type-design specialists — those go deeper on one topic; this is the five-dimension pass.
Step 1 — Resolve the target to concrete refs
Resolve once, before dispatching anything, so all five reviewers diff the exact same content:
| Input | Resolve to |
|---|---|
| No argument, dirty working tree | git diff HEAD (and staged: git diff --cached) |
| No argument, clean working tree | git diff $(git merge-base main HEAD)...HEAD |
| A number | GitHub PR — gh pr view <n> --json baseRefOid,headRefOid first, then diff those two SHAs directly (don't re-diff a moving PR head mid-review) |
| A branch name | git diff $(git merge-base main <branch>)...<branch> |
| An already-merged PR / a merge commit | git diff <merge>^1 <merge> — first parent is the base branch as of the merge, so this is exactly the PR's changes |
| A path | Scope filter appended to whichever diff above applies |
If gh isn't authenticated and the target is a PR number, find its merge commit (git log --merges --grep "#<n>") and use the merge-commit row.
Never pick a base by reading git log --oneline adjacency. The commit listed just before a merge is usually the previous PR's tip — a sibling branch, not an ancestor — and diffing against it shows that PR's work as if the target reverted it. Verify with git merge-base --is-ancestor <base> <head> before dispatching; if it fails, you have the wrong base.
Step 2 — Pick the model tier per dimension
Default Sonnet for all five (review-only, no code generation). Escalate a dimension to Opus when any of its triggers hit — same escalation logic as any other review/analysis agent:
- security, regressions → escalate if the diff touches auth, credentials, payments, or points/pricing math
- performance, regressions → escalate if the diff touches async/concurrency, ordering, streaming, or a state machine
- all five → escalate if the diff is large or cross-cutting (rough guide: >300 LOC or spans unrelated modules)
- any one dimension → re-dispatch that dimension alone on Opus if its Sonnet result comes back generic or surface-level
When genuinely unsure, escalate — a missed finding here is expensive, wasted Opus tokens on a clean diff are not.
Step 3 — Dispatch all five in parallel
One Agent call per dimension, subagent_type: "principal-engineer-reviewer", all in a single message (this is what makes them independent and concurrent — sequential dispatch lets later reviewers' context drift and wastes wall-clock for no benefit). Each prompt must give that agent, self-contained:
- Its one dimension (exact name from the agent's checklist)
- The resolved diff command/refs from Step 1 (not a pasted diff — let the agent run it and read real files for context)
- Any path scope
- Relevant project-convention excerpts worth weighing against — quoted from CLAUDE.md or a file you read this session, not from memory. A stale test command or framework name in the prompt sends five reviewers down the same wrong path; if you're not sure, leave it out and let the agent read
package.jsonitself.
Pass model per the Step 2 tier on each dispatch.
If principal-engineer-reviewer is not in the available agent types (agent directories are read at session start, so a session older than the file won't have it), dispatch with subagent_type: "general-purpose" instead and paste the body of ~/.claude/agents/principal-engineer-reviewer.md — everything below its frontmatter — at the top of each prompt, then add "Do not write or edit any files." A general-purpose agent has write tools; the paste-in gives it the same method and output contract, the sentence removes the one capability difference.
If the diff is UI-facing, you may add a UX lens (visual/interaction quality) and a PM lens (does it deliver the intended user outcome) as two more parallel dispatches using the same agent with a dimension of your own description — the five above are the required minimum, not a ceiling.
Step 4 — Synthesize
Once all dispatches return, merge into one report:
- Dedupe — the same underlying defect sometimes surfaces from two lenses (e.g. a missing auth check is both a security and a regression finding). Keep it once, note both lenses caught it.
- Rank: Blocking → Major → Minor → Nit, using each agent's own severity call — don't re-score, they've already read the code and you haven't.
- Verdict: ship / ship with fixes / do not ship, based on whether any Blocking findings survived dedupe.
- Report format:
# Principal Engineer Review — <target>
## Verdict: <ship | ship with fixes | do not ship>
## Blocking (N)
- [dimension] summary — file:line
## Major (N)
...
## Minor / Nit (N)
...
## Strengths
- what's well done, if anything stood out
## Dimensions run
maintainability (sonnet) · performance (sonnet) · security (opus, escalated: touches credentials) · regressions (sonnet) · best-practices (sonnet)
Always list all five (or more) dimensions run, even ones with zero findings — that line is what proves coverage, not just results.
Common mistakes
- Pasting the diff into each prompt instead of giving refs. Bloats every dispatch and the agent still needs file context Read/Grep gives it anyway.
- Dispatching sequentially "to save tokens." Defeats independence (context can leak across turns in the same session) and is slower, not cheaper — parallel dispatch is a single message.
- Skipping escalation on a security-sensitive diff because it "looks small." LOC size and blast radius aren't the same thing; check the trigger list in Step 2, not the diff stat.
- Re-scoring or softening an agent's severity in synthesis. You're aggregating, not re-reviewing — if a verdict looks wrong, re-dispatch that dimension, don't silently downgrade it.
- Treating zero findings from a dimension as the dispatch having failed. It's the expected outcome on a clean diff; only worry if the agent's output is missing the
Dimension: ... Findings: 0line entirely. - Giving up when the
Agentcall errors with "Agent type 'principal-engineer-reviewer' not found." That's the session-start registration issue above, not a broken skill — use the general-purpose fallback in Step 3.