skill: document scoped patch/hotfix release flow
Cherry-pick off the previous tag instead of branching off development when a patch should contain only specific PRs. Co-Authored-By: SplitFire v1.1.1-acp <noreply@splitfire.ai>
Seto Elkahfi committed
Oct 11, 2026 at 13:15 UTC
32de9b2d8c3ab969c0e67c898516aabe018c8a6f
1 file changed
+39
.agents/skills/sigit-code-release/SKILL.md
+39
@@ -55,6 +55,44 @@ Step 4 is the only way commits are meant to reach `main`. A feature or fix PR ta
55
56
Pushing the `v*.*.*` tag is what fires every release workflow, so create and push it only after the merge into `main` has landed. Do not commit, tag, or push until the user explicitly asks — confirm the version and that they want the release to go out first.
57
58
+### Scoped patch / hotfix flow (cherry-pick, not branch-off-development)
59
+
60
+The flow above assumes the release ships everything on `development`. A **scoped
61
+patch** is different: the user wants a new version that contains only one or a
62
+few specific merged PRs on top of the **last tag**, deliberately leaving out
63
+other work that has since landed on `development`. "A PR is merged into
64
+`development`" does **not** mean it belongs in a patch — a patch inherits the
65
+*previous tag's* tree, not `development`'s.
66
+
67
+Branching the release off `development` and only bumping the version is the
68
+classic mistake here: it silently drags in every unrelated PR merged since the
69
+last tag. For a scoped patch, never branch off `development`. Instead:
70
+
71
+1. Branch `release/v<version>` off the **previous tag** (`git checkout -b
72
+ release/v<version> v<previous>`), not off `development`. The tag already
73
+ points at the right `main` merge commit.
74
+2. `git cherry-pick` exactly the wanted commit(s). Prefer the feature/squash
75
+ commit (the merge commit's second parent) over the merge commit itself.
76
+ Resolve conflicts to keep the scope minimal.
77
+3. Apply the version bump and changelog edits (promote the cherry-picked
78
+ `## Unreleased` bullets into the `## <version>` section), then commit `Release
79
+ v<version>`.
80
+4. **Audit the scope before going further:** `git log --oneline
81
+ v<previous>..release/v<version>` must show only the cherry-picks plus the
82
+ release commit, and `git diff --stat v<previous>..release/v<version>` must be
83
+ the wanted source/test changes plus the three release-metadata files
84
+ (`Cargo.toml`, `Cargo.lock`, `CHANGELOG.md`) — nothing else.
85
+5. Merge `release/v<version>` into `development` (so the version bump and the
86
+ promoted changelog entry are not lost), then merge `development` into `main`
87
+ and tag `v<version>` on that `main` merge commit, exactly as in the normal
88
+ flow. The `development` merge may be a no-op for the cherry-picked source if
89
+ it was already there; that is expected.
90
+
91
+Decide up front which case you are in and confirm the exact PR list with the
92
+user. If in doubt about whether a release is "everything on `development`" or a
93
+scoped patch, ask — the two flows start from different base commits and are not
94
+interchangeable.
95
+
96
## Typical files to inspect
97
98
- `Cargo.toml`
@@ -80,6 +118,7 @@ Pushing the `v*.*.*` tag is what fires every release workflow, so create and pus
118
- `pypi/pyproject.toml` still uses dynamic versioning unless there is a deliberate packaging change.
119
- Release workflows still derive their version from the tag as expected.
120
- Git flow followed: bump committed on `release/v<version>`, merged back to `development`, then `development` merged into `main`, with `v<version>` tagged on the `main` merge commit.
121
+- Scope matches intent: for a scoped patch/hotfix, `release/v<version>` is branched off the **previous tag** and carries only the cherry-picked PR(s) plus the release-metadata bump — confirmed with `git log --oneline v<previous>..release/v<version>` and `git diff --stat v<previous>..release/v<version>` — not everything that landed on `development` since the last tag.
122
- Release notes or changelog entries match the actual changes.
123
- CI-equivalent local checks pass for the relevant platform or target.
124
- Package names, install commands, and branding stay consistent across npm, PyPI, crates.io, Homebrew, NuGet, Scoop, winget, AUR, and the `.deb`/`.rpm` packages.