Repository navigation
fix(opencode): self-retire superseded verdict polls #1649
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 9 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
ebc9f46
test(opencode): require stale poll self-retirement
seonghobae 13aa1b4
fix(opencode): self-retire stale verdict polls
seonghobae f4ac727
docs(opencode): record stale-poll capacity repair
seonghobae f140a71
test(opencode): execute stale poll retirement branches
seonghobae aeaa570
test(opencode): reproduce transient live-state poll failure
seonghobae 61ee229
docs(opencode): disambiguate incident observation date
seonghobae b4482ac
test(opencode): bound live-state transport retries
seonghobae d75f79a
test(opencode): bound review transport retries
seonghobae 9ca4dce
fix(opencode): bound verdict poll transport retries
seonghobae 41a0bff
test(opencode): bound verdict poll REST request pressure
seonghobae 9406d83
merge(main): reconcile OpenCode poll self-retirement
seonghobae b1378cc
fix(opencode): bound verdict poll REST pressure
seonghobae 8683f6e
test(opencode): pin OIDC audience variable
seonghobae 3455a30
fix(opencode): restore OIDC audience binding
seonghobae 1354a1e
docs(opencode): record poll rate-budget repair
seonghobae 0d9a016
test(opencode): align executable poll harness with rate budget
seonghobae File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| # OpenCode stale-poll self-retirement | ||
|
|
||
| ## Incident boundary | ||
|
|
||
| On 2026-09-01 UTC (2026-09-02 Asia/Seoul), `ContextualWisdomLab/fast-mlsirm` retained an in-progress `Required OpenCode Review` run for PR #1519 on predecessor head `5453d0df84e4e...` while the live PR head had already advanced to `3a3865f40da12211898c97cbd47e7460381736ae`. The predecessor run had entered the required workflow's Reviews API wait and continued occupying a runner. At the same observation, the repository had a fresh current-head OpenCode run queued and the organization-wide Actions fleet was heavily queued. | ||
|
|
||
| The protected central workflow intentionally keys concurrency by repository, PR number, and exact head SHA. That protects a newer authoritative run from a delayed old-head event, but it also means a new commit cannot cancel the previous head through the concurrency group. A separate `cancel-superseded-opencode-review-runs` job exists for that cleanup, yet it needs its own runner. Under saturation, the cleanup job can therefore wait behind the stale poll it is meant to retire. | ||
|
|
||
| ## Root cause | ||
|
|
||
| `opencode-review-target` validated the live PR head/state/draft once before entering an unbounded `while` loop. The loop then queried only the Reviews API every 30 seconds. A head movement after the first validation was invisible to the occupied run, so an obsolete head could remain in progress until GitHub's job ceiling even though it could never receive an authoritative current-head verdict. | ||
|
|
||
| This is a control-plane capacity defect, not a reason to shorten semantic-review inference deadlines. A fixed short `timeout-minutes` would trade one failure mode for another and can kill legitimate long-running review work. | ||
|
|
||
| ## Repair contract | ||
|
|
||
| The polling loop now re-fetches the live pull request before every Reviews API read. It: | ||
|
|
||
| - fails closed when live head/state/draft evidence is missing or malformed; | ||
| - exits non-passing when the live head no longer equals the workflow's immutable `HEAD_SHA`, allowing the stale run to release its runner itself; | ||
| - exits successfully when the PR closes or becomes Draft while the same head is waiting, because no verdict is required in those states; | ||
| - keeps exact-head formal `APPROVED` / `CHANGES_REQUESTED` review evidence as the only terminal substantive verdict; and | ||
| - retains the existing no-short-timeout contract for legitimate semantic reviews. | ||
|
|
||
| The sibling cancellation job remains defense in depth for queued/requested predecessor runs and for legacy workflow revisions that do not contain the in-loop self-retirement check. | ||
|
|
||
| ## Regression evidence | ||
|
|
||
| `tests/test_opencode_poll_self_retirement.py` was committed before the production workflow change. The protected-main workflow did not contain the required in-loop live-state lookup, so the new contract is RED on `main@7d707b8abbb8a3fed95d0efe4121ed9b4f76bb2a`. The production repair follows on the same single-writer branch and is constrained to the existing required-workflow entrypoint plus the new regression and this doctoring record. | ||
|
|
||
| Hosted exact-head evidence remains authoritative for merge. Queue, predecessor, cancelled, skipped, or locally reasoned evidence is not promoted to a passing required check or formal review. | ||
|
|
||
| ## Rollback and observability | ||
|
|
||
| Rollback is the ordinary revert of the workflow repair if exact-head evidence shows false retirement of an authoritative run. During operation, inspect the live PR head together with the workflow run's immutable head SHA. An old-head run that remains in progress after a poll interval indicates either a legacy workflow revision or a failure before the self-retirement loop; do not classify a queued replacement verdict as success. | ||
|
|
||
| After protected integration, re-observe affected leaf repositories. Acceptance requires predecessor-head OpenCode polls to release runner capacity without waiting for a separate cleanup runner, while unchanged current-head semantic reviews remain able to run beyond arbitrary short deadlines. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.