Distribution & Release Runbook
How AoA is intended to ship: Docker images on GHCR plus scoped npm packages, automated through GitHub Actions and gated by post-publish smoke tests.
Current status (2026-07-20): no MeteoriteLabs @armyofagents/*
package is available from the public npm registry. The release workflow is
disabled, release PR #227 closed without merging, and its post-publish smoke
job did not run. Source checkout is the supported installation path until a
release is published and the exact install command passes a clean-container
smoke test.
Decision locks (Phase H)
Artifact destinations
- Docker:
ghcr.io/${{ github.repository }}:<tag>. A default-branch push publisheslatestand the gitsha. A deliberately createdv*tag also activates{{version}}(for example0.1.0) and{{major}}.{{minor}}(for example0.1). - NPM (configured, not yet published): public
@armyofagents/*workspace packages on npmjs.org, including the intended@armyofagents/clipackage that provides theaoabinary. The local release script derives the owned package set from non-private@armyofagents/*pnpm workspaces; it excludes private workspaces.
${{ github.repository }}. A future owner or npm scope change requires a separate release decision.
Required secrets
Configured in GitHub repo Settings → Secrets and variables → Actions:
GHCR push uses
GITHUB_TOKEN with packages: write permission — no extra secret needed.
Release runbook (Changesets flow)
-
Developer creates a
.changeset/*.mdfile:Pick affected packages, bump type (patch / minor / major), write a one-line description. -
PR merges to main (or current porting branch). The Changesets action in
release.ymlopens or updates a “Version Packages” PR aggregating all unprocessed.changeset/*.mdfiles. That PR contains thepackage.jsonversion bumps + generatedCHANGELOG.mdentries. -
Reviewing + merging the Version Packages PR retriggers
release.yml. The Changesets action invokespnpm changeset publish, which publishes each public package to npmjs.org and creates per-package tags such as@armyofagents/cli@0.2.8(plus package-specific GitHub releases). -
docker.ymlalso runs for the merge push tomain. Multi-arch buildx (amd64 + arm64) publisheslatestandshatags to GHCR. Its version andmajor.minorpatterns activate only for a separatev*tag; Changesets does not create that repository-level tag automatically. Do not claim a versioned GHCR image exists unless av*tag was deliberately created and the corresponding Docker run succeeded. -
After a successful publish,
release-smoke.ymlruns as thepost-publish-smokejob inrelease.yml(gated onchangesets/actionpublished == 'true'). It is configured to pull@armyofagents/cli@latestinside a freshly-built smoke Docker image and run the complete Playwright release-smoke project. Until that package exists, this lane cannot validate a release. CI cannot automate a real Google account, so the founder-entry scenario uses the explicit local identity, saves a profile, creates an organization, and verifies health before the environment filesystem probe. Separate scenarios exercise scoped memory through Tasks and Discussions. Diagnostics are uploaded as therelease-smoke-post-publishartifact and retained for 14 days.
scripts/release.sh remains as a local-only escape hatch for one-shot bumps outside CI. NOT invoked by the workflow.
Rollback runbook
npm deprecateeach package returned by the shared owned-workspace package discovery at that package’s current manifest version with a message (default:"Reverted by rollback-latest.sh on <ISO timestamp>"; override with--message <text>). This surfaces a deprecation warning on subsequent installs and does not unpublish.- Delete local + remote git tag
v<current_version>. - Optional (
--revert-commit):git revert --no-edit HEADif HEAD subject matcheschore: release v<current_version>. Creates a new commit; does NOT rewrite history.
Manual release-smoke (canary)
release-smoke.yml is wired to release.yml only for the published-stable path. To smoke a canary or re-run smoke against any published version:
GitHub → Actions → “Release Smoke” workflow → “Run workflow” → pick:
aoa_version:canary(latest canary dist-tag) orlatest(stable)host_port: defaults to3232artifact_name: defaults torelease-smoke
Local Docker testing
Before pushing release-affecting changes:docker:smoke requires a working docker daemon and pulls from npm — won’t work against unpublished local changes. Use it after a canary publish to verify the published artifact end-to-end.
SemVer vs CalVer
AoA uses SemVer; the upstream project uses CalVer. First AoA version is0.1.0, signaling “pre-1.0 evolving — APIs may change between minors.” Bump rules:
- patch (0.1.0 → 0.1.1): bug fixes, no API changes
- minor (0.1.0 → 0.2.0): backward-compatible features (relaxed pre-1.0 — minors may include API changes)
- major (0.1.0 → 1.0.0): API breaking changes; 1.0 declares stability commitment
Known gaps / Phase I follow-ups
- Repository owner or npm scope change — image destination follows
${{ github.repository }}; an npm scope change needs a separate Changesets-driven publish. - Canary auto-wiring — release-smoke.yml exposes
workflow_callbutrelease.yml’spost-publish-smokeonly fires on stable publish. Canary stays manual. - Desktop installer (Electron/Tauri) — out of Phase H per H.D1; separate phase.
- Expanded smoke coverage (H.D6) — the founder-entry scenario stops at the environment step because continuing performs a real container filesystem probe and later verifies a local Commander CLI. Other scenarios already cover scoped memory through Tasks and Discussions. A future lane can supply the container-specific founder fixtures and add MCP inbound, budget, and artifact coverage.
- GHCR image signing (cosign) — Phase I+ security hardening.
- arm/v7 Docker support — tied to Phase I.12 Pi-local adapter.
- Release notes automation (parse conventional commits) — Phase I.
compute_next_version+list_public_package_info+set_public_package_versioninrelease-lib.sh— dead code since H.2-part-2 (release.shport) was SKIPPED (Changesets handles versioning). Decide in Phase I cleanup: delete vs. keep as reference.- Package ownership — release and rollback share workspace discovery and
include only public packages in the
@armyofagents/*scope. The private private workspaces are outside the publish graph.