ADR 0005 — Versioning and releases: tag-driven, lockstep
Status: accepted (2026-08)
Decision
- SemVer 2.0, all packages in lockstep. Every shipped package carries the same version, always. Pre-1.0, minor bumps may break; from 1.0.0, strict semver.
- Git tags are the single source of truth (MinVer,
MinVerTagPrefix=v). Tagv1.2.3→ packages build as1.2.3. Untagged commits build as the next patch with an-alpha.0.<height>suffix — unique, traceable, never impersonating a release. No version is ever written into a file. - A release is pushing a tag.
release.ymltriggers onv*, re-runs the full quality gauntlet (tests, coverage gate, AOT proof), packs, pushes to NuGet.org, and creates a GitHub release with generated notes and the packages attached. - One package carries the generator.
EmissaryembedsEmissary.SourceGeneratorsunderanalyzers/dotnet/cs; the generator does not ship standalone. Shipped packages:Emissary,Emissary.Testing,Emissary.AspNetCore,Emissary.Mcp,Emissary.Sqlite. - Release hygiene: SourceLink (SDK built-in),
.snupkgsymbol packages,EnablePackageValidation(setPackageValidationBaselineVersionafter the first stable release so pack fails on unannounced API breaks), and a pack dry-run on every CI run.
The concrete steps and gates for the first non-preview release are kept in the release checklist, including what must change in the docs at the tag and which API shapes to settle before semver freezes them.
Operational notes
- One-time setup: a NuGet.org API key scoped to
Emissary.*stored as theNUGET_API_KEYrepository secret; apply forEmissary.package-ID prefix reservation after first publish. - The
[GeneratedCode]version stamped into generated sources tracks the generator assembly version automatically. - CI checkouts use
fetch-depth: 0— MinVer needs tag history.