36 KiB
summary, title, read_when
| summary | title | read_when | |||
|---|---|---|---|---|---|
| Release lanes, operator checklist, validation boxes, version naming, and cadence | Release policy |
|
OpenClaw has three public release lanes:
- stable: tagged releases that publish to npm
betaby default, or to npmlatestwhen explicitly requested - 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 releases publish to npm
betaby default; release operators can targetlatestexplicitly, or promote a vetted beta build later - Every stable OpenClaw 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 operator checklist
This checklist is the public shape of the release flow. Private credentials, signing, notarization, dist-tag recovery, and emergency rollback details stay in the maintainer-only release runbook.
- Start from current
main: pull latest, confirm the target commit is pushed, and confirm currentmainCI is green enough to branch from it. - Rewrite the top
CHANGELOG.mdsection from real commit history with/changelog, keep entries user-facing, commit it, push it, and rebase/pull once more before branching. - Review release compatibility records in
src/plugins/compat/registry.tsandsrc/commands/doctor/shared/deprecation-compat.ts. Remove expired compatibility only when the upgrade path stays covered, or record why it is intentionally carried. - Create
release/YYYY.M.Dfrom currentmain; do not do normal release work directly onmain. - Bump every required version location for the intended tag, run
pnpm plugins:syncso publishable plugin packages share the release version and compatibility metadata, then run the local deterministic preflight:pnpm check:test-types,pnpm check:architecture,pnpm build && pnpm ui:build,pnpm plugins:sync:check, andpnpm release:check. - Run
OpenClaw NPM Releasewithpreflight_only=true. Before a tag exists, a full 40-character release-branch SHA is allowed for validation-only preflight. Save the successfulpreflight_run_id. - Kick off all pre-release tests with
Full Release Validationfor the release branch, tag, or full commit SHA. This is the one manual entrypoint for the four big release test boxes: Vitest, Docker, QA Lab, and Package. - If validation fails, fix on the release branch and rerun the smallest failed file, lane, workflow job, package profile, provider, or model allowlist that proves the fix. Rerun the full umbrella only when the changed surface makes prior evidence stale.
- For beta, tag
vYYYY.M.D-beta.N, then runOpenClaw Release Publishfrom the matchingrelease/YYYY.M.Dbranch. It verifiespnpm plugins:sync:check, publishes all publishable plugin packages to npm first, publishes the same set to ClawHub second as ClawPack npm-pack tarballs, and then promotes the prepared OpenClaw npm preflight artifact with the matching dist-tag. After publish, run post-publish package acceptance against the publishedopenclaw@YYYY.M.D-beta.Noropenclaw@betapackage. If a pushed or published prerelease needs a fix, cut the next matching prerelease number; do not delete or rewrite the old prerelease. - For stable, continue only after the vetted beta or release candidate has the
required validation evidence. Stable npm publish also goes through
OpenClaw Release Publish, reusing the successful preflight artifact viapreflight_run_id; stable macOS release readiness also requires the packaged.zip,.dmg,.dSYM.zip, and updatedappcast.xmlonmain. - After publish, run the npm post-publish verifier, optional standalone
published-npm Telegram E2E when you need post-publish channel proof,
dist-tag promotion when needed, GitHub release/prerelease notes from the
complete matching
CHANGELOG.mdsection, and the release announcement steps.
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 plugins:syncafter the root version bump and before tagging. It updates publishable plugin package versions, OpenClaw peer/API compatibility metadata, build metadata, and plugin changelog stubs to match the core release version.pnpm plugins:sync:checkis the non-mutating release guard; the publish workflow fails before any registry mutation if this step was forgotten. - Run the manual
Full Release Validationworkflow before release approval to kick off all pre-release test boxes from one entrypoint. It accepts a branch, tag, or full commit SHA, dispatches manualCI, and dispatchesOpenClaw Release Checksfor install smoke, package acceptance, Docker release-path suites, live/E2E, OpenWebUI, QA Lab parity, Matrix, and Telegram lanes. Withrelease_profile=fullandrerun_group=all, it also runs package Telegram E2E against therelease-package-under-testartifact from release checks. Providenpm_telegram_package_specafter publishing when the same Telegram E2E should prove the published npm package too. Providepackage_acceptance_package_specafter publishing when Package Acceptance should run its package/update matrix against the shipped npm package instead of the SHA-built artifact. Provideevidence_package_specwhen the private evidence report should prove that the validation matches a published npm package without forcing Telegram E2E. Example:gh workflow run full-release-validation.yml --ref main -f ref=release/YYYY.M.D - Run the manual
Package Acceptanceworkflow when you want side-channel proof for a package candidate while release work continues. Usesource=npmforopenclaw@beta,openclaw@latest, or an exact release version;source=refto pack a trustedpackage_refbranch/tag/SHA with the currentworkflow_refharness;source=urlfor an HTTPS tarball with a required SHA-256; orsource=artifactfor a tarball uploaded by another GitHub Actions run. The workflow resolves the candidate topackage-under-test, reuses the Docker E2E release scheduler against that tarball, and can run Telegram QA against the same tarball withtelegram_mode=mock-openaiortelegram_mode=live-frontier. When the selected Docker lanes includepublished-upgrade-survivor, the package artifact is the candidate andpublished_upgrade_survivor_baselineselects the published baseline. Example:gh workflow run package-acceptance.yml --ref main -f workflow_ref=main -f source=npm -f package_spec=openclaw@beta -f suite_profile=product -f published_upgrade_survivor_baseline=openclaw@2026.4.26 -f telegram_mode=mock-openaiCommon profiles:smoke: install/channel/agent, gateway network, and config reload lanespackage: artifact-native package/update/plugin lanes without OpenWebUI or live ClawHubproduct: package profile plus MCP channels, cron/subagent cleanup, OpenAI web search, and OpenWebUIfull: Docker release-path chunks with OpenWebUIcustom: exactdocker_lanesselection for a focused rerun
- Run the manual
CIworkflow directly when you only need full normal CI coverage for the release candidate. Manual CI dispatches bypass changed scoping and force the Linux Node shards, bundled-plugin shards, channel contracts, Node 22 compatibility,check,check-additional, build smoke, docs checks, Python skills, Windows, macOS, Android, and Control UI i18n lanes. Example:gh workflow run ci.yml --ref release/YYYY.M.D - Run
pnpm qa:otel:smokewhen validating release telemetry. It exercises QA-lab through a local OTLP/HTTP receiver and verifies the exported trace span names, bounded attributes, and content/identifier redaction without requiring Opik, Langfuse, or another external collector. - Run
pnpm release:checkbefore every tagged release - Run
OpenClaw Release Publishfor the mutating publish sequence after the tag exists. Dispatch it fromrelease/YYYY.M.D(ormainwhen publishing a main-reachable tag), pass the release tag and successful OpenClaw npmpreflight_run_id, and keep the default plugin publish scopeall-publishableunless you are deliberately running a focused repair. The workflow serializes plugin npm publish, plugin ClawHub publish, and OpenClaw npm publish so the core package is not published before its externalized plugins. - Release checks now run in a separate manual workflow:
OpenClaw Release Checks OpenClaw Release Checksalso runs the QA Lab mock parity lane plus the fast live Matrix profile and Telegram QA lane before release approval. The live lanes use theqa-live-sharedenvironment; Telegram also uses Convex CI credential leases. Run the manualQA-Lab - All Lanesworkflow withmatrix_profile=allandmatrix_shards=truewhen you want full Matrix transport, media, and E2EE inventory in parallel.- Cross-OS install and upgrade runtime validation is part of public
OpenClaw Release ChecksandFull Release Validation, which call the reusable workflow.github/workflows/openclaw-cross-os-release-checks-reusable.ymldirectly - 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
- Secret-bearing release checks should be dispatched through
Full Release Validationor from themain/release workflow ref so workflow logic and secrets stay controlled OpenClaw Release Checksaccepts a branch, tag, or full commit SHA as long as the resolved commit is reachable from an OpenClaw branch or release tagOpenClaw NPM Releasevalidation-only preflight also accepts the current full 40-character workflow-branch commit SHA without requiring a pushed tag- That SHA path is validation-only and cannot be promoted into a real publish
- In SHA mode the workflow synthesizes
v<package.json version>only for the package metadata check; real publish still requires a real release tag - Both workflows keep the real publish and promotion path on GitHub-hosted runners, while the non-mutating validation path can use the larger Blacksmith Linux runners
- That workflow runs
OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_CACHE_TEST=1 pnpm test:live:cacheusing bothOPENAI_API_KEYandANTHROPIC_API_KEYworkflow secrets - npm release preflight no longer waits on the separate release checks lane
- Run
RELEASE_TAG=vYYYY.M.D node --import tsx scripts/openclaw-npm-release-check.ts(or the matching beta/correction tag) before approval - After npm publish, run
node --import tsx scripts/openclaw-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 - After a beta publish, run
OPENCLAW_NPM_TELEGRAM_PACKAGE_SPEC=openclaw@YYYY.M.D-beta.N OPENCLAW_NPM_TELEGRAM_CREDENTIAL_SOURCE=convex OPENCLAW_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 threeOPENCLAW_QA_TELEGRAM_*env credentials directly. - To run the full post-publish beta smoke from a maintainer machine, use
pnpm release:beta-smoke -- --beta betaN. The helper runs Parallels npm update/fresh-target validation, dispatchesNPM Telegram Beta E2E, polls the exact workflow run, downloads the artifact, and prints the Telegram report. - 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 uses preflight-then-promote:
- real npm publish must pass a successful npm
preflight_run_id - the real npm publish must be dispatched from the same
mainorrelease/YYYY.M.Dbranch as the successful preflight run - stable npm releases default to
beta - stable npm publish can target
latestexplicitly via workflow input - token-based npm dist-tag mutation now lives in
openclaw/releases-private/.github/workflows/openclaw-npm-dist-tags.ymlfor security, becausenpm dist-tag addstill needsNPM_TOKENwhile the public repo keeps OIDC-only publish - public
macOS Releaseis validation-only; when a tag lives only on a release branch but the workflow is dispatched frommain, setpublic_release_branch=release/YYYY.M.D - real private mac publish must pass successful private mac
preflight_run_idandvalidate_run_id - the real publish paths promote prepared artifacts instead of rebuilding them again
- real npm publish must pass a successful npm
- 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 preflight 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 published plugin entrypoints and
package metadata are present in the installed registry layout. A release that
ships missing plugin runtime payloads fails the postpublish verifier and
cannot be promoted to
latest. 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
plugin-prerelease-extension-shardmatrix outputs from.github/workflows/plugin-prerelease.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
Release test boxes
Full Release Validation is how operators kick off all pre-release tests from
one entrypoint. For a pinned commit proof on a fast-moving branch, use the
helper so every child workflow runs from a temporary branch fixed at the target
SHA:
pnpm ci:full-release --sha <full-sha>
The helper pushes release-ci/<sha>-..., dispatches Full Release Validation
from that branch with ref=<sha>, verifies every child workflow headSha
matches the target, then deletes the temporary branch. This avoids proving a
newer main child run by accident.
For release branch or tag validation, run it from the trusted main workflow
ref and pass the release branch or tag as ref:
gh workflow run full-release-validation.yml \
--ref main \
-f ref=release/YYYY.M.D \
-f provider=openai \
-f mode=both \
-f release_profile=stable \
-f evidence_package_spec=openclaw@YYYY.M.D-beta.N
The workflow resolves the target ref, dispatches manual CI with
target_ref=<release-ref>, dispatches OpenClaw Release Checks, prepares a
parent release-package-under-test artifact for package-facing checks, and
dispatches standalone package Telegram E2E when release_profile=full with
rerun_group=all or when npm_telegram_package_spec is set. OpenClaw Release Checks then fans out install smoke, cross-OS release checks, live/E2E Docker
release-path coverage, Package Acceptance with Telegram package QA, QA Lab
parity, live Matrix, and live Telegram. A full run is only acceptable when the
Full Release Validation
summary shows normal_ci and release_checks as successful. In full/all mode,
the npm_telegram child must also be successful; outside full/all it is skipped
unless a published npm_telegram_package_spec was provided. The final
verifier summary includes slowest-job tables for each child run, so the release
manager can see the current critical path without downloading logs.
See Full release validation for the
complete stage matrix, exact workflow job names, stable versus full profile
differences, artifacts, and focused rerun handles.
Child workflows are dispatched from the trusted ref that runs Full Release Validation, normally --ref main, even when the target ref points at an
older release branch or tag. There is no separate Full Release Validation
workflow-ref input; choose the trusted harness by choosing the workflow run ref.
Do not use --ref main -f ref=<sha> for exact commit proof on moving main;
raw commit SHAs cannot be workflow dispatch refs, so use
pnpm ci:full-release --sha <sha> to create the pinned temporary branch.
Use release_profile to select live/provider breadth:
minimum: fastest release-critical OpenAI/core live and Docker pathstable: minimum plus stable provider/backend coverage for release approvalfull: stable plus broad advisory provider/media coverage
OpenClaw Release Checks uses the trusted workflow ref to resolve the target
ref once as release-package-under-test and reuses that artifact in both
release-path Docker checks and Package Acceptance. This keeps all
package-facing boxes on the same bytes and avoids repeated package builds.
The cross-OS OpenAI install smoke uses OPENCLAW_CROSS_OS_OPENAI_MODEL when the
repo/org variable is set, otherwise openai/gpt-5.4, because this lane is
proving package install, onboarding, gateway startup, and one live agent turn
rather than benchmarking the slowest default model. The broader live provider
matrix remains the place for model-specific coverage.
Use these variants depending on release stage:
# Validate an unpublished release candidate branch.
gh workflow run full-release-validation.yml \
--ref main \
-f ref=release/YYYY.M.D \
-f provider=openai \
-f mode=both \
-f release_profile=stable
# Validate an exact pushed commit.
gh workflow run full-release-validation.yml \
--ref main \
-f ref=<40-char-sha> \
-f provider=openai \
-f mode=both
# After publishing a beta, add published-package Telegram E2E.
gh workflow run full-release-validation.yml \
--ref main \
-f ref=release/YYYY.M.D \
-f provider=openai \
-f mode=both \
-f release_profile=full \
-f evidence_package_spec=openclaw@YYYY.M.D-beta.N \
-f npm_telegram_package_spec=openclaw@YYYY.M.D-beta.N \
-f npm_telegram_provider_mode=mock-openai
Do not use the full umbrella as the first rerun after a focused fix. If one box
fails, use the failed child workflow, job, Docker lane, package profile, model
provider, or QA lane for the next proof. Run the full umbrella again only when
the fix changed shared release orchestration or made earlier all-box evidence
stale. The umbrella's final verifier re-checks the recorded child workflow run
ids, so after a child workflow is rerun successfully, rerun only the failed
Verify full validation parent job.
For bounded recovery, pass rerun_group to the umbrella. all is the real
release-candidate run, ci runs only the normal CI child, plugin-prerelease
runs only the release-only plugin child, release-checks runs every release
box, and the narrower release groups are install-smoke, cross-os,
live-e2e, package, qa, qa-parity, qa-live, and npm-telegram.
Focused npm-telegram reruns require npm_telegram_package_spec; full/all runs
with release_profile=full use the release-checks package artifact.
Vitest
The Vitest box is the manual CI child workflow. Manual CI intentionally
bypasses changed scoping and forces the normal test graph for the release
candidate: Linux Node shards, bundled-plugin shards, channel contracts, Node 22
compatibility, check, check-additional, build smoke, docs checks, Python
skills, Windows, macOS, Android, and Control UI i18n.
Use this box to answer "did the source tree pass the full normal test suite?" It is not the same as release-path product validation. Evidence to keep:
Full Release Validationsummary showing the dispatchedCIrun URLCIrun green on the exact target SHA- failed or slow shard names from the CI jobs when investigating regressions
- Vitest timing artifacts such as
.artifacts/vitest-shard-timings.jsonwhen a run needs performance analysis
Run manual CI directly only when the release needs deterministic normal CI but not the Docker, QA Lab, live, cross-OS, or package boxes:
gh workflow run ci.yml --ref main -f target_ref=release/YYYY.M.D
Docker
The Docker box lives in OpenClaw Release Checks through
openclaw-live-and-e2e-checks-reusable.yml, plus the release-mode
install-smoke workflow. It validates the release candidate through packaged
Docker environments instead of only source-level tests.
Release Docker coverage includes:
- full install smoke with the slow Bun global install smoke enabled
- root Dockerfile smoke image preparation/reuse by target SHA, with QR, root/gateway, and installer/Bun smoke jobs running as separate install-smoke shards
- repository E2E lanes
- release-path Docker chunks:
core,package-update-openai,package-update-anthropic,package-update-core,plugins-runtime-plugins,plugins-runtime-services,plugins-runtime-install-a,plugins-runtime-install-b,plugins-runtime-install-c,plugins-runtime-install-d,plugins-runtime-install-e,plugins-runtime-install-f,plugins-runtime-install-g, andplugins-runtime-install-h - OpenWebUI coverage inside the
plugins-runtime-serviceschunk when requested - split bundled plugin install/uninstall lanes
bundled-plugin-install-uninstall-0throughbundled-plugin-install-uninstall-23 - live/E2E provider suites and Docker live model coverage when release checks include live suites
Use Docker artifacts before rerunning. The release-path scheduler uploads
.artifacts/docker-tests/ with lane logs, summary.json, failures.json,
phase timings, scheduler plan JSON, and rerun commands. For focused recovery,
use docker_lanes=<lane[,lane]> on the reusable live/E2E workflow instead of
rerunning all release chunks. Generated rerun commands include prior
package_artifact_run_id and prepared Docker image inputs when available, so a
failed lane can reuse the same tarball and GHCR images.
QA Lab
The QA Lab box is also part of OpenClaw Release Checks. It is the agentic
behavior and channel-level release gate, separate from Vitest and Docker
package mechanics.
Release QA Lab coverage includes:
- mock parity lane comparing the OpenAI candidate lane against the Opus 4.6 baseline using the agentic parity pack
- fast live Matrix QA profile using the
qa-live-sharedenvironment - live Telegram QA lane using Convex CI credential leases
pnpm qa:otel:smokewhen release telemetry needs explicit local proof
Use this box to answer "does the release behave correctly in QA scenarios and live channel flows?" Keep the artifact URLs for parity, Matrix, and Telegram lanes when approving the release. Full Matrix coverage remains available as a manual sharded QA-Lab run rather than the default release-critical lane.
Package
The Package box is the installable-product gate. It is backed by
Package Acceptance and the resolver
scripts/resolve-openclaw-package-candidate.mjs. The resolver normalizes a
candidate into the package-under-test tarball consumed by Docker E2E, validates
the package inventory, records the package version and SHA-256, and keeps the
workflow harness ref separate from the package source ref.
Supported candidate sources:
source=npm:openclaw@beta,openclaw@latest, or an exact OpenClaw release versionsource=ref: pack a trustedpackage_refbranch, tag, or full commit SHA with the selectedworkflow_refharnesssource=url: download an HTTPS.tgzwith requiredpackage_sha256source=artifact: reuse a.tgzuploaded by another GitHub Actions run
OpenClaw Release Checks runs Package Acceptance with source=artifact, the
prepared release package artifact, suite_profile=custom,
docker_lanes=doctor-switch update-channel-switch upgrade-survivor published-upgrade-survivor plugins-offline plugin-update,
published_upgrade_survivor_baselines=all-since-2026.4.23,
published_upgrade_survivor_scenarios=reported-issues, and
telegram_mode=mock-openai. Package Acceptance keeps migration, update, stale
plugin dependency cleanup, offline plugin fixtures, plugin update, and Telegram
package QA against the same resolved tarball. The upgrade matrix covers every stable npm-published baseline from 2026.4.23 through latest; use
Package Acceptance with source=npm for an already shipped candidate, or
source=ref/source=artifact for a SHA-backed local npm tarball before
publish. It is the GitHub-native
replacement for most of the package/update coverage that previously required
Parallels. Cross-OS release checks still matter for OS-specific onboarding,
installer, and platform behavior, but package/update product validation should
prefer Package Acceptance.
The canonical checklist for update and plugin validation is
Testing updates and plugins. Use it when
deciding which local, Docker, Package Acceptance, or release-check lane proves a
plugin install/update, doctor cleanup, or published-package migration change.
Exhaustive published update migration from every stable 2026.4.23+ package is
a separate manual Update Migration workflow, not part of Full Release CI.
Legacy package-acceptance leniency is intentionally time boxed. Packages through
2026.4.25 may use the compatibility path for metadata gaps already published
to npm: private QA inventory entries missing from the tarball, missing
gateway install --wrapper, missing patch files in the tarball-derived git
fixture, missing persisted update.channel, legacy plugin install-record
locations, missing marketplace install-record persistence, and config metadata
migration during plugins update. The published 2026.4.26 package may warn
for local build metadata stamp files that were already shipped. Later packages
must satisfy the modern package contracts; those same gaps fail release
validation.
Use broader Package Acceptance profiles when the release question is about an actual installable package:
gh workflow run package-acceptance.yml \
--ref main \
-f workflow_ref=main \
-f source=npm \
-f package_spec=openclaw@beta \
-f suite_profile=product \
-f published_upgrade_survivor_baseline=openclaw@2026.4.26
Common package profiles:
smoke: quick package install/channel/agent, gateway network, and config reload lanespackage: install/update/plugin package contracts without live ClawHub; this is the release-check defaultproduct:packageplus MCP channels, cron/subagent cleanup, OpenAI web search, and OpenWebUIfull: Docker release-path chunks with OpenWebUIcustom: exactdocker_laneslist for focused reruns
For package-candidate Telegram proof, enable telegram_mode=mock-openai or
telegram_mode=live-frontier on Package Acceptance. The workflow passes the
resolved package-under-test tarball into the Telegram lane; the standalone
Telegram workflow still accepts a published npm spec for post-publish checks.
Release publish automation
OpenClaw Release Publish is the normal mutating publish entrypoint. It
orchestrates the trusted-publisher workflows in the order the release needs:
- Check out the release tag and resolve its commit SHA.
- Verify the tag is reachable from
mainorrelease/*. - Run
pnpm plugins:sync:check. - Dispatch
Plugin NPM Releasewithpublish_scope=all-publishableandref=<release-sha>. - Dispatch
Plugin ClawHub Releasewith the same scope and SHA. - Dispatch
OpenClaw NPM Releasewith the release tag, npm dist-tag, and savedpreflight_run_id.
Beta publish example:
gh workflow run openclaw-release-publish.yml \
--ref release/YYYY.M.D \
-f tag=vYYYY.M.D-beta.N \
-f preflight_run_id=<successful-openclaw-npm-preflight-run-id> \
-f npm_dist_tag=beta
Stable publish to the default beta dist-tag:
gh workflow run openclaw-release-publish.yml \
--ref release/YYYY.M.D \
-f tag=vYYYY.M.D \
-f preflight_run_id=<successful-openclaw-npm-preflight-run-id> \
-f npm_dist_tag=beta
Stable promotion directly to latest is explicit:
gh workflow run openclaw-release-publish.yml \
--ref release/YYYY.M.D \
-f tag=vYYYY.M.D \
-f preflight_run_id=<successful-openclaw-npm-preflight-run-id> \
-f npm_dist_tag=latest
Use the lower-level Plugin NPM Release and Plugin ClawHub Release workflows
only for focused repair or republish work. For a selected plugin repair, pass
plugin_publish_scope=selected and plugins=@openclaw/name to
OpenClaw Release Publish, or dispatch the child workflow directly when the
OpenClaw package must not be published.
NPM workflow inputs
OpenClaw NPM Release accepts these operator-controlled inputs:
tag: required release tag such asv2026.4.2,v2026.4.2-1, orv2026.4.2-beta.1; whenpreflight_only=true, it may also be the current full 40-character workflow-branch commit SHA for validation-only preflightpreflight_only:truefor validation/build/package only,falsefor the real publish pathpreflight_run_id: required on the real publish path so the workflow reuses the prepared tarball from the successful preflight runnpm_dist_tag: npm target tag for the publish path; defaults tobeta
OpenClaw Release Publish accepts these operator-controlled inputs:
tag: required release tag; must already existpreflight_run_id: successfulOpenClaw NPM Releasepreflight run id; required whenpublish_openclaw_npm=truenpm_dist_tag: npm target tag for the OpenClaw packageplugin_publish_scope: defaults toall-publishable; useselectedonly for focused repair workplugins: comma-separated@openclaw/*package names whenplugin_publish_scope=selectedpublish_openclaw_npm: defaults totrue; setfalseonly when using the workflow as a plugin-only repair orchestrator
OpenClaw Release Checks accepts these operator-controlled inputs:
ref: branch, tag, or full commit SHA to validate. Secret-bearing checks require the resolved commit to be reachable from an OpenClaw branch or release tag.
Rules:
- Stable and correction tags may publish to either
betaorlatest - Beta prerelease tags may publish only to
beta - For
OpenClaw NPM Release, full commit SHA input is allowed only whenpreflight_only=true OpenClaw Release ChecksandFull Release Validationare always validation-only- The real publish path must use the same
npm_dist_tagused during preflight; the workflow verifies that metadata before publish continues
Stable npm release sequence
When cutting a stable npm release:
- Run
OpenClaw NPM Releasewithpreflight_only=true- Before a tag exists, you may use the current full workflow-branch commit SHA for a validation-only dry run of the preflight workflow
- Choose
npm_dist_tag=betafor the normal beta-first flow, orlatestonly when you intentionally want a direct stable publish - Run
Full Release Validationon the release branch, release tag, or full commit SHA when you want normal CI plus live prompt cache, Docker, QA Lab, Matrix, and Telegram coverage from one manual workflow - If you intentionally only need the deterministic normal test graph, run the
manual
CIworkflow on the release ref instead - Save the successful
preflight_run_id - Run
OpenClaw Release Publishwith the sametag, the samenpm_dist_tag, and the savedpreflight_run_id; it publishes externalized plugins to npm and ClawHub before promoting the OpenClaw npm package - If the release landed on
beta, use the privateopenclaw/releases-private/.github/workflows/openclaw-npm-dist-tags.ymlworkflow to promote that stable version frombetatolatest - If the release intentionally published directly to
latestandbetashould follow the same stable build immediately, use that same private workflow to point both dist-tags at 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/full-release-validation.yml.github/workflows/package-acceptance.yml.github/workflows/openclaw-npm-release.yml.github/workflows/openclaw-release-checks.yml.github/workflows/openclaw-cross-os-release-checks-reusable.ymlscripts/resolve-openclaw-package-candidate.mjsscripts/openclaw-npm-release-check.tsscripts/package-mac-dist.shscripts/make_appcast.sh
Maintainers use the private release docs in
openclaw/maintainers/release/README.md
for the actual runbook.