Skip to content

Commit db1aec8

Browse files
committed
phase 0: flip branch protection on main and document the admin-bypass posture
Branch protection applied 2026-05-09 via gh api after PRs #3 and #4 registered the required check names with GitHub. Required checks engine (clang), engine (gcc), frontend; 1 review required; linear history; conversation resolution; no force pushes; no deletions. enforce_admins is set to false because the legacy GitHub branch-protection API cannot express the per-rule admin carveout the project actually wants. The discipline is enforced in CLAUDE.md "When the user says push" instead: the standing --admin authorization is limited to the review-bypass case only and never extends to bypassing required CI checks or linear history. docs/setup-guide.md section 12.1 reframed from "manual UI step" to "applied" with the gh api command captured for reproducibility, plus a documented migration path (GitHub Repository Rulesets) if a future iteration ever needs the carveout enforced by the platform rather than by convention. STATUS.md Resume notes drop the "branch protection deferred" item and now record the protection state with the date and the admin-bypass posture in one paragraph.
1 parent 7fe65cc commit db1aec8

2 files changed

Lines changed: 10 additions & 8 deletions

File tree

STATUS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ Phase 0 closed cleanly. PR #3 (`phase 0: brainstorm, plan, scaffold, and audit`)
3535

3636
**Outstanding deferred work** (not Phase 0 blockers, but worth tracking):
3737

38-
* Branch protection on `main` is not yet flipped via the GitHub web UI. The required-check names (`engine (clang)`, `engine (gcc)`, `frontend`) are registered with GitHub after the first PR run, so flipping this is a manual UI step the user can do at any time per `docs/setup-guide.md` section 12.1.
3938
* No Code Reviewer dispatch ran on Phase 0; PR review by a dispatched Code Reviewer agent was deferred since Phase 0 is mostly docs and scaffolding. Phase 1 onward will dispatch Code Reviewer per the PM brief.
4039

40+
**Branch protection on `main`**: applied 2026-05-09 via `gh api`. Required checks `engine (clang)`, `engine (gcc)`, `frontend`; 1 review required; linear history; conversation resolution; no force pushes; no deletions. `enforce_admins` is `false` so `gh pr merge --admin` continues to work for the review-bypass case per `CLAUDE.md`'s standing push protocol. Details in `docs/setup-guide.md` section 12.1.
41+
4142
## Design sync log
4243

4344
The user can change the design at any time, including after Phase 11 ships, via either flow in `CLAUDE.md` ("Design change workflow"):

docs/setup-guide.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,23 +52,24 @@ To be filled in by DevOps in Phase 10. Will cover the multi stage Dockerfile, th
5252

5353
To be filled in by DevOps as each workflow lands. Will cover the secrets configured in GitHub (`FLY_API_TOKEN`, `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_ACCOUNT_ID`), the protection rules on `main`, and how to manually trigger the bench workflow.
5454

55-
### 12.1 Branch protection on `main` (Phase 0, manual UI step)
55+
### 12.1 Branch protection on `main`
5656

57-
The DevOps Engineer cannot flip branch protection bits non-interactively in this dispatch; the Project Manager session does this with the user via the GitHub web UI at `https://github.com/MustafaNazeer/Meridian/settings/branches`. Configure the protection rule on `main` as follows once `ci.yml` has run at least once on a PR (so the check names are registered):
57+
Applied 2026-05-09 via `gh api -X PUT repos/MustafaNazeer/Meridian/branches/main/protection` after PRs #3 and #4 ran `ci.yml` and registered the check names with GitHub. The rule is active and enforces:
5858

5959
1. **Require a pull request before merging.** Approvals: `1`. Dismiss stale pull request approvals when new commits are pushed: enabled. Require review from Code Owners: disabled (no `CODEOWNERS` file in v1).
60-
2. **Require status checks to pass before merging.** Require branches to be up to date before merging: enabled. Required checks (after `ci.yml` has run once so GitHub registers the names):
60+
2. **Require status checks to pass before merging.** Require branches to be up to date before merging: enabled. Required checks:
6161
* `engine (clang)`
6262
* `engine (gcc)`
6363
* `frontend`
6464
3. **Require conversation resolution before merging.** Enabled.
6565
4. **Require linear history.** Enabled (matches the squash merge convention in `CLAUDE.md`).
66-
5. **Do not allow bypassing the above settings.** Enabled, with one exception: include administrators in restrictions, but allow `--admin` merges from the repo owner per the standing protocol in `CLAUDE.md` ("When the user says push"). The `--admin` authorization is documented as bypassing only the "1 review required" rule, never the required status checks or the linear history rule.
67-
6. **Restrict who can push to matching branches.** No direct pushes to `main`; all changes flow through pull requests.
66+
5. **Restrict who can push to matching branches.** No direct pushes to `main`; all changes flow through pull requests. Force pushes and branch deletion both blocked.
6867

69-
When Phase 5 lands `bench.yml` (manual workflow), the bench job is added to the required-checks list only if the user explicitly requests it; bench runs are typically gated to manual triggers, so making it a required check would block merges on a workflow that does not auto-run.
68+
**Admin bypass posture.** `enforce_admins` is set to `false` because the legacy GitHub branch-protection API cannot express the per-rule admin carveout the project actually wants (admins should be able to bypass the "1 review required" rule on solo PRs since the rule is structurally unsatisfiable, but should never bypass required status checks or linear history). The discipline is enforced in `CLAUDE.md` instead: the standing `--admin` authorization is explicitly limited to the review-bypass case only and never extends to bypassing required CI checks or any other rule. If a future iteration needs the carveout enforced by the platform rather than by convention, migrate to GitHub Repository Rulesets, which support per-rule bypass actors.
7069

71-
When Phase 8 lands the WebSocket smoke job inside `ci.yml`, that job's name is added to the required-checks list.
70+
When Phase 5 lands `bench.yml` (manual workflow), the bench job is added to the required-checks list only if the user explicitly requests it; bench runs are typically gated to manual triggers, so making it a required check would block merges on a workflow that does not auto-run. Update via `gh api -X PATCH repos/MustafaNazeer/Meridian/branches/main/protection/required_status_checks` with the augmented `contexts` array.
71+
72+
When Phase 8 lands the WebSocket smoke job inside `ci.yml`, that job's name is added to the required-checks list with the same `gh api` PATCH.
7273

7374
When Phase 10 lands `deploy.yml`, the deploy jobs are not required checks; they run after merge to `main`, not on PRs.
7475

0 commit comments

Comments
 (0)