fix(recovery): drop the stale #1173 caveat from the recovery PR body (#1500) #1504

Merged
claude merged 3 commits from claude/1500-recovery-body-1173 into main 2026-10-02 21:53:58 +02:00
Member

Refs #1500

What changed

The recovery (B) PR body that reusable-recover-pending-cut.yml writes no longer prints its **Tagged-adopter dependency:** paragraph. That paragraph claimed release-toolkit#1173 had not landed, and that a tag-pinned adopter could therefore run an older recovery binary. Three commits:

  • 50d132f fix(recovery) removes the printf. Both twins change, and changelog.d/1500-recovery-body-1173.fixed.md is added. The commit was rebased onto aa6f603 with the forge's update-branch; git range-diff shows it is unchanged from the original b9997ae.
  • e5e61ca chore(recovery) adds a bash comment in the run block saying why the body carries no pin-floor caveat. It names each supported pin shape (review 7199, item 1).
  • c231c21 docs(recovery): docs/integration.md recovery (B) said toolkit-self's "local @main invocation" was never affected. It now says the wrapper's @main pin goes through the release-toolkit#456 floating-pin override. The wording comes from the withdrawn duplicate #1522 (comment 114308).

The .gitea twin was regenerated with rt gitea-twin --write in both workflow commits, not hand-edited.

Measured (2026-10-02)

  • #1173 is closed. 1347777 adds the file to canonicalFiles (internal/bake/marker.go) and bd28bdd adds it to bakeRefFiles (cmd/rt/prep.go). Both first ship in v0.58.0 (2026-09-05).
  • BUILD_BAKED_TOOLKIT_REF in the file at each tag. It was read through the forge's raw API at every tag, and every tag SHA matched git ls-remote:
tag                .forgejo     .gitea
v0.57.0..v0.57.4   'v0.57.0'    'v0.57.0'     <- frozen
v0.58.0            'v0.58.0'    'v0.58.0'     <- first baked tag
v0.59.0..v0.64.0   own name     own name      (all 12 tags in that range)
  • The fragment restore (dfe9a85, #1166) first ships in v0.57.3. So a tag pin runs it only from v0.58.0 on.
  • docs/integration.md recovery (B) was corrected in dc9df38. This PR brings the workflow text into line with it.

Remove or rewrite

  • Rewrite is right when some run that prints the new text could select a binary older than that text. That reader would need the v0.58.0 floor right there in the body.
  • Remove is right when no supported pin produces such a run. Per resolve toolkit ref and scripts/bootstrap-rt.sh:
    • A tag pin from v0.58.0 resolves to the baked marker, which is the tag's own name. Bootstrap then fetches that tag's rt.
    • An @main pin takes the #456 arm and builds rt from main. Toolkit-self builds it from its own checkout.
    • A commit-SHA pin resolves to the SHA (#336). Bootstrap then refuses it, so no recovery runs. Since #1514 the refusal names the remedy; at 55a12b9 it was already refused as "unsupported toolkit ref".
    • The #1222 wrapper-ref fallback reaches a working bootstrap only with a v... ref, and that ref then fetches its own tag's rt.

Removal is right for every supported pin. Review 7199 found two off-contract shapes that break the "same ref" property:

  • an adopter whose canonical wrapper pins an old tag, but who runs this reusable from @main through a second wrapper;
  • a toolkit-self dispatch from a branch older than dfe9a85.

In neither shape would a pin floor in the body point at the cause, and no remote branch is that old (all 8 heads checked). The bash comment now claims only the supported shapes. The floor still matters when an adopter chooses a pin, and docs/integration.md covers that.

Self-bootstrap (AGENTS.md section 2.1)

By mechanism-of-touch this is a compose-script change: the file is in DefaultComposeScripts (internal/gates/selfboot_check.go:242) and in canonicalFiles. No re-pin is needed: toolkit-self floats @main (AGENTS.md section 2.1). rt check-self-bootstrap passes a main pin before it compares any content (cmd/rt/check_self_bootstrap.go:177). Measured at c231c21:

[check-self-bootstrap] pinned toolkit ref: main
[check-self-bootstrap] floating-pin (release-toolkit#456): main matches main by construction
rc=0

The previous compose-script change agrees. dc9df38 landed with 29b541b, and the job log of that push:main run (#18600, read in the web UI) prints the same floating-pin pass.

Tag-pinned adopters get the change from the next cut tag, which bakes the file to that tag.

Tests

These ran at c231c21, in an LF clone, in a container with go, bats, jq, PyYAML and minisign:

  • go vet ./...: clean. go test ./...: every package ok.
  • bats tests/: 221 ok, 0 not ok, 0 skipped, rc=0. That includes the recovery arms (#1135, #1138, #1160).
  • rt gitea-twin --check: PASS, 11 twins.
  • FRAGMENT_CHECK_COVERAGE=content rt fragment-check changelog.d: PASS. Coverage needs PR metadata, so CI grades it.
  • rt tag-action-digest-check over README.md, docs/integration.md and examples: PASS. scripts/dated-examples-check.py and scripts/contract-paths-check.sh: rc=0.
  • scripts/anchor-check.py could not grade locally because its renderer was unreachable. CI grades it. The docs change adds no link or anchor.
  • PyYAML loads both twins. The comment lines sit inside the recover step's run: | scalar, in the { ... } > "$body_file" group, so they are bash comments. The added workflow lines are ASCII-only (AGENTS.md section 11). bash -n passes on the body group, and all three body variants render.
  • Nothing asserts on the removed text. Outside the twins and docs/integration.md:991, the only 1173 hits under tests/, cmd/ and internal/ are census history (internal/bake/marker.go:151, marker_test.go:102,140).

Verify at source (AGENTS.md section 6)

Review 7199 verified 50d132f. The two commits after it carry that review's items. dismiss_stale_approvals dismissed review 7198, so c231c21 needs a fresh approval. Please check:

  1. The removed sentence is false at every tag from v0.58.0: git show v0.58.0:.forgejo/workflows/reusable-recover-pending-cut.yml | grep BUILD_BAKED_TOOLKIT_REF, and the same for .gitea.
  2. The comment's three pin shapes match resolve toolkit ref and scripts/bootstrap-rt.sh.
  3. The docs/integration.md:991 sentence matches the resolve step's floating-pin-override (release-toolkit#456) arm, given .forgejo/workflows/recover-pending-cut.yml:33.
  4. The twins are generator-identical (rt gitea-twin --check).

🤖 Generated with Claude Code

Refs #1500 ## What changed The recovery (B) PR body that `reusable-recover-pending-cut.yml` writes no longer prints its `**Tagged-adopter dependency:**` paragraph. That paragraph claimed release-toolkit#1173 had not landed, and that a tag-pinned adopter could therefore run an older recovery binary. Three commits: - `50d132f` `fix(recovery)` removes the printf. Both twins change, and `changelog.d/1500-recovery-body-1173.fixed.md` is added. The commit was rebased onto `aa6f603` with the forge's update-branch; `git range-diff` shows it is unchanged from the original `b9997ae`. - `e5e61ca` `chore(recovery)` adds a bash comment in the run block saying why the body carries no pin-floor caveat. It names each supported pin shape (review 7199, item 1). - `c231c21` `docs(recovery)`: `docs/integration.md` recovery (B) said toolkit-self's "local `@main` invocation" was never affected. It now says the wrapper's `@main` pin goes through the release-toolkit#456 floating-pin override. The wording comes from the withdrawn duplicate #1522 (comment 114308). The `.gitea` twin was regenerated with `rt gitea-twin --write` in both workflow commits, not hand-edited. ## Measured (2026-10-02) - #1173 is closed. `1347777` adds the file to `canonicalFiles` (`internal/bake/marker.go`) and `bd28bdd` adds it to `bakeRefFiles` (`cmd/rt/prep.go`). Both first ship in v0.58.0 (2026-09-05). - `BUILD_BAKED_TOOLKIT_REF` in the file at each tag. It was read through the forge's raw API at every tag, and every tag SHA matched `git ls-remote`: ``` tag .forgejo .gitea v0.57.0..v0.57.4 'v0.57.0' 'v0.57.0' <- frozen v0.58.0 'v0.58.0' 'v0.58.0' <- first baked tag v0.59.0..v0.64.0 own name own name (all 12 tags in that range) ``` - The fragment restore (`dfe9a85`, #1166) first ships in v0.57.3. So a tag pin runs it only from v0.58.0 on. - `docs/integration.md` recovery (B) was corrected in `dc9df38`. This PR brings the workflow text into line with it. ## Remove or rewrite - **Rewrite is right when** some run that prints the new text could select a binary older than that text. That reader would need the v0.58.0 floor right there in the body. - **Remove is right when** no supported pin produces such a run. Per `resolve toolkit ref` and `scripts/bootstrap-rt.sh`: - **A tag pin** from v0.58.0 resolves to the baked marker, which is the tag's own name. Bootstrap then fetches that tag's rt. - **An `@main` pin** takes the #456 arm and builds rt from main. Toolkit-self builds it from its own checkout. - **A commit-SHA pin** resolves to the SHA (#336). Bootstrap then refuses it, so no recovery runs. Since #1514 the refusal names the remedy; at `55a12b9` it was already refused as "unsupported toolkit ref". - **The #1222 wrapper-ref fallback** reaches a working bootstrap only with a `v...` ref, and that ref then fetches its own tag's rt. Removal is right for every supported pin. Review 7199 found two off-contract shapes that break the "same ref" property: - an adopter whose canonical wrapper pins an old tag, but who runs this reusable from `@main` through a second wrapper; - a toolkit-self dispatch from a branch older than `dfe9a85`. In neither shape would a pin floor in the body point at the cause, and no remote branch is that old (all 8 heads checked). The bash comment now claims only the supported shapes. The floor still matters when an adopter *chooses* a pin, and `docs/integration.md` covers that. ## Self-bootstrap (AGENTS.md section 2.1) By mechanism-of-touch this is a compose-script change: the file is in `DefaultComposeScripts` (`internal/gates/selfboot_check.go:242`) and in `canonicalFiles`. **No re-pin is needed: toolkit-self floats `@main` (AGENTS.md section 2.1).** `rt check-self-bootstrap` passes a `main` pin before it compares any content (`cmd/rt/check_self_bootstrap.go:177`). Measured at `c231c21`: ``` [check-self-bootstrap] pinned toolkit ref: main [check-self-bootstrap] floating-pin (release-toolkit#456): main matches main by construction rc=0 ``` The previous compose-script change agrees. `dc9df38` landed with `29b541b`, and the job log of that push:main run (#18600, read in the web UI) prints the same floating-pin pass. Tag-pinned adopters get the change from the next cut tag, which bakes the file to that tag. ## Tests These ran at `c231c21`, in an LF clone, in a container with go, bats, jq, PyYAML and minisign: - `go vet ./...`: clean. `go test ./...`: every package ok. - `bats tests/`: 221 ok, 0 not ok, 0 skipped, rc=0. That includes the recovery arms (#1135, #1138, #1160). - `rt gitea-twin --check`: PASS, 11 twins. - `FRAGMENT_CHECK_COVERAGE=content rt fragment-check changelog.d`: PASS. Coverage needs PR metadata, so CI grades it. - `rt tag-action-digest-check` over README.md, `docs/integration.md` and examples: PASS. `scripts/dated-examples-check.py` and `scripts/contract-paths-check.sh`: rc=0. - `scripts/anchor-check.py` could not grade locally because its renderer was unreachable. CI grades it. The docs change adds no link or anchor. - PyYAML loads both twins. The comment lines sit inside the `recover` step's `run: |` scalar, in the `{ ... } > "$body_file"` group, so they are bash comments. The added workflow lines are ASCII-only (AGENTS.md section 11). `bash -n` passes on the body group, and all three body variants render. - Nothing asserts on the removed text. Outside the twins and `docs/integration.md:991`, the only `1173` hits under tests/, cmd/ and internal/ are census history (`internal/bake/marker.go:151`, `marker_test.go:102,140`). ## Verify at source (AGENTS.md section 6) Review 7199 verified `50d132f`. The two commits after it carry that review's items. `dismiss_stale_approvals` dismissed review 7198, so `c231c21` needs a fresh approval. Please check: 1. The removed sentence is false at every tag from v0.58.0: `git show v0.58.0:.forgejo/workflows/reusable-recover-pending-cut.yml | grep BUILD_BAKED_TOOLKIT_REF`, and the same for `.gitea`. 2. The comment's three pin shapes match `resolve toolkit ref` and `scripts/bootstrap-rt.sh`. 3. The `docs/integration.md:991` sentence matches the resolve step's `floating-pin-override (release-toolkit#456)` arm, given `.forgejo/workflows/recover-pending-cut.yml:33`. 4. The twins are generator-identical (`rt gitea-twin --check`). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(recovery): drop the stale #1173 caveat from the recovery PR body (#1500)
All checks were successful
fork-pr-approval-notice / explain fork workflow approval (pull_request_target) Successful in 5s
ac-closure-check / ac-closure check (pull_request) Successful in 7s
ac-closure-check / check (pull_request) Successful in 0s
base-divergence-check / check (pull_request) Successful in 6s
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 / coverage (pull_request) Successful in 7s
fragment-check / density (pull_request) Successful in 7s
fragment-check / check (pull_request) Successful in 0s
gitea-twin-check / check (pull_request) Successful in 6s
go-ci / lint + build + test (pull_request) Successful in 30s
go-ci / record reviewed vs landed commit (pull_request) Has been skipped
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 7s
manifest-check / check (pull_request) Successful in 0s
prep-order-check / check (pull_request) Successful in 6s
readme-pin-check / mirror (pull_request) Successful in 7s
readme-pin-check / digest (pull_request) Successful in 6s
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 32s
tests / dated-examples (pull_request) Successful in 5s
tests / contract-paths (pull_request) Successful in 4s
tests / shellcheck (pull_request) Successful in 4s
toolkit-self-gates / toolkit-self gates (PR's own rt) (pull_request) Successful in 7s
workflow-parse-check / toolkit-self parse guard and controls (pull_request) Successful in 4s
workflow-parse-check / workflow parse and schema (pull_request) Successful in 5s
workflow-parse-check / check (pull_request) Successful in 0s
go-ci / page landing-tree failure (pull_request) Has been skipped
b9997ae995
The body that reusable-recover-pending-cut.yml writes still said #1173
had not landed, so a tag-pinned adopter could run an older recovery
binary. #1173 shipped in v0.58.0: the file is in canonicalFiles
(1347777) and bakeRefFiles (bd28bdd), and every tag from v0.58.0
through v0.63.1 bakes it to its own name, in .forgejo and .gitea alike.

The line is removed, not rewritten. The rt that runs is resolved from
the same ref as the workflow file, so any run that prints this body is
past v0.58.0 and already carries the fragment restore (#1166). The pin
floor matters when an adopter chooses a pin, and docs/integration.md
recovery (B) already states it (dc9df38).

- .forgejo + .gitea twin (rt gitea-twin --write): printf removed; a
  comment in the run block records why there is no caveat
- changelog.d/1500-recovery-body-1173.fixed.md

Refs #1500

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude requested review from bosun 2026-10-02 11:35:36 +02:00
Author
Member

Duplicate note: #1522 (issue #1499) made the same removal independently and is withdrawn in favour of this PR. One item from it is not here yet. I'm offering it as a suggestion for a new commit:

docs/integration.md:991 (on main @ aa6f603) ends with "Toolkit-self's local @main invocation was never affected." The word "local" is wrong:

  • Toolkit-self's wrapper (.forgejo/workflows/recover-pending-cut.yml:33) pins frankenbit/release-toolkit/...@main.
  • The resolve step routes that pin through the #456 floating-pin arm (SOURCE="floating-pin-override (release-toolkit#456)").
  • The toolkit-self local invocation arm handles only a ./.forgejo/... uses line.

The wording #1522 used:

Toolkit-self's wrapper pins @main, which the release-toolkit#456 floating-pin override resolves to main, so toolkit-self was never affected.

Two notes for the reviewer, both measured on main @ aa6f603:

  • v0.64.0 was cut after this PR's base (55a12b9). It also bakes 'v0.64.0' in both twins, so the bake table now holds for v0.58.0 through v0.64.0.
  • Since #1514, bootstrap rt refuses a commit-SHA pin (composite/bootstrap-rt/action.yml:9-11). The SHA arm of the remove-or-rewrite list therefore ends in a refusal rather than a run. The conclusion holds either way.
Duplicate note: #1522 (issue #1499) made the same removal independently and is withdrawn in favour of this PR. One item from it is not here yet. I'm offering it as a suggestion for a new commit: `docs/integration.md:991` (on `main` @ `aa6f603`) ends with "Toolkit-self's local `@main` invocation was never affected." The word "local" is wrong: - Toolkit-self's wrapper (`.forgejo/workflows/recover-pending-cut.yml:33`) pins `frankenbit/release-toolkit/...@main`. - The resolve step routes that pin through the #456 floating-pin arm (`SOURCE="floating-pin-override (release-toolkit#456)"`). - The `toolkit-self local invocation` arm handles only a `./.forgejo/...` uses line. The wording #1522 used: > Toolkit-self's wrapper pins `@main`, which the release-toolkit#456 floating-pin override resolves to `main`, so toolkit-self was never affected. Two notes for the reviewer, both measured on `main` @ `aa6f603`: - `v0.64.0` was cut after this PR's base (`55a12b9`). It also bakes `'v0.64.0'` in both twins, so the bake table now holds for v0.58.0 through v0.64.0. - Since #1514, `bootstrap rt` refuses a commit-SHA pin (`composite/bootstrap-rt/action.yml:9-11`). The SHA arm of the remove-or-rewrite list therefore ends in a refusal rather than a run. The conclusion holds either way.
alex force-pushed claude/1500-recovery-body-1173 from b9997ae995
All checks were successful
fork-pr-approval-notice / explain fork workflow approval (pull_request_target) Successful in 5s
ac-closure-check / ac-closure check (pull_request) Successful in 7s
ac-closure-check / check (pull_request) Successful in 0s
base-divergence-check / check (pull_request) Successful in 6s
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 / coverage (pull_request) Successful in 7s
fragment-check / density (pull_request) Successful in 7s
fragment-check / check (pull_request) Successful in 0s
gitea-twin-check / check (pull_request) Successful in 6s
go-ci / lint + build + test (pull_request) Successful in 30s
go-ci / record reviewed vs landed commit (pull_request) Has been skipped
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 7s
manifest-check / check (pull_request) Successful in 0s
prep-order-check / check (pull_request) Successful in 6s
readme-pin-check / mirror (pull_request) Successful in 7s
readme-pin-check / digest (pull_request) Successful in 6s
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 32s
tests / dated-examples (pull_request) Successful in 5s
tests / contract-paths (pull_request) Successful in 4s
tests / shellcheck (pull_request) Successful in 4s
toolkit-self-gates / toolkit-self gates (PR's own rt) (pull_request) Successful in 7s
workflow-parse-check / toolkit-self parse guard and controls (pull_request) Successful in 4s
workflow-parse-check / workflow parse and schema (pull_request) Successful in 5s
workflow-parse-check / check (pull_request) Successful in 0s
go-ci / page landing-tree failure (pull_request) Has been skipped
to 50d132f592
Some checks failed
fork-pr-approval-notice / explain fork workflow approval (pull_request_target) Successful in 4s
ac-closure-check / ac-closure check (pull_request) Successful in 6s
ac-closure-check / check (pull_request) Successful in 0s
base-divergence-check / check (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 / coverage (pull_request) Successful in 7s
fragment-check / density (pull_request) Successful in 7s
fragment-check / check (pull_request) Successful in 0s
gitea-twin-check / check (pull_request) Successful in 5s
go-ci / lint + build + test (pull_request) Successful in 29s
go-ci / record reviewed vs landed commit (pull_request) Has been skipped
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 7s
manifest-check / check (pull_request) Successful in 0s
prep-order-check / check (pull_request) Successful in 6s
readme-pin-check / mirror (pull_request) Failing after 7s
readme-pin-check / digest (pull_request) Successful in 6s
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 34s
tests / dated-examples (pull_request) Successful in 4s
tests / contract-paths (pull_request) Successful in 4s
tests / shellcheck (pull_request) Successful in 4s
toolkit-self-gates / toolkit-self gates (PR's own rt) (pull_request) Successful in 7s
workflow-parse-check / toolkit-self parse guard and controls (pull_request) Successful in 4s
workflow-parse-check / workflow parse and schema (pull_request) Successful in 4s
workflow-parse-check / check (pull_request) Successful in 0s
go-ci / page landing-tree failure (pull_request) Has been skipped
2026-10-02 21:22:22 +02:00
Compare
alex approved these changes 2026-10-02 21:22:33 +02:00
Dismissed
claude left a comment

Verdict: APPROVE at 50d132f592387685ca38c1af8e75b605fe31cb51, with no blocking findings. I'm posting it as a COMMENT because the forge identity claude authored this PR, and self-approval is a global 422 (AGENTS.md section 8). alex's approval (review 7198) is already on this head. bosun's is still requested.

Which head. This review was briefed at b9997ae. The forge head is now 50d132f, alex's update-branch rebase of b9997ae onto aa6f603 (21:22:21).

  • git range-diff 55a12b9...b9997ae aa6f603...50d132f gives 1: b9997ae = 1: 50d132f.
  • Replaying b9997ae onto aa6f603 with the tests.yml recipe gives tree 1195474, the same as 50d132f's.
  • Just before this post, rt review-submit-check refused b9997ae (rc=1, the head moved) and passed 50d132f (rc=0).

Everything below ran at 50d132f. That is the landing tree: its base is live main, aa6f603.

Verified at source

  • Diff against aa6f603: 3 files, +13/-2. Each twin drops the one printf and gains the 5-line comment, and the fragment is added. Nothing else changes.
  • Bake table, extended to v0.64.0:
    • There are 18 tags from v0.57.0 to v0.64.0, and every tag SHA matches git ls-remote.
    • I read BUILD_BAKED_TOOLKIT_REF at each tag through the forge's raw API, for both twins. v0.57.0 to v0.57.4 carry 'v0.57.0'. Each of the 13 tags from v0.58.0 to v0.64.0 carries its own name.
    • 1347777 and bd28bdd first ship in v0.58.0 (2026-09-05). The restore commit dfe9a85 (#1166) first ships in v0.57.3.
  • Resolve arms, run from the 50d132f YAML against sample wrappers:
    • canonical wrapper @main -> main (source=floating-pin-override (release-toolkit#456))
    • @<tag> with its own bake -> source=baked, so bootstrap FETCHes that tag's rt
    • @<40-hex> -> source=consumer SHA pin (release-toolkit#336), which the *) arm of scripts/bootstrap-rt.sh then refuses. It already refused at 55a12b9 ("unsupported toolkit ref"); #1514 only sharpened the message. So the body's SHA bullet never described a run that gets as far as an rt.
    • no wrapper at the canonical path -> source=baked
  • Gates, run in a golang:1.25 / rt-bats container on an LF clone at 50d132f:
    • rt gitea-twin --check: PASS, 11 twins.
    • rt check-self-bootstrap: floating-pin (release-toolkit#456): main matches main by construction, rc=0. No re-pin is needed (AGENTS.md section 2.1).
    • FRAGMENT_CHECK_COVERAGE=content rt fragment-check changelog.d: PASS.
    • go vet ./...: clean. go test ./...: every package ok.
    • bats tests/: 221 ok, 0 not ok, 0 skipped, with minisign installed.
  • YAML and bash:
    • PyYAML loads both twins.
    • The comment lines sit inside the recover step's run: | scalar, in the { ... } > "$body_file" group. That group is not a heredoc, so the lines are bash comments.
    • No added or removed line contains a non-ASCII byte (section 11).
    • I rendered the group for all three arms: no second cut, REMAINING, and RECHECK_UNGRADED. Each returned rc=0, the body now ends at "...stays manual.", and the follow-on sections still open with their own \n---.
  • No test asserted on the removed text.
    • At aa6f603, excluding CHANGELOG.md, Tagged-adopter, older recovery binary, canonical file set and bake-population fix hit only the two twins and docs/integration.md:991.
    • The 1173 hits under tests/, cmd/ and internal/ are the census history at internal/bake/marker.go:151 and marker_test.go:102,140.
  • Fragment:
    • Its shape matches the template: a header, a blank line, and an indented two-sentence body with "No action needed". (#1500) ends a 17-word summary.
    • .fixed (patch, ### Fixed, docs/conventions.md section Recognized kinds) is the right kind, because the change corrects output adopters read in their recovery PR bodies. That rules out internal.
  • Close keywords: closeKeywordRE (internal/gates/ac_closure_check.go:21) finds no match in the title, body or commit message.
  • CI at 50d132f:
    • 29 of 30 contexts are green, including base-divergence-check.
    • The red one is readme-pin-check / mirror (pull_request), and branch protection does not require it (it requires readme-pin-check / digest).
    • Its log (run 19230) flags README and docs pins still at v0.63.0 now that v0.64.0 is published. #1519 handles that, so it is unrelated to this diff.

Non-blocking

  1. The new comment overstates the mechanism (.forgejo/workflows/reusable-recover-pending-cut.yml:427-431, .gitea twin :440-444). "The rt that ran is resolved from the same ref as this file" holds for every supported pin, but nothing structural enforces it. The same is true of item 2 in the body's verify list. Two shapes break it:

    • The #1222 fallback reads the canonical wrapper, not the running caller.
      • Suppose an adopter runs this reusable through a second wrapper pinned @main, while their .forgejo/workflows/recover-pending-cut.yml pins @v0.57.0. The simulated resolve prints resolved toolkit ref: v0.57.0 (source=wrapper-ref fallback (release-toolkit#1222)).
      • Bootstrap then fetches the v0.57.0 rt, which predates dfe9a85, while the body prints the new text.
      • This is off-contract and needs two wrappers: adopters pin release tags, and @main needs Go on the runner.
    • Toolkit-self builds rt from the dispatched commit.
      • The main) arm of bootstrap-rt.sh builds from $GITHUB_WORKSPACE, while the workflow file comes from @main.
      • A dispatch from a branch cut between 4445750 (the wrapper was added) and dfe9a85 would pair the new text with an rt that lacks the restore.
      • All 8 remote heads contain dfe9a85 (checked), so no live branch can do this.

    Neither shape argues for keeping or rewriting the caveat. In neither case would a pin floor in the body point at the cause, so removing it is still right. If a new commit lands for another reason, this ASCII wording claims only the supported shapes:

    # No pin-floor caveat in this body (release-toolkit#1500). A tag pin
    # from v0.58.0 bakes this file to its own tag (#1173) and fetches that
    # tag's rt; an @main pin builds rt from main (toolkit-self: from its
    # checkout); a commit pin is refused at bootstrap (#1514). Each of those
    # runs has the fragment restore (#1166). The floor matters when CHOOSING
    # a pin: docs/integration.md, recovery (B).
    
  2. Two body statements went stale with the rebase:

    • "AGENTS.md section 2 still describes the red and the re-pin" no longer holds. aa9521b (#1511) is in aa6f603 but not in 55a12b9, and section 2.1 now says no re-pin is needed.
    • The section 8 Axis C caveat on run 18600 can go. I read that run's job log in the web UI. It is the push:main run for 29b541b, which landed together with dc9df38, and its run check-self-bootstrap step prints the floating-pin pass.
  3. #1500 wording. "shipped five weeks ago" overstates it: v0.58.0 is dated 2026-09-05, 27 days before today.

Carried-over docs suggestion (comment 114308)

The finding is correct:

  • docs/integration.md:991 says "Toolkit-self's local @main invocation".
  • But .forgejo/workflows/recover-pending-cut.yml:33 pins frankenbit/release-toolkit/...@main, and the simulated resolve takes floating-pin-override (release-toolkit#456).
  • The local-invocation arm matches only a ./.forgejo/... uses line.

The sentence's conclusion, "never affected", is right. Only the mechanism name is wrong.

  • It belongs in this PR when another commit lands anyway, such as the comment wording above or a rebase forced by #1519 landing first. Add a matching AC to #1500 at the same time. The comment then points readers to an accurate recovery (B) paragraph.
  • It belongs in a follow-up otherwise. 50d132f is approved and green on every required context, and a docs-only wording change should not reset that.

I lean towards a follow-up. Either way it needs a tracker: #1499 carried it as AC 2 and is now shut, and #1500 has no matching AC.

**Verdict: APPROVE at `50d132f592387685ca38c1af8e75b605fe31cb51`**, with no blocking findings. I'm posting it as a COMMENT because the forge identity `claude` authored this PR, and self-approval is a global 422 (AGENTS.md section 8). alex's approval (review 7198) is already on this head. bosun's is still requested. **Which head.** This review was briefed at `b9997ae`. The forge head is now `50d132f`, alex's update-branch rebase of `b9997ae` onto `aa6f603` (21:22:21). - `git range-diff 55a12b9...b9997ae aa6f603...50d132f` gives `1: b9997ae = 1: 50d132f`. - Replaying `b9997ae` onto `aa6f603` with the tests.yml recipe gives tree `1195474`, the same as `50d132f`'s. - Just before this post, `rt review-submit-check` refused `b9997ae` (rc=1, the head moved) and passed `50d132f` (rc=0). Everything below ran at `50d132f`. That is the landing tree: its base is live main, `aa6f603`. ### Verified at source - **Diff against `aa6f603`:** 3 files, +13/-2. Each twin drops the one printf and gains the 5-line comment, and the fragment is added. Nothing else changes. - **Bake table, extended to v0.64.0:** - There are 18 tags from v0.57.0 to v0.64.0, and every tag SHA matches `git ls-remote`. - I read `BUILD_BAKED_TOOLKIT_REF` at each tag through the forge's raw API, for both twins. v0.57.0 to v0.57.4 carry `'v0.57.0'`. Each of the 13 tags from v0.58.0 to v0.64.0 carries its own name. - `1347777` and `bd28bdd` first ship in v0.58.0 (2026-09-05). The restore commit `dfe9a85` (#1166) first ships in v0.57.3. - **Resolve arms**, run from the `50d132f` YAML against sample wrappers: - canonical wrapper `@main` -> `main (source=floating-pin-override (release-toolkit#456))` - `@<tag>` with its own bake -> `source=baked`, so bootstrap FETCHes that tag's rt - `@<40-hex>` -> `source=consumer SHA pin (release-toolkit#336)`, which the `*)` arm of `scripts/bootstrap-rt.sh` then refuses. It already refused at `55a12b9` ("unsupported toolkit ref"); #1514 only sharpened the message. So the body's SHA bullet never described a run that gets as far as an rt. - no wrapper at the canonical path -> `source=baked` - **Gates**, run in a golang:1.25 / rt-bats container on an LF clone at `50d132f`: - `rt gitea-twin --check`: PASS, 11 twins. - `rt check-self-bootstrap`: `floating-pin (release-toolkit#456): main matches main by construction`, rc=0. No re-pin is needed (AGENTS.md section 2.1). - `FRAGMENT_CHECK_COVERAGE=content rt fragment-check changelog.d`: PASS. - `go vet ./...`: clean. `go test ./...`: every package ok. - `bats tests/`: 221 ok, 0 not ok, 0 skipped, with minisign installed. - **YAML and bash:** - PyYAML loads both twins. - The comment lines sit inside the `recover` step's `run: |` scalar, in the `{ ... } > "$body_file"` group. That group is not a heredoc, so the lines are bash comments. - No added or removed line contains a non-ASCII byte (section 11). - I rendered the group for all three arms: no second cut, `REMAINING`, and `RECHECK_UNGRADED`. Each returned rc=0, the body now ends at "...stays manual.", and the follow-on sections still open with their own `\n---`. - **No test asserted on the removed text.** - At `aa6f603`, excluding CHANGELOG.md, `Tagged-adopter`, `older recovery binary`, `canonical file set` and `bake-population fix` hit only the two twins and `docs/integration.md:991`. - The `1173` hits under tests/, cmd/ and internal/ are the census history at `internal/bake/marker.go:151` and `marker_test.go:102,140`. - **Fragment:** - Its shape matches the template: a header, a blank line, and an indented two-sentence body with "No action needed". `(#1500)` ends a 17-word summary. - `.fixed` (patch, `### Fixed`, docs/conventions.md section Recognized kinds) is the right kind, because the change corrects output adopters read in their recovery PR bodies. That rules out `internal`. - **Close keywords:** `closeKeywordRE` (`internal/gates/ac_closure_check.go:21`) finds no match in the title, body or commit message. - **CI at `50d132f`:** - 29 of 30 contexts are green, including `base-divergence-check`. - The red one is `readme-pin-check / mirror (pull_request)`, and branch protection does not require it (it requires `readme-pin-check / digest`). - Its log (run 19230) flags README and docs pins still at v0.63.0 now that v0.64.0 is published. #1519 handles that, so it is unrelated to this diff. ### Non-blocking 1. **The new comment overstates the mechanism** (`.forgejo/workflows/reusable-recover-pending-cut.yml:427-431`, `.gitea` twin `:440-444`). "The rt that ran is resolved from the same ref as this file" holds for every supported pin, but nothing structural enforces it. The same is true of item 2 in the body's verify list. Two shapes break it: - **The #1222 fallback reads the canonical wrapper, not the running caller.** - Suppose an adopter runs this reusable through a second wrapper pinned `@main`, while their `.forgejo/workflows/recover-pending-cut.yml` pins `@v0.57.0`. The simulated resolve prints `resolved toolkit ref: v0.57.0 (source=wrapper-ref fallback (release-toolkit#1222))`. - Bootstrap then fetches the v0.57.0 rt, which predates `dfe9a85`, while the body prints the new text. - This is off-contract and needs two wrappers: adopters pin release tags, and `@main` needs Go on the runner. - **Toolkit-self builds rt from the dispatched commit.** - The `main)` arm of `bootstrap-rt.sh` builds from `$GITHUB_WORKSPACE`, while the workflow file comes from `@main`. - A dispatch from a branch cut between `4445750` (the wrapper was added) and `dfe9a85` would pair the new text with an rt that lacks the restore. - All 8 remote heads contain `dfe9a85` (checked), so no live branch can do this. Neither shape argues for keeping or rewriting the caveat. In neither case would a pin floor in the body point at the cause, so removing it is still right. If a new commit lands for another reason, this ASCII wording claims only the supported shapes: ``` # No pin-floor caveat in this body (release-toolkit#1500). A tag pin # from v0.58.0 bakes this file to its own tag (#1173) and fetches that # tag's rt; an @main pin builds rt from main (toolkit-self: from its # checkout); a commit pin is refused at bootstrap (#1514). Each of those # runs has the fragment restore (#1166). The floor matters when CHOOSING # a pin: docs/integration.md, recovery (B). ``` 2. **Two body statements went stale with the rebase:** - "AGENTS.md section 2 still describes the red and the re-pin" no longer holds. `aa9521b` (#1511) is in `aa6f603` but not in `55a12b9`, and section 2.1 now says no re-pin is needed. - The section 8 Axis C caveat on run 18600 can go. I read that run's job log in the web UI. It is the push:main run for `29b541b`, which landed together with `dc9df38`, and its `run check-self-bootstrap` step prints the floating-pin pass. 3. **#1500 wording.** "shipped five weeks ago" overstates it: v0.58.0 is dated 2026-09-05, 27 days before today. ### Carried-over docs suggestion (comment 114308) The finding is correct: - `docs/integration.md:991` says "Toolkit-self's local `@main` invocation". - But `.forgejo/workflows/recover-pending-cut.yml:33` pins `frankenbit/release-toolkit/...@main`, and the simulated resolve takes `floating-pin-override (release-toolkit#456)`. - The local-invocation arm matches only a `./.forgejo/...` uses line. The sentence's conclusion, "never affected", is right. Only the mechanism name is wrong. - **It belongs in this PR when another commit lands anyway**, such as the comment wording above or a rebase forced by #1519 landing first. Add a matching AC to #1500 at the same time. The comment then points readers to an accurate recovery (B) paragraph. - **It belongs in a follow-up otherwise.** `50d132f` is approved and green on every required context, and a docs-only wording change should not reset that. I lean towards a follow-up. Either way it needs a tracker: #1499 carried it as AC 2 and is now shut, and #1500 has no matching AC.
Author
Member

HOLD. The operator has asked me to fold review 7199's items into this PR and then land it. I'm pushing two new commits on top of 50d132f592387685ca38c1af8e75b605fe31cb51, with no rebase and no force-push:

  1. chore(recovery): the no-caveat comment now names each supported pin shape (review 7199, item 1). Both twins change; the .gitea one was regenerated with rt gitea-twin --write.
  2. docs(recovery): docs/integration.md recovery (B) now says toolkit-self's @main pin goes through the release-toolkit#456 floating-pin override, not a "local" invocation (comment 114308).

dismiss_stale_approvals is on, so this push dismisses review 7198. The new head needs a fresh approval before it can merge. The full new head SHA and a corrected body follow.

HOLD. The operator has asked me to fold review 7199's items into this PR and then land it. I'm pushing two new commits on top of `50d132f592387685ca38c1af8e75b605fe31cb51`, with no rebase and no force-push: 1. `chore(recovery)`: the no-caveat comment now names each supported pin shape (review 7199, item 1). Both twins change; the `.gitea` one was regenerated with `rt gitea-twin --write`. 2. `docs(recovery)`: `docs/integration.md` recovery (B) now says toolkit-self's `@main` pin goes through the release-toolkit#456 floating-pin override, not a "local" invocation (comment 114308). `dismiss_stale_approvals` is on, so this push dismisses review 7198. The new head needs a fresh approval before it can merge. The full new head SHA and a corrected body follow.
The comment said the rt that ran "is resolved from the same ref as this
file". That holds for every supported pin, but not structurally: the
#1222 fallback reads the canonical wrapper rather than the running
caller, and toolkit-self builds rt from its own checkout. Review 7199
measured both shapes; neither is reachable from a supported pin.

The comment now names the supported shapes instead: a tag pin from
v0.58.0 fetches its own tag's rt (#1173), an @main pin builds from main,
and a commit pin is refused at bootstrap (#1514). Comment-only; the .gitea
twin is regenerated with rt gitea-twin --write.

Refs #1500

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs(recovery): toolkit-self's @main pin takes the #456 override (#1500)
All checks were successful
tests / bats (pull_request) Successful in 34s
tests / dated-examples (pull_request) Successful in 4s
tests / contract-paths (pull_request) Successful in 4s
tests / shellcheck (pull_request) Successful in 4s
workflow-parse-check / toolkit-self parse guard and controls (pull_request) Successful in 4s
workflow-parse-check / workflow parse and schema (pull_request) Successful in 4s
workflow-parse-check / check (pull_request) Successful in 0s
ac-closure-check / ac-closure check (pull_request) Successful in 6s
ac-closure-check / check (pull_request) Successful in 0s
fragment-check / coverage (pull_request) Successful in 7s
fragment-check / density (pull_request) Successful in 7s
fragment-check / check (pull_request) Successful in 0s
toolkit-self-gates / toolkit-self gates (PR's own rt) (pull_request) Successful in 7s
go-ci / page landing-tree failure (pull_request) Has been skipped
check-self-bootstrap / check (push) Successful in 5s
gitea-twin-check / check (push) Successful in 4s
go-ci / lint + build + test (push) Successful in 29s
go-ci / record reviewed vs landed commit (push) Successful in 2s
prepared-uncut-check / toolkit-self prepared-uncut controls (push) Successful in 5s
prepared-uncut-check / prepared-but-uncut release (push) Successful in 7s
prepared-uncut-check / check (push) Successful in 0s
release / decide + act (push) Successful in 9s
release / release (push) Successful in 0s
tests / workflow-schema (push) Successful in 3s
tests / bats (push) Successful in 33s
tests / dated-examples (push) Successful in 4s
tests / contract-paths (push) Successful in 4s
tests / shellcheck (push) Successful in 3s
go-ci / page landing-tree failure (push) Has been skipped
release / fire-cut (push) Has been skipped
c231c21f8e
docs/integration.md recovery (B) said "Toolkit-self's local @main
invocation was never affected". Toolkit-self's wrapper
(.forgejo/workflows/recover-pending-cut.yml) pins
frankenbit/release-toolkit/...@main, which the resolve step routes
through the release-toolkit#456 floating-pin override. The local
invocation arm handles only a ./.forgejo/... uses line. The conclusion
was right; the mechanism name was not.

Wording carried over from #1522 (issue #1499, withdrawn as a duplicate).

Refs #1500

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude dismissed alex's review 2026-10-02 21:44:28 +02:00
Reason:

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

Author
Member

HOLD released. The new head is c231c21f8ebb06d5467c9142f632455e49893352, a fast-forward from 50d132f:

  • e5e61ca chore(recovery): names each pin shape in the no-caveat comment. Both twins change.
  • c231c21 docs(recovery): the @main pin in docs/integration.md:991 now goes through the release-toolkit#456 override.

I've corrected the body and checked the read-back against what I sent, byte for byte. What changed in it: the commit list, the bake table now runs to v0.64.0, the SHA and #1222 arms now end at bootstrap, it cites section 2.1 for the no-re-pin note, and the run #18600 log has been read. All local checks passed at c231c21: the gates, go test, and bats (221/221). CI is running.

Review 7198 is dismissed, so the merge needs a fresh crew approval at this head. Pin it first:

rt review-submit-check --owner frankenbit --repo release-toolkit --pr 1504 --reviewed-head c231c21f8ebb06d5467c9142f632455e49893352
HOLD released. The new head is `c231c21f8ebb06d5467c9142f632455e49893352`, a fast-forward from `50d132f`: - `e5e61ca` `chore(recovery)`: names each pin shape in the no-caveat comment. Both twins change. - `c231c21` `docs(recovery)`: the `@main` pin in `docs/integration.md:991` now goes through the release-toolkit#456 override. I've corrected the body and checked the read-back against what I sent, byte for byte. What changed in it: the commit list, the bake table now runs to v0.64.0, the SHA and #1222 arms now end at bootstrap, it cites section 2.1 for the no-re-pin note, and the run #18600 log has been read. All local checks passed at `c231c21`: the gates, `go test`, and bats (221/221). CI is running. Review 7198 is dismissed, so the merge needs a fresh `crew` approval at this head. Pin it first: ``` rt review-submit-check --owner frankenbit --repo release-toolkit --pr 1504 --reviewed-head c231c21f8ebb06d5467c9142f632455e49893352 ```
alex approved these changes 2026-10-02 21:53:16 +02:00
claude merged commit c231c21f8e into main 2026-10-02 21:53:58 +02:00
claude deleted branch claude/1500-recovery-body-1173 2026-10-02 21:53:58 +02:00

Landing identity record

  • PR: #1504
  • landed commit (server merge_commit_sha): c231c21f8ebb06d5467c9142f632455e49893352
  • effective official approval(s):
    • @alex, review #7200, stamped commit: c231c21f8ebb06d5467c9142f632455e49893352
  • replay comparison: no identity change (stamped SHA equals landed SHA)

This is a post-merge identity record. It does not retroactively review the landed object; it records whether the server landed the object that an official approval named.

<!-- release-toolkit:landing-review-record-v1 landed=c231c21f8ebb06d5467c9142f632455e49893352 --> ## Landing identity record - PR: #1504 - landed commit (server merge_commit_sha): `c231c21f8ebb06d5467c9142f632455e49893352` - effective official approval(s): - @alex, review #7200, stamped commit: `c231c21f8ebb06d5467c9142f632455e49893352` - replay comparison: no identity change (stamped SHA equals landed SHA) This is a post-merge identity record. It does not retroactively review the landed object; it records whether the server landed the object that an official approval named.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
frankenbit/release-toolkit!1504
No description provided.