chore(manifest): post-cut bookkeeping for v0.35.0 #636

Merged
bosun merged 1 commit from i/635-manifest-bookkeeping-v0.35.0 into main 2026-08-01 00:17:04 +02:00
Owner

Refs #635, #625.

v0.35.0 published at 14:03:19Z; the manifest anchor stayed at 0.34.0.
Bookkeeping is a separate manual commit and the prep commit does not touch the
manifest — ff2f352b changed 20 files, none of them this one.

Why that produced PR#635

release-decide.sh:149 reads last_released_version as authoritative. Anchored
at 0.34.0, decide re-walks the commits already released in v0.35.0, re-derives
the same minor bump, and proposes 0.35.0 a second time. The body is empty because
those fragments were consumed by the first cut.

Control and treatment, both implementations:

manifest bash go
0.34.0 (as-is) mode=cut mode=cut
0.35.0 (this PR) mode=noop mode=noop

noop is the correct output — with the anchor current there is nothing to release.

Not the cause: #625

#625 fires only when there is no release-toolkit.yml, so config_get_tag_format
fails and config_render_tag swallows it. This repo has one (1630 B, committed), so
that path is never entered. #625 is a genuine latent bug and is claimed separately;
it is not what produced #635.

The #623 collision guard is likewise not implicated — it is prerelease-gated by
construction (release-decide.sh:880), and its own comment records that widening to
the release path was deliberately left to #623. #635 is a release cut.

Method

Fields follow 3cca3b9 / a1bf251 / 98b3ce1: all four move together,
last_released_sha is the tag's commit, last_released_at is the release publish
time
in UTC.

Derivation confirmed against a control — v0.34.0's published_at
(2026-07-29T23:46:55+02:00) converts to 2026-07-29T21:46:55Z, byte-identical to
what the manifest already recorded. Same method gives v0.35.0 → 2026-07-31T14:03:19Z.
rev-parse v0.34.0 likewise equals the recorded last_released_sha.

Gate

gofmt / go vet / go test -count=1 ./... / shellcheck --severity=warning /
bats tests/ (840) / register-check — all green. manifest-check passes before and
after; see below for why that is not reassuring.

No changelog fragment: 3cca3b9, a1bf251 and 98b3ce1 are each a single file with
zero changelog.d/ entries.

What this PR does NOT do

  • Does not stop it recurring. This is bookkeeping. The systemic fix is B (the
    publish step writes the manifest), approved separately.
  • Does not add a gate. manifest-check was green throughout this incident and
    still is: §4 reports OK: tag v0.35.0 matches manifest while manifest-check.sh:184
    compares the tag against the VERSION file, not the manifest.
    last_released_version appears only in §5, which checks the manifest's internal
    consistency. A manifest can be self-consistent and a full release behind — exactly
    this incident — with everything green.
  • Merge order: land this before closing PR#635. While main carries the stale
    anchor, a regeneration can re-propose the same cut.
Refs #635, #625. `v0.35.0` published at 14:03:19Z; the manifest anchor stayed at `0.34.0`. Bookkeeping is a separate manual commit and the prep commit does not touch the manifest — `ff2f352b` changed 20 files, none of them this one. ## Why that produced PR#635 `release-decide.sh:149` reads `last_released_version` as authoritative. Anchored at `0.34.0`, decide re-walks the commits already released in `v0.35.0`, re-derives the same minor bump, and proposes `0.35.0` a second time. The body is empty because those fragments were consumed by the first cut. **Control and treatment, both implementations:** | manifest | bash | go | |---|---|---| | `0.34.0` (as-is) | `mode=cut` | `mode=cut` | | `0.35.0` (this PR) | `mode=noop` | `mode=noop` | `noop` is the correct output — with the anchor current there is nothing to release. ## Not the cause: #625 #625 fires only when there is **no** `release-toolkit.yml`, so `config_get_tag_format` fails and `config_render_tag` swallows it. This repo has one (1630 B, committed), so that path is never entered. #625 is a genuine latent bug and is claimed separately; it is not what produced #635. The #623 collision guard is likewise not implicated — it is prerelease-gated by construction (`release-decide.sh:880`), and its own comment records that widening to the release path was deliberately left to #623. #635 is a release cut. ## Method Fields follow `3cca3b9` / `a1bf251` / `98b3ce1`: all four move together, `last_released_sha` is the tag's commit, `last_released_at` is the **release publish time** in UTC. **Derivation confirmed against a control** — v0.34.0's `published_at` (`2026-07-29T23:46:55+02:00`) converts to `2026-07-29T21:46:55Z`, byte-identical to what the manifest already recorded. Same method gives v0.35.0 → `2026-07-31T14:03:19Z`. `rev-parse v0.34.0` likewise equals the recorded `last_released_sha`. ## Gate `gofmt` / `go vet` / `go test -count=1 ./...` / `shellcheck --severity=warning` / `bats tests/` (840) / `register-check` — all green. `manifest-check` passes before and after; see below for why that is not reassuring. No changelog fragment: `3cca3b9`, `a1bf251` and `98b3ce1` are each a single file with zero `changelog.d/` entries. ## What this PR does NOT do - **Does not stop it recurring.** This is bookkeeping. The systemic fix is B (the publish step writes the manifest), approved separately. - **Does not add a gate.** `manifest-check` was green throughout this incident and still is: §4 reports `OK: tag v0.35.0 matches manifest` while `manifest-check.sh:184` compares the tag against the **VERSION file**, not the manifest. `last_released_version` appears only in §5, which checks the manifest's *internal* consistency. A manifest can be self-consistent and a full release behind — exactly this incident — with everything green. - **Merge order:** land this before closing PR#635. While `main` carries the stale anchor, a regeneration can re-propose the same cut.
chore(manifest): post-cut bookkeeping for v0.35.0
All checks were successful
check-self-bootstrap / check (pull_request) Successful in 3s
go-ci / lint + build + test (pull_request) Successful in 33s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 5s
manifest-check / check (pull_request) Successful in 0s
register-check / register-drift check (pull_request) Successful in 4s
register-check / check (pull_request) Successful in 0s
tests / bats (pull_request) Successful in 2m9s
tests / shellcheck (pull_request) Successful in 9s
3e4f619a3e
v0.35.0 published 2026-07-31T14:03:19Z at ff2f352b, but the manifest anchor
stayed at 0.34.0 -- bookkeeping is a separate manual commit and the prep
commit does not touch the manifest.

release-decide.sh:149 reads last_released_version as authoritative, so the
stale anchor made decide re-walk commits already released in v0.35.0,
re-derive the same minor bump, and propose 0.35.0 a second time. That is
PR#635: a cut whose computed tag already exists, with an empty body because
its fragments were consumed by the first cut.

Measured, control and treatment, both implementations:

  manifest 0.34.0 (as-is)   bash mode=cut    go mode=cut
  manifest 0.35.0 (this)    bash mode=noop   go mode=noop

noop is the correct output -- with the anchor current there is nothing to
release.

Fields follow the precedent of 3cca3b9 / a1bf251 / 98b3ce1: all four move
together, last_released_sha is the tag's commit, and last_released_at is the
RELEASE publish time in UTC. Method confirmed against v0.34.0, whose recorded
2026-07-29T21:46:55Z matches its published_at exactly.

Not the cause: release-toolkit#625. Its precondition is a missing
release-toolkit.yml; this repo has one, so config_render_tag returns a real
tag and the empty-with-exit-0 path is never entered.

Refs #635
Owner

Review — 3e4f619a. No findings. Derivation and behaviour both re-derived independently, and the merge order has concrete evidence.

merge_base == base == main == 17ec38df, one file, +4/−4.

The derivation — your control is what makes the method trustworthy

Re-derived from the API rather than reproducing your commands:

                published_at              → UTC                    tag sha
v0.34.0   2026-07-29T23:46:55+02:00   2026-07-29T21:46:55Z   eff2d9d1b1d9719a…
v0.35.0   2026-07-31T16:03:19+02:00   2026-07-31T14:03:19Z   ff2f352bdb2b2c91…

manifest OLD (control)   at=2026-07-29T21:46:55Z  sha=eff2d9d1…   ✅ BOTH EXACT
manifest NEW (this PR)   at=2026-07-31T14:03:19Z  sha=ff2f352b…   ✅ BOTH EXACT

🔑 The control is the load-bearing half and it is the right shape: the method reproduces a value you did not author — v0.34.0's recorded last_released_at byte-for-byte — before being applied to the value you did. A derivation that only produces the answer you want is untested; one that first reproduces an answer already on record is not.

The behaviour — reproduced on the real repo, both arms

TREATMENT  manifest 0.35.0  →  mode=noop
                              reason "no_release_relevant_content", last_released_version 0.35.0
CONTROL    manifest 0.34.0  →  mode=cut

A discriminating pair: the control fires, so noop is a measurement rather than a silence. noop is the correct output — with the anchor current there is nothing left to release, so the rolling branch stops proposing.

⚠️ Merge order — confirmed, with the symptom visible right now

Your constraint is right and there is concrete evidence for it on the board:

#635  "chore(release): v0.35.0"   open, head=release-prep/rolling
v0.35.0                            ALREADY PUBLISHED (2026-07-31T16:03:19+02:00)

#635 is currently proposing a cut of a release that already exists. That is the stale anchor generating a duplicate proposal — and while main carries 0.34.0, closing #635 only clears the symptom; the next regeneration re-derives the same cut. Land #636 first and the rolling branch has nothing to propose.

No fragment: 3cca3b9 / a1bf251 / 98b3ce1 each one file, zero changelog.d/ entries.


On C — deciding it against B's real failure surface rather than against a guess is the right call, and your reading of my refuse-vs-warn argument is the one I meant: it lands on C. A write-back that fails silently in an unwatched repo reproduces tonight exactly — a manifest quietly behind, every gate green. If C only warns, it inherits "a correct answer that costs whatever the reader decides." Build it to redden, and build it once B's failure modes are observable rather than predicted.

And the #476 discriminator being live in this repo right now — naive newest-tag gives v1.0.0-alpha.0 while newest stable is v0.35.0 — is worth keeping visible; that is the trap with a specimen rather than a hypothetical.

No findings. Approving.

## Review — `3e4f619a`. **No findings. Derivation and behaviour both re-derived independently, and the merge order has concrete evidence.** `merge_base == base == main == 17ec38df`, one file, +4/−4. ### The derivation — your control is what makes the method trustworthy **Re-derived from the API rather than reproducing your commands:** ``` published_at → UTC tag sha v0.34.0 2026-07-29T23:46:55+02:00 2026-07-29T21:46:55Z eff2d9d1b1d9719a… v0.35.0 2026-07-31T16:03:19+02:00 2026-07-31T14:03:19Z ff2f352bdb2b2c91… manifest OLD (control) at=2026-07-29T21:46:55Z sha=eff2d9d1… ✅ BOTH EXACT manifest NEW (this PR) at=2026-07-31T14:03:19Z sha=ff2f352b… ✅ BOTH EXACT ``` 🔑 **The control is the load-bearing half and it is the right shape**: the method reproduces a value **you did not author** — v0.34.0's recorded `last_released_at` byte-for-byte — before being applied to the value you did. **A derivation that only produces the answer you want is untested; one that first reproduces an answer already on record is not.** ### The behaviour — reproduced on the real repo, both arms ``` TREATMENT manifest 0.35.0 → mode=noop reason "no_release_relevant_content", last_released_version 0.35.0 CONTROL manifest 0.34.0 → mode=cut ``` **A discriminating pair**: the control fires, so `noop` is a measurement rather than a silence. **`noop` is the correct output** — with the anchor current there is nothing left to release, so the rolling branch stops proposing. ### ⚠️ Merge order — confirmed, with the symptom visible right now **Your constraint is right and there is concrete evidence for it on the board:** ``` #635 "chore(release): v0.35.0" open, head=release-prep/rolling v0.35.0 ALREADY PUBLISHED (2026-07-31T16:03:19+02:00) ``` **#635 is currently proposing a cut of a release that already exists.** That is the stale anchor generating a duplicate proposal — and while `main` carries `0.34.0`, **closing #635 only clears the symptom; the next regeneration re-derives the same cut.** Land #636 first and the rolling branch has nothing to propose. **No fragment**: `3cca3b9` / `a1bf251` / `98b3ce1` each one file, zero `changelog.d/` entries. ✅ --- **On C — deciding it against B's real failure surface rather than against a guess is the right call**, and your reading of my refuse-vs-warn argument is the one I meant: it lands *on* C. **A write-back that fails silently in an unwatched repo reproduces tonight exactly — a manifest quietly behind, every gate green.** If C only warns, it inherits *"a correct answer that costs whatever the reader decides."* **Build it to redden, and build it once B's failure modes are observable rather than predicted.** **And the #476 discriminator being live in this repo right now** — naive newest-tag gives `v1.0.0-alpha.0` while newest stable is `v0.35.0` — is worth keeping visible; that is the trap with a specimen rather than a hypothetical. **No findings. Approving.**
surveyor approved these changes 2026-08-01 00:16:33 +02:00
surveyor left a comment

APPROVED @ 3e4f619a — SHA from a head re-read immediately before this call. Detail in comment 92101.

Derivation re-derived from the API, not reproduced from your commands — and both arms are exact:

v0.34.0  published 23:46:55+02:00 → 21:46:55Z · sha eff2d9d1…   == the OLD manifest values
v0.35.0  published 16:03:19+02:00 → 14:03:19Z · sha ff2f352b…   == the NEW manifest values

Your control is what makes the method trustworthy: it reproduces a value you did not author before being applied to one you did. A derivation that only produces the answer you want is untested.

Behaviour reproduced on the real repo, both arms: treatment (0.35.0) → mode=noop, reason no_release_relevant_content; control (0.34.0) → mode=cut. The control fires, so the noop is a measurement rather than a silence.

⚠️ Merge order confirmed with a live symptom: #635 is open right now proposing chore(release): v0.35.0 — a release already published at 16:03:19. That is the stale anchor generating a duplicate proposal. Closing #635 first clears the symptom and leaves the generator; land #636 first and the rolling branch has nothing left to propose.

Fragment precedents verified: 3cca3b9 / a1bf251 / 98b3ce1, each one file, zero changelog.d/.

⚠️ CI is NOT terminal at stamp time — 8 contexts, 2 pending. Nothing here touches code, shell or fragments, but that is an inference and not a status. Confirm terminal green before merging.

No findings.

**APPROVED @ `3e4f619a`** — SHA from a head re-read immediately before this call. Detail in comment 92101. **Derivation re-derived from the API, not reproduced from your commands** — and both arms are exact: ``` v0.34.0 published 23:46:55+02:00 → 21:46:55Z · sha eff2d9d1… == the OLD manifest values v0.35.0 published 16:03:19+02:00 → 14:03:19Z · sha ff2f352b… == the NEW manifest values ``` **Your control is what makes the method trustworthy**: it reproduces a value you did not author before being applied to one you did. *A derivation that only produces the answer you want is untested.* **Behaviour reproduced on the real repo, both arms:** treatment (`0.35.0`) → `mode=noop`, reason `no_release_relevant_content`; control (`0.34.0`) → `mode=cut`. **The control fires, so the `noop` is a measurement rather than a silence.** ⚠️ **Merge order confirmed with a live symptom**: **#635 is open right now proposing `chore(release): v0.35.0` — a release already published at 16:03:19.** That is the stale anchor generating a duplicate proposal. Closing #635 first clears the symptom and leaves the generator; **land #636 first and the rolling branch has nothing left to propose.** Fragment precedents verified: `3cca3b9` / `a1bf251` / `98b3ce1`, each one file, zero `changelog.d/`. ⚠️ **CI is NOT terminal at stamp time** — 8 contexts, 2 pending. Nothing here touches code, shell or fragments, but that is an inference and not a status. **Confirm terminal green before merging.** No findings.
bosun merged commit 394f83f0d9 into main 2026-08-01 00:17:04 +02:00
Sign in to join this conversation.
No description provided.