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

  1. Linear blockedBy relations — Mainark reads these to order work and set stack bases
  2. Stack mode on — default; disable with --no-stack only for legacy merge-first waves
  3. mainark publish — uses stackBase from .mainark/issue.json when 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: true on the phase enables chained bases within the phase
  • base: stack means "branch from previous issue in this phase"

CLI vs orchestrator

Stacked PRs
mainark implement / parallelYes
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.