merge-and-release · git:20260506.b1f0fef · 2026-05-06 · sha256 2c1d1e58977c449b
merge-and-release git:20260506.b1f0fefA
Immutable. This exact content is served forever at /api/v1/blob/2c1d1e58977c449b.
--- name: merge-and-release description: "Reference document describing merge prerequisites (approval, CI checks, mergeable, conversations resolved, stale approval), release versioning (semantic semver), and changelog generation. Explains why Tier 3 confirmation is structural: merge and release cost is borne by downstream people. Reference only (`disable-model-invocation: true`); consumed by `/flow:merge` and `/flow:release`." allowed-tools: Read context: fork agent: Explore disable-model-invocation: true --- # Merge and Release Reference document for merge and release policy. The executable bash lives in `plugins/flow/commands/merge.md` and `plugins/flow/commands/release.md`. This skill describes **what those commands enforce and why**. Both merge and release are **Tier 3** — they always require explicit human confirmation, even in autonomous mode. This is non-negotiable. ## Iron Law **MERGE IS IRREVERSIBLE IN PRACTICE. Treat every merge as permanent. Every prerequisite must be verified with fresh evidence, not memory.** Reverting a merge is technically possible in git but disruptive in practice — downstream branches rebase off the merge, deploys propagate it, and history grows confusing. Prevention is the only reliable strategy. The Tier 3 confirmation requirement is the structural expression of that fact. ## Merge Prerequisites — The Five-Check Gate Before a merge proceeds, all five checks must pass. The runnable verification is in `plugins/flow/commands/merge.md` Phase 1. | # | Check | Requirement | What it protects against | |---|-------|-------------|--------------------------| | 1 | Approval | At least one approval, no outstanding requested changes | Merging code that no human has signed off on | | 2 | CI Checks | All status checks pass (`statusCheckRollup` all success) | Merging code that fails the project's automated tests | | 3 | Mergeable | No merge conflicts (`mergeable == "MERGEABLE"`) | Merging a PR whose content cannot cleanly land on the base branch | | 4 | Conversations | All review threads resolved (unresolved count == 0) | Closing reviewer concerns by ignoring them | | 5 | Stale approval | No commits after the last approval timestamp | Merging code that was approved before the latest changes existed | The conversation-resolution check requires GitHub's GraphQL API (the REST `reviewThreads` field is incomplete). The exact GraphQL query used is in `plugins/flow/commands/merge.md`. ## Stop Conditions — Non-Negotiable When any of these conditions is detected, the command **stops without asking "merge anyway?"**: - ANY of the five prerequisites fails - Stale approval detected — request re-review, do not merge - Unresolved conversations > 0 — resolve first, do not merge - Finding-ledger check fails (see `pr-lifecycle` skill for details) There is no "override the gate" option in autonomous mode. Overrides require the human user to take the action themselves outside the command. ## Stale Approval Detection A "stale" approval is one that predates the most recent commit on the PR. The check compares: - The latest `submittedAt` timestamp among reviews where `state == "APPROVED"` - The `committedDate` of the most recent commit on the PR If commits exist after the last approval, the command warns: "Approval may be stale." Stale approvals are a stop condition because the approver has not actually seen what is being merged. ## Merge Execution After all prerequisites pass, the command displays a **Merge Assessment** table and explicitly asks the user to confirm. Only after a clear "yes" does the merge proceed: - Strategy is read from settings (`squash` | `merge` | `rebase`, default `squash`) - Branch deletion is read from settings (default `true`) - The `gh pr merge` invocation is in `plugins/flow/commands/merge.md` Phase 3 The user-visible assessment lists every prerequisite's status, the chosen strategy, and the branch-delete decision so the human can verify before approving. ## Release Process Releases follow the same Tier 3 confirmation discipline as merges. The runnable bash is in `plugins/flow/commands/release.md`. ### Version Calculation | Bump type | Format | When to use | |-----------|--------|-------------| | `patch` | 0.0.X+1 | Bug fixes only, no behavior change | | `minor` | 0.X+1.0 | New features, no breaking changes | | `major` | X+1.0.0 | Breaking changes | The first release defaults to `v1.0.0` if no prior tag exists. ### Changelog Generation The changelog is built from merged PRs since the last release tag, categorized by conventional commit prefix: - **Features** — `feat:` PRs - **Bug Fixes** — `fix:` PRs - **Other Changes** — `docs:`, `chore:`, etc. Each entry includes the PR number and author. A "Full Changelog" link compares the previous tag to the new one. ### Release Execution After the changelog and version are displayed, the command asks the user to confirm. Only after explicit confirmation: 1. Create annotated tag: `git tag -a "$TAG" -m "Release $TAG"` 2. Push tag: `git push origin "$TAG"` 3. Create GitHub release: `gh release create "$TAG" --title "$TAG" --notes "$CHANGELOG"` These three operations together are the release. They are not split across multiple agent turns — the user confirms once and the command performs them in sequence. ## Post-Merge / Post-Release After either operation completes, the command verifies state: - Merge: `gh pr view $PR_NUM --json state` should return `MERGED` - Release: `gh release view $TAG` should succeed The command then suggests cleanup: switch to the default branch, pull latest, and (for releases) update plugin version files if applicable. ## Why Tier 3 Is Structural, Not Optional Merges and releases produce visible, durable artifacts: a merge commit on `main`, a published tag, a GitHub release page that subscribers may receive notifications for. The cost of an unwanted merge or release is paid by everyone downstream — other developers rebasing, users seeing a notification for a release that was a mistake, package managers fetching the new version. Tier 3 is not gatekeeping for its own sake. It is the structural expression of: **the cost of an unwanted action is borne by people who are not in this conversation.** The human in the loop is the only person who can speak for those downstream people. ## Where the Bash Lives This skill is reference-only. The runnable implementations are: - **Merge prerequisites + execution**: `plugins/flow/commands/merge.md` - **Release version calculation + tagging + GitHub release creation**: `plugins/flow/commands/release.md` When the policy needs to evolve — a new prerequisite, a new release strategy, a different versioning scheme — update the command and update this reference together. The bash is the runtime; this document is the rationale.