fix(review): harden ce-review base resolution (#452)
This commit is contained in:
@@ -11,9 +11,13 @@ color: yellow
|
||||
|
||||
You verify that prior review feedback on this PR has been addressed. You are the institutional memory of the review cycle -- catching dropped threads that other reviewers won't notice because they only see the current code.
|
||||
|
||||
## Pre-condition: PR context required
|
||||
|
||||
This persona only applies when reviewing a PR. The orchestrator passes PR metadata in the `<pr-context>` block. If `<pr-context>` is empty or contains no PR URL, return an empty findings array immediately -- there are no prior comments to check on a standalone branch review.
|
||||
|
||||
## How to gather prior comments
|
||||
|
||||
Fetch all review comments and review threads from the PR:
|
||||
Extract the PR number from the `<pr-context>` block. Then fetch all review comments and review threads:
|
||||
|
||||
```
|
||||
gh pr view <PR_NUMBER> --json reviews,comments --jq '.reviews[].body, .comments[].body'
|
||||
|
||||
@@ -338,6 +338,8 @@ If a plan is found, read its **Requirements Trace** (R1, R2, etc.) and **Impleme
|
||||
|
||||
Read the diff and file list from Stage 1. The 4 always-on personas and 2 CE always-on agents are automatic. For each cross-cutting and stack-specific conditional persona in the persona catalog included below, decide whether the diff warrants it. This is agent judgment, not keyword matching.
|
||||
|
||||
**`previous-comments` is PR-only.** Only select this persona when Stage 1 gathered PR metadata (PR number or URL was provided as an argument, or `gh pr view` returned metadata for the current branch). Skip it entirely for standalone branch reviews with no associated PR -- there are no prior comments to check.
|
||||
|
||||
Stack-specific personas are additive. A Rails UI change may warrant `kieran-rails` plus `julik-frontend-races`; a TypeScript API diff may warrant `kieran-typescript` plus `api-contract` and `reliability`.
|
||||
|
||||
For CE conditional agents, check if the diff includes files matching `db/migrate/*.rb`, `db/schema.rb`, or data backfill scripts.
|
||||
@@ -376,11 +378,7 @@ Pass the resulting path list to the `project-standards` persona inside a `<stand
|
||||
|
||||
Persona sub-agents do focused, scoped work and should use cheaper/faster models to reduce cost and latency. The orchestrator itself stays on the default (most capable) model.
|
||||
|
||||
| Platform | Persona agent model | How to set |
|
||||
|----------|-------------------|------------|
|
||||
| **Claude Code** | Haiku | Pass `model: "haiku"` in the Agent tool call |
|
||||
| **Codex** | GPT-4o mini | Set the model parameter to `gpt-4o-mini` in the agent spawn config |
|
||||
| **Other platforms** | Cheapest capable model available | Use the platform's equivalent of a fast/cheap tier |
|
||||
Use the platform's cheapest capable model for all persona and CE sub-agents. In Claude Code, pass `model: "haiku"` in the Agent tool call. On other platforms, use the equivalent fast/cheap tier (e.g., `gpt-4o-mini` in Codex). If the platform has no model override mechanism or the available model names are unknown, omit the model parameter and let agents inherit the default -- a working review on the parent model is better than a broken dispatch from an unrecognized model name.
|
||||
|
||||
CE always-on agents (agent-native-reviewer, learnings-researcher) and CE conditional agents (schema-drift-detector, deployment-verification-agent) also use the cheaper model tier since they perform scoped, focused work.
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ Spawned when the orchestrator identifies relevant patterns in the diff. The orch
|
||||
| `data-migrations` | `compound-engineering:review:data-migrations-reviewer` | Migration files, schema changes, backfill scripts, data transformations |
|
||||
| `reliability` | `compound-engineering:review:reliability-reviewer` | Error handling, retry logic, circuit breakers, timeouts, background jobs, async handlers, health checks |
|
||||
| `adversarial` | `compound-engineering:review:adversarial-reviewer` | Diff has >=50 changed non-test, non-generated, non-lockfile lines, OR touches auth, payments, data mutations, external API integrations, or other high-risk domains |
|
||||
| `previous-comments` | `compound-engineering:review:previous-comments-reviewer` | Reviewing a PR that has existing review comments or review threads from prior review rounds |
|
||||
| `previous-comments` | `compound-engineering:review:previous-comments-reviewer` | **PR-only.** Reviewing a PR that has existing review comments or review threads from prior review rounds. Skip entirely when no PR metadata was gathered in Stage 1. |
|
||||
|
||||
## Stack-Specific Conditional (5 personas)
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ set -euo pipefail
|
||||
|
||||
REVIEW_BASE_BRANCH=""
|
||||
PR_BASE_REPO=""
|
||||
PR_BASE_REMOTE=""
|
||||
BASE_REF=""
|
||||
|
||||
# Step 1: Try PR metadata (handles fork workflows)
|
||||
@@ -51,19 +52,37 @@ if [ -n "$REVIEW_BASE_BRANCH" ]; then
|
||||
if [ -n "$PR_BASE_REPO" ]; then
|
||||
PR_BASE_REMOTE=$(git remote -v | awk "index(\$2, \"github.com:$PR_BASE_REPO\") || index(\$2, \"github.com/$PR_BASE_REPO\") {print \$1; exit}")
|
||||
if [ -n "$PR_BASE_REMOTE" ]; then
|
||||
git rev-parse --verify "$PR_BASE_REMOTE/$REVIEW_BASE_BRANCH" >/dev/null 2>&1 || git fetch --no-tags "$PR_BASE_REMOTE" "$REVIEW_BASE_BRANCH" 2>/dev/null || true
|
||||
git rev-parse --verify "$PR_BASE_REMOTE/$REVIEW_BASE_BRANCH" >/dev/null 2>&1 || git fetch --no-tags "$PR_BASE_REMOTE" "$REVIEW_BASE_BRANCH:refs/remotes/$PR_BASE_REMOTE/$REVIEW_BASE_BRANCH" 2>/dev/null || git fetch --no-tags "$PR_BASE_REMOTE" "$REVIEW_BASE_BRANCH" 2>/dev/null || true
|
||||
BASE_REF=$(git rev-parse --verify "$PR_BASE_REMOTE/$REVIEW_BASE_BRANCH" 2>/dev/null || true)
|
||||
fi
|
||||
fi
|
||||
if [ -z "$BASE_REF" ]; then
|
||||
git rev-parse --verify "origin/$REVIEW_BASE_BRANCH" >/dev/null 2>&1 || git fetch --no-tags origin "$REVIEW_BASE_BRANCH" 2>/dev/null || true
|
||||
BASE_REF=$(git rev-parse --verify "origin/$REVIEW_BASE_BRANCH" 2>/dev/null || git rev-parse --verify "$REVIEW_BASE_BRANCH" 2>/dev/null || true)
|
||||
# Only try origin if it exists as a remote; otherwise skip to avoid
|
||||
# confusing errors in fork setups where origin points at the user's fork.
|
||||
if git remote get-url origin >/dev/null 2>&1; then
|
||||
git rev-parse --verify "origin/$REVIEW_BASE_BRANCH" >/dev/null 2>&1 || git fetch --no-tags origin "$REVIEW_BASE_BRANCH:refs/remotes/origin/$REVIEW_BASE_BRANCH" 2>/dev/null || git fetch --no-tags origin "$REVIEW_BASE_BRANCH" 2>/dev/null || true
|
||||
BASE_REF=$(git rev-parse --verify "origin/$REVIEW_BASE_BRANCH" 2>/dev/null || true)
|
||||
fi
|
||||
# Fall back to a bare local ref only if remote resolution failed
|
||||
if [ -z "$BASE_REF" ]; then
|
||||
BASE_REF=$(git rev-parse --verify "$REVIEW_BASE_BRANCH" 2>/dev/null || true)
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Compute merge-base
|
||||
if [ -n "$BASE_REF" ]; then
|
||||
BASE=$(git merge-base HEAD "$BASE_REF" 2>/dev/null) || BASE=""
|
||||
if [ -z "$BASE" ] && [ "$(git rev-parse --is-shallow-repository 2>/dev/null || echo false)" = "true" ]; then
|
||||
if git remote get-url origin >/dev/null 2>&1; then
|
||||
git fetch --no-tags --unshallow origin 2>/dev/null || true
|
||||
BASE=$(git merge-base HEAD "$BASE_REF" 2>/dev/null) || BASE=""
|
||||
fi
|
||||
if [ -z "$BASE" ] && [ -n "$PR_BASE_REMOTE" ] && [ "$PR_BASE_REMOTE" != "origin" ]; then
|
||||
git fetch --no-tags --unshallow "$PR_BASE_REMOTE" 2>/dev/null || true
|
||||
BASE=$(git merge-base HEAD "$BASE_REF" 2>/dev/null) || BASE=""
|
||||
fi
|
||||
fi
|
||||
else
|
||||
BASE=""
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user