Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .squad/decisions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# PR Review Squad — Shared Decisions

These rules apply to every worker on every PR fix task. Deviating from them causes commits landing on the wrong remote or history rewrites that break collaborators.

## Push Safety

1. **NEVER force push** — no `--force`, `--force-with-lease`, or any force variant. Force pushing after a rebase is what caused wrong-remote pushes in the first place.

2. **ALWAYS use `gh pr checkout <N>`** to check out a PR branch — never `git fetch origin pull/<N>/head:pr-<N>`. The `gh` tool sets the branch tracking to the correct remote (fork or origin) automatically. A manually fetched branch has no tracking and `git push` will default to `origin`, silently pushing to the wrong repo.

3. **ALWAYS integrate with `git merge origin/main`** — never `git rebase origin/main`. Merge adds a merge commit (no history rewrite, no force push needed).

4. **ALWAYS verify the push target before pushing**:
```bash
gh pr view <N> --json headRepositoryOwner,headRefName \
--jq '"Expected: " + .headRepositoryOwner.login + "/" + .headRefName'
git config branch.$(git branch --show-current).remote
```
These must agree. If they don't, something is wrong — stop and investigate.

## Review Workflow

5. When reviewing only (no fix), use `gh pr diff <N>` — never check out the branch.

6. Consensus filter: include a finding in the final report only if flagged by 2+ of the 5 sub-agent models.

7. Do not comment on style, naming, or formatting. Flag only: bugs, data loss, race conditions, security issues, logic errors.
58 changes: 58 additions & 0 deletions .squad/push-to-pr.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/usr/bin/env bash
# push-to-pr.sh — Safe push helper for PR review workers
#
# Usage: .squad/push-to-pr.sh <PR-number>
#
# This script:
# 1. Reads PR metadata to find the correct remote and branch
# 2. Verifies the current branch matches the PR branch
# 3. Pushes to the correct remote (handles forks transparently)
# 4. Verifies the push landed by comparing local and remote HEADs

set -euo pipefail

PR_NUMBER="${1:?Usage: push-to-pr.sh <PR-number>}"

echo "==> Fetching PR #${PR_NUMBER} metadata..."
PR_JSON=$(gh pr view "$PR_NUMBER" --json headRefName,headRepositoryOwner,headRepository)
BRANCH=$(echo "$PR_JSON" | jq -r '.headRefName')
OWNER=$(echo "$PR_JSON" | jq -r '.headRepositoryOwner.login')
REPO=$(echo "$PR_JSON" | jq -r '.headRepository.name')

echo " PR branch: ${BRANCH}"
echo " PR owner: ${OWNER}"
echo " PR repo: ${REPO}"

# Verify current branch matches the PR branch
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [ "$CURRENT_BRANCH" != "$BRANCH" ]; then
echo "ERROR: Current branch '${CURRENT_BRANCH}' does not match PR branch '${BRANCH}'"
echo " Run: gh pr checkout ${PR_NUMBER}"
exit 1
fi

# Find the remote that points to owner/repo
# gh pr checkout registers the fork owner's login as the remote name
REMOTE=$(git remote -v | grep "${OWNER}/${REPO}" | head -1 | awk '{print $1}' || true)
if [ -z "$REMOTE" ]; then
echo "ERROR: No remote found matching ${OWNER}/${REPO}"
echo "Available remotes:"
git remote -v
exit 1
fi

echo "==> Pushing to remote '${REMOTE}' (${OWNER}/${REPO}), branch '${BRANCH}'..."
git push "$REMOTE" HEAD:"$BRANCH"

# Verify push succeeded by comparing SHAs
LOCAL_SHA=$(git rev-parse HEAD)
REMOTE_SHA=$(git ls-remote "$REMOTE" "refs/heads/${BRANCH}" | awk '{print $1}')

if [ "$LOCAL_SHA" = "$REMOTE_SHA" ]; then
echo "✅ Push verified: ${LOCAL_SHA}"
else
echo "❌ Push verification failed!"
echo " Local: ${LOCAL_SHA}"
echo " Remote: ${REMOTE_SHA}"
exit 1
fi
103 changes: 103 additions & 0 deletions .squad/routing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# PR Review Squad — Work Routing

## Fix Process (when told to fix a PR)

> **Critical:** Follow this process exactly. Deviating — especially using rebase or force push — causes commits to land on the wrong remote.

### 1. Check out the PR branch
```bash
gh pr checkout <number>
```
This sets the branch tracking to the correct remote automatically (fork or origin).
**Never** use `git fetch origin pull/<N>/head:...` — that creates a branch with no tracking.

> **Worktree conflict?** If `gh pr checkout` fails with "already checked out at...", run:
> ```bash
> git worktree list # find which worktree has the branch
> git worktree remove <path> # remove stale worktree if safe, OR
> gh pr checkout <number> -b pr-<number>-fix # use a unique local branch name
> ```

### 2. Integrate with main (MERGE, not rebase)
```bash
git fetch origin main
git merge origin/main
```
**Never** use `git rebase origin/main`. Merge adds a merge commit; no force push needed.
If there are conflicts, resolve them, then `git add <files> && git merge --continue`.

### 3. Make the fix
- Use the `edit` tool for file changes, never `sed`
- Make minimal, surgical changes

### 4. Run tests
Discover and run the repo's test suite. Look for test projects, Makefiles, CI scripts, or package.json test scripts. Run them and verify only pre-existing failures remain.

### 5. Commit
```bash
git add <specific-files> # Never git add -A blindly
git commit -m "fix: <description>

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>"
```

### 6. Push to the correct remote

**Always verify the push target before pushing:**
```bash
# Get expected owner/branch from the PR
gh pr view <N> --json headRepositoryOwner,headRefName \
--jq '"Expected: " + .headRepositoryOwner.login + "/" + .headRefName'

# Confirm branch tracking matches
git config branch.$(git branch --show-current).remote
```
These must agree. If they don't, stop and investigate before pushing.

Once verified:
```bash
git push
```
`gh pr checkout` sets branch tracking correctly, so bare `git push` lands on the right remote.

**If `git push` fails** (e.g., tracking not set up correctly), push explicitly using the owner's remote.
`gh pr checkout` registers the fork owner's GitHub login as a named remote — use it directly:
```bash
# Discover the owner's remote name
OWNER=$(gh pr view <N> --json headRepositoryOwner --jq '.headRepositoryOwner.login')
BRANCH=$(gh pr view <N> --json headRefName --jq '.headRefName')
git remote -v | grep "$OWNER" # confirm remote exists

git push "$OWNER" HEAD:"$BRANCH"
```
Alternatively, use `.squad/push-to-pr.sh <N>` which automates the above.

### 7. Verify the push landed
```bash
gh pr view <N> --json commits --jq '.commits[-1].messageHeadline'
```
The last commit headline should match your fix commit message.

### 8. Re-review
Dispatch 5 parallel sub-agent reviews with the updated diff (include previous findings for status tracking).

---

## Review Process (no fix)

Use `gh pr diff <N>` — **never** check out the branch for review-only tasks.

Dispatch 5 parallel reviews:
- claude-opus-4.6
- claude-opus-4.6
- claude-sonnet-4.6
- gemini-3-pro-preview
- gpt-5.3-codex

Synthesize with 2+ model consensus filter.

---

## Why `gh pr checkout` + merge beats manual fetch + rebase

`gh pr checkout` reads PR metadata and configures the branch to track the correct remote (fork or origin). Bare `git fetch pull/<N>/head:...` creates a local branch with no upstream — `git push` then defaults to `origin`, silently pushing to the base repository instead of the author's fork.
7 changes: 7 additions & 0 deletions .squad/team.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# PR Review Squad

Workers that review and fix pull requests using multi-model consensus review.

| Member | Role | Expertise |
|--------|------|-----------|
| reviewer | PR Reviewer | Multi-model dispatch, consensus synthesis, bug detection |