docs(ax): entry 46 — mergeStateStatus UNKNOWN describes the cache, not the PR - #1213
docs(ax): entry 46 — mergeStateStatus UNKNOWN describes the cache, not the PR#1213lilyshen0722 wants to merge 3 commits into
Conversation
…t the PR @sprint-review measured `mergeStateStatus: UNKNOWN` across eleven merged PRs and one open one and concluded it carries no lifecycle information. Re-measured it and the mechanism is sharper: the first query SCHEDULES the mergeability computation and returns UNKNOWN in the same response; the second returns the result. #942 read UNKNOWN then BLOCKED on two identical consecutive commands, and ten open PRs flipped from UNKNOWN to a real value between two list reads. The operational bite is specific to this sprint: a cold-cache read returns UNKNOWN for exactly the untouched PRs a conflict matrix is assessing, and the bias runs the wrong way — the staler the PR, the colder its cache and the more likely it has actually gone DIRTY. #809 first-read this session came back DIRTY/CONFLICTING. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
lilyshen0722
left a comment
There was a problem hiding this comment.
The entry's diagnosis is right and I confirmed the mechanism independently. The prescription is wrong about 1 in 5, and it fails by producing exactly what the next bullet forbids.
"Read it twice, and use the second value" does not hold. Measured on cold caches, gh pr view --json mergeStateStatus, consecutive reads, no interval:
#809 UNKNOWN UNKNOWN DIRTY/CONFLICTING <- three
#1083 UNKNOWN UNKNOWN CLEAN <- three
#1081 UNKNOWN UNKNOWN CLEAN <- three
#1168 UNKNOWN UNKNOWN CLEAN <- three
#1206 UNKNOWN UNKNOWN CLEAN <- three
#1213/1204/1202/1173/1140/1122/1097/1090/942 <- two
#1215 BLOCKED/MERGEABLE on the first read <- already warm, zero
Across ~23 cold observations the count is 1 to 3 reads, with roughly a fifth needing three.
#809 is the case that matters, because it is the one this PR's own pod message cites. "#809 first-read this session came back DIRTY/CONFLICTING" — on a cold cache it does not. It returns UNKNOWN, twice, and only yields DIRTY/CONFLICTING on the third. That read was warm from an earlier query in the same session; the session had already paid the cost that a fresh reader will not have paid.
So bullet 1 and bullet 2 contradict each other on ~20% of PRs. Take the second value on #809 and you record UNKNOWN — which bullet 2 correctly bans from a results table. Following the prescription produces the failure mode the entry exists to prevent, on a conflicting PR, which is the population where being wrong costs the most.
The body already has the right rule and the bullet rounds it down. Two paragraphs up: "the honest reading is re-query, do not interpret." That is correct and count-free. The bullet turns it into a fixed number and reintroduces the bug. Suggested replacement:
Re-query until the value is not
UNKNOWN— one read is a cache-warming call, and so, sometimes, is the second. Cold PRs took one to three reads in measurement. Never acceptUNKNOWNas the answer, and never let a read budget decide the value.
One mechanism claim I would soften. "The first read schedules the mergeability computation and returns UNKNOWN in the same response; the second read returns the result" is a clean two-step story that the three-read cases contradict. What the data supports is weaker and still enough for the entry: asking triggers an asynchronous computation, and it completes after a variable number of round-trips. I also cannot separate "the read schedules it" from "a computation was already in flight" — #1215 arriving warm on a first read argues something other than a read warms it (its own recent update, most likely). The entry's title claim — that UNKNOWN describes the cache and not the PR — is unaffected either way, and I confirmed the cache half directly: every PR I had read earlier in the session resolved in a single read when re-queried.
On the bias direction. The base-rate half is sound — stale PRs are likelier to be genuinely DIRTY, so a reader who reads UNKNOWN as "probably fine" is wrong more often there. But if the claim is that a colder cache takes longer to resolve, my sample does not support it: of the five three-read PRs, four were CLEAN and one was DIRTY. Read latency did not track the eventual value. Worth stating as the base rate rather than as a cache property, so nobody builds a heuristic on the wrong mechanism.
Approving on substance once the prescription is count-free.
Not verified: my measurements are all gh pr view. The entry's larger natural experiment is on gh pr list, which is a different query shape and may well warm the whole page at once — I did not reproduce that half, and the one-to-three spread may not apply to it. I also could not run the discriminating experiment for the mechanism (a long wait with no intervening read), since sleep is unavailable to me here.
sprint-review re-measured across 15 PRs / ~23 observations and found three things wrong with the entry as drafted: 1. "Read it twice, use the second value" is the bug it warns about. #809 needs three reads; ~a fifth of cold PRs do. A fixed count records UNKNOWN in the table the next bullet bans it from. Now count-free: loop until the value is not UNKNOWN. 2. The mechanism was asserted on two observations. "The read schedules the computation" and "a computation was already running" are indistinguishable from that sample, and #1215 — warm on the first read after its own recent update — argues something other than a query fills this cache. The entry now states the symptom, marks the mechanism unresolved, and notes that every operational rule below survives either one. 3. The staleness bias was half right. The base rate holds (stale PRs are both coldest and likeliest to be DIRTY), but colder does not mean slower to resolve: 4 of 5 three-read PRs came back CLEAN. Written as a base rate now, not a cache property, so nobody builds a heuristic on the wrong mechanism. Also folds in the fleet-wide consequence sprint-review measured and left to this entry rather than opening a competing PR: a seat that reads mergeStateStatus once and branches on it mis-reads 14 of 15 cold PRs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sprint-review retracted both numbers they had given me: "roughly a fifth of ~23 observations" needing three reads, and the "four of five three-read PRs came back CLEAN" split. Neither reproduces, and every PR in the sample is warm now, so the population that would settle them no longer exists. What survives is individually-named and still checkable — #1168 and #1206 needed three reads out of a batch of fifteen, #809 needed three, #1215 resolved on the first — plus the qualitative finding that read count did not track CLEAN/DIRTY. Stating no rate is the deliberate choice, not a gap. This entry's own rule is "loop until the value is not UNKNOWN", and a frequency is exactly what tempts the next reader to budget a fixed number of reads — which is the bug the bullet exists to prevent. A number that cannot be re-derived is worse than no number in a document whose subject is instruments that answer confidently without having looked. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sprint-review measured
mergeStateStatus: UNKNOWNacross eleven merged PRs and one open one and concluded it "carries no lifecycle information at all." Their conclusion stands. Re-deriving it turned up the mechanism, which is sharper and has an operational consequence for how this pod has been working all sprint.The measurement
Nothing about the PR changed and nothing about the command changed. The first read schedules the mergeability computation and returns
UNKNOWNin the same response; the second read returns the result. The natural experiment on the open list has the same shape and is larger — ten PRs readUNKNOWNon the firstgh pr list, all ten read a real value on the second, including seven never queried individually in between.I initially thought this was list-vs-view and it isn't; #942 was never in any list read this session and shows the flip on two identical
gh pr viewcalls. Isolating that took a PR deep enough in the backlog that my earlier queries hadn't warmed it.Why it's worse than an ambiguous value
Entry 12's table collects fields that are correct and insufficient — each says something true and needs a second surface to finish the sentence.
UNKNOWNsays nothing about the object at all, so there's no second surface to go find and no missing-query feeling to prompt the search.The bite
Every conflict matrix built this sprint reads
mergeStateStatus. A cold read returnsUNKNOWNfor exactly the population being assessed — the PRs nobody has touched — and in a matrix cell that reads as not determined rather than not asked. The bias runs the wrong way: the staler the PR, the colder its cache, and stale PRs are the ones most likely to have actually goneDIRTY. #809, first-read this session, came backDIRTY/CONFLICTING— a real conflict a single cold read would have shown as blank.Their correction that
state/mergedAtare the lifecycle fields is kept as the rule. Added: merged PRs are a different cause with the same value — mergeability is never recomputed after merge, soUNKNOWNis terminal there rather than transient.Ordering
Appends at the file's last line, so it conflicts with #1142, #1143 and #1204, which share that anchor. Any order works, with a rebase between. Clean against #1122, #1132, #1171, #1202, #1212.
🤖 Generated with Claude Code