Skip to content

Integrate GitHub native stacked pull requests into carve-changesets #108

Description

@shaug

Outcome

Integrate GitHub's native stacked pull request support into carve-changesets while preserving immutable source identity, changeset provenance, exact-head evidence, explicit remote-mutation authority, and compatibility with ordinary unlinked PR chains.

GitHub announcement: https://github.blog/changelog/2026-07-30-stacked-pull-requests-are-now-in-public-preview/

Context

GitHub native stacks introduce first-class stack membership, trunk-relative protections and CI, atomic contiguous-prefix merges, and automatic rebasing and retargeting of the remaining suffix. The current carve-changesets workflow publishes correctly based ordinary PRs, delegates one PR lifecycle at a time, merges one PR, and then propagates the suffix itself.

Without native-stack awareness, a native stack merge can merge multiple PRs and rewrite the remaining suffix before carve-changesets resumes, making the existing merge-and-propagate path unsafe.

Scope

  • Detect native stack capability and live stack membership during publication, status, validation, lifecycle handoff, merge, propagation, recovery, and resume.
  • Register a published changeset chain as one GitHub native stack through the GitHub REST stack API when native mode is selected and supported.
  • Read back and verify the native stack number, trunk, ordered PR membership, positions, heads, bases, and size against live git, commit trailers, and carve-changesets PR metadata.
  • Keep native GitHub stack topology distinct from changeset provenance:
    • GitHub stack state is live topology and merge behavior.
    • Commit trailers and delimited PR metadata retain changeset intent, stable index, immutable source lineage, and recovery provenance.
  • Model the predecessor branch and SHA used for a layer's review diff separately from the native stack trunk used for GitHub protections, required checks, CODEOWNERS, and CI.
  • Add a safety fence that blocks legacy merge-propagate and propagate behavior when native stack membership is present but the native workflow cannot be completed safely.
  • Replace the legacy single-PR merge path for native stacks with GitHub's asynchronous stack-aware merge API, fenced by the exact selected PR head SHA.
  • Resolve and report the exact contiguous PR prefix affected by a native merge before mutation; require merge authority to cover every affected PR.
  • Poll and verify the asynchronous merge result, then rehydrate every affected PR, branch, base, head, and mainline result from live GitHub and git state.
  • Accept GitHub's automatic suffix rebase and retarget only after verifying order, ownership, exact new identities, linearity, and whole-chain equivalence. Do not run duplicate manual propagation afterward.
  • Invalidate and rebuild candidate-bound validation, review, CI, feedback, and mergeability evidence for every head or effective-candidate change caused by native stack operations.
  • Update the babysit-pr handoff so ownership of one PR cannot implicitly authorize or report merges of other stack members. Define the stack-level handback needed before an atomic native merge.
  • Preserve suffix-recovery safety, stable positions, PR identities, source lineage, exact leases, and resumability when a native stack is involved.
  • Preserve capability-gated support for existing unlinked v1/v2 chains and repositories where the public-preview APIs are unavailable.
  • Update the normative contract, CLI reference, suite handoffs, implementation, tests, and evaluations together.

Acceptance criteria

  • Status clearly classifies a published chain as unlinked, native, unavailable, or inconsistent using live GitHub evidence.
  • Publishing in native mode creates or adopts exactly one same-repository GitHub stack with the expected trunk and ordered PR membership, then verifies the returned state.
  • A partially created or externally modified native stack fails closed with exact recovery guidance; weaker plan or cached state cannot override GitHub.
  • Native stack reads work through documented REST or GraphQL fields without depending on gh stack private local tracking.
  • Review packets continue to use each layer's exact predecessor comparison base, while GitHub gate evidence records the native stack trunk separately.
  • Native merges use the asynchronous stack-aware merge endpoint with an exact expected head SHA and explicit affected-prefix authority.
  • A native merge never falls through to the legacy gh pr merge plus manual suffix propagation path.
  • After a native merge, every merged PR is verified on the trunk and every automatically updated suffix head and base is rehydrated and validated before further delegation.
  • Head-changing native operations invalidate all candidate-bound evidence required by the existing contract.
  • babysit-pr cannot merge an implicit PR prefix under authority granted for only one PR.
  • Existing ordinary unlinked chains retain their current behavior and evaluations.
  • Existing v1 and v2 provenance and suffix-recovery invariants remain valid for both native and unlinked modes.
  • Public-preview capability absence or incompatible API behavior produces a precise safe fallback or blocked result rather than partial mutation.
  • Tests cover native publication, adoption, inconsistent membership, atomic prefix merge, merge queue selection, automatic suffix rebase/retarget, interrupted async merge, evidence invalidation, recovery, and legacy fallback.
  • just format, just lint, and just test pass.

Non-goals

Coordination

Coordinate the babysit-pr ownership and terminal-result seam with #104 and keep the carve-changesets remediation migration in #105 separate. This ticket owns native GitHub stack topology, publication, merge, and propagation semantics.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions