---
name: tm-pr-workflow
description: Branch protection, trusty-review gate, squash-merge, and worktree discipline for landing work on main
user-invocable: false
version: "1.0.0"
category: pm-workflow
tags: [git, pr, branch-protection, worktree, pm-required]
effort: medium
---
# PR Workflow: The tm-Specific Layer
Native Claude Code already knows how to run `gh pr create` — this skill does
not re-explain that mechanic. It covers the parts that are specific to this
repo's delivery discipline and are easy to get wrong: worktree isolation,
branch protection, the trusty-review gate, and the squash-merge requirement.
## The Full Delivery Chain (this repo's convention)
```
spec -> issue -> worktree branch -> PR (linked to issue)
-> trusty-review gate -> squash-merge -> worktree cleanup
```
Every step matters. Skipping the worktree step or the review gate is not a
shortcut — it's a protocol violation the PM must not take on the user's
behalf without being asked.
## Worktree Discipline (Mandatory Before Any Edit)
Per root `CLAUDE.md`: the main checkout is **inspection-only** (read-only
`git status`/`log`/`diff`/`show`, file reads — no edits, no builds or test
runs (whatever the project's gate is — `cargo build`/`test`, `npm run
build`/`test`, `pytest`, ...), no destructive git ops). All write-side work
happens in a dedicated worktree branched off `origin/main`:
```bash
git fetch origin main
git worktree add -b <feature-or-fix-branch> \
.claude/worktrees/<dirname> origin/main
cd .claude/worktrees/<dirname>
```
Every subagent dispatch must name the exact worktree path it is confined to
and must never leave it into the main checkout, `git reset --hard`, `git
checkout .`, or `git stash` against main. Clean up after merge with `git
worktree remove --force <path>` and `git branch -D <branch>` — this never
touches the main checkout.
## Branch Protection
All pushes to `main`/`master` require a feature branch + PR — no exceptions,
including "trivial" docs/chore/typo work (which may skip the linked-issue
step but still requires branch + PR + squash-merge). The only bypass is
release tooling (version-bump / lockfile-update commits per the release
workflow), and only for those specific commit types.
When a user asks to "commit to main" / "push to main" / "merge to main",
proactively translate: "Creating feature branch workflow instead" — don't
wait for a git error to correct course.
## Changelog Requirement (Before Merge)
Changelogs go stale when updating them is left to "sometime at release" — so
it is part of every PR, not a separate chore:
- Every PR that changes a package's source adds one bullet per user-visible
change to that package's `CHANGELOG.md`, under the topmost `## [Unreleased]`
heading (create the heading if the file has none yet). Match the file's
existing bullet style and wording. Docs-only / CI-only PRs may skip this.
- A PR that changes source and lands without a matching changelog entry is a
**review-gate failure** — the same tier as a failing build/test/lint gate.
Treat it exactly like CB#8 (QA gate): block the merge, delegate back to the
Engineer to add the entry, don't wave it through as "trivial."
- If the project has automated changelog-generation tooling (e.g. a
conventional-commits generator run at release time), that tooling and these
hand-written per-PR entries can conflict — it may regenerate a section from
git log without knowing about, merging, or deduping against what's already
written by hand. Check the project's own instructions (root `CLAUDE.md` /
`.trusty-mpm/INSTRUCTIONS.md`) for the precedence rule before assuming the
two coexist safely; do not invent one on the fly.
## The trusty-review Gate
Before merge, delegate to the review gate:
```
mcp__trusty-review__review_diff # in-progress diff review
mcp__trusty-review__review_pr # open-PR review (correctness/design/security)
```
This is CB#8's evidence for a PR-shaped completion claim — "the PR is ready"
requires a review verdict (or human approval), not just green CI.
## Shipped Defaults: Assignee, Label, and Attribution Footer
These trusty-mpm framework defaults override any harness default and apply to
both the linked issue and the PR:
- **`--assignee @me --label trusty-mpm --label ws/<session-name>`** on every
`gh issue create` and `gh pr create`. This is multi-harness support: the
assignee + `trusty-mpm` label identify which issues/PRs a trusty-mpm session
owns and should pick up; `ws/<session-name>` (this session's own tmux
session name, via `tmux display-message -p '#{session_name}'`) is how
per-workstream activity is tracked — labels, never milestones, which stay
reserved for epics/releases. Full convention + rationale:
`PM_INSTRUCTIONS.md` "Commits & Issues". Create the labels first if missing:
```bash
gh label create trusty-mpm \
--description "Created/managed by a trusty-mpm session" --color 8250df \
2>/dev/null || true
gh issue create --assignee @me --label trusty-mpm --label "ws/<session-name>" --title "…" --body "…"
gh pr create --assignee @me --label trusty-mpm --label "ws/<session-name>" --title "…" --body "…"
```
- **Attribution footer** — every commit message and PR body ends with exactly:
```
🤖🤖🤖 Generated with trusty-mpm — https://github.com/bobmatnyc/trusty-tools
```
NEVER emit `🤖 Generated with Claude Code` or a `Co-Authored-By: Claude …`
trailer.
## Squash-Merge Is Required
PRs merge via **squash-merge only** — one clean commit on `main` per PR.
Delete the feature branch immediately after. No merge commits, no
rebase-merge, for PRs landing on `main`.
```bash
gh pr merge <PR> --squash --delete-branch
```
After a squash-merge the local feature branch will show as "unmerged" to git
(the squashed commit has a different hash) — this is expected, not a sign
the merge failed; see `docs/reference/worktree-discipline.md`.
## Delegation
PR creation itself (branch push, `gh pr create`, description, linking the
issue, requesting reviews) delegates to the **Version Control** agent —
provide it: work summary, files changed, test status, the trusty-review
verdict, and the shipped defaults above (`--assignee @me --label trusty-mpm
--label ws/<session-name>` plus the trusty-mpm attribution footer on the PR
body). The PM constructs the
delegation prompt; it does not run `gh pr create` itself (CB#6 boundary — the
PM stays out of `gh pr`/`gh issue` tooling).
## Related Skills
- `tm-git-file-tracking` — files must be tracked on the feature branch before PR creation
- `tm-circuit-breaker` — CB#6 (forbidden `gh` tool usage) and CB#8 (QA/review gate)
- `tm-ticketing` — the issue-linking half of the same delivery chain