fix(ci): bypass the changeset requirement on mid-stack PRs - #83
Conversation
Require Changeset runs only on PRs based on `main` and reads the PR's own diff, so a mid-stack PR never runs it and the bottom PR is the only place a changeset can satisfy it. Labelling mid-stack PRs `skip-changeset` implies a decision that was never needed; putting the changeset at the base means every branch above inherits it. Grow that one file as the stack lands, so a reviewer evaluates a release note matching the diff in front of them rather than the whole future change. Also notes in iterate-pr that a lower PR on a merge-down stack can be legitimately red, with the instruction to verify that against the change's own tasks rather than assume it.
On a stack, one changeset describes the whole change and lives on the bottom PR — the one targeting `main`, which is where the check has to pass. Branches above inherit that file, so it is never *added* in a child's own diff and every mid-stack PR failed. Labelling them `skip-changeset` records a deliberate "ships no release note," which is false, so the workflow bypasses on the base ref instead. The `on: branches: [main]` filter does not hold for stacked PRs in practice — the workflow still runs on a PR based on a feature branch — so the base is re-checked inside the step rather than trusted. Observed on #80, #81, and #73, all of which ran and failed the check with a non-main base.
256f6f2 to
2944a99
Compare
…k branch Branching "from main" immediately after a propagate picks up the last rebased branch instead, so the new PR carries the entire stack and an OpenSpec change directory it never touched. Hit while opening this PR.
There was a problem hiding this comment.
Pull request overview
Updates repository guidance and CI behavior around changesets in merge-down stacks, aiming to ensure only the stack’s bottom PR (targeting main) is responsible for adding and evolving the single changeset while mid-stack PRs don’t get pressured into using skip-changeset.
Changes:
- Add workflow logic to bypass the changeset requirement when the PR base branch is not
main. - Document “one changeset on the bottom PR, grown incrementally” guidance in
CLAUDE.md. - Extend the
iterate-pragent skill docs with stack-specific failure interpretation and workflow hygiene notes.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
CLAUDE.md |
Adds documented guidance for changeset placement/growth on merge-down stacks. |
.github/workflows/require-changeset.yml |
Adds a base-branch guard to bypass the changeset requirement for non-main base refs. |
.agents/skills/iterate-pr/SKILL.md |
Documents stack-related “structural” failures and safe next-steps for iterate-pr. |
|
@claude /review |
|
Claude finished @thecodedrift's task in 4m 19s —— View job Review of #83Summary: This PR is documentation + a defensive CI guard, all correct in intent (one changeset lives on the bottom PR of a merge-down stack and is inherited by children; 1. The "
|
…laim Review pushed back on three statements, and two of them were wrong. `propagate_stack.py` does return you to the branch you started on — normal completion, rebase conflict, balloon guard, and push failure all check it out before returning. Only a failure to check out a *child* (exit 6, typically that branch being held by a worktree) returns early without it. That is the path that actually bit, so the warning now names it instead of describing the script's normal behavior. The `branches: [main]` claim is reframed rather than dropped. It is documented to filter on the base branch, and the guard should be unreachable — but #73, #80, and #81 each produced a failing `Require a changeset` check run with an `openspec/partition-engine-*` base, and a workflow that never triggers produces no check run at all. The comment now cites that evidence and presents the check as a defensive guard, without teaching that Actions filters are unreliable in general. Also replaces the "structural failures are acceptable" guidance with the opposite rule: a mid-stack PR that is red is incomplete, and the fix belongs in it. That advice let this stack sit on 20 failures that turned out to be two real defects.
…l target `branches: [main]` reads as "only PRs whose base is main," and filtered that way when a PR had one base. Under GitHub's stacked-PR support a stacked PR targets `main` eventually, so the filter matches the eventual target and these workflows run on mid-stack PRs too — which is why #73, #80, and #81 each produced a failing `Require a changeset` run with an `openspec/partition-engine-*` base. That makes the base-ref guard required rather than defensive, and generalizes: a workflow whose correctness depends on "is this the PR that merges to main" has to establish that itself. Corrects the OpenSpec archive-check section too, which told readers a stacked PR would not run that check at all.
Both findings were right, and both are fixed. The The So the conclusion inverts: — AI Coding Agent |
Both of your findings are addressed (replied inline and resolved). The — AI Coding Agent |
Records how changesets behave on a merge-down stack, learned while landing the
partition-rules-by-enginestack (#79 → #80 → #81 → #73).require-changeset.ymlison: pull_request: branches: [main]and looks for a.changeset/*.mdadded in that PR's own diff. So a mid-stack PR never runs the check at all, and the bottom PR is the only place a changeset can satisfy it — one added on the tip is invisible to the diff of the PR that actually merges. Labelling mid-stack PRsskip-changeset"fixes" a check that was never going to run, while implying the change ships no release note.Putting the changeset at the base means every branch above inherits it, since a child contains its ancestors' commits.
The guidance also asks for the changeset to be grown as the stack lands rather than written up front to describe the whole future change, so a reviewer evaluates a release note that matches the diff in front of them.
Separately,
iterate-prnow names the other structural red check on this shape: a lower PR can be legitimately failing because the unit that completes it has not landed yet. The instruction is to verify that against the change's own tasks by running the suite on the branch — not to assume it, and not to write throwaway assertions to make an intermediate state look green.