chore: add release skill to .agents/skills
Add the end-to-end release runbook for onde-cli: version-bump surfaces, the release/vX.Y.Z -> development -> main flow with the tag on the final main merge commit, the signing requirement, and the post-push back-merge check. Includes evals covering the previously seen failure modes (fast-forwarded main, unsigned bump commits, a failed crates.io verify). Co-Authored-By: siGit Code v1.6.7-acp <noreply@sigit.si> Co-Authored-By: SplitFire v1.1.1-acp <noreply@splitfire.ai>
Seto Elkahfi committed
Oct 13, 2026 at 12:05 UTC
caff1839215055abd07ee6cbccfb71450dda6de0
2 files changed
+184
.agents/skills/release/SKILL.md
new
+149
@@ -0,0 +1,149 @@
1
+---
2
+name: release
3
+description: Use whenever cutting, preparing, tagging, or publishing an onde-cli release — version bumps, release branch, merges, tagging, pushing to trigger the publish pipeline, and verifying it landed. Also use when a release went wrong (wrong tag target, failed crates.io verify, development left behind main, unsigned release commits) and the repo state needs repair. Trigger even if the user only says "release vX.Y.Z", "bump the version", "tag a release", or "publish the new version".
4
+user-invocable: true
5
+---
6
+
7
+# Release skill
8
+
9
+End-to-end release procedure for `onde-cli`. Complements the git skill (merge rules)
10
+and the distribution skill (channel details) — this skill is the concrete runbook.
11
+
12
+## Decide the version
13
+
14
+- Look at `git tag -l 'v*' --sort=-v:refname | head -1` for the latest release.
15
+- Look at the commits since (`git log v<latest>..development --oneline`).
16
+ Fixes and chores only → patch bump. New user-facing features → minor bump.
17
+- Check for an abandoned `release/vX.Y.Z` branch — its version is usually the
18
+ intended next one. If it exists, inspect it (`git log development..release/...`)
19
+ before deciding to reuse or delete it; do not blindly `branch -D` without looking,
20
+ and never reuse a branch whose commits were made unsigned or by the wrong identity.
21
+
22
+## Version bump surfaces
23
+
24
+These files pin the crate version and must all move together:
25
+
26
+- `Cargo.toml` — `version = "X.Y.Z"` in `[package]`
27
+- `pub/onde_cli/pubspec.yaml` — `version: X.Y.Z`
28
+- `server.json` — three occurrences: top-level `version`, and the npm and NuGet
29
+ `packages[].version` entries (search for the old version string to catch all)
30
+
31
+`docs/mcp-registry.md` and `.github/workflows/release-mcp-registry.yml` mention
32
+past versions only as historical examples — do not bump those.
33
+
34
+The npm wrapper manifests are NOT bump targets: the committed `package.json` files
35
+are rewritten at release time by `npm/scripts/render-*.cjs` from the tag.
36
+
37
+After editing, run `cargo check --locked` (or let the build update `Cargo.lock`)
38
+so the lockfile carries the new version, and commit it in the same bump commit.
39
+
40
+## Sequence
41
+
42
+Follow the git skill's branch flow — `release/vX.Y.Z → development → main`,
43
+`--no-ff` at every hop, tag on the final `main` merge commit. Concretely:
44
+
45
+```bash
46
+git checkout development
47
+git pull <remote> development # start from the pushed tip
48
+git checkout -b release/vX.Y.Z
49
+# ... edit the bump surfaces ...
50
+git commit -am "Prepare vX.Y.Z" # signed, correct identity (see below)
51
+git checkout development
52
+git merge --no-ff release/vX.Y.Z -m "Merge release prep for vX.Y.Z"
53
+git checkout main
54
+git pull <remote> main
55
+git merge --no-ff development -m "Merge development for vX.Y.Z"
56
+git tag vX.Y.Z
57
+git push <remote> development main vX.Y.Z
58
+git branch -d release/vX.Y.Z # only after the merge lands
59
+```
60
+
61
+The remote here is the one whose URL is the sigit.si or GitHub org repo —
62
+check `git remote -v`; this repo is commonly cloned with per-account remotes
63
+(`gh-setoelkahfi`, `gh-paydii`, `gh-keypair34`) rather than `origin`.
64
+
65
+### What a good result looks like
66
+
67
+- The tag sits on the step-3 merge commit on `main` (`git log --graph main`
68
+ shows a merge commit directly above the previous release).
69
+- `git log development..main` and `git log main..development` are both empty
70
+ after the merges — the two branches carry identical trees.
71
+- Never tag a release-branch tip or a bare bump commit on `main`; if the work
72
+ somehow already landed on `main` linearly, follow the git skill's fallback
73
+ (normal commit, tag it) rather than rewriting history.
74
+
75
+### Post-push back-merge check
76
+
77
+If anything reached `main` without passing through `development` first (hotfix,
78
+manual push, a fast-forwarded release), bring it back immediately:
79
+
80
+```bash
81
+git checkout development
82
+git merge --no-ff main -m "Merge main for vX.Y.Z"
83
+git push <remote> development
84
+```
85
+
86
+A release is not done until the two branches contain the same tree.
87
+
88
+## Commits and signatures — read the git-commit-signing skill first
89
+
90
+Release commits must be GPG-signed by the maintainer identity that GitHub can
91
+verify (this repo: `Seto Elkahfi <1797197+setoelkahfi@users.noreply.github.com>`,
92
+EDDSA key `2B76DF0F04014E36`). The `gh` CLI's active account is independent of
93
+git config — set both, and verify before pushing:
94
+
95
+```bash
96
+git log -1 --format='%an <%ae> sig:%G? %GK' # want sig:G and the right key
97
+gh api repos/<owner>/<repo>/commits/<sha> --jq .commit.verification.verified
98
+```
99
+
100
+Every `git commit` and `git merge` in this flow creates a commit — configure
101
+signing so merges are signed too, or amend unsigned ones before pushing
102
+(`git commit --amend --no-edit -S`, only on unpushed commits).
103
+
104
+Commit trailer: end release-related commit messages with
105
+
106
+```
107
+Co-Authored-By: siGit Code v1.6.7-acp <noreply@sigit.si>
108
+```
109
+
110
+## The tag push is the release
111
+
112
+Pushing `vX.Y.Z` triggers `release-crates.yml`, which verifies the tag against
113
+`Cargo.toml` and `pubspec.yaml`, publishes the crate, then dispatches the
114
+wrapper workflows (GitHub Releases, npm, NuGet, PyPI, then Homebrew and pub.dev
115
+after the GitHub Release assets exist). There is no separate "publish" step.
116
+
117
+Watch it land:
118
+
119
+```bash
120
+gh run list --branch vX.Y.Z
121
+gh run watch <run-id> --exit-status
122
+```
123
+
124
+`CI` also runs on the tag push; both should be green. If `release-crates` fails,
125
+no wrapper publishes — fix the cause, move the tag only if it has not published
126
+anything yet (crates.io versions are immutable; a failed verify is safe to retry,
127
+a published crate is not).
128
+
129
+## Verify
130
+
131
+After the pipeline finishes, spot-check the fan-out (all idempotent, safe to re-check):
132
+
133
+- crates.io: `cargo search onde-cli --limit 1`
134
+- GitHub Release: `gh release view vX.Y.Z`
135
+- npm: `npm view onde-cli version`
136
+- PyPI: `https://pypi.org/pypi/onde-cli/json` → `info.version`
137
+- NuGet: flat container index for `onde-cli`
138
+- Homebrew/pub.dev trail the GitHub Release; they may take a few extra minutes
139
+
140
+## Failure modes seen before
141
+
142
+- Fast-forwarding `main` to the bump commit and tagging it — leaves no merge
143
+ commit, and leaves `development` behind. Back-merge `main` into `development`
144
+ right away and prefer merge commits next time.
145
+- Deleting a leftover `release/` branch that contained unsigned bump commits and
146
+ redoing the bump fresh — fine, but check it first.
147
+- Forgetting `Cargo.lock` in the bump commit.
148
+- Pushing with the wrong `gh` account active — the push works, but PR/issue
149
+ actions afterwards get attributed to the wrong identity.
.agents/skills/release/evals/evals.json
new
+35
@@ -0,0 +1,35 @@
1
+{
2
+ "skill_name": "release",
3
+ "evals": [
4
+ {
5
+ "id": 1,
6
+ "prompt": "Cut release v0.4.3 for onde-cli. Bump all version pins, follow the repo's release branch flow, tag, and push.",
7
+ "expected_output": "Agent bumps Cargo.toml, pubspec.yaml, server.json (3 spots), commits signed with Co-Authored-By trailer, creates release/v0.4.3 from development, merges --no-ff into development then main, tags the main merge commit, pushes development+main+tag, and watches the release pipeline.",
8
+ "files": []
9
+ },
10
+ {
11
+ "id": 2,
12
+ "prompt": "We fast-forwarded main to the version bump commit by mistake and tagged it. development is now behind main. Fix the repo state without rewriting pushed history.",
13
+ "expected_output": "Agent recognizes the git skill's rule (tag belongs on a merge commit; development must carry the release state) and back-merges main into development with --no-ff instead of rewriting main or deleting the pushed tag.",
14
+ "files": []
15
+ },
16
+ {
17
+ "id": 3,
18
+ "prompt": "The v0.4.2 tag push failed the crates.io verify step because pubspec.yaml still said 0.4.1. Nothing was published. Walk me through fixing it and re-releasing.",
19
+ "expected_output": "Agent fixes the pubspec version on a new release branch or hotfix, re-runs the release flow, deletes and recreates the tag only if crates.io never published, and explains why crates.io versions are immutable so a published 0.4.2 would require 0.4.3 instead.",
20
+ "files": []
21
+ },
22
+ {
23
+ "id": 4,
24
+ "prompt": "Update the README install instructions for the npm wrapper and fix the NuGet README badge that points at the wrong package id.",
25
+ "expected_output": "Should NOT deeply engage the release skill beyond reading it; this is distribution/README work. Agent edits npm/onde-cli/README.md and nuget/onde-cli/README.md without cutting a release, bumping versions, or tagging.",
26
+ "files": []
27
+ },
28
+ {
29
+ "id": 5,
30
+ "prompt": "Merge the feature/lora-scheduler branch into development.",
31
+ "expected_output": "Should NOT trigger the release skill; this is a normal feature merge governed by the git skill (--no-ff into development, no tag).",
32
+ "files": []
33
+ }
34
+ ]
35
+}