Skip to content

Feat/branch gates applier - #1043

Merged
hyperpolymath merged 3 commits into
mainfrom
feat/branch-gates-applier
Sep 23, 2026
Merged

hyperpolymath merged 3 commits into
mainfrom
feat/branch-gates-applier

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Summary

Closes #

Type of change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 💥 Breaking change (would change existing behaviour)
  • 🕳️ Soundness fix (fixes a checker/proof false-negative)
  • 📖 Documentation
  • 🧹 Refactor / tech debt (behaviour-preserving)
  • ⚡ Performance
  • 🔧 Build / CI / tooling

How has this been verified?

Checklist

  • My commits are signed (git commit -S).
  • I ran the project's own checks/tests locally and they pass.
  • New files carry the correct SPDX-License-Identifier (code/config MPL-2.0,
    prose CC-BY-SA-4.0); I did not relicense existing files.
  • Docs are updated, and no public claim now overstates what the code does.
  • I have not introduced a soundness hole (or I have flagged where I might have).

Notes for reviewers

hyperpolymath and others added 2 commits September 22, 2026 22:14
…cified but nothing performed

config/rulesets/README.adoc has said so since it was written: "the propagation
mechanism is still missing by design, and this note is the reminder that a
template fix without an applier is a half fix." That was literally true —
nothing in this repository read config/rulesets/gates.json as DATA. Every
reference was prose, or tests/test_governance_reusable_shape.sh asserting the
file's contents. gates.json specified a context derivation that no code
performed, so required_status_checks was never propagated to any repository.
apply-tag-ruleset-canon.sh is the TAG applier; this is its branch sibling.

CONTEXTS ARE DERIVED, NEVER TYPED
  Per gates.json, contexts come from the check names the latest default-branch
  run of each gate workflow actually emitted, via
    /actions/workflows/{file}/runs?branch=<default>&per_page=1
    /actions/runs/{id}/jobs
  A hand-typed context that nothing emits is a PHANTOM: it can never turn
  green, so it blocks the branch permanently.

THE REFUSAL THAT MATTERS
  Zero derivable contexts => report UNGATED and write NOTHING. A
  required_status_checks rule carrying an empty list is a VACUOUS GATE: it
  reports "protected" in every summary view while requiring nothing, which is
  strictly worse than having no rule, because it is indistinguishable from a
  working one.

EXACTNESS GUARD
  A ruleset PUT replaces the whole object. The planned body, normalised with
  the required_status_checks rule removed from both sides, must be
  byte-identical to the source; anything else moved is a refusal. Without it,
  one jq slip strips required_signatures from every repo it touches, silently.

DELIBERATE NON-ACTIONS
  * never creates a ruleset (NORULESET is reported, not repaired) — creating
    branch protection where none exists is a policy act, not a gate-fill;
  * never removes the four retired rule types unless --strip-retired is passed
    — the estate census was ruled report-only;
  * two active branch rulesets => AMBIGUOUS, fail closed. Rulesets are
    ADDITIVE: filling one of a pair leaves the other enforcing and the repo
    stays blocked by a rule nothing announced.

--require-green N implements the standing ruling on #956, "require the
reliably-green set": a context that is currently red becomes a merge deadlock
the instant it is required. `skipped` and `neutral` count as green, because
GitHub treats both as satisfying a required status check.

TESTS — a passing suite would not have been evidence
  scripts/tests/branch-gates-apply-test.sh runs 18 controls, two of which are
  MUTANTS that must go red:
    A. delete the zero-context refusal -> the applier writes the vacuous
       empty-list rule (verified by inspecting the captured PUT body);
    B. make the body-builder also drop required_signatures -> the exactness
       guard refuses.
  Both die. The suite exercises the applier through a `gh` shim, so it needs
  no network and no credentials.

Two defects were found by these controls rather than in review: the
--strip-retired jq filter used `index(.type)`, where jq rebinds `.` to the
array so `.type` was always null (the same class of bug apply-baseline-test.sh
was written to pin), and the exactness guard rejected its own honest control
because ADDING the required_status_checks rule legitimately changes the rules
array length.

Both files are committed 100755 — a suite committed 0644 passes every local
run and dies in CI at exit 126 before a single control executes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ji1bq3TypfycfUPAR7hSxR
@coderabbitai

coderabbitai Bot commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Next included review available in 53 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: d7478de5-ebc2-46b2-a272-05d4885337fd

📥 Commits

Reviewing files that changed from the base of the PR and between 520dcf6 and f67ad63.

📒 Files selected for processing (2)
  • scripts/apply-branch-gates.sh
  • scripts/tests/branch-gates-apply-test.sh

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.

@hyperpolymath
hyperpolymath enabled auto-merge (squash) September 23, 2026 09:27
Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
@hyperpolymath
hyperpolymath enabled auto-merge (squash) September 23, 2026 09:28
@sonarqubecloud

Copy link
Copy Markdown

@hyperpolymath
hyperpolymath merged commit f56da4f into main Sep 23, 2026
43 of 45 checks passed
@hyperpolymath
hyperpolymath deleted the feat/branch-gates-applier branch September 23, 2026 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant