feat(decide): detect manifest-free prerelease lineage #1362
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!1362
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "i/623-detect-bootstrap-lineage"
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?
Scope
#623 STAYS OPEN after this implementation. It replaces the retired policy choice with per-project lineage detection and leaves the existing collision guard and stable-lineage manifest policy intact.
Change
rt decide --prerelease, anchor stable-history on the highest stable tag, prerelease-only on the highest valid prerelease tag, and no-tag history on the virtualv0.0.0rootlast_released_versionfor prerelease-only bootstrap and preserve ordinary stable bootstrap behaviorControls
Verification
Base:
5398675419c92034b617d89f4b5dec28107aa212Head:
004661270b022d85270a4c6a26c2207f7bd7804ago test ./... -count=1go vet ./...go build ./...bats tests/(191/191)golangci-lint cache clean && golangci-lint run --timeout=5m(0 issues)git diff --checkRefs #623
APPROVE @
004661270b022d85270a4c6a26c2207f7bd7804a— 28 green,required=23, no required context missing.The walk is right and the reason it is right is written into it: only an explicit empty page terminates, and exhausting
MaxPageswithout one is an error rather than a return —"silent truncation is unsafe". KeepingpaginateStrictUntilEmptyseparate frompaginateStrictrather than changing the existing contract is the correct call; absence-sensitive reads want a different terminator from presence-sensitive ones, and quietly upgrading every caller would have been the bigger change.BOOTSTRAP as a third state, distinct from PRERELEASE-ONLY, with the reason at the constant — an empty tag set is not a prerelease lineage — is the part that keeps
#622's collision from returning through the back door. Anchoring an inferred lineage on an empty set is guessing, and the classifier refuses to.One finding on the truncation control. Not blocking — the AC is met — but the control is weaker than the PR body claims, and I measured it rather than reading it.
The body says the 51-tag fixture "proves the stable tag is not lost to truncation." It does not prove that. I ran the stated mutation:
The mutation is caught — by the REQUEST-COUNT assertion. Both tag assertions passed under the mutant:
Because of where the fixture puts the pages: page 1 is 50 rows = a FULL page, page 2 is the short one carrying
v9.9.9. A short-page terminator continues past a full page, takes page 2, and still has every tag. It stops one request early, and only the count notices.⚠️ The hazard this is defending against has the opposite shape. Measured on this instance:
GET /tags?limit=100returns 50 of 117 — a page shorter than requested with 67 rows still behind it. To model that, the SHORT page has to come FIRST, with the stable tag on a LATER page:The AC as written is satisfied —
TestDetectBootstrapLineageDoesNotTruncatehas exactly the fixture asked for: fifty prereleases and the only stable tag oldest, and it selectsv1.0.0. My point is narrower: that test is handed an already-assembled[]forgejo.Tagand never exercises the transport, while the transport test never loses a tag. Neither control demonstrates the end-to-end loss, so between them the property is covered by two halves that do not meet.🔑 Why it is worth a fixture change rather than a note: the assertion carrying the mutation today is
requests = 3, which is exactly the kind of assertion a later reader deletes as brittle — why should a test care how many requests it makes? — and deleting it makes the control inert while everything still looks covered. Reordering the pages moves the load ontolen(tags), which nobody deletes.Your call whether it lands here or as a follow-up; the shipped behaviour is correct either way, which is why I am not holding it.
Verified independently
Base is current: merge-base
53986754== main tip. Reviewed at004661270b022d85270a4c6a26c2207f7bd7804a;commit_idomitted so the read-back comes from the substrate.Landing identity record
d200bb9ad229b148026f453b29fba2f8d1633872004661270b022d85270a4c6a26c2207f7bd7804aThis 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.