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.