Skip to content

fix(scheduler): require independent exact-head approval - #828

Open
seonghobae wants to merge 2 commits into
mainfrom
fix/scheduler-independent-current-head-approval
Open

fix(scheduler): require independent exact-head approval#828
seonghobae wants to merge 2 commits into
mainfrom
fix/scheduler-independent-current-head-approval

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Safety gap

The organization merge scheduler could enter direct-merge or auto-merge paths from a same-head OpenCode APPROVED review while GitHub still reported reviewDecision: REVIEW_REQUIRED. That allowed automation to run ahead of the repository's independent-review gate if a scheduler credential ever acquired a ruleset bypass path.

Fail-closed repair

Before either merge entrypoint, the scheduler requires:

  • GitHub aggregate reviewDecision == APPROVED;
  • a non-empty pull-request author identity from authoritative GitHub metadata;
  • exact-current-head OpenCode approval where configured;
  • an exact-current-head formal APPROVED review from a different non-author, non-OpenCode identity; and
  • all pre-existing exact-head Strix, security, required-check, thread, mergeability, freshness, and expected-head gates.

Stale, predecessor-head, dismissed, comment-only, anonymous, author-self, OpenCode-only, status-only, and synthetic-merge evidence is non-authorizing. If aggregate approval is lost, queued auto-merge is disarmed. GitHub remains authoritative for last-push approval and other ruleset semantics; the scheduler does not invent a last-pusher identity.

The mature scheduler engine remains in scripts/ci/_pr_review_merge_scheduler_core.py; scripts/ci/pr_review_merge_scheduler.py is the auditable approval-policy facade.

Scope repair and exact identity

  • protected base: main@6eb06cdd08c79a06f7b390069d4ffa49e2eb7dba;
  • exact current head: 911f95c4a256000d8aabdcc45e178ab1cfbb81f6;
  • mergeable at last authoritative refetch: true.

Two unrelated materializer/architecture commits had entered the branch after the previously reviewed scheduler head 33b84e20c97fc30b367bbdbe92c888c51e5aa0ff. They were removed with ordinary forward commits, not a force-push. GitHub compare now reports zero file differences between 33b84e20... and current head 911f95c4...; the effective product diff is again the bounded independent-approval gate.

Prior-head checks and reviews remain historical only. The current head must earn its own exact-head checks and formal approvals.

Merge and operational acceptance

Auto-merge may be armed, but protected integration is authorized only after the unchanged current head receives all terminal required checks, zero unresolved valid findings, qualifying exact-head OpenCode review, the independent non-author approval required by the repository ruleset, and ordinary expected-head merge authority. No admin merge, self-approval, synthetic approval, review dismissal, or ruleset bypass is requested.

After protected integration, accepted-main evidence must confirm that the scheduler blocks REVIEW_REQUIRED/CHANGES_REQUESTED, disarms stale auto-merge, and proceeds only from current-head aggregate and independent formal approval evidence.

Documentation

  • docs/doctoring/scheduler-independent-current-head-approval.md
  • CHANGELOG.md

This PR closes #771 only after protected merge. It does not solve the organization-wide counted-independent-review availability gap tracked in #772 and #948.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: cea0c673-212c-4444-936c-51e2d8cb718e

📝 Walkthrough

Walkthrough

현재 HEAD에 연결된 독립 승인과 GitHub APPROVED 상태를 병합 조건으로 추가했다. 회귀 테스트, 정확한 HEAD 품질 워크플로, 스케줄러 계약 검증, 운영 문서를 함께 갱신했다.

Changes

승인 거버넌스

Layer / File(s) Summary
독립 승인 회귀 테스트
tests/test_scheduler_independent_approval_gate.py, tests/test_pr_review_merge_scheduler.py
현재 HEAD의 독립 승인과 GitHub 승인 상태를 조합해 merge, wait, disable_auto_merge 결과를 검증한다. 기존 병합 테스트는 공통 승인 헬퍼와 작성자 정보를 사용한다.
스케줄러 계약 검증 정렬
tests/test_required_workflow_queue_contract.py
계약 테스트가 코어 스케줄러 경로와 큐 스윕, 자격 증명, 저장소 필터, 실패 로깅, 런북 계약을 검증한다.
정확한 HEAD 품질 워크플로
.github/workflows/scheduler-independent-approval-quality-ci.yml
워크플로가 정확한 PR HEAD를 체크아웃하고 고정 해시 의존성을 설치한다. 승인 게이트 테스트, Python 컴파일, 작업 트리 상태를 검증한다.
승인 정책 및 운영 기록
docs/doctoring/scheduler-independent-current-head-approval.md, CHANGELOG.md
독립 승인 조건, 거부 사례, 보호 규칙, 롤백 절차와 변경 기록을 문서화한다.

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

Possibly related issues

  • ContextualWisdomLab/clearfolio#321 — 정확한 HEAD 독립 승인과 적격 인간 또는 CODEOWNERS 검토 경로를 함께 다룬다.
  • ContextualWisdomLab/.github#772 — 정확한 HEAD의 비작성자 독립 승인과 GitHub 검토자 거버넌스를 다룬다.
  • ContextualWisdomLab/four-pillars#28 — PR 병합 스케줄러의 승인 및 자동 병합 제어를 다룬다.

Suggested labels: needs-revision, do-not-merge

Suggested reviewers: opencode-agent

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning [771] 테스트와 문서는 추가했지만, 승인 게이트를 구현하는 운영 코드와 우회 자격 증명 제한 변경이 변경 목록에 없습니다. 운영 코드에 두 승인 조건과 fail-closed 동작을 구현하고, 우회 자격 증명 제한 및 필수 롤백 문서를 추가하십시오.
✅ Passed checks (4 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed 변경 사항은 승인 게이트의 테스트, 품질 검증, 문서화, 변경 로그 범위에 포함되며 명백한 무관 변경은 없습니다.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 스케줄러가 현재 HEAD의 독립 승인을 요구하도록 변경한 PR의 핵심 목적을 정확하고 간결하게 설명합니다.
✨ 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/scheduler-independent-current-head-approval

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.

Copy link
Copy Markdown
Contributor Author

@opencode-agent address

Repair only the six stale positive scheduler fixtures on exact current Draft head 8abddc8df9ebddcb14e40e818593e71e1c4ca40a, protected base 1131b1bbafb24e455fc8619cdf316813e8721861. The authoritative tests/test_pr_review_merge_scheduler.py blob is still 3e421e9039654aa669bf147db3be63fd1386d461; abort and re-read if head/base/blob moves.

Production approval policy is already the intended security fix and must not be weakened. Strix Changed Path Quality CI run 31229459086 completed the central suite with 978 passed + 16 subtests and exactly six stale positive-path failures because they still expect merge/auto-merge while modeling reviewDecision: REVIEW_REQUIRED and/or OpenCode-only approval:

  • test_inspect_pr_blocks_and_waits_for_policy_states
  • test_inspect_pr_handles_approved_reviews_and_dispatch
  • test_direct_or_auto_falls_back_to_auto_merge_when_branch_policy_blocks_direct_merge
  • test_direct_or_auto_attempts_direct_merge_when_mergeability_is_blocked
  • test_body_head_sha_approval_prevents_same_run_opencode_rerun
  • test_current_head_approval_cleans_previous_head_change_gate_before_merge

Update only the semantically authorized positive fixtures used by those paths so they model the real post-repair authorization state: reviewDecision: "APPROVED"; authoritative non-empty PR author.login; exact-current-head OpenCode formal approval where configured; and an exact-current-head formal APPROVED review from a different non-author, non-OpenCode identity. Preserve predecessor/stale/self/comment-only/anonymous/REVIEW_REQUIRED negatives as fail-closed.

Do not change the default make_pr() helper to globally inject approval. If repetition warrants it, add a narrow beginner-readable helper such as an explicitly named authorized/mergeable fixture constructor and use it only where the test is supposed to prove an authorized merge path. Preserve explicit caller-provided reviews and derive the review commit from that fixture's current headRefOid rather than hard-coding head when a test overrides the head.

After the test-only repair, rerun the focused independent-approval gate, complete central suite, Strix quick gate, compilation, exact 100% production statement/branch coverage and public-docstring gate, plus all exact-head security/supply-chain checks. Keep Draft; no self-approval, synthetic approval, branch-protection bypass, or temporary/write-capable repair workflow.

Copy link
Copy Markdown
Contributor Author

@opencode-agent Fix only the current exact-head Strix regression on PR #828 at head 8abddc8df9ebddcb14e40e818593e71e1c4ca40a, base 1131b1bbafb24e455fc8619cdf316813e8721861, with tests/test_pr_review_merge_scheduler.py blob 3e421e9039654aa669bf147db3be63fd1386d461. The exact-head Strix job 31229459086 proved 978 passed / 16 subtests passed / 6 failed; all six failures are stale positive merge/auto-merge fixtures, not production defects. Repair those positive fixtures test-first so each merge-authorizing case explicitly models the post-repair authorization state already pinned by tests/test_scheduler_independent_approval_gate.py: reviewDecision="APPROVED", a non-empty PR author.login (e.g. pull-request-author), the existing exact-head OpenCode APPROVED review, and an exact-head formal APPROVED review from a different non-OpenCode/non-author identity (e.g. cwl-noema-review). Do not change the default make_pr() to approved, do not globally inject approval, do not weaken production scheduler logic, and do not alter negative/fail-closed review-policy fixtures.

The six observed failures to repair are:

  1. test_body_head_sha_approval_prevents_same_run_opencode_rerun
  2. test_current_head_approval_cleans_previous_head_change_gate_before_merge
  3. the rest_clean positive case inside test_inspect_pr_blocks_and_waits_for_policy_states
  4. merge-authorizing positive cases inside test_inspect_pr_handles_approved_reviews_and_dispatch (update every positive path that must now satisfy the gate, not just the first assertion; preserve negative cases)
  5. test_direct_or_auto_falls_back_to_auto_merge_when_branch_policy_blocks_direct_merge
  6. test_direct_or_auto_attempts_direct_merge_when_mergeability_is_blocked

Use an explicit small positive-fixture helper only if it makes the intent clearer; it must not affect default/negative fixtures. Before pushing, re-read the live PR head and target blob and abort/re-plan if either moved. Validate the focused independent-approval regression, all affected legacy scheduler tests, full suite, exact 100% production statement/branch coverage and public-docstring gate, Strix quick gate, compilation/syntax, and clean diff. Keep the PR Draft and do not merge or synthesize approval.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review
@opencode-agent review
@cwl-noema-review review

Review-only on exact current head c10607aec1f1f23f2125422310101e03de9bd86d. Do not mutate the branch, approve from the author identity, merge, release, or create repair automation. Verify that the scheduler facade still delegates to the authoritative core without duplicating privileged implementation, that the independent exact-current-head approval gate remains fail-closed (reviewDecision == APPROVED, non-empty PR author, exact-head OpenCode approval where configured, and a distinct exact-head non-author/non-OpenCode formal approval), and that positive scheduler fixtures do not weaken negative stale/self/comment-only/anonymous/review-required cases. Treat all predecessor-head checks and reviews as stale. Report only exact-head actionable findings or an exact-head no-finding verdict.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

expected_head='c10607aec1f1f23f2125422310101e03de9bd86d'
repo='ContextualWisdomLab/.github'
pr='828'

echo '== Live PR metadata =='
gh pr view "$pr" --repo "$repo" --json number,isDraft,headRefOid,baseRefOid,url \
  --jq '{number, isDraft, headRefOid, baseRefOid, url}'

echo '== Checked-out commit =='
git rev-parse HEAD
git status --short

echo '== Exact-head commit verification =='
test "$(git rev-parse HEAD)" = "$expected_head"
test "$(gh pr view "$pr" --repo "$repo" --json headRefOid --jq .headRefOid)" = "$expected_head"
echo 'exact-head verified'

echo '== Changed files at exact head relative to merge base =='
base="$(git merge-base HEAD origin/main)"
git diff --name-status "$base"...HEAD

echo '== Relevant source/test file locations =='
fd -t f -a '(^|/)(pr_review_merge_scheduler|_pr_review_merge_scheduler_core|test_scheduler_independent_approval_gate|test_pr_review_merge_scheduler)\.py$' .

echo '== Python structure maps =='
ast-grep outline scripts/ci/pr_review_merge_scheduler.py --items all || true
ast-grep outline scripts/ci/_pr_review_merge_scheduler_core.py --items all || true
ast-grep outline tests/test_scheduler_independent_approval_gate.py --items all || true
ast-grep outline tests/test_pr_review_merge_scheduler.py --items all || true

echo '== Policy identifiers with context =='
rg -n -C 5 --type py \
  'reviewDecision|headRefOid|author|OpenCode|APPROVED|independent|formal.*review|reviews' \
  scripts/ci/pr_review_merge_scheduler.py \
  scripts/ci/_pr_review_merge_scheduler_core.py \
  tests/test_scheduler_independent_approval_gate.py \
  tests/test_pr_review_merge_scheduler.py

echo '== Exact-head diff for relevant files =='
git diff --unified=80 "$base"...HEAD -- \
  scripts/ci/pr_review_merge_scheduler.py \
  scripts/ci/_pr_review_merge_scheduler_core.py \
  tests/test_scheduler_independent_approval_gate.py \
  tests/test_pr_review_merge_scheduler.py

Length of output: 101369


🏁 Script executed:

#!/bin/bash
set -euo pipefail

expected_head='c10607aec1f1f23f2125422310101e03de9bd86d'
test "$(git rev-parse HEAD)" = "$expected_head"

facade='scripts/ci/pr_review_merge_scheduler.py'
core='scripts/ci/_pr_review_merge_scheduler_core.py'
legacy='tests/test_pr_review_merge_scheduler.py'
regression='tests/test_scheduler_independent_approval_gate.py'

echo '== Facade full map and bounded source =='
nl -ba "$facade" | sed -n '1,360p'

echo '== Core approval-related definitions and entrypoint call sites =='
rg -n -C 12 --type py \
  '^(def (pull_request_author_login|has_independent_current_head_approval|merge_approval_block_reason|inspect_pr|enable_auto_merge|merge_pr|fetch_pr|fetch_open_prs)|PULL_REQUEST_FIELDS_FRAGMENT)|\bmerge_approval_block_reason\(|\bhas_independent_current_head_approval\(|Decision\(.*"(merge|auto_merge)"' \
  "$core"

echo '== Core exact source regions around each relevant definition/call =='
for line in $(rg -n --type py \
  '^(def (pull_request_author_login|has_independent_current_head_approval|merge_approval_block_reason|inspect_pr|enable_auto_merge|merge_pr|fetch_pr|fetch_open_prs)|PULL_REQUEST_FIELDS_FRAGMENT)|\bmerge_approval_block_reason\(' \
  "$core" | cut -d: -f1 | sort -nu); do
  start=$(( line > 25 ? line - 25 : 1 ))
  end=$(( line + 100 ))
  echo "--- $core:$start-$end ---"
  nl -ba "$core" | sed -n "${start},${end}p"
done

echo '== Merge and auto-merge return sites, with enclosing context =='
rg -n -C 20 --type py 'Decision\([^)]*"(merge|auto_merge)"|action="(merge|auto_merge)"' "$core"

echo '== Approval regression test, complete =='
nl -ba "$regression" | sed -n '1,280p'

echo '== Legacy fixture definitions and all modified authorized/negative-policy regions =='
rg -n -C 16 --type py \
  '^(def (make_pr|merge_approved_pr|test_body_head_sha_approval_prevents_same_run_opencode_rerun|test_current_head_approval_cleans_previous_head_change_gate_before_merge|test_inspect_pr_blocks_and_waits_for_policy_states|test_inspect_pr_handles_approved_reviews_and_dispatch|test_direct_or_auto_falls_back_to_auto_merge_when_branch_policy_blocks_direct_merge|test_direct_or_auto_attempts_direct_merge_when_mergeability_is_blocked))|reviewDecision|independent-reviewer|pull-request-author|COMMENTED|anonymous|stale|previous-head' \
  "$legacy"

echo '== Test-only diff, minimal context =='
base="$(git merge-base HEAD origin/main)"
git diff --unified=12 "$base"...HEAD -- "$legacy" "$regression"

Length of output: 2832


🏁 Script executed:

#!/bin/bash
set -euo pipefail

expected_head='c10607aec1f1f23f2125422310101e03de9bd86d'
test "$(git rev-parse HEAD)" = "$expected_head"

numbered() { awk '{printf "%6d\t%s\n", NR, $0}' "$1"; }

facade='scripts/ci/pr_review_merge_scheduler.py'
core='scripts/ci/_pr_review_merge_scheduler_core.py'
legacy='tests/test_pr_review_merge_scheduler.py'
regression='tests/test_scheduler_independent_approval_gate.py'

echo '== Facade, complete (expected small policy facade) =='
numbered "$facade"

echo '== Core approval definitions and calls =='
rg -n -C 10 --type py \
  '^(def (pull_request_author_login|has_independent_current_head_approval|merge_approval_block_reason|inspect_pr|enable_auto_merge|merge_pr|fetch_pr|fetch_open_prs)|PULL_REQUEST_FIELDS_FRAGMENT)|\bmerge_approval_block_reason\(|\bhas_independent_current_head_approval\(' \
  "$core"

echo '== Core exact regions =='
for line in $(rg -n --type py \
  '^(def (pull_request_author_login|has_independent_current_head_approval|merge_approval_block_reason|inspect_pr|enable_auto_merge|merge_pr|fetch_pr|fetch_open_prs)|PULL_REQUEST_FIELDS_FRAGMENT)' \
  "$core" | cut -d: -f1 | sort -nu); do
  start=$(( line > 20 ? line - 20 : 1 ))
  end=$(( line + 120 ))
  echo "--- $core:$start-$end ---"
  sed -n "${start},${end}p" "$core" | awk -v n="$start" '{printf "%6d\t%s\n", n++, $0}'
done

echo '== All core merge/auto-merge decision sites =='
rg -n -C 24 --type py 'Decision\([^)]*"(merge|auto_merge)"|action="(merge|auto_merge)"' "$core"

echo '== Independent-gate regression test =='
numbered "$regression"

echo '== Legacy fixture helpers =='
sed -n '1,115p' "$legacy" | awk '{printf "%6d\t%s\n", NR, $0}'

echo '== Legacy tests named in the request, with sufficient bounded context =='
for name in \
  test_body_head_sha_approval_prevents_same_run_opencode_rerun \
  test_current_head_approval_cleans_previous_head_change_gate_before_merge \
  test_inspect_pr_blocks_and_waits_for_policy_states \
  test_inspect_pr_handles_approved_reviews_and_dispatch \
  test_direct_or_auto_falls_back_to_auto_merge_when_branch_policy_blocks_direct_merge \
  test_direct_or_auto_attempts_direct_merge_when_mergeability_is_blocked; do
  line="$(rg -n "^def ${name}\b" "$legacy" | head -1 | cut -d: -f1)"
  echo "--- $legacy:$line ($name) ---"
  sed -n "${line},$((line + 300))p" "$legacy" | awk -v n="$line" '{printf "%6d\t%s\n", n++, $0}' \
    | sed -n '1,/^ *[0-9][0-9]*[[:space:]]def /{ /^ *[0-9][0-9]*[[:space:]]def /!p; }'
done

echo '== Direct negative-policy test cases in legacy suite =='
rg -n -C 8 --type py \
  'REVIEW_REQUIRED|CHANGES_REQUESTED|COMMENTED|author.*login|author.*\{\}|author.*None|commit.*old|previous-head|anonymous|independent' \
  "$legacy"

echo '== Test-only exact-head diff =='
base="$(git merge-base HEAD origin/main)"
git diff --unified=16 "$base"...HEAD -- "$legacy" "$regression"

Length of output: 178950


🏁 Script executed:

#!/bin/bash
set -euo pipefail

expected_head='c10607aec1f1f23f2125422310101e03de9bd86d'
repo='ContextualWisdomLab/.github'
test "$(git rev-parse HEAD)" = "$expected_head"
test "$(gh pr view 828 --repo "$repo" --json headRefOid --jq .headRefOid)" = "$expected_head"

core='scripts/ci/_pr_review_merge_scheduler_core.py'
facade='scripts/ci/pr_review_merge_scheduler.py'

echo '== Exact live head remains verified =='
gh pr view 828 --repo "$repo" --json headRefOid,isDraft --jq '{headRefOid,isDraft}'

echo '== Complete core decision segment =='
sed -n '2340,2650p' "$core" | awk -v n=2340 '{printf "%6d\t%s\n", n++, $0}'

echo '== Production direct-core imports, file execution, and scheduler entrypoints =='
rg -n -C 4 \
  '_pr_review_merge_scheduler_core|pr_review_merge_scheduler(\.py)?|--self-test|inspect_pr\(' \
  --glob '*.py' --glob '*.yml' --glob '*.yaml' --glob '!tests/**' .

echo '== Workflow references to scheduler files =='
rg -n -C 5 \
  'scripts/ci/(pr_review_merge_scheduler|_pr_review_merge_scheduler_core)\.py' \
  .github

echo '== Core module export or runtime alias changes =='
rg -n -C 4 \
  '__all__|sys\.modules|importlib|exec_module|from scripts\.ci\._pr_review_merge_scheduler_core|import scripts\.ci\._pr_review_merge_scheduler_core' \
  scripts tests .github

echo '== Final changed file list and production diff summary =='
base="$(git merge-base HEAD origin/main)"
git diff --stat "$base"...HEAD
git diff --name-status "$base"...HEAD
git diff --check "$base"...HEAD
git diff --unified=8 "$base"...HEAD -- "$facade" "$core"

Length of output: 108137


@seonghobae, no exact-head actionable findings.

I verified live PR #828 head c10607aec1f1f23f2125422310101e03de9bd86d.

The facade delegates scheduler behavior to the authoritative core. It adds the approval boundary without duplicating privileged scheduler implementation.

The merge gate fails closed for:

  • reviewDecision != APPROVED;
  • missing PR author identity;
  • stale reviews;
  • author self-approval;
  • OpenCode-only approval;
  • anonymous reviews; and
  • comment-only reviews.

The positive fixtures use a narrow authorized fixture helper. The default fixture remains REVIEW_REQUIRED with no injected approval. Negative fixtures remain fail-closed.

No branch mutation, approval, merge, release, or repair automation was performed.

⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor Author

@opencode-agent address

Reconcile this Draft with the exact current protected main before generating any further review evidence. Current PR head is c10607aec1f1f23f2125422310101e03de9bd86d; current protected main is 6eb06cdd08c79a06f7b390069d4ffa49e2eb7dba. The branch is one protected-main commit behind. The only overlapping path from that base movement is CHANGELOG.md: PR blob aa391048c86632aa2010ec249c6980aa8ba26aff, protected-main blob bf30091dd6df4551f211142b4828b5c674362bb8.

Before writing, refetch and require those head/main/blob identities to remain exact. Merge the protected-main tip into the existing branch with a normal non-forced merge. Resolve CHANGELOG.md by preserving both independent [Unreleased] fixes: protected main's bounded Strix timeout-fixture entry and this PR's independent exact-head approval-gate entry. Preserve every other line from both sides. No rebase/force-push, -X ours/-X theirs, temporary/write-capable workflow, global fixture approval injection, reviewer/credential change, or production-policy weakening.

After reconciliation, ensure the effective feature diff remains the scheduler approval-policy facade/core, its permanent quality workflow/tests, doctoring, and changelog only. Rerun Scheduler Independent Approval Quality CI, the complete central suite, Strix Changed Path Quality CI, Python compilation, exact 100% production statement/branch and public-docstring gates, plus security/supply-chain checks. Keep Draft until fresh exact-head automated review, zero valid unresolved findings, qualifying independent non-author approval, and branch protection all pass.

Copy link
Copy Markdown
Contributor Author

@opencode-agent address

Reconcile this scheduler separation-of-duties repair onto current protected main without rewriting history. Exact PR head is c10607aec1f1f23f2125422310101e03de9bd86d; current protected main tip is 6eb06cdd08c79a06f7b390069d4ffa49e2eb7dba. The approval-policy facade blob is 1d6538b306094c09e13928698efbc464f1450943 on the PR head and 75e18c860c30b80055bec18a6c3c456f1d53d195 on current main. Do not write if the head, protected-main tip, or relevant blobs have moved.

Use a trusted checkout and normally merge exact protected main into this existing branch. Preserve all newer main behavior and the narrow authorization invariant already implemented on this branch:

  • direct merge or auto-merge entrypoints require GitHub aggregate reviewDecision == APPROVED;
  • authoritative PR author identity must be non-empty;
  • exact-current-head OpenCode approval remains required where configured;
  • a separate exact-current-head formal APPROVED review must come from a non-author, non-OpenCode identity;
  • all existing exact-head Strix/security/check/thread/mergeability/freshness/expected-head gates remain in force;
  • stale, dismissed, comment-only, anonymous, author-self, OpenCode-only, status-only, predecessor-head, or synthetic evidence remains non-authorizing.

The current branch diff already updates positive scheduler fixtures toward merge_approved_pr/independent-review evidence; do not globally inject approvals into negative fixtures and do not weaken the production facade merely to satisfy legacy tests. Resolve merge conflicts minimally, preserving the mature core plus the auditable approval-policy facade.

Do not force-push, use -X ours/-X theirs, create temporary/self-modifying/write-capable workflows, or change reviewer credentials/branch protection. After reconciliation run the focused independent-approval quality gate, complete central suite and Strix quick gate, exact 100% production statement/branch/public-docstring gates, and all security/supply-chain checks on the resulting exact head. Keep Draft until zero valid findings and current-head automated/independent review are satisfied; do not merge or synthesize approval.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/scheduler-independent-approval-quality-ci.yml:
- Around line 60-65: Update the workflow validation steps after the
scheduler-independent approval gate test to run the complete suite with `python
-m pytest -q` instead of only
`tests/test_scheduler_independent_approval_gate.py`. Replace the `git diff
--exit-code` check with validation that `git status --porcelain=v1
--untracked-files=all` produces no output, while preserving the existing
compileall checks.

In `@CHANGELOG.md`:
- Line 24: Update the changelog entry describing the central merge scheduler
security change to explicitly state that the approving reviewer must also differ
from the pull request’s most recent pusher, in addition to being non-author and
non-OpenCode.

In `@docs/doctoring/scheduler-independent-current-head-approval.md`:
- Around line 13-20: Update the production gate and regression tests to obtain
the authoritative last-pusher identity and require the independent exact-head
approver to be non-empty, different from both the pull-request author and last
pusher, and not the OpenCode reviewer. In
docs/doctoring/scheduler-independent-current-head-approval.md:13-20, add the
last-pusher exclusion to the mandatory fail-closed conditions while preserving
all existing gates. In CHANGELOG.md:24, explicitly record that last pusher
identities are excluded from independent approval.

In `@tests/test_pr_review_merge_scheduler.py`:
- Around line 84-98: Extend the independent-approval gate tests so a
current-head APPROVED review by the PR author, when that same identity is the
last pusher, does not pass as an independent approval and does not merge. Update
the synthetic PR setup around merge_approved_pr in
tests/test_pr_review_merge_scheduler.py:84-98 as needed to model the last-pusher
identity, and add the corresponding negative test in
tests/test_scheduler_independent_approval_gate.py:154-216.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 041ab136-9699-4b81-bedc-3a8f613b8af8

📥 Commits

Reviewing files that changed from the base of the PR and between 6eb06cd and 96d9d6f.

📒 Files selected for processing (8)
  • .github/workflows/scheduler-independent-approval-quality-ci.yml
  • CHANGELOG.md
  • docs/doctoring/scheduler-independent-current-head-approval.md
  • scripts/ci/_pr_review_merge_scheduler_core.py
  • scripts/ci/pr_review_merge_scheduler.py
  • tests/test_pr_review_merge_scheduler.py
  • tests/test_required_workflow_queue_contract.py
  • tests/test_scheduler_independent_approval_gate.py

Comment thread .github/workflows/scheduler-independent-approval-quality-ci.yml Outdated
Comment thread CHANGELOG.md Outdated
Comment thread docs/doctoring/scheduler-independent-current-head-approval.md
Comment thread tests/test_pr_review_merge_scheduler.py
@opencode-agent
opencode-agent Bot disabled auto-merge August 9, 2026 13:12

Copy link
Copy Markdown
Contributor Author

@coderabbitai review
@opencode-agent review
@cwl-noema-review review

Review-only on exact current head ea7e80a851f647eae087969232e2e87916b319cd against protected base 6eb06cdd08c79a06f7b390069d4ffa49e2eb7dba. The current change adds a permanent fail-first contract requiring the scheduler approval workflow to run the complete suite and detect staged/untracked artifacts, then implements that workflow repair. Exact local evidence is 11 focused tests plus 988 repository tests and 16 subtests passing; the exact-head focused GitHub quality and Strix workflows are successful, while remaining queued security/supply-chain workflows are not yet acceptance. The valid workflow thread is resolved; the three last-pusher suggestions were rejected with exact feasibility evidence because GitHub exposes no authoritative PR-envelope pusher identity and the live CLEAN/BLOCKED merge-state boundary remains server-authoritative. Treat every predecessor-head review as stale. Review only; do not mutate the branch, approve from the author identity, merge, or release.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Rate Limit Exceeded

@seonghobae have exceeded the limit for the number of chat messages per hour. Please wait 10 minutes and 22 seconds before sending another message.

@seonghobae
seonghobae enabled auto-merge (squash) August 9, 2026 16:15

@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 cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head ea7e80a851f647eae087969232e2e87916b319cd.

  • Head SHA: ea7e80a851f647eae087969232e2e87916b319cd

  • Workflow run: 31322615000

  • Workflow attempt: 1

Coverage evidence

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Workflow: scheduler-independent-approval-quality-ci.yml"]
  S1 --> I1["GitHub Actions review job"]
  I1 --> R1["Review risk: Workflow: scheduler-independent-approval-quality-ci.yml"]
  R1 --> V1["actionlint plus required checks"]
  Evidence --> S2["Changed file: CHANGELOG.md"]
  S2 --> I2["repository behavior"]
  I2 --> R2["Review risk: Changed file: CHANGELOG.md"]
  R2 --> V2["required checks"]
  Evidence --> S3["Docs: scheduler-independent-current-head-approval.md"]
  S3 --> I3["operator or user guidance"]
  I3 --> R3["Review risk: Docs: scheduler-independent-current-head-approval.md"]
  R3 --> V3["docs review"]
  Evidence --> S4["CI script (2 files)"]
  S4 --> I4["review and security gate shell path"]
  I4 --> R4["Review risk: CI script (2 files)"]
  R4 --> V4["bash -n plus Strix self-test"]
  Evidence --> S5["Test (3 files)"]
  S5 --> I5["regression suite"]
  I5 --> R5["Review risk: Test (3 files)"]
  R5 --> V5["targeted test run"]
Loading

@opencode-agent

opencode-agent Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

OpenCode Review Overview

  • Head SHA: 87db55a032e7f0585fe3346ce4bb481caffd7dc5
  • Workflow run: 32137083990
  • Workflow attempt: 1
  • Gate result: REQUEST_CHANGES (approval step)

Pull request overview

OpenCode reviewed the current-head mergeability evidence and changed-file flow before approval, then found merge conflicts on the affected path.

Findings

1. HIGH Merge Conflict Guidance - Resolve the PR branch against the latest base branch

  • Problem: GitHub reports mergeStateStatus DIRTY for this pull request.
  • Root cause: Branch fix/scheduler-independent-current-head-approval cannot be merged cleanly into main; the changed-file flow below shows which review/runtime path is blocked by the conflict.
  • Fix: Merge or rebase the latest main into fix/scheduler-independent-current-head-approval, resolve conflict markers in the PR branch, rerun the focused checks, and push the same branch.
  • Repair commands:
gh pr checkout 828 --repo ContextualWisdomLab/.github
git fetch origin main
git merge --no-ff origin/main  # or: git rebase origin/main
git status --short
# resolve files, then git add <resolved-files>
# merge path: git commit
# rebase path: git rebase --continue
git push origin HEAD:fix/scheduler-independent-current-head-approval
# rebase path only: git push --force-with-lease origin HEAD:fix/scheduler-independent-current-head-approval
  • Regression test: Keep OpenCode approval gated on mergeability so model-output failures cannot approve a conflicted PR.

Merge Conflict Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Workflow: scheduler-independent-approval-quality-ci.yml"]
  S1 --> I1["GitHub Actions review job"]
  I1 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V1["actionlint plus required checks"]
  Evidence --> S2["Changed file: CHANGELOG.md"]
  S2 --> I2["repository behavior"]
  I2 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V2["required checks"]
  Evidence --> S3["Docs: scheduler-independent-current-head-approval.md"]
  S3 --> I3["operator or user guidance"]
  I3 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V3["docs review"]
  Evidence --> S4["CI script (2 files)"]
  S4 --> I4["review and security gate shell path"]
  I4 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V4["bash -n plus Strix self-test"]
  Evidence --> S5["Test (3 files)"]
  S5 --> I5["regression suite"]
  I5 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V5["targeted test run"]
Loading
  • Result: REQUEST_CHANGES
  • Reason: mergeStateStatus is DIRTY; mergeable is CONFLICTING.
  • Head SHA: 87db55a032e7f0585fe3346ce4bb481caffd7dc5
  • Workflow run: 32137083990
  • Workflow attempt: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Workflow: scheduler-independent-approval-quality-ci.yml"]
  S1 --> I1["GitHub Actions review job"]
  I1 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V1["actionlint plus required checks"]
  Evidence --> S2["Changed file: CHANGELOG.md"]
  S2 --> I2["repository behavior"]
  I2 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V2["required checks"]
  Evidence --> S3["Docs: scheduler-independent-current-head-approval.md"]
  S3 --> I3["operator or user guidance"]
  I3 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V3["docs review"]
  Evidence --> S4["CI script (2 files)"]
  S4 --> I4["review and security gate shell path"]
  I4 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V4["bash -n plus Strix self-test"]
  Evidence --> S5["Test (3 files)"]
  S5 --> I5["regression suite"]
  I5 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V5["targeted test run"]
Loading

Merge Conflict Guidance

  • Current merge state: DIRTY
  • Base branch: main
  • Head branch: fix/scheduler-independent-current-head-approval
  • Fix direction: merge or rebase origin/main into fix/scheduler-independent-current-head-approval, resolve conflict markers in the changed files, rerun the focused checks, then push the same branch.
  • Repair commands:
gh pr checkout 828 --repo ContextualWisdomLab/.github
git fetch origin main
git merge --no-ff origin/main  # or: git rebase origin/main
git status --short
# resolve files, then git add <resolved-files>
# merge path: git commit
# rebase path: git rebase --continue
git push origin HEAD:fix/scheduler-independent-current-head-approval
# rebase path only: git push --force-with-lease origin HEAD:fix/scheduler-independent-current-head-approval

@opencode-agent
opencode-agent Bot disabled auto-merge August 9, 2026 16:23

@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 cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head ea7e80a851f647eae087969232e2e87916b319cd.

  • Head SHA: ea7e80a851f647eae087969232e2e87916b319cd

  • Workflow run: 31323315093

  • Workflow attempt: 1

Coverage evidence

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Workflow: scheduler-independent-approval-quality-ci.yml"]
  S1 --> I1["GitHub Actions review job"]
  I1 --> R1["Review risk: Workflow: scheduler-independent-approval-quality-ci.yml"]
  R1 --> V1["actionlint plus required checks"]
  Evidence --> S2["Changed file: CHANGELOG.md"]
  S2 --> I2["repository behavior"]
  I2 --> R2["Review risk: Changed file: CHANGELOG.md"]
  R2 --> V2["required checks"]
  Evidence --> S3["Docs: scheduler-independent-current-head-approval.md"]
  S3 --> I3["operator or user guidance"]
  I3 --> R3["Review risk: Docs: scheduler-independent-current-head-approval.md"]
  R3 --> V3["docs review"]
  Evidence --> S4["CI script (2 files)"]
  S4 --> I4["review and security gate shell path"]
  I4 --> R4["Review risk: CI script (2 files)"]
  R4 --> V4["bash -n plus Strix self-test"]
  Evidence --> S5["Test (3 files)"]
  S5 --> I5["regression suite"]
  I5 --> R5["Review risk: Test (3 files)"]
  R5 --> V5["targeted test run"]
Loading

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/test_scheduler_independent_approval_gate.py`:
- Around line 126-129: Strengthen the workflow assertions in the relevant test
so the run block contains the exact path-free command `python -m pytest -q`,
rather than accepting it as a substring of a path-specific command. Also verify
that the `git status --porcelain=v1 --untracked-files=all` check exits non-zero
when staged or untracked changes exist, and run the complete test suite before
merging.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 17236b07-0151-4cf4-acaa-a587f04c73b9

📥 Commits

Reviewing files that changed from the base of the PR and between 96d9d6f and 49937ee.

📒 Files selected for processing (2)
  • .github/workflows/scheduler-independent-approval-quality-ci.yml
  • tests/test_scheduler_independent_approval_gate.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/scheduler-independent-approval-quality-ci.yml

Comment thread tests/test_scheduler_independent_approval_gate.py Outdated

Copy link
Copy Markdown
Contributor Author

Exact-current-head independent review request for 33b84e20c97fc30b367bbdbe92c888c51e5aa0ff over protected main@6eb06cdd08c79a06f7b390069d4ffa49e2eb7dba.

The current head has exact-head OpenCode APPROVED, all ten hosted quality/security workflows terminal-success, and all inline threads resolved. Review the fail-closed aggregate and independent approval policy, stale auto-merge disarm, authoritative GitHub blocked-state boundary for last-push approval, facade/core separation, and exact-head clean-worktree quality workflow. Predecessor REQUEST_CHANGES and predecessor CodeRabbit findings are historical.

Keep the branch unchanged. Do not synthesize author approval, substitute a non-authoritative last_pusher identity, dismiss reviews, merge, release, bypass the ruleset, or weaken required checks.

@coderabbitai review
@cwl-noema-review review
@strix review

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Rate Limit Exceeded

@seonghobae have exceeded the limit for the number of chat messages per hour. Please wait 26 minutes and 0 seconds before sending another message.

@seonghobae
seonghobae enabled auto-merge (squash) August 12, 2026 10:53

Copy link
Copy Markdown
Contributor Author

Independent exact-current-head review requested for 33b84e20c97fc30b367bbdbe92c888c51e5aa0ff against protected main@6eb06cdd08c79a06f7b390069d4ffa49e2eb7dba.

Fresh evidence: the dedicated Scheduler Independent Approval Quality CI and all nine generic exact-head workflows are terminal-success, every inline finding is resolved or withdrawn, and OpenCode has submitted a formal exact-head APPROVED review with three falsified adversarial probes. The application gate requires GitHub aggregate APPROVED plus a non-empty current-head formal approval by a different non-author, non-OpenCode identity; last-push approval remains authoritative in GitHub and leaves the PR BLOCKED rather than being invented from commit metadata.

A qualifying independent non-author reviewer must inspect and formally approve this unchanged head. Do not update the branch, synthesize a last-pusher identity, weaken aggregate review or merge-state gates, synthesize author approval, or bypass protection.

Copy link
Copy Markdown
Contributor Author

Exact-current-head read-only review request for ba011da757e77781e628ce32d57d216cbb748974 over protected main@6eb06cdd08c79a06f7b390069d4ffa49e2eb7dba.

All eleven directly observed exact-head workflows are terminal-success: Scheduler Independent Approval Quality CI, Trusted uv Materializer Quality CI, Strix Changed Path Quality CI, CodeQL PR, Python Security, Security Scan, SAST Semgrep, Secret Scan, OSV-Scanner PR, Scorecard PR, and SBOM Generation. Every published inline thread is resolved; the last-pusher identity suggestions were correctly withdrawn because GitHub remains the authoritative enforcement source and does not expose a trustworthy application-level identity field. Prior OpenCode approval belongs to an older head and was dismissed.

Review the unchanged current head only. Preserve aggregate reviewDecision == APPROVED, exact-head non-author/non-OpenCode formal approval, stale-auto-merge disarming, live merge-state and branch-protection authority, and the full exact-head quality suite. Do not mutate the branch, invent last-pusher evidence, synthesize approval, or bypass protection.

@coderabbitai review
@opencode-agent review
@cwl-noema-review review
@strix review

@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown

Rate Limit Exceeded

@seonghobae have exceeded the limit for the number of chat messages per hour. Please wait 1 minutes and 16 seconds before sending another message.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review
@opencode-agent review
@cwl-noema-review review
@strix review

Review only exact current head ba011da757e77781e628ce32d57d216cbb748974 against live protected main. All 11 directly observed current-head hosted workflows are terminal-success and every review thread is resolved; earlier approvals are predecessor-head evidence only. Preserve the documented fail-closed separation: GitHub remains authoritative for last-push approval because the PR evidence surface does not expose an authoritative last-pusher identity. Review read-only; do not mutate source, synthesize author approval, weaken protection, or merge.

@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo='ContextualWisdomLab/.github'
pr='828'
expected_head='ba011da757e77781e628ce32d57d216cbb748974'

echo '== Live pull request metadata =='
gh pr view "$pr" --repo "$repo" \
  --json number,url,isDraft,headRefOid,baseRefName,baseRefOid,mergeStateStatus,reviewDecision \
  --jq '{number,url,isDraft,headRefOid,baseRefName,baseRefOid,mergeStateStatus,reviewDecision}'

echo '== Local exact-head verification =='
printf 'local HEAD: '
git rev-parse HEAD
test "$(git rev-parse HEAD)" = "$expected_head"
test "$(gh pr view "$pr" --repo "$repo" --json headRefOid --jq '.headRefOid')" = "$expected_head"
git status --short
echo 'exact head verified'

echo '== Protected main reference =='
git ls-remote origin refs/heads/main

echo '== Changed paths against the pull-request base =='
base_oid="$(gh pr view "$pr" --repo "$repo" --json baseRefOid --jq '.baseRefOid')"
git diff --name-status "$base_oid...$expected_head"
git diff --check "$base_oid...$expected_head"

echo '== Candidate files =='
fd -t f -a \
  '(^|/)(_pr_review_merge_scheduler_core|pr_review_merge_scheduler|test_scheduler_independent_approval_gate|test_pr_review_merge_scheduler|test_required_workflow_queue_contract)\.py$|scheduler-independent-approval-quality-ci\.ya?ml$|scheduler-independent-current-head-approval\.md$' \
  . | sort

echo '== Structure maps =='
for path in \
  scripts/ci/pr_review_merge_scheduler.py \
  scripts/ci/_pr_review_merge_scheduler_core.py \
  tests/test_scheduler_independent_approval_gate.py \
  tests/test_pr_review_merge_scheduler.py \
  .github/workflows/scheduler-independent-approval-quality-ci.yml
do
  if test -f "$path"; then
    echo "--- $path ---"
    ast-grep outline "$path" --items all || true
  fi
done

echo '== Approval and merge-state policy definitions/call sites =='
rg -n -C 8 --type py \
  '^(def (pull_request_author_login|has_independent_current_head_approval|merge_approval_block_reason|inspect_pr|enable_auto_merge|merge_pr|fetch_pr|fetch_open_prs))|reviewDecision|headRefOid|mergeStateStatus|has_independent_current_head_approval\(|merge_approval_block_reason\(|Decision\([^)]*"(merge|auto_merge)"' \
  scripts/ci/pr_review_merge_scheduler.py \
  scripts/ci/_pr_review_merge_scheduler_core.py \
  tests/test_scheduler_independent_approval_gate.py \
  tests/test_pr_review_merge_scheduler.py

echo '== Quality workflow =='
if test -f .github/workflows/scheduler-independent-approval-quality-ci.yml; then
  nl -ba .github/workflows/scheduler-independent-approval-quality-ci.yml
fi

echo '== Focused effective diff =='
git diff --unified=35 "$base_oid...$expected_head" -- \
  scripts/ci/pr_review_merge_scheduler.py \
  scripts/ci/_pr_review_merge_scheduler_core.py \
  tests/test_scheduler_independent_approval_gate.py \
  tests/test_pr_review_merge_scheduler.py \
  tests/test_required_workflow_queue_contract.py \
  .github/workflows/scheduler-independent-approval-quality-ci.yml \
  docs/doctoring/scheduler-independent-current-head-approval.md \
  CHANGELOG.md

Length of output: 213273


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo='ContextualWisdomLab/.github'
pr='828'
expected_head='ba011da757e77781e628ce32d57d216cbb748974'

test "$(git rev-parse HEAD)" = "$expected_head"
test "$(gh pr view "$pr" --repo "$repo" --json headRefOid --jq '.headRefOid')" = "$expected_head"
base_oid="$(gh pr view "$pr" --repo "$repo" --json baseRefOid --jq '.baseRefOid')"

print_range() {
  path="$1"
  start="$2"
  end="$3"
  echo "--- ${path}:${start}-${end} ---"
  sed -n "${start},${end}p" "$path" | awk -v n="$start" '{printf "%6d\t%s\n", n++, $0}'
}

echo '== Complete facade =='
print_range scripts/ci/pr_review_merge_scheduler.py 1 240

echo '== Core inspection and auto-merge disarm path =='
print_range scripts/ci/_pr_review_merge_scheduler_core.py 1120 1210
print_range scripts/ci/_pr_review_merge_scheduler_core.py 1520 1550
print_range scripts/ci/_pr_review_merge_scheduler_core.py 2250 2745

echo '== Independent-approval regression tests =='
print_range tests/test_scheduler_independent_approval_gate.py 1 280

echo '== Quality workflow =='
print_range .github/workflows/scheduler-independent-approval-quality-ci.yml 1 220

echo '== Workflow-contract regression tests =='
print_range tests/test_required_workflow_queue_contract.py 1 260

echo '== Effective diff =='
git diff --unified=24 "$base_oid...$expected_head" -- \
  .github/workflows/scheduler-independent-approval-quality-ci.yml \
  scripts/ci/pr_review_merge_scheduler.py \
  scripts/ci/_pr_review_merge_scheduler_core.py \
  tests/test_scheduler_independent_approval_gate.py \
  tests/test_required_workflow_queue_contract.py \
  tests/test_pr_review_merge_scheduler.py \
  scripts/ci/materialize_base_python_requirements.py \
  tests/test_materialize_base_python_requirements.py \
  AGENTS.md ARCHITECTURE.md CLAUDE.md \
  docs/doctoring/scheduler-independent-current-head-approval.md \
  CHANGELOG.md

echo '== Exact-head stability check =='
test "$(git rev-parse HEAD)" = "$expected_head"
test "$(gh pr view "$pr" --repo "$repo" --json headRefOid --jq '.headRefOid')" = "$expected_head"
echo 'exact head remains verified'

Length of output: 104951


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo='ContextualWisdomLab/.github'
pr='828'
expected_head='ba011da757e77781e628ce32d57d216cbb748974'
test "$(git rev-parse HEAD)" = "$expected_head"
test "$(gh pr view "$pr" --repo "$repo" --json headRefOid --jq '.headRefOid')" = "$expected_head"

show() {
  path="$1"
  start="$2"
  end="$3"
  echo "--- ${path}:${start}-${end} ---"
  sed -n "${start},${end}p" "$path" | awk -v n="$start" '{printf "%6d\t%s\n", n++, $0}'
}

echo '== Approval-policy facade decision path =='
show scripts/ci/pr_review_merge_scheduler.py 65 215

echo '== Core direct and auto-merge decision path =='
show scripts/ci/_pr_review_merge_scheduler_core.py 2250 2470
show scripts/ci/_pr_review_merge_scheduler_core.py 2470 2660

echo '== Approval-gate tests, especially auto-merge disarming =='
show tests/test_scheduler_independent_approval_gate.py 120 250

echo '== Quality workflow =='
show .github/workflows/scheduler-independent-approval-quality-ci.yml 1 180

echo '== Merge-capable call sites outside the core =='
rg -n -C 4 --glob '*.py' \
  '\b(enable_auto_merge|merge_pr|run_head_guarded_merge)\s*\(' \
  scripts tests

echo '== Facade-to-core import and replacement points =='
rg -n -C 4 --type py \
  '_original_inspect_pr|_core\.inspect_pr|sys\.modules|module_from_spec|spec_from_file_location' \
  scripts/ci/pr_review_merge_scheduler.py

echo '== Final exact-head verification =='
test "$(git rev-parse HEAD)" = "$expected_head"
test "$(gh pr view "$pr" --repo "$repo" --json headRefOid --jq '.headRefOid')" = "$expected_head"
echo 'exact head remains verified'

Length of output: 53215


@seonghobae, I verified exact head ba011da757e77781e628ce32d57d216cbb748974 against live main@6eb06cdd08c79a06f7b390069d4ffa49e2eb7dba.

I found one actionable issue.

  • scripts/ci/pr_review_merge_scheduler.py, Line 179 only disables existing auto-merge when the effective merge state is CLEAN. If GitHub reports BLOCKED after aggregate approval or independent approval becomes invalid, the facade returns the guarded wait decision and leaves native auto-merge enabled. GitHub blocks the PR at that time, but it can later merge without a new scheduler evaluation if GitHub clears the unrelated blocker. Disarm existing auto-merge for every unsatisfied approval-gate state, not only CLEAN. Add a regression case for mergeStateStatus: BLOCKED, autoMergeRequest present, and missing aggregate or independent approval.

I did not mutate the branch, create approval, merge, or release.

⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor Author

@opencode-agent @cwl-noema-review @coderabbitai review

Review exact head 911f95c4a256000d8aabdcc45e178ab1cfbb81f6. GitHub compare proves its tree is identical to the previously bounded scheduler head 33b84e20c97fc30b367bbdbe92c888c51e5aa0ff, with unrelated materializer/architecture drift removed by forward commits. Re-verify aggregate reviewDecision == APPROVED, exact-head OpenCode plus independent non-author formal approval, stale/anonymous/self/status-only rejection, and auto-merge disarm on lost aggregate approval. Submit a formal exact-head verdict; do not reuse predecessor evidence.

@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown

Rate Limit Exceeded

@seonghobae have exceeded the limit for the number of chat messages per hour. Please wait 22 minutes and 22 seconds before sending another message.

@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 mergeability evidence and changed-file flow before approval, then found merge conflicts on the affected path.

Findings

1. HIGH Merge Conflict Guidance - Resolve the PR branch against the latest base branch

  • Problem: GitHub reports mergeStateStatus DIRTY for this pull request.
  • Root cause: Branch fix/scheduler-independent-current-head-approval cannot be merged cleanly into main; the changed-file flow below shows which review/runtime path is blocked by the conflict.
  • Fix: Merge or rebase the latest main into fix/scheduler-independent-current-head-approval, resolve conflict markers in the PR branch, rerun the focused checks, and push the same branch.
  • Repair commands:
gh pr checkout 828 --repo ContextualWisdomLab/.github
git fetch origin main
git merge --no-ff origin/main  # or: git rebase origin/main
git status --short
# resolve files, then git add <resolved-files>
# merge path: git commit
# rebase path: git rebase --continue
git push origin HEAD:fix/scheduler-independent-current-head-approval
# rebase path only: git push --force-with-lease origin HEAD:fix/scheduler-independent-current-head-approval
  • Regression test: Keep OpenCode approval gated on mergeability so model-output failures cannot approve a conflicted PR.

Merge Conflict Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Workflow: scheduler-independent-approval-quality-ci.yml"]
  S1 --> I1["GitHub Actions review job"]
  I1 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V1["actionlint plus required checks"]
  Evidence --> S2["Changed file: CHANGELOG.md"]
  S2 --> I2["repository behavior"]
  I2 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V2["required checks"]
  Evidence --> S3["Docs: scheduler-independent-current-head-approval.md"]
  S3 --> I3["operator or user guidance"]
  I3 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V3["docs review"]
  Evidence --> S4["CI script (2 files)"]
  S4 --> I4["review and security gate shell path"]
  I4 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V4["bash -n plus Strix self-test"]
  Evidence --> S5["Test (3 files)"]
  S5 --> I5["regression suite"]
  I5 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V5["targeted test run"]
Loading
  • Result: REQUEST_CHANGES
  • Reason: mergeStateStatus is DIRTY; mergeable is CONFLICTING.
  • Head SHA: 911f95c4a256000d8aabdcc45e178ab1cfbb81f6
  • Workflow run: 31940466721
  • Workflow attempt: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Workflow: scheduler-independent-approval-quality-ci.yml"]
  S1 --> I1["GitHub Actions review job"]
  I1 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V1["actionlint plus required checks"]
  Evidence --> S2["Changed file: CHANGELOG.md"]
  S2 --> I2["repository behavior"]
  I2 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V2["required checks"]
  Evidence --> S3["Docs: scheduler-independent-current-head-approval.md"]
  S3 --> I3["operator or user guidance"]
  I3 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V3["docs review"]
  Evidence --> S4["CI script (2 files)"]
  S4 --> I4["review and security gate shell path"]
  I4 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V4["bash -n plus Strix self-test"]
  Evidence --> S5["Test (3 files)"]
  S5 --> I5["regression suite"]
  I5 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V5["targeted test run"]
Loading

seonghobae added a commit that referenced this pull request Aug 16, 2026
Unique-source replay of #828 onto origin/main.
Keep the current main scheduler as the mature core and add the approval
facade. Merge and auto-merge stay fail-closed unless GitHub reviewDecision
is APPROVED and an independent non-author, non-OpenCode reviewer formally
approved the exact live head.
@seonghobae
seonghobae force-pushed the fix/scheduler-independent-current-head-approval branch from 911f95c to 87db55a Compare August 16, 2026 14:15
@cursor

cursor Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@seonghobae
seonghobae enabled auto-merge (squash) August 16, 2026 14:15
@opencode-agent
opencode-agent Bot disabled auto-merge August 18, 2026 01:26

@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 mergeability evidence and changed-file flow before approval, then found merge conflicts on the affected path.

Findings

1. HIGH Merge Conflict Guidance - Resolve the PR branch against the latest base branch

  • Problem: GitHub reports mergeStateStatus DIRTY for this pull request.
  • Root cause: Branch fix/scheduler-independent-current-head-approval cannot be merged cleanly into main; the changed-file flow below shows which review/runtime path is blocked by the conflict.
  • Fix: Merge or rebase the latest main into fix/scheduler-independent-current-head-approval, resolve conflict markers in the PR branch, rerun the focused checks, and push the same branch.
  • Repair commands:
gh pr checkout 828 --repo ContextualWisdomLab/.github
git fetch origin main
git merge --no-ff origin/main  # or: git rebase origin/main
git status --short
# resolve files, then git add <resolved-files>
# merge path: git commit
# rebase path: git rebase --continue
git push origin HEAD:fix/scheduler-independent-current-head-approval
# rebase path only: git push --force-with-lease origin HEAD:fix/scheduler-independent-current-head-approval
  • Regression test: Keep OpenCode approval gated on mergeability so model-output failures cannot approve a conflicted PR.

Merge Conflict Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Workflow: scheduler-independent-approval-quality-ci.yml"]
  S1 --> I1["GitHub Actions review job"]
  I1 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V1["actionlint plus required checks"]
  Evidence --> S2["Changed file: CHANGELOG.md"]
  S2 --> I2["repository behavior"]
  I2 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V2["required checks"]
  Evidence --> S3["Docs: scheduler-independent-current-head-approval.md"]
  S3 --> I3["operator or user guidance"]
  I3 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V3["docs review"]
  Evidence --> S4["CI script (2 files)"]
  S4 --> I4["review and security gate shell path"]
  I4 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V4["bash -n plus Strix self-test"]
  Evidence --> S5["Test (3 files)"]
  S5 --> I5["regression suite"]
  I5 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V5["targeted test run"]
Loading
  • Result: REQUEST_CHANGES
  • Reason: mergeStateStatus is DIRTY; mergeable is CONFLICTING.
  • Head SHA: 87db55a032e7f0585fe3346ce4bb481caffd7dc5
  • Workflow run: 32128473270
  • Workflow attempt: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Workflow: scheduler-independent-approval-quality-ci.yml"]
  S1 --> I1["GitHub Actions review job"]
  I1 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V1["actionlint plus required checks"]
  Evidence --> S2["Changed file: CHANGELOG.md"]
  S2 --> I2["repository behavior"]
  I2 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V2["required checks"]
  Evidence --> S3["Docs: scheduler-independent-current-head-approval.md"]
  S3 --> I3["operator or user guidance"]
  I3 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V3["docs review"]
  Evidence --> S4["CI script (2 files)"]
  S4 --> I4["review and security gate shell path"]
  I4 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V4["bash -n plus Strix self-test"]
  Evidence --> S5["Test (3 files)"]
  S5 --> I5["regression suite"]
  I5 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V5["targeted test run"]
Loading

@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 mergeability evidence and changed-file flow before approval, then found merge conflicts on the affected path.

Findings

1. HIGH Merge Conflict Guidance - Resolve the PR branch against the latest base branch

  • Problem: GitHub reports mergeStateStatus DIRTY for this pull request.
  • Root cause: Branch fix/scheduler-independent-current-head-approval cannot be merged cleanly into main; the changed-file flow below shows which review/runtime path is blocked by the conflict.
  • Fix: Merge or rebase the latest main into fix/scheduler-independent-current-head-approval, resolve conflict markers in the PR branch, rerun the focused checks, and push the same branch.
  • Repair commands:
gh pr checkout 828 --repo ContextualWisdomLab/.github
git fetch origin main
git merge --no-ff origin/main  # or: git rebase origin/main
git status --short
# resolve files, then git add <resolved-files>
# merge path: git commit
# rebase path: git rebase --continue
git push origin HEAD:fix/scheduler-independent-current-head-approval
# rebase path only: git push --force-with-lease origin HEAD:fix/scheduler-independent-current-head-approval
  • Regression test: Keep OpenCode approval gated on mergeability so model-output failures cannot approve a conflicted PR.

Merge Conflict Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Workflow: scheduler-independent-approval-quality-ci.yml"]
  S1 --> I1["GitHub Actions review job"]
  I1 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V1["actionlint plus required checks"]
  Evidence --> S2["Changed file: CHANGELOG.md"]
  S2 --> I2["repository behavior"]
  I2 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V2["required checks"]
  Evidence --> S3["Docs: scheduler-independent-current-head-approval.md"]
  S3 --> I3["operator or user guidance"]
  I3 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V3["docs review"]
  Evidence --> S4["CI script (2 files)"]
  S4 --> I4["review and security gate shell path"]
  I4 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V4["bash -n plus Strix self-test"]
  Evidence --> S5["Test (3 files)"]
  S5 --> I5["regression suite"]
  I5 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V5["targeted test run"]
Loading
  • Result: REQUEST_CHANGES
  • Reason: mergeStateStatus is DIRTY; mergeable is CONFLICTING.
  • Head SHA: 87db55a032e7f0585fe3346ce4bb481caffd7dc5
  • Workflow run: 32137083990
  • Workflow attempt: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Workflow: scheduler-independent-approval-quality-ci.yml"]
  S1 --> I1["GitHub Actions review job"]
  I1 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V1["actionlint plus required checks"]
  Evidence --> S2["Changed file: CHANGELOG.md"]
  S2 --> I2["repository behavior"]
  I2 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V2["required checks"]
  Evidence --> S3["Docs: scheduler-independent-current-head-approval.md"]
  S3 --> I3["operator or user guidance"]
  I3 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V3["docs review"]
  Evidence --> S4["CI script (2 files)"]
  S4 --> I4["review and security gate shell path"]
  I4 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V4["bash -n plus Strix self-test"]
  Evidence --> S5["Test (3 files)"]
  S5 --> I5["regression suite"]
  I5 --> Conflict["Merge conflict blocks this path"]
  Conflict --> V5["targeted test run"]
Loading

Unique-source replay of #828 onto origin/main.
Keep the current main scheduler as the mature core and add the approval
facade. Merge and auto-merge stay fail-closed unless GitHub reviewDecision
is APPROVED and an independent non-author, non-OpenCode reviewer formally
approved the exact live head.
@seonghobae
seonghobae force-pushed the fix/scheduler-independent-current-head-approval branch from 87db55a to ac07b5d Compare August 20, 2026 02:53
@seonghobae

Copy link
Copy Markdown
Contributor Author

Rebased onto current origin/main c47bee5 and pushed exact verified HEAD ac07b5d. Focused proof: 212 scheduler/approval/queue tests passed, compileall, and git diff --check. Merge authorization now requires GitHub APPROVED plus an independent non-author, non-OpenCode approval for the exact live head. Current-main branch-update behavior was retained in the extracted core. Please review this exact head. @opencode-agent

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.

Block scheduler merges without exact-head independent approval

1 participant