Repository navigation
Release timeout falsely reports workflow approval after CI has already started #145
Description
Observed failure and immutable source
At main 247b95e6214f687d0d838d1685cc0e99db664cd6, release.yml initializes awaiting_approval=0 once before the merge loop, sets it to 1 when a run is action_required/waiting, and never resets it when a later poll reports no approval-pending runs.
Daily Release 39015290805 timed out at 08:37:04 UTC on October 17 and told the maintainer to approve the CI run. But the same log repeatedly reports both required tests in progress, including at 08:37:03. Node 22 started at 08:13:14 and passed at 08:38:02; Node 26 started at 08:12:55 and passed at 08:39:04. This was a slow-check timeout, not an approval still required at timeout.
At the 09:15 UTC read, release PR #144 remains open at 328e284cd30afb2811998fc6d0f02e78994d537c, its checks are green, and the latest GitHub release is still v2026.10.16. Publication/tagging steps were skipped. This report does not authorize a merge, retry, or release.
Bounded reproduction
Run the workflow's approval-state assignments in isolation, without any gh/git/network calls:
- Initialize awaiting_approval=0
- First poll: pending_runs is nonempty, so the existing conditional sets awaiting_approval=1
- Later poll: pending_runs is empty because CI is now in_progress; the same conditional leaves awaiting_approval at 1
- Execute the deadline diagnostic conditional: it selects 'awaiting workflow approval'
Observed exit 0 and approval-required diagnostic despite current approval-required=false. Source inspection finds only three uses: initialization line 354, setting line 479, deadline branch line 484.
Expected: terminal diagnostics reflect the latest successfully observed approval/check state and distinguish slow-running checks from a genuinely approval-blocked workflow. Actual: a historical approval observation permanently selects the approval message, directing the maintainer to an action that is no longer applicable.
Goal and impact
The protected-release merge loop introduced in PR #33 deliberately keeps publication behind verified merge and diagnoses a bounded wait. Preserve that safety behavior. The defect is stale state in the recovery guidance; increasing timeouts or bypassing checks is not required to correct it. Today it obscures why a fully green release PR is still unpublished.
Regression acceptance
- action_required -> in_progress -> deadline reports checks still settling, without claiming approval is currently required
- action_required -> action_required -> deadline still reports the actual pending run
- action_required -> successful checks/merge does not emit a stale approval blocker
- An unavailable run-state read is distinguished from a verified empty result
- No reduction to required checks, review gates, permissions or publication protections
Scope: hosted log/check evidence and a minimal isolated state-transition reproduction, not a full release replay or newly run package suite. All-status repository issues/PRs and all 131 canonical PM records were checked for an existing owner before filing.
Activity
unbraind commentedon Oct 18, 2026
Fixed in PR #148 at
f94e4e5e7f06b5a3d443f082a1b4f4215c967534(pushed). The actual release merge-wait shell now clears historical approval after a successful empty run-state read and reports unavailable reads separately.node --test test/release-approval.test.tspasses 4/4: pending-to-running timeout, still-pending timeout with run URL, unavailable read, and later verified merge. Reverting only release.yml fails 2/4; restoring it passes. Full isolated npm/Bun gates and CI are in progress; no live merge or publication was performed.unbraind commentedon Oct 18, 2026
Final delivery for PR #148 is pushed at
96a4b4bedea2943797a02510e7f4e7aad395b8f6. Actual release-loop regression: 4/4 pass; reverting only the fix fails 2/4. Both isolated CI release commands pass 824/824 with zero failures/skips and exact 100% in all four coverage dimensions across 14 modules. Final-head Node 22/26, native Bun acceptance, CodeQL and Semgrep pass: https://github.com/unbraind/pm-github/actions/runs/39098874412 . Implementation and tests match the release-gated source; the temporary validation workflow was removed. No PR was merged.unbraind commentedon Oct 18, 2026
Revalidated after integrating current main in pushed head
04bbf3603c30e6dd81efa2622e3aa0d086f845eb.node --test test/release-approval.test.tspasses 4/4. Both exact isolated-identitynpm run release:checkandbun run release:checkpass 836/836 with exact 100/100/100/100 coverage across all 14 authored modules: https://github.com/unbraind/pm-github/actions/runs/39105101037. The validated head was762285d94e90e645927b90e8032292c191772b49; final production code, tests, scripts, docs and dependency pins are byte-identical. Existing behavioral revert proof is preserved, and PR #148 retains its closing link. Final-head CI is tracked in the PR body; this comment does not close the issue.unbraind commentedon Oct 18, 2026
PR #148 is pushed at
7d4306774005b5542ab617926593252c6b319f80.node --test test/release-approval.test.tspasses 4/4. Original approval-state transition fix and recorded production-only revert proof are retained after merging current main.Both exact isolated
npm run release:checkandbun run release:checkpass 893/893 with zero failures/skips/cancellations/todos and exact 100/100/100/100 source coverage: https://github.com/unbraind/pm-github/actions/runs/39119457879 . Fresh-clone strict health passes. Final-head Node 22/26 CI, including native Bun acceptance, passes (https://github.com/unbraind/pm-github/actions/runs/39120403305); CodeQL and Semgrep pass; no merge or release was performed.