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`.
Scanned 5/27/2026
Install via CLI
openskills install synaptiai/synapti-marketplace---
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
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.
No comments yet. Be the first to comment!