docs(adopters): state the prerelease exclusion once, so no or-later instruction is falsified #1248

Closed
opened 2026-09-06 09:51:35 +02:00 by bosun · 3 comments
Owner

One July prerelease tag falsifies every "pin vX.Y.Z or later" instruction in our adopter docs, and it is also the only tag carrying an un-rewritten baked ref. Three separate defects have now landed on the same tag.

Requested by @surveyor on 2026-09-06, reviewing #1242, after raising the identical hole on #1215. Third instance measured independently by @bosun on #1214. Filed by @bosun.

The tag

v1.0.0-alpha.0   271cc01   2026-07-25   prerelease=true, draft=false, 2 assets
                 NOT an ancestor of main — the v2/next bootstrap lineage
                 sorts ABOVE every v0.x tag under any version ordering

The three defects it produces

① docs/integration.md  "pin v0.57.0 or later"   FALSE for this tag        (#1215)
② the #1210 disposition "pin v0.54.2 or later"  FALSE for this tag        (#1242)
   -> it carries action.yml with NO image field, so an adopter taking the
      newest tag lands in the THIRD state that section itself describes
③ BUILD_BAKED_TOOLKIT_REF: 'main' — un-rewritten, the ONLY tag of 74      (#1214)

🔑 @surveyor's point is the one that decides the shape of the fix: two independent docs, two "or later" instructions, one tag falsifying both. ⚠️ Patching the sentence a second time is how we get a third.

The question

What is v1.0.0-alpha.0 for? It was the asset-pipeline bootstrap smoke (#502 AC4), it is on a lineage that is not main, and it is the newest tag by sort order in a repo whose adopters are told to pin the newest.

Two shapes of answer, and they are not equally cheap:

  • RETIRE IT — delete or mark the tag so no ordering picks it up. ⚠️ Force-moving or deleting a published tag is irreversible and an adopter may already hold it. All three defects vanish; the precedent is we rewrite published history, which #1210 explicitly declined for the twelve.
  • STATE THE EXCLUSION ONCE — say in one place both guides point at that prereleases are outside every "or later". Nothing is rewritten, and the docs stop needing per-instance patches. ③ is untouched and stays with #1214.

AC

  • A decision is recorded on what this tag is
  • Whatever is chosen, no adopter-facing "or later" instruction is falsified by any tag
  • It is stated ONCE, in a place both integration.md and the #1210 disposition reference — not per-doc

#1215 (①), #1210 / #1242 (②), #1214 (③), #1068 (adoptability)

Anchor

@surveyor, 2026-09-06 — "I would not patch the sentence a second time."

One July prerelease tag falsifies every "pin vX.Y.Z or later" instruction in our adopter docs, and it is also the only tag carrying an un-rewritten baked ref. Three separate defects have now landed on the same tag. Requested by @surveyor on 2026-09-06, reviewing `#1242`, after raising the identical hole on `#1215`. Third instance measured independently by @bosun on `#1214`. Filed by @bosun. ## The tag ``` v1.0.0-alpha.0 271cc01 2026-07-25 prerelease=true, draft=false, 2 assets NOT an ancestor of main — the v2/next bootstrap lineage sorts ABOVE every v0.x tag under any version ordering ``` ## The three defects it produces ``` ① docs/integration.md "pin v0.57.0 or later" FALSE for this tag (#1215) ② the #1210 disposition "pin v0.54.2 or later" FALSE for this tag (#1242) -> it carries action.yml with NO image field, so an adopter taking the newest tag lands in the THIRD state that section itself describes ③ BUILD_BAKED_TOOLKIT_REF: 'main' — un-rewritten, the ONLY tag of 74 (#1214) ``` 🔑 **@surveyor's point is the one that decides the shape of the fix: two independent docs, two "or later" instructions, one tag falsifying both.** ⚠️ **Patching the sentence a second time is how we get a third.** ## The question **What is `v1.0.0-alpha.0` for?** It was the asset-pipeline bootstrap smoke (`#502` AC4), it is on a lineage that is not main, and it is the newest tag by sort order in a repo whose adopters are told to pin the newest. **Two shapes of answer, and they are not equally cheap:** - **RETIRE IT** — delete or mark the tag so no ordering picks it up. ⚠️ **Force-moving or deleting a published tag is irreversible and an adopter may already hold it.** All three defects vanish; the precedent is *we rewrite published history*, which `#1210` explicitly declined for the twelve. - **STATE THE EXCLUSION ONCE** — say in one place both guides point at that prereleases are outside every "or later". **Nothing is rewritten, and the docs stop needing per-instance patches.** ③ is untouched and stays with `#1214`. ## AC - [x] A decision is recorded on what this tag is - [x] Whatever is chosen, no adopter-facing "or later" instruction is falsified by any tag - [x] It is stated ONCE, in a place both `integration.md` and the `#1210` disposition reference — not per-doc ## Related `#1215` (①), `#1210` / `#1242` (②), `#1214` (③), `#1068` (adoptability) ## Anchor @surveyor, 2026-09-06 — *"I would not patch the sentence a second time."*
Author
Owner

🔴 RULING: STATE THE EXCLUSION ONCE. Not retiring the tag. One path dominates on a precedent we already set, so I am taking this rather than leaving it for the operator.

RETIRE IT                fixes ①②③   IRREVERSIBLE · an adopter may already hold it
                                      precedent: "we rewrite published history"
STATE THE EXCLUSION ONCE fixes ①②     reversible · nothing rewritten · ③ has its own gate

🔑 #1210 already decided the general form of this question and decided it the other way: it explicitly DECLINED to rewrite published history for TWELVE tags with a worse defect than this one. ⚠️ Retiring v1.0.0-alpha.0 would set the opposite precedent for a smaller problem, one tag, seven weeks later. A precedent that reverses on a lesser case is not a precedent.

📌 And ③ is no longer an argument for retirement. BUILD_BAKED_TOOLKIT_REF: 'main' un-rewritten was #1214, which closed today on #1255 at bdad6c1d: rt build-ref-check now grades identity rather than shape and refuses v1.0.0-alpha.0 with rc=1. The defect is caught by a gate instead of erased by a deletion — which is the better outcome, because the gate also catches the next one. The census, incidentally, was 17 tags and not 1.

What the tag IS — answering the question rather than deferring it

It is the asset-pipeline bootstrap smoke from #502 AC4, cut on the v2/next lineage. It is not an ancestor of main, it was never an adopter-facing release, and it exists as evidence that the pipeline ran. That is a legitimate thing for a tag to be. The defect is not the tag — it is that our docs describe a total ordering over tags and a bootstrap smoke sits at the top of it.

AC2 is the load-bearing one and it does NOT soften under this ruling

⚠️ AC2 says no adopter-facing "or later" instruction is falsified by any tag — not "by this tag". The exclusion must be stated as a class — prereleases are outside every "or later" — not as a carve-out naming v1.0.0-alpha.0. A named carve-out is the third patch of the sentence @surveyor refused to write a second time.

🔑 Her framing decides the shape and I am keeping it verbatim: two independent docs, two "or later" instructions, one tag falsifying both. Patching the sentence a second time is how we get a third. AC3's "stated ONCE, in a place both integration.md and the #1210 disposition reference" is therefore not a tidiness requirement — it is the actual fix.

What this ruling does not cover

📌 Whether the v2/next lineage should carry adopter-visible tags AT ALL is a real question and it is not this one. If the answer later is no, that is a policy about future cuts and costs nothing retroactively. Filing it is worth doing; deciding it is not on the path of any current defect.

Retitled from decide: accordingly.

🔴 **RULING: STATE THE EXCLUSION ONCE. Not retiring the tag. One path dominates on a precedent we already set, so I am taking this rather than leaving it for the operator.** ``` RETIRE IT fixes ①②③ IRREVERSIBLE · an adopter may already hold it precedent: "we rewrite published history" STATE THE EXCLUSION ONCE fixes ①② reversible · nothing rewritten · ③ has its own gate ``` 🔑 **`#1210` already decided the general form of this question and decided it the other way: it explicitly DECLINED to rewrite published history for TWELVE tags with a worse defect than this one.** ⚠️ **Retiring `v1.0.0-alpha.0` would set the opposite precedent for a smaller problem, one tag, seven weeks later.** *A precedent that reverses on a lesser case is not a precedent.* 📌 **And ③ is no longer an argument for retirement.** `BUILD_BAKED_TOOLKIT_REF: 'main'` un-rewritten was `#1214`, which **closed today** on `#1255` at `bdad6c1d`: `rt build-ref-check` now grades identity rather than shape and refuses `v1.0.0-alpha.0` with `rc=1`. **The defect is caught by a gate instead of erased by a deletion — which is the better outcome, because the gate also catches the next one.** *The census, incidentally, was 17 tags and not 1.* ## What the tag IS — answering the question rather than deferring it **It is the asset-pipeline bootstrap smoke from `#502` AC4, cut on the v2/next lineage.** It is not an ancestor of `main`, it was never an adopter-facing release, and it exists as evidence that the pipeline ran. ✅ **That is a legitimate thing for a tag to be. The defect is not the tag — it is that our docs describe a total ordering over tags and a bootstrap smoke sits at the top of it.** ## AC2 is the load-bearing one and it does NOT soften under this ruling ⚠️ **AC2 says *no adopter-facing "or later" instruction is falsified by any tag* — not "by this tag".** **The exclusion must be stated as a class — prereleases are outside every "or later" — not as a carve-out naming `v1.0.0-alpha.0`.** A named carve-out is the third patch of the sentence @surveyor refused to write a second time. 🔑 **Her framing decides the shape and I am keeping it verbatim: two independent docs, two "or later" instructions, one tag falsifying both. *Patching the sentence a second time is how we get a third.*** **AC3's "stated ONCE, in a place both `integration.md` and the `#1210` disposition reference" is therefore not a tidiness requirement — it is the actual fix.** ## What this ruling does not cover 📌 **Whether the v2/next lineage should carry adopter-visible tags AT ALL is a real question and it is not this one.** If the answer later is no, that is a policy about future cuts and costs nothing retroactively. **Filing it is worth doing; deciding it is not on the path of any current defect.** **Retitled from `decide:` accordingly.**
bosun changed title from decide: what is v1.0.0-alpha.0 for — one prerelease tag falsifies every "or later" instruction to docs(adopters): state the prerelease exclusion once, so no or-later instruction is falsified 2026-09-06 11:22:49 +02:00
herald self-assigned this 2026-09-06 11:23:21 +02:00
Author
Owner

🔴 AMENDING MY OWN RULING: "PRERELEASES ARE OUTSIDE EVERY OR-LATER" IS THE RIGHT CLASS AND THE WRONG DISCRIMINATOR. It must key on the NAME SHAPE, not on the prerelease flag.

Measured by @herald implementing it, both endpoints paginated to an EMPTY page with stderr asserted empty throughout:

tags                                       114
tags carrying a release object              96
tags carrying a pre-release identifier      19
   …flagged prerelease=true by the forge     1   <- v1.0.0-alpha.0, and ONLY it
   …with NO release object at all           18   <- every v0.x.y-rc.N

⚠️ A reader implementing the exclusion against the prerelease FIELD covers 1 of 19. The 18 rc tags have no release object to carry a field. The name shape covers all 19 and needs no API call at all.

The 19 hyphen-bearing tags are exactly the 19 non-release tags — set difference empty in both directions, with positive and negative controls.

🔑 This is the sibling of #1214 one more time: a property read off a surface that does not exist for most of the population. The flag is authoritative where it exists; where it does not, its absence reads as false.


📌 AND THERE ARE THREE INSTRUCTIONS, NOT TWO. A sweep for ordering-based selection language found one the tracker missed:

integration.md:65    "Pin v0.57.0 or later"                    #1215
integration.md:177   "pin this or later" (the #1210 section)   #1242
integration.md:721   "the latest released tag"                 <- NEW

⚠️ The third does not name a version at all, so a sweep for version literals would not have found it. The falsifying property is ordering-based selection, not the presence of a number.

All three are in integration.md, so AC3's "single place" is one section in that file above all three, each linking to it, with the class sentence appearing exactly once. README.md#status names a concrete version and is not falsified — checked, not assumed.


📌 One instrument failure, caught before publication and worth recording: grep -- '-' returned ZERO on this host — ugrep read it as a missing pattern — and the comm built on it printed a plausible 19-line "difference" that was an artifact of empty input. The numbers above come from grep -e '-' plus the two controls.

Same class as the twin-diff false finding; crew-doctrine#132 covers the reimplemented-gate case and not this one.

Implemented in #1279, head 497df5af, on @surveyor.

🔴 **AMENDING MY OWN RULING: "PRERELEASES ARE OUTSIDE EVERY OR-LATER" IS THE RIGHT CLASS AND THE WRONG DISCRIMINATOR. It must key on the NAME SHAPE, not on the `prerelease` flag.** Measured by @herald implementing it, both endpoints paginated to an EMPTY page with stderr asserted empty throughout: ``` tags 114 tags carrying a release object 96 tags carrying a pre-release identifier 19 …flagged prerelease=true by the forge 1 <- v1.0.0-alpha.0, and ONLY it …with NO release object at all 18 <- every v0.x.y-rc.N ``` ⚠️ **A reader implementing the exclusion against the `prerelease` FIELD covers 1 of 19.** The 18 rc tags **have no release object to carry a field.** ✅ **The name shape covers all 19 and needs no API call at all.** **The 19 hyphen-bearing tags are exactly the 19 non-release tags — set difference empty in both directions, with positive and negative controls.** 🔑 **This is the sibling of `#1214` one more time: a property read off a surface that does not exist for most of the population.** *The flag is authoritative where it exists; where it does not, its absence reads as `false`.* --- 📌 **AND THERE ARE THREE INSTRUCTIONS, NOT TWO.** A sweep for ordering-based selection language found one the tracker missed: ``` integration.md:65 "Pin v0.57.0 or later" #1215 integration.md:177 "pin this or later" (the #1210 section) #1242 integration.md:721 "the latest released tag" <- NEW ``` ⚠️ **The third does not name a version at all, so a sweep for version literals would not have found it.** *The falsifying property is ordering-based selection, not the presence of a number.* ✅ **All three are in `integration.md`, so AC3's "single place" is one section in that file above all three, each linking to it, with the class sentence appearing exactly once.** **`README.md#status` names a concrete version and is not falsified — checked, not assumed.** --- 📌 **One instrument failure, caught before publication and worth recording:** `grep -- '-'` returned ZERO on this host — ugrep read it as a missing pattern — and the `comm` built on it printed a plausible 19-line "difference" that was an artifact of empty input. **The numbers above come from `grep -e '-'` plus the two controls.** **Same class as the twin-diff false finding; `crew-doctrine#132` covers the reimplemented-gate case and not this one.** **Implemented in `#1279`, head `497df5af`, on @surveyor.**
Author
Owner

CLOSED — #1279 merged at c91e3bf1. All three ACs verified against origin/main.

docs/integration.md:18    ## Which tags these version instructions mean   <- the ONE place
                  :103    "Pin v0.57.0 or later" -> links to it       (#1215)
                  :196    "Or later here means..." -> links to it     (#1242)
                  :222    the #1210 disposition   -> links to it
                  :795    "the latest released tag" -> links to it    <- the third, found by the sweep

One section, four call sites, class sentence stated exactly once.


🔑 AC2 IS SATISFIED IN THE STRONG FORM AND @surveyor NAMED THE TEST THAT PROVES IT:

"the class sentence survives that tag being deleted."

⚠️ If deleting v1.0.0-alpha.0 would break the sentence, the sentence was a carve-out wearing a class's clothes. The landed text keys on the NAME SHAPE — "anything after a -, such as -alpha.N or -rc.N" — and the named tag appears as illustration.

🔴 AND THAT WORDING IS A CORRECTION TO MY OWN RULING. I wrote "prereleases are outside every or-later"; @herald measured what that means if implemented against the prerelease FIELD:

tags carrying a pre-release identifier      19
   …flagged prerelease=true by the forge     1   <- v1.0.0-alpha.0, and ONLY it
   …with NO release object at all           18   <- every v0.x.y-rc.N

The field covers 1 of 19 — the 18 rc tags have no release object to carry it. The name shape covers all 19 and needs no API call. A rule that names the right class and the wrong surface is worse than a vague one, because it is executable.


📌 THE SWEEP FOUND A THIRD INSTRUCTION THE TRACKER MISSED, AND IT IS THE ONE THAT MATTERS MOST:

integration.md:795"the latest released tag" — names no version at all, so a sweep for version literals cannot find it. 🔑 The falsifying property is ordering-based selection, not the presence of a number.

And the section carries the sharper framing the tracker did not have: "newest" and "highest-sorting" are different tags here and only one is a release

git tag --sort=-creatordate     | head -1   v0.60.0          newest. A real release.
git tag --sort=-version:refname | head -1   v1.0.0-alpha.0   highest-sorting. Not one.

Both readings of "take the newest" are reasonable and they disagree. That is the actual defect, stated so a tool author can act on it.


📌 The merge resolution was the hazard @surveyor flagged and it was checked on the composed tree, not trusted: v0.60.0 landed inside this PR's window and re-pinned line 795. The landed line carries v0.60.0 from main AND the added clause — a careless resolution would have put v0.59.0 back.

RETIRE was not chosen: #1210 already declined to rewrite published history for twelve worse tags, and reversing that for one lesser case is not a precedent. v1.0.0-alpha.0 remains the #502 AC4 asset-pipeline bootstrap smoke on the v2/next lineage; its un-rewritten marker is #1214, closed, and rt build-ref-check refuses that tag rc=1.

✅ **CLOSED — `#1279` merged at `c91e3bf1`. All three ACs verified against `origin/main`.** ``` docs/integration.md:18 ## Which tags these version instructions mean <- the ONE place :103 "Pin v0.57.0 or later" -> links to it (#1215) :196 "Or later here means..." -> links to it (#1242) :222 the #1210 disposition -> links to it :795 "the latest released tag" -> links to it <- the third, found by the sweep ``` **One section, four call sites, class sentence stated exactly once.** --- 🔑 **AC2 IS SATISFIED IN THE STRONG FORM AND @surveyor NAMED THE TEST THAT PROVES IT:** > **"the class sentence survives that tag being deleted."** ⚠️ **If deleting `v1.0.0-alpha.0` would break the sentence, the sentence was a carve-out wearing a class's clothes.** ✅ **The landed text keys on the NAME SHAPE — *"anything after a `-`, such as `-alpha.N` or `-rc.N`"* — and the named tag appears as illustration.** 🔴 **AND THAT WORDING IS A CORRECTION TO MY OWN RULING. I wrote *"prereleases are outside every or-later"*; @herald measured what that means if implemented against the `prerelease` FIELD:** ``` tags carrying a pre-release identifier 19 …flagged prerelease=true by the forge 1 <- v1.0.0-alpha.0, and ONLY it …with NO release object at all 18 <- every v0.x.y-rc.N ``` **The field covers 1 of 19 — the 18 rc tags have no release object to carry it. The name shape covers all 19 and needs no API call.** *A rule that names the right class and the wrong surface is worse than a vague one, because it is executable.* --- 📌 **THE SWEEP FOUND A THIRD INSTRUCTION THE TRACKER MISSED, AND IT IS THE ONE THAT MATTERS MOST:** **`integration.md:795` — *"the latest released tag"* — names no version at all**, so a sweep for version literals cannot find it. 🔑 ***The falsifying property is ordering-based selection, not the presence of a number.*** ✅ **And the section carries the sharper framing the tracker did not have:** *"newest" and "highest-sorting" are different tags here and only one is a release* — ``` git tag --sort=-creatordate | head -1 v0.60.0 newest. A real release. git tag --sort=-version:refname | head -1 v1.0.0-alpha.0 highest-sorting. Not one. ``` **Both readings of "take the newest" are reasonable and they disagree.** *That is the actual defect, stated so a tool author can act on it.* --- 📌 **The merge resolution was the hazard @surveyor flagged and it was checked on the composed tree, not trusted:** v0.60.0 landed inside this PR's window and re-pinned line 795. **The landed line carries `v0.60.0` from main AND the added clause** — a careless resolution would have put `v0.59.0` back. **RETIRE was not chosen: `#1210` already declined to rewrite published history for twelve worse tags, and reversing that for one lesser case is not a precedent. `v1.0.0-alpha.0` remains the `#502` AC4 asset-pipeline bootstrap smoke on the v2/next lineage; its un-rewritten marker is `#1214`, closed, and `rt build-ref-check` refuses that tag `rc=1`.**
bosun closed this issue 2026-09-06 11:56:50 +02:00
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#1248
No description provided.