fix(governance): automate ruleset owner-plane reconciliation - #1644
seonghobae wants to merge 252 commits into
Conversation
…ked-pr-central-required-workflows
# Conflicts: # scripts/ci/test_strix_quick_gate.sh
Merge protected main non-destructively while retaining only the create-transition audit and its executable regressions. Focused ruleset audit: 20 passed. Full suite: 1,402 passed, 1 skipped, 16 subtests.
Preserve only the two governance owner files over protected main 0c6b9a6. Focused ruleset audit: 20 passed. Full suite: 1,402 passed, 1 skipped, 16 subtests.
seonghobae
left a comment
There was a problem hiding this comment.
Exact-head execution receipt: ordinary parents 665adfbb220317daf8efae0124d7c2005fc5576b + protected main@7fd571dbcdbae6acf29d8f4ee704d7ba6297e4db, exact tree 8191b45cb3dbcc6a084107fc61e1c84afdf04f95. The protected #2028 CodeQL repair is preserved and the governance delta remains 21 paths. Local GREEN: governance focused 208 passed; owner reconciler 186 passed; full 3149 passed, 1 skipped, 21 subtests; diff check PASS. Hosted successor gates are nonterminal, so this COMMENT is evidence only and is not approval or merge authorization.
|
2026-09-12 current-main reconciliation receipt
|
|
REVIEW ADMISSION — unchanged exact head |
|
SOURCE WRITER RELEASE — ordinary non-force descendant |
Exact-head CodeQL RCARun 34685614235 is terminal FAILURE on unchanged head All other current-head required workflows are SUCCESS. This remains a central authenticated terminal-settlement defect under active owner |
There was a problem hiding this comment.
Pull request overview
OpenCode could not approve from deterministic current-head evidence because GitHub Checks have failed.
Findings
1. HIGH Current-head GitHub Checks - Fix failed required checks before approval
- Problem: Failed same-head checks remain for
4d775cd1918177886b6303d4f807c5c098acb366. - Root cause: The model-unavailable evidence fallback is allowed only when peer GitHub Checks are complete and clean.
- Fix: Read and fix the failed check logs below, then rerun the current-head checks.
- Regression test: Keep the model-unavailable fallback gated on an empty failed-check rollup.
Failed checks:
- CodeQL PR/CodeQL compatibility analysis (actions): FAILURE (https://github.com/ContextualWisdomLab/.github/actions/runs/34685614235/job/103534058894)
- CodeQL compatibility analysis (actions) check run: failure (https://github.com/ContextualWisdomLab/.github/actions/runs/34685614235/job/103534058894)
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Workflow: audit-central-ruleset.yml"]
S1 --> I1["GitHub Actions review job"]
I1 --> R1["Review risk: Workflow: audit-central-ruleset.yml"]
R1 --> V1["actionlint plus required checks"]
Evidence --> S2["Workflow: ruleset-governance-reconcile.yml"]
S2 --> I2["GitHub Actions review job"]
I2 --> R2["Review risk: Workflow: ruleset-governance-reconcile.yml"]
R2 --> V2["actionlint plus required checks"]
Evidence --> S3["Repository file: CHANGELOG.md"]
S3 --> I3["repository behavior"]
I3 --> R3["Review risk: Repository file: CHANGELOG.md"]
R3 --> V3["required checks"]
Evidence --> S4["Repository file: ruleset-governance.json"]
S4 --> I4["repository behavior"]
I4 --> R4["Review risk: Repository file: ruleset-governance.json"]
R4 --> V4["required checks"]
Evidence --> S5["Docs: ruleset-owner-plane-reconciliation.md (2 files)"]
S5 --> I5["operator or user guidance"]
I5 --> R5["Review risk: Docs: ruleset-owner-plane-reconciliation.md (2 files)"]
R5 --> V5["docs review"]
Evidence --> S6["CI script: audit_central_required_workflows.py"]
S6 --> I6["review and security gate shell path"]
I6 --> R6["Review risk: CI script: audit_central_required_workflows.py"]
R6 --> V6["bash -n plus Strix self-test"]
Evidence --> S7["CI script: reconcile_ruleset_governance.py"]
S7 --> I7["review and security gate shell path"]
I7 --> R7["Review risk: CI script: reconcile_ruleset_governance.py"]
R7 --> V7["bash -n plus Strix self-test"]
Evidence --> S8["Test: test_central_required_workflow_exact_inventory.py (13 files)"]
S8 --> I8["regression suite"]
I8 --> R8["Review risk: Test: test_central_required_workflow_exact_inventory.py (13 files)"]
R8 --> V8["targeted test run"]
OpenCode Review Overview
|
Protected-main restack receipt — 2026-09-12Exact head The five new protected-main commits touched six paths disjoint from this PR's 21 governance paths. Git Data construction reproduced the locally merged tree byte-for-byte, then the ref advanced with Exact-tree verification: focused governance plus new protected-main contracts 114 passed; complete All predecessor hosted results are invalidated. Keep Draft until new exact-head checks are terminal and a qualifying independent approval exists; source integration does not claim live ruleset convergence. |
There was a problem hiding this comment.
Noema LLM review
The PR introduces a ruleset governance reconciler and extends the central audit to also validate the owner repository ruleset. The core reconciler logic is well-reasoned with strong collision recovery, but the audit workflow's error handling can mask a central ruleset drift. When the central ruleset audit fails, audit_status=1 is set but the workflow continues; if a subsequent repository or stacked ruleset fetch fails, the job exits immediately with a non-audit error before the final audit_status check, so a scheduled owner-plane audit can fail without surfacing the compliance drift. The final error message is also misleading when only the central audit failed.
Reviewed changed lines
.github/workflows/audit-central-ruleset.yml:97 (RIGHT): Central ruleset audit result is captured into audit_status rather than failing immediately, which is the root cause of the masking issue..github/workflows/audit-central-ruleset.yml:104 (RIGHT): Repository ruleset fetch failure exits the job without checking audit_status, bypassing the final failure check..github/workflows/audit-central-ruleset.yml:111 (RIGHT): Stacked ruleset fetch failure has the same early-exit behavior, also bypassing the final audit_status check..github/workflows/audit-central-ruleset.yml:124 (RIGHT): Final error message is unconditional and references 'fetched rulesets' even when only the central audit failed.
Adversarial validation
.github/workflows/audit-central-ruleset.yml:104 (RIGHT)confirmed: A central ruleset audit failure will still be surfaced even if a later repository ruleset fetch fails. — Static flow: the central audit sets audit_status=1, then the repository fetchif ! gh api ...is false and triggersexit 1at line 104. The final audit_status check at line 123 is never reached, so the central drift is masked by an unrelated fetch error..github/workflows/audit-central-ruleset.yml:124 (RIGHT)confirmed: The final error message accurately describes the set of drifted rulesets when only the central audit failed. — The final message unconditionally states 'One or more fetched rulesets drift...' even though no repository/stacked ruleset was fetched, misleading operators about which ruleset actually failed.- Residual risk: After fixing the early-exit masking, ensure the scheduled audit surfaces a central ruleset drift even if all later fetches succeed; the current design also needs a dedicated annotation for the central audit failure.
Findings
- [medium] .github/workflows/audit-central-ruleset.yml:104 (RIGHT): Central ruleset audit failure can be masked: when audit_status is set, the workflow continues and a subsequent repository ruleset fetch failure exits the job at line 104 before the final audit_status check at line 123. On the scheduled owner-plane audit, a central ruleset drift would not be reported, defeating the fail-closed drift detection.
- [low] .github/workflows/audit-central-ruleset.yml:124 (RIGHT): The final error message says 'One or more fetched rulesets drift' even when only the central ruleset audit failed and no repository/stacked ruleset was fetched, which misleads operators about the actual drift source.
- Result: REQUEST_CHANGES
- Head SHA:
02d76fa76a9772e4abd506845aa3d383a45efaf5 - Reviewer credential:
noema-review-github-app-refresh - Actor:
cwl-noema-review[bot]
|
Exact-head repair receipt for Noema's source finding was valid. RED pinned the missing failure ledger, subject-specific central/owner/stacked attribution, absence of early exits before the next audit, and the terminal named receipt. The workflow now records a failed API read as a named failure, skips auditing the unavailable payload, continues collecting any remaining subject evidence, and exits nonzero once with every proven failure subject. A later owner/stacked fetch error can no longer hide an already-observed central governance drift. Verification on the exact tree:
The PR is Draft/Proposed while the new hosted runs and qualifying independent review are reacquired. This does not claim live ruleset convergence or authorize bypass/merge. |
|
Exact-head CodeQL RCA for
Draft/Proposed remains correct. Do not manually rerun, synthesize status, transfer successor evidence, or merge until exact-head CodeQL converges and a qualifying independent approval exists. |
|
Ready transition preserved exact head Noema's source finding is bound to predecessor |
|
@opencode-agent Revalidate unchanged exact head |
|
Fresh consumer canary for the governance owner: |
Current authority / repair state — 2026-09-15
Canonical source head remains
722fec9de67aece7500993ee2999b21df0fab83b, but its historical basemain@fb17ef556f94f673234aa557254ae52779e9a7b0is no longer current. Fresh comparison against protected.github/main@91be6442906c7b6b4f600272c953699708394327is diverged: 44 ahead / 252 behind, and the PR is currently non-mergeable. It has therefore been returned to Draft. Historical source-tree verification remains useful evidence for the retained delta, but it is not current-base acceptance and must not be transferred through reconciliation.The Noema current-head masking finding on this source lineage was reproduced RED and repaired by accumulating named central, owner-repository, and stacked-ruleset failures before one terminal fail-closed exit; missing payloads are never audited as valid. Historical exact-tree verification on
722fec9...was focused governance contracts 55 passed; full 3195 passed, 1 skipped, 36 subtests; warnings-as-errors, workflow syntax, andgit diff --checkPASS.Required next source action is an ordinary/non-force, conflict-aware reconciliation onto the then-current protected main, preserving the canonical solo-maintainer policy and all valid intervening central fixes. Do not force-push, destructively rebase, merge the stale head, or reuse historical Checks/reviews. After the reconciled descendant exists, reacquire all exact-head/current-base workflows, threads, and review evidence from zero before any Ready/merge decision.
Buyer/control-plane outcome
This is the canonical owner-plane writer for the live ruleset drift tracked by #772. Source integration alone does not mutate live settings: privileged apply remains disabled unless trusted protected
mainhasCWL_RULESET_RECONCILE_ENABLED=trueand the protectedruleset-governance-maintenanceenvironment supplies a separately provisioned least-privilegeCWL_RULESET_ADMIN_TOKENwith Administration write authority.Fresh live drift
Live rulesets were re-read independently of this source head:
18156473remains active on default branches withrequired_approving_review_count=1,required_reviewers=[], CODEOWNER review disabled, last-push approval disabled, stale-review dismissal/thread resolution retained, central required workflows enforced, andOrganizationAdmin/alwaysbypass still present;.githubrepository ruleset17921150remains active with approval count 0, last-push/CODEOWNER review disabled and thread resolution retained, but it still permitsrebasein addition to merge/squash and still carriesOrganizationAdmin/alwaysbypass.Therefore the live owner plane has not converged merely because this PR contains the desired policy source. The one-generic-approval organization rule remains structurally unsatisfiable for the accepted one-human-maintainer model without self-approval, fake humans, or treating bot/model review as human approval. Those workarounds remain forbidden.
Reviewed implementation boundary
config/ruleset-governance.jsonbinds exactly repository ruleset17921150and organization ruleset18156473.PUTprecondition for these ruleset updates. A second live read detects visible drift but is not represented as compare-and-swap.PUT, and rechecks version state after settlement before trusting the restore.PUTmay already have been accepted, history settlement and lossless compensation finish without a stale-main veto so an overwritten administrator predecessor is not stranded.Conflicting sibling candidate
#1861 remains a blocked sibling candidate because its current proposal hard-codes two approving reviews plus last-push approval, which contradicts #772 and this canonical policy and would deepen the solo-maintainer deadlock. Its early-preflight mechanism may be retained only if a future ordinary descendant derives expected review settings from the canonical policy/config; the hard-coded two-human policy must not be merged or applied.
Acceptance boundary
After an ordinary/non-force current-main reconciliation, require terminal successor-head deterministic security/review evidence before normal protected integration. After source reaches protected
main, provision the distinct least-privilege owner-plane identity, enable reconciliation only for a controlled maintenance interval, require exact live payload plus immutable-history convergence, re-run the canonical audit, and prove an unchanged deterministic-GREEN protected-PR can take the ordinary merge path without synthetic approval or routine administrator bypass. Genuine failed/absent required workflows and unresolved required threads remain blocking.Do not mark Ready merely because the historical head tested clean. Do not self-approve, fabricate reviewers, count bots/models as humans, force-update, destructively rebase, use no-op wake commits, weaken required workflows/security/SAST/coverage/package/SBOM/provenance/thread/deletion/non-fast-forward controls, or use routine administrator bypass.
Refs #772, #1176, #1340, #1351, #1669, #1728, #1731, #1734, #1861, ContextualWisdomLab/Orgmetra#89.