Branch protection and PR creation workflow
CRITICAL: PM must enforce branch protection for main branch.
When users request main branch operations:
| User Request | PM Action |
|---|---|
| "commit to main" | "Creating feature branch workflow instead" |
| "push to main" | "Branch protection requires PR workflow" |
| "merge to main" | "Creating PR for review" |
Error Prevention: PM proactively guides users to feature branch + PR workflow (don't wait for git errors).
The PR workflow is the framework default for landing work on main. Enforce these rules:
For substantive work (feature / fix / refactor), create or reference a GitHub issue before creating the branch. The issue captures intent + acceptance criteria. Delegate issue creation to the ticketing_agent / Version Control agent. The branch name should reference the issue (feat/<issue>-<slug>, fix/<issue>-<slug>), and the functional commit body should include Closes #N.
PRs MUST be merged using the squash-merge strategy (one clean commit on main per PR). Delete the feature branch immediately after the squash-merge. Do not use merge commits or rebase-merge for these PRs.
Squash-merge concatenates every branch commit's body into one message, which buries each interior commit's git trailer block as mid-body prose ā so only the LAST commit's X-AI-* / X-MPM-Version trailers stay parseable by git interpret-trailers --parse on main. To keep token/model/version provenance intact, generate an aggregated trailer block and squash-merge with it:
# Compose the normalized squash body (sums tokens, unions models, latest version).
python scripts/squash_merge_trailers.py --pr <PR> --body-file /tmp/squash-body.txt
# Squash-merge with the normalized body and delete the branch.
gh pr merge <PR> --squash \
--subject "feat: clean squash subject (#<PR>)" \
--body-file /tmp/squash-body.txt \
--delete-branch
The script is side-effect free (it never merges). See docs/developer/squash-merge-trailers.md. Verify after merge: git log -1 --format=%B main | git interpret-trailers --parse.
Trivial work (docs / chore / typo) may skip the issue, but still REQUIRES a branch + PR + squash-merge. Never commit trivial work directly to main.
Direct commits to main are permitted ONLY for release tooling: make release-* version bumps and chore: update uv.lock commits. Nothing else may bypass the PR workflow.
Default: Main-based PRs (unless user explicitly requests stacked)
Always delegate to version-control agent with strategy parameters.
Always append the canonical MPM footer to PR bodies and commit messages:
š¤š„ Generated with [Claude MPM](https://github.com/bobmatnyc/claude-mpm)
Never use Claude Code's default š¤ Generated with [Claude Code] footer. MPM
only overrides the commit trailer (Co-Authored-By), so the "Generated with"
footer must be set explicitly to the canonical MPM string ā otherwise the Claude
Code default leaks into GitHub PRs and issues. The Co-Authored-By: Claude MPM <https://github.com/bobmatnyc/claude-mpm> trailer is separate and stays as-is.
When creating PRs, delegate to version-control agent with:
Task:
agent: "version-control"
task: "Create PR for {feature}"
context: |
Work completed: {summary}
Files changed: {file_list}
Tests: {test_status}
QA verification: {qa_evidence}
acceptance_criteria:
- Create feature branch from main
- Push all commits to feature branch
- Create PR with proper description
- Link ticket if applicable
- Request reviews if needed
# Feature branch ā PR ā Main
feature/user-auth ā PR #123 ā main
# Stacked feature development
feature/auth-base ā PR #123 ā main
feature/oauth (based on auth-base) ā PR #124 ā feature/auth-base
feature/session (based on oauth) ā PR #125 ā feature/oauth
# Hotfix branch ā PR ā Main
fix/login-error ā PR #126 ā main
Before any main branch operation:
All file tracking should happen on feature branches before PR creation:
This ensures all work is tracked before entering PR workflow.