Stacked PRs
Stack mode (default for mainark implement) opens pull requests in a chain: each dependent PR targets its blocker's branch, not main.
Why stack
For chains like FUL-576 → FUL-419 → FUL-578:
- Each PR stays small and reviewable
- GitHub shows only the delta for that ticket vs its parent branch
- Agents can proceed on dependents before earlier PRs merge (branches exist on the remote after push)
Requirements
- Linear
blockedByrelations — Mainark reads these to order work and set stack bases - Stack mode on — default; disable with
--no-stackonly for legacy merge-first waves mainark publish— usesstackBasefrom.mainark/issue.jsonwhen opening the PR
How stackBase is set
For issue B blocked by A:
- B's git branch is created from A's branch
- B's manifest gets
stackBase: "feat/ful-…-A-slug"(blocker branch name) gh pr create --base <stackBase>instead of--base main
Dry-run preview:
mainark implement --plan FUL-576 FUL-419 FUL-578
# or
mainark parallel --plan FUL-576 FUL-419 FUL-578
Output shows PR → main vs PR → feat/ful-…-576-….
Merge order
Review and merge from the bottom of the stack up (root → dependent):
FUL-576 → PR base: main merge first
FUL-419 → PR base: FUL-576 branch merge second
FUL-578 → PR base: FUL-419 branch merge third
After GitHub merges the base PR, retarget or merge dependents according to your team's stacked-PR workflow (GitHub often offers "merge into main" after base lands).
Epic phase checkpoints (checkpoint: merge in ## Mainark plan) pause until all phase PRs are merged, then --resume advances.
Epic plan stacking
In the Linear epic description:
## Mainark plan
### Phase 1 — Foundation
checkpoint: merge
stack: true
- FUL-516 base: main
- FUL-517 base: stack
stack: trueon the phase enables chained bases within the phasebase: stackmeans "branch from previous issue in this phase"
CLI vs orchestrator
| Stacked PRs | |
|---|---|
mainark implement / parallel | Yes |
mainark dev (backend) | No — PRs use main today |
Review diffs
Local pre-push review compares against stackBase (or main for roots), not always origin/main. That keeps review scoped to the ticket's changes.