Skip to content

fix(scheduler): do not cancel same-SHA scan-pr-queue on review - #2289

Open
seonghobae wants to merge 18 commits into
fix/opencode-inflight-dispatch-dedupefrom
fix/scan-pr-queue-same-sha-review-cancel
Open

seonghobae wants to merge 18 commits into
fix/opencode-inflight-dispatch-dedupefrom
fix/scan-pr-queue-same-sha-review-cancel

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Current authority — 2026-09-22 KST

Exact head is e2b699a45a3f29d48fd0891ae9cb42997789e9ec, OPEN / Draft, still based on canonical OpenCode admission owner #2283 predecessor 368b87cd929438241032bc6110e33856965b1f5a. The parent has since moved ordinary-forward to 928fc276891b185943a2a93ac003e227e4e47f6a; this successor is therefore intentionally stale-base until that parent obtains complete fresh exact-head acceptance. Do not duplicate the parent fixture repair or shared dependency repair into this effective delta.

The earlier stale-base finding was repaired ordinary-forward at e2b699a… as a two-parent adoption commit over prior #2289 021ffb2bb6914f810f192cc69980ecc1245c79d0 and then-current #2283 368b87cd…. Compare from that accepted-at-the-time base leaves the eight scheduler-owned effective paths; #2283's admission implementation/test are base-owned. Current-head COMMENT review 5260136260 records that single-writer split.

This lane owns exact-head scheduler serialization, metadata-only predecessor cleanup, live PR-head revalidation immediately before cancellation, and bounded proof that accepted cancellations reach terminal completed/cancelled. The canonical #2283 admission state machine remains parent-owned.

#2283's former Runtime Quality RED was causally source-repaired: 0d472b4c546388e115fad9c1919696d7aeb3a098 adds only the missing "status":"queued" to the retained already-in-flight fixture, and 928fc276891b185943a2a93ac003e227e4e47f6a restores trailing-newline collateral. Current parent evidence is now split: Runtime Quality 35552210925, Security Scan 35552210897, and SAST 35552210972 are exact-head success; Python Security 35552210893 is terminal failure after pip-audit reports AnyIO 4.14.0 CVE-2026-63374 / CVE-2026-64847 / CVE-2026-63349 in requirements-strix-ci-hashes.txt; CodeQL 35552210898 remains queued. Canonical dependency owner #2278 already owns AnyIO 4.14.0 -> 4.14.2, so this successor must not copy that repair. Parent evidence: #2283 comment 5763321717; the delayed Security recovery / remaining CodeQL queue is tracked under #712 comment 5763458164.

Current #2289 hosted generation remains predecessor-relative and cannot override the moving parent: SAST 35501047691 completed success; CodeQL PR 35501047686 and Security Scan 35501047693 were queued on this head. None transfer after a future restack.

Completion requires #2278 accepted integration/adoption and #2283 complete fresh exact-head terminal acceptance first, then ordinary/non-force reconciliation onto that accepted parent, followed by fresh exact-head hosted acceptance for this successor, no actionable review, qualifying independent approval, and ordinary protected-main merge. No self-approval, source-neutral wake/no-op commit, blind rerun, dependency-fix duplication, paid fallback, force push, destructive rebase, synthetic passing status, or gate weakening.

A pull_request_review shares the PR concurrency group with pull_request_target, so cancel-in-progress on that event retired scan-pr-queue even when the head SHA had not changed.
@coderabbitai

coderabbitai Bot commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 8c26032c-f16c-43c2-922a-2acf0475e205

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

P1 concurrency finding at exact head 846cee70c79ad8645d185f548e7ea3017733ea0f: removing pull_request_review from cancel-in-progress preserves an already-running scan, but GitHub's concurrency contract still cancels and replaces an existing pending run when another run enters the same group. Thus a review event can still retire a queued scan-pr-queue for the same exact head. The authoritative contract is https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/control-workflow-concurrency (queue: single is the default; queue: max preserves multiple pending runs; it cannot be combined with cancel-in-progress: true). Repair should first add a RED contract for pending preservation, then use the native queue contract and rely on the scheduler's live PR/head validation to make stale events fail closed. No arbitrary retry/count fallback is appropriate.

Comment thread .github/workflows/pr-review-merge-scheduler.yml Outdated
@seonghobae
seonghobae marked this pull request as draft September 19, 2026 20:02

Copy link
Copy Markdown
Contributor Author

Repair receipt — exact head be51220705e2967ebd87746be8d95c35ef42d6d6

  • Root cause: excluding pull_request_review from cancel-in-progress prevented running cancellation but left GitHub's default queue: single, so a new review run could still replace a pending required scan.
  • RED 17be694aaff421f8b48aa24250aeedd8eb2d696c: pending-preservation contract present; production fails it.
  • GREEN ce3a4d9f0b93584de85a076fb314840d262d3b68: native queue: max, no cancellation key, no head-SHA group partition, live PR targeting retained.
  • Exact remote evidence: focused assertions 2/2; Python compile 1/1; YAML parse 1/1.
  • Governance: CONTROL-SCHEDULER-PENDING-PRESERVATION-01 added to docs/product-technical-gap-baseline.md; PR remains Draft/Proposed.

Full pytest is not claimed because pytest is absent from the isolated execution environment. Fresh hosted exact-head Checks and qualifying independent approval remain mandatory; no self-approval, gate relaxation, force push, or stale evidence was used.

queue: max already keeps a pending run when cancellation is off, but the
close-event contracts still required the cancellation key GitHub rejects
beside that queue. State both cases in the contract instead.

Co-authored-by: Cursor <cursoragent@cursor.com>
@seonghobae

Copy link
Copy Markdown
Contributor Author

6784c19 evidence boundary

Platform contract, not a live run of this SHA:

GitHub has not validated this head's workflow file. pull_request_target run 35467474589 is queued for this PR and executes the base-branch copy, not 6784c193a. No server-side validation error for this blob has been observed, and none has been produced. Local actionlint is not that check; this repo already records that actionlint 1.7.12 misses GitHub-only workflow validation.

The 76 passed tests in tests/test_required_workflow_queue_contract.py and tests/test_close_empty_pr_queue_pressure.py are string contracts: queue: max is present, the cancellation key is absent, and the group does not contain the head SHA. They are not a live pending, running, or new-head preservation experiment. Those three cases have not been executed on this SHA.

Close-event cleanup, static only: scan-pr-queue is skipped when github.event.action == 'closed'. There is no cancel-closed-pr-runs job. Because the cancellation key is absent, a close event does not cancel an in-progress scan. No close event has run on this SHA.

Independent review: GraphQL requestReviews for bot copilot-pull-request-reviewer (BOT_kgDOCnlnWA) returned no remaining review request. The PR is still draft, reviewDecision is null, and the only reviews are the author's comments. Draft stays. No admin bypass, no self-approval.

@seonghobae
seonghobae marked this pull request as ready for review September 19, 2026 20:53
Corrected RED: preserve same-head pending scans with an exact-head workflow
queue, while requiring an actions:write metadata cleanup to retire only
predecessor-head runs after repository/PR/head revalidation.

Focused result before production repair: 4 failed, 72 passed.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

P1 exact-head inconsistency at e2647c5b6d72259e99a36a4955faeb0a2967931c: the newly committed contracts require an exact-head concurrency key and a bounded cancel-superseded-pr-runs metadata job, but the production workflow contains neither that job nor client_payload.pr_head_sha, force-cancel, live_target_matches, or TARGET_PR_HEAD_SHA. The exact test tree is therefore RED and the PR body still names predecessor head be512207…. Keep Draft/Proposed, implement the tested production boundary, and regenerate exact-head evidence before review admission.

Comment thread tests/test_required_workflow_queue_contract.py
@seonghobae
seonghobae marked this pull request as draft September 19, 2026 21:03

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

P0 scheduler contract finding on exact head e2647c5b6d72259e99a36a4955faeb0a2967931c.

queue: max itself is now an official GitHub Actions concurrency contract (up to 100 pending runs; it cannot coexist with cancel-in-progress: true), so that part is valid. The current production group, however, is still PR-stable: pull_request_target / pull_request_review resolve to pr-{number} and do not include github.event.pull_request.head.sha or dispatch pr_head_sha. That directly contradicts the new tests/docstrings, which assert both head-SHA expressions are present and describe an “exact-head queue” where a successor head enters another workflow group. The workflow comment also still says “the group is the PR number, not the head SHA.”

RED: execute the current exact-head focused tests against the actual workflow blob and prove two concurrent admissions for head A are serialized/preserved while head B is admitted into a distinct group; the literal contract assertions should currently fail because the group contains no head SHA. Also cover targeted repository_dispatch, where client_payload.pr_head_sha must be bound to the same identity contract.

GREEN: choose one causal contract and make production/tests/docs agree. If the intended design is exact-head workflow groups, include the validated live head SHA in every PR-targeted group and keep the bounded PR-level predecessor cleanup as the retirement boundary. If the intended design is PR-stable FIFO, remove the exact-head assertions/claims and prove that a queued stale predecessor cannot delay or mutate the successor beyond the stated SLA. Preserve queue: max, live PR revalidation, and fail-closed stale-event behavior. Then re-run exact-head hosted scheduler tests/security checks. The PR body’s Current authority SHA (be512207…) is also stale versus this live head and should be currentized before merge review.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

P0 single-writer follow-up: live .github#2283 already owns this exact scheduler-admission boundary at 91c19fd49f00bb44f8143dea8c0f0ecb2de6a564 and has the stronger layered contract: workflow-level {repository, PR, exact head} + queue: max, with downstream {repository, PR} cancellation to retire predecessor-head review work. Its focused/full regressions also cover malformed workflow-run pages and explicit present/stale/missing admission states.

That makes #2289 a parallel writer on the same pr-review-merge-scheduler.yml concurrency contract, and its current PR-stable group is semantically behind #2283. Do not independently repair the same boundary here or close this PR merely as “duplicate.”

Acceptance: inventory every valid #2289 delta/evidence not already present in #2283 (including the observed #2284 cancellation incident, queue-limit/FIFO documentation, close-event cleanup assertions, and Gap-row evidence). Ordinary-forward those missing deltas into the canonical scheduler owner or a verified successor, then prove source/test/fixture/docs equivalence at exact heads. Only after complete succession is verified can #2289 become PR=0. If #2289 contains no unique valid semantic delta after that comparison, record the zero-delta/equivalence proof rather than landing a second scheduler implementation.

@seonghobae

Copy link
Copy Markdown
Contributor Author

actionlint queue evidence, not a suppression

Local binary: actionlint 1.7.12, built from source with go1.26.1. On 6784c193a it reported unexpected key "queue" for "concurrency" section at .github/workflows/pr-review-merge-scheduler.yml:98.

Official platform contract, which this binary does not implement: GitHub changelog 2026-05-07 allows queue: max when cancellation is false or unset. https://github.blog/changelog/2026-05-07-github-actions-concurrency-groups-now-allow-larger-queues/ Docs: queue: max combined with cancel-in-progress: true is a workflow validation error. https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/control-workflow-concurrency

Released tool: the latest actionlint release is still v1.7.12, published 2026-03-30, before that changelog. rhysd/actionlint#661 would parse queue, and its author closed it on 2026-06-23. It is not in the latest release, so there is no newer released binary to install. No ignore rule was added.

Required CI: branch protection on main does not list an actionlint context. The required contexts are CodeQL, scan-pr-queue, dependency-review, osv-scan, trivy-fs, scorecard, noema-review, required-workflow-bootstrap, coverage-evidence, and opencode-review. pr-review-autofix.yml can invoke actionlint only when the binary is already installed, and that job is not one of those required contexts. Current head rollup is PENDING, so this note is not a completed required-check result.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Follow-up on exact 406c7178974c3b887694a229a59c66a02e0810dd: the earlier production/tests/docs contradiction is source-level repaired. The workflow group now actually binds PR admissions to exact head SHA (including dispatch pr_head_sha), keeps queue: max, and introduces a revalidated predecessor-retirement job; the focused contracts now describe the implementation they test. That closes my prior RED about a PR-stable production group masquerading as an exact-head queue.

The remaining gate is single-writer succession, not the original concurrency bug. .github#2283 still owns the same scheduler-admission boundary and already carries the broader duplicate-dispatch/formal-receipt/malformed-page state machine. Before either PR can disappear, compare the two exact heads and move every valid #2289-only delta into one canonical successor—especially the observed #2284 cancellation incident, close-event cleanup behavior, queue: max evidence, and any predecessor-run retirement tests/docs that #2283 does not yet own. Then prove source/test/fixture/Gap evidence equivalence. Until that succession is verified, #2289 is not PR=0 and should remain Draft.

Traceability is also still stale: the body’s Current authority says be512207… while the live head is 406c7178…. Currentize that evidence and reacquire exact-head hosted checks/independent review after consolidation.

Preserve both divergent exact-head admission lineages with an ordinary two-parent merge. Resolve the shared queue-contract test by retaining the scheduler predecessor-retirement contracts and the OpenCode exact-head dispatch contracts.
@seonghobae
seonghobae changed the base branch from main to fix/opencode-inflight-dispatch-dedupe September 19, 2026 21:12

Copy link
Copy Markdown
Contributor Author

Exact-head repair receipt — 10dc596407af27560974b7323aa9cd9e1b3f013d

  • Root cause: default single-pending replacement, then tests/production drift, then misuse of pull_request_target run .head_sha as PR-head authority.
  • RED→GREEN: 17be694ace3a4d9f; concurrent RED e2647c5b→production 739a34c0; authority RED 648674c9→GREEN 406c7178.
  • Single-writer lifecycle: ordinary two-parent stack 873a35f4 preserves both divergent histories; fix(scheduler): do not cancel same-SHA scan-pr-queue on review #2289 is retargeted onto fix(opencode): skip duplicate same-head review dispatch while in flight #2283 and is 11 commits ahead / 0 behind with four scheduler-owned paths. No predecessor was closed or discarded.
  • Exact evidence: static contracts 14/14; jq synchronize/closed semantic fixtures 2/2; Python compile 2/2; YAML parse 1/1; cleanup Bash syntax 1/1. The final Gap commit 10dc5964 leaves all source/test blob SHAs unchanged.
  • Full pytest is not claimed because pytest is absent in the isolated environment.
  • Status remains Draft / Proposed. Prerequisite fix(opencode): skip duplicate same-head review dispatch while in flight #2283 integration, fresh exact-head hosted Checks, actionable-thread exhaustion, and qualifying independent approval remain required.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Current-head direct repair receipt for c39f57d4890be5bab12e8845014eeefe1e99f7ae (tree 722fc4d1…). RED: predecessor source accepted force-cancel without proving terminal state and did not re-read the live PR after candidate selection; three executable regressions failed. GREEN 8067fb65 revalidates immediately before every mutation and requires completed/cancelled within six bounded reads. Exact combined scheduler-contract file is 74/74 GREEN in both default and GITHUB_ACTIONS=true; compile and diff checks are GREEN. c39f57d4 updates the canonical Gap evidence. The branch remains Draft/Proposed pending #2283, hosted exact-head Checks, and independent approval.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Review scope against the live base, then ready

The 15-file / 40-commit figure is real, and it is not this pull request's unique diff. git diff 6784c193a3aba019c12906802cf74d3c6ac29cc5...021ffb2bb6914f810f192cc69980ecc1245c79d0 is 15 files, +1551/−87, and git rev-list --count over that range is 40. That measures only the increment since the previous review SHA.

The live base is 91c19fd49f00bb44f8143dea8c0f0ecb2de6a564. git merge-base of that base and 021ffb2bb6914f810f192cc69980ecc1245c79d0 is the base itself. The unique three-dot diff is 8 files, +424/−19, across 17 commits:

  • .github/workflows/pr-review-merge-scheduler.yml
  • docs/doctoring/20260920-scheduler-cancellation-verification.md
  • docs/product-technical-gap-baseline.md
  • tests/test_close_empty_pr_queue_pressure.py
  • tests/test_current_head_coalescer_self_cancellation.py
  • tests/test_opencode_agent_contract.py
  • tests/test_opencode_workflow_shell_syntax.py
  • tests/test_required_workflow_queue_contract.py

The OpenCode workflow and inflight-dispatch files in the 40-commit range are already on this base, so they are outside the pull request's own delta. Review of record for the increment remains #2289 (comment).

No listed Orca worktree on this host or on s1 is checked out at 021ffb2. The only scheduler worktree found is /tmp/scan-same-sha-cancel, still at 6784c193a, and it did not push the later commits. MacBookAir's worktree list from here still returns the local host, so that host was not actually enumerated. The tip commit is 2026-09-19T21:36:59Z and has not moved. Draft stays only if someone still has edits; say so on this thread. Otherwise this comment marks the pull request ready so CodeRabbit and Devin are not skipped. A non-author GitHub APPROVE is still required and is not claimed here.

@seonghobae
seonghobae marked this pull request as ready for review September 19, 2026 21:58
@seonghobae
seonghobae marked this pull request as draft September 19, 2026 22:03
@seonghobae

Copy link
Copy Markdown
Contributor Author

Ready 이후 현재 head 021ffb2bb6914f810f192cc69980ecc1245c79d0를 다시 읽었습니다. 미해결 리뷰 스레드는 0입니다. CodeRabbit/Devin의 새 라인 지적은 없고, 기존 작성자 코멘트는 이전 SHA의 이미 수리된 항목입니다. 코드 수정은 하지 않았습니다.

필수 컨텍스트의 최신 완료 결론은 21:58Z pull_request_target 런(scan-pr-queue 35471951373, noema 35471951365, OpenCode bootstrap 35471951449, Strix 35471951435)이 CANCELLED라 rollup은 FAILURE입니다. 같은 head의 후속은 22:04:01Z에 이미 QUEUED입니다: scan-pr-queue 35472240809, noema 35472240824, OpenCode bootstrap 35472240839, Strix 35472240849. pull_request Semgrep/CodeQL/gitleaks(35471951129 등)도 QUEUED입니다. 대기 중인 후속이 있으므로 추가 dispatch는 넣지 않았습니다.

독립 비작성자 APPROVE는 없습니다. reviewDecision은 null이고 merge하지 않습니다. 이 PR의 base는 main이 아니라 fix/opencode-inflight-dispatch-dedupe(91c19fd49, #2283 head)입니다.

@seonghobae

Copy link
Copy Markdown
Contributor Author

스택: #2289 021ffb2bb → base #2283 91c19fd49main e6334e229. #2289 unique diff는 그 base 대비 8 files, +424/−19입니다. 22:03:59Z에 head 변경 없이 ConvertToDraft 되었습니다. 22:04:01Z QUEUED 후속(35472240809 등)을 또 취소하지 않으려고 이번 턴에 ready를 다시 누르지 않습니다. 부모 #2283은 미해결 스레드가 없어 ready로 전환합니다. 둘 다 독립 APPROVE와 필수 체크 성공 전에는 merge하지 않습니다.

@seonghobae

Copy link
Copy Markdown
Contributor Author

같은 SHA draft 재전환의 원인. 이번 턴에 ready/draft는 바꾸지 않았습니다.

이벤트 actor는 전부 GitHub 사용자 seonghobae입니다. 로그인만으로는 세션을 구분할 수 없습니다. scripts/와 workflow에는 convertPullRequestToDraft가 없습니다. 워크플로가 draft로 바꾸는 자동화는 아닙니다.

  • 21:03:00Z 리뷰: Keep Draft/Proposed, implement the tested production boundary (e2647c5b 시점). ConvertToDraft는 21:03:02Z.
  • 21:44:30Z 리뷰: Draft/Proposed remains correct because #2283 is the prerequisite base, hosted check가 queued이고 독립 승인이 없음. 대상 head는 지금과 같은 021ffb2.
  • 22:03:59Z ConvertToDraft는 21:58:02Z Ready 이후 6분, head 변경 없음, 같은 시각의 댓글 없음.

실행되는 파일은 이 head가 아닙니다. pull_request_target은 base 91c19fd49의 workflow를 탑니다. 그 파일은 group이 pr-{number}이고 cancel-in-progress: true이며 ready_for_reviewconverted_to_draft가 둘 다 트리거입니다. 그래서 같은 SHA의 ready/draft 한 번이 이전 scan을 취소합니다. head 021ffb2queue: max는 이 PR 실행에 쓰이지 않습니다.

리뷰 skip도 그 base 파일에 있습니다. noema-review.yml의 noema job ifconverted_to_draft를 제외합니다. opencode-review.yml은 live draft==true이면 current-head review를 요청하지 않습니다. 22:04:01Z QUEUED 런(35472240809, 35472240824, 35472240839, 35472240849)은 그대로 두고 다시 dispatch하지 않습니다. 그 런이 시작될 때 PR이 draft면 리뷰 job은 skip됩니다.

조치 소유: Keep Draft 리뷰를 쓴 seonghobae 세션. 이 리드는 ready/draft를 다시 누르지 않습니다. 해제 조건: 같은 SHA 021ffb2에 ConvertToDraft를 다시 호출하지 말 것. 21:03의 production 공백은 이후 커밋이 고쳤다고 그 리뷰 계열이 적었습니다. 21:44의 #2283 선행·독립 승인·hosted check는 merge 조건이지, queued scan을 취소하는 draft 이벤트의 근거가 아닙니다. 리뷰 job과 queued scan을 동시에 살리려면 실행 base(#2283 브랜치)의 cancel-in-progress를 고쳐야 하는데, #2283은 22:18:29Z에 이미 QUEUED(35472949574 등)라 지금 그 브랜치에 새 SHA를 올리지 않습니다.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

21:03:00Z와 21:44:30Z Keep Draft 리뷰에 대한 답입니다. 이번 턴에 ready/draft는 바꾸지 않았습니다.

merge 조건과 ready 조건은 다릅니다. merge는 비작성자 APPROVE, 필수 체크 성공, 그리고 이 PR보다 #2283이 main에 들어가는 순서입니다. ready는 그 승인이 아닙니다. opencode-review.yml은 live draft이면 리뷰 dispatch를 하지 않고, changed-scope job은 converted_to_draft 이벤트를 제외합니다. CodeRabbit/Devin도 draft를 건너뜁니다. 그래서 merge 게이트를 이유로 ConvertToDraft를 내면, 같은 SHA의 대기 중인 scan이 base workflow의 cancel-in-progress: true로 취소되고 리뷰 job은 시작되지 않습니다.

GitHub actor seonghobae는 사람 직접 조작의 증거가 아니고, 그 리뷰의 세션 소유는 명령 근거 없이 확정하지 않습니다. 같은 SHA 021ffb2bb에 ConvertToDraft를 반복하지 말아 주십시오.

현재 순서는 이렇습니다. 22:04:01Z 런 35472240809, 35472240824, 35472240839, 35472240849는 아직 QUEUED입니다. 35472240839의 Detect changed scope는 이미 SKIPPED라 이 런은 OpenCode를 요청하지 않습니다. 이 넷이 끝나기 전에 ready를 누르면 네 그룹이 함께 취소되므로 지금은 누르지 않습니다. #2283 91c19fd49는 이미 ready이고 22:18:29Z 런 35472949574 외가 QUEUED입니다. 그 대기열이 리뷰 입구이고 두 번째 이벤트는 만들지 않습니다. 이 넷이 terminal이 된 뒤에 ready 한 번이 #2289 리뷰 개시입니다. 그 전에도 후에도 같은 SHA draft 반복은 하지 않습니다.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Ready once: original same-SHA pull_request_target quartet is terminal — merge-scheduler 35472240809 SUCCESS; Noema/OpenCode/Strix 35472240824/839/849 CANCELLED. Leaving draft had blocked review admission.

35474630698 (pull_request_review) was still QUEUED; marking ready may cancel that redundant scheduler. No draft flip-flop after this. Independent non-author APPROVE still required before merge.

Copy link
Copy Markdown
Contributor Author

Governance handoff: this successor's exact-head queue: max + metadata-only predecessor cleanup is currently the strongest executable reference for avoiding same-head loss and proving stale cancellation, but it conflicts with the still-protected AGENTS.md@e6334e229581a918e2f22de18733b76fa65d7e71 rule that PR workflows use PR-wide cancel-in-progress: true and omit head SHA.

This is not a request to undo #2289 or copy its mutable source elsewhere. Canonical AGENTS lane #1885 now owns the explicit reconciliation finding (comment 5747791655), and #712 tracks the operational classification consequence. Preserve #2289 and its tests/evidence as candidate architecture; do not claim ordinary merge authority until protected governance and prerequisite #2283 agree on the same event-order-independent contract. No close, self-approval, bypass, force update, or synthetic GREEN is requested.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Merge-prep (lead, local three-dot — no REST Actions re-poll)

Stack: base fix/opencode-inflight-dispatch-dedupe (#2283), not main. Land #2283 first; this PR is not independently mergeable onto main.

Delta (local origin/main...021ffb2): scheduler concurrency moves to exact-head groups + queue: max (drops review/pull_request_target cancel-in-progress same-SHA cancel), plus cancel-superseded-pr-runs that retires only revalidated predecessor heads; OpenCode inflight gate + tests/docs.

Blockers (unchanged policy):

  1. Independent non-author formal APPROVE on exact head 021ffb2… (same-login cannot self-approve).
  2. Required checks on current head — last GraphQL sample still showed post-ready OpenCode/Noema/Strix/CodeQL etc. runner QUEUED (pre-admit). Not treated as endpoint failure.
  3. Do not draft-flip; do not age-cancel same-head runs.

REST Actions listing hit rate limit this tick — no further run-list polling; resume cancel triage from proven CLOSED/superseded evidence when core quota recovers.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Independent review request (lead, pre-CI-complete)

Exact head 021ffb2bb691. Please run a full review on this head without waiting for Actions queue drain.

Merge still requires fail=0 ∧ pending=0 ∧ independent non-author APPROVE — bot COMMENT is not merge APPROVE evidence.

Copy link
Copy Markdown
Contributor Author

Ordinary/non-force descendant repair completed after canonical #2283 advanced. #2283 moved from 91c19fd49f00bb44f8143dea8c0f0ecb2de6a564 to 368b87cd929438241032bc6110e33856965b1f5a; #2289 had therefore become a diverged stack even though the branch name still targeted #2283.

I preserved prior #2289 021ffb2bb6914f810f192cc69980ecc1245c79d0 as first parent, adopted current #2283 368b87cd929438241032bc6110e33856965b1f5a as second parent, and rebuilt the tree from the current #2283 tree with only #2289's eight effective scheduler-owned paths overlaid. New exact head is e2b699a45a3f29d48fd0891ae9cb42997789e9ec.

Fresh compare against current #2283 is now ahead 18 / behind 0, merge base exactly 368b87cd..., and the effective delta remains exactly the same eight paths. The two newly landed #2283 in-flight gate files are inherited rather than overwritten. GitHub metadata is OPEN / Ready / mergeable with base SHA now equal to current #2283.

New exact-head hosted generation is natural, not a wake commit: CodeQL 35501047686, SAST 35501047691, Security 35501047693 are queued/nonterminal. Pre-restack checks/reviews do not transfer. Do not merge until prerequisite #2283 and this exact successor have terminal required evidence and qualifying independent current-head approval.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Current-stack review after concurrent ordinary-forward movement. e2b699a45a3f29d48fd0891ae9cb42997789e9ec is an ordinary two-parent adoption commit with parents prior #2289 021ffb2… and current canonical #2283 368b87cd…. Fresh compare from current base 368b87cd… leaves exactly the eight scheduler-owned effective paths; the two opencode_inflight_dispatch_gate paths owned by #2283 disappear from the remaining delta. This resolves the stale-base/parallel-owner finding without force/rebase or source copying. Fresh current-head CodeQL/SAST/Security are queued, so no hosted or review evidence from 021ffb2… transfers to this head. COMMENT only; qualifying independent approval and terminal exact-head acceptance remain required.

@opencode-agent opencode-agent 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.

Pull request overview

OpenCode reviewed the current-head product diff. Coverage is a separate gate.

Changed files

  • .github/workflows/pr-review-merge-scheduler.yml — GitHub Actions review job
  • CHANGELOG.d/20260920-scheduler-cancellation-verification.md — repository behavior
  • docs/product-technical-gap-baseline.md — operator or user guidance
  • tests/test_close_empty_pr_queue_pressure.py — regression suite
  • tests/test_current_head_coalescer_self_cancellation.py — regression suite
  • tests/test_opencode_agent_contract.py — regression suite
  • tests/test_opencode_workflow_shell_syntax.py — regression suite
  • tests/test_required_workflow_queue_contract.py — regression suite

Changed behavior

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Workflow: pr-review-merge-scheduler.yml"]
  S1 --> I1["GitHub Actions review job"]
  I1 --> R1["Review risk: Workflow: pr-review-merge-scheduler.yml"]
  R1 --> V1["actionlint plus required checks"]
  Evidence --> S2["Repository file: 20260920-scheduler-cancellation-verification.md"]
  S2 --> I2["repository behavior"]
  I2 --> R2["Review risk: Repository file: 20260920-scheduler-cancellation-verification.md"]
  R2 --> V2["required checks"]
  Evidence --> S3["Docs: product-technical-gap-baseline.md"]
  S3 --> I3["operator or user guidance"]
  I3 --> R3["Review risk: Docs: product-technical-gap-baseline.md"]
  R3 --> V3["docs review"]
  Evidence --> S4["Test: test_close_empty_pr_queue_pressure.py (5 files)"]
  S4 --> I4["regression suite"]
  I4 --> R4["Review risk: Test: test_close_empty_pr_queue_pressure.py (5 files)"]
  R4 --> V4["targeted test run"]
Loading

Findings

No source-backed product finding is synthesized from the coverage gate. A coverage miss belongs in the status comment.

  • Head SHA: e2b699a45a3f29d48fd0891ae9cb42997789e9ec
  • Workflow run: 35529329097
  • Workflow attempt: 1
  • Coverage gate: failure

Review outcome

Coverage is a gate, not the review. This body reviews the changed product files.

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Workflow: pr-review-merge-scheduler.yml"]
  S1 --> I1["GitHub Actions review job"]
  I1 --> R1["Review risk: Workflow: pr-review-merge-scheduler.yml"]
  R1 --> V1["actionlint plus required checks"]
  Evidence --> S2["Repository file: 20260920-scheduler-cancellation-verification.md"]
  S2 --> I2["repository behavior"]
  I2 --> R2["Review risk: Repository file: 20260920-scheduler-cancellation-verification.md"]
  R2 --> V2["required checks"]
  Evidence --> S3["Docs: product-technical-gap-baseline.md"]
  S3 --> I3["operator or user guidance"]
  I3 --> R3["Review risk: Docs: product-technical-gap-baseline.md"]
  R3 --> V3["docs review"]
  Evidence --> S4["Test: test_close_empty_pr_queue_pressure.py (5 files)"]
  S4 --> I4["regression suite"]
  I4 --> R4["Review risk: Test: test_close_empty_pr_queue_pressure.py (5 files)"]
  R4 --> V4["targeted test run"]
Loading

@opencode-agent

opencode-agent Bot commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

OpenCode Review Overview

Coverage evidence did not pass, so approval is blocked. The formal pull-request review is the source-backed diff review, not this status comment.

@seonghobae
seonghobae marked this pull request as ready for review September 22, 2026 08:39

@cwl-noema-review cwl-noema-review 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.

Noema LLM review

The PR correctly implements the transition from cancel-in-progress to queue: max for the scheduler, ensuring that runs for the same head are preserved while runs for superseded heads are retired via the new cancel-superseded-pr-runs job. This resolves the 'pending-preservation' P1 issues identified in prior threads. Security is improved by enforcing a case-insensitive match between the targeted dispatch's TARGET_HEAD_SHA_INPUT and the live PR head SHA (lines 418-421). The implementation is verified by three distinct executable probes in tests/test_required_workflow_queue_contract.py: test_scheduler_cleanup_revalidates_target_after_run_selection (falsifies concurrent head advance regression), test_scheduler_cleanup_fails_when_accepted_cancel_never_finishes (falsifies non-terminal cancellation regression), and test_scheduler_cleanup_verifies_accepted_cancelled_state (falsifies asynchronous terminal proof regression). All changes align with the updated product-technical gap baseline.

Reviewed changed lines

  • .github/workflows/pr-review-merge-scheduler.yml:90 (RIGHT): The updated concurrency group now includes the PR head SHA as a suffix. This ensures that runs for the same head are grouped together, while runs for different heads enter distinct groups. Combined with queue: max, this preserves pending runs for the same head while allowing new heads to proceed, resolving the previous pending-preservation issue.
  • .github/workflows/pr-review-merge-scheduler.yml:110 (RIGHT): The cancel-superseded-pr-runs job introduces a robust metadata-only cleanup. It implements live_target_matches to revalidate the PR state before and during the cancellation loop, preventing accidental cancellation of runs if the head advances concurrently. The force-cancel loop correctly polls for a terminal completed/cancelled status rather than assuming a successful POST request implies completion.
  • .github/workflows/pr-review-merge-scheduler.yml:420 (RIGHT): The targeted dispatch validation now requires TARGET_HEAD_SHA_INPUT to match the live PR head SHA (case-insensitive). This closes the security/correctness gap where a caller could have triggered a scheduler run for a stale head.
  • tests/test_required_workflow_queue_contract.py:1552 (RIGHT): The new test cases test_scheduler_cleanup_revalidates_target_after_run_selection, test_scheduler_cleanup_fails_when_accepted_cancel_never_finishes, and test_scheduler_cleanup_verifies_accepted_cancelled_state provide direct executable proof that the three critical failure modes (concurrent advance, non-terminal state, and asynchronous terminal proof) are handled correctly.

Adversarial validation

  • tests/test_required_workflow_queue_contract.py:1552 (RIGHT) falsified: Concurrent head advance after run selection might still lead to cancellation of the new head. — The test simulates a head change between the selection of a run to cancel and the actual cancellation call, proving that live_target_matches prevents the mutation.
  • tests/test_required_workflow_queue_contract.py:1552 (RIGHT) falsified: A successful API response to force-cancel is treated as terminal, potentially leaving a zombie run. — The test mocks a scenario where force-cancel returns 200 but the run remains in_progress, proving the cleanup job correctly errors out.
  • tests/test_required_workflow_queue_contract.py:1552 (RIGHT) falsified: Asynchronous cancellation state updates are missed, leading to false failure reporting. — The test mocks a delayed transition to completed/cancelled and proves the polling loop correctly identifies the terminal state.
  • Residual risk: low

Findings

  • No blocking findings.
  • Result: APPROVE
  • Head SHA: e2b699a45a3f29d48fd0891ae9cb42997789e9ec
  • Reviewer credential: noema-review-github-app-refresh
  • Actor: cwl-noema-review[bot]

This branch has not been deployed

No deployments
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