Skip to content

fix(ship): recheck pull requests before transition dispatch - #2234

Merged
justinhelmer merged 1 commit into
mainfrom
fix/2208-fresh-pr-transition-reads
Sep 22, 2026
Merged

justinhelmer merged 1 commit into
mainfrom
fix/2208-fresh-pr-transition-reads

Conversation

@coreplane-switchboard

Copy link
Copy Markdown
Contributor

Ship transitions now re-read pull request state, head, and branch existence before posting or dispatching follow-up work. Deleted, moved, closed, merged, or unreadable heads therefore fail closed instead of advancing stale work.

Why: Closes the remaining three findings on #2208. After #2221 landed, these stale-read paths were the remaining contradictions of agent-ship items 9 and 10.

Where to look

  1. Branch-aware verdict guard Requires one fresh facts read to prove the PR is open, its head ref exists, and the pinned commit still matches before posting. ⚠ A false positive could post a stale approval.
  2. Rebase outcomes stop for fresh facts Routes both conflict and changed resolver results into a pull-request check instead of dispatching immediately.
  3. Refreshed rebase dispatch Ends on terminal or deleted heads and pins any replacement coding or review child to the newly read head. ⚠ Wrong routing could spawn work on a stale or deleted branch.
  4. Recovered branch refresh Re-reads an open-or-edit result through the shared facts reducer; unknown branch state becomes a retryable GitHub error. ⚠ Recovery is a restart boundary for pushed child work.
  5. Deleted post regression Proves a lingering pinned SHA cannot bypass deleted or unreadable branch facts.
  6. Post-rebase dispatch regression Proves deleted conflict heads spawn nothing and moved changed heads pin review to the refreshed commit.
  7. Recovered-branch regression Proves deleted facts are returned fail-closed while unknown and unavailable facts return retryable errors.

Feedback wanted: Please focus on whether every dispatching rebase outcome is held behind the fresh pr-check and whether recovery preserves durable retry semantics.

Risk: The blast radius is ship review posting and coordinator follow-up dispatch. A mistake can suppress a valid transition or act on stale GitHub state; rollback is the single commit.

Verified: Passed 454 targeted tests, root TypeScript, changed-file Prettier/ESLint, hygiene, specs, and specs coverage; CI remains the merge gate.

Decisions (2)
  • Use full facts only for the ship post guard. Standalone reviews retain their existing post-publication head read. Ship children need the stronger pre-write state/head/ref proof because the parent can revoke that transition while the child runs.
  • Model rebase refresh as a durable pr-check phase. Calling GitHub inside the pure machine would violate the coordinator boundary. A named pr-check step lets the existing adapter return retryable 502s for unknown branch state and keeps dispatch pure over facts.
Validation (5 criteria)
Criterion Proof
Each reported stale-read path has a regression that fails on the old behavior The initial targeted run failed exactly the new review-post, rebase-dispatch, and recovered-branch tests; all three pass at the pushed head.
Deleted or unreadable heads block all three transitions npx vitest run src/core/reviewRound.test.ts src/core/ship/coordinator.test.ts src/channels/adminCoordinator.test.ts src/core/dispatch/runLoop.test.ts src/core/coordinator/driver.test.ts — 454 passed.
Changed TypeScript remains type-safe NODE_OPTIONS=--max-old-space-size=6144 npx tsc --noEmit -p tsconfig.json — passed.
Changed files meet style and static-analysis gates npx prettier --check <11 changed files> and npx eslint <10 changed TypeScript files> — passed.
Specification bindings and repository hygiene remain valid npm run hygiene:check; npm run specs:check; npm run specs:coverage -- --changed origin/main...HEAD --test-guard — passed.
For agents

Rebased onto origin/main at 3dd0af6 immediately before the final gate run and push. The implementation commit is 6be601e. The three regressions are bound to agent-ship items 9 and 10 in docs/reference/specs/agent-ship.md.
Requested by @justinhelmer in slack:C0BRRHKFLCB

🤖 Generated with Claude Code

Co-Authored-By: coreplane-switchboard[bot] <318072483+coreplane-switchboard[bot]@users.noreply.github.com>

@coreplane-switchboard coreplane-switchboard Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

LGTM: The fresh PR-facts guards close the transition races without weakening existing review or coordinator behavior.

Note

Approved · head 6be601e · no findings

Full review

No findings. The transition guards consistently fail closed on stale, deleted, or unreadable pull request heads.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Auto-approved: coreplane-switchboard[bot] reviewed this PR and posted an LGTM verdict (see its review). This repository opted in through its REVIEW_BOT_LOGIN and REVIEW_BOT_ID variables.

@coreplane-switchboard coreplane-switchboard Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

LGTM: The fresh pull-request reads correctly fail closed and preserve the coordinator's transition invariants.

Note

Approved · head 6be601e · no findings

Full review

No findings; the fresh transition reads and fail-closed handling are consistent with the coordinator’s state invariants.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Auto-approved: coreplane-switchboard[bot] reviewed this PR and posted an LGTM verdict (see its review). This repository opted in through its REVIEW_BOT_LOGIN and REVIEW_BOT_ID variables.

@justinhelmer
justinhelmer merged commit 32873f4 into main Sep 22, 2026
31 checks passed
@justinhelmer
justinhelmer deleted the fix/2208-fresh-pr-transition-reads branch September 22, 2026 20:57
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.

1 participant