io-harness 0.23.0

An embeddable agent runtime for Rust: any task, any provider, in your own process. Run commands, edit files and search a repository under a layered permission boundary on files, commands and network; gate the result on the project's own test command in any language, or on nothing at all; and keep a full SQLite trace of every step, refusal and budget draw. With an execution sandbox, contained sub-agents, an MCP client, and durable resume for unattended runs.
Documentation
# Release Process — IO Harness

This is the same across every [initorigin](https://github.com/initorigin) repo so
releases look and work the same everywhere.

## Branches

- **`develop`** — integration branch. All feature work merges here first.
- **`feat/<version>`** — work branch for a version (for example `feat/0.1.0`),
  cut from `develop`, merged back into `develop` by PR.
- **`main`** — released versions only. Nothing lands here except a
  `develop``main` release PR.

## Versioning

[Semantic Versioning](https://semver.org/spec/v2.0.0.html): `MAJOR.MINOR.PATCH`.
Pre-1.0.0, minor versions may include breaking changes; they are always noted in
the CHANGELOG. The public surface governed by this is defined in
[CONTRACT.md](CONTRACT.md).

## Steps to cut a release

1. On `develop`, confirm the work for the version is complete and the
   `## [Unreleased]` section of [CHANGELOG.md]../CHANGELOG.md is accurate.
2. Rename `## [Unreleased]` to `## [X.Y.Z] - YYYY-MM-DD` and open a fresh
   `## [Unreleased]` block above it, following
   [CHANGELOG_STRUCTURE.md]CHANGELOG_STRUCTURE.md.
3. Open a **`develop``main`** pull request titled `release: vX.Y.Z`.
4. After review and merge, tag `main` as `vX.Y.Z`.
5. Create the **GitHub Release** for `vX.Y.Z`. Its notes are taken **verbatim
   from the `## [X.Y.Z]` section of the CHANGELOG** — do not rewrite them.
6. Publish to crates.io. This is **last**, after both merges and the Release
   exist, because it is the one step that cannot be undone.
7. Record the release in the UltraShip release record for this product.
8. Sync `develop` with `main` (`git merge --ff-only main`), so the two do not
   diverge.

## Steps 4–5, by workflow

[`.github/workflows/release.yml`](../.github/workflows/release.yml) does steps 4
and 5. There are two ways to start it, and they differ only in which one creates
the tag:

- **Push a `v*` tag.** The tag names the version and the Release is cut from the
  commit it points at. `git tag vX.Y.Z && git push origin vX.Y.Z`.
- **Run it from the Actions tab** (or `gh workflow run release.yml --ref main -f
  version=X.Y.Z`), giving the version with no leading `v`. The workflow creates
  the tag itself, pinned to the commit that passed the gate.

Either way the same checks run first. It runs the gate CI runs — `fmt`,
`clippy --all-features`, the three test invocations, `cargo package --locked` —
against the exact commit being released, then cuts the Release with the CHANGELOG
section as its notes. It refuses to start when the commit is not on `main`, when
`Cargo.toml` declares a different version, when the Release already exists, or
when the CHANGELOG has no section to quote.

The "must be on `main`" check asks whether the *commit* is an ancestor of
`main`, not whether the ref is `main` — the same question, and the only form of
it that can be asked of a tag.

**Step 6 is not in the workflow and must not be added to it.** `cargo publish`
is run by hand, from a checkout of `main`, after the Release exists — always the
last thing that happens. It is the one step of a release that cannot be
recalled: a version can never be re-uploaded, and the only remedy is a forward
patch plus `cargo yank`. A workflow that *could* publish is a workflow that can
publish by mistake, so it holds no registry token and needs no environment.

The workflow changes what is typed, not what is decided: a human still decides
the version is ready and presses the button, and steps 1–3 and 6–8 stay by hand.

## Why the CHANGELOG drives release notes

One source, no drift: what contributors write during development becomes the
release notes with no re-authoring. That only works if CHANGELOG entries are
user-facing and complete, so treat every entry as release copy.