feat(api): record durable merge gate requests at apply drive tails - #868
Draft
aparajon wants to merge 4 commits into
Draft
feat(api): record durable merge gate requests at apply drive tails#868aparajon wants to merge 4 commits into
aparajon wants to merge 4 commits into
Conversation
This was referenced Aug 5, 2026
aparajon
force-pushed
the
armand/check-refresh-drive-tail
branch
from
August 5, 2026 14:03
02dbe05 to
6ba60ea
Compare
aparajon
force-pushed
the
armand/check-refresh-storage
branch
from
August 5, 2026 15:13
4a57268 to
5bce323
Compare
When a drive settles an apply to terminal success, the target's live schema has changed and other open PRs' stored check state against that target is stale. The operator drive tails now record a durable check refresh request (idempotent per apply) as part of the terminal transition, before pending control requests are completed — the same ordering the terminal summary uses. Recording never fails the drive: a storage error is logged and counted, and the processor's backstop sweep re-records it. Rollbacks need no special casing — a rollback is an ordinary apply row settling to Completed, so the same tails cover it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…heck refresh The refresh processor polls the durable request table, so a request recorded right after a tick waits a full poll interval before any sibling PR check moves. OnCheckRefreshRecorded lets the webhook handler register a wake-up that the drive tail invokes after a successful record; the durable row stays the source of truth, so a missed call (processor on another pod, callback unset) only costs poll latency, never the refresh. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…time A gRPC/CLI-only server has no PR check state to refresh and no processor to drain refresh requests, so a drive tail recording there would leave rows pending forever. The webhook handler's registration of the recorded-notifier now doubles as the consumer signal: drive tails record (and wake the consumer) only when it is set, and skip with a debug log otherwise. The check is a nil test, so the drive tail pays nothing for it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…requests The drive tail records the originating change as a provider-scoped change_key string via ChangeKeyForPullRequest, replacing the pull_request integer, and component prose follows the merge gate rename. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
aparajon
force-pushed
the
armand/check-refresh-drive-tail
branch
from
August 5, 2026 15:14
6ba60ea to
56faf88
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: The moment a drive settles an apply to terminal success, every other open PR planning against that target holds check state computed against a schema that no longer exists. If that moment isn't captured durably, the merge gate guardrail has nothing to act on — and a pod crash right after the terminal write would lose the signal forever. Stack 2/7, on top of #867.
What it does:
recordMergeGateIfApplyResolvedruns at all three operator drive tails (recovery, multi-operation drive, pending-stop recovery), placed before pending control requests are completed — the same ordering the terminal summary uses. Only terminal success records; rollbacks are ordinary apply rows settling toCompleted, so they're covered with zero special-casing.OnMergeGateRecordeddoubles as the consumer signal: drive tails record only when it is set — a nil check, so the drive tail pays nothing for it.OnMergeGateRecordedalso serves as the wake-up: the drive tail invokes it after a successful record so a co-located merge gate processor drains immediately instead of waiting out its poll interval. The durable row stays the source of truth: a lost wake-up only costs poll latency, never the re-plan.RecordMergeGateRecordFailure), and left for the processor's backstop sweep to re-record. A sustainedsource="sweep"rate onRecordMergeGateRecordedis the operator signal that drive tails are failing to record.How it moves us toward the northstar: Every schema mutation on a GitHub-connected server — PR-driven or CLI-driven — leaves a durable, at-least-once breadcrumb the moment it lands, and servers with no PR surface stay entirely out of the flow. The processor (stack 3/7, #866) turns those breadcrumbs into re-planned sibling PR checks.
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