OpenClaw Release Policy: Channels, Versions, and Cadence
Learn about OpenClaw's four update channels, version naming conventions, and release cadence. This page is for operators and developers managing installations or planning upgrades.
Read this when
- Looking for public release channel definitions
- Running release validation or package acceptance
- Looking for version naming and cadence
OpenClaw provides four update channels that users can choose from:
- stable: the promoted regular release on npm
latest - extended-stable: the trailing completed month's
.33+maintenance line on npmextended-stable - beta: prerelease tags on npm
beta - dev: the moving head of
main
The extended-stable channel delivers the previous month's Gateway, official npm plugins, and Docker images while leaving the regular latest and main selectors untouched.
Tideclaw alpha builds operate as a distinct internal prerelease track, identified by the npm dist-tag alpha, and are detailed in NPM workflow inputs along with Release test boxes.
Version naming
- Monthly Gateway extended-stable release version:
YYYY.M.PATCH, paired withPATCH >= 33, git tagvYYYY.M.PATCH - Daily or regular final release version:
YYYY.M.PATCH, paired withPATCH < 33, git tagvYYYY.M.PATCH - Regular fallback correction release version:
YYYY.M.PATCH-N, git tagvYYYY.M.PATCH-N - Beta prerelease version:
YYYY.M.PATCH-beta.N, git tagvYYYY.M.PATCH-beta.N - Alpha prerelease version:
YYYY.M.PATCH-alpha.N, git tagvYYYY.M.PATCH-alpha.N - Month and patch values must never be zero-padded
PATCHacts as a sequential monthly release-train counter rather than a calendar date. Regular final and beta releases move the current train forward; alpha-only tags neither consume nor advance the beta or regular patch number, so when picking a beta or regular train, disregard older alpha-only tags that carry higher patch numbers.- Alpha and nightly builds target the next unreleased patch train and bump only
alpha.Nfor each subsequent build. Once that patch receives a beta, fresh alpha builds shift to the following patch. - npm versions cannot be changed after publication: never remove, re-upload, or repurpose a released tag. Instead, produce the next prerelease number or the next monthly patch.
latestkeeps tracking the current regular or daily npm line;betaserves as the active beta install targetextended-stabledesignates the supported trailing-month Gateway distribution, starting at patch33; patches34and beyond are maintenance releases on that monthly line- Regular final and regular correction releases default to publishing on npm
beta; release operators may explicitly chooselatest, or later promote a validated beta build - Gateway extended-stable publishes core, every npm-publishable official plugin, and its Docker images at a single exact version; consult the dedicated workflow below.
- Each regular final release bundles the npm package, macOS app, signed standalone Android APK, and signed Windows Hub installers in one go. Beta releases typically validate and publish the npm or package path first, holding native app build, sign, notarize, and promote steps for regular final unless explicitly requested.
Release cadence
- Releases proceed beta-first; stable follows only once the newest beta passes validation
- Maintainers usually cut releases from a
release/YYYY.M.PATCHbranch created off currentmain, so release validation and fixes do not stall new work onmain - If a beta tag has been pushed or published and requires a fix, maintainers create the next
-beta.Ntag rather than deleting or recreating the previous one - The full release procedure, approvals, credentials, and recovery notes are restricted to maintainers
Monthly Gateway extended-stable publication
For the completed month YYYY.M, set up extended-stable/YYYY.M.33 and release
.33+ from that branch. Tag, branch, checkout, package version, preflight, and
validation must all point to one commit. Before .33, protected main must hold
a later month's final version below patch 33; subsequent maintenance patches stay
eligible.
Prepare and stabilize the candidate
Review the unaudited mainline range, reconcile private security work, approve a limited backport set, and merge one coordinated PR. Never push directly to the canonical branch.
On the canonical branch, configure YYYY.M.P, execute pnpm release:prep, and enforce
that version across every publishable official plugin. From the approved ledger,
generate and commit a full ## YYYY.M.P section containing ### Highlights,
### Changes, and ### Fixes, citing original merged main PRs for matching
backports. Preflight rejects a missing or empty section.
Include the complete current-main Docker release-channel unit: workflow, promoter, policy, shared classifier, tests, and workflow validation. GitHub loads tag workflows from the tagged commit; an incomplete copy can fail after building or shift regular aliases. Run focused checks.
Lock the full branch-tip SHA. Before tagging, preflight its exact npm bytes and run Full Release Validation against that SHA:
RELEASE_SHA="$(git rev-parse HEAD)"
gh workflow run openclaw-npm-release.yml \
--ref extended-stable/YYYY.M.33 \
-f tag="$RELEASE_SHA" \
-f preflight_only=true \
-f npm_dist_tag=extended-stable
gh workflow run full-release-validation.yml \
--ref extended-stable/YYYY.M.33 \
-f ref=extended-stable/YYYY.M.33 \
-f expected_sha="$RELEASE_SHA" \
-f release_profile=stable
The SHA form is preflight-only. Run validation on the canonical branch; publish
binds its workflow ref, head or target SHA, run ID, and attempt. Save both IDs and
the successful run_attempt; reject release-ci/* evidence.
Sort failures before making changes:
- Product: merge another approved backport PR.
- Frozen-target tooling: backport only the smallest compatibility fix that tests the old product unchanged.
- Provider, approval, runner, or service: leave the candidate unchanged and use the bounded retry path.
Any branch change invalidates both gates. Once they pass, confirm the tip still
equals RELEASE_SHA, then push signed vYYYY.M.P. Later changes require the next
patch; never move or delete the tag. Tagging fixes the immutable release
identity; it does not publish Docker images.
Publish the npm packages
Publish every npm-publishable official plugin from the same SHA and record the successful run ID:
RELEASE_SHA="$(git rev-parse HEAD)"
gh workflow run plugin-npm-release.yml \
--ref extended-stable/YYYY.M.33 \
-f publish_scope=all-publishable \
-f ref="$RELEASE_SHA" \
-f npm_dist_tag=extended-stable
The workflow handles all all-publishable packages, including unchanged ones,
and checks every exact version and selector. Reruns reuse published versions.
Publish the prepared core tarball next, carrying all three saved run identities along with it:
gh workflow run openclaw-npm-release.yml \
--ref extended-stable/YYYY.M.33 \
-f tag=vYYYY.M.P \
-f preflight_only=false \
-f npm_dist_tag=extended-stable \
-f preflight_run_id=<npm-preflight-run-id> \
-f full_release_validation_run_id=<full-validation-run-id> \
-f full_release_validation_run_attempt=<full-validation-run-attempt> \
-f plugin_npm_run_id=<plugin-npm-run-id>
Should the immutable candidate already hold a passing saved preflight and Full Release Validation, yet core publication only needs a workflow-level recovery, trigger the trusted current-main workflow in its place. Preserve the existing tag and evidence identities; leave the tag in place and avoid republishing plugins:
gh workflow run openclaw-npm-release.yml \
--ref main \
-f tag=vYYYY.M.P \
-f preflight_only=false \
-f npm_dist_tag=extended-stable \
-f release_candidate_branch=extended-stable/YYYY.M.33 \
-f preflight_run_id=<npm-preflight-run-id> \
-f full_release_validation_run_id=<full-validation-run-id> \
-f full_release_validation_run_attempt=<full-validation-run-attempt> \
-f plugin_npm_run_id=<plugin-npm-run-id>
This recovery route checks out and publishes the immutable tag, and it demands the canonical branch that the tag implies. It will accept Full Release Validation evidence from the canonical candidate branch directly, from current main directly when its workflow SHA is reachable from current main, or from the trusted main-pinned harness. Every accepted form must attest the immutable tag's SHA. Reserve this path for cases where the candidate source and recorded evidence remain untouched.
For non-production rehearsal only, append
-f bypass_extended_stable_guard=true to preflight and publish. It skips the
month guard exclusively, never canonical-ref, SHA/tag/version equality, provenance,
approval, or readback checks. Production must never use it.
Verify and recover
From a separate clean current-main checkout, not the frozen branch, execute:
node --import tsx scripts/openclaw-npm-postpublish-verify.ts YYYY.M.P
npm view openclaw@YYYY.M.P version --userconfig "$(mktemp)"
npm view openclaw@extended-stable version --userconfig "$(mktemp)"
Signatures and npm provenance are mandatory for the canonical branch, along with publish,
preflight, and tarball-digest binding to the release SHA. Both commands must
return YYYY.M.P. Verify every prepared core package and all-publishable
official plugin at its exact version and selector.
If only the root selector fails, apply the generated
npm dist-tag add openclaw@YYYY.M.P extended-stable repair command printed in
the workflow summary. Repair existing plugin or other prepared-core selectors
through approved credential-isolated tooling; the OIDC source cannot mutate
them. Never republish an immutable version.
Require Docker Release to verify exact default, slim, browser, and architecture
images in GHCR and Docker Hub, including attestations and platform versions. It
must advance only
extended-stable, extended-stable-slim, and extended-stable-browser by
digest; regular aliases remain unchanged and automatic rollback is rejected.
Once that core registry readback succeeds, initiate Docker publication only through
OpenClaw Release Publish. Its Docker-only extended-stable path rechecks the
saved npm preflight artifact, exact Full Release Validation evidence, exact npm
version and extended-stable selector, and published tarball digest before it
calls the reusable Docker Release workflow. A tag push never publishes Docker
images by itself:
gh workflow run openclaw-release-publish.yml \
--ref main \
-f tag=vYYYY.M.P \
-f preflight_run_id=<npm-preflight-run-id> \
-f full_release_validation_run_id=<full-validation-run-id> \
-f full_release_validation_run_attempt=<full-validation-run-attempt> \
-f npm_dist_tag=extended-stable \
-f publish_openclaw_npm=false \
-f publish_docker_only=true
For alias repair, run approval-gated Docker Channel Promotion from current
main with the tag. It repeats digest, attestation, and platform checks, allows
an explicit rollback, and never rebuilds images.
Slack, Discord, and Codex are the initial documented support surfaces, not a
release allowlist: every npm-publishable official plugin ships. The regular
checklist alone owns beta/latest, GitHub Releases, ClawHub, native apps, mobile,
website, and private dist-tags; do not run those steps for this Gateway path.
Regular 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 confirmmainCI is green enough to branch from. -
Create
release/YYYY.M.PATCHfrom that commit. Backports are optional; apply only the operator-selected set. Bump every required version location, runpnpm release:prep, finish release fixes and required forward-ports, and reviewsrc/plugins/compat/registry.tsplussrc/commands/doctor/shared/deprecation-compat.ts. -
Freeze the product-complete pre-changelog commit as the Code SHA and record the trusted Tooling SHA. Run the deterministic source preflight, then use
node scripts/full-release-validation-at-sha.mjs --sha <code-sha> --target-ref release/YYYY.M.PATCH. Beta-publish usesrelease_profile=betawithout soak; postpublish-confidence owns broad live, QA-live, mobile, and Parallels work. -
Classify failures before editing as product, harness/tooling/provenance, infrastructure/credential, or wrapper. Only confirmed product failure creates a new Code SHA. Use one diagnosis, one fix when needed, and one narrow retry, then reassess.
-
Only after the Code SHA is green, generate the top
CHANGELOG.mdsection from merged PRs and direct commits since the last reachable shipped tag. Keep entries user-facing and deduplicated. When a divergent shipped tag or later forward-port re-associates already-released PRs, pass it explicitly as--shipped-ref. -
Commit only
CHANGELOG.md. This commit is the Release SHA. The complete diff from Code SHA to Release SHA must be exactlyCHANGELOG.md; any other changed path returns the release to step 2. -
Run SHA-pinned Full Release Validation for the Release SHA with evidence reuse enabled. The lightweight parent must record
changelog-only-release-v1, point at the green Code SHA, and dispatch no product child lanes. This reuses product evidence; it does not reuse package bytes. -
Run
OpenClaw NPM Releasewithpreflight_only=trueagainst the Release SHA/tag. Save the successfulpreflight_run_id. This builds and checks the exact package bytes that include the final changelog. Review its Plugin SDK API diff summary. If it reports changes, inspect the readable diff (also uploaded asplugin-sdk-api-release-diff-<run-id>-<run-attempt>) and record the 8-character acknowledgement digest printed by the report; omit the acknowledgement when it reports no Plugin SDK API changes. -
Run the candidate helper against the untagged Release SHA with the successful Release-SHA validation parent and npm preflight instead of dispatching either again:
pnpm release:candidate -- \ --tag vYYYY.M.PATCH-beta.N \ --target-sha <release-sha> \ --full-release-run <release-sha-validation-run-id> \ --npm-preflight-run <preflight-run-id> \ --plugin-sdk-api-acknowledgement <reviewed-8-character-digest> \ --skip-dispatchInclude
--plugin-sdk-api-acknowledgementonly when the preflight reported Plugin SDK API changes. For stable, also pass--windows-node-tag vX.Y.Z. Beta and alpha candidates defer Parallels install/update proof to the postpublishpnpm release:beta-smokeroster by default; pass--run-parallelsonly when the operator explicitly wants that proof before publish. Stable and full candidates run Parallels by default. The helper still verifies release-note provenance, npm preflight bytes, Telegram package proof, and plugin publish plans, then prints the publish command. After it completes green, create and push the final signed tag at that same Release SHA, then run the printed publish command.pnpm release:candidatevalidates the current frozen branch tip by default (or the explicit--target-sha), and rejects a tag that already exists. It records evidence before the final signed tag is pushed.OpenClaw Release Publishdispatches the selected or all-publishable plugin packages to npm and the same set to ClawHub in parallel, then promotes the prepared OpenClaw npm preflight artifact with the matching dist-tag once plugin npm publish succeeds. It keeps the GitHub release as a draft while it verifies registry readback, callsDocker Releasewith the immutable tag and Release SHA, and only then finalizes the GitHub release. The release checkout remains the product/data root, while planning and final verification execute from the exact trusted workflow-source checkout so an older release commit cannot silently use obsolete release tooling. Before any publish child starts, it renders and caches the exact GitHub release body. When the complete matchingCHANGELOG.mdsection fits GitHub's 125,000-character limit and the renderer's matching 125,000-byte safety ceiling, the page contains that exact## YYYY.M.PATCHsection including its heading. When the source section does not fit, the page keeps the exact grouped editorial notes and replaces the oversized contribution record with a stable link to the full record in the tag-pinnedCHANGELOG.md; partial records and truncated bullets are never published. The workflow chooses that full or compact body before adding### Release verification; if the proof tail would exceed the limit, it keeps the canonical body and relies on the immutable attached evidence instead. Stable releases published to npmlatestbecome the GitHub latest release, while stable maintenance releases kept on npmbetaare created with GitHublatest=false. The workflow also uploads the preflight dependency evidence, the full-validation manifest, and postpublish registry verification evidence to the GitHub release for post-release incident response. It prints child run IDs immediately, auto-approves release environment gates the workflow token is allowed to approve, summarizes failed child jobs with log tails, creates the draft GitHub release page up front and promotes Windows and Android assets concurrently with the OpenClaw npm publish, waits for ClawHub whenever OpenClaw npm is being published, then runs the trusted-main beta verifier and uploads postpublish evidence for the GitHub release, npm package, selected plugin npm packages, selected ClawHub packages, child workflow run IDs, and optional NPM Telegram run ID. The ClawHub bootstrap verifier requires the exact trusted-main workflow path and SHA, producer and terminal run attempts, release SHA, requested package set, immutable package artifact tuple, and terminal registry readback artifact; a successful legacy release-ref run is not accepted.
Then run post-publish package acceptance against the published openclaw@YYYY.M.PATCH-beta.N or openclaw@beta package. Should a pushed or published prerelease require a fix, produce the next matching prerelease number; the old one must never be deleted or overwritten.
- When a publish attempt fails, leave the Release SHA untouched unless the failure points to a genuine product or changelog issue. Continue with any immutable children and artifacts that already succeeded; a package version that has succeeded must not be rebuilt or republished.
- For stable, proceed only once the vetted beta or release candidate carries the required validation evidence. Stable npm publish also passes through
OpenClaw Release Publish, leveraging the successful preflight artifact throughpreflight_run_id. Stable macOS release readiness additionally demands the packaged.zip,.dmg,.dSYM.zip, and updatedappcast.xmlonmain; the macOS publish workflow pushes the signed appcast to publicmainautomatically after release assets pass verification, or opens or updates an appcast PR when branch protection blocks the direct push. Stable Windows Hub readiness calls for the signedOpenClawCompanion-Setup-x64.exe,OpenClawCompanion-Setup-arm64.exe, andOpenClawCompanion-SHA256SUMS.txtassets on the OpenClaw GitHub release. Pass the exact signedopenclaw/openclaw-windows-noderelease tag aswindows_node_tagand its candidate-approved installer digest map aswindows_node_installer_digests;OpenClaw Release Publishpreserves the release draft, triggersWindows Node Release, and checks all three assets before publication. - After publishing, execute the npm post-publish verifier, the optional standalone published-npm Telegram E2E when post-publish channel proof is needed, dist-tag promotion when applicable, confirm the generated GitHub release page, carry out the release announcement steps, and then finish Stable main closeout before declaring a stable release complete.
Stable main closeout
Stable publication is only finished once main holds the actual shipped release state.
- Begin from a fresh latest
main. Comparerelease/YYYY.M.PATCHagainst it and forward-port real fixes that are missing frommain. Do not blindly merge release-only compatibility, test, or validation adapters into a newermain. - For the normal path, assign
mainthe shipped stable version. A late closeout may usemainonce it has moved to a later stable OpenClaw CalVer; do not downgrade an already-started release train solely to wrap up the prior release. The validator still demands the exact shipped changelog section and appcast entry and logs the actualmainversion and SHA. Runpnpm release:prepafter any root version change. - Make sure
CHANGELOG.md's## YYYY.M.PATCHsection onmainmatches the tagged release branch precisely. Include the stableappcast.xmlupdate when the mac release published one. - Do not add
YYYY.M.PATCH+1, a beta version, or an empty future changelog section tomainuntil the operator explicitly starts that release train. - Run
pnpm release:generated:check,pnpm deps:npm-lock:check, andOPENCLAW_TESTBOX=1 pnpm check:changed. Push, then confirmorigin/maincontains the shipped version and changelog before calling the stable release done. - Keep the repository variables
RELEASE_ROLLBACK_DRILL_IDandRELEASE_ROLLBACK_DRILL_DATEcurrent after each private rollback drill.
OpenClaw Stable Main Closeout originates from the main push that carries the shipped version, changelog, and appcast after stable publication. It reads immutable postpublish evidence to tie the shipped tag to its Full Release Validation and Publish runs, then checks the stable main state, release, mandatory stable soak, and blocking performance evidence. It attaches an immutable closeout manifest and checksum to the GitHub release. The automatic push trigger skips legacy releases that predate immutable postpublish evidence and never treats that skip as a finished closeout.
A complete closeout needs both assets and a matching checksum. A partial manifest replays its recorded main SHA and rollback drill to recreate identical bytes, then attaches the missing checksum; an invalid pair, or a checksum without a manifest, stays blocking. A push-triggered run without rollback drill repository variables skips without completing closeout; a missing or more-than-90-day-old drill record still blocks manual evidence-backed closeout. Private recovery commands live in the maintainer-only runbook. Use manual dispatch only to repair or replay an evidence-backed stable closeout.
If the Release Publish parent failed only after immutable npm/plugin evidence was attached, repair and publish every stable platform asset first. Then a maintainer may manually dispatch closeout with allow_failed_publish_recovery=true; that mode accepts only a completed failed parent and additionally requires the exact Android and Windows asset contracts, GitHub SHA-256 digests, checksum verification, Android provenance, and a successful parent-dispatched Windows promotion whose Authenticode checks and candidate-approved digests match the published installers, alongside the normal macOS/appcast checks. Automatic push closeout never enables this recovery mode.
A legacy fallback correction tag may reuse base-package evidence only when the correction tag resolves to the same source commit as the base stable tag. Its Android release reuses the base tag's verified APK and adds provenance for the correction tag. A correction with different source must publish and verify its own package evidence and use a higher Android versionCode.
Release preflight
-
Execute
pnpm check:test-typesprior to the release preflight so that test TypeScript coverage remains intact beyond the quicker localpnpm checkcheck. -
Execute
pnpm check:architectureprior to the release preflight so that the wider import cycle and architecture boundary validations pass outside the quicker local gate. -
Execute
pnpm build && pnpm ui:buildbeforepnpm release:checkso that the anticipateddist/*release artifacts and Control UI bundle are available for the pack validation process. -
Execute
pnpm release:prepfollowing the root version increment and prior to tagging. It runs every deterministic release generator that typically drifts after a version or configuration change: plugin versions, plugin inventory, base config schema, bundled channel config metadata, config docs baseline, plugin SDK exports, and Control UI locale bundles. It also waits until native app translations and platform-generated locale resources align with the source inventory; if they are behind, wait for or triggerNative App Locale Refreshbefore fixing the Code SHA.pnpm release:checkre-runs those checks plus transient npm package-lock validation in check mode (including the strict locale gates and the plugin SDK surface budget) and reports every failure in one pass before executing package release checks. The npm preflight separately compares the exact release SHA with the prior published dist-tag and reports any Plugin SDK API changes. -
Plugin version sync updates the publishable
@openclaw/airuntime package, official plugin package versions, and existingopenclaw.compat.pluginApifloors to the OpenClaw release version by default. Treat that field as the plugin SDK/runtime API floor, not just a copy of the package version: for plugin-only releases that intentionally remain compatible with older OpenClaw hosts, keep the floor at the oldest supported host API and document that choice in the plugin release proof. -
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, cross-OS package checks, QA Lab parity, Matrix, and Telegram lanes. Stable and full runs always include exhaustive live/E2E and Docker release-path soak;run_release_soak=trueis retained for an explicit beta soak. Package Acceptance provides the canonical package Telegram E2E during candidate validation, avoiding a second concurrent live poller.Provide
release_package_specafter publishing a beta to reuse the shipped npm package across release checks, Package Acceptance, and package Telegram E2E without rebuilding the release tarball. Providenpm_telegram_package_speconly when Telegram should use a different published package from the rest of release validation. Providepackage_acceptance_package_specwhen Package Acceptance should use a different published package from the release package spec. Provideevidence_package_specwhen the release evidence report should prove that validation matches a published npm package without forcing Telegram E2E.node scripts/full-release-validation-at-sha.mjs \ --sha <code-sha> \ --target-ref release/YYYY.M.PATCH -
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 a public HTTPS tarball with a required SHA-256 and strict public URL policy;source=trusted-urlfor a named trusted-source policy using requiredtrusted_source_idand SHA-256; orsource=artifactfor a tarball uploaded by another GitHub Actions run.The workflow resolves the candidate to
package-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.update-restart-authuses the candidate package as both the installed CLI and the package-under-test so it exercises the candidate update command's managed restart path.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/restart/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 deterministic normal CI coverage for the release candidate. Manual CI dispatches bypass changed scoping and force the Linux Node shards, bundled-plugin shards, plugin and channel contract shards, Node 22 compatibility,check-*,check-additional-*, built-artifact smoke checks, docs checks, Python skills, Windows, macOS, and Control UI i18n lanes. Standalone manual CI runs Android only when dispatched withinclude_android=true;Full Release Validationpasses that input for its CI child.gh workflow run ci.yml --ref release/YYYY.M.PATCH -f include_android=true -
When validating release telemetry, execute
pnpm qa:otel:smoke. This runs QA-lab through a local OTLP/HTTP receiver and confirms trace, metric, and log export, along with bounded trace attributes and content/identifier redaction, without needing Opik, Langfuse, or any other external collector. -
To check collector compatibility, run
pnpm qa:otel:collector-smoke. It sends the same QA-lab OTLP export through a real OpenTelemetry Collector Docker container before the local receiver assertions take place. -
For protected Prometheus scraping validation, use
pnpm qa:prometheus:smoke. It exercises QA-lab, rejects unauthenticated scrapes, and ensures release-critical metric families remain free of prompt content, raw identifiers, auth tokens, and local paths. -
Execute
pnpm qa:observability:smokefor the source-checkout OpenTelemetry and Prometheus smoke lanes in sequence. -
Run
pnpm release:checkprior to every tagged release. -
The
OpenClaw NPM Releasepreflight generates dependency release evidence before packing the npm tarball. The npm advisory vulnerability gate blocks the release. The transitive manifest risk, dependency ownership/install surface, and dependency change reports serve as release evidence only. The dependency change report compares the release candidate against the previous reachable release tag. The preflight uploads dependency evidence asopenclaw-release-dependency-evidence-<tag>and also embeds it underdependency-evidence/within the prepared npm preflight artifact. The actual publish path reuses that preflight artifact, then attaches the same evidence to the GitHub release asopenclaw-<version>-dependency-evidence.zip. -
After the tag exists, run
OpenClaw Release Publishfor the mutating publish sequence. Dispatch regular beta and stable publishes from trustedmain; the release tag still selects the exact target commit and may point intorelease/YYYY.M.PATCH. Tideclaw alpha publishes remain on their matching alpha branch. Pass the successful OpenClaw npmpreflight_run_id, successfulfull_release_validation_run_id, and exactfull_release_validation_run_attempt, 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; Windows and Android promotion runs concurrently with the core npm publish against the draft release page. Publish reruns are resumable: an already-published core npm version skips the core dispatch after the workflow proves the registry tarball matches the tag's preflight artifact, and Windows/Android promotion is skipped when the release already carries the verified asset contract, so a retry only redoes the failed stages. Focused plugin-only repairs requireplugin_publish_scope=selectedand a nonempty plugin list. Plugin-onlyall-publishableruns require complete immutable preflight and Full Release Validation evidence; partial evidence is rejected. -
Stable
OpenClaw Release Publishrequires an exactwindows_node_tagafter the matching non-prereleaseopenclaw/openclaw-windows-noderelease exists, plus the candidate-approvedwindows_node_installer_digestsmap. Before dispatching any publish child, it verifies that source release is published, non-prerelease, contains the required x64/ARM64 installers, and still matches that approved map. It then dispatchesWindows Node Releasewhile the OpenClaw release is still a draft, carrying the pinned installer digest map unchanged. The child workflow downloads the signed Windows Hub installers from that exact tag, matches them against the pinned digests, verifies their Authenticode signatures use the expected OpenClaw Foundation signer on a Windows runner, writes a SHA-256 manifest, and uploads the installers plus manifest onto the canonical OpenClaw GitHub release, then re-downloads the promoted assets and verifies manifest membership and hashes. The parent verifies the current x64, ARM64, and checksum asset contract before publication. Direct recovery rejects unexpectedOpenClawCompanion-*asset names before replacing the expected contract assets with the pinned source bytes.Manually dispatch
Windows Node Releaseonly for recovery, and always pass an exact tag, neverlatest, plus the explicitexpected_installer_digestsJSON map from the approved source release. Website download links should target exact OpenClaw release asset URLs for the current stable release, orreleases/latest/download/...only after verifying GitHub's latest redirect points at that same release; do not link only to the companion repo release page. -
A separate manual workflow,
OpenClaw Release Checks, now hosts the release checks. It always executes the QA Lab mock parity lane. The Matrix catalog and Telegram QA-live lanes run for stable/full validation, soak-enabled validation, or an explicitqa/qa-livererun group. Bounded beta-publishallwithout soak defers those live lanes to postpublish-confidence. The live lanes use theqa-live-sharedenvironment; Telegram also uses Convex CI credential leases. -
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 tag. -
OpenClaw 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 synthesizesv<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.
-
Before tagging a release candidate locally, run
RELEASE_TAG=vYYYY.M.PATCH-beta.N pnpm release:fast-pretag-check. The helper runs the fast release guardrails, plugin npm/ClawHub release checks, build, UI build, andrelease:openclaw:npm:checkin the order that catches common approval-blocking mistakes before the GitHub publish workflow starts. -
Run
RELEASE_TAG=vYYYY.M.PATCH node --import tsx scripts/openclaw-npm-release-check.ts(or the matching prerelease/correction tag) before approval. -
After npm publish, run
node --import tsx scripts/openclaw-npm-postpublish-verify.ts YYYY.M.PATCH(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.PATCH-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 uses preflight-then-promote:
- Real npm publish must pass a successful npm
preflight_run_id. - Regular beta and stable publish orchestration and preflight use trusted
mainagainst the exact target tag. Tideclaw alpha publish and preflight use the matching alpha branch. - Stable npm releases default to
beta; stable npm publish can targetlatestexplicitly via workflow input. - Token-based npm dist-tag mutation lives in
openclaw/releases/.github/workflows/openclaw-npm-dist-tags.ymlbecausenpm dist-tag addstill needsNPM_TOKENwhile the source 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.PATCH. - Real macOS publish must pass successful macOS
preflight_run_idandvalidate_run_id. - 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.PATCH-N, the post-publish verifier also checks the same temp-prefix upgrade path fromYYYY.M.PATCHtoYYYY.M.PATCH-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 macOS publish workflow commits it automatically, or opens an appcast PR when direct push is blocked); the packaged app must keep a non-debug bundle id, a non-empty Sparkle feed URL, and aCFBundleVersionat or above the canonical Sparkle build floor for that release version.
Release test boxes
Full Release Validation is how operators kick off the full product matrix from one entrypoint. Use the helper so every child workflow runs from a temporary branch fixed at one trusted main workflow SHA while the requested commit remains the candidate under test:
pnpm ci:full-release \
--sha <code-sha> \
--target-ref release/YYYY.M.PATCH
The helper retrieves the current origin/main, publishes release-ci/<workflow-sha>-... at the pinned Tooling SHA, derives beta from alpha/beta package versions or stable when those are absent, and sends Full Release Validation carrying the Validation SHA as expected_sha. Target resolution blocks any mismatch prior to child dispatch. Each child workflow headSha is required to align with the Tooling SHA. Supply -f reuse_evidence=false to compel a fresh execution, -f release_profile=full for the comprehensive advisory scan, or --workflow-sha <trusted-main-sha> to lock in an older compatible commit still accessible from the present origin/main. The helper declines pinned tooling missing the expected_sha dispatch input and never quietly picks a newer Tooling SHA. The workflow itself never writes to repository refs.
Once the Code SHA passes, commit solely CHANGELOG.md and execute the same helper with the Release SHA:
pnpm ci:full-release \
--sha <release-sha> \
--target-ref release/YYYY.M.PATCH
The second parent reuses product evidence only when GitHub confirms the Release SHA is a descendant of the Code SHA and the full set of changed paths equals exactly CHANGELOG.md. It logs changelog-only-release-v1 and skips dispatching product children. Npm preflight and package/install acceptance still execute on the Release SHA because its tarball bytes differ.
For a new Code SHA, the workflow resolves the target, dispatches manual CI, then dispatches OpenClaw Release Checks. Beta-publish corresponds to release_profile=beta and run_release_soak=false; its all run omits broad live/E2E and QA-live lanes. Postpublish-confidence applies the exact published package with soak or explicitly selected focused groups. Stable-publish corresponds to release_profile=stable. The final verifier summary presents slowest-job tables for each child run.
In this release path, the product-performance child is artifact-only. The umbrella dispatches it with publish_reports=false, and validation is refused unless its artifact-only guard verifies that the Clawgrit report publisher stayed skipped.
Refer to Full release validation for the complete stage matrix, precise workflow job names, stable versus full profile differences, artifacts, and focused rerun handles.
Child workflows are dispatched from the SHA-pinned trusted ref that executes Full Release Validation. Every child run must use the exact parent workflow SHA. Avoid raw --ref main -f ref=<sha> dispatches for release proof; use pnpm ci:full-release --sha <target-sha> --target-ref release/YYYY.M.PATCH instead.
Use release_profile to pick live/provider breadth:
beta: quickest release-critical OpenAI/core live and Docker pathstable: beta plus stable provider/backend coverage for release approvalfull: stable plus broad advisory provider/media coverage
Stable and full validation always run the exhaustive live/E2E, Docker release-path, and bounded published upgrade-survivor sweep before promotion. Use run_release_soak=true to request that same sweep for a beta. That sweep covers the latest four stable packages plus pinned 2026.4.23 and 2026.5.2 baselines plus older 2026.4.15 coverage, with duplicate baselines removed and each baseline sharded into its own Docker runner job.
OpenClaw Release Checks uses the trusted workflow ref to resolve the target ref once as release-package-under-test and reuses that artifact in cross-OS, Package Acceptance, and release-path Docker checks when soak runs. This keeps all package-facing boxes on the same bytes and avoids repeated package builds. After a beta is already on npm, set release_package_spec=openclaw@YYYY.M.PATCH-beta.N so release checks download the shipped package once, extract its build source SHA from dist/build-info.json, and reuse that artifact for cross-OS, Package Acceptance, release-path Docker, and package Telegram lanes.
The cross-OS OpenAI install smoke uses OPENCLAW_CROSS_OS_OPENAI_MODEL when the repo/org variable is set, otherwise openai/gpt-5.6-luna, because this lane is proving package install, onboarding, gateway startup, and one live agent turn rather than benchmarking the most capable model. The broader live provider matrix remains the place for model-specific coverage.
Choose among these variants based on release stage:
# Validate the product-complete Code SHA.
pnpm ci:full-release \
--sha <code-sha> \
--target-ref release/YYYY.M.PATCH
# Validate the changelog-only Release SHA by reusing Code SHA product evidence.
pnpm ci:full-release \
--sha <release-sha> \
--target-ref release/YYYY.M.PATCH
# After publishing a beta, add published-package Telegram E2E.
pnpm ci:full-release \
--sha <release-sha> \
--target-ref release/YYYY.M.PATCH \
-f release_package_spec=openclaw@YYYY.M.PATCH-beta.N \
-f evidence_package_spec=openclaw@YYYY.M.PATCH-beta.N \
-f run_release_soak=true \
-f npm_telegram_provider_mode=mock-openai
Do not use the full umbrella as the first rerun after a focused fix. Classify the failure as product, harness/tooling/provenance, infrastructure/credential, or wrapper. Only confirmed product failure changes the Code SHA. Use one diagnosis, one fix when needed, and one narrow retry, then reassess. A narrow green run is evidence, not publish authorization by itself; there is no standalone parent finalizer.
rerun_group=all may reuse a prior green umbrella run when the release profile, effective soak setting, and validation inputs match and either the target SHA is identical or the new target is a descendant whose complete changed path set is exactly CHANGELOG.md. Exact-target reuse records exact-target-full-validation-v1; the post-validation Release SHA records changelog-only-release-v1. The latter reuses only product validation. Npm preflight, package bytes, release-note provenance, and install/update acceptance must still run against the Release SHA. Any version, source, generated, dependency, package, or workflow-owned target change requires a new Code SHA and fresh full validation. Concurrency is keyed by Validation SHA, Tooling SHA, and rerun group and does not cancel prior runs. Parent cancellation leaves adopted children running until the operator cancels the exact child. Pass reuse_evidence=false only when a fresh full run is intentionally required.
For bounded recovery, pass rerun_group to the umbrella. all is the actual release-candidate run, ci executes only the standard CI child, plugin-prerelease executes only the release-only plugin child, release-checks executes 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 need release_package_spec or npm_telegram_package_spec; full/all runs use the canonical package Telegram E2E inside Package Acceptance. Focused cross-OS reruns may include cross_os_suite_filter=windows/packaged-upgrade or another OS/suite filter. QA release-check failures block normal release validation, including OpenClaw dynamic tool drift in the core runtime-pair lane. Tideclaw alpha runs may still treat non-package-safety release-check lanes as advisory. With release_profile=beta, the Run repo/live E2E validation live-provider suites are advisory (warnings, not blockers); stable and full profiles keep them blocking. When live_suite_filter explicitly requests a gated QA live lane such as Discord, WhatsApp, or Slack, the matching OPENCLAW_RELEASE_QA_*_LIVE_CI_ENABLED repo variable must be enabled; otherwise input capture fails instead of silently skipping the lane.
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, plugin and channel contract shards, Node 22 compatibility, check-*, check-additional-*, built-artifact smoke checks, docs checks, Python skills, Windows, macOS, and Control UI i18n. Android is included when Full Release Validation runs the box because the umbrella passes include_android=true; standalone manual CI requires include_android=true for Android coverage.
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. Use the first command for non-Android direct CI. Add include_android=true when direct release-candidate CI must cover Android:
gh workflow run ci.yml --ref main -f target_ref=release/YYYY.M.PATCH
gh workflow run ci.yml --ref main -f target_ref=release/YYYY.M.PATCH -f include_android=true
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-athroughplugins-runtime-install-h, andopenwebui - OpenWebUI coverage on a dedicated large-disk runner 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:
- a mock parity lane that compares the OpenAI candidate lane against the
anthropic/claude-opus-4-8baseline using the agentic parity pack - the Matrix live-adapter catalog lane running on the
qa-live-sharedenvironment - a live Telegram QA lane that relies on Convex CI credential leases
pnpm qa:otel:smoke,pnpm qa:otel:collector-smoke,pnpm qa:prometheus:smoke, orpnpm qa:observability:smokewhen release telemetry needs explicit local proof
This box answers the question "does the release behave correctly in QA scenarios and live channel flows?" When approving the release, retain the artifact URLs for the parity, Matrix, and Telegram lanes. Matrix runs apply the same catalog-derived sharded selection across scheduled, manual, and release workflows.
Package
The Package box serves as the gate for installable products. It relies on Package Acceptance and the resolver scripts/resolve-openclaw-package-candidate.mts. The resolver turns a candidate into the package-under-test tarball that Docker E2E consumes, checks 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 a specific OpenClaw release versionsource=ref: bundle a trustedpackage_refbranch, tag, or full commit SHA with the chosenworkflow_refharnesssource=url: fetch a public HTTPS.tgzwith requiredpackage_sha256; URL credentials, non-default HTTPS ports, private/internal/special-use hostnames or resolved addresses, and unsafe redirects are not allowedsource=trusted-url: fetch an HTTPS.tgzwith requiredpackage_sha256andtrusted_source_idfrom a named policy in.github/package-trusted-sources.json; use this for maintainer-owned enterprise mirrors or private package repositories instead of adding an input-level private-network bypass tosource=urlsource=artifact: reuse a.tgzuploaded by another GitHub Actions run
OpenClaw Release Checks executes Package Acceptance with source=artifact, the prepared release package artifact, suite_profile=custom, docker_lanes=doctor-switch update-channel-switch skill-install update-corrupt-plugin upgrade-survivor published-upgrade-survivor root-managed-vps-upgrade update-restart-auth plugins-offline plugin-update plugin-binding-command-escape, telegram_mode=mock-openai. Package Acceptance validates migration, update, root-managed VPS upgrade, configured-auth update restart, live ClawHub skill install, stale plugin dependency cleanup, offline plugin fixtures, plugin update, plugin command-binding escape hardening, and Telegram package QA against the same resolved tarball. Blocking release checks use the default latest published package baseline; the beta profile with run_release_soak=true, release_profile=stable, or release_profile=full widens the published-upgrade-survivor sweep to last-stable-4 plus the pinned 2026.4.23, 2026.5.2, and 2026.4.15 baselines with reported-issues scenarios. For an already shipped candidate, run Package Acceptance with source=npm; for a SHA-backed local npm tarball before publish, use source=ref; for a maintainer-owned enterprise/private mirror, choose source=trusted-url; or for a prepared tarball uploaded by another GitHub Actions run, go with source=artifact.
It replaces most of the package/update coverage that previously demanded Parallels, directly within GitHub. 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 to determine 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 deliberately 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/restart/plugin package contracts plus live ClawHub skill install proof; 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, turn on telegram_mode=mock-openai or telegram_mode=live-frontier on Package Acceptance. The resolved package-under-test tarball is handed to the Telegram lane by the workflow; the standalone Telegram workflow still takes a published npm spec for post-publish checks.
Regular release publish automation
For beta, latest, plugin, GitHub Release, and platform publication,
OpenClaw Release Publish serves as the standard mutating entrypoint. The monthly
.33+ Gateway extended-stable path bypasses this orchestrator. The
regular workflow sequences the trusted-publisher workflows according to what the
release requires:
- Check out the release tag and resolve its commit SHA.
- Confirm the tag is reachable from
mainorrelease/*(or a Tideclaw alpha branch for alpha prereleases). - Execute
pnpm plugins:sync:check. - Send
Plugin NPM Releasewithpublish_scope=all-publishableandref=<release-sha>. - Send
Plugin ClawHub Releasewith the same scope and SHA. - Send
OpenClaw NPM Releasewith the release tag, npm dist-tag, and savedpreflight_run_idafter checking the savedfull_release_validation_run_idand exact run attempt. - Verify the published npm package and selector readback, then invoke reusable
Docker Releasewith the immutable tag and SHA. For stable releases, create or update the GitHub release as a draft, dispatchWindows Node Releasewith the explicitwindows_node_tagand candidate-approvedwindows_node_installer_digests, and verify the canonical Windows installer/checksum assets. Also dispatchAndroid Releaseto build the exact-tag signed APK plus checksum and provenance. Finalize the GitHub release only after Docker and both native asset contracts succeed.
Beta publish example:
gh workflow run openclaw-release-publish.yml \
--ref main \
-f tag=vYYYY.M.PATCH-beta.N \
-f preflight_run_id=<successful-openclaw-npm-preflight-run-id> \
-f full_release_validation_run_id=<successful-full-release-validation-run-id> \
-f full_release_validation_run_attempt=<successful-full-release-validation-run-attempt> \
-f plugin_sdk_api_acknowledgement=<reviewed-8-character-digest> \
-f npm_dist_tag=beta
Add plugin_sdk_api_acknowledgement only when the npm preflight's Plugin SDK API report shows changes.
Stable publish to the default beta dist-tag:
gh workflow run openclaw-release-publish.yml \
--ref main \
-f tag=vYYYY.M.PATCH \
-f windows_node_tag=vX.Y.Z \
-f windows_node_installer_digests='{"OpenClawCompanion-Setup-x64.exe":"sha256:<approved-x64-sha256>","OpenClawCompanion-Setup-arm64.exe":"sha256:<approved-arm64-sha256>"}' \
-f preflight_run_id=<successful-openclaw-npm-preflight-run-id> \
-f full_release_validation_run_id=<successful-full-release-validation-run-id> \
-f full_release_validation_run_attempt=<successful-full-release-validation-run-attempt> \
-f plugin_sdk_api_acknowledgement=<reviewed-8-character-digest> \
-f npm_dist_tag=beta
Stable promotion directly to latest is explicit:
gh workflow run openclaw-release-publish.yml \
--ref main \
-f tag=vYYYY.M.PATCH \
-f windows_node_tag=vX.Y.Z \
-f windows_node_installer_digests='{"OpenClawCompanion-Setup-x64.exe":"sha256:<approved-x64-sha256>","OpenClawCompanion-Setup-arm64.exe":"sha256:<approved-arm64-sha256>"}' \
-f preflight_run_id=<successful-openclaw-npm-preflight-run-id> \
-f full_release_validation_run_id=<successful-full-release-validation-run-id> \
-f full_release_validation_run_attempt=<successful-full-release-validation-run-attempt> \
-f plugin_sdk_api_acknowledgement=<reviewed-8-character-digest> \
-f npm_dist_tag=latest
Use the lower-level Plugin NPM Release and Plugin ClawHub Release workflows only for focused repair or republish work. OpenClaw Release Publish rejects plugin_publish_scope=selected when publish_openclaw_npm=true so the core package cannot ship without every publishable official plugin, including @openclaw/diffs-language-pack. For a selected plugin repair, set publish_openclaw_npm=false with plugin_publish_scope=selected and plugins=@openclaw/name, or dispatch the child workflow directly.
First-publish ClawHub bootstrap is the exception: dispatch Plugin ClawHub New
from trusted main and pass the full target release SHA through ref.
Never run the bootstrap workflow itself from the release tag or branch:
gh workflow run plugin-clawhub-new.yml \
--ref main \
-f plugins=@openclaw/name \
-f ref=<full-40-character-release-sha> \
-f pretag_validation=true \
-f dry_run=true
Pre-tag validation requires dry_run=true, rejects release-tag and parent-run
inputs, and accepts only an exact target reachable from main or release/*.
It does not load ClawHub credentials, publish package bytes, or alter trusted
publisher configuration. The workflow still resolves the live registry plan,
checks out and packs the target only in a secretless job, materializes the
locked ClawHub toolchain, and validates the immutable artifact and package
slug/identity before the release tag exists. Approve the
clawhub-plugin-bootstrap environment only after the secretless pack jobs
finish; this protected validation job has no credentials or mutation commands.
An approved dry run or real bootstrap after tagging must include the exact
release tag plus the parent OpenClaw Release Publish run id, attempt, and
branch. The parent attests its own workflow SHA and a separate exact trusted
main SHA for Plugin ClawHub New; the child run and every protected
environment approval must match that approved child SHA. The release tag is
rechecked before every publish attempt and trusted-publisher mutation.
The pack job
uploads one immutable artifact whose name, Actions artifact ID/digest,
producer run/attempt, target SHA, and per-package tarball SHA-256/size are
carried into the validation and protected jobs. The protected job checks out trusted main
tooling only, validates the artifact tuple through the GitHub API, downloads
by exact artifact ID, rehashes every tarball, and validates local TAR paths and
package identity with the pinned CLI's USTAR canonicalization rules. Every
candidate then passes the pinned CLI publish dry-run, which returns before
registry lookup or auth. The credential-job prefilter caps compressed ClawPacks
at 120 MiB, total file payload at 50 MiB, expanded TAR data at 64 MiB, and
TAR entry count at 10,000. Existing-package trusted-publisher repair remains
configure-only, but it still packs the target and requires the requested tag
plus exact registry byte and metadata equality before changing trusted-publisher
configuration. Post-publish verification downloads the ClawHub artifact and
requires the same SHA-256 and size. A rerun-failed recovery may reuse an earlier
attempt's package artifact only when the exact producer job completed
successfully. Final evidence also binds the locked ClawHub version, lock
SHA-256, and npm integrity. A mismatch requires a new package version.
NPM workflow inputs
OpenClaw NPM Release accepts these operator-controlled inputs:
tag: the release tag that must be supplied, for examplev2026.4.2,v2026.4.2-1,v2026.4.2-beta.1, orv2026.4.2-alpha.1; when set topreflight_only=true, it can alternatively hold the full 40-character commit SHA from the workflow branch, used only for validation preflight checkspreflight_only: choosetrueto run validation, build, and packaging only, orfalseto execute the actual publishing sequencepreflight_run_id: the id of an earlier successful preflight run, which the real publish path needs so it can reuse the already prepared tarball rather than generating it againfull_release_validation_run_id: a successfulFull Release Validationrun id tied to this tag or SHA, mandatory for actual publishing. Beta releases can proceed with just the preflight and a warning, but stable andlatestpromotions still demand this id.full_release_validation_run_attempt: the exact positive attempt number that pairs withfull_release_validation_run_id; whenever a run id is supplied, this must be included so that reruns cannot alter the authorization proof during publicationrelease_publish_run_id: an approvedOpenClaw Release Publishrun id, required when the parent workflow triggers this one, which happens on bot-actor real-publish callsplugin_npm_run_id: a successful exact-headPlugin NPM Releaserun id, which is mandatory for an actualextended-stablecore releasenpm_dist_tag: the npm target tag used by the publish path; it acceptsalpha,beta,latest, orextended-stableand falls back tobetawhen not given. Final patch releases33and newer must useextended-stable; by default,extended-stablerefuses earlier patches and always rejects tags that are not final.bypass_extended_stable_guard: a boolean meant only for testing, defaulting tofalse; settingnpm_dist_tag=extended-stableskips the monthly extended-stable eligibility gate while still enforcing release identity, artifact, approval, and readback checks.
For existing release behavior, Plugin NPM Release takes npm_dist_tag=default, or npm_dist_tag=extended-stable when the guarded monthly path is wanted. The extended-stable option calls for publish_scope=all-publishable, an empty plugins input, a final patch at or above 33, and the canonical extended-stable/YYYY.M.33 branch sitting exactly at its tip. Plugin latest and beta are never moved by it. New package versions get extended-stable applied atomically through OIDC trusted publication (npm publish --tag extended-stable); this source workflow avoids token-authenticated npm dist-tag add. On retries, exact versions already present in npm are skipped, then the process fails closed unless complete readback verifies that every exact package and extended-stable tag has converged.
Operator-controlled inputs are accepted by OpenClaw Release Publish as follows:
tag: the release tag that is mandatory and must be present beforehandpreflight_run_id: a successful preflight run id fromOpenClaw NPM Release, which is mandatory whenpublish_openclaw_npm=trueorplugin_publish_scope=all-publishableappliesfull_release_validation_run_id: a successful run id fromFull Release Validation, required underpublish_openclaw_npm=trueorplugin_publish_scope=all-publishablefull_release_validation_run_attempt: the exact positive attempt paired withfull_release_validation_run_id, required whenever a run id is suppliedwindows_node_tag: the exact non-prereleaseopenclaw/openclaw-windows-noderelease tag, needed for stable OpenClaw publishingwindows_node_installer_digests: a candidate-approved compact JSON map linking current Windows installer names to their pinnedsha256:digests, required for stable OpenClaw publishingnpm_telegram_run_id: an optional successfulNPM Telegram Beta E2Erun id to include in the final release evidencenpm_dist_tag: the npm target tag for the OpenClaw package, chosen fromalpha,beta,latest, orextended-stablepublish_docker_only: the recovery and closeout path limited to extended-stable. It demandspublish_openclaw_npm=false, complete preflight and Full Release Validation evidence, then checks the exact npm package, selector, and tarball digest before triggering Docker publication.plugin_publish_scope: defaults toall-publishable;selectedis reserved for focused plugin-only repair work withpublish_openclaw_npm=falseplugins: comma-separated@openclaw/*package names whenplugin_publish_scope=selectedis in effectpublish_openclaw_npm: defaults totrue; assignfalseonly when the workflow acts as a plugin-only repair orchestratorrelease_profile: the release coverage profile for release evidence summaries, defaulting tofrom-validation, which pulls it from the validation manifest, or overridden bybeta,stable, orfullwait_for_clawhub: defaults tofalseso npm availability is not delayed by the ClawHub sidecar; settrueonly when workflow completion must wait for ClawHub completion
OpenClaw Release Checks takes these operator-controlled inputs:
ref: a branch, tag, or full commit SHA to validate. Checks involving secrets require the resolved commit to be reachable from an OpenClaw branch or release tag.run_release_soak: opt into exhaustive live/E2E, Docker release-path, and all-since upgrade-survivor soak for beta release checks.release_profile=stableandrelease_profile=fullforce this on.
Rules:
- Regular final and correction versions below patch
33can publish to eitherbetaorlatest. Final versions at patch33or higher must publish toextended-stable, and correction-suffix versions at that boundary are rejected. - Beta prerelease tags can only publish to
beta; alpha prerelease tags can only publish toalpha - For
OpenClaw NPM Release, full commit SHA input is allowed only whenpreflight_only=trueholds OpenClaw Release ChecksandFull Release Validationare always validation-only- The real publish path must reuse the same
npm_dist_tagfrom preflight; the workflow verifies that metadata before publish continues
Regular beta/latest stable release sequence
This older workflow covers the standard orchestrated release, which also handles plugins, GitHub Release, Windows, and other platform-related tasks. It is separate from the monthly .33+ Gateway extended-stable process described earlier on this page.
For a regular orchestrated stable release:
- Execute
OpenClaw NPM Releasewithpreflight_only=true. If no tag exists yet, the current full workflow-branch commit SHA can be used for a validation-only dry run of the preflight workflow. - Pick
npm_dist_tag=betafor the standard beta-first approach, orlatestonly when a direct stable publish is explicitly intended. - Run
Full Release Validationagainst the release branch, release tag, or full commit SHA to get normal CI plus live prompt cache, Docker, QA Lab, Matrix, and Telegram coverage from a single manual workflow. If only the deterministic normal test graph is needed, use the manualCIworkflow on the release ref instead. - Choose the exact non-prerelease
openclaw/openclaw-windows-noderelease tag whose signed x64 and ARM64 installers are to ship. Store it aswindows_node_tag, and store their validated digest map aswindows_node_installer_digests. The release-candidate helper records both and embeds them in the publish command it generates. - Save the successful
preflight_run_id,full_release_validation_run_id, and the exactfull_release_validation_run_attempt. - Run
OpenClaw Release Publishfrom trustedmainwith the sametag, the samenpm_dist_tag, the selectedwindows_node_tag, its savedwindows_node_installer_digests, the savedpreflight_run_id,full_release_validation_run_id, andfull_release_validation_run_attempt. This publishes externalized plugins to npm and ClawHub before promoting the OpenClaw npm package. - If the release landed on
beta, use theopenclaw/releases/.github/workflows/openclaw-npm-dist-tags.ymlworkflow to promote that stable version frombetatolatest. - If the release deliberately published directly to
latestandbetashould immediately follow the same stable build, use that same release workflow to point both dist-tags at the stable version, or let its scheduled self-healing sync movebetalater.
The dist-tag change lives in the release ledger repo because it still requires NPM_TOKEN, while the source repo keeps OIDC-only publish. This keeps both the direct publish path and the beta-first promotion path documented and visible to operators.
If a maintainer needs to 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.yml.github/workflows/docker-release.ymlscripts/resolve-openclaw-package-candidate.mtsscripts/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.