name: release description: Cut a release of the onde-ed Rust workspace. Covers version bumping, the release branch/PR flow, tagging, and the two tag-triggered GitHub Actions (crates.io publish and Swift XCFramework). Use when asked to create, cut, or publish a release. allowed-tools: Read, Write, Edit, Glob, Grep, Bash
user-invocable: true
Skill: Release
What This Skill Covers
How to cut a release of the onde-ed Cargo workspace: bumping the version,
landing it through the branch/PR flow, tagging, and what the two tag-triggered
workflows do automatically afterwards.
The one-number rule
The whole workspace releases on one version. Every crate declares
version.workspace = true, so a release changes exactly one source of truth:
the root Cargo.toml.
[workspace.package]
version = "X.Y.Z"
Plus the internal path dependencies in the same file, which pin the version explicitly:
ed-agent = { version = "X.Y.Z", path = "crates/ed-agent" }
ed-mcp = { version = "X.Y.Z", path = "crates/ed-mcp" }
ed-acp = { version = "X.Y.Z", path = "crates/ed-acp" }
ed-acp-tui = { version = "X.Y.Z", path = "crates/ed-acp-tui" }
ed-acp-testkit = { version = "X.Y.Z", path = "crates/ed-acp-testkit" }
ed-onde-account = { version = "X.Y.Z", path = "crates/ed-onde-account" }
Bump all of these together. The crate manifests under crates/*/Cargo.toml
need no edits.
Versioning
Semver. Given the current X.Y.Z:
- patch (Z+1) — bug fixes, internal changes, no API additions.
- minor (Y+1, Z=0) — backwards-compatible API additions.
- major (X+1, Y=Z=0) — breaking changes.
Step-by-step
The base branch is development; main is the promoted/stable branch.
Releases land on development first, get tagged, then development is promoted
to main.
1. Branch off development
git checkout development && git pull
git checkout -b release/X.Y.Z
2. Bump the version
Edit the root Cargo.toml ([workspace.package] version and the internal
ed-* path-dependency versions). A quick way, run from the repo root:
sed -i '' 's/OLD\.VER\.SION/X.Y.Z/g' Cargo.toml
3. Refresh the lockfile and verify
cargo check --workspace # updates Cargo.lock, catches breakage
cargo fmt --all -- --check, cargo test --locked --workspace, and
cargo clippy --locked --workspace --all-targets -- -D warnings must all pass —
the release workflow re-runs them and fails the publish otherwise.
4. Commit and push
git add Cargo.toml Cargo.lock
git commit -m "Release X.Y.Z: bump the workspace"
git push
Commit subject convention: Release X.Y.Z: bump the workspace.
5. Open the release PR → development
gh pr create --base development --head release/X.Y.Z \
--title "Release X.Y.Z" --body "..."
gh pr edit <n> --add-assignee <you> --add-reviewer <reviewer>
6. Merge, then tag the merge commit
After approval, merge the PR, update local development, and tag the merge
commit (this is what every historical release tag points at):
gh pr merge <n> --merge
git checkout development && git pull
git tag vX.Y.Z <merge-sha>
git push origin vX.Y.Z
The tag name carries a
vprefix (vX.Y.Z); the workspace version does not (X.Y.Z). The workflows strip thevwhen comparing, so they must match on the numeric part.
7. Promote development → main
Open a second PR to bring main up to the tagged state:
gh pr create --base main --head development --title "Merge development → main (vX.Y.Z)"
Merging it runs ci.yml on main as a final green check.
What the tag triggers
Pushing a vX.Y.Z tag fires two workflows. Both start with a preflight
job that validates the tag matches the ed-agent version in Cargo.toml, then
runs fmt + test + clippy. If the version and tag disagree, the release fails
here — this is the safety net for step 6.
release-sdk-rust.yml → crates.io
- Dry-runs the workspace publish with
cargo-workspaces(plaincargo publish --dry-runcan't resolve the inter-crate path deps post-package). - Publishes crates in dependency order to crates.io.
cargo workspaces plan --skip-publishedmakes re-runs safe: a run that dies mid-publish only publishes the crates still missing from the registry.
release-sdk-swift.yml → XCFramework + ed-swift
- Builds the
EdFramework.xcframeworkfor Apple targets (~2h20m build; not cancel-in-progress — killing it leaves half-published state). - Creates a GitHub Release with the xcframework zip + checksum as assets.
- Checks out
ondeinference/ed-swift, rewritesPackage.swiftwith the new release URL + checksum, copies the generateded_agent_ffi.swift, commits, pushes toed-swiftmain, and tags itvX.Y.Z.
Manual / recovery runs
Both workflows have a workflow_dispatch with a publish boolean and a
release_tag input. Use this to re-publish an existing tag if a run failed
after tagging — e.g. the crates.io publish succeeded but the Swift build timed
out. Point it at the existing vX.Y.Z tag; the crates.io re-run skips anything
already on the registry.
Toolchain
The Rust toolchain is pinned in rust-toolchain.toml (currently 1.94.0).
Workflows read channel from it, so a toolchain bump is a normal source change,
not release-time config.
Checklist
- On a
release/X.Y.Zbranch offdevelopment. - Root
Cargo.toml:[workspace.package] version+ alled-*path deps bumped. -
cargo check --workspacerun (Cargo.lock updated). - fmt / test / clippy all green locally.
- Commit
Release X.Y.Z: bump the workspace. - PR →
development, reviewed, merged. -
vX.Y.Ztag on the merge commit, pushed. -
development→mainPR opened/merged. - Both tag workflows green (crates.io + Swift).