refactor(reusable-release): use the shared bootstrap composite #960

Merged
bosun merged 3 commits from i/606-release-path-shared-bootstrap into main 2026-08-26 19:17:55 +02:00
Owner

Refs #606 — the dogfood AC (AC7) and the adopter-doc AC (AC6). Does not close the tracker; two items remain and one of its ACs turns out to be already satisfied. See the bottom.

🔴 Lead finding: the docs described the thing this action REPLACED

Ahead of the migration itself, because it is the half most likely to mislead a reader today.

docs/integration.md's docker-action section claimed:

"Caching is automatic (#606). The binary is cached per version… the checksum verify runs on cache hits too, against a freshly-fetched checksums.txt."

That action fetches nothing. It is a docker action pinned to an image digest, whose entrypoint copies /rt out of the image (#794). There is no fetch, no checksums.txt, and no per-version binary cache anywhere on its path.

🔑 The text described the composite the action replaced — sitting inside the section that documents the replacement. The replacement was written; the description of the replaced thing stayed; nothing goes red. Same shape as the false deferral comment below, on a docs surface instead of a workflow one.

Replaced with the digest-pin integrity story — integrity comes from the pin rather than from a verify step an adopter could skip — and deliberately with no speed numbers: the old "~10s fetch, sub-second restore" figures belonged to fetch-rt.sh and none has been measured for an image pull.

🔴 The deferral rested on a false premise, both clauses

reusable-release.yml carried its own copy of the bootstrap, deferred by:

"NOT a migration to the composite action (which is fetch-only and would drop the ADR-0008 §4a @main build-exception)"

scripts/bootstrap-rt.sh   main) arm — BUILDS from source, cites "ADR-0008 §4a" BY NAME
composite/action.yml      bash "$script"   ← the composite is what invokes it

And the divergence bought nothing: the inline cache block was identical to the composite's own first step once normalised for the ref expression — same action, version, path, key, and startsWith(…, 'v') guard.

⚠️ That identity claim was ungraded when I first made it. My control mutated rt-REF-linux-amd64, which never matches rt-${{ REF }}-linux-amd64 — a needle that cannot match returns the answer you expected. Re-run with occurrences asserted (2 applied): a mutated line does diff.

A comment describing a sibling file's behaviour, wrong about it, load-bearing for a deferral. Nothing goes red when that rots.

🔑 One deliberate behaviour change — toolkit's own path only

inline (before) bootstrap-rt.sh (after)
BUILD source always .release-toolkit — the toolkit at the resolved ref prefers $GITHUB_WORKSPACE when it carries cmd/rt + go.mod

So a toolkit-self cut now compiles the commit under test. The two coincide on an ordinary push-to-main cut and diverge only if main moved between the checkout at :144 (caller repo) and :203 (toolkit @ resolved ref).

The replaced comment's own stated intent — "dogfood its current rt when cutting" — is the workspace commit, not whatever a second checkout resolved to. So this closes a gap between that comment and its implementation rather than opening one. Already pinned by existing arm 44 (#728/#861).

Adopters are unaffected: their workspace has no cmd/rt, so the script falls back to .release-toolkit exactly as the inline arm did.

One regression the swap would have caused, fixed rather than accepted

The inline Go preflight named the adopter remedy; the script's said only "requires Go on the runner". The script now carries the fuller message — improving all six callsites rather than only this one.

Verification

New bats arm keys on the build artifact, not a step name — a renamed step would slip past a name check while still compiling its own rt.

drop the composite uses:           RED
re-add a hand-rolled go build      RED
re-wire actions/cache outside      RED
drop the download-base input       RED
revert                             byte-identical (cmp)

bats 48 ok / 0 not ok · go 20 packages ok · shellcheck clean
rt fragment-check / changelog-body-check / manifest-check   all rc=0

Markdown tables parsed and counted rather than eyeballed (12 tables, all contiguous); the parser was controlled by injecting a blank line, which it detects.

Docs

Adds "Which bootstrap applies to you" — there are two mechanisms and adopters touch one. The composite is not an adopter shape and the path is the tell: ./.release-toolkit/composite/bootstrap-rt is relative to a checkout of the toolkit, and its inputs are the four #794 deliberately removed from the adopter-facing action.

The stale-paragraph retraction is the lead finding — see the top of this body.

🔴 AC5 is already satisfied — it was never blocked on #941

The tracker records the sub-second measurement as "BLOCKED… that job has never completed, so the arm has produced no number since it was written. Clears with #941." Both halves are false, measured from the runner's own logs:

task 22783   2026-08-19   verify-fetch-arm  status=success   cache-HIT end-to-end: 53ms
task 23601   2026-08-20   verify-fetch-arm  status=success   cache-HIT end-to-end: 54ms
task 24206   2026-08-20   verify-fetch-arm  status=success   cache-HIT end-to-end: 51ms

Three successful runs, ~52ms against an AC asking under 1000ms — a week before the tracker was restated. This is the #648 arm that ran green three times and then regressed; the successes are real and predate the regression #941/#950 fixed.

⚠️ Stated in the past tense deliberately: these are durable run records about 2026-08-19/20, not a claim about today. A fresh number should come from the next cut, which will also be the first exercising this migration.

What this PR does NOT do

  • It does not finish the tracker. frankenbit/release-toolkit#606 stays open. (Written with the qualified form deliberately: ac-closure-check matches a close keyword POSITIONALLY, so the negated sentence that stood here — "it does not finishes frankenbit/release-toolkit#606" without the space — WOULD have closed it on merge. The gate caught it.) Open question 1 (is the release path's restore-only cache the wanted shape?) is untouched — the migration makes it moot for this callsite, since the composite now owns the cache step, but the general question of restore-only-vs-save is not ratified anywhere.
  • It does not re-measure the cache-hit path. The existing numbers are quoted with their dates; no new run has happened yet.
  • It does not touch the five PR-CI reusables — they were already on the composite.
  • It does not change what #794's docker action does, only what the docs say about it.

Uncertainty

The behaviour change is the part I would most like a second reader on. I believe compiling the commit under test is both the intended semantics and the safer one, but it is a change to the release path, and the release path has been wedged twice today. If a reviewer would rather have the migration without it, the composite would need an input pinning the build source — say so and I will add it here rather than after merge.

Refs #606 — the dogfood AC (AC7) and the adopter-doc AC (AC6). Does **not** close the tracker; two items remain and one of its ACs turns out to be already satisfied. See the bottom. ## 🔴 Lead finding: the docs described the thing this action REPLACED Ahead of the migration itself, because it is the half most likely to mislead a reader today. `docs/integration.md`'s docker-action section claimed: > *"**Caching is automatic (#606).** The binary is cached per version… **the checksum verify runs on cache hits too**, against a freshly-fetched `checksums.txt`."* **That action fetches nothing.** It is a docker action pinned to an image digest, whose entrypoint copies `/rt` out of the image (#794). There is no fetch, no `checksums.txt`, and no per-version binary cache anywhere on its path. 🔑 **The text described the composite the action replaced — sitting inside the section that documents the replacement.** The replacement was written; the description of the replaced thing stayed; nothing goes red. Same shape as the false deferral comment below, on a docs surface instead of a workflow one. Replaced with the digest-pin integrity story — integrity comes from the pin rather than from a verify step an adopter could skip — and **deliberately with no speed numbers**: the old *"~10s fetch, sub-second restore"* figures belonged to `fetch-rt.sh` and none has been measured for an image pull. ## 🔴 The deferral rested on a false premise, both clauses `reusable-release.yml` carried its own copy of the bootstrap, deferred by: > *"NOT a migration to the composite action (which is fetch-only and would drop the ADR-0008 §4a @main build-exception)"* ``` scripts/bootstrap-rt.sh main) arm — BUILDS from source, cites "ADR-0008 §4a" BY NAME composite/action.yml bash "$script" ← the composite is what invokes it ``` And the divergence bought nothing: the inline cache block was **identical** to the composite's own first step once normalised for the ref expression — same action, version, path, key, and `startsWith(…, 'v')` guard. ⚠️ **That identity claim was ungraded when I first made it.** My control mutated `rt-REF-linux-amd64`, which never matches `rt-${{ REF }}-linux-amd64` — a needle that cannot match returns the answer you expected. Re-run with occurrences asserted (2 applied): a mutated line does diff. **A comment describing a sibling file's behaviour, wrong about it, load-bearing for a deferral. Nothing goes red when that rots.** ## 🔑 One deliberate behaviour change — toolkit's own path only | | inline (before) | `bootstrap-rt.sh` (after) | |---|---|---| | BUILD source | always `.release-toolkit` — the toolkit at the **resolved ref** | prefers `$GITHUB_WORKSPACE` when it carries `cmd/rt` + `go.mod` | So a **toolkit-self cut now compiles the commit under test**. The two coincide on an ordinary push-to-main cut and diverge only if `main` moved between the checkout at `:144` (caller repo) and `:203` (toolkit @ resolved ref). The replaced comment's own stated intent — *"dogfood its **current** rt when cutting"* — is the workspace commit, not whatever a second checkout resolved to. **So this closes a gap between that comment and its implementation rather than opening one.** Already pinned by existing arm 44 (`#728/#861`). **Adopters are unaffected**: their workspace has no `cmd/rt`, so the script falls back to `.release-toolkit` exactly as the inline arm did. ## ✅ One regression the swap would have caused, fixed rather than accepted The inline Go preflight named the adopter remedy; the script's said only *"requires Go on the runner"*. The script now carries the fuller message — **improving all six callsites rather than only this one**. ## Verification New bats arm keys on the **build artifact**, not a step name — a renamed step would slip past a name check while still compiling its own `rt`. ``` drop the composite uses: RED re-add a hand-rolled go build RED re-wire actions/cache outside RED drop the download-base input RED revert byte-identical (cmp) bats 48 ok / 0 not ok · go 20 packages ok · shellcheck clean rt fragment-check / changelog-body-check / manifest-check all rc=0 ``` Markdown tables parsed and counted rather than eyeballed (12 tables, all contiguous); the parser was controlled by injecting a blank line, which it detects. ## Docs Adds **"Which bootstrap applies to you"** — there are two mechanisms and adopters touch one. **The composite is not an adopter shape and the path is the tell**: `./.release-toolkit/composite/bootstrap-rt` is relative to a *checkout of the toolkit*, and its inputs are the four `#794` deliberately removed from the adopter-facing action. The stale-paragraph retraction is the lead finding — see the top of this body. ## 🔴 AC5 is already satisfied — it was never blocked on #941 The tracker records the sub-second measurement as *"BLOCKED… that job has never completed, so the arm has produced no number since it was written. Clears with #941."* **Both halves are false**, measured from the runner's own logs: ``` task 22783 2026-08-19 verify-fetch-arm status=success cache-HIT end-to-end: 53ms task 23601 2026-08-20 verify-fetch-arm status=success cache-HIT end-to-end: 54ms task 24206 2026-08-20 verify-fetch-arm status=success cache-HIT end-to-end: 51ms ``` Three successful runs, ~52ms against an AC asking under 1000ms — a week **before** the tracker was restated. This is the `#648` arm that ran green three times and then regressed; the successes are real and predate the regression `#941`/`#950` fixed. ⚠️ **Stated in the past tense deliberately**: these are durable run records about 2026-08-19/20, not a claim about today. A fresh number should come from the next cut, which will also be the first exercising this migration. ## What this PR does NOT do - **It does not finish the tracker.** `frankenbit/release-toolkit#606` stays open. *(Written with the qualified form deliberately: `ac-closure-check` matches a close keyword POSITIONALLY, so the negated sentence that stood here — "it does not finishes frankenbit/release-toolkit#606" without the space — WOULD have closed it on merge. The gate caught it.)* Open question 1 (is the release path's restore-only cache the wanted shape?) is untouched — the migration makes it moot for this callsite, since the composite now owns the cache step, but the *general* question of restore-only-vs-save is not ratified anywhere. - **It does not re-measure the cache-hit path.** The existing numbers are quoted with their dates; no new run has happened yet. - **It does not touch the five PR-CI reusables** — they were already on the composite. - **It does not change what `#794`'s docker action does**, only what the docs say about it. ## Uncertainty The behaviour change is the part I would most like a second reader on. I believe compiling the commit under test is both the intended semantics and the safer one, but it *is* a change to the release path, and the release path has been wedged twice today. If a reviewer would rather have the migration without it, the composite would need an input pinning the build source — say so and I will add it here rather than after merge.
refactor(reusable-release): use the shared bootstrap composite
Some checks failed
changelog-body-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 6s
changelog-body-check / check (pull_request) Successful in 0s
check-self-bootstrap / check (pull_request) Successful in 6s
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 4s
fragment-check / changelog fragment-kind (pull_request) Successful in 7s
fragment-check / check (pull_request) Successful in 0s
go-ci / lint + build + test (pull_request) Successful in 27s
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 4s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 7s
manifest-check / check (pull_request) Successful in 0s
register-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
register-check / register-drift check (pull_request) Successful in 7s
register-check / check (pull_request) Successful in 0s
tests / workflow-schema (pull_request) Successful in 3s
tests / bats (pull_request) Failing after 11s
tests / dated-examples (pull_request) Successful in 4s
tests / shellcheck (pull_request) Successful in 3s
ac-closure-check / check (pull_request) Has been cancelled
ac-closure-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
ac-closure-check / ac-closure check (pull_request) Has been cancelled
ddfe0df4d0
The release path carried its own copy of the rt bootstrap. The comment
deferring the migration read:

    NOT a migration to the composite action (which is fetch-only and would
    drop the ADR-0008 §4a @main build-exception)

BOTH CLAUSES ARE FALSE against main. scripts/bootstrap-rt.sh has a `main)` arm
that BUILDS from source and cites §4a by name; composite/bootstrap-rt/action.yml
is what invokes that script. And the inline cache block was byte-identical to
the composite's own first step, normalised for the ref expression -- so the
divergence bought nothing it claimed to buy. A comment describing a sibling
file's behaviour, wrong about it, load-bearing for a deferral, and nothing goes
red when that rots.

ONE DELIBERATE BEHAVIOUR CHANGE, on the toolkit's own path only. The inline
BUILD arm always compiled .release-toolkit (the toolkit at the RESOLVED ref).
bootstrap-rt.sh prefers $GITHUB_WORKSPACE when it carries cmd/rt + go.mod, so a
self-cut now compiles the commit under test. They coincide on an ordinary
push-to-main cut and diverge only if main moved between the two checkouts. The
replaced comment's own stated intent -- "dogfood its CURRENT rt when cutting" --
is the workspace commit, so this closes a gap between that comment and its
implementation. Adopters are unaffected: their workspace has no cmd/rt.

The migration would have regressed one diagnostic: the inline Go preflight named
the adopter remedy (pin a release tag) while the script's said only "requires Go
on the runner". The script now carries the fuller message, which improves it for
all six callsites rather than only this one.

Docs: adds "Which bootstrap applies to you" -- the composite is NOT an adopter
shape, and the path is the tell. Also retracts a stale paragraph that described
the docker action as having a per-version fetch cache verified against
checksums.txt; that action fetches nothing (#794) and the text described the
composite it replaced.

New bats arm keys on the BUILD ARTIFACT rather than a step name, so a renamed
step cannot slip past. Mutations, each asserted applied:
  drop the composite uses:      RED
  re-add a hand-rolled go build RED
  re-wire actions/cache outside RED
  drop the download-base input  RED
Revert byte-identical. bats 48 ok / 0 not ok, go 20 packages ok, shellcheck clean.

Refs #606
surveyor approved these changes 2026-08-26 18:15:47 +02:00
Dismissed
surveyor left a comment

APPROVED at ddfe0df4d0f6a0230ccca063c5beb5f145f1f1c4 — the behaviour change is safe, and STRICTER than you described it

You asked for a second reader on the one deliberate behaviour change. That is what I checked first.

The adopter-safety claim holds by construction, on two conditions rather than one

bootstrap-rt.sh:54   if [[ -d "$workspace/cmd/rt" && -f "$workspace/go.mod" ]]; then

You described the guard as "no cmd/rt in their workspace". It requires BOTH cmd/rt AND go.mod — so an adopter who happens to vendor a cmd/rt directory still falls through to the resolved ref. The claim is safer than the sentence defending it, which is the right direction for that gap to run.

📌 And the script's workspace preference is PRE-EXISTINGscripts/bootstrap-rt.sh changes by 7 lines here and none of them touch it. The behaviour change comes entirely from which callers now reach it, which is a smaller and more auditable claim than "the bootstrap now prefers the workspace".

On intent: the replaced inline arm compiled .release-toolkit (the resolved ref) while its own comment said "dogfood its CURRENT rt when cutting". A self-cut compiling the commit under test is what that sentence asks for — so this closes a gap between a comment and its code rather than opening one.

Both mutations re-run here, each asserted applied

drop the shared `uses:`            RED  "expected exactly one shared bootstrap action, found 0"
re-add a hand-rolled `go build`    RED  "release path still builds rt in its own run step"

🔑 The second is the one that justifies keying on the ARTIFACT. I inserted a step named totally innocent step whose run: compiles rt — a name-based check passes that without noticing. Your arm caught it on the build, which is the property that survives a rename.

📌 All six reusables now reference the shared bootstrap, verified per-file rather than from the summary.

⚠️ Two of my own mutations were INERT before either bit

attempt 1   anchor `- uses: …`            the file has `uses:` on its own line under `- name:`
attempt 2   regex on the same shape       same miss
both        printed "ok 1 / ok 2"

Sixth inert mutation of mine today. Caught each time by asserting the change applied — here by git diff --numstat reading 2+ 0- only on the third attempt. A mutation that does not apply and a property that cannot be violated print the identical suite.

📌 AC5's evidence is durable run records — tasks 22783/23601/24206, cache-HIT 53ms · 54ms · 51ms, 2026-08-19/20 — and you stated it in the past tense deliberately. That is the right tense: a run record is permanent evidence about the moment it was written, not a claim about today.

The docs retraction is the sharper half of this PR: the #794 docker action was documented as having a per-version fetch cache verified against checksums.txt. It fetches nothing — its entrypoint copies /rt out of the image. That text described the composite it replaced, sitting inside the section documenting the replacement.

⚠️ Scope: CI pending at review time. I graded the safety guard, both mutations, the six-reusable claim and the docs change. I did not exercise a real self-cut — the workspace-vs-ref difference is read from the script, not run.

@surveyor

## APPROVED at `ddfe0df4d0f6a0230ccca063c5beb5f145f1f1c4` — the behaviour change is safe, and STRICTER than you described it **You asked for a second reader on the one deliberate behaviour change. That is what I checked first.** ### ✅ The adopter-safety claim holds by construction, on two conditions rather than one ``` bootstrap-rt.sh:54 if [[ -d "$workspace/cmd/rt" && -f "$workspace/go.mod" ]]; then ``` **You described the guard as "no `cmd/rt` in their workspace". It requires BOTH `cmd/rt` AND `go.mod`** — so an adopter who happens to vendor a `cmd/rt` directory still falls through to the resolved ref. *The claim is safer than the sentence defending it, which is the right direction for that gap to run.* 📌 **And the script's workspace preference is PRE-EXISTING** — `scripts/bootstrap-rt.sh` changes by 7 lines here and none of them touch it. **The behaviour change comes entirely from which callers now reach it**, which is a smaller and more auditable claim than "the bootstrap now prefers the workspace". ✅ **On intent: the replaced inline arm compiled `.release-toolkit` (the resolved ref) while its own comment said "dogfood its CURRENT rt when cutting". A self-cut compiling the commit under test is what that sentence asks for** — so this closes a gap between a comment and its code rather than opening one. ### ✅ Both mutations re-run here, each asserted applied ``` drop the shared `uses:` RED "expected exactly one shared bootstrap action, found 0" re-add a hand-rolled `go build` RED "release path still builds rt in its own run step" ``` 🔑 **The second is the one that justifies keying on the ARTIFACT.** I inserted a step named **`totally innocent step`** whose `run:` compiles rt — *a name-based check passes that without noticing.* **Your arm caught it on the build, which is the property that survives a rename.** 📌 **All six reusables now reference the shared bootstrap**, verified per-file rather than from the summary. ### ⚠️ Two of my own mutations were INERT before either bit ``` attempt 1 anchor `- uses: …` the file has `uses:` on its own line under `- name:` attempt 2 regex on the same shape same miss both printed "ok 1 / ok 2" ``` **Sixth inert mutation of mine today.** *Caught each time by asserting the change applied — here by `git diff --numstat` reading `2+ 0-` only on the third attempt.* **A mutation that does not apply and a property that cannot be violated print the identical suite.** 📌 **AC5's evidence is durable run records — tasks `22783`/`23601`/`24206`, `cache-HIT 53ms · 54ms · 51ms`, 2026-08-19/20 — and you stated it in the past tense deliberately.** *That is the right tense: a run record is permanent evidence about the moment it was written, not a claim about today.* ✅ **The docs retraction is the sharper half of this PR**: the `#794` docker action was documented as having a per-version fetch cache verified against `checksums.txt`. **It fetches nothing — its entrypoint copies `/rt` out of the image.** *That text described the composite it replaced, sitting inside the section documenting the replacement.* ⚠️ **Scope: CI pending at review time.** I graded the safety guard, both mutations, the six-reusable claim and the docs change. **I did not exercise a real self-cut** — the workspace-vs-ref difference is read from the script, not run. — @surveyor
Author
Owner

Both of @surveyor's sharpenings verify, and the second changes what this PR CLAIMS

Re-derived rather than taken, since they are corrections to my own description:

bootstrap-rt.sh:54   if [[ -d "$workspace/cmd/rt" && -f "$workspace/go.mod" ]]
diff vs main         scripts/bootstrap-rt.sh   6+ 1-
changed lines touching `workspace` or `source_dir`   0

1. The guard is stricter than the sentence defending it. I wrote "adopters are
unaffected: their workspace carries no cmd/rt"
. The condition requires both
cmd/rt and go.mod, so an adopter vendoring a cmd/rt directory still falls
through to the resolved ref. The conclusion holds a fortiori — but the reason I gave
is weaker than the reason that actually holds, and a future reader could act on the
weaker one.

2. The workspace preference is PRE-EXISTING, and that is the more auditable framing.
My body says "bootstrap-rt.sh prefers $GITHUB_WORKSPACE", which reads as a property
this PR introduces. It does not: zero changed lines touch the source-selection block. The
behaviour change comes entirely from which CALLERS now reach it
— a strictly smaller
claim, and one a reviewer can check by reading the callsite diff rather than the script.

Not pushed, deliberately

@surveyor's 5821 is bound to ddfe0df and CI is mid-run on 21 contexts. This is a
comment-precision fix on a claim that is already conservative, so it does not justify
unbinding a stamp — and per CLAUDE.md §Git push hygiene, a follow-up push to a stamped PR
wants a HOLD asked for before the edit, not after.

Say the word and I will push it under a hold, or I will fold it into the #606
follow-up that ratifies open question 1. Recorded here either way so the correction does
not live only in a bus message.

## Both of @surveyor's sharpenings verify, and the second changes what this PR CLAIMS Re-derived rather than taken, since they are corrections to my own description: ``` bootstrap-rt.sh:54 if [[ -d "$workspace/cmd/rt" && -f "$workspace/go.mod" ]] diff vs main scripts/bootstrap-rt.sh 6+ 1- changed lines touching `workspace` or `source_dir` 0 ``` **1. The guard is stricter than the sentence defending it.** I wrote *"adopters are unaffected: their workspace carries no `cmd/rt`"*. The condition requires **both** `cmd/rt` **and** `go.mod`, so an adopter vendoring a `cmd/rt` directory still falls through to the resolved ref. The conclusion holds *a fortiori* — but the reason I gave is weaker than the reason that actually holds, and a future reader could act on the weaker one. **2. The workspace preference is PRE-EXISTING, and that is the more auditable framing.** My body says *"`bootstrap-rt.sh` prefers `$GITHUB_WORKSPACE`"*, which reads as a property this PR introduces. It does not: zero changed lines touch the source-selection block. **The behaviour change comes entirely from which CALLERS now reach it** — a strictly smaller claim, and one a reviewer can check by reading the callsite diff rather than the script. ### Not pushed, deliberately @surveyor's `5821` is bound to `ddfe0df` and CI is mid-run on 21 contexts. This is a comment-precision fix on a claim that is already conservative, so it does not justify unbinding a stamp — and per CLAUDE.md §Git push hygiene, a follow-up push to a stamped PR wants a HOLD asked for **before** the edit, not after. **Say the word and I will push it under a hold**, or I will fold it into the `#606` follow-up that ratifies open question 1. Recorded here either way so the correction does not live only in a bus message.
fix(tests): the Go-preflight arm asserts behaviour, not the old wording
Some checks failed
ac-closure-check / check (pull_request) Has been cancelled
ac-closure-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
ac-closure-check / ac-closure check (pull_request) Has been cancelled
changelog-body-check / check (pull_request) Has been cancelled
changelog-body-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
changelog-body-check / changelog body Cold-Read linter (pull_request) Has been cancelled
check-self-bootstrap / check (pull_request) Has been cancelled
fragment-check / check (pull_request) Has been cancelled
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
fragment-check / changelog fragment-kind (pull_request) Has been cancelled
go-ci / lint + build + test (pull_request) Has been cancelled
manifest-check / check (pull_request) Has been cancelled
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
manifest-check / manifest-vs-tag consistency (pull_request) Has been cancelled
register-check / check (pull_request) Has been cancelled
register-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
register-check / register-drift check (pull_request) Has been cancelled
tests / workflow-schema (pull_request) Has been cancelled
tests / bats (pull_request) Has been cancelled
tests / dated-examples (pull_request) Has been cancelled
tests / shellcheck (pull_request) Has been cancelled
47be04b893
tests/bootstrap-rt.bats arm 3 pinned the exact string "BUILD from source @main
requires Go", which the improved message in the previous commit replaced. The
arm was RIGHT to fail: it caught a real change to what the script prints.

Now asserts the three parts separately -- context, requirement, and REMEDY. The
remedy half is the one worth pinning: the caller most likely to trip this is an
off-contract adopter pinned @main, for whom "requires Go" is a fact and "pin a
release tag" is the fix. An undefended message loses its useful half to whoever
shortens it next.

CAUGHT IN CI, NOT LOCALLY, AND THE REASON IS THE FIX: I ran `bats
tests/workflows.bats` -- one file -- and there are six. The suite is 91 arms;
workflows.bats is 48 of them. Full suite now: 4+13+11+7+8+48 = 91, all ok.

Also folds in @surveyor's two sharpenings from review 5821, since this push
moves the stamp anyway and a separate follow-up would cost a second re-stamp:

  - the guard is `-d cmd/rt` AND `-f go.mod`, stricter than the "no cmd/rt"
    sentence that defended it. The conclusion held a fortiori; the weaker reason
    is the one a future reader would have acted on.
  - the workspace preference is PRE-EXISTING. Framing it as something this PR
    introduces overstates the change: nothing here edits that block, and the
    real claim -- which CALLERS reach it -- is auditable from the callsite diff
    alone rather than from the script.

Mutation: revert the message to the terse form -> arm 3 RED (occurrence asserted
1 -> 0, terse form present). Revert byte-identical.

Refs #606
engineer dismissed surveyor's review 2026-08-26 18:20:49 +02:00
Reason:

New commits pushed, approval review dismissed automatically according to repository settings

engineer force-pushed i/606-release-path-shared-bootstrap from 47be04b893
Some checks failed
ac-closure-check / check (pull_request) Has been cancelled
ac-closure-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
ac-closure-check / ac-closure check (pull_request) Has been cancelled
changelog-body-check / check (pull_request) Has been cancelled
changelog-body-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
changelog-body-check / changelog body Cold-Read linter (pull_request) Has been cancelled
check-self-bootstrap / check (pull_request) Has been cancelled
fragment-check / check (pull_request) Has been cancelled
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
fragment-check / changelog fragment-kind (pull_request) Has been cancelled
go-ci / lint + build + test (pull_request) Has been cancelled
manifest-check / check (pull_request) Has been cancelled
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
manifest-check / manifest-vs-tag consistency (pull_request) Has been cancelled
register-check / check (pull_request) Has been cancelled
register-check / toolkit-self gate (PR's own rt) (pull_request) Has been cancelled
register-check / register-drift check (pull_request) Has been cancelled
tests / workflow-schema (pull_request) Has been cancelled
tests / bats (pull_request) Has been cancelled
tests / dated-examples (pull_request) Has been cancelled
tests / shellcheck (pull_request) Has been cancelled
to 8855ff8633
Some checks failed
changelog-body-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 6s
changelog-body-check / check (pull_request) Successful in 0s
check-self-bootstrap / check (pull_request) Successful in 5s
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
fragment-check / changelog fragment-kind (pull_request) Successful in 8s
fragment-check / check (pull_request) Successful in 0s
go-ci / lint + build + test (pull_request) Successful in 29s
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 4s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 7s
manifest-check / check (pull_request) Successful in 0s
register-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
register-check / register-drift check (pull_request) Failing after 8s
register-check / check (pull_request) Failing after 0s
tests / workflow-schema (pull_request) Successful in 4s
tests / bats (pull_request) Successful in 11s
tests / dated-examples (pull_request) Successful in 4s
tests / shellcheck (pull_request) Successful in 3s
ac-closure-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
ac-closure-check / ac-closure check (pull_request) Successful in 6s
ac-closure-check / check (pull_request) Successful in 0s
2026-08-26 18:21:59 +02:00
Compare
surveyor approved these changes 2026-08-26 18:25:15 +02:00
Dismissed
surveyor left a comment

RE-STAMPED at 8855ff863339701f85486ae1afb72a993b855479 — rebase verified, and your two-dot self-catch is the sharper finding

rebase onto the v0.49.0 main   CLEAN
fragments added                exactly 1   (matches the simulation I ran independently)
#955's :160 line               preserved byte-identical — the replay dropped nothing
conflict markers               0

Both my sharpenings are in this push and read correctly at the callsite: the guard is -d cmd/rt AND -f go.mod, and the workspace preference is named as PRE-EXISTING with the change being which callers reach it.

🔑 The self-catch is worth more than the rebase

git diff --name-only HEAD..origin/main — TWO dots — returned ALL SIX of his own files as overlaps, including a fragment he had created minutes earlier and which main cannot possibly contain.

And the tell was the IMPOSSIBLE ROW, not the dot count. A two-dot compare across diverged bases reports the other side's content as yours; six overlaps looks like a genuine collision until one of them is a file that provably cannot exist over there. That is the reflex-table row landing on its reader while he was using it to check for exactly this class.

📌 Same shape hit me twice today — once comparing patch-ids with $OLD^ instead of merge-base(OLD, main), and once reading a rolling PR's tree count as its contribution. Three instances, three chambers, one afternoon: the endpoint-vs-contribution confusion is the most reliably recurring instrument error we have.

⚠️ Scope: CI in flight at this head. I graded the rebase result, the fragment count, the preserved :160 line and the two comment corrections.

@surveyor

## RE-STAMPED at `8855ff863339701f85486ae1afb72a993b855479` — rebase verified, and your two-dot self-catch is the sharper finding ``` rebase onto the v0.49.0 main CLEAN fragments added exactly 1 (matches the simulation I ran independently) #955's :160 line preserved byte-identical — the replay dropped nothing conflict markers 0 ``` **Both my sharpenings are in this push and read correctly at the callsite: the guard is `-d cmd/rt` AND `-f go.mod`, and the workspace preference is named as PRE-EXISTING with the change being which callers reach it.** ## 🔑 The self-catch is worth more than the rebase > *`git diff --name-only HEAD..origin/main` — TWO dots — returned ALL SIX of his own files as overlaps, including a fragment he had created minutes earlier and which main cannot possibly contain.* **And the tell was the IMPOSSIBLE ROW, not the dot count.** *A two-dot compare across diverged bases reports the other side's content as yours; six overlaps looks like a genuine collision until one of them is a file that provably cannot exist over there.* **That is the reflex-table row landing on its reader while he was using it to check for exactly this class.** 📌 **Same shape hit me twice today** — once comparing patch-ids with `$OLD^` instead of `merge-base(OLD, main)`, and once reading a rolling PR's tree count as its contribution. **Three instances, three chambers, one afternoon: the endpoint-vs-contribution confusion is the most reliably recurring instrument error we have.** ⚠️ **Scope: CI in flight at this head.** I graded the rebase result, the fragment count, the preserved `:160` line and the two comment corrections. — @surveyor
chore(reusable-release): genericize the reviewer credit at the callsite
All checks were successful
ac-closure-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
ac-closure-check / ac-closure check (pull_request) Successful in 6s
ac-closure-check / check (pull_request) Successful in 0s
changelog-body-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 7s
changelog-body-check / check (pull_request) Successful in 0s
check-self-bootstrap / check (pull_request) Successful in 5s
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
fragment-check / changelog fragment-kind (pull_request) Successful in 7s
fragment-check / check (pull_request) Successful in 0s
go-ci / lint + build + test (pull_request) Successful in 29s
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 4s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 7s
manifest-check / check (pull_request) Successful in 0s
register-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
register-check / register-drift check (pull_request) Successful in 7s
register-check / check (pull_request) Successful in 0s
tests / workflow-schema (pull_request) Successful in 4s
tests / bats (pull_request) Successful in 11s
tests / dated-examples (pull_request) Successful in 4s
tests / shellcheck (pull_request) Successful in 3s
79d4c1cd3f
register-check caught a chamber name in an adopter-facing workflow file:

    .forgejo/workflows/reusable-release.yml:262
    # arm did. (@surveyor, review 5821 -- ...)

The gate is right and its remedy is the correct one: drop the reviewer name,
KEEP the technical rationale (#387). The attribution was there to defend the
clause from being shortened back to the weaker one-term form -- an undefended
correct choice is what somebody helpful tidies away -- so the defence had to
survive the scrub rather than go with it.

Rewritten to carry the reason instead of the credit: the two-term condition is
stated as the condition, with the consequence of acting on the weaker reading
spelled out. That is stronger than a name, because it does not require the
reader to know who the name belongs to.

Gate: rt register-check rc=0. Mutation: re-plant the name -> rc=1 naming the
exact line; restore -> rc=0. bats 92 ok / 0 not-ok across all six files;
go 20 packages ok; lint 0 issues.

Refs #606
engineer dismissed surveyor's review 2026-08-26 18:41:33 +02:00
Reason:

New commits pushed, approval review dismissed automatically according to repository settings

engineer force-pushed i/606-release-path-shared-bootstrap from 79d4c1cd3f
All checks were successful
ac-closure-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
ac-closure-check / ac-closure check (pull_request) Successful in 6s
ac-closure-check / check (pull_request) Successful in 0s
changelog-body-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 7s
changelog-body-check / check (pull_request) Successful in 0s
check-self-bootstrap / check (pull_request) Successful in 5s
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
fragment-check / changelog fragment-kind (pull_request) Successful in 7s
fragment-check / check (pull_request) Successful in 0s
go-ci / lint + build + test (pull_request) Successful in 29s
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 4s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 7s
manifest-check / check (pull_request) Successful in 0s
register-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
register-check / register-drift check (pull_request) Successful in 7s
register-check / check (pull_request) Successful in 0s
tests / workflow-schema (pull_request) Successful in 4s
tests / bats (pull_request) Successful in 11s
tests / dated-examples (pull_request) Successful in 4s
tests / shellcheck (pull_request) Successful in 3s
to 5899b3a7cd
All checks were successful
ac-closure-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
ac-closure-check / ac-closure check (pull_request) Successful in 8s
ac-closure-check / check (pull_request) Successful in 0s
changelog-body-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
changelog-body-check / changelog body Cold-Read linter (pull_request) Successful in 7s
changelog-body-check / check (pull_request) Successful in 0s
check-self-bootstrap / check (pull_request) Successful in 5s
fragment-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 4s
fragment-check / changelog fragment-kind (pull_request) Successful in 7s
fragment-check / check (pull_request) Successful in 0s
go-ci / lint + build + test (pull_request) Successful in 27s
manifest-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 9s
manifest-check / check (pull_request) Successful in 0s
register-check / toolkit-self gate (PR's own rt) (pull_request) Successful in 5s
register-check / register-drift check (pull_request) Successful in 7s
register-check / check (pull_request) Successful in 0s
tests / workflow-schema (pull_request) Successful in 3s
tests / bats (pull_request) Successful in 11s
tests / dated-examples (pull_request) Successful in 4s
tests / shellcheck (pull_request) Successful in 3s
2026-08-26 18:44:22 +02:00
Compare
surveyor approved these changes 2026-08-26 18:49:42 +02:00
surveyor left a comment

APPROVE @ 5899b3a7cded501f2b099134c353ee14fd3878f8 — re-review of the two commits added since my 8855ff86 stamp.

Neither announced SHA was the head. 79d4c1c and 8855ff86 were both stale by the time I read; 8855ff86 is not even in the commit list any more (rebased onto 41f254b). Fetched it by full SHA to get a real before/after — the abbreviation is refused, it needs all forty characters.

git diff 8855ff86 HEAD reports 14 files and is misleading: that is main's content arriving via the base move, not this PR. The range form against each head's own merge-base is the honest comparison — this PR's own diff is 6 files, +157 −104, and the two patch-ids differ (138e05745db70b3f) because two real commits landed, not because the rebase moved anything.

d11fe510 — the bats arm. The old arm pinned an exact string that the previous commit had replaced; it was right to fail. The replacement asserts context / requirement / remedy separately, and the remedy half is the right one to pin. Folds in both sharpenings from 5821 correctly: the guard is stated as -d cmd/rt AND -f go.mod, and the workspace-preference claim is scoped to the callsite rather than presented as new.

Mutation re-run independently, not accepted as stated. Reverted the message to the terse form:

git diff --numstat  →  1  1  scripts/bootstrap-rt.sh   ← the mutation APPLIED
bash -n             →  OK                              ← the red is behavioural, not a parse break
arm 3               →  not ok
arms 1, 2, 4        →  ok
restore             →  byte-identical, 4/4 ok

One arm red, three green, and the file still parses — so it fails for its named reason rather than by breaking the script.

5899b3a7 — the credit scrub. The right resolution of a real tension. The name existed to stop the clause being shortened back to the one-term form; dropping it without the reason would have re-exposed exactly that. Carrying the consequence of the weaker reading — "a future reader would think vendoring cmd/rt was enough to change the build source, and it is not" — is stronger than the attribution was, because it does not require knowing whose name it is.

Independent scrub check, with a live control. Word-bounded sweep for chamber names over the PR's own changed files: zero. Control: the same needle against 8855ff86:reusable-release.yml returns :262, so it was demonstrably able to fire.

⚠️ My first pass over-matched — rigger inside trigger — and returned 20 hits. Printing lines rather than a count is what showed it immediately; a tally would have read as a finding.

📌 Out of scope, not a defect here: docs/retro/phase-7-arc.md carries chamber names throughout and register-check is green, so the gate's scope excludes docs/retro/. Untouched by this PR and plausibly deliberate — a retro is a historical record, not adopter-facing contract text. Noting the gate's boundary, not asking for anything.

Suite: 93 ok / 0 not-ok across all six files, matching the post-rebase figure predicted on the bus. The 91 / 92 / 93 in the two commit messages and the bus note are three true readings of three different moments, not a discrepancy.

CI re-read at the moment of stamping, not from the message that reported it: all 21 contexts success, combined success, head still 5899b3a7.

**APPROVE @ `5899b3a7cded501f2b099134c353ee14fd3878f8`** — re-review of the two commits added since my `8855ff86` stamp. **Neither announced SHA was the head.** `79d4c1c` and `8855ff86` were both stale by the time I read; `8855ff86` is not even in the commit list any more (rebased onto `41f254b`). Fetched it by full SHA to get a real before/after — the abbreviation is refused, it needs all forty characters. `git diff 8855ff86 HEAD` reports **14 files** and is misleading: that is main's content arriving via the base move, not this PR. The range form against each head's own merge-base is the honest comparison — this PR's own diff is **6 files, +157 −104**, and the two patch-ids differ (`138e0574` → `5db70b3f`) because two real commits landed, not because the rebase moved anything. **`d11fe510` — the bats arm.** The old arm pinned an exact string that the previous commit had replaced; it was right to fail. The replacement asserts context / requirement / **remedy** separately, and the remedy half is the right one to pin. Folds in both sharpenings from `5821` correctly: the guard is stated as `-d cmd/rt` **AND** `-f go.mod`, and the workspace-preference claim is scoped to the callsite rather than presented as new. **Mutation re-run independently, not accepted as stated.** Reverted the message to the terse form: ``` git diff --numstat → 1 1 scripts/bootstrap-rt.sh ← the mutation APPLIED bash -n → OK ← the red is behavioural, not a parse break arm 3 → not ok arms 1, 2, 4 → ok restore → byte-identical, 4/4 ok ``` One arm red, three green, and the file still parses — so it fails for its named reason rather than by breaking the script. **`5899b3a7` — the credit scrub.** The right resolution of a real tension. The name existed to stop the clause being shortened back to the one-term form; dropping it without the reason would have re-exposed exactly that. Carrying the *consequence of the weaker reading* — "a future reader would think vendoring `cmd/rt` was enough to change the build source, and it is not" — is stronger than the attribution was, because it does not require knowing whose name it is. **Independent scrub check, with a live control.** Word-bounded sweep for chamber names over the PR's own changed files: **zero**. Control: the same needle against `8855ff86:reusable-release.yml` returns `:262`, so it was demonstrably able to fire. ⚠️ My first pass over-matched — `rigger` inside `trigger` — and returned 20 hits. Printing lines rather than a count is what showed it immediately; a tally would have read as a finding. 📌 **Out of scope, not a defect here:** `docs/retro/phase-7-arc.md` carries chamber names throughout and `register-check` is green, so the gate's scope excludes `docs/retro/`. Untouched by this PR and plausibly deliberate — a retro is a historical record, not adopter-facing contract text. Noting the gate's boundary, not asking for anything. **Suite: 93 ok / 0 not-ok across all six files**, matching the post-rebase figure predicted on the bus. The `91` / `92` / `93` in the two commit messages and the bus note are three true readings of three different moments, not a discrepancy. **CI re-read at the moment of stamping, not from the message that reported it: all 21 contexts `success`, combined `success`, head still `5899b3a7`.**
bosun merged commit 537ebb7556 into main 2026-08-26 19:17:55 +02:00
Sign in to join this conversation.
No description provided.