diff --git a/.claude/BRANCHING.md b/.claude/BRANCHING.md index f4b7366..e602fbc 100644 --- a/.claude/BRANCHING.md +++ b/.claude/BRANCHING.md @@ -179,6 +179,35 @@ else; say plainly where it came from rather than implying a check passed. A hotfix that touches only one domain deploys only that domain. Check the other half's `/api/version` before assuming the fix is live end to end. +### When you genuinely need to push directly + +`apply_to_admins` is on, which means these rules bind the owner too. That is +deliberate — protection an admin walks straight through is documentation, not a +control, and every account here is an admin — but it does remove the escape +hatch, so the way back in is worth writing down before it is needed at 3am. + +There is no force flag. The supported route is to lift the rule, do the thing, +and put it back: + +``` +forge_branch_protection(branch="dev", delete=true) # rule gone; direct push allowed +git push origin dev # the emergency change +forge_branch_protection(branch="dev", apply=true) # restored to policy +``` + +Both the removal and the restore are audited, which is the point: the hatch is +open on the record rather than by a quiet exception. Restore it in the same +session — a protection rule "temporarily" removed is how a repo ends up +unprotected for a month. + +The failure mode that actually justifies this: if the required status context +is ever renamed and no longer matches, **nothing can merge into `dev` or `main` +at all**, including by you, because `apply_to_admins` no longer exempts anyone. +`forge_pr_await` and `forge_pr_merge` both name that case explicitly when they +see it. The fix is to correct `pr-build.yml`'s workflow/job names and +`CENTRALIS_REQUIRED_CHECK` together — but if you need to land the fix itself, +lift the rule as above. + ## Guardrails - Never force-push `dev`, `main` or `release`.