Skip to content
commission

Release checklist

The steps to cut a commission release. Written to be run by a human or an agent, in order, top to bottom. Every step is a command or a decision with a stated answer — no step says “verify things look right”.

The compatibility promises this checklist enforces are in compatibility.md. The entries it publishes are in ../CHANGELOG.md CHANGELOG.md.

Automation status: run by hand today. relay-52 wires it into a workflow; anything below marked (manual) is a decision that stays with a human even after that lands.

0. Preconditions

  • Working tree is clean: git status --porcelain prints nothing.
  • On main, up to date with the remote.
  • No commission task for this release is still in flight: commission board --project commission shows nothing in_progress that the release is supposed to contain.

1. Decide the number (manual)

Read the ## Unreleased section of the changelog and apply compatibility.md:

  • Any entry under ### Breakingmajor.
  • Any new command, flag, endpoint, MCP tool, or config key → minor.
  • Fixes and internals only → patch.
  • Release candidates are 1.0.0-rc.N, and are held to the 1.x contracts.

A schema version bump on its own does not force a major — see the database section of the compatibility policy.

Write the number down; every later step uses it.

2. Green build

  • bun test — all pass. This includes tests/version.test.ts, which is what guarantees the number you are about to publish is reported identically by the CLI, MCP, HTTP, and package manifest.
  • bunx tsc --noEmit — clean.
  • bun run build — produces dist/commission.
  • ./dist/commission doctor on a scratch database exits 0: COMMISSION_DB=$(mktemp -d)/commission.db ./dist/commission doctor

3. Bump the version

The version lives in exactly one place: the version field in package.json. src/version.ts derives from it and every surface derives from src/version.ts. Do not edit src/version.ts, and do not add a literal anywhere else — tests/version.test.ts fails if you do.

  • Edit package.jsonversion.
  • bun test tests/version.test.ts — confirms all four surfaces moved together.

4. Close the changelog section

  • Rename ## Unreleased to ## X.Y.Z — YYYY-MM-DD.
  • Add the Schema version N · config version M line, taking the numbers from MIGRATIONS.length in src/db/ddl.ts and CONFIG_VERSION in src/config/schema.ts. GET /v1/version reports both if you would rather ask the binary.
  • Re-read every entry as someone upgrading (manual). Delete anything that reads like a commit message. Confirm each ### Breaking entry carries its migration inline.
  • Open a fresh empty ## Unreleased above it.

5. Upgrade rehearsal

This is the step that catches the mistakes the test suite cannot.

  • Take a database created by the previous release — keep one per release under ~/.commission/upgrade-fixtures/ — copy it, and check what the new binary intends to do to it before it does it: ./dist/commission migrate --check --db /tmp/upgrade.db. It exits 2 and lists exactly the migrations this release adds.
  • Run the new binary against the copy: COMMISSION_DB=/tmp/upgrade.db ./dist/commission board.
  • It migrates without error, prints the backup path and its restore command on stderr, and ./dist/commission doctor reports the expected schema level. commission migrate --check now exits 0.
  • The backup it wrote is a working database at the previous level, and the restore command it printed puts it back.
  • Task counts, statuses, and evidence match what the old binary reported.
  • If the release adds a migration: confirm it is appended, never edited in place, and that no released migration’s text changed (git diff <previous-tag> -- src/db/ddl.ts shows additions only), and that tests/migrations.test.ts has a step covering it — the suite fails if it does not.
  • A .commission.json from the previous release still validates: ./dist/commission config validate.

6. Documentation

  • bun run generate:config — regenerate the config reference; commit any diff, or confirm there is none.
  • README install instructions name the new version if they pin one.
  • If a surface changed, compatibility.md reflects it — especially a new exit code, a new enum member, or a config version bump.

7. Cut it

  • Commit: Release X.Y.Z.
  • Tag: git tag -a vX.Y.Z -m "Release X.Y.Z".
  • Push the commit and the tag.

Pushing the tag is what builds and publishes. .github/workflows/release.yml takes it from there: it builds all five platform binaries on their own runners, refuses to continue if any of them cannot run init through done on its own platform, publishes SHA256SUMS, and creates the GitHub release with this version’s changelog section as the body plus a generated table of binary sizes and measured cold-start times. How that works, and what it does and does not guarantee, is release-engineering.md.

  • Watch the run. A red leg means that platform’s binary does not work, not that CI is flaky — read the failing smoke step before re-running.
  • Confirm the release body carries the artifact table and that SHA256SUMS lists all five files.
  • Update the distribution channels (relay-52).

8. Verify what shipped

Against the published artifact, not your working tree:

  • The installed binary reports the new number: commission --version.
  • GET /v1/version on a served instance returns the same commission value.
  • The MCP handshake advertises it: serverInfo.version from commission mcp.
  • Install from a clean machine or container by following the README verbatim, and run commission init through commission done once.

9. Close the loop

  • commission done the release task with the tag as evidence: commission evidence commission-NN release=vX.Y.Z commit=<sha>.
  • Note anything that went wrong on the task. A release checklist that never changes is a release checklist nobody is following.

If a release is bad

Do not delete or move the tag — someone has already installed it.

  1. Fix forward. Cut X.Y.Z+1 with the fix, and add a ### Fixed entry naming the broken release explicitly.
  2. If the bad release corrupts data or cannot be upgraded past, say so at the top of the new release’s changelog entry, with the recovery steps.
  3. Commission never downgrades a database. If a release migrated a database and must be backed out, the recovery path is restoring a backup, and the changelog entry has to say that in those words.

This page is docs/release-checklist.md in the Commission repository, rendered in place — the site keeps no copy of it. The repository is private, so there is no edit link to follow.