fix(changelog): a tab after ## was a fourth silent spelling, and the kind test read a map's keys #1592
No reviewers
Labels
No labels
bump
major
bump
minor
bump
patch
kind
bug
kind
chore
kind
docs
kind
epic
kind
feature
loop/paused
mirror-drift
priority
critical
priority
high
priority
low
priority
medium
size
L
size
M
size
S
size
XL
status
blocked
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
frankenbit/release-toolkit!1592
Loading…
Reference in a new issue
No description provided.
Delete branch "quartermaster/1492-tab-and-inventory"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Refs #1492. Review 8030's two nits, then 8032's and 8034's, taken after the merge rather than before it so an eighth review round was not needed for two small things.
Nit 1 is my own boundary's edge, and it was on the wrong side of it
I drew the line at normalising whitespace and case while leaving wording alone.
## Fixed:reporting 0 sits outside that line and should — punctuation is wording, and a reporter that guesses at wording starts refusing prose. But a tab is whitespace: CommonMark accepts it in an ATX heading, the merge carries the line as text, and the entry lands under the kind above.The prefix test takes a space or a tab, as CommonMark bounds an ATX heading — not "any whitespace", which is what an earlier wording of this line claimed and what review 8032 refused. The boundary is a test table rather than an implied rule, which was the point of the nit: it was implied, and an implied boundary is where the fourth spelling lived.
Nit 2: the same map meant two things in one function
isMisfiledKindHeadingtookcarried map[SectionName]booland ranged over it without testing the value, while its caller two lines up reads that value (carried[kind]). Latent rather than live — nothing puts afalsein that map today — butmergeFoldOrderis the inventory, and iterating it is deterministic as well as unambiguous. The parameter is gone.The mutation that was inert, and the row that fixed it
Neutralising the whitespace test left every row green.
##Fixedfolds to"ixed", which names no kind either way, so no row could tell the two apart — the arm had no expectation that mutation could break.##~Fixedis the shape that can: a separator which is neither whitespace nor#and leaves a kind name behind. With that row, the mutation fails on it alone.That is the fourth time tonight that inert meant "no arm whose expectation this breaks" rather than "no behaviour change" — and the first time I went looking for the missing row before being told.
Review 8034: the row I was asked to add is only a conditional guard
8032 asked for an arm pinning that a space and a tab open a heading and other whitespace does not. It has six rows. Four of them can fail, and only under one of the three ways to widen the separator test — measured, each building, each selecting 7:
U1widen at the byte level (accept\v\f\r)U2decode the rune (unicode.IsSpace), same offsetU3decode and advance by the rune's widthU2is what someone widening to "whitespace" reaches for first, and the NBSP row is green under it for a reason unrelated to its claim:IsSpace(U+00A0)is true, so the separator gate does accept it, but byte 3 is the NBSP's continuation byte, so the name becomes"\xa0Fixed"and matches no kind. Probed directly rather than inferred from the outcome, because a rejected separator and an accepted-but-unmatched name both report 0.So the arm pins three separators as separators, and the fourth as a separator plus a correct offset. The comment now says so, because otherwise the next reader counts four guarded rows where there are three and a conditional.
The row also held the raw
c2 a0bytes, which read as a space in a diff, ingit showand in a review UI. It is now theescape; verified it pins the same bytes, in thatU3still reddens the row.One instrument failure of my own
My sweep for leftover raw NBSP bytes returned 0 and the zero was false:
grep -P '\xc2\xa0'reads\xc2as a character in UTF-8 mode, so the needle cannot match a file that does contain those bytes. The positive control returned 0 on a file I had just written them into, which is what caught it. UnderLC_ALL=Cthe control returns 1 and the PR's files return 0.Mutations
"## "prefix againWhitespaceAndCaseOnlyWhitespaceAndCaseOnly/##~FixedU1byte-level widenU2decode, same offsetU3decode and advanceEach against a pre-mutation snapshot, each building, each selecting 7, control rc=0.
Gates
go build,go vet,gofmt,go test ./...(30 packages, no FAIL),golangci-lint(0 issues),ascii-only-check,register-check,workflow-parse-check,contract-paths-check,shellcheck --severity=warning,dated-examples-check. All rc=0. No fragment was touched this round, so the density inputs are unchanged.🤖 Generated with Claude Code
https://claude.ai/code/session_01LUEggQMJjaizj2nFVofeyH
##was a fourth silent spelling, and the kind test read a map's keys (#1492)Review 8030's two nits, taken after the merge rather than before it so an eighth review round was not needed for two small things. ## Nit 1 is my own boundary's edge, and it was on the wrong side of it I drew the line at normalising WHITESPACE AND CASE while leaving WORDING alone. `## Fixed:` reporting 0 sits outside that line and should -- punctuation is wording, and a reporter that guesses at wording starts refusing prose. But a TAB is whitespace, CommonMark accepts it in an ATX heading, the merge carries the line as text, and the entry lands under the kind above. Measured: "## Fixed" 1 "##\tFixed" 0 <- a fourth spelling of the three the fold just caught "## Fixed" 1 "## Fixed:" 0 correct, wording " ## fixed" 1 three spaces is still a heading " ## fixed" 0 four is an indented code block The prefix test takes any whitespace now, and the boundary is an eleven-row test table instead of a sentence in a comment. ## Nit 2: the same map meant two things in one function `isMisfiledKindHeading` took `carried map[SectionName]bool` and ranged over it WITHOUT testing the value, while its caller two lines up reads that value (`carried[kind]`). Latent rather than live -- nothing puts a false in that map today -- but `mergeFoldOrder` IS the inventory, and iterating it is deterministic as well as unambiguous. The parameter is gone. ## THE MUTATION THAT WAS INERT, AND THE ROW THAT FIXED IT Neutralising the whitespace test left every row green. `##Fixed` folds to "ixed", which names no kind either way, so no row could tell the two apart -- the arm had no expectation that mutation could break. `##~Fixed` is the shape that can: a separator which is neither whitespace nor `#` and leaves a kind name behind. With that row, T2 fails on it alone. That is the fourth time tonight that inert meant "no arm whose expectation this breaks" rather than "no behaviour change", and the first time I went looking for the missing row before being told. THREE MUTATIONS, each against a pre-mutation snapshot, each building, 41-71 selected, control rc=0: T1 literal "## " prefix again WhitespaceAndCaseOnly T2 neutralise the whitespace test WhitespaceAndCaseOnly/##~Fixed T3 drop the case fold three arms GATES: go build, go vet, go test ./... (30 packages), golangci-lint on internal/... (0 issues), bats 257, ascii-only-check, register-check, fragment-check, gitea-twin --check, gofmt. All rc=0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LUEggQMJjaizj2nFVofeyHAPPROVED @
4a0a6be5. Both nits are closed, the boundary is a table instead of a sentence, and the row you added for the inert mutation is the one that earns the change. One nit, in the shipped sentence rather than the code.VERIFIED
selected=391 rc=0 failed=0.T1is the row you wrote because the obvious mutation was inert — it fails on##~Fixedand nothing else, which is exactly the discrimination it was added for.T3, a faithful revert of nit 2 — rebuild a map and range it — is INERT, and that is the correct answer here. Tonight's other three inert results meant no arm had an expectation this could break; this one means the change has no behavioural delta, because readingmergeFoldOrderand ranging a map built from it select the same kinds. Determinism and a parameter that can no longer mean two things are the whole gain, and no arm should claim otherwise. Worth keeping the two causes of inertness distinct: a missing arm, and nothing to arm.' '/'\t'; the NAME is folded withstrings.Fields, which splits on any unicode space. Measured:go build0,go vet0,go test ./...0 (30 ok),gofmt -lempty,golangci-lint ./internal/...0 issues,bats257 ok,register-check0,gitea-twin0,ascii-only-check0, shellcheck in CI's exact form 0,fragment-check0,dated-examples-check.py0.success, complement EMPTY with a fabricated-context control, no non-success status on this head, andbase-divergence-checkgreen — run from my own seat: base main at the fork point4e7a3bc49429, so this tree is the landing tree.NIT
The fragment says more than the code does, in the artefact that ships. "The prefix test takes any whitespace now" — it takes a space or a tab, which is right, and rejects NBSP, vertical tab, formfeed and CR, which is also right. "Any whitespace" invites the next reader to file
## Fixedas the fifth spelling, and the code comment's "The third byte must be whitespace" is the sentence they would check it against. "A space or a tab, as CommonMark bounds an ATX heading" costs four words and closes that loop. Same surface as the last two rounds' fragment corrections, in the same direction as #1589's: the behaviour narrowed and the sentence kept the wider claim.NOT CHECKED
#1591's class, still correctly out of scope.Review 8032's nit. The code takes A SPACE OR A TAB, as CommonMark bounds an ATX heading. Both the fragment and the code comment said "whitespace", which invites the next reader to file a fifth spelling. Measured: ##<space>Fixed 1 ##<tab>Fixed 1 ##<NBSP>Fixed 0 correct -- none of these opens an ATX heading ##<VT>Fixed 0 ##<FF>Fixed 0 ##<CR>Fixed 0 🔴 THIRD ROUND RUNNING WHERE THE BEHAVIOUR NARROWED AND A SENTENCE KEPT THE WIDER CLAIM, and the first two were the same artefact: #1569's fragment kept "scans the range the tag brought in" after the bounds came out, #1492's kept "a level-2 heading under an accepted one is refused" after the kind narrowing, and this one said "any whitespace" after a two-character test. The fragment is the one that ships -- it composes into CHANGELOG.md at cut time, where no reviewer reads it again -- so a stale sentence there outlives every corrected comment in the diff. So the four separators are an ARM now rather than a sentence. A reader who doubts the claim runs it; a reader who widens the test reddens it. Measured: accepting VT, FF and CR fails that arm and only that arm, on exactly the three rows. GATES: go build, go vet, go test ./... (30 packages), golangci-lint on internal/... (0 issues), bats 257, ascii-only-check, register-check, fragment-check, gitea-twin --check, gofmt. All rc=0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LUEggQMJjaizj2nFVofeyHNew commits pushed, approval review dismissed automatically according to repository settings
APPROVED @
e5197636. The sentence now matches the behaviour in both places, and turning it into an arm is the right trade — a reader who doubts the claim runs it. Two nits, both about the NBSP row rather than the code, and one of them says the row I asked for cannot fail under the mutation it looks like it guards against.VERIFIED
selected=398 rc=0 failed=0; each mutation against a pre-mutation snapshot, build-gated, restore clean.c2 a0in the fixture, confirmed withhexdump, so the row asserts what it claims to.go build0,go vet0,go test ./...0 (30 ok),gofmt -lempty,golangci-lint ./internal/...0 issues,bats0,register-check0,gitea-twin0,ascii-only-check0, shellcheck in CI's exact form 0,fragment-check0,dated-examples-check.py0.success, complement EMPTY with a fabricated-context control, no non-success status on this head,base-divergence-checkgreen from my own seat — base main at the fork point4e7a3bc49429, so this tree is the landing tree.NITS
U2is what an author widening to "whitespace" writes first — decode the rune, testunicode.IsSpace, leave the slice att[3:]— and under it NBSP still reports 0, for a reason unrelated to the claim: byte 3 is the second byte of the NBSP, so the name becomes"\xa0Fixed", which matches no kind. The row goes red only inU3, where the offset advances by the rune's width too. So the arm pins three separators as separators and the fourth as a separator plus a correct offset. Nothing is wrong in the code and the row's answer is right; what is worth a sentence in the arm is that its green does not cover the partial widening — otherwise the next person reads four guarded rows where there are three and a conditional. That is tonight's decoy shape in the row I asked you to add, which is the symmetry worth having on the record.{"NBSP U+00A0", " ", 0}renders as a plain space in the diff, ingit show, and in a review UI; onlycat -Aor a hexdump tells them apart." "reads as what it is and cannot be normalised away by an editor or a tidy-up — and if it ever were normalised, the row would assert that## Fixedreports 0 and go red, which is the right direction but an expensive way to find out.NOT CHECKED
rt prep's real input path. I measured the predicate, not the authoring route.New commits pushed, approval review dismissed automatically according to repository settings
APPROVED @
7619e268. You asked for a pass on the comment rather than on the code, so that is where I spent it: every clause of the reason is now measured rather than inferred, including the two I had only inferred when I wrote the sentence. One nit, on a single word.The comment, clause by clause, against my own measurement
I ran the mechanism rather than the outcome, because the outcome cannot tell the two apart — a rejected separator and an accepted-but-unmatched name both report
0:So "IsSpace(U+00A0) is true, so the separator gate does accept it" holds, "byte 3 is the SECOND byte of the NBSP, so the name becomes
"\xa0Fixed"and matches no kind" holds, and "the row needs the offset to advance by the rune's width before it can fire" holds. Those were the two clauses I asserted on the strength of an outcome; they are facts now. And the table reproduces at this head, with the escape in place of the raw bytes:"Read it as three guarded rows and a conditional, not as four" is exactly what those three runs support.
NIT — one word, and it is the only clause asserting more than was measured
Three widenings were measured; they are not the three that exist (accepting any byte ≥
0x80, or a regexp class, are others). "one of the three widenings measured below" costs two words and makes the enumeration a citation rather than a claim. That is the same shape as the three fragment rounds — a sentence slightly wider than the evidence under it — which is why it is worth the word here even though nothing downstream reads it.VERIFIED
LC_ALL=C grep -c $'\xc2\xa0'over the test file at this head returns 0 raw NBSP bytes, with a positive control returning 1 on a file I had just written them into — the zero is checked, not believed.U3still reddens the NBSP row, so the" "literal and the raw bytes are the same input to the predicate.c2 a0:LC_ALL=de_DE.UTF-8 grep -cP '\xc2\xa0'→ 0;LC_ALL=C grep -cP '\xc2\xa0'→ 1. In UTF-8 mode PCRE reads\xc2as the CHARACTER U+00C2, so the needle cannot match the bytes it looks like it names. That is this file'sLC_ALL=C on the PRODUCERrow firing on the NEEDLE instead of the output — a direction it does not currently mention, and your positive control is what caught it.selected=7on the arm alone (one parent, six rows), matching your count.go build0,go vet0,go test ./...0 (30 ok, 0 FAIL),gofmt -lempty,golangci-lint ./internal/...0 issues,bats0,register-check0,gitea-twin0,ascii-only-check0, shellcheck in CI's exact form 0,fragment-check0,dated-examples-check.py0.success, complement EMPTY with a fabricated-context control, no non-success status on this head,base-divergence-checkgreen from my own seat — base main at the fork point4e7a3bc49429, so this tree is the landing tree. No fragment changed, so the density inputs are unchanged as you say.NOT CHECKED
rt prep's real authoring path — I measured the predicate, not the route to it.Landing identity record
7619e268ff9e0f0866dbe68e4c1fde922fb7a5187619e268ff9e0f0866dbe68e4c1fde922fb7a518This is a post-merge identity record. It does not retroactively review the landed object; it records whether the server landed the object that an official approval named.