Flow PR
End-to-end PR lifecycle for a unit of work: default branch detection, branch
cutting, commit → push → PR open, review gate, CI gate, and merge. The policy
layer on top of existing mechanics.
Defers:
- Commit message policy →
/commit
- Code-review logic →
/code-review (flow-pr runs it as the review gate; does not implement it)
- Issue filing → repo's intake convention
- Merge mechanics →
merge-mechanics.md
/code-review here means the installed two-axis Standards+Spec skill
(Matt's), which is what resolves for that name today (#556).
Default branch detection
The repo's default branch is always the integration target. Read it dynamically:
gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name'
Examples:
main (library/tool) → feature PRs merge to main; promotion doesn't apply.
staging (deployed app) → feature PRs merge to staging; promotion (staging → main) is a separate always-confirmed step.
Override (rare). If a repo uses a non-default branch as its integration target, add to the repo's CLAUDE.md: Flow-PR integration branch: <branch>. The skill reads this before the API call and uses it instead.
Feature mode (default path)
Runs when the user signals done/ship, or when all autonomy triggers below are satisfied.
Branch check. If already on a feature/* branch, stay on it. If on the default branch, cut a feature/<slug> branch from it first. Never commit directly onto the default branch.
Commit → push. Use /commit for commit message policy. Push the feature branch to origin.
Open PR. gh pr create --base <default-branch>. The base is always the dynamic default branch — never hardcode main if the default is staging.
PR body format:
## Summary
<1–3 bullets>
## Test plan
[Bulleted checklist]
🤖 Generated with [Claude Code](https://claude.ai/claude-code)
If a PR for the branch already exists, update it instead of opening a new one. Check with gh pr list --head <branch> first (idempotent).
Review gate (default on). Invoke /code-review on the PR diff and apply fixes. Loop review → fix → re-review until /code-review reports no actionable findings or a 2-pass cap is hit. If actionable findings remain at the cap, halt and surface them — do not merge.
Skip only on explicit caller opt-out (/flow-pr skip-review or a stated "skip review"). Do not auto-classify the diff to decide — diff size and file type are poor proxies for review need.
FP-exclusion list. When judging whether a /code-review finding is
actionable, do not treat any of the following as a finding to fix or a
blocker to the cap:
- Pre-existing issues — already present before this diff, not introduced by it.
- Issues a linter, typechecker, or compiler would catch on its own (CI covers these).
- Issues explicitly silenced in the code (e.g. a lint-ignore comment) — deliberately suppressed, not missed.
- Changes in functionality that look intentional and are directly related to the broader change.
- Real issues, but on lines the diff didn't touch.
- General code-quality gripes (test coverage, docs, style) absent a documented standard (CLAUDE.md, ADR, or repo convention) that the diff violates.
Mirrored verbatim in council's Falsifier seat brief (skills/engineering/council/SKILL.md) — keep the two lists in sync.
Fix or name the failure. A finding that survives the FP-exclusion list is confirmed actionable: the fix pass returns the specific fix, or the concrete failure point it hits. "The original is fine" is not available here — that judgment already happened in the FP-exclusion pass; re-arguing it re-opens a decided question and stalls the loop.
CI gate. Poll gh pr checks until all checks pass. Do not merge with red or pending CI.
Merge. gh pr merge --merge (merge-commit only; see merge-mechanics.md).
Post-merge sync.
git checkout <default-branch> && git pull
git branch -d <feature-branch> (remote branch is auto-deleted by GitHub; local is not)
Promotion mode
Applies only when the default branch is not main. When the default branch is main, feature merges are the final step and promotion doesn't exist.
Always user-confirmed before running.
- Triggered only by explicit invocation:
/flow-pr promote or an explicit user request. Never auto-triggered.
- Opens
gh pr create --base main from the default branch (e.g. staging → main).
- Merge-commit only; never squash or rebase.
Autonomy triggers
Fire when all hold:
- User explicitly signals done/ship, OR a coherent unit of work is logically complete, AND
- The verify gate is green (tests, typecheck, CI), AND
- The working tree is a reviewable diff (not mid-edit noise).
Do not fire:
- After individual file edits.
- Mid-task or on work-in-progress.
- When the verify gate is red or failing.
- Before the unit is logically complete.
- On structural work without first proposing and getting go-ahead.
A passing verify gate is what makes autonomous merge trustworthy — it is not optional.
GraphQL flap resilience
gh pr create and gh pr merge route through GraphQL, which can intermittently 401 even when auth is healthy.
gh pr create failure: fall back to REST — gh api -X POST repos/{owner}/{repo}/pulls -f title=... -f body=... -f head=... -f base=...
gh pr merge failure: fall back to local git merge --no-ff <feature-branch> + git push from the integration branch (GitHub marks the PR merged).
- Check
gh auth status before assuming a real auth failure. Note: gh auth status can report healthy without live-validating the token.
- If REST also 401s after a GraphQL flap, it is a real auth issue — surface to the user, do not re-run.
1---2name: flow-pr3description: Flow-aware end-to-end PR helper — cuts a feature branch from the repo's default branch, commits → pushes → opens a PR with the default branch as base, reviews and fixes the diff (via `/code-review`), gates on CI, then merges to the default branch. When the default branch is not main, promotion (default→main) is a separate always-confirmed mode. Invokable as a slash command or by the model on a done+green signal.4---56# Flow PR78End-to-end PR lifecycle for a unit of work: default branch detection, branch9cutting, commit → push → PR open, review gate, CI gate, and merge. The policy10layer on top of existing mechanics.1112Defers:13- **Commit message policy** → `/commit`14- **Code-review logic** → `/code-review` (flow-pr *runs* it as the review gate; does not implement it)15- **Issue filing** → repo's intake convention16- **Merge mechanics** → [`merge-mechanics.md`](merge-mechanics.md)1718> `/code-review` here means the installed two-axis Standards+Spec skill19> (Matt's), which is what resolves for that name today (#556).2021---2223## Default branch detection2425The repo's **default branch is always the integration target**. Read it dynamically:2627```28gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name'29```3031Examples:32- `main` (library/tool) → feature PRs merge to `main`; promotion doesn't apply.33- `staging` (deployed app) → feature PRs merge to `staging`; promotion (`staging → main`) is a separate always-confirmed step.3435**Override (rare).** If a repo uses a non-default branch as its integration target, add to the repo's `CLAUDE.md`: `Flow-PR integration branch: <branch>`. The skill reads this before the API call and uses it instead.3637---3839## Feature mode (default path)4041Runs when the user signals done/ship, or when all autonomy triggers below are satisfied.42431. **Branch check.** If already on a `feature/*` branch, stay on it. If on the default branch, cut a `feature/<slug>` branch from it first. Never commit directly onto the default branch.44452. **Commit → push.** Use `/commit` for commit message policy. Push the feature branch to origin.46473. **Open PR.** `gh pr create --base <default-branch>`. The base is always the dynamic default branch — never hardcode `main` if the default is `staging`.4849 PR body format:5051 ```52 ## Summary53 <1–3 bullets>5455 ## Test plan56 [Bulleted checklist]5758 🤖 Generated with [Claude Code](https://claude.ai/claude-code)59 ```6061 If a PR for the branch already exists, update it instead of opening a new one. Check with `gh pr list --head <branch>` first (idempotent).62634. **Review gate (default on).** Invoke `/code-review` on the PR diff and apply fixes. Loop review → fix → re-review until `/code-review` reports no actionable findings or a **2-pass cap** is hit. If actionable findings remain at the cap, halt and surface them — do not merge.6465 Skip only on explicit caller opt-out (`/flow-pr skip-review` or a stated "skip review"). Do not auto-classify the diff to decide — diff size and file type are poor proxies for review need.6667 **FP-exclusion list.** When judging whether a `/code-review` finding is68 actionable, do not treat any of the following as a finding to fix or a69 blocker to the cap:7071 - Pre-existing issues — already present before this diff, not introduced by it.72 - Issues a linter, typechecker, or compiler would catch on its own (CI covers these).73 - Issues explicitly silenced in the code (e.g. a lint-ignore comment) — deliberately suppressed, not missed.74 - Changes in functionality that look intentional and are directly related to the broader change.75 - Real issues, but on lines the diff didn't touch.76 - General code-quality gripes (test coverage, docs, style) absent a documented standard (CLAUDE.md, ADR, or repo convention) that the diff violates.7778 Mirrored verbatim in `council`'s Falsifier seat brief (`skills/engineering/council/SKILL.md`) — keep the two lists in sync.7980 **Fix or name the failure.** A finding that survives the FP-exclusion list is confirmed actionable: the fix pass returns the specific fix, or the concrete failure point it hits. "The original is fine" is not available here — that judgment already happened in the FP-exclusion pass; re-arguing it re-opens a decided question and stalls the loop.81825. **CI gate.** Poll `gh pr checks` until all checks pass. Do not merge with red or pending CI.83846. **Merge.** `gh pr merge --merge` (merge-commit only; see [`merge-mechanics.md`](merge-mechanics.md)).85867. **Post-merge sync.**87 - `git checkout <default-branch> && git pull`88 - `git branch -d <feature-branch>` (remote branch is auto-deleted by GitHub; local is not)8990---9192## Promotion mode9394Applies only when the default branch is **not** `main`. When the default branch is `main`, feature merges are the final step and promotion doesn't exist.9596Always user-confirmed before running.9798- Triggered only by explicit invocation: `/flow-pr promote` or an explicit user request. Never auto-triggered.99- Opens `gh pr create --base main` from the default branch (e.g. `staging → main`).100- Merge-commit only; never squash or rebase.101102---103104## Autonomy triggers105106**Fire when all hold:**107- User explicitly signals done/ship, OR a coherent unit of work is logically complete, AND108- The verify gate is green (tests, typecheck, CI), AND109- The working tree is a reviewable diff (not mid-edit noise).110111**Do not fire:**112- After individual file edits.113- Mid-task or on work-in-progress.114- When the verify gate is red or failing.115- Before the unit is logically complete.116- On structural work without first proposing and getting go-ahead.117118A passing verify gate is what makes autonomous merge trustworthy — it is not optional.119120---121122## GraphQL flap resilience123124`gh pr create` and `gh pr merge` route through GraphQL, which can intermittently 401 even when auth is healthy.125126- **`gh pr create` failure:** fall back to REST — `gh api -X POST repos/{owner}/{repo}/pulls -f title=... -f body=... -f head=... -f base=...`127- **`gh pr merge` failure:** fall back to local `git merge --no-ff <feature-branch>` + `git push` from the integration branch (GitHub marks the PR merged).128- Check `gh auth status` before assuming a real auth failure. Note: `gh auth status` can report healthy without live-validating the token.129- If REST also 401s after a GraphQL flap, it is a real auth issue — surface to the user, do not re-run.