GitHub Branch Protection
This repository uses two protected long-lived branches:
developmentis the integration branch for active feature, hardening, and multi-agent work.mainis the release-ready branch.
Feature work should happen on short-lived branches and merge into development
only after CI passes. Release promotion should happen through a release/*
branch, not by opening development or a feature branch directly against
main.
Multi-Agent Branch Flow
Use this flow when multiple agents are working at the same time:
- Start each agent from the latest
origin/development. - Give each agent a short-lived branch with a bounded scope.
- Open each agent PR into
development, notmain. - Require
build-testto pass before merging intodevelopment. - Resolve review comments and conversations before merge.
- Queue auto-merge after opening the PR so GitHub merges it when required checks and conversations are clear.
- Promote
developmenttomainwith a separaterelease/*PR.
Agents should not commit directly to main. Direct pushes to development should be reserved for owner-controlled setup work, emergency repair, or branch-gate maintenance.
For agent PRs into development, use squash auto-merge with branch cleanup:
gh pr merge <pr-number> --squash --delete-branch --auto
Auto-merge does not bypass branch protection. GitHub waits for the required build-test status check, an up-to-date branch, and resolved review conversations before merging. If CI fails, review threads remain unresolved, the branch conflicts, or the PR is draft, the PR stays open.
Main Promotion Flow
main is production. Most work should never target it directly.
Normal release flow:
- Merge feature, docs, and hardening work into
development. -
Create a release branch from the current
developmenttip:git fetch origin main development git switch -c release/YYYY-MM-DD origin/development git merge -s ours --no-edit origin/main git push -u origin release/YYYY-MM-DD gh pr create --base main --head release/YYYY-MM-DDThe
-s oursmerge records the currentmaintip as release ancestry while keeping the testeddevelopmenttree. This prevents GitHub from replaying old development commits in future promotion PRs after a prior squash-style promotion. - The PR to
mainmust passbuild-testandmain-promotion-gate. - Merge the release PR with a merge commit. Do not squash release promotions.
Patch exception:
- Create a
hotfix/*orpatch/*branch fromorigin/main. - Label the PR
patchorhotfix. - Pass
build-testandmain-promotion-gate. - Backport or merge the fix into
developmentimmediately after the production patch.
Do not open development directly against main. Do not open codex/*,
feature, or cleanup branches directly against main unless they are explicit
patch branches following the exception above.
Required CI Check
The required status check for development is:
build-test
It is defined in .github/workflows/development-targeted.yml for
development PRs and pushes.
The required status checks for main are:
build-test
main-promotion-gate
build-test is defined in .github/workflows/ci.yml for main PRs and runs the
full test suite. main-promotion-gate is defined in
.github/workflows/main-promotion-gate.yml and rejects direct feature-branch or
direct development PRs to main.
Recommended Protection
Enable these settings for both long-lived branches:
- Require a pull request before merging.
- Require status checks to pass before merging.
- Require branches to be up to date before merging.
- Require conversation resolution before merging.
- Do not allow force pushes.
- Do not allow deletions.
- Include administrators when you want the rule to protect local owner workflows too.
For development, require build-test and keep linear history enabled so
feature PRs squash cleanly into the integration branch.
For main, require build-test and main-promotion-gate. Disable required
linear history so release promotion PRs can use merge commits. Squash-merging a
release promotion can make main and development file-identical while leaving
their histories unrelated, which causes the next promotion PR to replay old
development commits.
At the repository level, enable auto-merge and delete feature branches after merge. These settings apply to short-lived PR branches; branch protection still prevents deleting development or main.
For solo development, approving reviews can stay disabled or be set to zero required approvals. If more contributors are added, require at least one approving review and dismiss stale approvals on new commits.
GitHub CLI Setup
After the checks have appeared in GitHub at least once, apply branch protection:
Development:
gh api \
--method PUT \
"repos/paulboutin/aegis/branches/development/protection" \
--input - <<'JSON'
{
"required_status_checks": {
"strict": true,
"contexts": ["build-test"]
},
"enforce_admins": true,
"required_pull_request_reviews": {
"required_approving_review_count": 0,
"dismiss_stale_reviews": true,
"require_code_owner_reviews": false,
"require_last_push_approval": false
},
"restrictions": null,
"required_linear_history": true,
"allow_force_pushes": false,
"allow_deletions": false,
"required_conversation_resolution": true
}
JSON
Main:
gh api \
--method PUT \
"repos/paulboutin/aegis/branches/main/protection" \
--input - <<'JSON'
{
"required_status_checks": {
"strict": true,
"contexts": ["build-test", "main-promotion-gate"]
},
"enforce_admins": true,
"required_pull_request_reviews": {
"required_approving_review_count": 0,
"dismiss_stale_reviews": true,
"require_code_owner_reviews": false,
"require_last_push_approval": false
},
"restrictions": null,
"required_linear_history": false,
"allow_force_pushes": false,
"allow_deletions": false,
"required_conversation_resolution": true
}
JSON
Bootstrap note: .github/workflows/main-promotion-gate.yml must exist on main
before GitHub can require the main-promotion-gate status check for future PRs.
Merge the guard through the release flow once, then update main protection to
require the new check.
GitHub’s settings UI can be used instead: Repository Settings -> Rules -> Rulesets, or Repository Settings -> Branches -> Branch protection rules.