Skip to content

fix(ci): Enforce canonical region order in stacked-PR bodies#63

Merged
thecodedrift merged 2 commits into
mainfrom
fix/stack-breadcrumb-canonical-order
Jul 12, 2026
Merged

fix(ci): Enforce canonical region order in stacked-PR bodies#63
thecodedrift merged 2 commits into
mainfrom
fix/stack-breadcrumb-canonical-order

Conversation

@thecodedrift

Copy link
Copy Markdown
Member

Formalizes the order the managed regions appear in a stacked-PR body, and makes a stack sync reformat existing PRs to that order.

A stacked-PR body carries up to three managed regions: the stack breadcrumb (<!-- stack … -->), the human description, and carried-forward legacy (<!-- PR:N --> blocks, a merged child's body accumulated into its surviving parent). Their order was never defined — spliceRegion and upsertCarriedRegion both replace-in-place when the region exists and otherwise append, so a region stayed wherever it first landed. Depending on authoring history a PR could open with the breadcrumb, the description, or the legacy first, and reconcile only ever swapped content in place, never re-sorted.

This adds canonicalizeBody as the single layout authority and fixes the order to breadcrumb → description → carried-forward (carried sorted ascending by PR number). Both writers route through it:

  • Sync path (planUpdatereconcile): a git town sync / shape-change reconcile now also normalizes layout — the one moment the region order actually matters, per the discussion that prompted this.
  • Merge path (carryForward): ends with the same canonicalization, preserving the existing breadcrumb, so whichever of the two jobs writes the parent body last, the result is the same canonical string (race-safe, idempotent, convergent).

canonicalizeBody returns a body with nothing managed (no breadcrumb to place, none present, no carried regions) byte-for-byte untouched, so a plain non-stacked PR's description is never rewritten — this preserves the old spliceRegion no-op that kept reconcile from churning ordinary PRs. spliceRegion is retired (its in-place semantics were exactly why order was never enforced); its meaningful invariants moved into canonicalizeBody tests.

Reviewer notes:

  • The breadcrumb → description flip is the visible behavior change; existing PRs re-sort on their next stack sync, not retroactively.
  • Workflow-only change (.github/scripts/*.cjs), no published package touched, so no changeset.
  • 61 node --test cases pass; both files are prettier-clean.

🤖 Generated with Claude Code

Stacked-PR bodies carry three managed regions — the stack breadcrumb, the
human description, and carried-forward <!-- PR:N --> legacy — but their order
was emergent: spliceRegion and upsertCarriedRegion replaced in place or
appended, so a region stayed wherever it first landed.

Add canonicalizeBody as the single layout authority: breadcrumb → description
→ carried-forward (ascending PR#). Route the sync path (planUpdate/reconcile)
and the merge path (carryForward) through it so both converge to the same
canonical body, and a git town sync reformats an existing PR — the one moment
the order matters. A body with no managed regions is returned untouched, so
plain non-stacked PRs are never rewritten. Retire spliceRegion, now subsumed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 12, 2026 20:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR formalizes a canonical layout for stacked-PR bodies by introducing canonicalizeBody as the single authority for ordering managed regions, and routes both sync-time reconciliation and merge-time carry-forward through it to ensure deterministic, convergent formatting.

Changes:

  • Introduces canonicalizeBody to enforce breadcrumb → description → carried-forward ordering (with carried regions sorted by PR number).
  • Updates sync-time body planning (planUpdate) to reflow existing out-of-order bodies into canonical order.
  • Updates merge-time carry-forward (carryForward) to canonicalize the final parent body so merge and sync paths converge.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
.github/scripts/stack-breadcrumb.cjs Adds canonicalizeBody, removes spliceRegion, and routes reconcile + carry-forward through canonical layout.
.github/scripts/stack-breadcrumb.test.cjs Replaces spliceRegion tests with coverage for canonical ordering, idempotence, carried sorting, and sync/merge convergence.

Comment thread .github/scripts/stack-breadcrumb.cjs
@thecodedrift thecodedrift added the skip-changeset PR intentionally ships no release note (bypasses the changeset requirement) label Jul 12, 2026
canonicalizeBody derives the description via ownDescription, which used
.trim() — stripping leading indentation from a managed PR's prose, so a
description opening with an indented Markdown code block could be silently
reflowed. Tidy only the whitespace the region surgery introduces: collapse
seams, drop leading blank lines, and trim trailing whitespace, leaving the
first line's indentation intact.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@thecodedrift
thecodedrift merged commit c76b2cd into main Jul 12, 2026
4 checks passed
@thecodedrift
thecodedrift deleted the fix/stack-breadcrumb-canonical-order branch July 12, 2026 23:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changeset PR intentionally ships no release note (bypasses the changeset requirement)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants