Repository navigation
Block scheduler merges without exact-head independent approval #771
Description
Incident evidence
ContextualWisdomLab/inkspan#60 merged at 2026-08-05T03:30:37Z from exact head b02f1662c7118faf1aaf44b8ea1efb376cfc3a85 into merge commit 45d9bf315a626c686658b3148d3775405c878617 while its PR body still marked Exact-current-head independent approval and protected merge incomplete.
The retrievable review history contains only two dismissed OpenCode CHANGES_REQUESTED reviews, both attached to older head ab32926d84030f0e23cda4a2ca1fd87bf2035761. No approving review attached to the merged head is visible through the PR review API. Direct CI and security success does not substitute for independent approval.
This issue does not assert which actor performed the merge. The available connector does not expose the organization audit-log event, ruleset insight, bypass actor, or merged_by identity. An organization administrator must inspect those records.
Central scheduler defect
scripts/ci/pr_review_merge_scheduler.py currently treats an exact-head OpenCode approval as sufficient to enter direct merge or auto-merge paths. The direct path checks current-head OpenCode evidence, unresolved threads, failed checks, Strix evidence, and mergeability, then invokes gh pr merge --match-head-commit.
It does not require either of these before the mutation:
reviewDecision == APPROVED; or- an exact-head independent Noema/non-OpenCode approving review.
GitHub rulesets can designate users, roles, teams, or GitHub Apps as bypass actors. A scheduler credential that is accidentally or intentionally on a bypass list can therefore convert this omitted application-level gate into a real protected-merge bypass. GitHub documents both required pull-request review rules and ruleset bypass actors, including pull-request-only bypass mode.
Immediate administrative action
- Inspect the organization audit log and Rule Insights for the merge of
inkspan#60at2026-08-05T03:30:37Z. - Identify the merge actor and whether a repository role, organization administrator, user, team, GitHub App, or token source exercised ruleset or branch-protection bypass.
- Inspect all active organization and repository rulesets targeting
inkspan:main, including required approval count, latest-push approval, required OpenCode/Noema workflows, conversation resolution, and bypass actors/modes. - Remove merge-scheduler credentials and reviewer Apps from bypass lists unless a separately approved break-glass design requires them. A reviewer identity must not also possess an implicit path around its own gate.
- Preserve the audit evidence and record the root cause. Do not retroactively synthesize an approval for test: add scheduler decision contract fixtures #60.
Required code repair
Implement test-first, fail-closed merge eligibility:
- require
reviewDecision == APPROVEDbefore direct merge and before enabling native auto-merge; - require an exact-current-head approving review from the configured independent reviewer identity, separate from OpenCode and separate from the last pusher;
- reject stale, dismissed, commented, fallback-only, body/head-mismatched, or unknown-author reviews;
- require the independent review after the current head commit and retain the current unresolved-thread, required-check, Strix, security, freshness, and
--match-head-commitguards; - make absent/unknown review metadata a
WAIT, never merge evidence; - refuse direct mode when the mutation credential is a configured ruleset bypass actor, or eliminate direct mode in favor of GitHub-native auto-merge after all application-level gates pass;
- add an explicit machine-readable reason when
reviewDecisionor independent approval is missing; - add regression fixtures reproducing an OpenCode-approved,
CLEAN,REVIEW_REQUIREDPR and provemerge_pr()/enable_auto_merge()are never called; - add a fixture with stale Noema approval and a current OpenCode approval and prove it remains blocked;
- add a positive exact-head OpenCode + independent approval +
reviewDecision=APPROVEDfixture; - retain 100% production statement/branch coverage and complete public docstrings;
- update
docs/org-required-workflow-rollout.mdandCHANGELOG.mdwith the incident boundary and rollback.
Acceptance
- no scheduler path can merge or queue merge with only OpenCode approval;
- exact-head Noema/independent approval and GitHub review policy must both be satisfied;
- bypass credentials are removed or constrained by a documented break-glass policy that the routine scheduler cannot use;
- exact-head central tests, CodeQL, Semgrep, Python Security, Security Scan, OSV, Scorecard, Secret Scan, SBOM, OpenCode, Noema, independent approval, and branch protection pass;
- the repaired scheduler is replayed against a synthetic and a real target-repository PR without bypassing protections.
Official GitHub documentation
- About rulesets: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/about-rulesets
- Available rules for rulesets: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/available-rules-for-rulesets
- About protected branches: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches
- Creating rulesets and pull-request-only bypass: https://docs.github.com/en/enterprise-cloud@latest/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/creating-rulesets-for-a-repository
No formal GitHub conformity claim is made.
Activity
seonghobae commentedon Aug 7, 2026
Test-first implementation is now tracked in draft PR #828. Exact current branch head
5735b3427bf6a4210e0eba152f793af0b2fba1cedescends directly from protectedmain1131b1bbafb24e455fc8619cdf316813e8721861.Permanent read-only
Scheduler Independent Approval Quality CIrun31205949241checked out that exact head and reproduced the scheduler defect deterministically: 4 failed, 1 passed. The four intended RED cases prove the current production scheduler still returnsmergewhen (1) GitHub reportsREVIEW_REQUIRED, (2) GitHub reportsAPPROVEDbut no independent exact-head approval exists, (3) the independent approval is bound to a predecessor head, or (4) the only additional approval is from the PR author. The positive exact-head OpenCode + independent approval +reviewDecision=APPROVEDfixture passes.Keep #828 Draft/RED until the bounded production gate is implemented, full scheduler/central suites and 100% production statement/branch/public-docstring evidence pass, current-head security/supply-chain and automated review gates pass, and normal repository policy/branch protection plus a qualifying independent non-author approval permit integration without bypass.
seonghobae commentedon Aug 26, 2026
The Inkspan canary now shows three protected-main admission recurrences under the same governance defect class: #362, #230, and #384. The two newest merges occurred 35 seconds apart on 2026-08-26, and neither has a qualifying formal approval in the complete Reviews API.
#362 — prior recurrence, known scheduler run excluded
9b8c5e689968d2c41d0fdb2ce7160f2e8526702f;057762e003fadad418c38ee748bc3e5b20e711eb;2026-08-25T23:52:48Z,merged_by=seonghobae;APPROVED; OpenCodeCHANGES_REQUESTEDplus COMMENTED-only reviews;Exact-head scheduler run
32859091481used trusted central scheduler source.github@d2c554dbbc04854db6215970fabb70cef1ceb690,DRY_RUN=false,ENABLE_AUTO_MERGE=true,MERGE_MODE=direct_or_auto,UPDATE_BRANCHES=true, and anopencode-appmutation token, but its actual decision at2026-08-25T15:01:22ZwasWAITbecause same-head Strix was still running. It completed at15:01:26Z; the merge happened at23:52:48Z, and no later exact-head scheduler run appears in the exact-head inventory. That run did not execute the observed merge.#230 — new recurrence, draft-era scheduler run excluded
59d82f8b65cfad5230fa9e11afb97867293a43f5;1bdd1c4c9d891fcd62d0da549c9cede934ccd41b;2026-08-26T00:21:01Z,merged_by=seonghobae;COMMENTED, 0APPROVED;The exact-head Actions inventory contains scheduler run
32322068927from 2026-08-20. Its trusted job ran with merge mutation capability but observed #230 asdraft=trueand terminated withPR #230: skip: draft PR/ contract decisionNO_ACTION. No later exact-head scheduler run appears in that inventory. Therefore that known scheduler run did not execute the2026-08-26T00:21:01Zmerge.#384 — new recurrence, same-head scheduler run explicitly WAITed
78d3f447315f85830b26c4bf81bdb5c376f1fcdf;128a239f8b71ca16add9e15e21752d1ad63ff0;2026-08-26T00:21:36Z,merged_by=seonghobae;APPROVED;The exact-head Actions inventory contains exactly eight required/repository runs. Required PR Review Merge Scheduler run
32875279638used immutable central scheduler source.github@95b05b393c75931044b405ae491079d336d89293andPULL_REQUEST_NUMBER=384,DRY_RUN=false,ENABLE_AUTO_MERGE=true,MERGE_MODE=direct_or_auto,UPDATE_BRANCHES=true, withSCHEDULER_MUTATION_TOKEN_SOURCE=opencode-app. Its actual decision at2026-08-25T17:10:52Zwas explicitlyWAIT: current-head Strix was complete, but Required OpenCode Review had not materialized and the job lacked a cross-repository dispatch credential. The job completed hours before the00:21:36Zmerge, and no later exact-head scheduler run exists in the eight-run inventory. Run32875279638therefore did not execute the observed merge.Current falsifiable RCA boundary
These three incidents no longer support attributing the protected merges to the known exact-head scheduler invocations: #362 logged
WAIT, #230 loggedNO_ACTIONbecause Draft, and #384 loggedWAIT, all before their eventual merges. The remaining live hypotheses are materially distinct:merged_by=seonghobaeon all three identifies the GitHub merge actor but does not resolve authentication/token provenance or whether GitHub recorded a ruleset bypass. Audit log, Rule Insights, and merge-endpoint/authentication telemetry are therefore the first unresolved causal boundary. Do not retroactively synthesize approval and do not blindly revert product patches merely to repair governance evidence.Required owner-path action
The previous test-first repair PR #828 is closed unmerged, so its RED/GREEN lineage is not protected-main remediation. Continue this existing owner path rather than creating a duplicate:
WAIT/NO_ACTIONoutcomes;reviewDecision == APPROVED, exact-current-head independent non-author approval, stale/predecessor/comment/status/model evidence rejected, missing review metadata =>WAIT, no direct/auto-merge mutation otherwise;Inkspan-side revalidation after central repair: no remaining Inkspan PR may merge unless its then-current exact head/live base has qualifying formal approval, zero unresolved threads, and every applicable current-head gate. Do not transfer #362/#230/#384 evidence to another head.
seonghobae commentedon Aug 26, 2026
Fresh Inkspan policy evidence narrows the live bypass hypothesis without proving which path executed the merges.
For
ContextualWisdomLab/inkspan, active organization ruleset18156473(CWL Central required workflows) currently targets the default branch and requires 1 approving review, stale-review dismissal on push, review-thread resolution, and the seven central required workflows (close-empty-pr, OpenCode, merge scheduler, Security Scan, Strix, SAST, Noema). The same live ruleset exposesbypass_actors=[{actor_type: OrganizationAdmin, bypass_mode: always}], and the connected maintainer identity reportscurrent_user_can_bypass=always. The ruleset was updated2026-08-25T22:02:57.831Z, before the #230/#384 merges.This is capability evidence, not proof that the bypass was exercised. It is nevertheless consistent with the remaining hypothesis in the preceding #771 evidence: #384 contributor head
78d3f447315f85830b26c4bf81bdb5c376f1fcdfbecame protected merge128a239f8b71ca16add4b9e15e21752d1ad63ff0with 0 formalAPPROVEDreviews even though the live policy requires one, while exact-head scheduler run32875279638had already loggedWAITand did not perform the observed merge.The first unresolved causal boundary therefore remains organization Audit Log + Rule Insights + merge-endpoint/authentication provenance for #362/#230/#384. The owner repair should fail closed across every routine merge entry point and ensure routine automation/reviewer credentials cannot consume the always-admin bypass. Do not remove the review requirement, synthesize approval, or treat the existence of bypass capability as proof of the actor/path. Inkspan release issue #118 should remain blocked on this admission incident until the central repair is protected-main integrated and an Inkspan canary is revalidated under ordinary non-bypass policy.