diff --git a/RELEASING.md b/RELEASING.md index f23500a6..f96814c3 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -60,12 +60,12 @@ moved. Every step below exists to put that check before the irreversible one. already public, and a published tag that changes meaning is worse than one that never built. Bump to the next version, commit, run the preflight, and tag that. -`v0.1.0-rc3` is the standing example — pushed to `gh` while every crate still -said `0.1.0-rc2`, so `dist` refused and the four jobs behind `plan` skipped. It -has no GitHub release and is left as it is. (It is on `gh` **only**; `origin` -and `gitea` carry `rc1` and `rc2`. Check with `git ls-remote --tags ` -rather than assuming the mirrors agree — they did not.) +The worked example is `v0.1.0-rc3`: it was pushed while every crate still said +`0.1.0-rc2`, `dist` refused, and the four jobs behind `plan` skipped. No release +was ever built from it. -A tag with no release is not a tag to clean up on the way to cutting one; -whether the stale `rc` tags are ever removed is a separate decision, and not a -step here. +**Ask which tags exist; do not trust a document that tells you.** `git tag -l`, +and `git ls-remote --tags ` for each remote you push to. Which tags are +where is a fact with a shelf life — it changed twice while this file was being +written — so this file deliberately records no inventory of it. Cleaning up a +dead tag is a separate decision and is not a step in cutting a release. diff --git a/context/code/tooling.md b/context/code/tooling.md index 708c35e3..84803020 100644 --- a/context/code/tooling.md +++ b/context/code/tooling.md @@ -341,7 +341,7 @@ autogenerated mechanism, `README.md` §Installation describes the result, and plan. So the preflight is the second half of the fix; `RELEASING.md` is the first. -**What happened.** `v0.1.0-rc3` was pushed to `gh` while every +**What happened.** `v0.1.0-rc3` was pushed while every crate still said `0.1.0-rc2`. dist matches a tag against the root package's version, refused with *"This workspace doesn't have anything for dist to Release!"*, and the four jobs behind `plan` skipped. **Nothing was wrong with @@ -402,19 +402,35 @@ message. So the preflight runs *before* tagging and prints the tag command only once it has passed — the honest path made the easy one, the same shape as `Basis` having no public constructor (gotcha 43). -**"All three remotes" was wrong, and it is worth saying which way.** `rc3` is on -**`gh` alone**; `origin` and `gitea` carry `rc1` and `rc2` only -(`git ls-remote --tags `, all three checked). The claim came from -aa4e901's commit message and was repeated from there into this section and into -`RELEASING.md` before anyone ran the command — **that commit message is +**"All three remotes" was wrong when it was finally checked.** `aa4e901`'s +commit message said `v0.1.0-rc3` had been pushed to all three, and that was +copied from there into this section and into `RELEASING.md` before anyone ran +`git ls-remote`. Run, it showed the tag on `gh` alone. **That commit message is superseded on this point and cannot be corrected**, which is why `context/design-principles.md` §6 says an argument must not live only in one. -The irony is local: it sat two paragraphs from *an empty log is a statement -about retention, not about history*, which is the same failure — a remote-shaped -fact asserted rather than asked. It changes nothing about the rule (a published -tag is not moved, and `gh` is the remote with the release machinery) and -everything about how much cleanup there would be, which is exactly the kind of -detail a 2am reader would act on. +The irony was local: it sat two paragraphs from *an empty log is a statement +about retention, not about history* — the same failure, a remote-shaped fact +asserted rather than asked. + +**Then the fact changed again, within hours, and that is the better lesson.** +Three measurements of the same thing in one session: present on all three +remotes and locally; then on `gh` alone; then **nowhere at all** — `rc3` was +deleted while this branch was in review. Only the first reading was careless. +The second and third were each correct when taken, by two different people, and +they disagree. + +So the rule this section reaches for is **not** "ask rather than assert". It is +that **a remote-shaped fact has a shelf life even after you ask**: a verified +answer decays, and prose cannot distinguish a stale line from a live one, so a +reader at 2am has no way to tell which they are holding. A document that records +an inventory is therefore wrong on a schedule it does not control. This section +and `RELEASING.md` consequently record **how to ask** — `git tag -l`, +`git ls-remote --tags ` — and deliberately record no inventory of which +tags exist where. What never decayed is the principle: a wrong tag is left dead +and the next version is cut. Note which half of the original correction survives +and which did not: *the commit message was wrong* is durable, because it is a +fact about a fixed text; *the tag is on `gh` alone* was true and is now false. +The keeper is the one whose subject cannot change. **The primary check is textual and the `dist plan` run is a second opinion.** An absent `dist` must not read as a pass, so the script says which of the two diff --git a/scripts/release-preflight.sh b/scripts/release-preflight.sh index b8fe0248..ac5dbb60 100755 --- a/scripts/release-preflight.sh +++ b/scripts/release-preflight.sh @@ -4,7 +4,7 @@ # Usage: scripts/release-preflight.sh vX.Y.Z[-suffix] # scripts/release-preflight.sh --self-test # -# WHY THIS EXISTS. `v0.1.0-rc3` was pushed to three remotes while every crate +# WHY THIS EXISTS. `v0.1.0-rc3` was pushed while every crate # still said `0.1.0-rc2`. dist matches the tag against the root package version, # refused with "This workspace doesn't have anything for dist to Release!", and # the four jobs behind `plan` skipped. Nothing was wrong with the workflow.