| name | chatto-release-checklist |
| description | Run before making a new Chatto release. Compares the candidate version with stable and prerelease baselines, writes a developer checklist and separate user-facing announcement to .context/, and reports API changes separately. |
Chatto Release Checklist
Use this skill when preparing, reviewing, or announcing a new Chatto release.
This is a pre-release review workflow. Do not create tags, edit GitHub releases, push, or publish artifacts unless the user explicitly asks for that after seeing the checklist.
Inputs
- Candidate version: prefer the version named by the user. Otherwise query release-please first:
- Look for an open release-please PR targeting the relevant branch and use the version in its title, branch, body, or changed version files.
- Read
.release-please-config.json and .release-please-manifest.json to understand the current release-please version, release type, prerelease settings, tag format, changelog path, and extra version files.
- If no release-please PR exists, infer the next version from the manifest/config and Conventional Commit messages since the last release tag. State that the version is inferred, not release-please-confirmed.
- Only then fall back to
cli/version.go, frontend/package.json, or the current git tag.
- Candidate ref: prefer the ref named by the user. Otherwise use the open release-please PR head ref when one exists; if there is no release-please PR, use
HEAD on the target branch/release candidate branch.
- Stable baseline: use the newest stable tag matching
v[0-9]*.[0-9]*.[0-9]* with no prerelease suffix. Ignore tags like v0.4.0-beta.2 for this baseline.
- Prerelease baseline: when the candidate is a prerelease, also find the newest earlier prerelease tag in the same release line, such as
v0.4.0-beta.2 for 0.4.0-beta.3. Use this for beta-user and API compatibility notes.
Useful commands:
gh pr list --state open --json number,title,headRefName,baseRefName,url,body,labels,author \
--jq '.[] | select((.title | test("release"; "i")) or (.headRefName | test("release-please|autorelease"; "i")) or ([.labels[].name] | any(test("release-please|autorelease"; "i"))))'
gh pr view <release-pr-number> --json number,title,url,body,headRefName,baseRefName,files
jq . .release-please-config.json
jq . .release-please-manifest.json
git tag --list 'v[0-9]*.[0-9]*.[0-9]*' --sort=-v:refname | grep -Ev -- '-' | head -1
git tag --list 'v<major>.<minor>.<patch>-*' --sort=-v:refname | head -5
git ls-remote origin <candidate-ref-or-pr-head>
git rev-parse <candidate-ref>
git log --oneline <baseline>..<candidate-ref>
git log --first-parent --merges --pretty=format:'%h %s' <baseline>..<candidate-ref>
git diff --stat <baseline>..<candidate-ref>
git diff --name-status <baseline>..<candidate-ref> -- proto/chatto/auth/v1 proto/chatto/discovery/v1 proto/chatto/api/v1 proto/chatto/admin/v1 proto/chatto/realtime/v1 proto/chatto/core cli/internal/connectapi cli/internal/http_server/realtime.go packages/api-types apps/frontend/src/lib/api-client/server.ts apps/frontend/src/lib/state/server
gh pr view <number> --json number,title,url,body,mergedAt
If the candidate version already has a tag, compare <baseline>..<candidate-tag>. If an open release-please PR exists, compare <baseline>..<release-pr-head-ref>. Otherwise compare <baseline>..HEAD and clearly say the report is for the current release candidate state.
Workflow
- Confirm the range:
- Identify candidate version, candidate ref, stable baseline tag, prerelease baseline tag when applicable, and whether the candidate is stable or prerelease.
- Record the source of the candidate version: user-provided, open release-please PR, release-please config/manifest inference, version file fallback, or tag fallback.
- When using release-please inference, respect
.release-please-config.json settings such as release-type, versioning, prerelease, prerelease-type, include-v-in-tag, and include-component-in-tag.
- Record source freshness: release-please PR number, base branch, head ref, head SHA, fetch time/date, and whether the local reviewed ref matches the remote PR head SHA.
- Note if the candidate version is older than, equal to, or newer than the stable baseline version.
- If the candidate is a stable release and a newer stable tag already exists, stop and ask the user how to proceed.
- Gather release context:
- Inspect commits and merged PRs between the stable baseline and candidate. When a prerelease baseline exists, also inspect the narrower prerelease-baseline-to-candidate range for beta-specific compatibility notes.
- Read
CHANGELOG.md for generated release-please content in the candidate range.
- Check relevant FDRs/ADRs when a change is user-facing or architectural enough that the announcement would otherwise be guesswork.
- Build an evidence map that links major announcement bullets to PRs, commits, or docs. Keep this map in the developer checklist, not the announcement.
- Review API changes separately:
- Use
chatto-api-compatibility for every public API or protocol change and carry its temporal compatibility classification into the checklist.
- Public ConnectRPC/protobuf API: inspect diffs under
proto/chatto/{auth,discovery,api,admin}/v1/, generated TypeScript under packages/api-types/src/chatto/, generated Go under cli/internal/pb/chatto/{auth,discovery,api,admin}/v1/, and generated docs under apps/docs-website/src/content/docs/reference/connectrpc-api/.
- Persisted protobuf/event shapes: inspect the lifecycle packages under
proto/chatto/core/ and call out higher-risk persisted EVT, NOTIFICATIONS, RUNTIME_STATE, and ENCRYPTION_KEYS compatibility changes. When these files change, read proto/AGENTS.md, proto/chatto/core/AGENTS.md, and use guidance. Check removed fields, reused tags/oneof numbers, reserved or retired tags, replay compatibility, and old self-hosted records.
The announcement file must speak only to users, self-hosters, admins, and client developers. Do not include maintainer-only readiness status, blockers, source freshness, commands, PR evidence, uncertainty, or internal review notes in the announcement. If the developer checklist has blockers, still write the announcement as a draft but mark only the developer checklist as not ready.
Developer Checklist Format
Use this Markdown structure:
# Chatto <version> Release Checklist
Compared stable baseline `<stable-baseline>` to `<candidate-ref>` on <YYYY-MM-DD>.
Prerelease baseline: `<prerelease-baseline-or-none>`.
## Release Readiness
- Status: <Ready | Needs review | Blocked>
- Release blockers: <None | concise blocker list>
- Manual checks: <concise manual verification list>
- Recommendation: <publish / resolve blockers first / review announcement only>
## Source Freshness
- Candidate version source: `<source>`
- Release-please PR: <number/url or none>
- Release-please base/head: `<base>` / `<head>`
- Reviewed SHA: `<sha>`
- Remote head SHA: `<sha>`
- Freshness result: <matches remote | | , >
Stable self-hosters upgrading from :
Beta users upgrading from :
Retired legacy API clients:
ConnectRPC clients:
Realtime websocket clients:
Operators using Docker Compose:
Operators using clustered replicas:
Public protobuf source changed:
Generated Go protobuf/Connect files changed:
Generated TypeScript protobuf/Connect files changed:
Generated ConnectRPC docs changed:
Retired legacy API compatibility changed:
Codegen/drift check present:
Path:
Status:
:
Stable baseline tag:
Prerelease baseline tag:
Candidate version/ref: /
Candidate version source:
Commits reviewed:
PRs reviewed:
Commands:
[ ] Release blockers are resolved or explicitly accepted.
[ ] Breaking or upgrade notes are reflected in release notes and PR title/body when needed.
[ ] Public protobuf changes have generated outputs and docs.
[ ] API documentation is current when ConnectRPC, realtime websocket, or retired legacy API compatibility behavior changed.
[ ] Announcement wording has been reviewed by a human before publishing.
Announcement Format
Write this structure to .context/release-announcement-<version>.md:
# Chatto <version>
<A short human-facing opening paragraph suitable for users, admins, self-hosters, and client developers. Keep it concise and concrete. Qualify "new" or "first" claims as "since <stable-baseline>" or "for beta users" when needed.>
### New Features
- <New capability or workflow. Say "None." if there are no user-facing features.>
### Changes
- <Changed behavior, polish, performance, docs, or operational improvements. Say "None." if >
Keep announcement wording user-facing. Avoid maintainer-only phrases like "confirm this before publishing", "drift check", "PR #...", "candidate ref", "blocked", or "internal-only" in the announcement file.
Output
- Always tell the user the exact checklist and announcement paths.
- Summarize the candidate version, stable baseline tag, prerelease baseline tag when applicable, readiness status, and API-change classification in the final response.
- If no API changes are found, say so explicitly and mention which surfaces were checked.
- If the user later wants to update a GitHub release body, use the
chatto-release-notes skill after this checklist is reviewed.