docs(self-bootstrap): check-self-bootstrap, rt repin and arc42 still prescribe the rc re-pin that #456 made dormant #1512

Closed
opened 2026-10-02 15:45:02 +02:00 by claude · 1 comment
Member

#1511 (aa9521b) rewrote AGENTS.md section 2 for the #456 floating pin. Toolkit-self floats every wrapper at @main, so a routine change to the compose machinery needs no re-pin (2.1), and the rc re-pin is dormant (2.2). #1510 named four other surfaces that still describe the old posture and left them out of scope. This issue covers those four. A sweep of origin/main found three more files making the same claim, and they are included too.

Measured

All reads are on live origin/main aa9521b, 2026-10-02.

Under @main, the check cannot go red for drift.

  • cmd/rt/check_self_bootstrap.go:177-183: when the aligned pin is main, the check logs floating-pin (release-toolkit#456): main matches main by construction and returns before comparing any file. The drift comparison (lines 185-247) never runs.
  • All 7 uses: frankenbit/release-toolkit/... lines under .forgejo/workflows/ pin @main.
  • Observed on the forge: PR #1488 changed .forgejo/workflows/reusable-release.yml, the first entry in gates.DefaultComposeScripts. In its check-self-bootstrap / check run (run 18568, job 0, commit dc9df38), the run check-self-bootstrap step logged the floating-pin line, and the job passed.

rt repin is run by hand, never by a workflow.

  • git grep repin over .forgejo/workflows and .gitea/workflows finds only comments. Each baked reusable carries the marker comment # release-toolkit-build-ref (auto-updated by rt prep / rt repin), and reusable-release.yml mentions it in two more comment lines (192, 263). check-self-bootstrap.yml has three run: steps: replay onto the base, build rt, and rt check-self-bootstrap. None of them calls rt repin.
  • #1180 also says rt repin "is not invoked by any workflow".
  • rt repin rewrites only the top-level wrappers in .forgejo/workflows (repinWrappers, cmd/rt/repin.go:103-126). It finds them with wrappers.Discover, which reads that one directory and does not recurse, so it never touches examples/*/.forgejo/workflows.
  • rcTagShape (cmd/rt/repin.go:24) accepts only vX.Y.Z-rc.N, so rt repin cannot put a wrapper back on @main.

Surfaces that still describe the pre-#456 posture

# Where What it says Why it is wrong under @main
1 .forgejo/workflows/check-self-bootstrap.yml:3-17 (header) A red "is exactly one shape: the pinned ref needs to advance". On a compose-script PR "the red is EXPECTED", to be read as "re-pin queued for next cut" The check passes before comparing anything. Under @main, a red means alignment drift or a failed precondition (AGENTS.md section 2.3). The file has no .gitea/ twin.
2 cmd/rt/check_self_bootstrap.go:233-235 (drift failure) "Resolution: tag a new v<X.Y.Z>-rc.N at main's HEAD + re-pin" Right for a deliberate tag pin. After an accidental tag pin, the fix is to put the wrappers back on @main in a reviewed PR, and rt repin cannot do that (AGENTS.md section 2.2).
2a same file, :154-156 (alignment failure) "rt repin bumps every wrapper's uses:@ in lockstep; a manual re-pin must do the same." Under @main, alignment drift means one wrapper slipped off @main. Section 2.2 says to restore that wrapper by hand.
2b same file, :58-60 (--help Long text) "A failure means the pinned ref needs to advance to catch main up" Same as row 1.
3 docs/architecture/contracts/cli-surface.md:98 repin is invoked by "check-self-bootstrap.yml (at RC cut time)" and re-pins "example/consumer-wrapper refs" No workflow invokes it, and it does not touch the example wrappers.
4 docs/architecture/arc42/11-risks-technical-debt.md:13 (Bootstrap-lag) check-self-bootstrap "goes (correctly) red post-merge to signal 're-pin needed'" Under @main, a toolkit-self cut runs the commit it cuts (AGENTS.md section 2.1). There is no lag, and the check does not go red.
4a docs/architecture/arc42/07-deployment-view.md:82-99 (section 7.3, which row 4 cites) The toolkit "must re-pin" before a cut that includes compose changes, and the check "goes (correctly) red post-merge" Same as row 4.
5 cmd/rt/repin.go The command has no doc comment and no Long text The retired scripts/repin.sh header (git show 25c2fb3:scripts/repin.sh, lines 25-31) said it was no longer the routine mechanism for toolkit-self. Neither rt repin --help nor the source says so now.
6 docs/SECURITY.md:33 check-self-bootstrap.yml "fires on any PR that touches a compose-script and requires the baked ref to be re-pinned" Same as row 1.

#1510 did not list rows 2a, 2b, 4a and 6. A git grep on origin/main for the same phrases found them.

Do not port all of the retired repin.sh header. Its case (2) reads "toolkit-self recovery if a wrapper is hand-pinned back to a versioned tag by accident ... repin.sh restores discipline". That contradicts AGENTS.md section 2.2: rt repin accepts only an rc tag, so it cannot restore @main.

No test asserts on the text in rows 2, 2a or 2b. A git grep over *_test.go and tests/ finds no assertion on "Resolution:", "lockstep" or "catch main up". cmd/rt has no check_self_bootstrap_test.go, and no test calls runCheckSelfBootstrap. Nothing tests the command's output.

Why it matters

An author reads the check's header and its failure text when the check goes red or when they touch a compose script. Both still give the advice AGENTS.md section 2.1 now warns against. Running rt repin for a routine change would move every toolkit-self wrapper off @main to an rc tag, a posture change nobody intended. The old AGENTS.md text led #1496's body into the same mistake (review 7179).

Under @main, the check does go red in one case: when a wrapper slips to a tag. The current message then points the reader at rt repin, which cannot repair it.

docs/SECURITY.md is written for adopters, and it describes a protection that toolkit-self no longer exercises.

Acceptance criteria

  • check-self-bootstrap.yml's header says what a red means in each posture. Under @main, a red can only be alignment drift or a failed precondition. Under a tag pin, it is pin drift. The header stays ASCII-only (AGENTS.md section 11). — DONE @ #1513 (4ffde69, reviewed as 4ffde69). The header now has an @main arm (cannot go red for drift; a red is alignment drift or a failed precondition) and a tag-pin arm (pin drift, with both remedies). workflow-parse-check / workflow parse and schema (run 19046, job 2) logged .forgejo/workflows/check-self-bootstrap.yml workflow schema validation OK. One deviation: the AC says the header "stays" ASCII-only, but it never was. The PR added no non-ASCII line and removed two em-dashes (old lines 6 and 12). Two untouched header lines (32 and 37 at 4ffde69) still carry an em-dash. Below the header, 14 more lines carry non-ASCII: 8 comments and 6 echo strings in run: steps. The PR touched none of them.
  • The drift failure message in rt check-self-bootstrap names both remedies: rt repin for a deliberate tag pin, and restoring @main in a reviewed PR for an accidental one. The alignment failure message and the --help Long text agree with it. — DONE @ #1513 (4ffde69, reviewed as 4ffde69). Both reds call logPinRemedies (cmd/rt/check_self_bootstrap.go), which prints the accidental arm (restore @main in a reviewed PR; rt repin cannot) and the deliberate arm (rt repin <vX.Y.Z-rc.N>). The --help Long text describes both postures.
  • A test pins the remedy text of both failure messages. It fails when the @main remedy is removed. — DONE @ #1513 (4ffde69, reviewed as 4ffde69). cmd/rt/check_self_bootstrap_test.go (3 tests, fixture repo with no main ref). Mutant M1, which drops the @main remedy, is killed by both the pin-drift and the alignment-drift test; M2-M5 are each killed by their intended test (PR body, Tests).
  • cli-surface.md's repin row says no workflow invokes it and names what it actually rewrites. TestSubcommandsMatchC5Contract and TestC5ExclusionsAreDocumented stay green. — DONE @ #1513 (4ffde69, reviewed as 4ffde69). The row says no workflow invokes it and that it rewrites the top-level .forgejo/workflows/ wrappers, not the examples/ ones. Both C5 tests passed locally and in go-ci / lint + build + test (pull_request).
  • The arc42 Bootstrap-lag row (section 11.1) and section 7.3 say the lag is dormant under @main and returns with a tag pin. — DONE @ #1513 (4ffde69, reviewed as 4ffde69). Both say the lag is dormant under @main because a toolkit-self cut runs the commit it cuts (AGENTS.md section 2.1), and that it returns with a tag pin.
  • cmd/rt/repin.go carries the #456 note: rt repin is dormant for toolkit-self, is meant only for a deliberate tag pin, and is not a way back to @main. — DONE @ #1513 (4ffde69, reviewed as 4ffde69). A doc comment on newRepinCmd and a Long text. repin.sh's accidental-tag-pin use is deliberately not ported: the script also refused any tag without -rc..
  • docs/SECURITY.md:33 describes how the check behaves in each posture. — DONE @ #1513 (4ffde69, reviewed as 4ffde69). It also says the gate guards release-toolkit's own pin, not the adopter's.
  • rt register-check passes on every changed doc, and go test ./... passes. — DONE @ #1513 (4ffde69, reviewed as 4ffde69). Locally: rt register-check 0 hits on the four docs and the YAML; go test ./... all packages ok. On the forge: register-check / register-drift check (pull_request) and go-ci / lint + build + test (pull_request and push) are success.

Out of scope

  • Several arc42 sections describe a "483d guard": check-self-bootstrap's blob-compare running "on every PR". See 01-introduction-goals.md:45, 04-solution-strategy.md:46, 08-crosscutting-concepts.md:21-24, 10-quality-requirements.md:43, 11-risks-technical-debt.md:12 and 12-glossary.md:27. Under @main the check compares nothing. Whether the bake's Go tests and build-ref-check.yml now do that job is a separate question that needs its own measurement.
  • 11-risks-technical-debt.md:14 attributes the single-ref check to register-check. The only caller of gates.AlignRefs is rt check-self-bootstrap.
  • docs/architecture/arc42/02-constraints.md:24 cites AGENTS.md:131, a line number from before #1511.
#1511 (`aa9521b`) rewrote AGENTS.md section 2 for the #456 floating pin. Toolkit-self floats every wrapper at `@main`, so a routine change to the compose machinery needs no re-pin (2.1), and the rc re-pin is dormant (2.2). #1510 named four other surfaces that still describe the old posture and left them out of scope. This issue covers those four. A sweep of `origin/main` found three more files making the same claim, and they are included too. ## Measured All reads are on live `origin/main` `aa9521b`, 2026-10-02. **Under `@main`, the check cannot go red for drift.** - `cmd/rt/check_self_bootstrap.go:177-183`: when the aligned pin is `main`, the check logs `floating-pin (release-toolkit#456): main matches main by construction` and returns before comparing any file. The drift comparison (lines 185-247) never runs. - All 7 `uses: frankenbit/release-toolkit/...` lines under `.forgejo/workflows/` pin `@main`. - Observed on the forge: PR #1488 changed `.forgejo/workflows/reusable-release.yml`, the first entry in `gates.DefaultComposeScripts`. In its `check-self-bootstrap / check` run (run 18568, job 0, commit `dc9df38`), the `run check-self-bootstrap` step logged the floating-pin line, and the job passed. **`rt repin` is run by hand, never by a workflow.** - `git grep repin` over `.forgejo/workflows` and `.gitea/workflows` finds only comments. Each baked reusable carries the marker comment `# release-toolkit-build-ref (auto-updated by rt prep / rt repin)`, and `reusable-release.yml` mentions it in two more comment lines (192, 263). `check-self-bootstrap.yml` has three `run:` steps: replay onto the base, build `rt`, and `rt check-self-bootstrap`. None of them calls `rt repin`. - #1180 also says `rt repin` "is not invoked by any workflow". - `rt repin` rewrites only the top-level wrappers in `.forgejo/workflows` (`repinWrappers`, `cmd/rt/repin.go:103-126`). It finds them with `wrappers.Discover`, which reads that one directory and does not recurse, so it never touches `examples/*/.forgejo/workflows`. - `rcTagShape` (`cmd/rt/repin.go:24`) accepts only `vX.Y.Z-rc.N`, so `rt repin` cannot put a wrapper back on `@main`. **Surfaces that still describe the pre-#456 posture** | # | Where | What it says | Why it is wrong under `@main` | |---|---|---|---| | 1 | `.forgejo/workflows/check-self-bootstrap.yml:3-17` (header) | A red "is exactly one shape: the pinned ref needs to advance". On a compose-script PR "the red is EXPECTED", to be read as "re-pin queued for next cut" | The check passes before comparing anything. Under `@main`, a red means alignment drift or a failed precondition (AGENTS.md section 2.3). The file has no `.gitea/` twin. | | 2 | `cmd/rt/check_self_bootstrap.go:233-235` (drift failure) | "Resolution: tag a new v<X.Y.Z>-rc.N at main's HEAD + re-pin" | Right for a deliberate tag pin. After an accidental tag pin, the fix is to put the wrappers back on `@main` in a reviewed PR, and `rt repin` cannot do that (AGENTS.md section 2.2). | | 2a | same file, `:154-156` (alignment failure) | "rt repin bumps every wrapper's uses:@<ref> in lockstep; a manual re-pin must do the same." | Under `@main`, alignment drift means one wrapper slipped off `@main`. Section 2.2 says to restore that wrapper by hand. | | 2b | same file, `:58-60` (`--help` Long text) | "A failure means the pinned ref needs to advance to catch main up" | Same as row 1. | | 3 | `docs/architecture/contracts/cli-surface.md:98` | `repin` is invoked by "`check-self-bootstrap.yml` (at RC cut time)" and re-pins "example/consumer-wrapper refs" | No workflow invokes it, and it does not touch the example wrappers. | | 4 | `docs/architecture/arc42/11-risks-technical-debt.md:13` (Bootstrap-lag) | `check-self-bootstrap` "goes (correctly) red post-merge to signal 're-pin needed'" | Under `@main`, a toolkit-self cut runs the commit it cuts (AGENTS.md section 2.1). There is no lag, and the check does not go red. | | 4a | `docs/architecture/arc42/07-deployment-view.md:82-99` (section 7.3, which row 4 cites) | The toolkit "must re-pin" before a cut that includes compose changes, and the check "goes (correctly) red post-merge" | Same as row 4. | | 5 | `cmd/rt/repin.go` | The command has no doc comment and no `Long` text | The retired `scripts/repin.sh` header (`git show 25c2fb3:scripts/repin.sh`, lines 25-31) said it was no longer the routine mechanism for toolkit-self. Neither `rt repin --help` nor the source says so now. | | 6 | `docs/SECURITY.md:33` | `check-self-bootstrap.yml` "fires on any PR that touches a compose-script and requires the baked ref to be re-pinned" | Same as row 1. | #1510 did not list rows 2a, 2b, 4a and 6. A `git grep` on `origin/main` for the same phrases found them. **Do not port all of the retired `repin.sh` header.** Its case (2) reads "toolkit-self recovery if a wrapper is hand-pinned back to a versioned tag by accident ... repin.sh restores discipline". That contradicts AGENTS.md section 2.2: `rt repin` accepts only an rc tag, so it cannot restore `@main`. **No test asserts on the text in rows 2, 2a or 2b.** A `git grep` over `*_test.go` and `tests/` finds no assertion on "Resolution:", "lockstep" or "catch main up". `cmd/rt` has no `check_self_bootstrap_test.go`, and no test calls `runCheckSelfBootstrap`. Nothing tests the command's output. ## Why it matters An author reads the check's header and its failure text when the check goes red or when they touch a compose script. Both still give the advice AGENTS.md section 2.1 now warns against. Running `rt repin` for a routine change would move every toolkit-self wrapper off `@main` to an rc tag, a posture change nobody intended. The old AGENTS.md text led #1496's body into the same mistake (review 7179). Under `@main`, the check does go red in one case: when a wrapper slips to a tag. The current message then points the reader at `rt repin`, which cannot repair it. `docs/SECURITY.md` is written for adopters, and it describes a protection that toolkit-self no longer exercises. ## Acceptance criteria - [x] `check-self-bootstrap.yml`'s header says what a red means in each posture. Under `@main`, a red can only be alignment drift or a failed precondition. Under a tag pin, it is pin drift. The header stays ASCII-only (AGENTS.md section 11). — DONE @ #1513 (`4ffde69`, reviewed as `4ffde69`). The header now has an `@main` arm (cannot go red for drift; a red is alignment drift or a failed precondition) and a tag-pin arm (pin drift, with both remedies). `workflow-parse-check / workflow parse and schema` (run 19046, job 2) logged `.forgejo/workflows/check-self-bootstrap.yml workflow schema validation OK`. One deviation: the AC says the header "stays" ASCII-only, but it never was. The PR added no non-ASCII line and removed two em-dashes (old lines 6 and 12). Two untouched header lines (32 and 37 at `4ffde69`) still carry an em-dash. Below the header, 14 more lines carry non-ASCII: 8 comments and 6 `echo` strings in `run:` steps. The PR touched none of them. - [x] The drift failure message in `rt check-self-bootstrap` names both remedies: `rt repin` for a deliberate tag pin, and restoring `@main` in a reviewed PR for an accidental one. The alignment failure message and the `--help` Long text agree with it. — DONE @ #1513 (`4ffde69`, reviewed as `4ffde69`). Both reds call `logPinRemedies` (`cmd/rt/check_self_bootstrap.go`), which prints the accidental arm (restore `@main` in a reviewed PR; `rt repin` cannot) and the deliberate arm (`rt repin <vX.Y.Z-rc.N>`). The `--help` Long text describes both postures. - [x] A test pins the remedy text of both failure messages. It fails when the `@main` remedy is removed. — DONE @ #1513 (`4ffde69`, reviewed as `4ffde69`). `cmd/rt/check_self_bootstrap_test.go` (3 tests, fixture repo with no `main` ref). Mutant M1, which drops the `@main` remedy, is killed by both the pin-drift and the alignment-drift test; M2-M5 are each killed by their intended test (PR body, Tests). - [x] `cli-surface.md`'s `repin` row says no workflow invokes it and names what it actually rewrites. `TestSubcommandsMatchC5Contract` and `TestC5ExclusionsAreDocumented` stay green. — DONE @ #1513 (`4ffde69`, reviewed as `4ffde69`). The row says no workflow invokes it and that it rewrites the top-level `.forgejo/workflows/` wrappers, not the `examples/` ones. Both C5 tests passed locally and in `go-ci / lint + build + test (pull_request)`. - [x] The arc42 Bootstrap-lag row (section 11.1) and section 7.3 say the lag is dormant under `@main` and returns with a tag pin. — DONE @ #1513 (`4ffde69`, reviewed as `4ffde69`). Both say the lag is dormant under `@main` because a toolkit-self cut runs the commit it cuts (AGENTS.md section 2.1), and that it returns with a tag pin. - [x] `cmd/rt/repin.go` carries the #456 note: `rt repin` is dormant for toolkit-self, is meant only for a deliberate tag pin, and is not a way back to `@main`. — DONE @ #1513 (`4ffde69`, reviewed as `4ffde69`). A doc comment on `newRepinCmd` and a `Long` text. `repin.sh`'s accidental-tag-pin use is deliberately not ported: the script also refused any tag without `-rc.`. - [x] `docs/SECURITY.md:33` describes how the check behaves in each posture. — DONE @ #1513 (`4ffde69`, reviewed as `4ffde69`). It also says the gate guards release-toolkit's own pin, not the adopter's. - [x] `rt register-check` passes on every changed doc, and `go test ./...` passes. — DONE @ #1513 (`4ffde69`, reviewed as `4ffde69`). Locally: `rt register-check` 0 hits on the four docs and the YAML; `go test ./...` all packages ok. On the forge: `register-check / register-drift check (pull_request)` and `go-ci / lint + build + test` (pull_request and push) are success. ## Out of scope - Several arc42 sections describe a "483d guard": `check-self-bootstrap`'s blob-compare running "on every PR". See `01-introduction-goals.md:45`, `04-solution-strategy.md:46`, `08-crosscutting-concepts.md:21-24`, `10-quality-requirements.md:43`, `11-risks-technical-debt.md:12` and `12-glossary.md:27`. Under `@main` the check compares nothing. Whether the bake's Go tests and `build-ref-check.yml` now do that job is a separate question that needs its own measurement. - `11-risks-technical-debt.md:14` attributes the single-ref check to `register-check`. The only caller of `gates.AlignRefs` is `rt check-self-bootstrap`. - `docs/architecture/arc42/02-constraints.md:24` cites `AGENTS.md:131`, a line number from before #1511.
Author
Member

Landed through #1513 at 2026-10-02 16:05:59 +02:00 as a fast-forward: the PR's merge_commit_sha and its head are both 4ffde692129e10c252ec29dea53e910b268452f8. git range-diff aa9521b..4ffde69 against the reviewed range shows both commits (1545552, 4ffde69) as =.

  • Approval: alex, review 7187, APPROVED at 4ffde69, the head that landed.
  • Checks on 4ffde69:
    • All 30 pull_request contexts are success.
    • 15 of the 16 push contexts are success. The 16th, release / fire-cut (push), is pending with "Waiting to run". In the same run (19054), the decide + act job (job 2) logged mode=update, so no cut was decided.
  • Job logs read, not only status rows:
    • check-self-bootstrap / check (push) (run 19050) logged floating-pin (release-toolkit#456): main matches main by construction.
    • workflow-parse-check / workflow parse and schema (run 19046, job 2) logged .forgejo/workflows/check-self-bootstrap.yml workflow schema validation OK.
  • Head branch: claude/1512-self-bootstrap-456-framing no longer exists (branches API 404).
  • Acceptance criteria: all 8 are ticked above. The first carries a deviation. The YAML header was never fully ASCII. The PR added no non-ASCII and removed two em-dashes, but two untouched header lines still contain one each.

Every acceptance criterion is done, so I am shutting this issue by hand. The items under "Out of scope" are not addressed here and still need their own issues.

Landed through #1513 at 2026-10-02 16:05:59 +02:00 as a fast-forward: the PR's `merge_commit_sha` and its head are both `4ffde692129e10c252ec29dea53e910b268452f8`. `git range-diff aa9521b..4ffde69` against the reviewed range shows both commits (`1545552`, `4ffde69`) as `=`. - **Approval:** alex, review 7187, APPROVED at `4ffde69`, the head that landed. - **Checks on `4ffde69`:** - All 30 `pull_request` contexts are success. - 15 of the 16 `push` contexts are success. The 16th, `release / fire-cut (push)`, is pending with "Waiting to run". In the same run (19054), the `decide + act` job (job 2) logged `mode=update`, so no cut was decided. - **Job logs read, not only status rows:** - `check-self-bootstrap / check (push)` (run 19050) logged `floating-pin (release-toolkit#456): main matches main by construction`. - `workflow-parse-check / workflow parse and schema` (run 19046, job 2) logged `.forgejo/workflows/check-self-bootstrap.yml workflow schema validation OK`. - **Head branch:** `claude/1512-self-bootstrap-456-framing` no longer exists (branches API 404). - **Acceptance criteria:** all 8 are ticked above. The first carries a deviation. The YAML header was never fully ASCII. The PR added no non-ASCII and removed two em-dashes, but two untouched header lines still contain one each. Every acceptance criterion is done, so I am shutting this issue by hand. The items under "Out of scope" are not addressed here and still need their own issues.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
frankenbit/release-toolkit#1512
No description provided.