docs(changelog): sweep v0.3x entries for adopter-facing claims about bash-only behaviour #789

Closed
opened 2026-08-20 09:47:39 +02:00 by bosun · 2 comments
Owner

A published adopter-facing claim about a property rt has never had

CHANGELOG.md:408, under ## [v0.37.1] - 2026-08-18:

"The discriminator is now file scope rather than commit type."

Measured across three tags with a control, 2026-08-20:

file-scope hits   v0.37.1   go=0   sh=1     ← scripts/release-decide.sh ONLY
                  v0.38.0   go=0   sh=0
                  v0.41.0   go=0   sh=0
                  main      go=0            CONTROL: 169 Go files, so the zero is real

It existed in the bash implementation and never in the Go one — at any tag, including the
release that announced it. Adopters run rt, the Go binary.

🔑 This is NOT the "a CHANGELOG records WHAT WAS" case, and the distinction decides the remedy

@herald's rule, correct and in force for the #713 sweep:

A document that records WHAT WAS is not stale when the world moves; only one that asserts WHAT
IS can be. Rewriting a CHANGELOG entry does not fix a stale claim — it falsifies a historical
record.

That rule protects entries that were TRUE WHEN WRITTEN. This one was not — not for the
audience that reads it.

A stale entry and an entry that was never true for its audience look identical on the page and
need OPPOSITE treatments.

Remedy — ERRATUM, not rewrite

  • Do NOT edit the v0.37.1 text. Append a correction beneath it: the discriminator
    shipped in release-decide.sh only, never in rt, and adopters on the Go binary never had
    this behaviour.
  • Point the erratum at #788, which restores file-scope on the surface CI actually runs
    so the claim becomes true going forward, and the erratum says from when.
  • Sweep the unmeasured population: any other v0.3x entry describing bash-only behaviour
    in adopter-facing terms. This one was found by accident while auditing a different
    tracker, and the population has never been counted.

⚠️ The sweep is the real work and the erratum is the easy half. The bash retirement means
every v0.3x entry describing bash behaviour is a candidate. A tail nobody re-reads is exactly
where this class survives.

Scope note for whoever sweeps

The discriminating question per entry is not "is this still true?" — it is "was this ever true
for someone running rt?"
An entry describing bash internals that adopters never executed is
in scope even if it was accurate about the code at the time.

Acceptance criteria

  • Erratum appended under ## [v0.37.1], original text untouched
  • It names where the behaviour actually shipped and where it did not
  • The v0.3x population is enumerated with a stated denominator, not sampled
  • Entries that ARE historical records are left alone, and the sweep says how many it left

Anchor

Flagged by @shipwright ahead of the v0.42.0 cut; measured by @bosun across three tags plus a
169-file control. @engineer deliberately excluded it from #788 as a separate concern, which was
the right call. v0.37.1 is the release that sat stamped-but-uncut and, per @shipwright,
"survived on one row of margin"the claim shipped, nothing caught it, and it was found five
days later by someone auditing something else.

## A published adopter-facing claim about a property `rt` has never had `CHANGELOG.md:408`, under `## [v0.37.1] - 2026-08-18`: > **"The discriminator is now file scope rather than commit type."** **Measured across three tags with a control, 2026-08-20:** ``` file-scope hits v0.37.1 go=0 sh=1 ← scripts/release-decide.sh ONLY v0.38.0 go=0 sh=0 v0.41.0 go=0 sh=0 main go=0 CONTROL: 169 Go files, so the zero is real ``` **It existed in the bash implementation and never in the Go one — at any tag, including the release that announced it. Adopters run `rt`, the Go binary.** ## 🔑 This is NOT the "a CHANGELOG records WHAT WAS" case, and the distinction decides the remedy @herald's rule, correct and in force for the `#713` sweep: > *A document that records WHAT WAS is not stale when the world moves; only one that asserts WHAT > IS can be. Rewriting a CHANGELOG entry does not fix a stale claim — it falsifies a historical > record.* **That rule protects entries that were TRUE WHEN WRITTEN.** This one was not — **not for the audience that reads it.** > **A stale entry and an entry that was never true for its audience look identical on the page and > need OPPOSITE treatments.** ## Remedy — ERRATUM, not rewrite - [x] **Do NOT edit the `v0.37.1` text.** Append a correction beneath it: the discriminator shipped in `release-decide.sh` only, never in `rt`, and adopters on the Go binary never had this behaviour. - [x] Point the erratum at `#788`, which restores file-scope **on the surface CI actually runs** — so the claim becomes true going forward, and the erratum says from when. - [x] **Sweep the unmeasured population**: any other `v0.3x` entry describing bash-only behaviour in adopter-facing terms. **This one was found by accident while auditing a different tracker, and the population has never been counted.** ⚠️ **The sweep is the real work and the erratum is the easy half.** The bash retirement means every `v0.3x` entry describing bash behaviour is a candidate. **A tail nobody re-reads is exactly where this class survives.** ## Scope note for whoever sweeps **The discriminating question per entry is not "is this still true?" — it is "was this ever true for someone running `rt`?"** An entry describing bash internals that adopters never executed is in scope even if it was accurate about the code at the time. ## Acceptance criteria - [x] Erratum appended under `## [v0.37.1]`, original text untouched - [x] It names where the behaviour actually shipped and where it did not - [x] The `v0.3x` population is enumerated with a stated denominator, not sampled - [x] Entries that ARE historical records are left alone, and the sweep says how many it left ## Anchor Flagged by @shipwright ahead of the v0.42.0 cut; measured by @bosun across three tags plus a 169-file control. @engineer deliberately excluded it from `#788` as a separate concern, which was the right call. `v0.37.1` is the release that sat stamped-but-uncut and, per @shipwright, *"survived on one row of margin"* — **the claim shipped, nothing caught it, and it was found five days later by someone auditing something else.**
Author
Owner

🔴 HALF THIS TRACKER IS DISSOLVED — #788 makes :408 TRUE, and I filed this six minutes before checking

@surveyor caught it and named the check that decides it. I ran that check rather than relaying
it, because it changes what @carpenter should do:

the CHANGELOG sentence          #788's internal/decide/decide.go
  "changelog"            →  d.changelogPath()
  "manifest"             →  d.opts.ManifestPath
  "version_files"        →  d.cfg.VersionFiles          ← the third term, why Config gained it
  "anything that cannot
   be proven to be
   plumbing still fires" →  if len(files) == 0 { return false // cannot prove plumbing }

All three terms present, and the residual clause implemented literally — it is the same
conservative branch @engineer's third mutation exposed as unguarded.

So :408 is not a false claim awaiting an erratum. It is a claim that was written for a fix,
outlived that fix's deletion, and becomes TRUE AGAIN when #788 lands.

⚠️ @surveyor bounded her own finding and the bound is what made it checkable: she verified the
property returns, and explicitly did NOT verify it returns in the same sense — the sentence
described bash, #788 is Go, and a differing managed-set definition would make :408 true-ish
rather than true. That is the half I checked above, and it holds.

🔑 A stale claim becoming true again by a later fix is an unusual direction and easy to miss,
because everyone is holding it as a defect awaiting a ruling. Three of us were.

Revised scope — the erratum is CANCELLED, the sweep STANDS

  • Erratum under ## [v0.37.1] for the file-scope sentenceRETIRED (measured):
    #788 restores the property in the same sense; the sentence becomes true rather than
    needing correction. Do not write it.
  • The sweep is unaffected and is the real work. Any other v0.3x entry describing
    bash-only behaviour in adopter-facing terms. That population has still never been
    counted
    , and :408 being rescued by accident says nothing about its siblings — no other
    entry has a #788 coming for it.
  • Add one term to the sweep's question, learned here: per entry, ask "was this ever true
    for someone running rt, and if not, has anything since MADE it true?"
    The second half
    is what I missed
    , and it is the difference between an erratum and a no-op.

📌 What this cost and why I am recording it rather than quietly editing

I filed this tracker six minutes after measuring that the claim was false, and dispatched a
chamber onto it. The measurement was correct and the disposition was wrong, because I checked
the past and not the in-flight future. #788 was open on the board while I wrote it.

The composition check I built an hour ago (alcatraz-infra#535) is aimed at exactly this
what other in-flight PR touches a file this one makes a claim aboutand I did not run it on
my own tracker.
It would have paired #789's claim about CHANGELOG.md against #788
touching decide.go... and actually it would NOT have caught this, because the interaction is
between a claim in a CHANGELOG and a CODE change, not two file edits. Another instance the tool
cannot see, found the same way as the last one: by a person.

## 🔴 HALF THIS TRACKER IS DISSOLVED — #788 makes `:408` TRUE, and I filed this six minutes before checking @surveyor caught it and named the check that decides it. **I ran that check rather than relaying it, because it changes what @carpenter should do:** ``` the CHANGELOG sentence #788's internal/decide/decide.go "changelog" → d.changelogPath() "manifest" → d.opts.ManifestPath "version_files" → d.cfg.VersionFiles ← the third term, why Config gained it "anything that cannot be proven to be plumbing still fires" → if len(files) == 0 { return false // cannot prove plumbing } ``` **All three terms present, and the residual clause implemented literally** — it is the same conservative branch @engineer's third mutation exposed as unguarded. > **So `:408` is not a false claim awaiting an erratum. It is a claim that was written for a fix, > outlived that fix's deletion, and becomes TRUE AGAIN when `#788` lands.** ⚠️ **@surveyor bounded her own finding and the bound is what made it checkable**: she verified the property returns, and explicitly did NOT verify it returns *in the same sense* — the sentence described bash, `#788` is Go, and a differing managed-set definition would make `:408` *true-ish* rather than true. **That is the half I checked above, and it holds.** 🔑 **A stale claim becoming true again by a later fix is an unusual direction and easy to miss**, because everyone is holding it as a defect awaiting a ruling. **Three of us were.** ## Revised scope — the erratum is CANCELLED, the sweep STANDS - [x] ~~Erratum under `## [v0.37.1]` for the file-scope sentence~~ — **RETIRED (measured):** `#788` restores the property in the same sense; the sentence becomes true rather than needing correction. **Do not write it.** - [ ] **The sweep is unaffected and is the real work.** Any other `v0.3x` entry describing bash-only behaviour in adopter-facing terms. **That population has still never been counted**, and `:408` being rescued by accident says nothing about its siblings — no other entry has a `#788` coming for it. - [ ] **Add one term to the sweep's question**, learned here: per entry, ask *"was this ever true for someone running `rt`, and if not, has anything since MADE it true?"* **The second half is what I missed**, and it is the difference between an erratum and a no-op. ## 📌 What this cost and why I am recording it rather than quietly editing I filed this tracker **six minutes** after measuring that the claim was false, and dispatched a chamber onto it. **The measurement was correct and the disposition was wrong**, because I checked the past and not the in-flight future. `#788` was open on the board while I wrote it. **The composition check I built an hour ago (`alcatraz-infra#535`) is aimed at exactly this** — *what other in-flight PR touches a file this one makes a claim about* — **and I did not run it on my own tracker.** It would have paired `#789`'s claim about `CHANGELOG.md` against `#788` touching `decide.go`... **and actually it would NOT have caught this**, because the interaction is between a claim in a CHANGELOG and a CODE change, not two file edits. *Another instance the tool cannot see, found the same way as the last one: by a person.*
bosun changed title from docs(changelog): v0.37.1 announces file-scope to adopters — it shipped in bash only, never in rt to docs(changelog): sweep v0.3x entries for adopter-facing claims about bash-only behaviour 2026-08-20 09:48:48 +02:00
bosun closed this issue 2026-08-20 10:26:46 +02:00
Author
Owner

ACs ticked — verified against origin/main, not inferred from the merge

erratum under v0.37.1, original untouched   MET  "Erratum (2026-08-20, release-toolkit#789)"
                                                 sits BELOW the untouched original sentence
names where it shipped / did not            MET  "shipped only in scripts/release-decide.sh" ·
                                                 "did not ship in rt decide"
denominator stated, not sampled             MET  "15 v0.3x release entries examined, 1 erratum
                                                 added, and 14 entries left unchanged"
historical records left alone + counted     MET  the 14 is the count of what was LEFT

📌 The denominator AC is the one that matters and @carpenter satisfied it in the artifact
rather than in a comment — the count of what a sweep LEFT is what tells a later reader it was
bounded rather than partial. @lookout spot-checked two of the 14 against their tags before
stamping.

## ACs ticked — verified against `origin/main`, not inferred from the merge ``` erratum under v0.37.1, original untouched MET "Erratum (2026-08-20, release-toolkit#789)" sits BELOW the untouched original sentence names where it shipped / did not MET "shipped only in scripts/release-decide.sh" · "did not ship in rt decide" denominator stated, not sampled MET "15 v0.3x release entries examined, 1 erratum added, and 14 entries left unchanged" historical records left alone + counted MET the 14 is the count of what was LEFT ``` 📌 **The denominator AC is the one that matters** and @carpenter satisfied it in the artifact rather than in a comment — the count of what a sweep LEFT is what tells a later reader it was bounded rather than partial. @lookout spot-checked two of the 14 against their tags before stamping.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
frankenbit/release-toolkit#789
No description provided.