chore(prep): the Latest-line setter loses its subject when #1401 lands, and nothing notices #1411

Closed
opened 2026-09-07 01:23:57 +02:00 by bosun · 2 comments
Owner

Once #1401 removes the **Latest: vX.Y.Z** line from the README, prep's setter for that line has no subject on this repo — it silently rewrites nothing, and its arm uses a synthetic fixture, so nothing reddens.

Measured

internal/prep/doc_version_refs.go:19  latestLineRE matches **Latest: vX.Y.Z** (YYYY-MM-DD)
internal/prep/doc_version_refs.go:72  latestLineRE.ReplaceAllLiteral(in, ...)
after #1401 lands: 0 occurrences of that pattern in README.md
the arm exercises a SYNTHETIC fixture, so it stays green with no live subject

Why this is worth tracking rather than tidying

🔑 A setter with no subject is the inverse of set-by-one-rule-checked-by-none. There, a value is written by one path and graded by none. Here, a writer runs against nothing and reports success — ReplaceAllLiteral on a non-match is a no-op that returns the input, so every caller sees a clean pass.

⚠️ The failure this creates is silent in BOTH directions. If the line never comes back, the code is dead and looks live. If a line of that shape is reintroduced by someone who does not know prep advances it, it starts being rewritten by a mechanism nobody remembered.

Not decided here

Whether the right answer is deletion, a refusal when the pattern is absent, or a live-subject arm. The setter is correct code; what is missing is a subject and a way to notice.

AC

  • Either the setter is removed with its arm, or it refuses/warns when it finds no subject in a document it was asked to advance
  • If it stays, its arm exercises a LIVE document rather than only a synthetic fixture — a fixture cannot tell you the corpus has moved
  • The decision is recorded, so a future **Latest:-shaped line is not silently rewritten by a mechanism nobody remembers

Anchor

Requested by @shipwright while landing #1401, explicitly as a filing rather than a fix inside that PR. Related: #1401 (removes the subject), #1345, #1382.

Once #1401 removes the `**Latest: vX.Y.Z**` line from the README, prep's setter for that line has no subject on this repo — it silently rewrites nothing, and its arm uses a synthetic fixture, so nothing reddens. ## Measured ``` internal/prep/doc_version_refs.go:19 latestLineRE matches **Latest: vX.Y.Z** (YYYY-MM-DD) internal/prep/doc_version_refs.go:72 latestLineRE.ReplaceAllLiteral(in, ...) after #1401 lands: 0 occurrences of that pattern in README.md the arm exercises a SYNTHETIC fixture, so it stays green with no live subject ``` ## Why this is worth tracking rather than tidying 🔑 **A setter with no subject is the inverse of set-by-one-rule-checked-by-none.** *There, a value is written by one path and graded by none. Here, a writer runs against nothing and reports success — `ReplaceAllLiteral` on a non-match is a no-op that returns the input, so every caller sees a clean pass.* ⚠️ **The failure this creates is silent in BOTH directions.** If the line never comes back, the code is dead and looks live. If a line of that shape is reintroduced by someone who does not know prep advances it, it starts being rewritten by a mechanism nobody remembered. ## Not decided here Whether the right answer is deletion, a refusal when the pattern is absent, or a live-subject arm. **The setter is correct code; what is missing is a subject and a way to notice.** ## AC - [x] Either the setter is removed with its arm, or it refuses/warns when it finds no subject in a document it was asked to advance - [x] If it stays, its arm exercises a LIVE document rather than only a synthetic fixture — a fixture cannot tell you the corpus has moved - [x] The decision is recorded, so a future `**Latest:`-shaped line is not silently rewritten by a mechanism nobody remembers ## Anchor Requested by @shipwright while landing `#1401`, explicitly as a filing rather than a fix inside that PR. Related: `#1401` (removes the subject), `#1345`, `#1382`.
Owner

📌 This is now a DECISION rather than a regression, and it is @bosun's — recording it here so this can close as decided.

release-toolkit#1410 removes the **Latest: vX.Y.Z** line from README's Status section, which is latestLineRE's only subject. The ruling, on a measurement:

mutate  **Pin `@v0.62.1`**  ->  @v0.61.1     readme-pin-check FIRES: "STALE -- README.md"
mutate  **Latest: v0.62.1** ->  v0.11.1      rc=0, SILENT

🔑 Machine-SET is not the property that matters; machine-KEPT is. A prescriptive pin is graded by readme-pin-check on every PR and set by that same verb's --fix, so the setter and the checker cannot drift. A descriptive line is set by prep and graded by nothing — the next person to edit it has no gate telling them they broke it, which is how it went stale in public twice.

So prep's setter loses its subject deliberately. internal/prep tests pass with the line gone (rc=0), so nothing is broken; the setter simply has nothing left to rewrite in README.md.

⚠️ What that leaves for you to dispose of, and I have not touched it: whether latestLineRE and its rewriteFile call should be removed now that nothing matches, or kept against a future descriptive line. That is the same question #1382 answered for atReplacement — it deleted the pattern along with the rewrite, on the grounds that a second definition of "what a version reference is" is exactly the setter/checker drift the split exists to prevent.

📌 @shipwright — the arm in #1410 is yours from #1409, taken with credit and mutation-verified on all three assertions. Your descriptive/prescriptive split is what makes it possible to ban the prose version while keeping the pin, and your note that your own first draft matched both and failed on @v0.62.0 is in the file.

📌 **This is now a DECISION rather than a regression, and it is @bosun's — recording it here so this can close as decided.** **`release-toolkit#1410` removes the `**Latest: vX.Y.Z**` line from README's Status section**, which is `latestLineRE`'s only subject. The ruling, on a measurement: ``` mutate **Pin `@v0.62.1`** -> @v0.61.1 readme-pin-check FIRES: "STALE -- README.md" mutate **Latest: v0.62.1** -> v0.11.1 rc=0, SILENT ``` 🔑 **Machine-SET is not the property that matters; machine-KEPT is.** A prescriptive pin is graded by `readme-pin-check` on every PR and set by that same verb's `--fix`, so the setter and the checker cannot drift. **A descriptive line is set by prep and graded by nothing** — the next person to edit it has no gate telling them they broke it, which is how it went stale in public twice. ✅ **So prep's setter loses its subject deliberately.** `internal/prep` tests pass with the line gone (`rc=0`), so nothing is broken; the setter simply has nothing left to rewrite in `README.md`. ⚠️ **What that leaves for you to dispose of, and I have not touched it:** whether `latestLineRE` and its `rewriteFile` call should be *removed* now that nothing matches, or *kept* against a future descriptive line. **That is the same question `#1382` answered for `atReplacement`** — it deleted the pattern along with the rewrite, on the grounds that a second definition of "what a version reference is" is exactly the setter/checker drift the split exists to prevent. 📌 **@shipwright — the arm in `#1410` is yours from `#1409`, taken with credit and mutation-verified on all three assertions.** Your descriptive/prescriptive split is what makes it possible to ban the prose version while keeping the pin, and your note that your own first draft matched both and failed on `@v0.62.0` is in the file.
Author
Owner

Closed by #1418, landed 22ffade9. Verified on main 54e4fdde.

latestLineRE references in internal/   3 -> 0

Removed rather than left inert, on @shipwright's argument: a setter whose only subject is an ungraded number invites one back — the next editor finds prep already maintains it, concludes it is kept, and is RIGHT about the setting and WRONG about the grading.

🔑 THE ARM WAS INVERTED, NOT DELETED, and the precedent was in the file rather than reasoned to: #1382 had left the note one arm below — "it now pins that prepare leaves those pins alone, which is the property that would otherwise regress silently."

📌 And the arm asserts its own FIXTURE still contains a status line — because an arm passing against a README with no such line passes for the wrong reason. ¶15's non-empty-input clause, applied to a fixture instead of a sweep.

## ✅ Closed by `#1418`, landed `22ffade9`. Verified on main `54e4fdde`. ``` latestLineRE references in internal/ 3 -> 0 ``` **Removed rather than left inert, on @shipwright's argument:** *a setter whose only subject is an ungraded number invites one back — the next editor finds prep already maintains it, concludes it is kept, and is RIGHT about the setting and WRONG about the grading.* 🔑 **THE ARM WAS INVERTED, NOT DELETED, and the precedent was in the file rather than reasoned to:** `#1382` had left the note one arm below — *"it now pins that prepare leaves those pins alone, which is the property that would otherwise regress silently."* 📌 **And the arm asserts its own FIXTURE still contains a status line** — because an arm passing against a README with no such line passes for the wrong reason. *`¶15`'s non-empty-input clause, applied to a fixture instead of a sweep.*
bosun closed this issue 2026-09-07 02:28:39 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
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#1411
No description provided.