Daily operating policy
Use native GitHub stacked pull requests whenever reviewable changes depend on one another. This is our day-to-day workflow; no repository pilot or separate adoption approval is required. Split large dependent work into focused layers and continue on the next layer while earlier layers are reviewed. Keep independent changes on separate branches frommain, and keep a
single focused change in one PR.
GitHub’s upstream documentation currently labels the feature public preview.
That upstream label does not make our adoption a pilot. Follow the current
GitHub requirements
when capabilities change.
A stack has a trunk (normally main), a bottom PR targeting the trunk, and higher
PRs targeting the branch immediately below. Each layer shows its own diff. Put
foundations below their consumers; every layer must include the coverage and
supporting changes needed to review it. Do not separate regression tests merely
to leave an earlier layer unverified.
Native stacks and fallback chains
Native stacks require same-repository branches and fully linear history. Cross-fork
stacks and GitHub Desktop stack support are unavailable. A missing CLI extension
alone is not a reason to use manual chains: install it or create/link the stack
on GitHub. Record the concrete fallback reason in the PR and coordination note.
A non-main base or a stack label in a PR body does not establish native membership.
Tooling and worktree ownership
Install the official extension and inspect its supported commands:gh extension upgrade stack for an existing installation when an operation
needs a newer capability. Inspect its help and release notes before relying on
worktree support; do not mix extension versions during a paused operation.
The upstream agent skill is installed at .agents/skills/gh-stack, with source
tracking metadata for github/gh-stack@v0.2.0. Install or refresh it explicitly:
gh skill install github/gh-stack lists available skills in a non-interactive
terminal; supplying gh-stack installs it. Review upstream changes before updates.
Keep the installed files as upstream content; repository ownership, branch naming,
review gates, and delivery rules take precedence over generic skill examples.
Every open PR has an isolated owning worktree under .worktrees/. Run bun install
immediately after creating it. Never run bun setup, local builds, or local
bun check; use focused non-build checks and exact-head CI.
Current upstream gh-stack supports branches distributed across linked worktrees.
Its catalog and recovery journals live in Git’s common directory, so mutations
can affect more than the invoking checkout. Inspect active coordination notes,
git worktree list, and each affected owner’s status before rebase, sync, or
modify. Coordinate with those owners and keep affected worktrees idle. The
extension’s mutation lock does not serialize ordinary Git, editors, or agents.
Never use cascading commands to rewrite another owner’s work without coordination.
Use each branch’s owning directory for edits and commits. Navigation commands
such as gh stack checkout do not move a branch already checked out elsewhere;
use the reported owning path (or --print-path where supported). Do not switch
the shared main checkout or steal another worktree’s branch. Claim the repository
commit window before staging or committing; stage exact owned paths, not the
extension’s broad staging shortcuts.
See the upstream worktree and command reference
for version-specific behavior and recovery.
Repository corrections to upstream examples
Read these constraints together with the installed v0.2.0 skill; keep its vendored files unchanged so source tracking remains accurate:- A failed
gh stack syncrestores the cascade’s stack branches on conflict, but does not undo completed fetches or trunk fast-forwards. Inspect trunk and affected branch refs/worktrees after failure; recovery is not proof that the entire invocation left the clone unchanged. - A push rejection can come from remote movement, permissions, or server-side rules. Inspect the reported error and all affected remote heads, resolve its actual cause, and only then retry. Do not treat every rejection as a lease race or assume a multi-branch push completed atomically.
unstackandinitrebuild grouping metadata; they do not reorder existing Git ancestry. Preserve old boundary SHAs and deliberately reorder/rebase the commits first, then rebuild membership and rerun every affected gate.
Recover unexpected replay after a parent merge
A remaining child can have a valid scoped diff while the local catalog still tracks a merged parent. A cascading rebase can unexpectedly replay already landed commits and report conflicts in unrelated features. A stale parent tip is one possible boundary problem, but passing ancestry checks alone does not prove that the replay selected the correct range. Stop that replay rather than resolving those unrelated files into the child.- Abort the native rebase. Inspect every affected worktree and branch ref; completed fetches can remain after the abort.
- Recover the authoritative GitHub stack membership and base chain. Preserve
the pre-operation heads and local catalog boundaries. Check whether the
tracked parent tip and saved child base are ancestors of the child with
git merge-base --is-ancestor <boundary> <child-head>. Also inspectgit log origin/main..<child-head>and its diff, and compare the attempted replay with GitHub’s actual layer diff. Both boundaries can be ancestors while the attempted replay still includes unrelated landed commits. Confirm the parent is merged and the remaining range contains only owned unmerged changes; record the observed boundary mismatch without inventing a root cause. - Coordinate every affected owner and require clean, idle worktrees. When that
incorrect local replay range is confirmed, run
gh stack unstack --localand rebuild local tracking withgh stack init --base main <remaining-bottom> ... <top>in bottom-up order. This changes the local catalog; preserve the remote native group and its merge requirements. Do not remove server membership or rebuild ancestry as a shortcut around a native gate. - Inspect
gh stack view, then use the normal native rebase and push. Review only the intended conflicts, compare the resulting source with the preserved heads, and rerun focused regressions. - Read GitHub membership, bases and immutable heads again. Reconcile any partial push and rerun exact-head CI, reviews, the quiet window and contiguous-prefix gates before merging.
Create and submit a native stack
Create dependent branches in their owning worktrees, then adopt them in bottom-up order. Run from the bottom layer’s worktree:init can adopt existing branches without switching their owning worktrees.
For another dependent layer, create its worktree from the current top, install,
and adopt that existing branch with gh stack add feat/slice-three from the
top owner’s directory. Confirm this behavior in the installed version’s help.
gh stack submit --auto creates draft PRs; use --open when ready for review.
Inspect and edit every generated title/body to describe its focused change,
validation, and dependencies.
If PRs already exist, link them in bottom-up order without rewriting their
branches:
link can push branches, create PRs, and correct their bases; inspect the intended
membership and ownership first. Alternatively use GitHub’s Create stack
recommendation for an existing chain, or Add to stack for a new top layer.
Do not rewrite green published branches merely to register native membership.
Verify the stack map on GitHub or the PR REST resource’s stack metadata.
See creating stacks.
When running in T3 Code, register every created or worked-on PR with
link_pull_request, including each layer; gh stack submit and link do not
register them with the thread. Before closeout, reconcile list_thread_pull_requests.
GitHub’s stack map supplies ordering; still explain any dependency important to
reviewers in the PR body.
Iterate and review
Fix feedback in the layer that owns the behavior. Commit in its owning worktree, then cascade the change through higher layers:gh stack rebase to refresh the full stack from the trunk. These operations
rewrite affected histories; push uses force-with-lease. Inspect affected diffs
and record new heads, then rerun their focused checks, exact-head CI, and review
quiet windows. Do not merge main into native stack branches: restore linear
history with a cascading rebase.
On conflict, resolve only the reported files in the reported owning worktree,
stage them under its commit window, and run gh stack rebase --continue. Use
--abort to restore the pre-operation state when appropriate. Do not delete or
manually edit recovery journals. Server-side rebase creates unsigned commits;
use local signing when signed commits are required.
Humans can use the interactive gh stack modify for deliberate restructuring after
checking clean owners, linear history, and absence of queued merges. Dropping
work or rewriting another owner’s branch needs explicit scope/coordination.
Agents must not launch its TUI. For non-interactive restructuring, preserve the
old boundary SHAs, coordinate owners, and deliberately rebuild ancestry and
membership with unstack and init; do not drop work outside the authorized scope.
Submit the resulting composition again and review new diffs and heads.
Unstacking removes native membership while retaining bases; it changes the
workflow to manual chaining, not independent PRs. See
stack maintenance.
CI and merge gates
Native members use the trunk’s protections, required checks, CODEOWNERS, and pull-request workflow selection, even when their immediate base is another layer. A workflow filtering PRs tomain runs for native members whose trunk is main.
Custom automation must distinguish immediate base from stack trunk and handle
absent github.event.pull_request.stack for ordinary PRs. Do not disable a layer’s
required validation just because a higher layer is green. See the
Actions runbook.
Every selected layer needs its own resolved review threads, required reviews,
applicable successful exact-head checks, and five-minute review quiet window
(unless the user specified another duration). New pushes or review activity reset
the affected layer’s window. Record the complete selected prefix and all immutable
heads immediately before merging; stack CLI state alone is not a gate verifier.
Merge a verified prefix
Choose the highest PR in the authorized, fully verified contiguous prefix starting at the lowest unmerged layer. Landing the bottom alone remains useful when later layers need work. Landing a higher PR includes every unmerged PR below it; those PRs must all be within the authorized scope and pass the gates.
For a native stack, use the official stack merge operation with an explicit PR
and merge method:
gh stack merge: it can select the entire
stack. Native merges support merge, squash, and rebase; --merge remains our
normal choice. The extension checks only basic PR state before asking GitHub to
merge, does not bypass requirements, and has no equivalent to
gh pr merge --match-head-commit. Re-read all selected heads and gates just before
invoking it; if any changed, repeat validation. Do not apply the ordinary admin
merge fallback to native stacks. Custom API clients must use GitHub’s asynchronous
stack merge API, rather than the ordinary single-PR endpoint.
Merge queues may enqueue the selected group and split it across consecutive
merge groups. Queued is not merged; wait for every selected PR’s merged state and
record the resulting trunk SHA. Native stack auto-merge is not supported. See
GitHub merge requirements.
After a partial merge, confirm remaining membership, retargeting, diffs and heads.
Run gh stack sync only after coordinating affected worktrees: it can fetch,
fast-forward trunk, rebase remaining branches, and push. Rerun gates for changed
heads. Avoid --prune until each branch/worktree is eligible for cleanup; do not
update another session’s main checkout or resolve divergence by discarding its work.
Verify exact merged-main CI for the requested integration. Production sync and
its deployment/migration verification require production authorization; a request
to merge into main alone does not authorize bun git-sync.
Manual base-chain fallback
Without native membership, merge one PR at a time, parents first. Use a merge commit (gh pr merge <parent> --merge --match-head-commit <head-sha>) to keep
parent ancestry reachable from main. Squash/rebase merges can make child diffs
repeat already landed work; repair the child deliberately and rerun its gates.
Confirm each child’s baseRefName, diff, and checks after the parent merges.
Retarget with gh pr edit <child> --base main if needed. A base edit may not
trigger the configured workflows, so verify actual runs rather than assuming CI
restarted. Do not delete remote parent branches outside the PR merge flow:
dependent PRs can close instead of retargeting.
Cleanup
After the PR is confirmed merged intomain and the requested delivery gates pass,
remove only its completed clean owning worktree and local task branch. Keep dirty,
blocked, unmerged, active, or other-owned work. When production delivery was requested,
retain the worktree through production verification. Archive your completed
coordination note; never commit it.