From 56f49d11ea5e0fcff94826960f9a099e394fedc1 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Tue, 29 Sep 2026 09:37:58 -0700 Subject: [PATCH 1/9] docs(checklist): rule 32's fidelity test is patch-id, and rule 44's fork point is measured (TASK-190) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four corrections carried out of the #2000 landing, each a defect in text now on main rather than in an open branch. 1. RULE 44, a false statement of fact. The earned clause called `58298156` "a sibling of `1a811d84`". Measured on the real commits: `git merge-base 58298156 1a811d84` = `bbab5c31`, and `git merge-base 7f171637 1a811d84` = the same commit — so `7f171637` is no ancestor of `1a811d84` either, and the two heads are separate takes on the same TASK-180 change. The sentence now says "diverge at `bbab5c31`". 2. RULE 32, a wrong instrument. Its headline and its proof sentence compared `rev-parse ^{tree}` against `^{tree}`. Both failures were measured: it is BASE-RELATIVE (any base move under the PR makes the trees differ necessarily while the landing is faithful — #1988/#1989/#1992 all landed faithfully with differing trees) and SQUASH-SHAPED ONLY (`a20ea9b3`, #1994's landing, is a two-parent merge-queue commit whose `^{tree}` is main's tree, so the comparison cannot be run there at all). The test is now patch-id of `^..` against `..`, which is what held for all three of those landings (`81ecc062`, `b9feb00c`, `efcec768`) and is the instrument the AX audit reached independently for a refresh carry (entry 65). 3. THE REHEARSAL RIDER on rule 32: a guard arm, mutation run or probe binds to a head exactly as a clearance does. On #1994's hold, three arms were quoted after a third head move, and ARM 1 had measured a file that no longer existed at the then-current head. 4. THE RENUMBER CLAUSE in rule 43: its own squash subject announces "rule 42 … and rule 43" while the file it landed carries those as 43 and 44, because #2008 merged its own rule 42 between the gate and the press. A rule number is a queue position; a reader citing the log gets both wrong. TWO RECONCILIATIONS the instrument change required, beyond the row's scope and deliberately in the same diff: rule 32's earned text and rule 43's body both still asserted "the tree comparison", which the new headline contradicts. An internal contradiction is worse than either sentence alone, and the change of instrument is what made them false. Guard: `node scripts/verify-numbered-rules.js` -> 44 rules, numbers 1..44 ascending with no gap, 28 citations all resolve. Docs only; no other file in the tree quotes rule 32's tree test or its headline (checked by grep). --- docs/development/review-checklist.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/development/review-checklist.md b/docs/development/review-checklist.md index 170817cd6..c744ee866 100644 --- a/docs/development/review-checklist.md +++ b/docs/development/review-checklist.md @@ -102,7 +102,7 @@ And then note where the fix landed. Someone hit the audience gap, felt it, and b ## Merge mechanics -32. **Verify a merge at the consumer: for a squash merge, the merge commit's tree must equal the carried head's tree.** A merge SHA and a green tick prove the workflow ran; they do not prove that what landed is what was reviewed — carries, rebases and stale-base reverts move code between review and merge, and the merge commit's message will not say so. Under this repo's squash convention the proof is one command per side: `git rev-parse ^{tree}` against `git rev-parse ^{tree}`, plus the parent and the author/trailer check. Fetch the head yourself (`git fetch origin refs/pull//head`) — a reviewer's claim about remote state is as checkable as a code claim — and diff from the natural merge base, because `git diff main...head` against a stale local `main` is a fiction (a checkout whose local `main` trails `origin/main` by double digits is the ordinary state here, and every PR is cut from the fetched `origin/main`). Riders: a **carry** is a *per-file* claim (`git patch-id --stable`, per file), not a whole-PR one, and it is needed only where non-doc code moved between bases — a docs-only addition on top of a cleared head is a re-stamp, so state old→new head and let the reviewer stamp what actually lands, while a **code**-touching move cannot re-attach — a stamp names the head it was taken against, so that clearance is spent, and the author states old→new head and asks for the re-derivation instead of letting a press ride the old stamp; a **test**-only move counts as code-touching rather than a docs re-stamp, because the arms are much of what a clearance is about, and it re-gates in practice (#1986 `5c068c37`→`0cfd8c0f`, two commits inside the guard's own test file); and know the required-check set before calling anything green or blocked, because every check being green is not the same as the required check passing, and a required check that has not yet reported renders as `BLOCKED` — the ordinary in-flight state, not a verdict. *(Earned: every closure since — #1755 verified as `e938afc8`, tree `b86b05e4` equal to the carried head `ad3aa8d7`'s, parent `2d0ee979`, no foreign trailer; and the precedent that motivates the rule rather than any one incident: #568's fix regressed twice through a stale-base revert, which is exactly the class the tree comparison closes — the merge looked clean, the tick was green, and the fix was gone. **The code-touching rider earned itself in TASK-177's #1990**: a clearance stamped at `83fa2fcd` arrived in the same batch as two other findings — Wren's paging defect and a mutation label **the author's own ledger** caught crediting an arm that no longer witnessed it — plus the `at`/`ms` divergence **Vera measured in that same clearance** and prescribed `ms: mark` for. The author had already moved the head to `000fdbbd` with all three folded, which is why the head had to move at all. The clearance was honest and correct about the head it named, which is precisely why it briefed nobody about the head on the branch; the author asked for the re-derivation and listed what the new head carried, and that list is the cheap half of the obligation.)* +32. **Verify a merge at the consumer: the change that landed must be the change that was gated — `git patch-id --stable` of `^..` equal to the same of `..`.** A merge SHA and a green tick prove the workflow ran; they do not prove that what landed is what was reviewed — carries, rebases and stale-base reverts move code between review and merge, and the merge commit's message will not say so. Under this repo's squash convention the proof is one command per side: `git patch-id --stable` over the merge's own range against the same over the gated range, plus the parent and the author/trailer check. **Tree equality is the wrong instrument, in two measured ways.** It is **base-relative**: once main moves under a PR the trees differ *necessarily* while the landing is faithful, so `git rev-parse ^{tree}` against `git rev-parse ^{tree}` fails every faithful landing whose base moved — all three of #1988/#1989/#1992 landed faithfully with differing trees. And it is **squash-shaped only**: `a20ea9b3`, #1994's landing, is a two-parent merge-queue commit whose `^{tree}` is main's tree rather than the head's, so the comparison cannot be run there at all. Patch-id compares the *change* rather than the tree, which is what the claim is about; it held for all three of those landings (`81ecc062`, `b9feb00c`, `efcec768`), and it is the same instrument the AX audit reached independently for a refresh carry (entry 65). Fetch the head yourself (`git fetch origin refs/pull//head`) — a reviewer's claim about remote state is as checkable as a code claim — and diff from the natural merge base, because `git diff main...head` against a stale local `main` is a fiction (a checkout whose local `main` trails `origin/main` by double digits is the ordinary state here, and every PR is cut from the fetched `origin/main`). Riders: a **carry** is a *per-file* claim (`git patch-id --stable`, per file), not a whole-PR one, and it is needed only where non-doc code moved between bases — a docs-only addition on top of a cleared head is a re-stamp, so state old→new head and let the reviewer stamp what actually lands, while a **code**-touching move cannot re-attach — a stamp names the head it was taken against, so that clearance is spent, and the author states old→new head and asks for the re-derivation instead of letting a press ride the old stamp; a **test**-only move counts as code-touching rather than a docs re-stamp, because the arms are much of what a clearance is about, and it re-gates in practice (#1986 `5c068c37`→`0cfd8c0f`, two commits inside the guard's own test file); a **rehearsal** binds to a head exactly as a clearance does, one layer out — a guard arm, a mutation run or a probe quoted after the head has moved is a measurement of a file that may no longer exist there, with real numbers attached to a subject that has changed, so re-run the arm at the head you are reporting or state the head it ran at (on #1994's hold, three guard arms were quoted after a third head move, and ARM 1 had measured a file that no longer existed at the then-current head); and know the required-check set before calling anything green or blocked, because every check being green is not the same as the required check passing, and a required check that has not yet reported renders as `BLOCKED` — the ordinary in-flight state, not a verdict. *(Earned: every closure since — #1755 verified as `e938afc8`, tree `b86b05e4` equal to the carried head `ad3aa8d7`'s, parent `2d0ee979`, no foreign trailer — that being the tree check patch-id replaces, whose equality a base move under the PR removes; and the precedent that motivates the rule rather than any one incident: #568's fix regressed twice through a stale-base revert, which is exactly the class the change comparison closes — the merge looked clean, the tick was green, and the fix was gone. **The code-touching rider earned itself in TASK-177's #1990**: a clearance stamped at `83fa2fcd` arrived in the same batch as two other findings — Wren's paging defect and a mutation label **the author's own ledger** caught crediting an arm that no longer witnessed it — plus the `at`/`ms` divergence **Vera measured in that same clearance** and prescribed `ms: mark` for. The author had already moved the head to `000fdbbd` with all three folded, which is why the head had to move at all. The clearance was honest and correct about the head it named, which is precisely why it briefed nobody about the head on the branch; the author asked for the re-derivation and listed what the new head carried, and that list is the cheap half of the obligation.)* ## Enumerating a duplicated value @@ -154,8 +154,8 @@ And then note where the fix landed. Someone hit the audience gap, felt it, and b ## The merge queue -43. **A queued PR refuses every push, and that refusal is what keeps the merged head equal to the queued head.** Once a pull request is in the merge queue, GitHub rejects any push to its branch — `GH006: Protected branch update failed for refs/heads/ … branches that are queued for merging cannot be updated. To modify this branch, dequeue the associated pull request.` Read it as a mechanism rather than an obstacle: the queue merges the head it saw, so a delta arriving after queue entry cannot silently ride a stale clearance into main, and rule 32's tree comparison is then guaranteed rather than lucky. It is not a clearance in itself, though — that the *queued* head is the *gated* head is still the press's job to check, which is rule 44's question. Land a late delta as a **follow-up PR** based on the merged main, showing per-file fidelity is empty (`git rebase --onto origin/main `, then `git patch-id --stable` per file); the costlier alternative is to dequeue, apply, re-gate and re-queue, which spends every stamp bound to the head. The follow-up is **ungated** until it is gated at its own head: cite the pre-rebase commit as provenance, by **full** sha, since a short sha will not fetch and a provenance citation that gets read as a clearance is the defect rule 44 exists for. *(Earned: TASK-180's #1984 — ux-lead asked for the `%` fold at 04:48:45Z and the PR was queued at 04:50:20Z, 95 seconds later, so the fold could not land on that head at all and became #1988: one catalog line, a rebase and two gates. The queue had already merged the gated head faithfully — squash `f381b5aa` against `7f171637`, the three TASK-180 files byte-identical — so the pressed artifact was the reviewed artifact, which is the outcome the refusal buys. Before this entry existed the operator-facing half was documented nowhere else, and the count is **per string, not per union**: `merge queue` appeared in exactly one tracked file, `.github/workflows/tests.yml:13`, whose surrounding lines are about the `merge_group` trigger rather than the push refusal, while `GH006` and `queued for merging` appeared in **no** tracked file at all — `git grep -l -F` for the three strings over the whole tree on main returns 0, 0 and 1. Read those as the state of main *before* this rule landed, because the rule quotes all three: at this head it is the second file for every one of them, and a grep for `GH006` alone returning nothing is that pre-landing state and not a rule that has gone stale.)* +43. **A queued PR refuses every push, and that refusal is what keeps the merged head equal to the queued head.** Once a pull request is in the merge queue, GitHub rejects any push to its branch — `GH006: Protected branch update failed for refs/heads/ … branches that are queued for merging cannot be updated. To modify this branch, dequeue the associated pull request.` Read it as a mechanism rather than an obstacle: the queue merges the head it saw, so a delta arriving after queue entry cannot silently ride a stale clearance into main, and rule 32's change comparison is then guaranteed rather than lucky. It is not a clearance in itself, though — that the *queued* head is the *gated* head is still the press's job to check, which is rule 44's question. Land a late delta as a **follow-up PR** based on the merged main, showing per-file fidelity is empty (`git rebase --onto origin/main `, then `git patch-id --stable` per file); the costlier alternative is to dequeue, apply, re-gate and re-queue, which spends every stamp bound to the head. The follow-up is **ungated** until it is gated at its own head: cite the pre-rebase commit as provenance, by **full** sha, since a short sha will not fetch and a provenance citation that gets read as a clearance is the defect rule 44 exists for. *(Earned: TASK-180's #1984 — ux-lead asked for the `%` fold at 04:48:45Z and the PR was queued at 04:50:20Z, 95 seconds later, so the fold could not land on that head at all and became #1988: one catalog line, a rebase and two gates. The queue had already merged the gated head faithfully — squash `f381b5aa` against `7f171637`, the three TASK-180 files byte-identical — so the pressed artifact was the reviewed artifact, which is the outcome the refusal buys. Before this entry existed the operator-facing half was documented nowhere else, and the count is **per string, not per union**: `merge queue` appeared in exactly one tracked file, `.github/workflows/tests.yml:13`, whose surrounding lines are about the `merge_group` trigger rather than the push refusal, while `GH006` and `queued for merging` appeared in **no** tracked file at all — `git grep -l -F` for the three strings over the whole tree on main returns 0, 0 and 1. Read those as the state of main *before* this rule landed, because the rule quotes all three: at this head it is the second file for every one of them, and a grep for `GH006` alone returning nothing is that pre-landing state and not a rule that has gone stale. And the *number* is a queue position, not a property of the text: #2000's squash subject announces "rule 42 (a queued PR refuses every push) and rule 43 (a clearance …)" while the file it landed carries those two as **43** and **44**, because #2008 merged its own rule 42 between the gate and the press — so a reader citing the log gets both numbers wrong for two rules whose entire subject is that a record has to name the thing it claims. Read the number at the head you are reading; a sibling PR can renumber it between the gate and the land.)* ## What a clearance can bind -44. **A clearance has to exist as a PASS recorded against the head being pressed, and prose is not a record.** The question is existence, not identity: not whether the gated content is what merged (that is rule 32), but whether *any* clearance was ever taken at the head the press will read. Use GitHub's own record rather than anyone's prose — every review in `GET /pulls//reviews` carries `commit_id`, the head it was submitted against, so selecting reviews whose `commit_id` is the pressed head finds the reviews submitted against it: candidates, not clearances. **Existence is necessary and not sufficient, because a review at the head can be a refusal.** `state` carries no verdict here: measured across #1988, #1989 and #2000, every review on all three is `COMMENTED` — **18 of 18 when this was written, and that number only grows as seats post more, so re-run the count rather than quoting it** — not one `APPROVED` or `CHANGES_REQUESTED` across any of them, so the verdict is the body's first line and nothing else. The check is therefore **per required gate: a review whose `commit_id` is the pressed head and whose first line names that same head and declares that gate's PASS.** The head name is not decoration. `commit_id` records the head **at submission**, so a gate taken at X and posted after a push to Y lands at Y and reads fresh at a head nobody read — and a check that stops at `commit_id` will accept it. A first line naming an *older* head is a rule 32 carry question, not an existence pass: the two heads may share a tree, in which case the artifact really was gated (32's test) and no existence check can know it; or they may **differ**, in which case the clearance names content nobody gated. 44 answers whether a record claims *this* head; 32 answers whether an older claim still carries to it. Two counterexamples, one per half. #2000 @ `d1d56e4c` is what a bare existence test clears: its only review is a `DOCS-GATE: CHANGES` at that head. #1981 is what a `commit_id`-only test clears: pressed at `3d6e1763`, where its code review carries that `commit_id` and reads `DELTA RE-GATE: PASS @ a4566e29`. A head whose reviews are all refusals, or all corrections — "Correction to my gate above" declares no verdict — is ungated, which is the honest answer rather than a pass by default. `submitted_at` orders reviews but does not bind them to a head, and it cannot be used to select one either: every seat here posts under one GitHub identity, so `.[-1]` returns whichever seat reviewed last. Two checks that look right and are not. `git merge-base --is-ancestor ` passes a clearance a later head move has already spent — `b8048c72` is an ancestor of `177ba436` — which is 32's class of defect, not this one. And a sha missing from your clone says nothing about the remote: a commit can be there with no ref pointing at it, so the remote has it, no ordinary fetch brings it in, and `refs/pull//head` keeps a squashed-away head fetchable — an absence read in one clone is as clone-local as a presence read. `commit_id` cannot tell a carry from a re-derivation, so the body still has to be read for that; it answers only whether a review was submitted against that head at all. Its own entry rather than a rider on 32, and the argument is 41's test applied to 32: every guard 32 sends you to check passes here — nothing had merged, no head had moved, the required set was green — and the defect survives all of them, because 32 presupposes a clearance and this asks whether one exists. *(Earned: TASK-186's #1988. The row recorded "CODE PASS @ `58298156`" from 06:54Z on 2026-09-28 and carried it for **29.4h**; the board title carried "… (UX PASS @ `1a811d84` + CODE PASS)" for **8.7h** from 03:34Z the next morning. No clearance was ever taken at that commit: it is a **child** of `7f171637` — a sibling of `1a811d84`, not an ancestor of it, and `GET /pulls/1988/reviews` held four reviews at that point — every one of them `commit_id=1a811d84` — of which only the first existed before 12:17Z on 2026-09-29. The commit itself was confirmable — `gh api commits/` resolved it and a full-sha fetch retrieved it — but no advertised ref pointed at it — `git ls-remote` listed 2,579 of them when this was measured and not one was this sha, a number that only grows, so re-run it rather than quoting it — and `git fetch origin ` fails, so no ordinary fetch brought it into any other clone. So the commit could be confirmed and the gate could not, because there was no gate; a rule written about unresolvable heads would have mis-stated this incident. The title's *shape* did as much damage as its content — binding the sha to the UX pass and leaving the code pass bare is what let a later reader collapse it into "CODE PASS @ `1a811d84`", a head that was real and resolvable and so looked verifiable. And the `commit_id` half has its own incident: #1981 was pressed at `3d6e1763`, and the code review bearing that `commit_id` reads `DELTA RE-GATE: PASS @ a4566e29` — the stack had been re-authored from `a4566e29` to `3d6e1763` between the gate and its posting, and the two commits share tree `0e3b2d01cf`, so the artifact was gated and the record could not say so. Same PR, and the hazard's harsher half: the code review submitted at 21:26:47Z carries `commit_id=245dbaf4` while its first line names `5e0e7193`, and those trees **differ** — three files, three lines, the "pod, not room" string among them — so it attached a clearance to content nobody had gated; superseded seven minutes later and never pressed, which is why the incident above is the one that reached a press, and why a check that stops at `commit_id` cannot be trusted at all.)* +44. **A clearance has to exist as a PASS recorded against the head being pressed, and prose is not a record.** The question is existence, not identity: not whether the gated content is what merged (that is rule 32), but whether *any* clearance was ever taken at the head the press will read. Use GitHub's own record rather than anyone's prose — every review in `GET /pulls//reviews` carries `commit_id`, the head it was submitted against, so selecting reviews whose `commit_id` is the pressed head finds the reviews submitted against it: candidates, not clearances. **Existence is necessary and not sufficient, because a review at the head can be a refusal.** `state` carries no verdict here: measured across #1988, #1989 and #2000, every review on all three is `COMMENTED` — **18 of 18 when this was written, and that number only grows as seats post more, so re-run the count rather than quoting it** — not one `APPROVED` or `CHANGES_REQUESTED` across any of them, so the verdict is the body's first line and nothing else. The check is therefore **per required gate: a review whose `commit_id` is the pressed head and whose first line names that same head and declares that gate's PASS.** The head name is not decoration. `commit_id` records the head **at submission**, so a gate taken at X and posted after a push to Y lands at Y and reads fresh at a head nobody read — and a check that stops at `commit_id` will accept it. A first line naming an *older* head is a rule 32 carry question, not an existence pass: the two heads may share a tree, in which case the artifact really was gated (32's test) and no existence check can know it; or they may **differ**, in which case the clearance names content nobody gated. 44 answers whether a record claims *this* head; 32 answers whether an older claim still carries to it. Two counterexamples, one per half. #2000 @ `d1d56e4c` is what a bare existence test clears: its only review is a `DOCS-GATE: CHANGES` at that head. #1981 is what a `commit_id`-only test clears: pressed at `3d6e1763`, where its code review carries that `commit_id` and reads `DELTA RE-GATE: PASS @ a4566e29`. A head whose reviews are all refusals, or all corrections — "Correction to my gate above" declares no verdict — is ungated, which is the honest answer rather than a pass by default. `submitted_at` orders reviews but does not bind them to a head, and it cannot be used to select one either: every seat here posts under one GitHub identity, so `.[-1]` returns whichever seat reviewed last. Two checks that look right and are not. `git merge-base --is-ancestor ` passes a clearance a later head move has already spent — `b8048c72` is an ancestor of `177ba436` — which is 32's class of defect, not this one. And a sha missing from your clone says nothing about the remote: a commit can be there with no ref pointing at it, so the remote has it, no ordinary fetch brings it in, and `refs/pull//head` keeps a squashed-away head fetchable — an absence read in one clone is as clone-local as a presence read. `commit_id` cannot tell a carry from a re-derivation, so the body still has to be read for that; it answers only whether a review was submitted against that head at all. Its own entry rather than a rider on 32, and the argument is 41's test applied to 32: every guard 32 sends you to check passes here — nothing had merged, no head had moved, the required set was green — and the defect survives all of them, because 32 presupposes a clearance and this asks whether one exists. *(Earned: TASK-186's #1988. The row recorded "CODE PASS @ `58298156`" from 06:54Z on 2026-09-28 and carried it for **29.4h**; the board title carried "… (UX PASS @ `1a811d84` + CODE PASS)" for **8.7h** from 03:34Z the next morning. No clearance was ever taken at that commit: it is a **child** of `7f171637`, which is **no ancestor of `1a811d84`** — the two **diverge at `bbab5c31`** (`git merge-base 58298156 1a811d84` is that commit, and `merge-base 7f171637 1a811d84` is the same one), so they are separate takes on the same TASK-180 change rather than siblings, and `GET /pulls/1988/reviews` held four reviews at that point — every one of them `commit_id=1a811d84` — of which only the first existed before 12:17Z on 2026-09-29. The commit itself was confirmable — `gh api commits/` resolved it and a full-sha fetch retrieved it — but no advertised ref pointed at it — `git ls-remote` listed 2,579 of them when this was measured and not one was this sha, a number that only grows, so re-run it rather than quoting it — and `git fetch origin ` fails, so no ordinary fetch brought it into any other clone. So the commit could be confirmed and the gate could not, because there was no gate; a rule written about unresolvable heads would have mis-stated this incident. The title's *shape* did as much damage as its content — binding the sha to the UX pass and leaving the code pass bare is what let a later reader collapse it into "CODE PASS @ `1a811d84`", a head that was real and resolvable and so looked verifiable. And the `commit_id` half has its own incident: #1981 was pressed at `3d6e1763`, and the code review bearing that `commit_id` reads `DELTA RE-GATE: PASS @ a4566e29` — the stack had been re-authored from `a4566e29` to `3d6e1763` between the gate and its posting, and the two commits share tree `0e3b2d01cf`, so the artifact was gated and the record could not say so. Same PR, and the hazard's harsher half: the code review submitted at 21:26:47Z carries `commit_id=245dbaf4` while its first line names `5e0e7193`, and those trees **differ** — three files, three lines, the "pod, not room" string among them — so it attached a clearance to content nobody had gated; superseded seven minutes later and never pressed, which is why the incident above is the one that reached a press, and why a check that stops at `commit_id` cannot be trusted at all.)* From db073d36519a8bbba59e81a1fa7026f0b2e5fd17 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Tue, 29 Sep 2026 09:41:56 -0700 Subject: [PATCH 2/9] docs(checklist): correct rule 32's test in the body, not in its lead (TASK-190) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The guard caught this, and it was right to. `node scripts/verify-numbered-rules.js` without `--previous` is the weaker check — CI runs it with `--previous
`, and that mode pins every rule's LEAD sentence as its name: a rewritten lead is byte-indistinguishable from a foreign rule claiming the same number, so the job failed with rule 32 on main is "Verify a merge at the consumer: for a squash merge, the merg…" and this version's rule 32 is "Verify a merge at the consumer: the change that landed must …" (line 105) — one number, two rules. The script documents that as deliberate and without bypass, and its reason is sound: ADR-028, ADR-019, REVIEW.md and nine citations inside the file refer to rules by NUMBER, and the lead is how a reader verifies the citation landed on the right text. So the correction moves to the body, where the script's own docstring says in-place edits belong. Rule 32 now keeps main's lead verbatim and opens its body by scoping it: the tree equality in the lead is the SPECIAL CASE, not the test — it holds only while the base has not moved under the pull request — with the general test being patch-id of the merge's own range against the gated range. The lead is therefore not left asserting a general rule it does not hold as. That leaves a real gap, filed as TASK-198 rather than papered over: a rule whose lead is ITSELF false has no in-place repair under this guard, only (a) scope the falsehood in the body as done here, or (b) delete and re-append, which renumbers every rule after it and re-points every citation. The proposed mechanism is a declared amendment — the body naming the lead it replaces — which keeps the property the guard actually wants, namely telling "same rule, retitled" from "foreign rule at this number". Everything else from the previous head stands: rule 44's fork point measured as bbab5c31, the rehearsal rider, the renumber clause, and the two sentences that had to stop saying "the tree comparison". Guard, both modes: 44 rules, numbers 1..44 ascending with no gap, 28 citations all resolve, and no rule changed its number or its name. --- docs/development/review-checklist.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/development/review-checklist.md b/docs/development/review-checklist.md index c744ee866..68ae50661 100644 --- a/docs/development/review-checklist.md +++ b/docs/development/review-checklist.md @@ -102,7 +102,7 @@ And then note where the fix landed. Someone hit the audience gap, felt it, and b ## Merge mechanics -32. **Verify a merge at the consumer: the change that landed must be the change that was gated — `git patch-id --stable` of `^..` equal to the same of `..`.** A merge SHA and a green tick prove the workflow ran; they do not prove that what landed is what was reviewed — carries, rebases and stale-base reverts move code between review and merge, and the merge commit's message will not say so. Under this repo's squash convention the proof is one command per side: `git patch-id --stable` over the merge's own range against the same over the gated range, plus the parent and the author/trailer check. **Tree equality is the wrong instrument, in two measured ways.** It is **base-relative**: once main moves under a PR the trees differ *necessarily* while the landing is faithful, so `git rev-parse ^{tree}` against `git rev-parse ^{tree}` fails every faithful landing whose base moved — all three of #1988/#1989/#1992 landed faithfully with differing trees. And it is **squash-shaped only**: `a20ea9b3`, #1994's landing, is a two-parent merge-queue commit whose `^{tree}` is main's tree rather than the head's, so the comparison cannot be run there at all. Patch-id compares the *change* rather than the tree, which is what the claim is about; it held for all three of those landings (`81ecc062`, `b9feb00c`, `efcec768`), and it is the same instrument the AX audit reached independently for a refresh carry (entry 65). Fetch the head yourself (`git fetch origin refs/pull//head`) — a reviewer's claim about remote state is as checkable as a code claim — and diff from the natural merge base, because `git diff main...head` against a stale local `main` is a fiction (a checkout whose local `main` trails `origin/main` by double digits is the ordinary state here, and every PR is cut from the fetched `origin/main`). Riders: a **carry** is a *per-file* claim (`git patch-id --stable`, per file), not a whole-PR one, and it is needed only where non-doc code moved between bases — a docs-only addition on top of a cleared head is a re-stamp, so state old→new head and let the reviewer stamp what actually lands, while a **code**-touching move cannot re-attach — a stamp names the head it was taken against, so that clearance is spent, and the author states old→new head and asks for the re-derivation instead of letting a press ride the old stamp; a **test**-only move counts as code-touching rather than a docs re-stamp, because the arms are much of what a clearance is about, and it re-gates in practice (#1986 `5c068c37`→`0cfd8c0f`, two commits inside the guard's own test file); a **rehearsal** binds to a head exactly as a clearance does, one layer out — a guard arm, a mutation run or a probe quoted after the head has moved is a measurement of a file that may no longer exist there, with real numbers attached to a subject that has changed, so re-run the arm at the head you are reporting or state the head it ran at (on #1994's hold, three guard arms were quoted after a third head move, and ARM 1 had measured a file that no longer existed at the then-current head); and know the required-check set before calling anything green or blocked, because every check being green is not the same as the required check passing, and a required check that has not yet reported renders as `BLOCKED` — the ordinary in-flight state, not a verdict. *(Earned: every closure since — #1755 verified as `e938afc8`, tree `b86b05e4` equal to the carried head `ad3aa8d7`'s, parent `2d0ee979`, no foreign trailer — that being the tree check patch-id replaces, whose equality a base move under the PR removes; and the precedent that motivates the rule rather than any one incident: #568's fix regressed twice through a stale-base revert, which is exactly the class the change comparison closes — the merge looked clean, the tick was green, and the fix was gone. **The code-touching rider earned itself in TASK-177's #1990**: a clearance stamped at `83fa2fcd` arrived in the same batch as two other findings — Wren's paging defect and a mutation label **the author's own ledger** caught crediting an arm that no longer witnessed it — plus the `at`/`ms` divergence **Vera measured in that same clearance** and prescribed `ms: mark` for. The author had already moved the head to `000fdbbd` with all three folded, which is why the head had to move at all. The clearance was honest and correct about the head it named, which is precisely why it briefed nobody about the head on the branch; the author asked for the re-derivation and listed what the new head carried, and that list is the cheap half of the obligation.)* +32. **Verify a merge at the consumer: for a squash merge, the merge commit's tree must equal the carried head's tree.** That equality is the **special case, not the test** — it holds only while the base has not moved under the pull request — and the lead above is kept verbatim because `scripts/verify-numbered-rules.js --previous` pins a rule's lead sentence: a rewritten lead is indistinguishable from a foreign rule claiming that number, so a correction to a rule whose *lead* is itself wrong has no in-place mechanism today (filed as TASK-198, with the CI error quoted). A merge SHA and a green tick prove the workflow ran; they do not prove that what landed is what was reviewed — carries, rebases and stale-base reverts move code between review and merge, and the merge commit's message will not say so. Under this repo's squash convention the proof is one command per side: `git patch-id --stable` over the merge's own range against the same over the gated range, plus the parent and the author/trailer check. **Tree equality is the wrong instrument, in two measured ways.** It is **base-relative**: once main moves under a PR the trees differ *necessarily* while the landing is faithful, so `git rev-parse ^{tree}` against `git rev-parse ^{tree}` fails every faithful landing whose base moved — all three of #1988/#1989/#1992 landed faithfully with differing trees. And it is **squash-shaped only**: `a20ea9b3`, #1994's landing, is a two-parent merge-queue commit whose `^{tree}` is main's tree rather than the head's, so the comparison cannot be run there at all. Patch-id compares the *change* rather than the tree, which is what the claim is about; it held for all three of those landings (`81ecc062`, `b9feb00c`, `efcec768`), and it is the same instrument the AX audit reached independently for a refresh carry (entry 65). Fetch the head yourself (`git fetch origin refs/pull//head`) — a reviewer's claim about remote state is as checkable as a code claim — and diff from the natural merge base, because `git diff main...head` against a stale local `main` is a fiction (a checkout whose local `main` trails `origin/main` by double digits is the ordinary state here, and every PR is cut from the fetched `origin/main`). Riders: a **carry** is a *per-file* claim (`git patch-id --stable`, per file), not a whole-PR one, and it is needed only where non-doc code moved between bases — a docs-only addition on top of a cleared head is a re-stamp, so state old→new head and let the reviewer stamp what actually lands, while a **code**-touching move cannot re-attach — a stamp names the head it was taken against, so that clearance is spent, and the author states old→new head and asks for the re-derivation instead of letting a press ride the old stamp; a **test**-only move counts as code-touching rather than a docs re-stamp, because the arms are much of what a clearance is about, and it re-gates in practice (#1986 `5c068c37`→`0cfd8c0f`, two commits inside the guard's own test file); a **rehearsal** binds to a head exactly as a clearance does, one layer out — a guard arm, a mutation run or a probe quoted after the head has moved is a measurement of a file that may no longer exist there, with real numbers attached to a subject that has changed, so re-run the arm at the head you are reporting or state the head it ran at (on #1994's hold, three guard arms were quoted after a third head move, and ARM 1 had measured a file that no longer existed at the then-current head); and know the required-check set before calling anything green or blocked, because every check being green is not the same as the required check passing, and a required check that has not yet reported renders as `BLOCKED` — the ordinary in-flight state, not a verdict. *(Earned: every closure since — #1755 verified as `e938afc8`, tree `b86b05e4` equal to the carried head `ad3aa8d7`'s, parent `2d0ee979`, no foreign trailer — that being the tree check patch-id replaces, whose equality a base move under the PR removes; and the precedent that motivates the rule rather than any one incident: #568's fix regressed twice through a stale-base revert, which is exactly the class the change comparison closes — the merge looked clean, the tick was green, and the fix was gone. **The code-touching rider earned itself in TASK-177's #1990**: a clearance stamped at `83fa2fcd` arrived in the same batch as two other findings — Wren's paging defect and a mutation label **the author's own ledger** caught crediting an arm that no longer witnessed it — plus the `at`/`ms` divergence **Vera measured in that same clearance** and prescribed `ms: mark` for. The author had already moved the head to `000fdbbd` with all three folded, which is why the head had to move at all. The clearance was honest and correct about the head it named, which is precisely why it briefed nobody about the head on the branch; the author asked for the re-derivation and listed what the new head carried, and that list is the cheap half of the obligation.)* ## Enumerating a duplicated value From 9c17952b1e3566407f94a1d6b9ba231c9109e8d6 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Tue, 29 Sep 2026 09:46:36 -0700 Subject: [PATCH 3/9] =?UTF-8?q?docs(checklist):=20rule=2032's=20second=20f?= =?UTF-8?q?ailure=20cause=20was=20false=20=E2=80=94=20four=20base-moved=20?= =?UTF-8?q?witnesses=20(TASK-190)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sprint-review's re-gate finding, reproduced and it holds. Rule 32 claimed tree equality fails on #1994 for a SECOND reason: "squash-shaped only: a20ea9b3 is a two-parent merge-queue commit whose ^{tree} is main's tree rather than the head's, so the comparison cannot be run there at all". Measured: git rev-list --parents -n 1 a20ea9b3 -> one parent (95356c59) So it is not a merge of any shape. And with the base taken as the merge base, the patch-id agrees on both sides exactly like the other three: 95356c59..a20ea9b3 391ca7f451da 4e39c999..b2da9bff 391ca7f451da Trees for the record: parent 0de9aac7, landed commit 3a24f1ab, carried head 683663d9 — a base move, the same cause as #1988/#1989/#1992. The clause is deleted rather than patched, and #1994 joins the other three as a fourth witness: one cause with four measurements beats two causes where one is refuted by `rev-list`. On the shape claim itself, measured over main: all 200 of its most recent commits have exactly one parent, and the newest two-parent commit is dc9d849b (2026-04-07, 1766 commits back), so "the merge queue's shape" describes something this repo stopped producing in April. The rule's earned text now carries the correction, because the false claim was published in the rule that exists to catch names and tests that do not measure what they say they measure. Guard, both modes: 44 rules, numbers 1..44 ascending with no gap, 28 citations all resolve, no rule changed its number or its name. --- docs/development/review-checklist.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/development/review-checklist.md b/docs/development/review-checklist.md index 68ae50661..eee6d7838 100644 --- a/docs/development/review-checklist.md +++ b/docs/development/review-checklist.md @@ -102,7 +102,7 @@ And then note where the fix landed. Someone hit the audience gap, felt it, and b ## Merge mechanics -32. **Verify a merge at the consumer: for a squash merge, the merge commit's tree must equal the carried head's tree.** That equality is the **special case, not the test** — it holds only while the base has not moved under the pull request — and the lead above is kept verbatim because `scripts/verify-numbered-rules.js --previous` pins a rule's lead sentence: a rewritten lead is indistinguishable from a foreign rule claiming that number, so a correction to a rule whose *lead* is itself wrong has no in-place mechanism today (filed as TASK-198, with the CI error quoted). A merge SHA and a green tick prove the workflow ran; they do not prove that what landed is what was reviewed — carries, rebases and stale-base reverts move code between review and merge, and the merge commit's message will not say so. Under this repo's squash convention the proof is one command per side: `git patch-id --stable` over the merge's own range against the same over the gated range, plus the parent and the author/trailer check. **Tree equality is the wrong instrument, in two measured ways.** It is **base-relative**: once main moves under a PR the trees differ *necessarily* while the landing is faithful, so `git rev-parse ^{tree}` against `git rev-parse ^{tree}` fails every faithful landing whose base moved — all three of #1988/#1989/#1992 landed faithfully with differing trees. And it is **squash-shaped only**: `a20ea9b3`, #1994's landing, is a two-parent merge-queue commit whose `^{tree}` is main's tree rather than the head's, so the comparison cannot be run there at all. Patch-id compares the *change* rather than the tree, which is what the claim is about; it held for all three of those landings (`81ecc062`, `b9feb00c`, `efcec768`), and it is the same instrument the AX audit reached independently for a refresh carry (entry 65). Fetch the head yourself (`git fetch origin refs/pull//head`) — a reviewer's claim about remote state is as checkable as a code claim — and diff from the natural merge base, because `git diff main...head` against a stale local `main` is a fiction (a checkout whose local `main` trails `origin/main` by double digits is the ordinary state here, and every PR is cut from the fetched `origin/main`). Riders: a **carry** is a *per-file* claim (`git patch-id --stable`, per file), not a whole-PR one, and it is needed only where non-doc code moved between bases — a docs-only addition on top of a cleared head is a re-stamp, so state old→new head and let the reviewer stamp what actually lands, while a **code**-touching move cannot re-attach — a stamp names the head it was taken against, so that clearance is spent, and the author states old→new head and asks for the re-derivation instead of letting a press ride the old stamp; a **test**-only move counts as code-touching rather than a docs re-stamp, because the arms are much of what a clearance is about, and it re-gates in practice (#1986 `5c068c37`→`0cfd8c0f`, two commits inside the guard's own test file); a **rehearsal** binds to a head exactly as a clearance does, one layer out — a guard arm, a mutation run or a probe quoted after the head has moved is a measurement of a file that may no longer exist there, with real numbers attached to a subject that has changed, so re-run the arm at the head you are reporting or state the head it ran at (on #1994's hold, three guard arms were quoted after a third head move, and ARM 1 had measured a file that no longer existed at the then-current head); and know the required-check set before calling anything green or blocked, because every check being green is not the same as the required check passing, and a required check that has not yet reported renders as `BLOCKED` — the ordinary in-flight state, not a verdict. *(Earned: every closure since — #1755 verified as `e938afc8`, tree `b86b05e4` equal to the carried head `ad3aa8d7`'s, parent `2d0ee979`, no foreign trailer — that being the tree check patch-id replaces, whose equality a base move under the PR removes; and the precedent that motivates the rule rather than any one incident: #568's fix regressed twice through a stale-base revert, which is exactly the class the change comparison closes — the merge looked clean, the tick was green, and the fix was gone. **The code-touching rider earned itself in TASK-177's #1990**: a clearance stamped at `83fa2fcd` arrived in the same batch as two other findings — Wren's paging defect and a mutation label **the author's own ledger** caught crediting an arm that no longer witnessed it — plus the `at`/`ms` divergence **Vera measured in that same clearance** and prescribed `ms: mark` for. The author had already moved the head to `000fdbbd` with all three folded, which is why the head had to move at all. The clearance was honest and correct about the head it named, which is precisely why it briefed nobody about the head on the branch; the author asked for the re-derivation and listed what the new head carried, and that list is the cheap half of the obligation.)* +32. **Verify a merge at the consumer: for a squash merge, the merge commit's tree must equal the carried head's tree.** That equality is the **special case, not the test** — it holds only while the base has not moved under the pull request — and the lead above is kept verbatim because `scripts/verify-numbered-rules.js --previous` pins a rule's lead sentence: a rewritten lead is indistinguishable from a foreign rule claiming that number, so a correction to a rule whose *lead* is itself wrong has no in-place mechanism today (filed as TASK-198, with the CI error quoted). A merge SHA and a green tick prove the workflow ran; they do not prove that what landed is what was reviewed — carries, rebases and stale-base reverts move code between review and merge, and the merge commit's message will not say so. Under this repo's squash convention the proof is one command per side: `git patch-id --stable` over the merge's own range against the same over the gated range, plus the parent and the author/trailer check. **Tree equality is the wrong instrument, and its failure has one cause: it is base-relative.** Once main moves under a PR the trees differ *necessarily* while the landing is faithful, so `git rev-parse ^{tree}` against `git rev-parse ^{tree}` fails every faithful landing whose base moved — **four** measured, not three: #1988/#1989/#1992 landed faithfully with differing trees, and so did #1994, whose `a20ea9b3` has tree `3a24f1ab` where the carried head `b2da9bff` has `683663d9` and its own parent has `0de9aac7`. (An earlier version of this rule gave #1994 a *second*, different-sounding reason — "squash-shaped only: a two-parent merge-queue commit whose `^{tree}` is main's tree" — and that was false twice over: `git rev-list --parents -n 1 a20ea9b3` prints **one** parent, so it is not a merge at all, and with the base taken as the merge base the patch-id agrees on both sides like the other three. All 200 of main's most recent commits have exactly one parent; the newest two-parent commit on main is `dc9d849b`, 2026-04-07, 1,766 commits back, so the merge shape that clause described is one this repo stopped producing in April. A rule that gives one failure two unrelated causes is harder to act on than one that gives it one, and the second cause was wrong, which is the class this file exists to catch.) Patch-id compares the *change* rather than the tree, which is what the claim is about; it held for all four (`81ecc062`, `b9feb00c`, `efcec768`, `391ca7f451da`), and it is the same instrument the AX audit reached independently for a refresh carry (entry 65). Fetch the head yourself (`git fetch origin refs/pull//head`) — a reviewer's claim about remote state is as checkable as a code claim — and diff from the natural merge base, because `git diff main...head` against a stale local `main` is a fiction (a checkout whose local `main` trails `origin/main` by double digits is the ordinary state here, and every PR is cut from the fetched `origin/main`). Riders: a **carry** is a *per-file* claim (`git patch-id --stable`, per file), not a whole-PR one, and it is needed only where non-doc code moved between bases — a docs-only addition on top of a cleared head is a re-stamp, so state old→new head and let the reviewer stamp what actually lands, while a **code**-touching move cannot re-attach — a stamp names the head it was taken against, so that clearance is spent, and the author states old→new head and asks for the re-derivation instead of letting a press ride the old stamp; a **test**-only move counts as code-touching rather than a docs re-stamp, because the arms are much of what a clearance is about, and it re-gates in practice (#1986 `5c068c37`→`0cfd8c0f`, two commits inside the guard's own test file); a **rehearsal** binds to a head exactly as a clearance does, one layer out — a guard arm, a mutation run or a probe quoted after the head has moved is a measurement of a file that may no longer exist there, with real numbers attached to a subject that has changed, so re-run the arm at the head you are reporting or state the head it ran at (on #1994's hold, three guard arms were quoted after a third head move, and ARM 1 had measured a file that no longer existed at the then-current head); and know the required-check set before calling anything green or blocked, because every check being green is not the same as the required check passing, and a required check that has not yet reported renders as `BLOCKED` — the ordinary in-flight state, not a verdict. *(Earned: every closure since — #1755 verified as `e938afc8`, tree `b86b05e4` equal to the carried head `ad3aa8d7`'s, parent `2d0ee979`, no foreign trailer — that being the tree check patch-id replaces, whose equality a base move under the PR removes; and the precedent that motivates the rule rather than any one incident: #568's fix regressed twice through a stale-base revert, which is exactly the class the change comparison closes — the merge looked clean, the tick was green, and the fix was gone. **The code-touching rider earned itself in TASK-177's #1990**: a clearance stamped at `83fa2fcd` arrived in the same batch as two other findings — Wren's paging defect and a mutation label **the author's own ledger** caught crediting an arm that no longer witnessed it — plus the `at`/`ms` divergence **Vera measured in that same clearance** and prescribed `ms: mark` for. The author had already moved the head to `000fdbbd` with all three folded, which is why the head had to move at all. The clearance was honest and correct about the head it named, which is precisely why it briefed nobody about the head on the branch; the author asked for the re-derivation and listed what the new head carried, and that list is the cheap half of the obligation.)* ## Enumerating a duplicated value From 6e085f1fb5a57c135456482ac5860cc1ba327101 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Tue, 29 Sep 2026 09:50:16 -0700 Subject: [PATCH 4/9] docs(checklist): the 60-character name pin is a window, not a wall (TASK-190) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sprint-review measured that fingerprint() ends .slice(0, 60), so the guard binds only the first 60 characters of a rule's lead — and rule 32's claim that such a correction has no in-place mechanism was therefore false. Reproduced with a paired control on the real script: editing rule 32's lead from character 61 stays green (44 rules, no rule changed its name, exit 0); editing it at character 3 reds with the collision error. 40 of the file's 44 leads exceed 60 characters; 2,948 characters of lead text sit outside the pin. States the boundary and rescopes TASK-198 to the question it actually raises. --- docs/development/review-checklist.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/development/review-checklist.md b/docs/development/review-checklist.md index eee6d7838..a1bd38f94 100644 --- a/docs/development/review-checklist.md +++ b/docs/development/review-checklist.md @@ -102,7 +102,7 @@ And then note where the fix landed. Someone hit the audience gap, felt it, and b ## Merge mechanics -32. **Verify a merge at the consumer: for a squash merge, the merge commit's tree must equal the carried head's tree.** That equality is the **special case, not the test** — it holds only while the base has not moved under the pull request — and the lead above is kept verbatim because `scripts/verify-numbered-rules.js --previous` pins a rule's lead sentence: a rewritten lead is indistinguishable from a foreign rule claiming that number, so a correction to a rule whose *lead* is itself wrong has no in-place mechanism today (filed as TASK-198, with the CI error quoted). A merge SHA and a green tick prove the workflow ran; they do not prove that what landed is what was reviewed — carries, rebases and stale-base reverts move code between review and merge, and the merge commit's message will not say so. Under this repo's squash convention the proof is one command per side: `git patch-id --stable` over the merge's own range against the same over the gated range, plus the parent and the author/trailer check. **Tree equality is the wrong instrument, and its failure has one cause: it is base-relative.** Once main moves under a PR the trees differ *necessarily* while the landing is faithful, so `git rev-parse ^{tree}` against `git rev-parse ^{tree}` fails every faithful landing whose base moved — **four** measured, not three: #1988/#1989/#1992 landed faithfully with differing trees, and so did #1994, whose `a20ea9b3` has tree `3a24f1ab` where the carried head `b2da9bff` has `683663d9` and its own parent has `0de9aac7`. (An earlier version of this rule gave #1994 a *second*, different-sounding reason — "squash-shaped only: a two-parent merge-queue commit whose `^{tree}` is main's tree" — and that was false twice over: `git rev-list --parents -n 1 a20ea9b3` prints **one** parent, so it is not a merge at all, and with the base taken as the merge base the patch-id agrees on both sides like the other three. All 200 of main's most recent commits have exactly one parent; the newest two-parent commit on main is `dc9d849b`, 2026-04-07, 1,766 commits back, so the merge shape that clause described is one this repo stopped producing in April. A rule that gives one failure two unrelated causes is harder to act on than one that gives it one, and the second cause was wrong, which is the class this file exists to catch.) Patch-id compares the *change* rather than the tree, which is what the claim is about; it held for all four (`81ecc062`, `b9feb00c`, `efcec768`, `391ca7f451da`), and it is the same instrument the AX audit reached independently for a refresh carry (entry 65). Fetch the head yourself (`git fetch origin refs/pull//head`) — a reviewer's claim about remote state is as checkable as a code claim — and diff from the natural merge base, because `git diff main...head` against a stale local `main` is a fiction (a checkout whose local `main` trails `origin/main` by double digits is the ordinary state here, and every PR is cut from the fetched `origin/main`). Riders: a **carry** is a *per-file* claim (`git patch-id --stable`, per file), not a whole-PR one, and it is needed only where non-doc code moved between bases — a docs-only addition on top of a cleared head is a re-stamp, so state old→new head and let the reviewer stamp what actually lands, while a **code**-touching move cannot re-attach — a stamp names the head it was taken against, so that clearance is spent, and the author states old→new head and asks for the re-derivation instead of letting a press ride the old stamp; a **test**-only move counts as code-touching rather than a docs re-stamp, because the arms are much of what a clearance is about, and it re-gates in practice (#1986 `5c068c37`→`0cfd8c0f`, two commits inside the guard's own test file); a **rehearsal** binds to a head exactly as a clearance does, one layer out — a guard arm, a mutation run or a probe quoted after the head has moved is a measurement of a file that may no longer exist there, with real numbers attached to a subject that has changed, so re-run the arm at the head you are reporting or state the head it ran at (on #1994's hold, three guard arms were quoted after a third head move, and ARM 1 had measured a file that no longer existed at the then-current head); and know the required-check set before calling anything green or blocked, because every check being green is not the same as the required check passing, and a required check that has not yet reported renders as `BLOCKED` — the ordinary in-flight state, not a verdict. *(Earned: every closure since — #1755 verified as `e938afc8`, tree `b86b05e4` equal to the carried head `ad3aa8d7`'s, parent `2d0ee979`, no foreign trailer — that being the tree check patch-id replaces, whose equality a base move under the PR removes; and the precedent that motivates the rule rather than any one incident: #568's fix regressed twice through a stale-base revert, which is exactly the class the change comparison closes — the merge looked clean, the tick was green, and the fix was gone. **The code-touching rider earned itself in TASK-177's #1990**: a clearance stamped at `83fa2fcd` arrived in the same batch as two other findings — Wren's paging defect and a mutation label **the author's own ledger** caught crediting an arm that no longer witnessed it — plus the `at`/`ms` divergence **Vera measured in that same clearance** and prescribed `ms: mark` for. The author had already moved the head to `000fdbbd` with all three folded, which is why the head had to move at all. The clearance was honest and correct about the head it named, which is precisely why it briefed nobody about the head on the branch; the author asked for the re-derivation and listed what the new head carried, and that list is the cheap half of the obligation.)* +32. **Verify a merge at the consumer: for a squash merge, the merge commit's tree must equal the carried head's tree.** That equality is the **special case, not the test** — it holds only while the base has not moved under the pull request — and the lead above is kept verbatim because `scripts/verify-numbered-rules.js --previous` pins a rule's lead sentence: a rewritten lead is indistinguishable from a foreign rule claiming that number, so a correction to a rule whose *lead* is itself wrong appears to have no in-place mechanism (filed as TASK-198, with the CI error quoted). **That appearance is wrong, and how it is wrong matters more than the claim it replaces.** The pin is mechanically a **60-character prefix** of the lead: `fingerprint()` strips the emphasis markers, collapses whitespace and then takes `.slice(0, 60)`, so it binds those first 60 characters and nothing past them. Measured on this head with a paired control — **40 of this file's 44 leads are longer than 60 characters, leaving 2,948 characters of lead text outside the fingerprint**; rewriting *this* rule's lead from character 61 leaves the guard green (`✓ 44 rules … no rule changed its number or its name`, exit 0), while editing the same lead at character 3 reds it with the collision error quoted above. The lead is kept verbatim here regardless — the pin is the convention, and an undocumented reach is not a licence — but the honest statement is that a lead defect past character 60 is *invisible* to the guard rather than forbidden by it, which makes TASK-198's question "should 60 characters be the name at all," not "how do we amend a lead." A merge SHA and a green tick prove the workflow ran; they do not prove that what landed is what was reviewed — carries, rebases and stale-base reverts move code between review and merge, and the merge commit's message will not say so. Under this repo's squash convention the proof is one command per side: `git patch-id --stable` over the merge's own range against the same over the gated range, plus the parent and the author/trailer check. **Tree equality is the wrong instrument, and its failure has one cause: it is base-relative.** Once main moves under a PR the trees differ *necessarily* while the landing is faithful, so `git rev-parse ^{tree}` against `git rev-parse ^{tree}` fails every faithful landing whose base moved — **four** measured, not three: #1988/#1989/#1992 landed faithfully with differing trees, and so did #1994, whose `a20ea9b3` has tree `3a24f1ab` where the carried head `b2da9bff` has `683663d9` and its own parent has `0de9aac7`. (An earlier version of this rule gave #1994 a *second*, different-sounding reason — "squash-shaped only: a two-parent merge-queue commit whose `^{tree}` is main's tree" — and that was false twice over: `git rev-list --parents -n 1 a20ea9b3` prints **one** parent, so it is not a merge at all, and with the base taken as the merge base the patch-id agrees on both sides like the other three. All 200 of main's most recent commits have exactly one parent; the newest two-parent commit on main is `dc9d849b`, 2026-04-07, 1,766 commits back, so the merge shape that clause described is one this repo stopped producing in April. A rule that gives one failure two unrelated causes is harder to act on than one that gives it one, and the second cause was wrong, which is the class this file exists to catch.) Patch-id compares the *change* rather than the tree, which is what the claim is about; it held for all four (`81ecc062`, `b9feb00c`, `efcec768`, `391ca7f451da`), and it is the same instrument the AX audit reached independently for a refresh carry (entry 65). Fetch the head yourself (`git fetch origin refs/pull//head`) — a reviewer's claim about remote state is as checkable as a code claim — and diff from the natural merge base, because `git diff main...head` against a stale local `main` is a fiction (a checkout whose local `main` trails `origin/main` by double digits is the ordinary state here, and every PR is cut from the fetched `origin/main`). Riders: a **carry** is a *per-file* claim (`git patch-id --stable`, per file), not a whole-PR one, and it is needed only where non-doc code moved between bases — a docs-only addition on top of a cleared head is a re-stamp, so state old→new head and let the reviewer stamp what actually lands, while a **code**-touching move cannot re-attach — a stamp names the head it was taken against, so that clearance is spent, and the author states old→new head and asks for the re-derivation instead of letting a press ride the old stamp; a **test**-only move counts as code-touching rather than a docs re-stamp, because the arms are much of what a clearance is about, and it re-gates in practice (#1986 `5c068c37`→`0cfd8c0f`, two commits inside the guard's own test file); a **rehearsal** binds to a head exactly as a clearance does, one layer out — a guard arm, a mutation run or a probe quoted after the head has moved is a measurement of a file that may no longer exist there, with real numbers attached to a subject that has changed, so re-run the arm at the head you are reporting or state the head it ran at (on #1994's hold, three guard arms were quoted after a third head move, and ARM 1 had measured a file that no longer existed at the then-current head); and know the required-check set before calling anything green or blocked, because every check being green is not the same as the required check passing, and a required check that has not yet reported renders as `BLOCKED` — the ordinary in-flight state, not a verdict. *(Earned: every closure since — #1755 verified as `e938afc8`, tree `b86b05e4` equal to the carried head `ad3aa8d7`'s, parent `2d0ee979`, no foreign trailer — that being the tree check patch-id replaces, whose equality a base move under the PR removes; and the precedent that motivates the rule rather than any one incident: #568's fix regressed twice through a stale-base revert, which is exactly the class the change comparison closes — the merge looked clean, the tick was green, and the fix was gone. **The code-touching rider earned itself in TASK-177's #1990**: a clearance stamped at `83fa2fcd` arrived in the same batch as two other findings — Wren's paging defect and a mutation label **the author's own ledger** caught crediting an arm that no longer witnessed it — plus the `at`/`ms` divergence **Vera measured in that same clearance** and prescribed `ms: mark` for. The author had already moved the head to `000fdbbd` with all three folded, which is why the head had to move at all. The clearance was honest and correct about the head it named, which is precisely why it briefed nobody about the head on the branch; the author asked for the re-derivation and listed what the new head carried, and that list is the cheap half of the obligation.)* ## Enumerating a duplicated value From 2dcb823f7c32e21f1a562186ea33baf8b135c051 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Tue, 29 Sep 2026 09:52:13 -0700 Subject: [PATCH 5/9] docs(checklist): name the base, and say what the two heads actually were (TASK-190) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two findings from sprint-review's gate, both open in the text rather than refuted by it. (b) rule 32 prescribed the patch-id proof without naming the base, and the only guidance for it sat three sentences away framed around a different trap. The base is now named where the proof is prescribed: BASE=$(git merge-base ), the value actually run on all four of today's landings. (a) rule 44 called 58298156 and 1a811d84 'separate takes on the same change'. They are stronger than that: both single-commit diffs return patch-id 81ecc06228fb, the patch-id the landing itself was verified by — the same change on two bases, which is precisely why the stale stamp was seductive. --- docs/development/review-checklist.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/development/review-checklist.md b/docs/development/review-checklist.md index a1bd38f94..8c61a5a5a 100644 --- a/docs/development/review-checklist.md +++ b/docs/development/review-checklist.md @@ -102,7 +102,7 @@ And then note where the fix landed. Someone hit the audience gap, felt it, and b ## Merge mechanics -32. **Verify a merge at the consumer: for a squash merge, the merge commit's tree must equal the carried head's tree.** That equality is the **special case, not the test** — it holds only while the base has not moved under the pull request — and the lead above is kept verbatim because `scripts/verify-numbered-rules.js --previous` pins a rule's lead sentence: a rewritten lead is indistinguishable from a foreign rule claiming that number, so a correction to a rule whose *lead* is itself wrong appears to have no in-place mechanism (filed as TASK-198, with the CI error quoted). **That appearance is wrong, and how it is wrong matters more than the claim it replaces.** The pin is mechanically a **60-character prefix** of the lead: `fingerprint()` strips the emphasis markers, collapses whitespace and then takes `.slice(0, 60)`, so it binds those first 60 characters and nothing past them. Measured on this head with a paired control — **40 of this file's 44 leads are longer than 60 characters, leaving 2,948 characters of lead text outside the fingerprint**; rewriting *this* rule's lead from character 61 leaves the guard green (`✓ 44 rules … no rule changed its number or its name`, exit 0), while editing the same lead at character 3 reds it with the collision error quoted above. The lead is kept verbatim here regardless — the pin is the convention, and an undocumented reach is not a licence — but the honest statement is that a lead defect past character 60 is *invisible* to the guard rather than forbidden by it, which makes TASK-198's question "should 60 characters be the name at all," not "how do we amend a lead." A merge SHA and a green tick prove the workflow ran; they do not prove that what landed is what was reviewed — carries, rebases and stale-base reverts move code between review and merge, and the merge commit's message will not say so. Under this repo's squash convention the proof is one command per side: `git patch-id --stable` over the merge's own range against the same over the gated range, plus the parent and the author/trailer check. **Tree equality is the wrong instrument, and its failure has one cause: it is base-relative.** Once main moves under a PR the trees differ *necessarily* while the landing is faithful, so `git rev-parse ^{tree}` against `git rev-parse ^{tree}` fails every faithful landing whose base moved — **four** measured, not three: #1988/#1989/#1992 landed faithfully with differing trees, and so did #1994, whose `a20ea9b3` has tree `3a24f1ab` where the carried head `b2da9bff` has `683663d9` and its own parent has `0de9aac7`. (An earlier version of this rule gave #1994 a *second*, different-sounding reason — "squash-shaped only: a two-parent merge-queue commit whose `^{tree}` is main's tree" — and that was false twice over: `git rev-list --parents -n 1 a20ea9b3` prints **one** parent, so it is not a merge at all, and with the base taken as the merge base the patch-id agrees on both sides like the other three. All 200 of main's most recent commits have exactly one parent; the newest two-parent commit on main is `dc9d849b`, 2026-04-07, 1,766 commits back, so the merge shape that clause described is one this repo stopped producing in April. A rule that gives one failure two unrelated causes is harder to act on than one that gives it one, and the second cause was wrong, which is the class this file exists to catch.) Patch-id compares the *change* rather than the tree, which is what the claim is about; it held for all four (`81ecc062`, `b9feb00c`, `efcec768`, `391ca7f451da`), and it is the same instrument the AX audit reached independently for a refresh carry (entry 65). Fetch the head yourself (`git fetch origin refs/pull//head`) — a reviewer's claim about remote state is as checkable as a code claim — and diff from the natural merge base, because `git diff main...head` against a stale local `main` is a fiction (a checkout whose local `main` trails `origin/main` by double digits is the ordinary state here, and every PR is cut from the fetched `origin/main`). Riders: a **carry** is a *per-file* claim (`git patch-id --stable`, per file), not a whole-PR one, and it is needed only where non-doc code moved between bases — a docs-only addition on top of a cleared head is a re-stamp, so state old→new head and let the reviewer stamp what actually lands, while a **code**-touching move cannot re-attach — a stamp names the head it was taken against, so that clearance is spent, and the author states old→new head and asks for the re-derivation instead of letting a press ride the old stamp; a **test**-only move counts as code-touching rather than a docs re-stamp, because the arms are much of what a clearance is about, and it re-gates in practice (#1986 `5c068c37`→`0cfd8c0f`, two commits inside the guard's own test file); a **rehearsal** binds to a head exactly as a clearance does, one layer out — a guard arm, a mutation run or a probe quoted after the head has moved is a measurement of a file that may no longer exist there, with real numbers attached to a subject that has changed, so re-run the arm at the head you are reporting or state the head it ran at (on #1994's hold, three guard arms were quoted after a third head move, and ARM 1 had measured a file that no longer existed at the then-current head); and know the required-check set before calling anything green or blocked, because every check being green is not the same as the required check passing, and a required check that has not yet reported renders as `BLOCKED` — the ordinary in-flight state, not a verdict. *(Earned: every closure since — #1755 verified as `e938afc8`, tree `b86b05e4` equal to the carried head `ad3aa8d7`'s, parent `2d0ee979`, no foreign trailer — that being the tree check patch-id replaces, whose equality a base move under the PR removes; and the precedent that motivates the rule rather than any one incident: #568's fix regressed twice through a stale-base revert, which is exactly the class the change comparison closes — the merge looked clean, the tick was green, and the fix was gone. **The code-touching rider earned itself in TASK-177's #1990**: a clearance stamped at `83fa2fcd` arrived in the same batch as two other findings — Wren's paging defect and a mutation label **the author's own ledger** caught crediting an arm that no longer witnessed it — plus the `at`/`ms` divergence **Vera measured in that same clearance** and prescribed `ms: mark` for. The author had already moved the head to `000fdbbd` with all three folded, which is why the head had to move at all. The clearance was honest and correct about the head it named, which is precisely why it briefed nobody about the head on the branch; the author asked for the re-derivation and listed what the new head carried, and that list is the cheap half of the obligation.)* +32. **Verify a merge at the consumer: for a squash merge, the merge commit's tree must equal the carried head's tree.** That equality is the **special case, not the test** — it holds only while the base has not moved under the pull request — and the lead above is kept verbatim because `scripts/verify-numbered-rules.js --previous` pins a rule's lead sentence: a rewritten lead is indistinguishable from a foreign rule claiming that number, so a correction to a rule whose *lead* is itself wrong appears to have no in-place mechanism (filed as TASK-198, with the CI error quoted). **That appearance is wrong, and how it is wrong matters more than the claim it replaces.** The pin is mechanically a **60-character prefix** of the lead: `fingerprint()` strips the emphasis markers, collapses whitespace and then takes `.slice(0, 60)`, so it binds those first 60 characters and nothing past them. Measured on this head with a paired control — **40 of this file's 44 leads are longer than 60 characters, leaving 2,948 characters of lead text outside the fingerprint**; rewriting *this* rule's lead from character 61 leaves the guard green (`✓ 44 rules … no rule changed its number or its name`, exit 0), while editing the same lead at character 3 reds it with the collision error quoted above. The lead is kept verbatim here regardless — the pin is the convention, and an undocumented reach is not a licence — but the honest statement is that a lead defect past character 60 is *invisible* to the guard rather than forbidden by it, which makes TASK-198's question "should 60 characters be the name at all," not "how do we amend a lead." A merge SHA and a green tick prove the workflow ran; they do not prove that what landed is what was reviewed — carries, rebases and stale-base reverts move code between review and merge, and the merge commit's message will not say so. Under this repo's squash convention the proof is one command per side, **both taken against the base named rather than implied** — `BASE=$(git merge-base )`, then `git diff ^ | git patch-id --stable` against `git diff $BASE | git patch-id --stable`, plus the parent and the author/trailer check. Naming the base is most of the measurement: a `` left to the reader resolves to a local `main`, and a local `main` is the fiction the riders below describe. **Tree equality is the wrong instrument, and its failure has one cause: it is base-relative.** Once main moves under a PR the trees differ *necessarily* while the landing is faithful, so `git rev-parse ^{tree}` against `git rev-parse ^{tree}` fails every faithful landing whose base moved — **four** measured, not three: #1988/#1989/#1992 landed faithfully with differing trees, and so did #1994, whose `a20ea9b3` has tree `3a24f1ab` where the carried head `b2da9bff` has `683663d9` and its own parent has `0de9aac7`. (An earlier version of this rule gave #1994 a *second*, different-sounding reason — "squash-shaped only: a two-parent merge-queue commit whose `^{tree}` is main's tree" — and that was false twice over: `git rev-list --parents -n 1 a20ea9b3` prints **one** parent, so it is not a merge at all, and with the base taken as the merge base the patch-id agrees on both sides like the other three. All 200 of main's most recent commits have exactly one parent; the newest two-parent commit on main is `dc9d849b`, 2026-04-07, 1,766 commits back, so the merge shape that clause described is one this repo stopped producing in April. A rule that gives one failure two unrelated causes is harder to act on than one that gives it one, and the second cause was wrong, which is the class this file exists to catch.) Patch-id compares the *change* rather than the tree, which is what the claim is about; it held for all four (`81ecc062`, `b9feb00c`, `efcec768`, `391ca7f451da`), and it is the same instrument the AX audit reached independently for a refresh carry (entry 65). Fetch the head yourself (`git fetch origin refs/pull//head`) — a reviewer's claim about remote state is as checkable as a code claim — and diff from the base `git merge-base ` returns — the same command named above, and the value actually run on all four of today's landings — because `git diff main...head` against a stale local `main` is a fiction (a checkout whose local `main` trails `origin/main` by double digits is the ordinary state here, and every PR is cut from the fetched `origin/main`). Riders: a **carry** is a *per-file* claim (`git patch-id --stable`, per file), not a whole-PR one, and it is needed only where non-doc code moved between bases — a docs-only addition on top of a cleared head is a re-stamp, so state old→new head and let the reviewer stamp what actually lands, while a **code**-touching move cannot re-attach — a stamp names the head it was taken against, so that clearance is spent, and the author states old→new head and asks for the re-derivation instead of letting a press ride the old stamp; a **test**-only move counts as code-touching rather than a docs re-stamp, because the arms are much of what a clearance is about, and it re-gates in practice (#1986 `5c068c37`→`0cfd8c0f`, two commits inside the guard's own test file); a **rehearsal** binds to a head exactly as a clearance does, one layer out — a guard arm, a mutation run or a probe quoted after the head has moved is a measurement of a file that may no longer exist there, with real numbers attached to a subject that has changed, so re-run the arm at the head you are reporting or state the head it ran at (on #1994's hold, three guard arms were quoted after a third head move, and ARM 1 had measured a file that no longer existed at the then-current head); and know the required-check set before calling anything green or blocked, because every check being green is not the same as the required check passing, and a required check that has not yet reported renders as `BLOCKED` — the ordinary in-flight state, not a verdict. *(Earned: every closure since — #1755 verified as `e938afc8`, tree `b86b05e4` equal to the carried head `ad3aa8d7`'s, parent `2d0ee979`, no foreign trailer — that being the tree check patch-id replaces, whose equality a base move under the PR removes; and the precedent that motivates the rule rather than any one incident: #568's fix regressed twice through a stale-base revert, which is exactly the class the change comparison closes — the merge looked clean, the tick was green, and the fix was gone. **The code-touching rider earned itself in TASK-177's #1990**: a clearance stamped at `83fa2fcd` arrived in the same batch as two other findings — Wren's paging defect and a mutation label **the author's own ledger** caught crediting an arm that no longer witnessed it — plus the `at`/`ms` divergence **Vera measured in that same clearance** and prescribed `ms: mark` for. The author had already moved the head to `000fdbbd` with all three folded, which is why the head had to move at all. The clearance was honest and correct about the head it named, which is precisely why it briefed nobody about the head on the branch; the author asked for the re-derivation and listed what the new head carried, and that list is the cheap half of the obligation.)* ## Enumerating a duplicated value @@ -158,4 +158,4 @@ And then note where the fix landed. Someone hit the audience gap, felt it, and b ## What a clearance can bind -44. **A clearance has to exist as a PASS recorded against the head being pressed, and prose is not a record.** The question is existence, not identity: not whether the gated content is what merged (that is rule 32), but whether *any* clearance was ever taken at the head the press will read. Use GitHub's own record rather than anyone's prose — every review in `GET /pulls//reviews` carries `commit_id`, the head it was submitted against, so selecting reviews whose `commit_id` is the pressed head finds the reviews submitted against it: candidates, not clearances. **Existence is necessary and not sufficient, because a review at the head can be a refusal.** `state` carries no verdict here: measured across #1988, #1989 and #2000, every review on all three is `COMMENTED` — **18 of 18 when this was written, and that number only grows as seats post more, so re-run the count rather than quoting it** — not one `APPROVED` or `CHANGES_REQUESTED` across any of them, so the verdict is the body's first line and nothing else. The check is therefore **per required gate: a review whose `commit_id` is the pressed head and whose first line names that same head and declares that gate's PASS.** The head name is not decoration. `commit_id` records the head **at submission**, so a gate taken at X and posted after a push to Y lands at Y and reads fresh at a head nobody read — and a check that stops at `commit_id` will accept it. A first line naming an *older* head is a rule 32 carry question, not an existence pass: the two heads may share a tree, in which case the artifact really was gated (32's test) and no existence check can know it; or they may **differ**, in which case the clearance names content nobody gated. 44 answers whether a record claims *this* head; 32 answers whether an older claim still carries to it. Two counterexamples, one per half. #2000 @ `d1d56e4c` is what a bare existence test clears: its only review is a `DOCS-GATE: CHANGES` at that head. #1981 is what a `commit_id`-only test clears: pressed at `3d6e1763`, where its code review carries that `commit_id` and reads `DELTA RE-GATE: PASS @ a4566e29`. A head whose reviews are all refusals, or all corrections — "Correction to my gate above" declares no verdict — is ungated, which is the honest answer rather than a pass by default. `submitted_at` orders reviews but does not bind them to a head, and it cannot be used to select one either: every seat here posts under one GitHub identity, so `.[-1]` returns whichever seat reviewed last. Two checks that look right and are not. `git merge-base --is-ancestor ` passes a clearance a later head move has already spent — `b8048c72` is an ancestor of `177ba436` — which is 32's class of defect, not this one. And a sha missing from your clone says nothing about the remote: a commit can be there with no ref pointing at it, so the remote has it, no ordinary fetch brings it in, and `refs/pull//head` keeps a squashed-away head fetchable — an absence read in one clone is as clone-local as a presence read. `commit_id` cannot tell a carry from a re-derivation, so the body still has to be read for that; it answers only whether a review was submitted against that head at all. Its own entry rather than a rider on 32, and the argument is 41's test applied to 32: every guard 32 sends you to check passes here — nothing had merged, no head had moved, the required set was green — and the defect survives all of them, because 32 presupposes a clearance and this asks whether one exists. *(Earned: TASK-186's #1988. The row recorded "CODE PASS @ `58298156`" from 06:54Z on 2026-09-28 and carried it for **29.4h**; the board title carried "… (UX PASS @ `1a811d84` + CODE PASS)" for **8.7h** from 03:34Z the next morning. No clearance was ever taken at that commit: it is a **child** of `7f171637`, which is **no ancestor of `1a811d84`** — the two **diverge at `bbab5c31`** (`git merge-base 58298156 1a811d84` is that commit, and `merge-base 7f171637 1a811d84` is the same one), so they are separate takes on the same TASK-180 change rather than siblings, and `GET /pulls/1988/reviews` held four reviews at that point — every one of them `commit_id=1a811d84` — of which only the first existed before 12:17Z on 2026-09-29. The commit itself was confirmable — `gh api commits/` resolved it and a full-sha fetch retrieved it — but no advertised ref pointed at it — `git ls-remote` listed 2,579 of them when this was measured and not one was this sha, a number that only grows, so re-run it rather than quoting it — and `git fetch origin ` fails, so no ordinary fetch brought it into any other clone. So the commit could be confirmed and the gate could not, because there was no gate; a rule written about unresolvable heads would have mis-stated this incident. The title's *shape* did as much damage as its content — binding the sha to the UX pass and leaving the code pass bare is what let a later reader collapse it into "CODE PASS @ `1a811d84`", a head that was real and resolvable and so looked verifiable. And the `commit_id` half has its own incident: #1981 was pressed at `3d6e1763`, and the code review bearing that `commit_id` reads `DELTA RE-GATE: PASS @ a4566e29` — the stack had been re-authored from `a4566e29` to `3d6e1763` between the gate and its posting, and the two commits share tree `0e3b2d01cf`, so the artifact was gated and the record could not say so. Same PR, and the hazard's harsher half: the code review submitted at 21:26:47Z carries `commit_id=245dbaf4` while its first line names `5e0e7193`, and those trees **differ** — three files, three lines, the "pod, not room" string among them — so it attached a clearance to content nobody had gated; superseded seven minutes later and never pressed, which is why the incident above is the one that reached a press, and why a check that stops at `commit_id` cannot be trusted at all.)* +44. **A clearance has to exist as a PASS recorded against the head being pressed, and prose is not a record.** The question is existence, not identity: not whether the gated content is what merged (that is rule 32), but whether *any* clearance was ever taken at the head the press will read. Use GitHub's own record rather than anyone's prose — every review in `GET /pulls//reviews` carries `commit_id`, the head it was submitted against, so selecting reviews whose `commit_id` is the pressed head finds the reviews submitted against it: candidates, not clearances. **Existence is necessary and not sufficient, because a review at the head can be a refusal.** `state` carries no verdict here: measured across #1988, #1989 and #2000, every review on all three is `COMMENTED` — **18 of 18 when this was written, and that number only grows as seats post more, so re-run the count rather than quoting it** — not one `APPROVED` or `CHANGES_REQUESTED` across any of them, so the verdict is the body's first line and nothing else. The check is therefore **per required gate: a review whose `commit_id` is the pressed head and whose first line names that same head and declares that gate's PASS.** The head name is not decoration. `commit_id` records the head **at submission**, so a gate taken at X and posted after a push to Y lands at Y and reads fresh at a head nobody read — and a check that stops at `commit_id` will accept it. A first line naming an *older* head is a rule 32 carry question, not an existence pass: the two heads may share a tree, in which case the artifact really was gated (32's test) and no existence check can know it; or they may **differ**, in which case the clearance names content nobody gated. 44 answers whether a record claims *this* head; 32 answers whether an older claim still carries to it. Two counterexamples, one per half. #2000 @ `d1d56e4c` is what a bare existence test clears: its only review is a `DOCS-GATE: CHANGES` at that head. #1981 is what a `commit_id`-only test clears: pressed at `3d6e1763`, where its code review carries that `commit_id` and reads `DELTA RE-GATE: PASS @ a4566e29`. A head whose reviews are all refusals, or all corrections — "Correction to my gate above" declares no verdict — is ungated, which is the honest answer rather than a pass by default. `submitted_at` orders reviews but does not bind them to a head, and it cannot be used to select one either: every seat here posts under one GitHub identity, so `.[-1]` returns whichever seat reviewed last. Two checks that look right and are not. `git merge-base --is-ancestor ` passes a clearance a later head move has already spent — `b8048c72` is an ancestor of `177ba436` — which is 32's class of defect, not this one. And a sha missing from your clone says nothing about the remote: a commit can be there with no ref pointing at it, so the remote has it, no ordinary fetch brings it in, and `refs/pull//head` keeps a squashed-away head fetchable — an absence read in one clone is as clone-local as a presence read. `commit_id` cannot tell a carry from a re-derivation, so the body still has to be read for that; it answers only whether a review was submitted against that head at all. Its own entry rather than a rider on 32, and the argument is 41's test applied to 32: every guard 32 sends you to check passes here — nothing had merged, no head had moved, the required set was green — and the defect survives all of them, because 32 presupposes a clearance and this asks whether one exists. *(Earned: TASK-186's #1988. The row recorded "CODE PASS @ `58298156`" from 06:54Z on 2026-09-28 and carried it for **29.4h**; the board title carried "… (UX PASS @ `1a811d84` + CODE PASS)" for **8.7h** from 03:34Z the next morning. No clearance was ever taken at that commit: it is a **child** of `7f171637`, which is **no ancestor of `1a811d84`** — the two **diverge at `bbab5c31`** (`git merge-base 58298156 1a811d84` is that commit, and `merge-base 7f171637 1a811d84` is the same one), so they are not two sibling commits but **the same change carried on two bases** — `git diff 58298156^ 58298156 | git patch-id --stable` and `git diff 1a811d84^ 1a811d84 | git patch-id --stable` both return **`81ecc06228fb`**, the very patch-id the landing was verified by, which is why the stale stamp was seductive: what differed between the two heads was the base, not the change, and `GET /pulls/1988/reviews` held four reviews at that point — every one of them `commit_id=1a811d84` — of which only the first existed before 12:17Z on 2026-09-29. The commit itself was confirmable — `gh api commits/` resolved it and a full-sha fetch retrieved it — but no advertised ref pointed at it — `git ls-remote` listed 2,579 of them when this was measured and not one was this sha, a number that only grows, so re-run it rather than quoting it — and `git fetch origin ` fails, so no ordinary fetch brought it into any other clone. So the commit could be confirmed and the gate could not, because there was no gate; a rule written about unresolvable heads would have mis-stated this incident. The title's *shape* did as much damage as its content — binding the sha to the UX pass and leaving the code pass bare is what let a later reader collapse it into "CODE PASS @ `1a811d84`", a head that was real and resolvable and so looked verifiable. And the `commit_id` half has its own incident: #1981 was pressed at `3d6e1763`, and the code review bearing that `commit_id` reads `DELTA RE-GATE: PASS @ a4566e29` — the stack had been re-authored from `a4566e29` to `3d6e1763` between the gate and its posting, and the two commits share tree `0e3b2d01cf`, so the artifact was gated and the record could not say so. Same PR, and the hazard's harsher half: the code review submitted at 21:26:47Z carries `commit_id=245dbaf4` while its first line names `5e0e7193`, and those trees **differ** — three files, three lines, the "pod, not room" string among them — so it attached a clearance to content nobody had gated; superseded seven minutes later and never pressed, which is why the incident above is the one that reached a press, and why a check that stops at `commit_id` cannot be trusted at all.)* From b6318f5470fa07ad302bcfbf3ca76c19d270d26e Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Tue, 29 Sep 2026 09:55:31 -0700 Subject: [PATCH 6/9] docs(checklist): the pin counts normalised characters, so name the raw offset (TASK-190) sprint-review's non-blocking addition, folded while the stamp is unspent rather than deferred: fingerprint() strips ** and `*_ and collapses whitespace BEFORE it slices, so the 60 are counted on the normalised lead and the boundary lands at a different raw offset in every lead carrying markup. Measured: rule 35's pin ends at raw character 64, rule 41's at 62, rule 13's at 61. Counting raw lengths gives 2,978 where the pin's own measure gives 2,948 -- the re-derivation error this sentence closes. --- docs/development/review-checklist.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/development/review-checklist.md b/docs/development/review-checklist.md index 8c61a5a5a..e6e55cdec 100644 --- a/docs/development/review-checklist.md +++ b/docs/development/review-checklist.md @@ -102,7 +102,7 @@ And then note where the fix landed. Someone hit the audience gap, felt it, and b ## Merge mechanics -32. **Verify a merge at the consumer: for a squash merge, the merge commit's tree must equal the carried head's tree.** That equality is the **special case, not the test** — it holds only while the base has not moved under the pull request — and the lead above is kept verbatim because `scripts/verify-numbered-rules.js --previous` pins a rule's lead sentence: a rewritten lead is indistinguishable from a foreign rule claiming that number, so a correction to a rule whose *lead* is itself wrong appears to have no in-place mechanism (filed as TASK-198, with the CI error quoted). **That appearance is wrong, and how it is wrong matters more than the claim it replaces.** The pin is mechanically a **60-character prefix** of the lead: `fingerprint()` strips the emphasis markers, collapses whitespace and then takes `.slice(0, 60)`, so it binds those first 60 characters and nothing past them. Measured on this head with a paired control — **40 of this file's 44 leads are longer than 60 characters, leaving 2,948 characters of lead text outside the fingerprint**; rewriting *this* rule's lead from character 61 leaves the guard green (`✓ 44 rules … no rule changed its number or its name`, exit 0), while editing the same lead at character 3 reds it with the collision error quoted above. The lead is kept verbatim here regardless — the pin is the convention, and an undocumented reach is not a licence — but the honest statement is that a lead defect past character 60 is *invisible* to the guard rather than forbidden by it, which makes TASK-198's question "should 60 characters be the name at all," not "how do we amend a lead." A merge SHA and a green tick prove the workflow ran; they do not prove that what landed is what was reviewed — carries, rebases and stale-base reverts move code between review and merge, and the merge commit's message will not say so. Under this repo's squash convention the proof is one command per side, **both taken against the base named rather than implied** — `BASE=$(git merge-base )`, then `git diff ^ | git patch-id --stable` against `git diff $BASE | git patch-id --stable`, plus the parent and the author/trailer check. Naming the base is most of the measurement: a `` left to the reader resolves to a local `main`, and a local `main` is the fiction the riders below describe. **Tree equality is the wrong instrument, and its failure has one cause: it is base-relative.** Once main moves under a PR the trees differ *necessarily* while the landing is faithful, so `git rev-parse ^{tree}` against `git rev-parse ^{tree}` fails every faithful landing whose base moved — **four** measured, not three: #1988/#1989/#1992 landed faithfully with differing trees, and so did #1994, whose `a20ea9b3` has tree `3a24f1ab` where the carried head `b2da9bff` has `683663d9` and its own parent has `0de9aac7`. (An earlier version of this rule gave #1994 a *second*, different-sounding reason — "squash-shaped only: a two-parent merge-queue commit whose `^{tree}` is main's tree" — and that was false twice over: `git rev-list --parents -n 1 a20ea9b3` prints **one** parent, so it is not a merge at all, and with the base taken as the merge base the patch-id agrees on both sides like the other three. All 200 of main's most recent commits have exactly one parent; the newest two-parent commit on main is `dc9d849b`, 2026-04-07, 1,766 commits back, so the merge shape that clause described is one this repo stopped producing in April. A rule that gives one failure two unrelated causes is harder to act on than one that gives it one, and the second cause was wrong, which is the class this file exists to catch.) Patch-id compares the *change* rather than the tree, which is what the claim is about; it held for all four (`81ecc062`, `b9feb00c`, `efcec768`, `391ca7f451da`), and it is the same instrument the AX audit reached independently for a refresh carry (entry 65). Fetch the head yourself (`git fetch origin refs/pull//head`) — a reviewer's claim about remote state is as checkable as a code claim — and diff from the base `git merge-base ` returns — the same command named above, and the value actually run on all four of today's landings — because `git diff main...head` against a stale local `main` is a fiction (a checkout whose local `main` trails `origin/main` by double digits is the ordinary state here, and every PR is cut from the fetched `origin/main`). Riders: a **carry** is a *per-file* claim (`git patch-id --stable`, per file), not a whole-PR one, and it is needed only where non-doc code moved between bases — a docs-only addition on top of a cleared head is a re-stamp, so state old→new head and let the reviewer stamp what actually lands, while a **code**-touching move cannot re-attach — a stamp names the head it was taken against, so that clearance is spent, and the author states old→new head and asks for the re-derivation instead of letting a press ride the old stamp; a **test**-only move counts as code-touching rather than a docs re-stamp, because the arms are much of what a clearance is about, and it re-gates in practice (#1986 `5c068c37`→`0cfd8c0f`, two commits inside the guard's own test file); a **rehearsal** binds to a head exactly as a clearance does, one layer out — a guard arm, a mutation run or a probe quoted after the head has moved is a measurement of a file that may no longer exist there, with real numbers attached to a subject that has changed, so re-run the arm at the head you are reporting or state the head it ran at (on #1994's hold, three guard arms were quoted after a third head move, and ARM 1 had measured a file that no longer existed at the then-current head); and know the required-check set before calling anything green or blocked, because every check being green is not the same as the required check passing, and a required check that has not yet reported renders as `BLOCKED` — the ordinary in-flight state, not a verdict. *(Earned: every closure since — #1755 verified as `e938afc8`, tree `b86b05e4` equal to the carried head `ad3aa8d7`'s, parent `2d0ee979`, no foreign trailer — that being the tree check patch-id replaces, whose equality a base move under the PR removes; and the precedent that motivates the rule rather than any one incident: #568's fix regressed twice through a stale-base revert, which is exactly the class the change comparison closes — the merge looked clean, the tick was green, and the fix was gone. **The code-touching rider earned itself in TASK-177's #1990**: a clearance stamped at `83fa2fcd` arrived in the same batch as two other findings — Wren's paging defect and a mutation label **the author's own ledger** caught crediting an arm that no longer witnessed it — plus the `at`/`ms` divergence **Vera measured in that same clearance** and prescribed `ms: mark` for. The author had already moved the head to `000fdbbd` with all three folded, which is why the head had to move at all. The clearance was honest and correct about the head it named, which is precisely why it briefed nobody about the head on the branch; the author asked for the re-derivation and listed what the new head carried, and that list is the cheap half of the obligation.)* +32. **Verify a merge at the consumer: for a squash merge, the merge commit's tree must equal the carried head's tree.** That equality is the **special case, not the test** — it holds only while the base has not moved under the pull request — and the lead above is kept verbatim because `scripts/verify-numbered-rules.js --previous` pins a rule's lead sentence: a rewritten lead is indistinguishable from a foreign rule claiming that number, so a correction to a rule whose *lead* is itself wrong appears to have no in-place mechanism (filed as TASK-198, with the CI error quoted). **That appearance is wrong, and how it is wrong matters more than the claim it replaces.** The pin is mechanically a **60-character prefix** of the lead: `fingerprint()` strips the emphasis markers, collapses whitespace and then takes `.slice(0, 60)`, so it binds those first 60 characters and nothing past them — and **those 60 are counted on the *normalised* lead**, because the stripping and the whitespace collapse both happen *before* the slice. The boundary therefore lands at a different **raw** offset in every lead that carries markup: rule 35's pin ends at raw character 64, rule 41's at 62, rule 13's at 61. That is the trap for anyone re-deriving these counts from raw string lengths — measuring raw yields 2,978 where the pin's own measure yields 2,948. Measured on this head with a paired control — **40 of this file's 44 leads are longer than 60 characters, leaving 2,948 characters of lead text outside the fingerprint**; rewriting *this* rule's lead from character 61 leaves the guard green (`✓ 44 rules … no rule changed its number or its name`, exit 0), while editing the same lead at character 3 reds it with the collision error quoted above. The lead is kept verbatim here regardless — the pin is the convention, and an undocumented reach is not a licence — but the honest statement is that a lead defect past character 60 is *invisible* to the guard rather than forbidden by it, which makes TASK-198's question "should 60 characters be the name at all," not "how do we amend a lead." A merge SHA and a green tick prove the workflow ran; they do not prove that what landed is what was reviewed — carries, rebases and stale-base reverts move code between review and merge, and the merge commit's message will not say so. Under this repo's squash convention the proof is one command per side, **both taken against the base named rather than implied** — `BASE=$(git merge-base )`, then `git diff ^ | git patch-id --stable` against `git diff $BASE | git patch-id --stable`, plus the parent and the author/trailer check. Naming the base is most of the measurement: a `` left to the reader resolves to a local `main`, and a local `main` is the fiction the riders below describe. **Tree equality is the wrong instrument, and its failure has one cause: it is base-relative.** Once main moves under a PR the trees differ *necessarily* while the landing is faithful, so `git rev-parse ^{tree}` against `git rev-parse ^{tree}` fails every faithful landing whose base moved — **four** measured, not three: #1988/#1989/#1992 landed faithfully with differing trees, and so did #1994, whose `a20ea9b3` has tree `3a24f1ab` where the carried head `b2da9bff` has `683663d9` and its own parent has `0de9aac7`. (An earlier version of this rule gave #1994 a *second*, different-sounding reason — "squash-shaped only: a two-parent merge-queue commit whose `^{tree}` is main's tree" — and that was false twice over: `git rev-list --parents -n 1 a20ea9b3` prints **one** parent, so it is not a merge at all, and with the base taken as the merge base the patch-id agrees on both sides like the other three. All 200 of main's most recent commits have exactly one parent; the newest two-parent commit on main is `dc9d849b`, 2026-04-07, 1,766 commits back, so the merge shape that clause described is one this repo stopped producing in April. A rule that gives one failure two unrelated causes is harder to act on than one that gives it one, and the second cause was wrong, which is the class this file exists to catch.) Patch-id compares the *change* rather than the tree, which is what the claim is about; it held for all four (`81ecc062`, `b9feb00c`, `efcec768`, `391ca7f451da`), and it is the same instrument the AX audit reached independently for a refresh carry (entry 65). Fetch the head yourself (`git fetch origin refs/pull//head`) — a reviewer's claim about remote state is as checkable as a code claim — and diff from the base `git merge-base ` returns — the same command named above, and the value actually run on all four of today's landings — because `git diff main...head` against a stale local `main` is a fiction (a checkout whose local `main` trails `origin/main` by double digits is the ordinary state here, and every PR is cut from the fetched `origin/main`). Riders: a **carry** is a *per-file* claim (`git patch-id --stable`, per file), not a whole-PR one, and it is needed only where non-doc code moved between bases — a docs-only addition on top of a cleared head is a re-stamp, so state old→new head and let the reviewer stamp what actually lands, while a **code**-touching move cannot re-attach — a stamp names the head it was taken against, so that clearance is spent, and the author states old→new head and asks for the re-derivation instead of letting a press ride the old stamp; a **test**-only move counts as code-touching rather than a docs re-stamp, because the arms are much of what a clearance is about, and it re-gates in practice (#1986 `5c068c37`→`0cfd8c0f`, two commits inside the guard's own test file); a **rehearsal** binds to a head exactly as a clearance does, one layer out — a guard arm, a mutation run or a probe quoted after the head has moved is a measurement of a file that may no longer exist there, with real numbers attached to a subject that has changed, so re-run the arm at the head you are reporting or state the head it ran at (on #1994's hold, three guard arms were quoted after a third head move, and ARM 1 had measured a file that no longer existed at the then-current head); and know the required-check set before calling anything green or blocked, because every check being green is not the same as the required check passing, and a required check that has not yet reported renders as `BLOCKED` — the ordinary in-flight state, not a verdict. *(Earned: every closure since — #1755 verified as `e938afc8`, tree `b86b05e4` equal to the carried head `ad3aa8d7`'s, parent `2d0ee979`, no foreign trailer — that being the tree check patch-id replaces, whose equality a base move under the PR removes; and the precedent that motivates the rule rather than any one incident: #568's fix regressed twice through a stale-base revert, which is exactly the class the change comparison closes — the merge looked clean, the tick was green, and the fix was gone. **The code-touching rider earned itself in TASK-177's #1990**: a clearance stamped at `83fa2fcd` arrived in the same batch as two other findings — Wren's paging defect and a mutation label **the author's own ledger** caught crediting an arm that no longer witnessed it — plus the `at`/`ms` divergence **Vera measured in that same clearance** and prescribed `ms: mark` for. The author had already moved the head to `000fdbbd` with all three folded, which is why the head had to move at all. The clearance was honest and correct about the head it named, which is precisely why it briefed nobody about the head on the branch; the author asked for the re-derivation and listed what the new head carried, and that list is the cheap half of the obligation.)* ## Enumerating a duplicated value From 121b28606e4a800926843951cb05ba9068251073 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Tue, 29 Sep 2026 10:00:42 -0700 Subject: [PATCH 7/9] =?UTF-8?q?docs(checklist):=20the=20pin=20can=20skip?= =?UTF-8?q?=20over=2060=20=E2=80=94=20rule=2041's=20raw=20offset=20does=20?= =?UTF-8?q?not=20exist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer's finding: the sentence gave rule 41's raw offset as 62, computed as the last offset before the boundary while rules 35 and 13 were given as the offset at which the normalised count reaches 60 — one sentence, two quantities. Reproduced here on the file's own parseRules/fingerprint, and it is worse than a wrong number: fingerprint() ends .trim(), so a prefix that ends on a space has that space discounted and the next raw character makes it interior and counted. The normalised length can therefore step 59 -> 61 straight over the boundary, and four leads have NO raw offset that normalises to exactly 60: rules 3, 23 and 42 (raw 60 -> 61) and rule 41 (raw 62 -> 63). Exact landings: 34 leads at 60, rule 13 at 61, rule 35 at 64. Guard, CI's mode: 44 rules, 1..44, 38 citations resolve, no rule changed its number or its name. --- docs/development/review-checklist.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/development/review-checklist.md b/docs/development/review-checklist.md index e6e55cdec..4140b79b0 100644 --- a/docs/development/review-checklist.md +++ b/docs/development/review-checklist.md @@ -102,7 +102,7 @@ And then note where the fix landed. Someone hit the audience gap, felt it, and b ## Merge mechanics -32. **Verify a merge at the consumer: for a squash merge, the merge commit's tree must equal the carried head's tree.** That equality is the **special case, not the test** — it holds only while the base has not moved under the pull request — and the lead above is kept verbatim because `scripts/verify-numbered-rules.js --previous` pins a rule's lead sentence: a rewritten lead is indistinguishable from a foreign rule claiming that number, so a correction to a rule whose *lead* is itself wrong appears to have no in-place mechanism (filed as TASK-198, with the CI error quoted). **That appearance is wrong, and how it is wrong matters more than the claim it replaces.** The pin is mechanically a **60-character prefix** of the lead: `fingerprint()` strips the emphasis markers, collapses whitespace and then takes `.slice(0, 60)`, so it binds those first 60 characters and nothing past them — and **those 60 are counted on the *normalised* lead**, because the stripping and the whitespace collapse both happen *before* the slice. The boundary therefore lands at a different **raw** offset in every lead that carries markup: rule 35's pin ends at raw character 64, rule 41's at 62, rule 13's at 61. That is the trap for anyone re-deriving these counts from raw string lengths — measuring raw yields 2,978 where the pin's own measure yields 2,948. Measured on this head with a paired control — **40 of this file's 44 leads are longer than 60 characters, leaving 2,948 characters of lead text outside the fingerprint**; rewriting *this* rule's lead from character 61 leaves the guard green (`✓ 44 rules … no rule changed its number or its name`, exit 0), while editing the same lead at character 3 reds it with the collision error quoted above. The lead is kept verbatim here regardless — the pin is the convention, and an undocumented reach is not a licence — but the honest statement is that a lead defect past character 60 is *invisible* to the guard rather than forbidden by it, which makes TASK-198's question "should 60 characters be the name at all," not "how do we amend a lead." A merge SHA and a green tick prove the workflow ran; they do not prove that what landed is what was reviewed — carries, rebases and stale-base reverts move code between review and merge, and the merge commit's message will not say so. Under this repo's squash convention the proof is one command per side, **both taken against the base named rather than implied** — `BASE=$(git merge-base )`, then `git diff ^ | git patch-id --stable` against `git diff $BASE | git patch-id --stable`, plus the parent and the author/trailer check. Naming the base is most of the measurement: a `` left to the reader resolves to a local `main`, and a local `main` is the fiction the riders below describe. **Tree equality is the wrong instrument, and its failure has one cause: it is base-relative.** Once main moves under a PR the trees differ *necessarily* while the landing is faithful, so `git rev-parse ^{tree}` against `git rev-parse ^{tree}` fails every faithful landing whose base moved — **four** measured, not three: #1988/#1989/#1992 landed faithfully with differing trees, and so did #1994, whose `a20ea9b3` has tree `3a24f1ab` where the carried head `b2da9bff` has `683663d9` and its own parent has `0de9aac7`. (An earlier version of this rule gave #1994 a *second*, different-sounding reason — "squash-shaped only: a two-parent merge-queue commit whose `^{tree}` is main's tree" — and that was false twice over: `git rev-list --parents -n 1 a20ea9b3` prints **one** parent, so it is not a merge at all, and with the base taken as the merge base the patch-id agrees on both sides like the other three. All 200 of main's most recent commits have exactly one parent; the newest two-parent commit on main is `dc9d849b`, 2026-04-07, 1,766 commits back, so the merge shape that clause described is one this repo stopped producing in April. A rule that gives one failure two unrelated causes is harder to act on than one that gives it one, and the second cause was wrong, which is the class this file exists to catch.) Patch-id compares the *change* rather than the tree, which is what the claim is about; it held for all four (`81ecc062`, `b9feb00c`, `efcec768`, `391ca7f451da`), and it is the same instrument the AX audit reached independently for a refresh carry (entry 65). Fetch the head yourself (`git fetch origin refs/pull//head`) — a reviewer's claim about remote state is as checkable as a code claim — and diff from the base `git merge-base ` returns — the same command named above, and the value actually run on all four of today's landings — because `git diff main...head` against a stale local `main` is a fiction (a checkout whose local `main` trails `origin/main` by double digits is the ordinary state here, and every PR is cut from the fetched `origin/main`). Riders: a **carry** is a *per-file* claim (`git patch-id --stable`, per file), not a whole-PR one, and it is needed only where non-doc code moved between bases — a docs-only addition on top of a cleared head is a re-stamp, so state old→new head and let the reviewer stamp what actually lands, while a **code**-touching move cannot re-attach — a stamp names the head it was taken against, so that clearance is spent, and the author states old→new head and asks for the re-derivation instead of letting a press ride the old stamp; a **test**-only move counts as code-touching rather than a docs re-stamp, because the arms are much of what a clearance is about, and it re-gates in practice (#1986 `5c068c37`→`0cfd8c0f`, two commits inside the guard's own test file); a **rehearsal** binds to a head exactly as a clearance does, one layer out — a guard arm, a mutation run or a probe quoted after the head has moved is a measurement of a file that may no longer exist there, with real numbers attached to a subject that has changed, so re-run the arm at the head you are reporting or state the head it ran at (on #1994's hold, three guard arms were quoted after a third head move, and ARM 1 had measured a file that no longer existed at the then-current head); and know the required-check set before calling anything green or blocked, because every check being green is not the same as the required check passing, and a required check that has not yet reported renders as `BLOCKED` — the ordinary in-flight state, not a verdict. *(Earned: every closure since — #1755 verified as `e938afc8`, tree `b86b05e4` equal to the carried head `ad3aa8d7`'s, parent `2d0ee979`, no foreign trailer — that being the tree check patch-id replaces, whose equality a base move under the PR removes; and the precedent that motivates the rule rather than any one incident: #568's fix regressed twice through a stale-base revert, which is exactly the class the change comparison closes — the merge looked clean, the tick was green, and the fix was gone. **The code-touching rider earned itself in TASK-177's #1990**: a clearance stamped at `83fa2fcd` arrived in the same batch as two other findings — Wren's paging defect and a mutation label **the author's own ledger** caught crediting an arm that no longer witnessed it — plus the `at`/`ms` divergence **Vera measured in that same clearance** and prescribed `ms: mark` for. The author had already moved the head to `000fdbbd` with all three folded, which is why the head had to move at all. The clearance was honest and correct about the head it named, which is precisely why it briefed nobody about the head on the branch; the author asked for the re-derivation and listed what the new head carried, and that list is the cheap half of the obligation.)* +32. **Verify a merge at the consumer: for a squash merge, the merge commit's tree must equal the carried head's tree.** That equality is the **special case, not the test** — it holds only while the base has not moved under the pull request — and the lead above is kept verbatim because `scripts/verify-numbered-rules.js --previous` pins a rule's lead sentence: a rewritten lead is indistinguishable from a foreign rule claiming that number, so a correction to a rule whose *lead* is itself wrong appears to have no in-place mechanism (filed as TASK-198, with the CI error quoted). **That appearance is wrong, and how it is wrong matters more than the claim it replaces.** The pin is mechanically a **60-character prefix** of the lead: `fingerprint()` strips the emphasis markers, collapses whitespace and then takes `.slice(0, 60)`, so it binds those first 60 characters and nothing past them — and **those 60 are counted on the *normalised* lead**, because the stripping and the whitespace collapse both happen *before* the slice. The boundary therefore lands at a different **raw** offset in every lead that carries markup, and in four leads it lands *between* two of them: measured on this head, the pin ends at raw character 60 in 34 of the 40 long leads, at 61 in rule 13 and at 64 in rule 35, while no raw prefix of rules 3, 23, 41 and 42 normalises to exactly 60 at all. The mechanism is the `.trim()` inside `fingerprint()`: a prefix that ends on a space has that space discounted, and one raw character later that space is interior and is counted, so the normalised length can step 59 → 61 straight over the boundary — at raw 60 → 61 in rules 3, 23 and 42, and at raw 62 → 63 in rule 41. That is the trap for anyone re-deriving these counts from raw string lengths — measuring raw yields 2,978 where the pin's own measure yields 2,948. Measured on this head with a paired control — **40 of this file's 44 leads are longer than 60 characters, leaving 2,948 characters of lead text outside the fingerprint**; rewriting *this* rule's lead from character 61 leaves the guard green (`✓ 44 rules … no rule changed its number or its name`, exit 0), while editing the same lead at character 3 reds it with the collision error quoted above. The lead is kept verbatim here regardless — the pin is the convention, and an undocumented reach is not a licence — but the honest statement is that a lead defect past character 60 is *invisible* to the guard rather than forbidden by it, which makes TASK-198's question "should 60 characters be the name at all," not "how do we amend a lead." A merge SHA and a green tick prove the workflow ran; they do not prove that what landed is what was reviewed — carries, rebases and stale-base reverts move code between review and merge, and the merge commit's message will not say so. Under this repo's squash convention the proof is one command per side, **both taken against the base named rather than implied** — `BASE=$(git merge-base )`, then `git diff ^ | git patch-id --stable` against `git diff $BASE | git patch-id --stable`, plus the parent and the author/trailer check. Naming the base is most of the measurement: a `` left to the reader resolves to a local `main`, and a local `main` is the fiction the riders below describe. **Tree equality is the wrong instrument, and its failure has one cause: it is base-relative.** Once main moves under a PR the trees differ *necessarily* while the landing is faithful, so `git rev-parse ^{tree}` against `git rev-parse ^{tree}` fails every faithful landing whose base moved — **four** measured, not three: #1988/#1989/#1992 landed faithfully with differing trees, and so did #1994, whose `a20ea9b3` has tree `3a24f1ab` where the carried head `b2da9bff` has `683663d9` and its own parent has `0de9aac7`. (An earlier version of this rule gave #1994 a *second*, different-sounding reason — "squash-shaped only: a two-parent merge-queue commit whose `^{tree}` is main's tree" — and that was false twice over: `git rev-list --parents -n 1 a20ea9b3` prints **one** parent, so it is not a merge at all, and with the base taken as the merge base the patch-id agrees on both sides like the other three. All 200 of main's most recent commits have exactly one parent; the newest two-parent commit on main is `dc9d849b`, 2026-04-07, 1,766 commits back, so the merge shape that clause described is one this repo stopped producing in April. A rule that gives one failure two unrelated causes is harder to act on than one that gives it one, and the second cause was wrong, which is the class this file exists to catch.) Patch-id compares the *change* rather than the tree, which is what the claim is about; it held for all four (`81ecc062`, `b9feb00c`, `efcec768`, `391ca7f451da`), and it is the same instrument the AX audit reached independently for a refresh carry (entry 65). Fetch the head yourself (`git fetch origin refs/pull//head`) — a reviewer's claim about remote state is as checkable as a code claim — and diff from the base `git merge-base ` returns — the same command named above, and the value actually run on all four of today's landings — because `git diff main...head` against a stale local `main` is a fiction (a checkout whose local `main` trails `origin/main` by double digits is the ordinary state here, and every PR is cut from the fetched `origin/main`). Riders: a **carry** is a *per-file* claim (`git patch-id --stable`, per file), not a whole-PR one, and it is needed only where non-doc code moved between bases — a docs-only addition on top of a cleared head is a re-stamp, so state old→new head and let the reviewer stamp what actually lands, while a **code**-touching move cannot re-attach — a stamp names the head it was taken against, so that clearance is spent, and the author states old→new head and asks for the re-derivation instead of letting a press ride the old stamp; a **test**-only move counts as code-touching rather than a docs re-stamp, because the arms are much of what a clearance is about, and it re-gates in practice (#1986 `5c068c37`→`0cfd8c0f`, two commits inside the guard's own test file); a **rehearsal** binds to a head exactly as a clearance does, one layer out — a guard arm, a mutation run or a probe quoted after the head has moved is a measurement of a file that may no longer exist there, with real numbers attached to a subject that has changed, so re-run the arm at the head you are reporting or state the head it ran at (on #1994's hold, three guard arms were quoted after a third head move, and ARM 1 had measured a file that no longer existed at the then-current head); and know the required-check set before calling anything green or blocked, because every check being green is not the same as the required check passing, and a required check that has not yet reported renders as `BLOCKED` — the ordinary in-flight state, not a verdict. *(Earned: every closure since — #1755 verified as `e938afc8`, tree `b86b05e4` equal to the carried head `ad3aa8d7`'s, parent `2d0ee979`, no foreign trailer — that being the tree check patch-id replaces, whose equality a base move under the PR removes; and the precedent that motivates the rule rather than any one incident: #568's fix regressed twice through a stale-base revert, which is exactly the class the change comparison closes — the merge looked clean, the tick was green, and the fix was gone. **The code-touching rider earned itself in TASK-177's #1990**: a clearance stamped at `83fa2fcd` arrived in the same batch as two other findings — Wren's paging defect and a mutation label **the author's own ledger** caught crediting an arm that no longer witnessed it — plus the `at`/`ms` divergence **Vera measured in that same clearance** and prescribed `ms: mark` for. The author had already moved the head to `000fdbbd` with all three folded, which is why the head had to move at all. The clearance was honest and correct about the head it named, which is precisely why it briefed nobody about the head on the branch; the author asked for the re-derivation and listed what the new head carried, and that list is the cheap half of the obligation.)* ## Enumerating a duplicated value From 7da2f44344040bbbabca4f5aafed226e3b3080a6 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Tue, 29 Sep 2026 11:35:37 -0700 Subject: [PATCH 8/9] docs(checklist): state the pin's raw offsets as a set, and the renumber clause's real cause MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ux-lead's docs gate on the previous head measured three false sentences. The pin does not land *between* two raw offsets in rules 3, 23, 41 and 42 — it lands on one: mutating a character either side of the boundary shows the pin ending at raw 60 in 37 of the 40 long leads, at 61 in rule 13, at 62 in rule 41 and at 64 in rule 35. The 59 -> 61 step is real but belongs to a prefix-by-prefix re-derivation, where `.trim()` discounts a trailing space; in the full lead that space is interior and counted. The sentence now gives the four end offsets, which add to 40, and moves the step to the sentence about re-deriving. "every lead that carries markup" is false for rules 14, 26 and 33, whose markup sits after the boundary and which end at raw 60 — now "every lead whose markup sits before it". Rule 43 attributed the 42/43 -> 43/44 discrepancy to #2008 merging between the gate and the press. It did not: #2008 merged at 15:35:29Z, both clearing gates are at `b32428b9` (15:39 and 15:41), and that head's file already reads 43 and 44. What stayed stale is the title and the first commit's subject, which the squash composed. Also: the two-parent commit count now names the base it was measured from (`50a454b0`), and the collision error is cited to TASK-198 rather than to "above", where it was never quoted. --- docs/development/review-checklist.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/development/review-checklist.md b/docs/development/review-checklist.md index 4140b79b0..e819ac47d 100644 --- a/docs/development/review-checklist.md +++ b/docs/development/review-checklist.md @@ -102,7 +102,7 @@ And then note where the fix landed. Someone hit the audience gap, felt it, and b ## Merge mechanics -32. **Verify a merge at the consumer: for a squash merge, the merge commit's tree must equal the carried head's tree.** That equality is the **special case, not the test** — it holds only while the base has not moved under the pull request — and the lead above is kept verbatim because `scripts/verify-numbered-rules.js --previous` pins a rule's lead sentence: a rewritten lead is indistinguishable from a foreign rule claiming that number, so a correction to a rule whose *lead* is itself wrong appears to have no in-place mechanism (filed as TASK-198, with the CI error quoted). **That appearance is wrong, and how it is wrong matters more than the claim it replaces.** The pin is mechanically a **60-character prefix** of the lead: `fingerprint()` strips the emphasis markers, collapses whitespace and then takes `.slice(0, 60)`, so it binds those first 60 characters and nothing past them — and **those 60 are counted on the *normalised* lead**, because the stripping and the whitespace collapse both happen *before* the slice. The boundary therefore lands at a different **raw** offset in every lead that carries markup, and in four leads it lands *between* two of them: measured on this head, the pin ends at raw character 60 in 34 of the 40 long leads, at 61 in rule 13 and at 64 in rule 35, while no raw prefix of rules 3, 23, 41 and 42 normalises to exactly 60 at all. The mechanism is the `.trim()` inside `fingerprint()`: a prefix that ends on a space has that space discounted, and one raw character later that space is interior and is counted, so the normalised length can step 59 → 61 straight over the boundary — at raw 60 → 61 in rules 3, 23 and 42, and at raw 62 → 63 in rule 41. That is the trap for anyone re-deriving these counts from raw string lengths — measuring raw yields 2,978 where the pin's own measure yields 2,948. Measured on this head with a paired control — **40 of this file's 44 leads are longer than 60 characters, leaving 2,948 characters of lead text outside the fingerprint**; rewriting *this* rule's lead from character 61 leaves the guard green (`✓ 44 rules … no rule changed its number or its name`, exit 0), while editing the same lead at character 3 reds it with the collision error quoted above. The lead is kept verbatim here regardless — the pin is the convention, and an undocumented reach is not a licence — but the honest statement is that a lead defect past character 60 is *invisible* to the guard rather than forbidden by it, which makes TASK-198's question "should 60 characters be the name at all," not "how do we amend a lead." A merge SHA and a green tick prove the workflow ran; they do not prove that what landed is what was reviewed — carries, rebases and stale-base reverts move code between review and merge, and the merge commit's message will not say so. Under this repo's squash convention the proof is one command per side, **both taken against the base named rather than implied** — `BASE=$(git merge-base )`, then `git diff ^ | git patch-id --stable` against `git diff $BASE | git patch-id --stable`, plus the parent and the author/trailer check. Naming the base is most of the measurement: a `` left to the reader resolves to a local `main`, and a local `main` is the fiction the riders below describe. **Tree equality is the wrong instrument, and its failure has one cause: it is base-relative.** Once main moves under a PR the trees differ *necessarily* while the landing is faithful, so `git rev-parse ^{tree}` against `git rev-parse ^{tree}` fails every faithful landing whose base moved — **four** measured, not three: #1988/#1989/#1992 landed faithfully with differing trees, and so did #1994, whose `a20ea9b3` has tree `3a24f1ab` where the carried head `b2da9bff` has `683663d9` and its own parent has `0de9aac7`. (An earlier version of this rule gave #1994 a *second*, different-sounding reason — "squash-shaped only: a two-parent merge-queue commit whose `^{tree}` is main's tree" — and that was false twice over: `git rev-list --parents -n 1 a20ea9b3` prints **one** parent, so it is not a merge at all, and with the base taken as the merge base the patch-id agrees on both sides like the other three. All 200 of main's most recent commits have exactly one parent; the newest two-parent commit on main is `dc9d849b`, 2026-04-07, 1,766 commits back, so the merge shape that clause described is one this repo stopped producing in April. A rule that gives one failure two unrelated causes is harder to act on than one that gives it one, and the second cause was wrong, which is the class this file exists to catch.) Patch-id compares the *change* rather than the tree, which is what the claim is about; it held for all four (`81ecc062`, `b9feb00c`, `efcec768`, `391ca7f451da`), and it is the same instrument the AX audit reached independently for a refresh carry (entry 65). Fetch the head yourself (`git fetch origin refs/pull//head`) — a reviewer's claim about remote state is as checkable as a code claim — and diff from the base `git merge-base ` returns — the same command named above, and the value actually run on all four of today's landings — because `git diff main...head` against a stale local `main` is a fiction (a checkout whose local `main` trails `origin/main` by double digits is the ordinary state here, and every PR is cut from the fetched `origin/main`). Riders: a **carry** is a *per-file* claim (`git patch-id --stable`, per file), not a whole-PR one, and it is needed only where non-doc code moved between bases — a docs-only addition on top of a cleared head is a re-stamp, so state old→new head and let the reviewer stamp what actually lands, while a **code**-touching move cannot re-attach — a stamp names the head it was taken against, so that clearance is spent, and the author states old→new head and asks for the re-derivation instead of letting a press ride the old stamp; a **test**-only move counts as code-touching rather than a docs re-stamp, because the arms are much of what a clearance is about, and it re-gates in practice (#1986 `5c068c37`→`0cfd8c0f`, two commits inside the guard's own test file); a **rehearsal** binds to a head exactly as a clearance does, one layer out — a guard arm, a mutation run or a probe quoted after the head has moved is a measurement of a file that may no longer exist there, with real numbers attached to a subject that has changed, so re-run the arm at the head you are reporting or state the head it ran at (on #1994's hold, three guard arms were quoted after a third head move, and ARM 1 had measured a file that no longer existed at the then-current head); and know the required-check set before calling anything green or blocked, because every check being green is not the same as the required check passing, and a required check that has not yet reported renders as `BLOCKED` — the ordinary in-flight state, not a verdict. *(Earned: every closure since — #1755 verified as `e938afc8`, tree `b86b05e4` equal to the carried head `ad3aa8d7`'s, parent `2d0ee979`, no foreign trailer — that being the tree check patch-id replaces, whose equality a base move under the PR removes; and the precedent that motivates the rule rather than any one incident: #568's fix regressed twice through a stale-base revert, which is exactly the class the change comparison closes — the merge looked clean, the tick was green, and the fix was gone. **The code-touching rider earned itself in TASK-177's #1990**: a clearance stamped at `83fa2fcd` arrived in the same batch as two other findings — Wren's paging defect and a mutation label **the author's own ledger** caught crediting an arm that no longer witnessed it — plus the `at`/`ms` divergence **Vera measured in that same clearance** and prescribed `ms: mark` for. The author had already moved the head to `000fdbbd` with all three folded, which is why the head had to move at all. The clearance was honest and correct about the head it named, which is precisely why it briefed nobody about the head on the branch; the author asked for the re-derivation and listed what the new head carried, and that list is the cheap half of the obligation.)* +32. **Verify a merge at the consumer: for a squash merge, the merge commit's tree must equal the carried head's tree.** That equality is the **special case, not the test** — it holds only while the base has not moved under the pull request — and the lead above is kept verbatim because `scripts/verify-numbered-rules.js --previous` pins a rule's lead sentence: a rewritten lead is indistinguishable from a foreign rule claiming that number, so a correction to a rule whose *lead* is itself wrong appears to have no in-place mechanism (filed as TASK-198, with the CI error quoted). **That appearance is wrong, and how it is wrong matters more than the claim it replaces.** The pin is mechanically a **60-character prefix** of the lead: `fingerprint()` strips the emphasis markers, collapses whitespace and then takes `.slice(0, 60)`, so it binds those first 60 characters and nothing past them — and **those 60 are counted on the *normalised* lead**, because the stripping and the whitespace collapse both happen *before* the slice. The boundary therefore lands at a different **raw** offset in every lead whose markup sits *before* it, and the offsets are worth stating as a set rather than by example: on this head the pin ends at raw character 60 in 37 of the 40 long leads, at 61 in rule 13, at 62 in rule 41 and at 64 in rule 35 — those four counts add to 40, so the whole population can be checked. (Method: mutate one character either side of the boundary and run the guard with `--previous`; an edit to the last counted character leaves it green, and one character earlier reds it.) What misleads a re-derivation is the `.trim()` inside `fingerprint()` read **prefix by prefix**: a prefix that ends on a space has that space discounted, and one raw character later that space is interior and is counted, so the normalised length can step 59 → 61 and appear to step *over* the boundary — at raw 60 → 61 in rules 3, 23 and 42, and at raw 62 → 63 in rule 41. In the **full** lead that interior space is counted, which is why those leads end at 60 and 62 rather than skipping the boundary at all; the step belongs to the prefix-by-prefix re-derivation, and not to where the pin lands. That is the trap for anyone re-deriving these counts from raw string lengths — measuring raw yields 2,978 where the pin’s own measure yields 2,948. Measured on this head with a paired control — **40 of this file's 44 leads are longer than 60 characters, leaving 2,948 characters of lead text outside the fingerprint**; rewriting *this* rule's lead from character 61 leaves the guard green (`✓ 44 rules … no rule changed its number or its name`, exit 0), while editing the same lead at character 3 reds it with the collision error quoted on TASK-198. The lead is kept verbatim here regardless — the pin is the convention, and an undocumented reach is not a licence — but the honest statement is that a lead defect past character 60 is *invisible* to the guard rather than forbidden by it, which makes TASK-198's question "should 60 characters be the name at all," not "how do we amend a lead." A merge SHA and a green tick prove the workflow ran; they do not prove that what landed is what was reviewed — carries, rebases and stale-base reverts move code between review and merge, and the merge commit's message will not say so. Under this repo's squash convention the proof is one command per side, **both taken against the base named rather than implied** — `BASE=$(git merge-base )`, then `git diff ^ | git patch-id --stable` against `git diff $BASE | git patch-id --stable`, plus the parent and the author/trailer check. Naming the base is most of the measurement: a `` left to the reader resolves to a local `main`, and a local `main` is the fiction the riders below describe. **Tree equality is the wrong instrument, and its failure has one cause: it is base-relative.** Once main moves under a PR the trees differ *necessarily* while the landing is faithful, so `git rev-parse ^{tree}` against `git rev-parse ^{tree}` fails every faithful landing whose base moved — **four** measured, not three: #1988/#1989/#1992 landed faithfully with differing trees, and so did #1994, whose `a20ea9b3` has tree `3a24f1ab` where the carried head `b2da9bff` has `683663d9` and its own parent has `0de9aac7`. (An earlier version of this rule gave #1994 a *second*, different-sounding reason — "squash-shaped only: a two-parent merge-queue commit whose `^{tree}` is main's tree" — and that was false twice over: `git rev-list --parents -n 1 a20ea9b3` prints **one** parent, so it is not a merge at all, and with the base taken as the merge base the patch-id agrees on both sides like the other three. All 200 of main's most recent commits have exactly one parent; the newest two-parent commit on main at the base this was measured from (`50a454b0`) is `dc9d849b`, 2026-04-07, 1,766 commits back, so the merge shape that clause described is one this repo stopped producing in April. A rule that gives one failure two unrelated causes is harder to act on than one that gives it one, and the second cause was wrong, which is the class this file exists to catch.) Patch-id compares the *change* rather than the tree, which is what the claim is about; it held for all four (`81ecc062`, `b9feb00c`, `efcec768`, `391ca7f451da`), and it is the same instrument the AX audit reached independently for a refresh carry (entry 65). Fetch the head yourself (`git fetch origin refs/pull//head`) — a reviewer's claim about remote state is as checkable as a code claim — and diff from the base `git merge-base ` returns — the same command named above, and the value actually run on all four of today's landings — because `git diff main...head` against a stale local `main` is a fiction (a checkout whose local `main` trails `origin/main` by double digits is the ordinary state here, and every PR is cut from the fetched `origin/main`). Riders: a **carry** is a *per-file* claim (`git patch-id --stable`, per file), not a whole-PR one, and it is needed only where non-doc code moved between bases — a docs-only addition on top of a cleared head is a re-stamp, so state old→new head and let the reviewer stamp what actually lands, while a **code**-touching move cannot re-attach — a stamp names the head it was taken against, so that clearance is spent, and the author states old→new head and asks for the re-derivation instead of letting a press ride the old stamp; a **test**-only move counts as code-touching rather than a docs re-stamp, because the arms are much of what a clearance is about, and it re-gates in practice (#1986 `5c068c37`→`0cfd8c0f`, two commits inside the guard's own test file); a **rehearsal** binds to a head exactly as a clearance does, one layer out — a guard arm, a mutation run or a probe quoted after the head has moved is a measurement of a file that may no longer exist there, with real numbers attached to a subject that has changed, so re-run the arm at the head you are reporting or state the head it ran at (on #1994's hold, three guard arms were quoted after a third head move, and ARM 1 had measured a file that no longer existed at the then-current head); and know the required-check set before calling anything green or blocked, because every check being green is not the same as the required check passing, and a required check that has not yet reported renders as `BLOCKED` — the ordinary in-flight state, not a verdict. *(Earned: every closure since — #1755 verified as `e938afc8`, tree `b86b05e4` equal to the carried head `ad3aa8d7`'s, parent `2d0ee979`, no foreign trailer — that being the tree check patch-id replaces, whose equality a base move under the PR removes; and the precedent that motivates the rule rather than any one incident: #568's fix regressed twice through a stale-base revert, which is exactly the class the change comparison closes — the merge looked clean, the tick was green, and the fix was gone. **The code-touching rider earned itself in TASK-177's #1990**: a clearance stamped at `83fa2fcd` arrived in the same batch as two other findings — Wren's paging defect and a mutation label **the author's own ledger** caught crediting an arm that no longer witnessed it — plus the `at`/`ms` divergence **Vera measured in that same clearance** and prescribed `ms: mark` for. The author had already moved the head to `000fdbbd` with all three folded, which is why the head had to move at all. The clearance was honest and correct about the head it named, which is precisely why it briefed nobody about the head on the branch; the author asked for the re-derivation and listed what the new head carried, and that list is the cheap half of the obligation.)* ## Enumerating a duplicated value @@ -154,7 +154,7 @@ And then note where the fix landed. Someone hit the audience gap, felt it, and b ## The merge queue -43. **A queued PR refuses every push, and that refusal is what keeps the merged head equal to the queued head.** Once a pull request is in the merge queue, GitHub rejects any push to its branch — `GH006: Protected branch update failed for refs/heads/ … branches that are queued for merging cannot be updated. To modify this branch, dequeue the associated pull request.` Read it as a mechanism rather than an obstacle: the queue merges the head it saw, so a delta arriving after queue entry cannot silently ride a stale clearance into main, and rule 32's change comparison is then guaranteed rather than lucky. It is not a clearance in itself, though — that the *queued* head is the *gated* head is still the press's job to check, which is rule 44's question. Land a late delta as a **follow-up PR** based on the merged main, showing per-file fidelity is empty (`git rebase --onto origin/main `, then `git patch-id --stable` per file); the costlier alternative is to dequeue, apply, re-gate and re-queue, which spends every stamp bound to the head. The follow-up is **ungated** until it is gated at its own head: cite the pre-rebase commit as provenance, by **full** sha, since a short sha will not fetch and a provenance citation that gets read as a clearance is the defect rule 44 exists for. *(Earned: TASK-180's #1984 — ux-lead asked for the `%` fold at 04:48:45Z and the PR was queued at 04:50:20Z, 95 seconds later, so the fold could not land on that head at all and became #1988: one catalog line, a rebase and two gates. The queue had already merged the gated head faithfully — squash `f381b5aa` against `7f171637`, the three TASK-180 files byte-identical — so the pressed artifact was the reviewed artifact, which is the outcome the refusal buys. Before this entry existed the operator-facing half was documented nowhere else, and the count is **per string, not per union**: `merge queue` appeared in exactly one tracked file, `.github/workflows/tests.yml:13`, whose surrounding lines are about the `merge_group` trigger rather than the push refusal, while `GH006` and `queued for merging` appeared in **no** tracked file at all — `git grep -l -F` for the three strings over the whole tree on main returns 0, 0 and 1. Read those as the state of main *before* this rule landed, because the rule quotes all three: at this head it is the second file for every one of them, and a grep for `GH006` alone returning nothing is that pre-landing state and not a rule that has gone stale. And the *number* is a queue position, not a property of the text: #2000's squash subject announces "rule 42 (a queued PR refuses every push) and rule 43 (a clearance …)" while the file it landed carries those two as **43** and **44**, because #2008 merged its own rule 42 between the gate and the press — so a reader citing the log gets both numbers wrong for two rules whose entire subject is that a record has to name the thing it claims. Read the number at the head you are reading; a sibling PR can renumber it between the gate and the land.)* +43. **A queued PR refuses every push, and that refusal is what keeps the merged head equal to the queued head.** Once a pull request is in the merge queue, GitHub rejects any push to its branch — `GH006: Protected branch update failed for refs/heads/ … branches that are queued for merging cannot be updated. To modify this branch, dequeue the associated pull request.` Read it as a mechanism rather than an obstacle: the queue merges the head it saw, so a delta arriving after queue entry cannot silently ride a stale clearance into main, and rule 32's change comparison is then guaranteed rather than lucky. It is not a clearance in itself, though — that the *queued* head is the *gated* head is still the press's job to check, which is rule 44's question. Land a late delta as a **follow-up PR** based on the merged main, showing per-file fidelity is empty (`git rebase --onto origin/main `, then `git patch-id --stable` per file); the costlier alternative is to dequeue, apply, re-gate and re-queue, which spends every stamp bound to the head. The follow-up is **ungated** until it is gated at its own head: cite the pre-rebase commit as provenance, by **full** sha, since a short sha will not fetch and a provenance citation that gets read as a clearance is the defect rule 44 exists for. *(Earned: TASK-180's #1984 — ux-lead asked for the `%` fold at 04:48:45Z and the PR was queued at 04:50:20Z, 95 seconds later, so the fold could not land on that head at all and became #1988: one catalog line, a rebase and two gates. The queue had already merged the gated head faithfully — squash `f381b5aa` against `7f171637`, the three TASK-180 files byte-identical — so the pressed artifact was the reviewed artifact, which is the outcome the refusal buys. Before this entry existed the operator-facing half was documented nowhere else, and the count is **per string, not per union**: `merge queue` appeared in exactly one tracked file, `.github/workflows/tests.yml:13`, whose surrounding lines are about the `merge_group` trigger rather than the push refusal, while `GH006` and `queued for merging` appeared in **no** tracked file at all — `git grep -l -F` for the three strings over the whole tree on main returns 0, 0 and 1. Read those as the state of main *before* this rule landed, because the rule quotes all three: at this head it is the second file for every one of them, and a grep for `GH006` alone returning nothing is that pre-landing state and not a rule that has gone stale. And the *number* is a queue position, not a property of the text: #2000's squash subject announces "rule 42 (a queued PR refuses every push) and rule 43 (a clearance …)" while the file it landed carries those two as **43** and **44**, because #2008 merged its own rule 42 **after** the first gates: the head was renumbered and re-gated at `b32428b9`, and that head’s file already reads 43 and 44, at lines 157 and 161 — what still said 42 and 43 is the pull request’s title and its first commit’s subject, which the squash composes. So a reader citing the log gets both numbers wrong for two rules whose entire subject is that a record has to name the thing it claims. Read the number at the head you are reading; a sibling PR can renumber it between the gate and the land.)* ## What a clearance can bind From 34ee62a56566451d6e9ad0e9053bd497b0f421d8 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Tue, 29 Sep 2026 11:39:16 -0700 Subject: [PATCH 9/9] docs(checklist): the mutation direction was inverted, and a re-derived count is not a control sprint-review's second gate found one sentence false: the method this paragraph hands a reader. "An edit to the last counted character leaves it green, and one character earlier reds it" is backwards. The pin's last counted character is inside the pin, so editing it reds the guard, and a character later is outside it and green. Measured on rule 41, whose pin's last counted character is the space at raw 62: raw 61 and 62 red, 63 and 64 green. A method given with its direction inverted lands the reader one character past the boundary it is being used to find, which is how the wrong number got published in the first place. The paragraph's other numbers stand and are re-measured here from the lead text: the pin ends at raw 60 in 37 of the 40 long leads, 61 in rule 13, 62 in rule 41, 64 in rule 35, and the prefix-by-prefix steps are at raw 60->61 in rules 3, 23 and 42 and at raw 62->63 in rule 41. Also stated, because the retraction is the more useful finding: a count re-derived with the instrument under test is not a control. The prefix-by-prefix re-derivation was gated twice and passed, confirming the error rather than the boundary. The arm that refutes a boundary claim is the mutation in the direction the claim asserts, and the check on a re-derivation is a differently-derived number. --- docs/development/review-checklist.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/development/review-checklist.md b/docs/development/review-checklist.md index e819ac47d..2e1f27879 100644 --- a/docs/development/review-checklist.md +++ b/docs/development/review-checklist.md @@ -102,7 +102,7 @@ And then note where the fix landed. Someone hit the audience gap, felt it, and b ## Merge mechanics -32. **Verify a merge at the consumer: for a squash merge, the merge commit's tree must equal the carried head's tree.** That equality is the **special case, not the test** — it holds only while the base has not moved under the pull request — and the lead above is kept verbatim because `scripts/verify-numbered-rules.js --previous` pins a rule's lead sentence: a rewritten lead is indistinguishable from a foreign rule claiming that number, so a correction to a rule whose *lead* is itself wrong appears to have no in-place mechanism (filed as TASK-198, with the CI error quoted). **That appearance is wrong, and how it is wrong matters more than the claim it replaces.** The pin is mechanically a **60-character prefix** of the lead: `fingerprint()` strips the emphasis markers, collapses whitespace and then takes `.slice(0, 60)`, so it binds those first 60 characters and nothing past them — and **those 60 are counted on the *normalised* lead**, because the stripping and the whitespace collapse both happen *before* the slice. The boundary therefore lands at a different **raw** offset in every lead whose markup sits *before* it, and the offsets are worth stating as a set rather than by example: on this head the pin ends at raw character 60 in 37 of the 40 long leads, at 61 in rule 13, at 62 in rule 41 and at 64 in rule 35 — those four counts add to 40, so the whole population can be checked. (Method: mutate one character either side of the boundary and run the guard with `--previous`; an edit to the last counted character leaves it green, and one character earlier reds it.) What misleads a re-derivation is the `.trim()` inside `fingerprint()` read **prefix by prefix**: a prefix that ends on a space has that space discounted, and one raw character later that space is interior and is counted, so the normalised length can step 59 → 61 and appear to step *over* the boundary — at raw 60 → 61 in rules 3, 23 and 42, and at raw 62 → 63 in rule 41. In the **full** lead that interior space is counted, which is why those leads end at 60 and 62 rather than skipping the boundary at all; the step belongs to the prefix-by-prefix re-derivation, and not to where the pin lands. That is the trap for anyone re-deriving these counts from raw string lengths — measuring raw yields 2,978 where the pin’s own measure yields 2,948. Measured on this head with a paired control — **40 of this file's 44 leads are longer than 60 characters, leaving 2,948 characters of lead text outside the fingerprint**; rewriting *this* rule's lead from character 61 leaves the guard green (`✓ 44 rules … no rule changed its number or its name`, exit 0), while editing the same lead at character 3 reds it with the collision error quoted on TASK-198. The lead is kept verbatim here regardless — the pin is the convention, and an undocumented reach is not a licence — but the honest statement is that a lead defect past character 60 is *invisible* to the guard rather than forbidden by it, which makes TASK-198's question "should 60 characters be the name at all," not "how do we amend a lead." A merge SHA and a green tick prove the workflow ran; they do not prove that what landed is what was reviewed — carries, rebases and stale-base reverts move code between review and merge, and the merge commit's message will not say so. Under this repo's squash convention the proof is one command per side, **both taken against the base named rather than implied** — `BASE=$(git merge-base )`, then `git diff ^ | git patch-id --stable` against `git diff $BASE | git patch-id --stable`, plus the parent and the author/trailer check. Naming the base is most of the measurement: a `` left to the reader resolves to a local `main`, and a local `main` is the fiction the riders below describe. **Tree equality is the wrong instrument, and its failure has one cause: it is base-relative.** Once main moves under a PR the trees differ *necessarily* while the landing is faithful, so `git rev-parse ^{tree}` against `git rev-parse ^{tree}` fails every faithful landing whose base moved — **four** measured, not three: #1988/#1989/#1992 landed faithfully with differing trees, and so did #1994, whose `a20ea9b3` has tree `3a24f1ab` where the carried head `b2da9bff` has `683663d9` and its own parent has `0de9aac7`. (An earlier version of this rule gave #1994 a *second*, different-sounding reason — "squash-shaped only: a two-parent merge-queue commit whose `^{tree}` is main's tree" — and that was false twice over: `git rev-list --parents -n 1 a20ea9b3` prints **one** parent, so it is not a merge at all, and with the base taken as the merge base the patch-id agrees on both sides like the other three. All 200 of main's most recent commits have exactly one parent; the newest two-parent commit on main at the base this was measured from (`50a454b0`) is `dc9d849b`, 2026-04-07, 1,766 commits back, so the merge shape that clause described is one this repo stopped producing in April. A rule that gives one failure two unrelated causes is harder to act on than one that gives it one, and the second cause was wrong, which is the class this file exists to catch.) Patch-id compares the *change* rather than the tree, which is what the claim is about; it held for all four (`81ecc062`, `b9feb00c`, `efcec768`, `391ca7f451da`), and it is the same instrument the AX audit reached independently for a refresh carry (entry 65). Fetch the head yourself (`git fetch origin refs/pull//head`) — a reviewer's claim about remote state is as checkable as a code claim — and diff from the base `git merge-base ` returns — the same command named above, and the value actually run on all four of today's landings — because `git diff main...head` against a stale local `main` is a fiction (a checkout whose local `main` trails `origin/main` by double digits is the ordinary state here, and every PR is cut from the fetched `origin/main`). Riders: a **carry** is a *per-file* claim (`git patch-id --stable`, per file), not a whole-PR one, and it is needed only where non-doc code moved between bases — a docs-only addition on top of a cleared head is a re-stamp, so state old→new head and let the reviewer stamp what actually lands, while a **code**-touching move cannot re-attach — a stamp names the head it was taken against, so that clearance is spent, and the author states old→new head and asks for the re-derivation instead of letting a press ride the old stamp; a **test**-only move counts as code-touching rather than a docs re-stamp, because the arms are much of what a clearance is about, and it re-gates in practice (#1986 `5c068c37`→`0cfd8c0f`, two commits inside the guard's own test file); a **rehearsal** binds to a head exactly as a clearance does, one layer out — a guard arm, a mutation run or a probe quoted after the head has moved is a measurement of a file that may no longer exist there, with real numbers attached to a subject that has changed, so re-run the arm at the head you are reporting or state the head it ran at (on #1994's hold, three guard arms were quoted after a third head move, and ARM 1 had measured a file that no longer existed at the then-current head); and know the required-check set before calling anything green or blocked, because every check being green is not the same as the required check passing, and a required check that has not yet reported renders as `BLOCKED` — the ordinary in-flight state, not a verdict. *(Earned: every closure since — #1755 verified as `e938afc8`, tree `b86b05e4` equal to the carried head `ad3aa8d7`'s, parent `2d0ee979`, no foreign trailer — that being the tree check patch-id replaces, whose equality a base move under the PR removes; and the precedent that motivates the rule rather than any one incident: #568's fix regressed twice through a stale-base revert, which is exactly the class the change comparison closes — the merge looked clean, the tick was green, and the fix was gone. **The code-touching rider earned itself in TASK-177's #1990**: a clearance stamped at `83fa2fcd` arrived in the same batch as two other findings — Wren's paging defect and a mutation label **the author's own ledger** caught crediting an arm that no longer witnessed it — plus the `at`/`ms` divergence **Vera measured in that same clearance** and prescribed `ms: mark` for. The author had already moved the head to `000fdbbd` with all three folded, which is why the head had to move at all. The clearance was honest and correct about the head it named, which is precisely why it briefed nobody about the head on the branch; the author asked for the re-derivation and listed what the new head carried, and that list is the cheap half of the obligation.)* +32. **Verify a merge at the consumer: for a squash merge, the merge commit's tree must equal the carried head's tree.** That equality is the **special case, not the test** — it holds only while the base has not moved under the pull request — and the lead above is kept verbatim because `scripts/verify-numbered-rules.js --previous` pins a rule's lead sentence: a rewritten lead is indistinguishable from a foreign rule claiming that number, so a correction to a rule whose *lead* is itself wrong appears to have no in-place mechanism (filed as TASK-198, with the CI error quoted). **That appearance is wrong, and how it is wrong matters more than the claim it replaces.** The pin is mechanically a **60-character prefix** of the lead: `fingerprint()` strips the emphasis markers, collapses whitespace and then takes `.slice(0, 60)`, so it binds those first 60 characters and nothing past them — and **those 60 are counted on the *normalised* lead**, because the stripping and the whitespace collapse both happen *before* the slice. The boundary therefore lands at a different **raw** offset in every lead whose markup sits *before* it, and the offsets are worth stating as a set rather than by example: on this head the pin ends at raw character 60 in 37 of the 40 long leads, at 61 in rule 13, at 62 in rule 41 and at 64 in rule 35 — those four counts add to 40, so the whole population can be checked. (Method: mutate one character at the boundary and re-run the guard with `--previous`. **An edit to the last counted character reds it, and an edit one character later leaves it green** — measured on rule 41, whose pin's last counted character is the space at raw 62: replacing raw 61 or raw 62 reds the guard with the collision error, and replacing raw 63 or raw 64 leaves it green. This paragraph carried that direction inverted, which is a method for landing one character *past* the boundary it is being used to find.) What misleads a re-derivation is the `.trim()` inside `fingerprint()` read **prefix by prefix**: a prefix that ends on a space has that space discounted, and one raw character later that space is interior and is counted, so the normalised length can step 59 → 61 and appear to step *over* the boundary — at raw 60 → 61 in rules 3, 23 and 42, and at raw 62 → 63 in rule 41. In the **full** lead that interior space is counted, which is why those leads end at 60 and 62 rather than skipping the boundary at all; the step belongs to the prefix-by-prefix re-derivation, and not to where the pin lands. **A count re-derived with the instrument under test is not a control**: a reviewer who had twice gated the prefix-by-prefix version of these numbers confirmed the error rather than the boundary, and the sentence above that gives the mutation direction was the wording that reproduced it — so the arm to run is the mutation in the direction the claim asserts, and the check on a re-derivation is a differently-derived number, not a second reader of the same one. That is the trap for anyone re-deriving these counts from raw string lengths — measuring raw yields 2,978 where the pin’s own measure yields 2,948. Measured on this head with a paired control — **40 of this file's 44 leads are longer than 60 characters, leaving 2,948 characters of lead text outside the fingerprint**; rewriting *this* rule's lead from character 61 leaves the guard green (`✓ 44 rules … no rule changed its number or its name`, exit 0), while editing the same lead at character 3 reds it with the collision error quoted on TASK-198. The lead is kept verbatim here regardless — the pin is the convention, and an undocumented reach is not a licence — but the honest statement is that a lead defect past character 60 is *invisible* to the guard rather than forbidden by it, which makes TASK-198's question "should 60 characters be the name at all," not "how do we amend a lead." A merge SHA and a green tick prove the workflow ran; they do not prove that what landed is what was reviewed — carries, rebases and stale-base reverts move code between review and merge, and the merge commit's message will not say so. Under this repo's squash convention the proof is one command per side, **both taken against the base named rather than implied** — `BASE=$(git merge-base )`, then `git diff ^ | git patch-id --stable` against `git diff $BASE | git patch-id --stable`, plus the parent and the author/trailer check. Naming the base is most of the measurement: a `` left to the reader resolves to a local `main`, and a local `main` is the fiction the riders below describe. **Tree equality is the wrong instrument, and its failure has one cause: it is base-relative.** Once main moves under a PR the trees differ *necessarily* while the landing is faithful, so `git rev-parse ^{tree}` against `git rev-parse ^{tree}` fails every faithful landing whose base moved — **four** measured, not three: #1988/#1989/#1992 landed faithfully with differing trees, and so did #1994, whose `a20ea9b3` has tree `3a24f1ab` where the carried head `b2da9bff` has `683663d9` and its own parent has `0de9aac7`. (An earlier version of this rule gave #1994 a *second*, different-sounding reason — "squash-shaped only: a two-parent merge-queue commit whose `^{tree}` is main's tree" — and that was false twice over: `git rev-list --parents -n 1 a20ea9b3` prints **one** parent, so it is not a merge at all, and with the base taken as the merge base the patch-id agrees on both sides like the other three. All 200 of main's most recent commits have exactly one parent; the newest two-parent commit on main at the base this was measured from (`50a454b0`) is `dc9d849b`, 2026-04-07, 1,766 commits back, so the merge shape that clause described is one this repo stopped producing in April. A rule that gives one failure two unrelated causes is harder to act on than one that gives it one, and the second cause was wrong, which is the class this file exists to catch.) Patch-id compares the *change* rather than the tree, which is what the claim is about; it held for all four (`81ecc062`, `b9feb00c`, `efcec768`, `391ca7f451da`), and it is the same instrument the AX audit reached independently for a refresh carry (entry 65). Fetch the head yourself (`git fetch origin refs/pull//head`) — a reviewer's claim about remote state is as checkable as a code claim — and diff from the base `git merge-base ` returns — the same command named above, and the value actually run on all four of today's landings — because `git diff main...head` against a stale local `main` is a fiction (a checkout whose local `main` trails `origin/main` by double digits is the ordinary state here, and every PR is cut from the fetched `origin/main`). Riders: a **carry** is a *per-file* claim (`git patch-id --stable`, per file), not a whole-PR one, and it is needed only where non-doc code moved between bases — a docs-only addition on top of a cleared head is a re-stamp, so state old→new head and let the reviewer stamp what actually lands, while a **code**-touching move cannot re-attach — a stamp names the head it was taken against, so that clearance is spent, and the author states old→new head and asks for the re-derivation instead of letting a press ride the old stamp; a **test**-only move counts as code-touching rather than a docs re-stamp, because the arms are much of what a clearance is about, and it re-gates in practice (#1986 `5c068c37`→`0cfd8c0f`, two commits inside the guard's own test file); a **rehearsal** binds to a head exactly as a clearance does, one layer out — a guard arm, a mutation run or a probe quoted after the head has moved is a measurement of a file that may no longer exist there, with real numbers attached to a subject that has changed, so re-run the arm at the head you are reporting or state the head it ran at (on #1994's hold, three guard arms were quoted after a third head move, and ARM 1 had measured a file that no longer existed at the then-current head); and know the required-check set before calling anything green or blocked, because every check being green is not the same as the required check passing, and a required check that has not yet reported renders as `BLOCKED` — the ordinary in-flight state, not a verdict. *(Earned: every closure since — #1755 verified as `e938afc8`, tree `b86b05e4` equal to the carried head `ad3aa8d7`'s, parent `2d0ee979`, no foreign trailer — that being the tree check patch-id replaces, whose equality a base move under the PR removes; and the precedent that motivates the rule rather than any one incident: #568's fix regressed twice through a stale-base revert, which is exactly the class the change comparison closes — the merge looked clean, the tick was green, and the fix was gone. **The code-touching rider earned itself in TASK-177's #1990**: a clearance stamped at `83fa2fcd` arrived in the same batch as two other findings — Wren's paging defect and a mutation label **the author's own ledger** caught crediting an arm that no longer witnessed it — plus the `at`/`ms` divergence **Vera measured in that same clearance** and prescribed `ms: mark` for. The author had already moved the head to `000fdbbd` with all three folded, which is why the head had to move at all. The clearance was honest and correct about the head it named, which is precisely why it briefed nobody about the head on the branch; the author asked for the re-derivation and listed what the new head carried, and that list is the cheap half of the obligation.)* ## Enumerating a duplicated value