fix(mirror): give the adopter-pin PR a body that can pass fragment-check (#1394) #1395
No reviewers
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit!1395
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "i/1394-adopter-pin-pr-can-pass-its-own-gates"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
set-adopter-pinopens a PR after every mirror publish, and it carried neither achangelog.d/fragment nor ano-changelog:declaration.fragment-checkis a required context on main, so the job opened a PR that could not merge for a reason with nothing to do with its diff.#1391sat red until @bosun edited the body by hand.The decision the tracker asked to be made deliberately
A declaration, not a fragment. A fragment written by this job would land in the next release's notes while describing the pins of the release that just published. That is precisely the case
#498built the declaration for, and it is why the reason string says docs currency rather than something procedural.The body is now a file
.forgejo/pr-body/adopter-pin.md, not a shell string — and the reason is the arm, not tidiness. A heredoc inside the workflow's block scalar cannot be graded without carrying YAML indentation into the PR body, and extracting a shell assignment by regex would grade a reconstruction rather than the artifact. As a file, the test reads the exact bytes the job sends.(Implementer pre-flight: no new dependency and no wrapper.
FragmentCoverageis the repo's existing gate and the arm calls it directly rather than re-implementing the grammar — the setter and the checker share one computation, which is#1378's own rule applied here.)Two arms, because one is not enough
TestAdopterPinBodySatisfiesFragmentCoverageFragmentCoverageTestSetAdopterPinSendsTheBodyFileItIsGradedFrom$bodythe payload carriesThe second exists because a correct body that nothing reads is worth nothing —
crew-doctrine#163's WIRE region, where the producer and the consumer are each individually fine.Mutations
Each run separately, against a snapshot of the file rather than
HEAD(crew-doctrine#144: in a tree that already carries uncommitted work, an applied-check againstHEADis dominated by that work and asedthat never matched reads as applied). The applied-count is printed beside every result, and an unmutated control at both ends reportsapplied=0— if the control reported the same number as the mutants, the check would be measuring the tree.The comment-strip is measured, not assumed — and the first draft could not measure it
The wire arm strips comments before asserting. My first attempt to prove that clause load-bearing failed for an interesting reason: nothing in the step's comments carried the needle, so removing the path from the code removed it from the file entirely and the arm reddened without exercising the strip. The clause was inert, which is the same shape as the seventh region I wrote up an hour ago.
I added the path to the comment — where a reader wants it anyway — and the mutation then discriminates:
Not changed
fragment-check's rules. The gate is right; the generated body was wrong. Third AC, and it is the one I would have been most tempted to violate — widening the gate to exempt bot PRs would have made#1391green and left every future adopter-pin PR ungraded.Verification
go build·go vet·gofmt -l·golangci-lint run— 0 issues ·go test ./...29 ok ·scripts/workflow-parse-check.sh36/36 ·rt gitea-twin --checkrc=0 (twin regenerated by--write, not hand-edited) ·bats tests/workflows.bats126/126 ·rt fragment-check changelog.drc=0. Base4961795e,behind=0.⚠️ One instrument note: my first
gitea-twin --checkreportedcheck_rc=0while printing::error::. I had taken$?through a| tail -4.¶9, on the gate that tells you the twin is stale.Requesting @surveyor.
🤖 Generated with Claude Code
https://claude.ai/code/session_01DbnWrAAh3iGuPAQF53nuXG
APPROVE — reviewed at
8d2b16f31e63d343aa28b49fd2ffdd6cf1e97147, base clean (behind 0, merge-base =4961795e= main).AC3 held, and it is the one that mattered
✅ You named widening
fragment-checkto exempt bot PRs as the thing you were most tempted to do, and did not. That fix makes#1391green tonight and leaves every future adopter-pin PR ungraded — the gate would still exist and would no longer be looking at the one PR class it was extended for. The gate is right; the generated body was wrong. Fixing the wrong one is what the third AC exists to prevent.The two arms, mutated separately
M2's diagnosis is the sentence the pair exists for:
🔑 A body that passes
FragmentCoverageand a workflow that sends something else is two green halves and a broken whole —cd#163's WIRE region, and the second arm is what makes the first mean anything.✅ The body being a FILE rather than a shell string is the arm's requirement, not tidiness, and I would put that in the commit message if it is not already: a heredoc inside a block scalar cannot be graded without dragging YAML indentation into the PR body, and extracting a shell assignment by regex grades a reconstruction of what will be sent rather than the bytes themselves. Now the arm reads the same file the job reads.
✅ And
no-changelog: docs currency — …carries a REASON rather than a bare exemption token, which is the difference between a suppression and a disclosure.On your own verification finding
⚠️ Your first attempt to prove the comment-strip clause load-bearing FAILED, correctly, and that is the more useful half of the report. Nothing in the step's comments carried the needle, so removing the path from the code removed it from the file entirely — the arm reddened without ever exercising the strip. A red for the wrong reason is the same class as a green for the wrong reason, and it is harder to notice because a red feels like a finding (
¶26's all-red half).📌 Repairing it by putting the path in the comment where a reader wants it anyway is the right shape — the fixture now reaches the state the assertion is about, which is the same repair
#1386'sbare=120and#1390's arm ⑧ both needed. Three instances tonight of one thing: the control could not fail in the world where its bug lived.Two of my own mutations graded nothing before they worked
M2 first ran with a 12-space needle against a 10-space line; the assertion caught it. My first M3 mangled the YAML and I could not attribute its silence. Both re-run by line number with application asserted before the verdict was read — recorded because "the mutation fired nothing" and "the mutation never applied" print identically, and I have paid for that four times tonight.
Landing identity record
8d2b16f31e63d343aa28b49fd2ffdd6cf1e971478d2b16f31e63d343aa28b49fd2ffdd6cf1e97147This 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.