docs(self-bootstrap): the check, rt repin and arc42 follow AGENTS.md section 2 on the @main pin (#1512) #1513

Merged
alex merged 2 commits from claude/1512-self-bootstrap-456-framing into main 2026-10-02 16:05:59 +02:00
Member

Refs #1512

#1511 rewrote AGENTS.md section 2 for the #456 floating pin. This PR brings every other surface that still prescribed the rc re-pin into line with it: check-self-bootstrap's workflow header, failure messages and help, rt repin's doc and help, the C5 repin row, arc42 sections 7.3 and 11.1, and docs/SECURITY.md.

no-changelog: toolkit-self only. rt check-self-bootstrap and rt repin are outside the C5 adopter contract, and the rest is documentation, so no adopter-visible behaviour changes.

What changed

Row numbers are from #1512's table.

Row Surface Now says
1 .forgejo/workflows/check-self-bootstrap.yml header What a red means in each posture. Under @main, the check cannot go red for drift, so a red is alignment drift or a failed precondition, fixed by restoring @main. Under a tag pin, the red on a compose-script PR is expected, and the header names both remedies. The YAML change is comment-only and ASCII-only.
2, 2a rt check-self-bootstrap's drift and alignment reds Both print the same two labelled remedies, from one helper (logPinRemedies). Accidental tag pin: put each wrapper back on @main in a reviewed PR, because rt repin cannot. Deliberate tag pin: rt repin <vX.Y.Z-rc.N>.
2b rt check-self-bootstrap --help The Long text says what a failure means under each posture.
3 docs/architecture/contracts/cli-surface.md, repin row Invoked by no workflow; run by hand, only for a deliberate tag pin; cannot restore @main. It rewrites the top-level .forgejo/workflows/ wrappers, not the examples/ ones. The matching comment in c5ExcludedVerbs drops "example" too.
4, 4a arc42 section 11.1 (Bootstrap-lag) and section 7.3 The lag is dormant under @main, because a toolkit-self cut runs the commit it cuts. It returns with a tag pin. Section 7.3's tag-pin text is kept, labelled as the dormant posture.
5 cmd/rt/repin.go A doc comment and a Long text with the #456 note: dormant for toolkit-self, for a deliberate tag pin only, and not a way back to @main.
6 docs/SECURITY.md:33 The gate guards release-toolkit's own pin, not the adopter's, and its behaviour is described for each posture.

Decision tree

What a red should tell the reader.

  • Name only rt repin if a tag pin is always deliberate. That was true before #456, and it is what the old text did.
  • Name only "restore @main" if every tag pin is a slip. That breaks the day toolkit-self is pinned to a tag on purpose, a path AGENTS.md section 2.2 keeps open.
  • Name both, labelled, when the check cannot tell which case it is in. It cannot: a wrapper file carries no record of intent. This option is chosen. Both reds share one helper, so they cannot drift apart.

Whether the alignment red gets the remedies too. Yes. It is the only red the check can raise under @main; AGENTS.md section 2.2 says "If one wrapper moved, it is alignment drift". So this is where the @main remedy matters most. It would get its own text only if alignment drift had a different fix, and it does not.

What to keep from the retired repin.sh header. It carried the #456 note, plus two remaining uses. One was toolkit-self recovery after an accidental tag pin. That use is not ported: repin.sh also refused any tag without -rc. (line 80 at 25c2fb3), so it never could restore @main. The other, an adopter's emergency re-pin, is not ported either. cli-surface.md classifies rt repin as not adopter-facing, and this PR did not measure whether it works in an adopter repo.

Commit types. chore: for the Go change. Under the consumer-facing-surface test in docs/conventions.md, no adopter observes it: both verbs are toolkit-self. docs: for the rest. A fix: subject would request a patch bump for a change no pinned consumer can see.

Scope. In scope are the four surfaces #1510 listed, plus four rows (2a, 2b, 4a, 6) found by a git grep for the same phrases. #1512 records three items as out of scope:

  • the arc42 "483d guard" framing across six files, which needs its own measurement of what guards the bake under @main;
  • the register-check misattribution in section 11.1;
  • the stale AGENTS.md:131 citation in 02-constraints.md.

Section 2 note

No re-pin is needed: toolkit-self floats @main (AGENTS.md section 2.1). check-self-bootstrap.yml is not in gates.DefaultComposeScripts. The two Go files change only log text, help text and comments. Adopters get the new rt help and log text from the next cut tag; nothing they invoke changes behaviour.

Verified at source

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

  • @main cannot go red for drift.
    • cmd/rt/check_self_bootstrap.go:177-183 returns before rev-parse --verify on the pinned ref.
    • On the forge, PR #1488 changed .forgejo/workflows/reusable-release.yml. In its check-self-bootstrap / check run (run 18568, job 0), the run check-self-bootstrap step logged floating-pin (release-toolkit#456): main matches main by construction and the job passed. That is the job log, not only the status row.
  • All 7 uses: frankenbit/release-toolkit/... lines under .forgejo/workflows/ pin @main.
  • No workflow invokes rt repin.
    • git grep repin -- .forgejo/workflows .gitea/workflows returns marker comments plus reusable-release.yml:192,263, all of them comments.
    • #1180 says the same.
  • rt repin cannot restore @main. rcTagShape (cmd/rt/repin.go:24) is ^v[0-9]+\.[0-9]+\.[0-9]+-rc\.[0-9]+$.
  • rt repin does not touch examples/. repinWrappers calls wrappers.Discover on <dir>/.forgejo/workflows, which runs os.ReadDir on that one directory with no recursion.
  • Commit and tag citations.
    • 9bca7d5 is "chore: re-pin self-bootstrap to v0.30.0-rc.2 (#172)", 2026-07-07.
    • e9eca94 is the #456 floating-pin commit, the same day.
    • git ls-remote --tags shows v0.30.0-rc.2 as the newest rc tag.
  • The quote in section 7.3 ("a red on a compose-script PR is correct, not a defect") matches AGENTS.md section 2.3 at aa9521b.

Tests

Run in golang:1.25 against an LF clone.

  • go test ./...: every package is ok. gofmt is clean.

  • New cmd/rt/check_self_bootstrap_test.go. This command's output had no test before. The new tests drive the CLI against a fixture repo whose default branch is trunk. No main ref exists there, so the floating-pin case passes only if the check returns before resolving any ref.

    Mutation-checked, each mutant in a fresh copy:

    Mutant Killed by
    M0: control, no mutation (passes)
    M1: drop the @main remedy from the helper pinDrift…, alignmentDrift…
    M2: the drift red prints no remedies pinDrift…
    M3: the alignment red prints no remedies alignmentDrift…
    M4: the floating-pin exit never fires floatingMain…
    M5: the drift red goes back to the old rc-only line pinDrift…
  • Lockstep gates: TestHelpSnapshot, TestSubcommandsMatchC5Contract and TestC5ExclusionsAreDocumented are green. help.txt is unchanged, because no Short text changed.

  • rt register-check on the four changed docs and the YAML: 0 hits.

  • bats: workflows: check-self-bootstrap skips release-prep rolling PRs (#304 regression guard) is ok, and the YAML loads with yaml.safe_load.

  • Not run locally:

    • scripts/workflow-parse-check.sh, because the local image has no forgejo-runner (rc=127). CI grades it.
    • The rest of the bats suite.

Review request

@alex, please do a verify-at-source pass (AGENTS.md section 6), not an FYI:

  1. Compare the two reds' remedy text (logPinRemedies, cmd/rt/check_self_bootstrap.go) with AGENTS.md section 2.2's two cases. Does the accidental arm say what 2.2 says, and no more?
  2. Check the repin row in cli-surface.md. git grep -n repin -- .forgejo/workflows should show comments only.
  3. In arc42 section 7.3 and the section 11.1 row, is "a toolkit-self cut runs the commit it cuts" stated no more strongly than AGENTS.md section 2.1 states it?
  4. Check that the YAML header is ASCII-only (AGENTS.md section 11).

Pin your submission with rt review-submit-check --owner frankenbit --repo release-toolkit --pr 1513 --reviewed-head 4ffde692129e10c252ec29dea53e910b268452f8 (AGENTS.md section 6.2).

🤖 Generated with Claude Code

Refs #1512 #1511 rewrote AGENTS.md section 2 for the #456 floating pin. This PR brings every other surface that still prescribed the rc re-pin into line with it: `check-self-bootstrap`'s workflow header, failure messages and help, `rt repin`'s doc and help, the C5 `repin` row, arc42 sections 7.3 and 11.1, and `docs/SECURITY.md`. no-changelog: toolkit-self only. `rt check-self-bootstrap` and `rt repin` are outside the C5 adopter contract, and the rest is documentation, so no adopter-visible behaviour changes. ## What changed Row numbers are from #1512's table. | Row | Surface | Now says | |---|---|---| | 1 | `.forgejo/workflows/check-self-bootstrap.yml` header | What a red means in each posture. Under `@main`, the check cannot go red for drift, so a red is alignment drift or a failed precondition, fixed by restoring `@main`. Under a tag pin, the red on a compose-script PR is expected, and the header names both remedies. The YAML change is comment-only and ASCII-only. | | 2, 2a | `rt check-self-bootstrap`'s drift and alignment reds | Both print the same two labelled remedies, from one helper (`logPinRemedies`). Accidental tag pin: put each wrapper back on `@main` in a reviewed PR, because `rt repin` cannot. Deliberate tag pin: `rt repin <vX.Y.Z-rc.N>`. | | 2b | `rt check-self-bootstrap --help` | The Long text says what a failure means under each posture. | | 3 | `docs/architecture/contracts/cli-surface.md`, `repin` row | Invoked by no workflow; run by hand, only for a deliberate tag pin; cannot restore `@main`. It rewrites the top-level `.forgejo/workflows/` wrappers, not the `examples/` ones. The matching comment in `c5ExcludedVerbs` drops "example" too. | | 4, 4a | arc42 section 11.1 (Bootstrap-lag) and section 7.3 | The lag is dormant under `@main`, because a toolkit-self cut runs the commit it cuts. It returns with a tag pin. Section 7.3's tag-pin text is kept, labelled as the dormant posture. | | 5 | `cmd/rt/repin.go` | A doc comment and a `Long` text with the #456 note: dormant for toolkit-self, for a deliberate tag pin only, and not a way back to `@main`. | | 6 | `docs/SECURITY.md:33` | The gate guards release-toolkit's own pin, not the adopter's, and its behaviour is described for each posture. | ## Decision tree **What a red should tell the reader.** - Name only `rt repin` if a tag pin is always deliberate. That was true before #456, and it is what the old text did. - Name only "restore `@main`" if every tag pin is a slip. That breaks the day toolkit-self is pinned to a tag on purpose, a path AGENTS.md section 2.2 keeps open. - Name both, labelled, when the check cannot tell which case it is in. **It cannot: a wrapper file carries no record of intent.** This option is chosen. Both reds share one helper, so they cannot drift apart. **Whether the alignment red gets the remedies too.** Yes. It is the only red the check can raise under `@main`; AGENTS.md section 2.2 says "If one wrapper moved, it is alignment drift". So this is where the `@main` remedy matters most. It would get its own text only if alignment drift had a different fix, and it does not. **What to keep from the retired `repin.sh` header.** It carried the #456 note, plus two remaining uses. One was toolkit-self recovery after an accidental tag pin. That use is not ported: `repin.sh` also refused any tag without `-rc.` (line 80 at `25c2fb3`), so it never could restore `@main`. The other, an adopter's emergency re-pin, is not ported either. `cli-surface.md` classifies `rt repin` as not adopter-facing, and this PR did not measure whether it works in an adopter repo. **Commit types.** `chore:` for the Go change. Under the consumer-facing-surface test in `docs/conventions.md`, no adopter observes it: both verbs are toolkit-self. `docs:` for the rest. A `fix:` subject would request a patch bump for a change no pinned consumer can see. **Scope.** In scope are the four surfaces #1510 listed, plus four rows (2a, 2b, 4a, 6) found by a `git grep` for the same phrases. #1512 records three items as out of scope: - the arc42 "483d guard" framing across six files, which needs its own measurement of what guards the bake under `@main`; - the `register-check` misattribution in section 11.1; - the stale `AGENTS.md:131` citation in `02-constraints.md`. ## Section 2 note No re-pin is needed: toolkit-self floats `@main` (AGENTS.md section 2.1). `check-self-bootstrap.yml` is not in `gates.DefaultComposeScripts`. The two Go files change only log text, help text and comments. Adopters get the new `rt` help and log text from the next cut tag; nothing they invoke changes behaviour. ## Verified at source All reads are on live `origin/main` `aa9521b`, 2026-10-02. - **`@main` cannot go red for drift.** - `cmd/rt/check_self_bootstrap.go:177-183` returns before `rev-parse --verify` on the pinned ref. - On the forge, PR #1488 changed `.forgejo/workflows/reusable-release.yml`. In its `check-self-bootstrap / check` run (run 18568, job 0), the `run check-self-bootstrap` step logged `floating-pin (release-toolkit#456): main matches main by construction` and the job passed. That is the job log, not only the status row. - **All 7 `uses: frankenbit/release-toolkit/...` lines under `.forgejo/workflows/` pin `@main`.** - **No workflow invokes `rt repin`.** - `git grep repin -- .forgejo/workflows .gitea/workflows` returns marker comments plus `reusable-release.yml:192,263`, all of them comments. - #1180 says the same. - **`rt repin` cannot restore `@main`.** `rcTagShape` (`cmd/rt/repin.go:24`) is `^v[0-9]+\.[0-9]+\.[0-9]+-rc\.[0-9]+$`. - **`rt repin` does not touch `examples/`.** `repinWrappers` calls `wrappers.Discover` on `<dir>/.forgejo/workflows`, which runs `os.ReadDir` on that one directory with no recursion. - **Commit and tag citations.** - `9bca7d5` is "chore: re-pin self-bootstrap to v0.30.0-rc.2 (#172)", 2026-07-07. - `e9eca94` is the #456 floating-pin commit, the same day. - `git ls-remote --tags` shows `v0.30.0-rc.2` as the newest rc tag. - **The quote in section 7.3** ("a red on a compose-script PR is correct, not a defect") matches AGENTS.md section 2.3 at `aa9521b`. ## Tests Run in `golang:1.25` against an LF clone. - **`go test ./...`:** every package is `ok`. gofmt is clean. - **New `cmd/rt/check_self_bootstrap_test.go`.** This command's output had no test before. The new tests drive the CLI against a fixture repo whose default branch is `trunk`. No `main` ref exists there, so the floating-pin case passes only if the check returns before resolving any ref. Mutation-checked, each mutant in a fresh copy: | Mutant | Killed by | |---|---| | M0: control, no mutation | (passes) | | M1: drop the `@main` remedy from the helper | `pinDrift…`, `alignmentDrift…` | | M2: the drift red prints no remedies | `pinDrift…` | | M3: the alignment red prints no remedies | `alignmentDrift…` | | M4: the floating-pin exit never fires | `floatingMain…` | | M5: the drift red goes back to the old rc-only line | `pinDrift…` | - **Lockstep gates:** `TestHelpSnapshot`, `TestSubcommandsMatchC5Contract` and `TestC5ExclusionsAreDocumented` are green. `help.txt` is unchanged, because no Short text changed. - **`rt register-check`** on the four changed docs and the YAML: 0 hits. - **bats:** `workflows: check-self-bootstrap skips release-prep rolling PRs (#304 regression guard)` is ok, and the YAML loads with `yaml.safe_load`. - **Not run locally:** - `scripts/workflow-parse-check.sh`, because the local image has no `forgejo-runner` (rc=127). CI grades it. - The rest of the bats suite. ## Review request @alex, please do a verify-at-source pass (AGENTS.md section 6), not an FYI: 1. Compare the two reds' remedy text (`logPinRemedies`, `cmd/rt/check_self_bootstrap.go`) with AGENTS.md section 2.2's two cases. Does the accidental arm say what 2.2 says, and no more? 2. Check the `repin` row in `cli-surface.md`. `git grep -n repin -- .forgejo/workflows` should show comments only. 3. In arc42 section 7.3 and the section 11.1 row, is "a toolkit-self cut runs the commit it cuts" stated no more strongly than AGENTS.md section 2.1 states it? 4. Check that the YAML header is ASCII-only (AGENTS.md section 11). Pin your submission with `rt review-submit-check --owner frankenbit --repo release-toolkit --pr 1513 --reviewed-head 4ffde692129e10c252ec29dea53e910b268452f8` (AGENTS.md section 6.2). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Both failure messages of rt check-self-bootstrap pointed only at an rc
re-pin: the drift red said "tag a new v<X.Y.Z>-rc.N at main's HEAD +
re-pin", and the alignment red said rt repin bumps every wrapper in
lockstep. Since #456 toolkit-self floats every wrapper at @main, so a
tag pin is either a deliberate posture change or a slip, and the check
cannot tell which. rt repin cannot repair a slip: rcTagShape accepts
only vX.Y.Z-rc.N.

Both reds now print the same two remedies (AGENTS.md section 2.2):
restore @main in a reviewed PR when the tag pin is accidental, rt repin
when it is deliberate. The --help Long text says what a failure means
under each posture.

rt repin gains the #456 note the retired repin.sh header carried, minus
its claim that the script repaired an accidental tag pin: repin.sh also
refused any tag without -rc., so it never could.

The command's output had no test at all. The new tests drive the CLI
on a fixture repo whose default branch is not main, so the floating-pin
case passes only if the check returns before resolving any ref.

Refs #1512

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs(self-bootstrap): describe the check and the bootstrap lag under both pin postures (#1512)
All checks were successful
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
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
ac-closure-check / ac-closure check (pull_request) Successful in 7s
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 5s
go-ci / lint + build + test (push) Successful in 30s
go-ci / record reviewed vs landed commit (push) Successful in 3s
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 10s
release / release (push) Successful in 0s
tests / workflow-schema (push) Successful in 3s
tests / bats (push) Successful in 31s
tests / dated-examples (push) Successful in 5s
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
4ffde69212
The check-self-bootstrap.yml header, arc42 section 7.3 and the
Bootstrap-lag row in section 11.1, and docs/SECURITY.md all said a
compose-script PR turns the check red until the toolkit re-pins. Under
the #456 @main pin the check passes before comparing any file (PR
#1488's run 18568 logged the floating-pin line on a reusable-release.yml
change), and a toolkit-self cut runs the commit it cuts, so there is no
lag. Each surface now separates the @main posture from the dormant tag
pin posture, matching AGENTS.md sections 2.1-2.3.

cli-surface.md's repin row named check-self-bootstrap.yml as its caller.
No workflow invokes rt repin (#1180); only marker comments mention it.
The row also claimed it re-pins the example wrappers, but
wrappers.Discover reads only the top-level .forgejo/workflows directory.

Refs #1512

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude requested review from alex 2026-10-02 15:57:03 +02:00
alex approved these changes 2026-10-02 16:05:56 +02:00
alex merged commit 4ffde69212 into main 2026-10-02 16:05:59 +02:00
alex deleted branch claude/1512-self-bootstrap-456-framing 2026-10-02 16:05:59 +02:00

Landing identity record

  • PR: #1513
  • landed commit (server merge_commit_sha): 4ffde692129e10c252ec29dea53e910b268452f8
  • effective official approval(s):
    • @alex, review #7187, stamped commit: 4ffde692129e10c252ec29dea53e910b268452f8
  • 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=4ffde692129e10c252ec29dea53e910b268452f8 --> ## Landing identity record - PR: #1513 - landed commit (server merge_commit_sha): `4ffde692129e10c252ec29dea53e910b268452f8` - effective official approval(s): - @alex, review #7187, stamped commit: `4ffde692129e10c252ec29dea53e910b268452f8` - 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!1513
No description provided.