feat(api): gate apply start on confirmed sibling PR check holds - #941
Draft
aparajon wants to merge 3 commits into
Draft
feat(api): gate apply start on confirmed sibling PR check holds#941aparajon wants to merge 3 commits into
aparajon wants to merge 3 commits into
Conversation
This was referenced Aug 5, 2026
aparajon
force-pushed
the
armand/check-preflight-gate
branch
from
August 5, 2026 14:03
2d89e15 to
aeae2bb
Compare
aparajon
force-pushed
the
armand/check-hold-fanout
branch
from
August 5, 2026 14:03
8ab2a4c to
3973ef6
Compare
Before a driver starts an apply's engine work, it now records a durable preflight check refresh request and waits for the processor to confirm every sibling PR's stored check on the target is held action-required with its hold comment posted. The gate fails closed: a storage error or an unconfirmed hold abandons the drive attempt and leaves the apply claimable, so uncertainty is never converted into a started apply racing a green sibling check. A terminally failed preflight is re-armed for retry and the processor kicked again. The gate skips servers with no check refresh consumer (no GitHub runtime — nothing to hold) and applies with no tasks (a plan with no diff changes nothing, so there is nothing to hold against). Settles are now recorded on every terminal state — always for completed applies, and for failed/cancelled applies whose preflight held sibling checks — so a hold is always released by a re-plan against the live schema. A new preflight_gate_total metric counts passed/timeout/error outcomes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The check refresh request, the operator preflight gate, and their storage contracts are code-host independent: the gate keys off a registered consumer callback and durable request state, and any code-host integration can run the processor that drains requests. Core-layer comments, logs, and metric docs now describe that contract — a check refresh consumer, sibling change checks, a code-host outage — instead of naming GitHub, which is one adapter that implements it. GitHub vocabulary stays where the GitHub adapter lives (pkg/webhook, pkg/github). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
aparajon
force-pushed
the
armand/check-hold-fanout
branch
from
August 5, 2026 15:14
3973ef6 to
d30dc67
Compare
aparajon
force-pushed
the
armand/check-preflight-gate
branch
from
August 5, 2026 15:14
aeae2bb to
44166f4
Compare
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.
Why this matters
Holding sibling PR checks is only a guardrail if it happens before the apply changes anything. A multi-hour copy/cutover started from the CLI must not race the flip: if the holds land late, a sibling PR can merge on a green check the apply is about to invalidate. This PR makes the holds a hard precondition of the apply itself — the drive does not start engine work until every sibling PR's check flip and hold comment are confirmed landed, and it fails closed on any uncertainty. Stack 6/7, on top of #940.
What it does
gateApplyStartOnCheckPreflight), run when a driver claims an apply, before engine work:ReopenForRetryand re-kicked.schemabot.merge_gate.preflight_gate_totalwithpassed/timeout/error): a sustained non-passed rate means the processor is failing to drain preflights and applies on GitHub-configured servers are not starting — the metric comment says exactly that.pkg/api,pkg/storage,pkg/metrics) comments, logs, and metric docs describe that contract (a merge gate consumer, sibling change checks, a code-host outage); GitHub vocabulary lives only in the adapter (pkg/webhook,pkg/github), which is one implementation of the hold/re-plan fan-out. A future code-host integration registers its own consumer and renders the same stored state.Closing the loop: a commit pushed to a sibling PR while the apply is mid-flight would re-plan against the pre-apply schema and could mint a fresh green check — #942 closes that by storing such checks born held.
How it moves us toward the northstar
An apply's first observable effect is now telling every affected PR "this target is changing" — before a single row moves. Merge decisions and schema changes stop being able to race each other, which is exactly the safety bar a git-as-interface schema workflow has to clear.
The chain: #867 (storage) → #868 (drive-tail recording) → #866 (settle re-plan processor) → #939 (request kinds + hold storage) → #940 (preflight hold fan-out) → #941 (apply-start gate) → #942 (plan-time holds). Merges bottom-up; each PR retargets to
mainas its base merges.🤖 Generated with Claude Code