chore(readme-pin-check): the gate grades only README.md, so integration.md and examples/ are set by one rule and checked by none #1382

Closed
opened 2026-09-06 20:38:09 +02:00 by bosun · 2 comments
Owner

readme-pin-check grades only README.md, so the @vX.Y.Z pins that rt prep still advances in docs/integration.md and examples/** are set by one rule and checked by none.

Why it matters

#1378 stopped prep advancing README's prescriptive pins to a version the mirror cannot serve, and made the mirror set them through the gate's own computation. UpdateDocVersionRefs still rewrites @vX.Y.Z in docs/integration.md and examples/** at prepare time — a stranger copying an example hits the identical failure the README fix removed: the tag resolves, the checkout succeeds, and the fetch fails one line later with a green reference behind it.

Order matters, and it is the same principle #1378 settled

Widen the GATE first, then point the setter at what it covers. Doing it the other way leaves the new files set-but-unchecked, which is the defect #1378 existed to remove, reintroduced somewhere new. The setter and the checker must share one computation or they drift by construction.

AC

  • readme-pin-check grades docs/integration.md and examples/** as well as README.mdthe verb via #1384, the CI INVOCATION via #1389 at deda8728. On main: --doc README.md --doc docs/integration.md --doc examples. ⚠️ The first landed without the second, and the gap was found by running the widened verb with the workflow's own arguments and then reading the workflow — checked-by-no-verb had become checked-by-no-invocation.
  • Its output names WHICH file each finding is in, since a stranger's failure now has three possible sources — and the rc=0 line gained a graded: line naming the surfaces. "11 document(s)" says nothing about whether the set was the intended one.
  • The descriptive/prescriptive discriminator holds in the new files — an @ prefix, not any version mention — readmepin.pinRE is the single definition and Retarget reuses it. @surveyor verified it is strictly WIDER than the deleted atTagRE (prereleases included) and read ParsePins for a context filter that would have made the wider regex irrelevant; there is none.
  • --fix and prep are then repointed so the same files are set and checked by the same rule — prep advances none of the three surfaces; the mirror sets them all through the gate's own computation. Settling read on the regenerated rolling branch, which is the artefact rather than the arms: README 2 · docs/integration.md 12 · examples/ 5 — 19 pins, all @v0.61.1, zero @v0.62.0, and readme-pin-check with the full --doc set returns rc=0 across 11 documents.
  • An arm per newly-graded file, each reddening on its own mutation, plus a control that a correct pin in a new file still passes — seven mutations, each run separately. Two are worth the record: a step stops invoking the verb mutation PASSED the first draft because every rc branch echoes readme-pin-check:the needle matched the step's own diagnostic vocabulary — and the strip-control reddened for the WRONG occurrence because workflows.bats now holds two def code(step) helpers.

#1378 (the README half, closed), #1068 (the policy), #1379 (the implementation whose scope this widens).

Anchor

Requested by @shipwright while building #1379; he declined to widen past the gate for exactly the reason above and asked for this to be filed rather than folded in.

`readme-pin-check` grades only `README.md`, so the `@vX.Y.Z` pins that `rt prep` still advances in `docs/integration.md` and `examples/**` are set by one rule and checked by none. ## Why it matters `#1378` stopped `prep` advancing README's prescriptive pins to a version the mirror cannot serve, and made the mirror set them through the gate's own computation. `UpdateDocVersionRefs` still rewrites `@vX.Y.Z` in `docs/integration.md` and `examples/**` at prepare time — **a stranger copying an example hits the identical failure the README fix removed: the tag resolves, the checkout succeeds, and the fetch fails one line later with a green reference behind it.** ## Order matters, and it is the same principle #1378 settled **Widen the GATE first, then point the setter at what it covers.** Doing it the other way leaves the new files set-but-unchecked, which is the defect `#1378` existed to remove, reintroduced somewhere new. The setter and the checker must share one computation or they drift by construction. ## AC - [x] `readme-pin-check` grades `docs/integration.md` and `examples/**` as well as `README.md` — **the verb via `#1384`, the CI INVOCATION via `#1389` at `deda8728`.** On `main`: `--doc README.md --doc docs/integration.md --doc examples`. ⚠️ **The first landed without the second, and the gap was found by running the widened verb with the workflow's own arguments and then reading the workflow** — checked-by-no-verb had become checked-by-no-invocation. - [x] Its output names WHICH file each finding is in, since a stranger's failure now has three possible sources — and the `rc=0` line gained a `graded:` line naming the surfaces. *"11 document(s)" says nothing about whether the set was the intended one.* - [x] The descriptive/prescriptive discriminator holds in the new files — an `@` prefix, not any version mention — **`readmepin.pinRE` is the single definition and `Retarget` reuses it.** @surveyor verified it is strictly WIDER than the deleted `atTagRE` (prereleases included) and read `ParsePins` for a context filter that would have made the wider regex irrelevant; there is none. - [x] `--fix` and `prep` are then repointed so the same files are set and checked by the same rule — **`prep` advances none of the three surfaces; the mirror sets them all through the gate's own computation.** ✅ **Settling read on the regenerated rolling branch, which is the artefact rather than the arms:** README 2 · `docs/integration.md` 12 · `examples/` 5 — **19 pins, all `@v0.61.1`, zero `@v0.62.0`**, and `readme-pin-check` with the full `--doc` set returns `rc=0` across 11 documents. - [x] An arm per newly-graded file, each reddening on its own mutation, plus a control that a correct pin in a new file still passes — **seven mutations, each run separately.** Two are worth the record: a *step stops invoking the verb* mutation PASSED the first draft because every `rc` branch echoes `readme-pin-check:` — **the needle matched the step's own diagnostic vocabulary** — and the strip-control reddened for the WRONG occurrence because `workflows.bats` now holds two `def code(step)` helpers. ## Related `#1378` (the README half, closed), `#1068` (the policy), `#1379` (the implementation whose scope this widens). ## Anchor Requested by @shipwright while building `#1379`; he declined to widen past the gate for exactly the reason above and asked for this to be filed rather than folded in.
Author
Owner

🔴 AC1 is satisfied by the VERB and not by the GATE. #1384 widened what readme-pin-check can grade and did not widen what CI asks it to grade.

the verb, run with the wider set on the recomposed rolling branch
  rt readme-pin-check --doc README.md --doc docs/integration.md --doc examples …
  rc=0  PASS: all 19 prescriptive pin(s) across 11 document(s) name v0.61.1

the gate, .forgejo/workflows/readme-pin-check.yml on main, line 110
  "$RUNNER_TEMP/rt" readme-pin-check \
    --doc            README.md \        <- ONE document
    --target-owner   FrankenBit \
    ...

And #1384 did not touch that workflow — its file list is mirror-release.yml ×2, the fragment, readme_pin_check.go + test, cli-surface.md, doc_version_refs.go + test.

⚠️ So today's state is: prep no longer advances the pins in docs/integration.md and examples/**, --fix can set them, the verb can grade them — and nothing in CI does. 🔑 That is the set-by-one-rule-checked-by-none shape this tracker exists to remove, moved one layer out: from checked by no verb to checked by no invocation.

📌 The success path is also worth reading, because it will mislead the next person: the workflow's rc=0 message says "every prescriptive @vX.Y.Z in README.md names a version the mirror can serve." It is accurate and it is scoped to README.md, so a reader who sees green learns nothing about the other two surfaces — which is §Mechanism design's own rule, stated correctly at the point of use, and it now understates what the verb could have told them.

Settling read, which IS good news

The rolling branch regenerated at 4aeb4f29 after #1384 landed, and every pin moved the right way:

README.md            2 × @v0.61.1     (0 × @v0.62.0)
docs/integration.md 12 × @v0.61.1     (0 × @v0.62.0)
examples/            5 × @v0.61.1     (0 × @v0.62.0)

19 pins across three surfaces, none naming the uncut version. prep's half is done and measured on the artefact rather than on the arms.

Remaining

  • readme-pin-check.yml passes --doc docs/integration.md --doc examples alongside README.md
  • The rc=0 message names the surfaces it graded rather than only README.md
  • An arm pinning the workflow's --doc set, so a future edit cannot silently narrow it back to one document

⚠️ The third is the one that matters: without it, this exact regression is a one-line edit away and nothing would notice.

Found by running the widened verb with the workflow's own arguments and then reading the workflow.

🔴 **AC1 is satisfied by the VERB and not by the GATE. `#1384` widened what `readme-pin-check` can grade and did not widen what CI asks it to grade.** ``` the verb, run with the wider set on the recomposed rolling branch rt readme-pin-check --doc README.md --doc docs/integration.md --doc examples … rc=0 PASS: all 19 prescriptive pin(s) across 11 document(s) name v0.61.1 the gate, .forgejo/workflows/readme-pin-check.yml on main, line 110 "$RUNNER_TEMP/rt" readme-pin-check \ --doc README.md \ <- ONE document --target-owner FrankenBit \ ... ``` **And `#1384` did not touch that workflow** — its file list is `mirror-release.yml` ×2, the fragment, `readme_pin_check.go` + test, `cli-surface.md`, `doc_version_refs.go` + test. ⚠️ **So today's state is: `prep` no longer advances the pins in `docs/integration.md` and `examples/**`, `--fix` can set them, the verb can grade them — and nothing in CI does.** 🔑 **That is the set-by-one-rule-checked-by-none shape this tracker exists to remove, moved one layer out: from *checked by no verb* to *checked by no invocation*.** 📌 **The success path is also worth reading, because it will mislead the next person:** the workflow's `rc=0` message says *"every prescriptive `@vX.Y.Z` in README.md names a version the mirror can serve."* **It is accurate and it is scoped to README.md, so a reader who sees green learns nothing about the other two surfaces** — which is §Mechanism design's own rule, stated correctly at the point of use, and it now understates what the verb could have told them. ## Settling read, which IS good news The rolling branch regenerated at `4aeb4f29` after `#1384` landed, and every pin moved the right way: ``` README.md 2 × @v0.61.1 (0 × @v0.62.0) docs/integration.md 12 × @v0.61.1 (0 × @v0.62.0) examples/ 5 × @v0.61.1 (0 × @v0.62.0) ``` **19 pins across three surfaces, none naming the uncut version.** `prep`'s half is done and measured on the artefact rather than on the arms. ## Remaining - [ ] `readme-pin-check.yml` passes `--doc docs/integration.md --doc examples` alongside `README.md` - [ ] The rc=0 message names the surfaces it graded rather than only `README.md` - [ ] An arm pinning the workflow's `--doc` set, so a future edit cannot silently narrow it back to one document ⚠️ **The third is the one that matters: without it, this exact regression is a one-line edit away and nothing would notice.** Found by running the widened verb with the workflow's own arguments and then reading the workflow.
Author
Owner

All five ACs ticked. #1384 and #1389 merged; main at deda8728 is build/test rc=0, bats 196/0. Closing.

🔑 The finding this tracker produced that was not in its own body: widening the VERB is not widening the GATE. #1384 taught readme-pin-check to grade eleven documents and left CI asking it for one. Caught by running the widened verb with the workflow's own arguments and then reading the workflow — the arms were green, the settling read was green, and the invocation was still --doc README.md.

📌 #1389's third item is the one that keeps it fixed: an arm pinning the workflow's --doc set, so narrowing it back to one document reddens instead of passing quietly. Without it the regression is a one-line edit away and nothing notices.

Verified on main rather than on the PRs

.forgejo/workflows/readme-pin-check.yml
  --doc README.md · --doc docs/integration.md · --doc examples
tests/workflows.bats
  "no step invokes readme-pin-check with --doc -- this gate grades nothing"
rolling branch, regenerated: 19 pins across three surfaces, all @v0.61.1

@shipwright implemented both halves; @surveyor reviewed both and asked the question that made the first safe — a deletion that removes a setter is only safe if the checker is at least as wide; the verb-versus-gate gap and the merges are mine.

✅ **All five ACs ticked. `#1384` and `#1389` merged; `main` at `deda8728` is build/test rc=0, bats 196/0. Closing.** 🔑 **The finding this tracker produced that was not in its own body: widening the VERB is not widening the GATE.** `#1384` taught `readme-pin-check` to grade eleven documents and left CI asking it for one. **Caught by running the widened verb with the workflow's own arguments and then reading the workflow** — the arms were green, the settling read was green, and the invocation was still `--doc README.md`. 📌 **`#1389`'s third item is the one that keeps it fixed:** an arm pinning the workflow's `--doc` set, so narrowing it back to one document reddens instead of passing quietly. *Without it the regression is a one-line edit away and nothing notices.* ## Verified on main rather than on the PRs ``` .forgejo/workflows/readme-pin-check.yml --doc README.md · --doc docs/integration.md · --doc examples tests/workflows.bats "no step invokes readme-pin-check with --doc -- this gate grades nothing" rolling branch, regenerated: 19 pins across three surfaces, all @v0.61.1 ``` @shipwright implemented both halves; @surveyor reviewed both and asked the question that made the first safe — *a deletion that removes a setter is only safe if the checker is at least as wide*; the verb-versus-gate gap and the merges are mine.
bosun closed this issue 2026-09-06 21:35:14 +02:00
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#1382
No description provided.