Skip to content

follow-ups from the 2026-09-22 drain: six minors left open at merge #2208

Description

@justinhelmer

Findings left open when the 2026-09-22 drain merged their pull requests. Each was raised by a review arm at the merged head, judged a minor, and recorded here rather than spending another round before the release.

From #2195 (record 0075 + the typed provider-failure seam, 1ee9f2b0)

  1. The intake timeout path bypasses the seam. src/core/intake.ts around line 255: AbortSignal.timeout(...) yields an AbortError or TimeoutError, and the branch returns an ordinary silent timeout with no providerFailure, so Slack posts nothing. Model-proxy item 12b requires every intake provider failure to cross the typed seam and render the no-lease sentence. Classify the timeout as transient, preserve structured attempts, and let the existing delivery path post once.
  2. A buffered provider-up row can replay after a local retry wins. src/core/harness/pi/harness.ts around line 2380: a provider-up row arriving while a post-loop local retry is in flight is discarded by clearTurnProviderHold() without advancing mirror.inboxConsumedSeq, so after a restart the durable row can be delivered again and release a later hold with no new provider-up transition. Mark the buffered rows consumed when the local retry wins; regression covers provider-up during an in-flight retry followed by a restart.

From #2205 (decision-record reservations, 60f45b75)

  1. Durable-store transport failures bypass the typed admission refusal. src/index.ts around line 451: WorkerCoordinatorInstanceStore.reserveDecisionRecord() throws on timeouts and non-2xx responses while the callback translates only an { ok: false } result, so a state-Worker outage takes the generic setup-failure path instead of returning decision_record_store_unavailable. Catch failures from the durable reservation call and rethrow DecisionRecordReservationUnavailableError.

From #2206 (terminal pull-request transitions, a8fe55df)

All three are one shape: a transition path that still acts without a fresh, branch-existence-aware read.

  1. The ship-only pre-post guard ignores branch existence. src/core/reviewRound.ts around line 843: fetchPrHead verifies only that the PR is open and reports the pinned sha, so a head branch deleted during the review still lets the verdict post, against agent-ship item 9. Use the branch-existence-aware facts reader.
  2. Rebase outcomes dispatch without a fresh read. src/core/ship/coordinator.ts around line 3252: a conflict result spawns a coding child and a changed result spawns review, while the rebase itself can take long enough for the PR to merge, close or lose its branch. Route both through a fresh pr-check.
  3. A recovered pushed branch skips the transition guard. src/channels/adminCoordinator.ts around line 1812: the route returns an open PR without re-reading state, head or branch existence, so review can dispatch onto a deleted branch. Refresh through fetchPrFacts/pullRequestState and retry on unknown state.

Why one issue

Justin's direction on 2026-09-22 is to land everything open, cut a release with nothing new, then sign off what shipped with receipts, and repeat before starting new work. These six are the debt that decision knowingly took on; they are not lost, and they are the first candidates after the receipts round.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions