From a6cd3e5997be1031e75ed73eebecf3cc673215f8 Mon Sep 17 00:00:00 2001 From: clawbot Date: Sat, 28 Feb 2026 02:42:28 -0800 Subject: [PATCH] add branch protection as server-side interlock in both docs --- AUTOMATED_DEV.md | 34 ++++++++++++++++++++++++++++++++++ OPENCLAW_TRICKS.md | 5 +++++ 2 files changed, 39 insertions(+) diff --git a/AUTOMATED_DEV.md b/AUTOMATED_DEV.md index f5aebd5..3e4a3de 100644 --- a/AUTOMATED_DEV.md +++ b/AUTOMATED_DEV.md @@ -187,6 +187,40 @@ Labels and assignments are better because: lots of red = rebase debt, lots of orange = CI problems, lots of green = ready for review. +#### Branch Protection + +The state machine assumes nobody can bypass it by pushing directly to main. +Branch protection rules on Gitea (or GitHub) enforce this at the server level: + +- **Require pull request reviews** before merging — no direct pushes to main +- **Require CI to pass** — the Docker build (which runs `make check`) must + succeed before a PR can be merged +- **Block force-pushes** — history is immutable on protected branches +- **Require branches to be up-to-date** — PRs must be rebased before merge + +This is the server-side interlock that makes the entire state machine +trustworthy. Without branch protection, an agent could skip the review/check +cycle and push directly to main. With it, the only path to main is through a PR +that passes all gates. A tired human at 3am, or an overconfident agent, +physically cannot bypass the review and CI gates — the server won't allow it. + +Branch protection completes the interlocking chain: + +``` +Branch protection (server-side) + └── Requires CI pass + └── CI runs docker build + └── Dockerfile runs make check + ├── make fmt-check + ├── make lint + └── make test +``` + +Every layer enforces the one below it. The developer (human or agent) can't skip +any step because each gate is enforced by a different system: the Makefile +enforces test/lint/fmt, the Dockerfile enforces the Makefile, CI enforces the +Docker build, and branch protection enforces CI. No single point of failure. + ## Real-Time Activity Feed: Gitea → Mattermost Every repo has a Gitea webhook that sends all activity (pushes, PRs, issues, diff --git a/OPENCLAW_TRICKS.md b/OPENCLAW_TRICKS.md index 5e80c07..6c155e9 100644 --- a/OPENCLAW_TRICKS.md +++ b/OPENCLAW_TRICKS.md @@ -653,6 +653,11 @@ From REPO_POLICIES.md and our operational experience: love to `git add .` and accidentally commit `.DS_Store`, editor swap files, or debug output - **Never force-push to main** — feature branches only +- **Branch protection on main** — enforce this with Gitea/GitHub branch + protection rules: require PR reviews, require CI to pass, block force-pushes. + This is the server-side interlock that makes the "never push directly to main" + rule structural rather than aspirational. An agent (or a tired human at 3am) + physically cannot bypass the review and CI gates. - **Each change = separate commit** — formatting changes go in their own commit before logic changes - **Rebase before and after** — PRs must be mergeable at time of push