Skip to content

fix(opencode): self-retire superseded verdict polls - #1649

Merged
seonghobae merged 16 commits into
mainfrom
fix/opencode-poll-self-retire-20260902
Sep 1, 2026
Merged

fix(opencode): self-retire superseded verdict polls#1649
seonghobae merged 16 commits into
mainfrom
fix/opencode-poll-self-retire-20260902

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Root cause

A Required OpenCode Review run could validate its PR head once, enter an unbounded Reviews API wait, and keep occupying a runner after that PR advanced. Exact-head concurrency correctly prevents an older event from cancelling a newer authoritative head, while the separate cleanup job needs another runner; under Actions saturation this creates a capacity deadlock. The first self-retirement repair then exposed a second control-plane risk: re-fetching both live PR state and Reviews every 30 seconds roughly doubled repository REST pressure.

Test-first repair chain

  • ebc9f46e482fe777e02f640eb537321a38910a99 added the RED stale-poll self-retirement contract before production changed.
  • The production loop now revalidates live PR head/state/draft before every Reviews read, retires moved heads, preserves closed/Draft exemptions, bounds each REST call to 30 seconds, retries transport failures at most three times, and fails closed without synthesizing evidence.
  • 41a0bfffc7d85e5c63abad2c1acaf07348a8bb22 added the RED REST-rate budget contract after an external review identified the 30-second double-read pressure.
  • b1378cc1e73754186a079a054a10ac9310b5ac8e made that contract GREEN: the poll cadence is 60 seconds, every wait uses the same interval, and Reviews uses per_page=100 with pagination. Four healthy polls therefore issue about 480 baseline REST calls/hour before pagination rather than ~960.
  • A writer-side OIDC variable typo introduced while applying the rate fix was repaired immediately at 3455a3080abbc5ac975c631a99612a1ce1bfec0; tests/test_opencode_oidc_audience_contract.py now prevents recurrence.
  • 1354a1ee0fae1c696be8993442e0e5ffc19fedbb updates the doctoring/rollback record with the final cadence, retry, pagination, and observability contract.

Exact scope

Current protected base: main@546ebae907e997334195dabf0eac13cf6b648b42.
Current exact head: 1354a1ee0fae1c696be8993442e0e5ffc19fedbb.
Changed files:

  • .github/workflows/opencode-review.yml
  • tests/test_opencode_poll_self_retirement.py
  • tests/test_opencode_poll_rate_budget.py
  • tests/test_opencode_oidc_audience_contract.py
  • docs/doctoring/opencode-stale-poll-self-retirement.md

No review threshold, actor identity, branch protection, merge authority, provider route, or verdict semantics are weakened. The 30-second value is a per-request transport bound, not a semantic-review deadline; semantic review may continue indefinitely while the PR remains current and healthy.

Review-evaluation trace

Concrete external findings were turned into durable executable regressions rather than benchmark claims: Devin exposed structural-only poll tests; another reviewer exposed transient REST failure handling; CodeRabbit surfaced time-zone ambiguity in incident evidence; and the later external rate-budget finding demonstrated the double-read pressure. Current threads for those findings are resolved only after the corresponding source/test evidence became current.

Evidence boundary

Hosted exact-head checks/reviews remain authoritative. At the current head, GitHub Actions checks are materialized but still queued; queued, predecessor, skipped, or locally reasoned evidence is not promoted to a passing required check. After protected integration, affected leaf repositories must reacquire fresh exact-head OpenCode/Noema/Strix evidence and predecessor-poll release behavior must be re-observed.

@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

OpenCode verdict polling이 각 반복마다 live PR 상태를 다시 확인합니다. head가 변경되면 polling을 실패로 종료하고, PR이 닫히거나 draft가 되면 성공적으로 종료합니다. 회귀 테스트와 운영 문서가 이 계약을 검증하고 기록합니다.

Changes

OpenCode 폴링 자체 종료

Layer / File(s) Summary
Live PR 재검증 및 자체 종료
.github/workflows/opencode-review.yml
각 polling 반복 전에 live head, draft 여부, PR 상태를 확인합니다. head 불일치 시 superseded poll을 실패로 종료하고, PR이 닫히거나 draft가 되면 성공적으로 종료합니다. 기존 superseded-run 정리 주석도 갱신합니다.
회귀 검증 및 운영 계약
tests/test_opencode_poll_self_retirement.py, docs/doctoring/opencode-stale-poll-self-retirement.md
테스트가 재검증 순서, malformed evidence에 대한 fail-closed 처리, 지속 polling 및 30초 대기를 확인합니다. 문서가 stale poll incident, repair contract, rollback 절차 및 acceptance criteria를 기록합니다.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: 🔵 Low · up to f4ac7

The PR makes stale required-review polls re-check PR state and retire when superseded, reducing runner-capacity deadlocks without weakening verdict checks. Before merging, correct the doctoring document’s September 2, 2026 date or clearly label it as a planned example.

Sequence Diagram(s)

sequenceDiagram
  participant Workflow as OpenCode workflow
  participant GitHub as GitHub PR API
  participant Reviews as Reviews API
  Workflow->>GitHub: 각 polling 반복마다 PR head와 상태 조회
  GitHub-->>Workflow: live head, draft, state 반환
  alt head 변경
    Workflow-->>Workflow: superseded poll 실패 종료
  else PR closed 또는 draft
    Workflow-->>Workflow: polling 성공 종료
  else 상태 유효
    Workflow->>Reviews: verdict 조회
    Reviews-->>Workflow: 리뷰 상태 반환
  end
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 1 files. (2 skipped: 2 …
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 superseded verdict poll의 self-retirement 수정이라는 PR의 주요 변경 사항을 정확하고 간결하게 설명합니다.
Full details: Docstring Coverage

Explanation

Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 1 files. (2 skipped: 2 unsupported.)

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/opencode-poll-self-retire-20260902

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

devin-ai-integration[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

@codex address the current unresolved rate-budget feedback on exact head 41a0bfffc7d85e5c63abad2c1acaf07348a8bb22 using the already-added RED contract in tests/test_opencode_poll_rate_budget.py. Preserve the existing stale-head self-retirement and bounded transport retries. Implement the smallest compatible production change on this same branch: define poll_interval_seconds=60 for the long-running verdict poll, use sleep "$poll_interval_seconds" for normal and transport-retry waits, request Reviews with ?per_page=100 while retaining complete --paginate evidence, and update the stale-poll doctoring with the repository-token budget rationale. Do not weaken exact-head/state validation, semantic verdict filtering, gate authority, credentials, or the no-short-review-timeout contract. Run the focused poll tests and relevant workflow contract suite, then report exact head/evidence. Treat this comment only as implementation acceleration; no self-approval or synthetic status.

Copy link
Copy Markdown
Contributor Author

@codex fix the production regression now pinned RED by commit 8683f6e418a26a33d2c2904b45e4db0a27703b4e: b1378cc accidentally changed the trusted OIDC request from ${OIDC_AUDIENCE} to undefined ${OIDIDC_AUDIENCE} while implementing the rate-budget repair. Revert exactly that typo in .github/workflows/opencode-review.yml; preserve the 60-second poll interval, Reviews per_page=100, stale-head retirement, bounded retries, and every existing trust boundary. Run tests/test_opencode_oidc_audience_contract.py, tests/test_opencode_poll_rate_budget.py, tests/test_opencode_poll_self_retirement.py, plus the relevant workflow contract tests. Do not alter provider/model/credential semantics beyond restoring the declared OIDC audience variable.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

Devin Review

break
fi
sleep 30
sleep "$poll_interval_seconds"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Stale workflow contract fails tests

The existing workflow contract still requires sleep 30 and the old Reviews URL (workflow contract). Both assertions now fail.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

QUEUE_SATURATION_CHICKEN_EGG decision for exact head 0d9a016eb2a3912addbae63fd749d684dd7d49ba. Re-fetched live state immediately before integration: GitHub reports the PR Ready and mechanically mergeable with no conflict; every inline review thread is resolved. The branch now contains the TDD-backed stale-poll self-retirement, bounded 30s REST calls with three-failure fail-closed behavior, 60s steady-state/retry cadence, Reviews per_page=100 with complete pagination, executable fake-gh ordering/exit-status coverage, and the independently added OIDC audience regression plus production correction from accidental OIDIDC_AUDIENCE back to declared OIDC_AUDIENCE. No review timeout, verdict semantics, reviewer identity, credential class, provider route, branch protection, or merge authority is weakened. Current-head CodeRabbit is success; Devin has no submitted current-head substantive finding and remains pending as supplemental status, not a protected required context. The protected admission lanes are queued on this exact head (Security Scan, CodeQL, Python Security, Semgrep, Secret Scan, OSV, Scorecard, SBOM), while .github currently has 1,246 queued workflow runs. This PR directly removes a runner-capacity deadlock in Required OpenCode Review, so waiting for the saturated fleet preserves the defect that prevents those checks from starting. Using the owner-authorized minimum-safe bypass with the exact expected head; no failing substantive test/security finding/CHANGES_REQUESTED/provenance defect/conflict is being bypassed.

@seonghobae
seonghobae merged commit a33203e into main Sep 1, 2026
17 of 37 checks passed
@seonghobae
seonghobae deleted the fix/opencode-poll-self-retire-20260902 branch September 1, 2026 23:05
@chatgpt-codex-connector

Copy link
Copy Markdown

Summary

  • Restored the trusted OpenCode OIDC token request from the undefined OIDIDC_AUDIENCE typo to the declared OIDC_AUDIENCE variable, without changing polling, retries, review pagination, provider/model selection, credentials, or other trust boundaries. .github/workflows/opencode-review.ymlL352-L363
  • Committed the correction as 4a2a183a21909f864f168b2c0501f05baf2933de.
  • Created the requested follow-up PR metadata with title “fix(opencode): restore declared OIDC audience binding.”

Testing

  • python -m pytest -q tests/test_opencode_oidc_audience_contract.py tests/test_opencode_poll_rate_budget.py — 3 passed.
  • python -m pytest -q tests/test_opencode_oidc_audience_contract.py tests/test_opencode_poll_rate_budget.py tests/test_opencode_poll_self_retirement.py — 6 passed and 7 failed because existing self-retirement tests still assert the superseded 30-second/default-page polling contract; they conflict with the requested preserved 60-second and per_page=100 behavior and were not altered by this exact typo-only repair.
  • git diff --check
  • git status --short --branch — clean working tree on branch work.

View task →

@chatgpt-codex-connector

Copy link
Copy Markdown

Summary

Testing

  • python -m pytest -q tests/test_opencode_poll_rate_budget.py tests/test_opencode_poll_self_retirement.py — 12 passed.
  • python -m pytest -q tests/test_opencode_poll_rate_budget.py tests/test_opencode_poll_self_retirement.py tests/test_opencode_required_verdict_regression.py::test_required_workflow_cannot_succeed_with_an_echo_only_placeholder tests/test_opencode_workflow_shell_syntax.py — 18 passed.
  • git diff --check
  • python -m pytest -q tests/test_opencode_*.py tests/test_required_workflow_queue_contract.py — broad pre-commit run completed with 525 passed, 1 skipped, and 5 failures. The focused rate-budget, self-retirement, and updated workflow-contract checks subsequently passed; two failures were unrelated queue-contract expectations, while the remaining stale structural expectations were addressed where relevant.
  • git status --short --branch — clean branch at committed head.
  • ⚠️ gh project view 1 --owner ContextualWisdomLab --format json and gh issue view 974 --repo ContextualWisdomLab/naruon --comments — live Project/spec access was unavailable because this environment has no GitHub authentication.
  • ⚠️ command -v make_pr — the required make_pr tool is not installed or exposed in this environment, and no authenticated Git remote is configured, so a new pull request could not be created programmatically.

View task →

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant