feat(ci): preserve merged PRs in the stack breadcrumb - #51
Merged
Conversation
The breadcrumb previously dropped merged PRs (tree built from open PRs only) and cleared entirely once a stack collapsed to its last open PR — losing the record of how the final merged-down PR was constructed. Now the reconcile step also pulls in the stack members recorded in existing breadcrumb markers that are no longer open, fetches them for tree structure, and keeps them in the rendered list. GitHub auto-renders the PR reference with its merged/closed badge, so no explicit status marker is needed. Merged/closed members are frozen — reconcile keeps them in the tree (so open PRs keep listing them and the last open PR captures the whole history) but never rewrites their bodies. Root resolution still uses the open-PR list only. - stack-breadcrumb.cjs: reconcile skips writing any member whose state is not 'open' (records them under a new 'frozen' bucket); members without state are treated as open (unit fixtures / open-PR list). - stack-breadcrumb.yml: the reconcile job collects historical members from open PRs' markers, fetches them via pulls.get with state, and passes the union to reconcile; open PRs are tagged state: 'open'. - tests: a merged member is frozen but still listed; a lone open root with only merged descendants still renders (no clear). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the stack-breadcrumb GitHub Actions workflow + its zero-dependency reconciliation script to preserve full stack history by keeping merged/closed PRs in the rendered breadcrumb, so the last open PR in a stack doesn’t lose the construction record.
Changes:
- Extend Stage 2 (reconcile) to fetch and include merged/closed stack members referenced by existing breadcrumb markers, and pass the union into
reconcile. - Add a “frozen” bucket in
reconcileso merged/closed members remain in the tree but their PR bodies are never rewritten. - Add unit tests covering “frozen merged member” behavior and the “lone open root with merged descendants” case.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| .github/workflows/stack-breadcrumb.yml | Includes historical (non-open) PRs from existing breadcrumb markers and reconciles using the union list. |
| .github/scripts/stack-breadcrumb.cjs | Freezes non-open PRs during reconcile while still rendering them in open PR breadcrumbs. |
| .github/scripts/stack-breadcrumb.test.cjs | Adds coverage for frozen merged members and “don’t clear breadcrumb” behavior when only descendants are merged. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Address Copilot review on #51: - Skip a historical (merged/closed) PR whose head ref collides with an open PR's headRefName — the tree is keyed by head ref, so a reused branch name would corrupt derivation. - Validate marker member numbers (positive integers) before fetching, guarding against a malformed marker. - Fetch the historical members in parallel instead of sequentially (the set is bounded by stack size). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Follow-up to the previous hardening: the head-ref collision guard only compared historical PRs against open PRs. Two historical (merged/closed) PRs that reused the same branch name could still collide in the head-ref-keyed tree. Admit a historical PR only if its head ref isn't already claimed by an open OR an earlier historical member. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The pr= marker lives in a user-editable PR body, so a crafted/malformed list could trigger a large burst of pulls.get calls. Cap the historical fetch at 50 members (with a truncation log) before issuing any API calls. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The stack breadcrumb dropped merged PRs and cleared entirely once a stack collapsed to its last open PR, so the record of how the final merged-down PR was constructed was lost. This keeps the full history.
What changes
pr=list,pulls.gets any member that's no longer open, and passes the union toreconcilefor tree structure + rendering. Root resolution still uses the open-PR list only.reconcilekeeps them in the tree (so open PRs keep listing them, and the last open PR captures the whole stack) but never rewrites their bodies (newfrozenbucket; members without astateare treated as open, so unit fixtures are unaffected).#123reference with its merged/closed badge, so plain list items are enough.Result
After landing a stack (e.g.
50 → 49 → 47), #47 (the last to merge) freezes with:where #49/#50 render with their merged badges — a permanent record of the construction.
Notes
.github/**); the zero-dep.cjsis covered by itsnode --testsuite (41 tests, +2 here). Workflow YAML validated.main.🤖 Generated with Claude Code
https://claude.ai/code/session_01TEuUE3F23dgEyrkGPq3FiM