Skip to content

fix(skills/fanning-out-with-worktrees): stop self-merging sub-PRs with red CI - #104

Merged
sourcehawk merged 4 commits into
mainfrom
fix/sub-pr-ci-gate
Nov 3, 2026
Merged

sourcehawk merged 4 commits into
mainfrom
fix/sub-pr-ci-gate

Conversation

@sourcehawk

@sourcehawk sourcehawk commented Nov 3, 2026 •

Copy link
Copy Markdown
Owner

Description

Fixes #101

An orchestrator that runs a fan-out with sub_pr_approval: autonomous can self-merge a sub-PR whose CI is red, because Step 5 of fanning-out-with-worktrees goes from the review passes to the merge and never reads the PR's checks. This PR adds a CI gate before every sub-PR merge: the orchestrator reads every check on the head, waits in the background while checks run, and sends a failed check back to the worktree subagent the same way it sends a review finding. The integration PR gets no new gate here: developing-a-feature Step 7 already holds the teardown until the PR's checks are green, and the PR is not reported ready-to-merge before the teardown lands.

Changes

  • Step 5 has a new item 5, CI gate, between the ready flip and the merge. It covers four cases: all checks passed, checks pending (wait with gh pr checks <num> --watch --fail-fast in the background), a check failed or was cancelled (do not merge, send the check name, link and failed log to the subagent, then run the review items, the approval gate and the CI gate again on the new head), and no checks reported (decide from the repo's CI configuration, as Step 7 of developing-a-feature does).
  • The gate reads every check, not only --required. A feature branch seldom has protection rules, so it has no required checks to list. When CI starts a run on the ready transition, the gate waits until that run's checks show a startedAt later than the flip, so draft-time results do not pass it.
  • In stacking-dependent-prs §After a parent merges, a layer that gh stack sync rebased with no changed commit keeps its review and approval gates but not its CI gate. The CI gate reads the checks of the new head.
  • The ready flip is now its own item 4, before the gate, because some pipelines skip drafts and start only when the PR is ready. The later items are renumbered (merge is item 6). The bundle list in the approval gate and the Step 5.6 reference in the anti-patterns now use the new numbers. The Step 5, item 4 reference in stacking-dependent-prs still points at the ready flip.
  • A new red-flag row answers "the review loop is clean and the subagent's tests pass locally, so I can merge".

Testing

I tested the change with the RED → GREEN loop of superpowers:writing-skills. Each run was an isolated subagent with only the skill file and the scenario from #101: autonomous approval, a clean review loop, a subagent that did not run the full end-to-end suite, and a user who said "keep it moving".

  • RED, old skill: in 4 of 6 runs the agent flipped the PR ready and merged it with no read of its checks. In the other 2 runs the agent read the checks on its own judgment. One of those ran --watch in the foreground, and the other sent the red check to the user and not to the subagent.
  • GREEN, new skill, e2e red: 4 of 4 runs read gh pr checks after the flip, did not merge, fetched the failed log, and sent it to the worktree subagent. Each run then planned the review items and the gate again on the new head.
  • GREEN, new skill, e2e pending: 2 of 2 runs started the watch in the background, did not merge, and sent the failure to the subagent when the watch exited.

The three review fixes (the wait for the ready-transition run, the second approval after a CI fix, and the CI gate after a stack sync) did not get their own subagent runs.

The JSON in .claude-plugin/ parses. No script changed, so I did not run the script tests. A grep of the added lines found no project or product names.

🤖 Generated with Claude Code

Step 5 went from the review passes and the approval gate straight to
the merge, with no step that read the PR's checks. An orchestrator
could self-merge a sub-PR whose end-to-end check was red, because the
subagent ran only what fit on its machine and the review loop does not
read CI.

Split the ready flip out of the merge item and add a CI gate between
them: read every check on the head (not only --required, since a
feature branch seldom has protection rules), wait in the background
while checks are pending, route a failed or cancelled check back to
the worktree subagent like a review finding, and decide an empty
reading from the CI configuration. Renumber the later items and the
references to them, and add a red-flag row for "review clean and local
tests pass, so merge".

Towards #101

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings November 3, 2026 21:25

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.

🟡 Changes recommended

The merge flow can accept stale CI results after ready transitions or head rewrites and bypass renewed manual approval after CI fixes change the diff.

3 open issues
What changed in this PR

This PR addresses #101 by adding a CI gate to the fan-out workflow before sub-PR merges, so clean reviews and local tests alone do not authorize a merge.

Changes:

  • Separates the ready flip from merging and checks all reported CI checks afterward.
  • Adds background waiting, routes failed checks to the worktree subagent, and handles repositories without applicable CI.
  • Updates step references and adds a red flag against merging without checking CI.
File Description
skills/​fanning-out-with-worktrees/​SKILL.md Adds the pre-merge CI gate, failure recovery instructions, and updated workflow references.

Review effort: Balanced

sourcehawk and others added 3 commits November 3, 2026 21:30
…dy flip starts

A pipeline that runs on the ready transition starts after the flip, so a
read right after it can still show the draft-time results, skipping
among them, and pass the gate on checks that never ran on the ready PR.
The gate now waits until that run's checks show a startedAt later than
the flip.

Towards #101

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…a CI fix

In manual mode the user approves the diff at item 3, before the CI gate.
A fix for a red check changes that diff, so the route back now runs
item 3 again before the gate, and the user sees the changed diff before
it merges.

Towards #101

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…es a layer

After a parent merges, gh stack sync gives each layer above a new head
on a new parent. A layer whose commits all show = in range-diff kept
every gate it had passed, the CI gate among them, so it could merge on
the old head's checks. It now keeps only its review and approval gates,
and the CI gate reads the checks of the new head.

Towards #101

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings November 3, 2026 21:30
@sourcehawk

Copy link
Copy Markdown
Owner Author

Review round 1 (review of 0d30f68): 3 inline findings, 0 suppressed findings. All 3 are applied, and each thread has a reply.

  • Ready-transition CI: b51c260
  • Approval again after a CI fix: b64f4ed
  • CI gate after a stack sync: d9fe559

Comment gate (addressing-review-feedback), review base 0d30f68: 0 flagged, 0 listed, 0 removed, 0 not checked. The changes touch only skill prose, so no code comment changed.

Declaration Lines then / now Verdict
(none) — no change

The ubuntu-latest, Python 3.9 check fails for a reason outside this PR. The runner image is now Ubuntu 26.04, and actions/setup-python has no Python 3.9 build for it (The version '3.9' with architecture 'x64' was not found for Ubuntu 26.04). The job stops before the tests start.

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.

🟢 Approval recommended

No active review issues block approval of the pre-merge CI gate changes.

No open issues 🎉

3 resolved since last review

Review effort: Balanced

@sourcehawk
sourcehawk merged commit 28869ba into main Nov 3, 2026
5 of 6 checks passed
@sourcehawk
sourcehawk deleted the fix/sub-pr-ci-gate branch November 3, 2026 21:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fanning-out-with-worktrees: sub-PRs are self-merged without checking that CI passed

2 participants