# ADR 0003 — Build and release model - Status: Accepted - Date: 2026-07-05 ## Context ADR 0002 makes this repository a published package. Publishing needs a repeatable, auditable build and release process that does not depend on long-lived credentials and that produces artifacts consumers can pin. ## Decision - **Build backend:** `pyproject.toml` (PEP 621 metadata) with **hatchling**. Runtime dependency: `PyYAML`. Package data (schemas, template, oracle, contract version) is declared so it ships in the sdist and wheel. - **Versioning:** the package uses **Semantic Versioning** (`MAJOR.MINOR.PATCH`). This is distinct from the pack **contract version** (a separate integer + digest the package carries and the tools enforce); a package release notes which contract version it ships. Pre-1.0 (`0.y.z`) makes no backward-compatibility promise. - **Console entry points:** `aces-pack-validate`, `aces-pack-release`, `aces-new-pack`, `aces-pack-issue-skeleton`. - **Changelog:** fragment-based via `changelog.d/` (towncrier categories), collated into `CHANGELOG.md` at release time. No direct `CHANGELOG.md` edits. - **Release trigger:** pushing a `v..` tag runs the release workflow, which builds the sdist + wheel, generates the SBOM (ADR 0004), publishes to **PyPI via OpenID Connect trusted publishing** (no API tokens stored in the repository), and cuts a **GitHub Release** carrying the wheel, sdist, and SBOM. - **CI (every PR/push):** runs the unit tests and the content/release gates (`aces-pack-validate`, `aces-pack-release check --all`) so `main`/`dev` stay releasable. Releases are cut from `main`. ## Consequences - No secret PyPI token lives in the repository; publish authorization is the OIDC trust relationship between GitHub and PyPI. - A release is reproducible from a tag and leaves a durable, downloadable record (GitHub Release + PyPI) with the SBOM attached. - Consumers pin `aces-scenario-packs==X.Y.Z` (or a compatible range) and upgrade deliberately.