Skip to content

[finding] merge-queue-triage counts speculative-stack inheritance as "distinct pull requests" — a deterministic single-owner failure manufactures victims in proportion to queue depth #12933

Description

@claude

Filed unassigned by the os-dev seat that closed #12859 (the queue-flake anchor for src/plugin-artifact-forward-conversion.test.ts). Observation, not a graded defect — deliberately no pm:queue, and no fix proposed here.

What was measured

#12859 was filed by the merge-queue-triage workflow (#4859, aggregation #10128) because one test file ejected 3 distinct pull requests inside 24 hours. Closing it required establishing that only one of the three had any relationship to the failure at all.

The queue branch names carry GitHub's speculative stack — each branch's suffix is the base it was built on:

queue build head_branch stacked on
33140380738 (#12843) gh-readonly-queue/main/pr-12843-b489d3c725… b489d3c72 = main tip
33141029941 (#12851) gh-readonly-queue/main/pr-12851-e875b2f185… e875b2f18 = #12843's queue head
33141213420 (#12855) gh-readonly-queue/main/pr-12855-e391b5fb14… e391b5fb14 = #12851's queue head

So all three builds contained #12843's tree. Confirmed by contents-at-ref, positive control scripts/check-adr-anchors.mjs returning 200 on every row:

ref the failing test file control
b489d3c72main before the queue 404 200
e875b2f18 / e391b5fb1 / 1a24e9778 — the three queue heads 200 200

#12851's whole diff was one comment block in one script; #12855's was 3 files, none under packages/. Both re-queued unchanged and merged at 04:27:04Z. Only #12843 owned the failing test, and its failure was a deterministic assertion (expect.unreachable firing), fixed on that PR before it landed.

The generalisation

Under speculative stacking, every PR queued behind a broken one inherits the break. So for a deterministic failure the "distinct pull requests" count measures queue depth, not flakiness — and it keeps climbing until the owner lands a fix.

The anchor's trigger is that distinct-PR count and its title word is "flake", so the signal is systematically loudest in precisely the case where it carries the least information. A one-owner deterministic break in a busy hour will always look like a cross-PR flake.

⚠️ To be fair to the workflow: its prose is careful. The body it writes says "This issue is a NAME, not a diagnosis" and lists the four candidate causes without choosing between them. The finding is not that the workflow overclaims — it is that the count itself is inflated in a knowable, mechanically detectable way, and every reader has to re-derive that by hand. Two seats spent real time on #12859 doing exactly that.

A cheap discriminator, if anyone wants one

The workflow already holds each victim's queue branch name, and the suffix names its base commit. A PR whose queue base equals another victim's queue head is, by construction, downstream of it in the same stack — no new API calls needed to notice. Reporting "N in one stack" rather than "N distinct pull requests", or counting only PRs whose own diff can reach the failing test file, would separate co-occurrence from independent hits.

Why it is filed rather than fixed

Out of scope for the card that surfaced it, and the tooling is domain:devx while #12859 is domain:engine. Recorded so the observation does not disappear when #12859 closes.

Related: #12859 (the anchor, closed with this reading) · #4859 and #10128 (the workflow itself, both closed) · #12843 / #12851 / #12855 (the three victims).


Generated by Claude Code


Generated by Claude Code

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions