Genesis has three public release lanes:
- stable: published GitHub releases that publish to npm
latest - beta: prerelease tags that publish to npm
beta - dev: the moving head of
main
Version naming
- Stable release version:
YYYY.M.D- Git tag:
vYYYY.M.D
- Git tag:
- Stable correction release version:
YYYY.M.D-N- Git tag:
vYYYY.M.D-N
- Git tag:
- Beta prerelease version:
YYYY.M.D-beta.N- Git tag:
vYYYY.M.D-beta.N
- Git tag:
- Do not zero-pad month or day
latestmeans the current promoted stable npm releasebetameans the current beta install target- Stable and stable correction GitHub releases publish to npm
latestautomatically when the GitHub release is published - Every stable Genesis release ships the npm package and macOS app together; beta releases normally validate and publish the npm/package path first, with mac app build/sign/notarize reserved for stable unless explicitly requested
Release cadence
- Releases move beta-first
- Stable follows only after the latest beta is validated
- Maintainers normally cut releases from a
release/YYYY.M.Dbranch created from currentmain, so release validation and fixes do not block new development onmain - If a beta tag has been pushed or published and needs a fix, maintainers cut
the next
-beta.Ntag instead of deleting or recreating the old beta tag - Detailed release procedure, approvals, credentials, and recovery notes are maintainer-only
Release preflight
- Run
pnpm check:test-typesbefore release preflight so test TypeScript stays covered outside the faster localpnpm checkgate - Run
pnpm check:architecturebefore release preflight so the broader import cycle and architecture boundary checks are green outside the faster local gate - Run
pnpm build && pnpm ui:buildbeforepnpm release:checkso the expecteddist/*release artifacts and Control UI bundle exist for the pack validation step - Run
pnpm release:checkbefore every tagged release - Release checks now run in a separate manual workflow:
Genesis Release Checks Genesis Release Checksalso runs the QA Lab mock parity gate plus the live Matrix and Telegram QA lanes before release approval. The live lanes use theqa-live-sharedenvironment; Telegram also uses Convex CI credential leases.- Cross-OS install and upgrade runtime validation is dispatched from the
private caller workflow
genesis/releases-private/.github/workflows/genesis-cross-os-release-checks.yml, which invokes the reusable public workflow.github/workflows/genesis-cross-os-release-checks-reusable.yml - This split is intentional: keep the real npm release path short, deterministic, and artifact-focused, while slower live checks stay in their own lane so they do not stall or block publish
- Release checks must be dispatched from the
mainworkflow ref or from arelease/YYYY.M.Dworkflow ref so the workflow logic and secrets stay controlled - That workflow accepts either an existing release tag or the current full 40-character workflow-branch commit SHA
- In commit-SHA mode it only accepts the current workflow-branch HEAD; use a release tag for older release commits
Genesis NPM Releasepublishes only from a real release tag. It runs on GitHub-hosted runners so npm trusted publishing can issue provenance through GitHub OIDC.Genesis Release ChecksrunsGENESIS_LIVE_TEST=1 GENESIS_LIVE_CACHE_TEST=1 pnpm test:live:cacheusing bothOPENAI_API_KEYandANTHROPIC_API_KEYworkflow secrets- npm release publishing does not wait on the separate release checks lane
- Run
RELEASE_TAG=vYYYY.M.D node --import tsx scripts/genesis-npm-release-check.ts(or the matching beta/correction tag) before approval - After npm publish, run
node --import tsx scripts/genesis-npm-postpublish-verify.ts YYYY.M.D(or the matching beta/correction version) to verify the published registry install path in a fresh temp prefix - The post-publish verifier retries exact-version installs and the expected npm dist-tag check for short npm registry propagation windows after publish
- After a beta publish, run
GENESIS_NPM_TELEGRAM_PACKAGE_SPEC=@pixelzx/genesis@YYYY.M.D-beta.N GENESIS_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex GENESIS_NPM_TELEGRAM_CREDENTIAL_ROLE=ci pnpm test:docker:npm-telegram-liveto verify installed-package onboarding, Telegram setup, and real Telegram E2E against the published npm package using the shared leased Telegram credential pool. Local maintainer one-offs may omit the Convex vars and pass the threeGENESIS_QA_TELEGRAM_*env credentials directly. - Maintainers can run the same post-publish check from GitHub Actions via the
manual
NPM Telegram Beta E2Eworkflow. It is intentionally manual-only and does not run on every merge. - Maintainer release automation now publishes from the GitHub release event:
- publishing a GitHub prerelease or
vYYYY.M.D-beta.Ntag publishes@pixelzx/genesis@YYYY.M.D-beta.Nto the npmbetadist-tag - publishing a stable or correction GitHub release publishes
@pixelzx/genesis@YYYY.M.Dor@pixelzx/genesis@YYYY.M.D-Nto the npmlatestdist-tag - the workflow still supports manual dispatch for recovery runs
- token-based npm dist-tag mutation now lives in
genesis/releases-private/.github/workflows/genesis-npm-dist-tags.ymlfor security, becausenpm dist-tag addstill needsNPM_TOKENwhile the public repo keeps OIDC-only publish - public
macOS Releaseis validation-only - real private mac publish must pass successful private mac
preflight_run_idandvalidate_run_id - the private mac publish path promotes prepared artifacts instead of rebuilding them again
- publishing a GitHub prerelease or
- For stable correction releases like
YYYY.M.D-N, the post-publish verifier also checks the same temp-prefix upgrade path fromYYYY.M.DtoYYYY.M.D-Nso release corrections cannot silently leave older global installs on the base stable payload - npm release workflow fails closed unless the tarball includes both
dist/control-ui/index.htmland a non-emptydist/control-ui/assets/payload so we do not ship an empty browser dashboard again - Post-publish verification also checks that the published registry install
contains non-empty bundled plugin runtime deps under the root
dist/*layout. A release that ships with missing or empty bundled plugin dependency payloads fails the postpublish verifier and cannot be promoted tolatest. pnpm test:install:smokealso enforces the npm packunpackedSizebudget on the candidate update tarball, so installer e2e catches accidental pack bloat before the release publish path- If the release work touched CI planning, extension timing manifests, or
extension test matrices, regenerate and review the planner-owned
checks-node-extensionsworkflow matrix outputs from.github/workflows/ci.ymlbefore approval so release notes do not describe a stale CI layout - Stable macOS release readiness also includes the updater surfaces:
- the GitHub release must end up with the packaged
.zip,.dmg, and.dSYM.zip appcast.xmlonmainmust point at the new stable zip after publish- the packaged app must keep a non-debug bundle id, a non-empty Sparkle feed
URL, and a
CFBundleVersionat or above the canonical Sparkle build floor for that release version
- the GitHub release must end up with the packaged
NPM workflow inputs
Genesis NPM Release runs automatically when a GitHub release is published. It
also accepts these manual-dispatch recovery inputs:
tag: required release tag such asv2026.4.2,v2026.4.2-1, orv2026.4.2-beta.1npm_dist_tag:auto,beta, orlatest;autopublishes beta prereleases tobetaand stable releases tolatest
Genesis Release Checks accepts these operator-controlled inputs:
ref: existing release tag or the current full 40-charactermaincommit SHA to validate when dispatched frommain; from a release branch, use an existing release tag or the current full 40-character release-branch commit SHA
Rules:
- Automatic release-published runs publish stable and correction tags to
latest - Beta prerelease tags may publish only to
beta Genesis Release Checksis always validation-only and also accepts the current workflow-branch commit SHA- Release checks commit-SHA mode also requires the current workflow-branch HEAD
- Manual recovery dispatch can choose
betaorlatestfor stable and correction tags
Stable npm release sequence
When cutting a stable npm release:
- Run
Genesis Release Checksseparately with the same tag or the full current workflow-branch commit SHA when you want live prompt cache, QA Lab parity, Matrix, and Telegram coverage- This is separate on purpose so live coverage stays available without recoupling long-running or flaky checks to the publish workflow
- Publish the GitHub release for the tag.
Genesis NPM Releasestarts from the release-published event, validates the tag/package metadata, builds the release artifacts, runs the npm release checks, publishes to npmlatest, and verifies the published install path. - If
betashould follow the same stable build immediately, use the privategenesis/releases-private/.github/workflows/genesis-npm-dist-tags.ymlworkflow to pointbetaat the stable version, or let its scheduled self-healing sync movebetalater.
The dist-tag mutation lives in the private repo for security because it still
requires NPM_TOKEN, while the public repo keeps OIDC-only publish.
That keeps the direct publish path and the beta-first promotion path both documented and operator-visible.
If a maintainer must fall back to local npm authentication, run any 1Password
CLI (op) commands only inside a dedicated tmux session. Do not call op
directly from the main agent shell; keeping it inside tmux makes prompts,
alerts, and OTP handling observable and prevents repeated host alerts.
Public references
.github/workflows/genesis-npm-release.yml.github/workflows/genesis-release-checks.yml.github/workflows/genesis-cross-os-release-checks-reusable.ymlscripts/genesis-npm-release-check.tsscripts/package-mac-dist.shscripts/make_appcast.sh
Maintainers use the private release docs in
genesis/maintainers/release/README.md
for the actual runbook.