fix(release-decide): Layer 2 cut-safeguard uses list-and-filter with narrow window — switch to explicit PR lookup #240
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
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit#240
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
What happened (empirical anchor)
The v0.17.0 cut on 2026-06-28 was supposed to fire on the merge of rolling PR #227. Instead,
decide+actfell through tomode=updateand re-prepped v0.17.0 as a new rolling PR (#239). Recovered by merging #239 (which had a newer issue_id so it landed within Layer 2's lookup window).Root cause:
forgejo_find_pr_by_merge_shainscripts/lib/forgejo-api.shqueriesGET /pulls?state=closed&sort=updated&limit=5and filters client-side bymerge_commit_sha. Two problems compound:Forgejo's
sort=updatedempirically sorts by issue_id descending, not byupdated_at. So a PR that was created earlier but merged most-recently is positioned lower than throwaway/probe PRs with newer issue_ids.limit=5was an unsafe optimization. Today's v0.16.0 → v0.17.0 cycle had 10+ PRs close between cuts (audit PRs + Engineer's batch + Pilot's fix + re-pin + throwaway probes). PR #227 fell to position 11 in the list — completely outside the lookup window. Layer 2 returned empty even after retries (the retry window assumes API indexing lag; here the data is simply not in the limit=5 result).Source comment is honest about the typical-case optimization: "Queries the 5 most-recently-closed PRs (sufficient for typical merge cadence + bounded query cost)." Typical merge cadence has grown past 5.
Why this needs the substrate fix
Every future cycle with >4 closed PRs between cuts will hit this. The release-toolkit substrate's release-cadence has been climbing (sprints with 5-15 PRs between cuts are now typical). The current shape relies on an arbitrary window value — an "off-by-typical-cadence" footgun.
Three options
(3) Explicit PR lookup by commit SHA — PREFERRED
Forgejo may have a direct endpoint like
GET /repos/{owner}/{repo}/commits/{sha}/pulls(GitHub has it). If available, this bypasses the list-and-filter entirely + is the substrate-honest answer (explicit query for what we want, no arbitrary window).Recon needed: verify Forgejo 15.0.2 exposes such an endpoint OR equivalent. Check:
/repos/{owner}/{repo}/commits/{sha}/pulls(GitHub-parity)/repos/{owner}/{repo}/git/commits/{sha}/pull(alternate path)commitsAPI includes associated PR info in the response(1) Increase limit — FALLBACK
If no better endpoint exists in Forgejo 15.0.2: change
limit=5tolimit=50(Forgejo's typical max per page). Still has a ceiling but covers all reasonable cycles.(2) Paginate until found — REJECTED
More complex + unbounded cost; not preferred unless (3) is unavailable AND a single limit=50 page is also insufficient.
Implementation surface
scripts/lib/forgejo-api.sh: replaceforgejo_find_pr_by_merge_shabody with direct lookup (option 3) or wider list (option 1)tests/forgejo-api.bats: add a regression test that mocks the failure mode (the list-window misses the cut PR)scripts/release-decide.shdocs/integration.mdorAGENTS.mdif any docs reference the cut-safeguard layersEstimated scope: ~30 lines + bats coverage. Small Engineer-shape recon-before-build.
What this PR will NOT do
Refs
scripts/release-decide.shLayer 2 logic (caller of the to-be-fixed function)priority/high · size/S