OpenClaw Release Policy: Channels, Versioning, and Cadence
This page describes OpenClaw's four update channels, version naming conventions, and release cadence. It is intended for operators and developers managing deployments or consuming OpenClaw packages.
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 access:
- stable: the promoted regular release available on npm
latest - extended-stable: the trailing completed month's
.33+maintenance line on npmextended-stable - beta: prerelease tags distributed through npm
beta - dev: the moving head of
main
The extended-stable channel delivers the trailing month's Gateway, official npm plugins, and Docker images without updating the regular latest or main selectors.
Tideclaw alpha builds operate as a separate internal prerelease track (npm dist-tag alpha), documented under NPM workflow inputs and Release test boxes.
Version naming
- Monthly Gateway extended-stable release version:
YYYY.M.PATCH, withPATCH >= 33, git tagvYYYY.M.PATCH - Daily or regular final release version:
YYYY.M.PATCH, 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 - Never zero-pad month or patch
PATCHis a sequential monthly release train number, not a calendar day. Regular final and beta releases advance the current train; alpha only tags never consume or advance the beta or regular patch number, so ignore legacy alpha only tags with higher patch numbers when selecting a beta or regular train.- Alpha and nightly builds use the next unreleased patch train and increment only
alpha.Nfor repeated builds. Once that patch has a beta, new alpha builds move to the following patch. - npm versions are immutable: never delete, republish, or reuse a published tag. Instead, cut the next prerelease number or the next monthly patch.
latestcontinues to follow the current regular or daily npm line;betais the current beta install targetextended-stablemeans the supported trailing month Gateway distribution, beginning at patch33; patch34and later are maintenance releases on that monthly line- Regular final and regular correction releases publish to npm
betaby default; release operators can targetlatestexplicitly, or promote a vetted beta build later - Gateway extended-stable publishes core, every npm publishable official plugin, and its Docker images at one exact version; see the dedicated workflow below.
- Every regular final release ships the npm package, macOS app, signed standalone Android APK, and signed Windows Hub installers together. Beta releases normally validate and publish the npm or package path first, with native app build, sign, notarize, and promote reserved for regular final 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.PATCHbranch 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 one - Detailed release procedure, approvals, credentials, and recovery notes are maintainer only
Monthly Gateway extended-stable publication
For completed month YYYY.M, create extended-stable/YYYY.M.33 and publish .33+ from that branch. Tag, branch, checkout, package version, preflight, and validation must identify one commit. Before .33, protected main must contain a later month's final version below patch 33; later maintenance patches remain eligible.
Prepare and stabilize the candidate
Audit the unaudited mainline range, reconcile private security work, approve a bounded backport set, and land one coordinated PR. Do not push the canonical branch directly.
On the canonical branch, set YYYY.M.P, run pnpm release:prep, and require that version in every publishable official plugin. From the approved ledger, generate and commit a complete ## YYYY.M.P section with ### Highlights, ### Changes, and ### Fixes, citing original merged main PRs for equivalent backports. Preflight rejects a missing or empty section.
Carry the full 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 move regular aliases. Run focused checks.
Freeze 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 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.
Classify failures before editing:
- Product: land another approved backport PR.
- Frozen target tooling: backport only the smallest compatibility repair that tests the old product unchanged.
- Provider, approval, runner, or service: keep the candidate unchanged and use the bounded retry path.
Any branch change invalidates both gates. Once they pass, require the tip still equals RELEASE_SHA, then push signed vYYYY.M.P. Later changes need the next patch; never move or delete the tag. Its push starts Docker Release.
Publish the npm packages
Publish every npm publishable official plugin from the same SHA and save 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 processes every all-publishable package, including those that have not changed, and confirms each exact version and selector. Already published versions are reused on reruns.
After that, publish the prepared core tarball using all three stored run identities:
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>
For testing outside of production only, append -f bypass_extended_stable_guard=true to both preflight and publish commands. This skips just the month guard, not canonical-ref, SHA/tag/version equality, provenance, approval, or readback checks. Do not use this flag in production.
Verify and recover
From a separate clean checkout of current main, not from 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 required for the canonical branch, along with binding publish, preflight, and tarball-digest to the release SHA. Both commands must return YYYY.M.P. Check every prepared core package and all-publishable official plugin at its exact version and selector.
When only the root selector fails, apply the npm dist-tag add openclaw@YYYY.M.P extended-stable repair command that the workflow summary prints. Fix existing plugin or other prepared-core selectors using approved credential-isolated tooling; the OIDC source cannot change them. Never republish an immutable version.
Require Docker Release to confirm 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 stay unchanged and automatic rollback is disallowed.
For alias repair, run approval-gated Docker Channel Promotion from current main with the tag. It repeats digest, attestation, and platform checks, permits an explicit rollback, and never rebuilds images.
Slack, Discord, and Codex are the initially documented support surfaces, not a release allowlist: every npm-publishable official plugin ships. Only the regular checklist manages beta/latest, GitHub Releases, ClawHub, native apps, mobile, website, and private dist-tags; do not execute those steps for this Gateway path.
Regular release operator checklist
This checklist represents the public form of the release process. Private credentials, signing, notarization, dist-tag recovery, and emergency rollback details remain in the maintainer-only release runbook.
-
Start from current
main: pull the latest, verify 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. Run the deterministic source preflight, then use
node scripts/full-release-validation-at-sha.mjs --sha <code-sha> --target-ref release/YYYY.M.PATCH. This pins trusted workflow tooling while the full Vitest, Docker, QA, package, and performance matrix targets the exact Code SHA. -
Classify failures before editing. A product/code failure produces a new Code SHA and requires green full validation for that SHA. A workflow, harness, credential, approval, or infrastructure failure is repaired in its owning surface and rerun against the same Code SHA.
-
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. -
Tag the Release SHA, then run the candidate helper with the successful Release-SHA validation parent and npm preflight instead of dispatching either again:
pnpm release:candidate -- \ --tag vYYYY.M.PATCH-beta.N \ --full-release-run <release-sha-validation-run-id> \ --npm-preflight-run <preflight-run-id> \ --skip-dispatchFor stable, also pass
--windows-node-tag vX.Y.Z. The helper verifies release-note provenance, npm preflight bytes, Parallels install/update proof, Telegram package proof, and plugin publish plans, then prints the publish command.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. 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, closes out the release page and dependency evidence once those stages succeed, 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 the post-publish package acceptance against the published
openclaw@YYYY.M.PATCH-beta.Noropenclaw@betapackage. If a pushed or published prerelease needs a fix, cut the next matching prerelease number; never delete or rewrite the old one. -
If a publish attempt fails, leave the Release SHA unchanged unless the failure points to a flaw in the product or changelog. Resume any successful immutable children and artifacts; never rebuild or republish a package version that already completed successfully.
-
For a stable release, proceed only after the vetted beta or release candidate has the required validation evidence. Publishing the stable npm package also goes through
OpenClaw Release Publish, reusing the successful preflight artifact viapreflight_run_id. For a stable macOS release, readiness also requires the packaged.zip,.dmg,.dSYM.zip, and an updatedappcast.xmlonmain; the macOS publish workflow publishes the signed appcast to the publicmainautomatically once release assets are verified, or it opens or updates an appcast PR if branch protection prevents a direct push. Stable Windows Hub readiness requires 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 Publishkeeps the release draft, dispatchesWindows Node Release, and verifies all three assets before publication. -
After publishing, run the npm post-publish verifier, the optional standalone published-npm Telegram E2E when you need post-publish channel proof, promote dist-tags as needed, verify the generated GitHub release page, execute the release announcement steps, and then complete Stable main closeout before declaring a stable release finished.
Stable main closeout
A stable publication is not complete until main contains the actual shipped release state.
-
Start from the latest clean
main. Auditrelease/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, set
mainto the shipped stable version. A late closeout may usemainafter it has advanced to a later stable OpenClaw CalVer; do not downgrade an already-started release train solely to close the prior release. The validator still requires the exact shipped changelog section and appcast entry and records the actualmainversion and SHA. Runpnpm release:prepafter any root version change, thenpnpm deps:shrinkwrap:generate. -
Make
CHANGELOG.md's## YYYY.M.PATCHsection onmainexactly match the tagged release branch. Include the stableappcast.xmlupdate when the macOS 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:shrinkwrap:check, andOPENCLAW_TESTBOX=1 pnpm check:changed. Push, then verifyorigin/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 starts from the main push that carries the shipped version, changelog, and appcast after stable publication. It reads immutable postpublish evidence to bind the shipped tag to its Full Release Validation and Publish runs, then verifies 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 completed closeout.
A complete closeout requires both assets and a matching checksum. A partial manifest replays its recorded main SHA and rollback drill to regenerate 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 remain 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 TypeScript testing remains covered outside the faster localpnpm checkgate. -
Execute
pnpm check:architecturebefore the release preflight to ensure broader import cycle and architecture boundary checks pass outside the faster local gate. -
Execute
pnpm build && pnpm ui:buildbeforepnpm release:checkso the expecteddist/*release artifacts and Control UI bundle exist for pack validation. -
Execute
pnpm release:prepafter the root version bump and before tagging. It runs every deterministic release generator that commonly drifts after a version, config, or API change: plugin versions, npm shrinkwraps, plugin inventory, base config schema, bundled channel config metadata, config docs baseline, plugin SDK exports, the Plugin SDK API contract manifest, and Control UI locale bundles. It also blocks until native app translations and platform-generated locale resources match the source inventory; if they lag, wait for or dispatchNative App Locale Refreshbefore freezing the Code SHA.pnpm release:checkre-runs those guards in check mode (including the strict locale gates plus the plugin SDK surface budget) and reports every generated drift failure in one pass before running package release checks. -
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 or 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 and 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.Supply
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. Supplynpm_telegram_package_speconly when Telegram should use a different published package from the rest of release validation. Supplypackage_acceptance_package_specwhen Package Acceptance should use a different published package from the release package spec. Supplyevidence_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, or 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, and 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 -
Execute
pnpm qa:otel:smoketo validate release telemetry. This test runs QA-lab against a local OTLP/HTTP receiver, confirming trace, metric, and log export along with bounded trace attributes and content/identifier redaction, without relying on Opik, Langfuse, or any external collector. -
Execute
pnpm qa:otel:collector-smoketo validate collector compatibility. It sends the same QA-lab OTLP export through a real OpenTelemetry Collector Docker container before reaching the local receiver assertions. -
Execute
pnpm qa:prometheus:smoketo validate protected Prometheus scraping. This test runs QA-lab, blocks unauthenticated scrape requests, and confirms that release-critical metric families contain no prompt content, raw identifiers, auth tokens, or local paths. -
Execute
pnpm qa:observability:smoketo run the source-checkout OpenTelemetry and Prometheus smoke lanes consecutively. -
Execute
pnpm release:checkbefore 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 with the previous reachable release tag. The preflight uploads dependency evidence asopenclaw-release-dependency-evidence-<tag>and also embeds it underdependency-evidence/inside 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. -
Execute
OpenClaw Release Publishfor the mutating publish sequence after the tag exists. 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 handles release checks. It also executes the QA Lab mock parity lane, the Matrix release profile, and the Telegram QA lane prior to release approval. The live lanes operate within theqa-live-sharedenvironment, while Telegram additionally uses Convex CI credential leases. When you need to run every maintained Matrix scenario, trigger the manualQA-Lab - All Lanesworkflow withmatrix_profile=all; the workflow distributes that selection across the transport, media, and E2EE profiles to maintain full proof within per-job time limits. -
Cross-OS install and upgrade runtime validation is part of the public
OpenClaw Release ChecksandFull Release Validationworkflows, which directly invoke the reusable workflow.github/workflows/openclaw-cross-os-release-checks-reusable.yml. This separation is deliberate: keep the actual npm release path short, deterministic, and focused on artifacts, while slower live checks remain in their own lane so they don't delay or block publishing. -
Release checks that involve secrets should be dispatched through
Full Release Validationor from themain/release workflow ref to keep workflow logic and secrets under control. -
OpenClaw Release Checksaccepts a branch, tag, or full commit SHA, provided the resolved commit is reachable from an OpenClaw branch or release tag. -
The
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 an actual publish. In SHA mode, the workflow generatesv<package.json version>only for the package metadata check; real publishing still demands a genuine release tag. -
Both workflows keep the actual 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. -
The npm release preflight no longer waits on the separate release checks lane.
-
Before tagging a release candidate locally, execute
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 begins. -
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 temporary 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 can omit the Convex variables and pass the threeOPENCLAW_QA_TELEGRAM_*environment 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 outputs the Telegram report. -
Maintainers can run the same post-publish check from GitHub Actions via the manual
NPM Telegram Beta E2Eworkflow. This is intentionally manual-only and does not execute on every merge. -
Maintainer release automation uses a preflight-then-promote approach:
- Real npm publish requires 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 through 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 exists only on a release branch but the workflow is dispatched frommain, setpublic_release_branch=release/YYYY.M.PATCH. - Real macOS publish requires successful macOS
preflight_run_idandvalidate_run_id. - Real publish paths promote prepared artifacts instead of rebuilding them.
- Real npm publish requires 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. -
The npm release preflight fails closed unless the tarball contains both
dist/control-ui/index.htmland a non-emptydist/control-ui/assets/payload, preventing the shipment of an empty browser dashboard again. -
Post-publish verification also confirms that published plugin entrypoints and package metadata exist 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 don't 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, pushes release-ci/<workflow-sha>-... at that trusted workflow commit, determines beta from alpha or beta package versions and stable otherwise, triggers Full Release Validation from the temporary branch using ref=<target-sha>, confirms each child workflow headSha matches the pinned parent workflow SHA, then removes the temporary branch. Provide -f reuse_evidence=false to enforce a new run, -f release_profile=full for the wide advisory scan, or --workflow-sha <trusted-main-sha> to pin an older commit still accessible from the current origin/main. The workflow never writes repository refs. This keeps main-only release tooling accessible without adding tooling commits to the candidate and prevents accidentally proving a newer main child run.
Once the Code SHA passes, commit only 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 descends from the Code SHA and the complete set of changed paths is exactly CHANGELOG.md. It records changelog-only-release-v1 and does not trigger any product children. Npm preflight and package or install acceptance still execute on the Release SHA because its tarball bytes changed.
For a new Code SHA, the workflow resolves the target, sends manual CI, then sends OpenClaw Release Checks. OpenClaw Release Checks fans out install smoke, cross-OS release checks, live and E2E Docker release-path coverage when soak is enabled, Package Acceptance with the canonical Telegram package E2E, QA Lab parity, live Matrix, and live Telegram. A full or all run is acceptable only when the Full Release Validation summary shows normal_ci, plugin_prerelease, and release_checks as successful, unless a targeted rerun deliberately omitted the separate Plugin Prerelease child. Use the standalone npm-telegram child only for a targeted published-package rerun with release_package_spec or npm_telegram_package_spec. The final verifier summary includes slowest-job tables for each child run, so the release manager can identify the current critical path without downloading logs.
The product-performance child is artifact-only in this release path. The umbrella sends it with publish_reports=false, and validation is rejected unless its artifact-only guard confirms the Clawgrit report publisher remained skipped.
Refer to Full release validation for the complete stage matrix, exact workflow job names, differences between stable and full profiles, artifacts, and targeted rerun handles.
Child workflows are dispatched from the SHA-pinned trusted ref that runs Full Release Validation. Every child run must use the exact parent workflow SHA. Do not use raw --ref main -f ref=<sha> dispatches for release proof; use pnpm ci:full-release --sha <target-sha> --target-ref release/YYYY.M.PATCH.
Use release_profile to choose live or provider breadth:
beta: fastest release-critical OpenAI core live and Docker pathstable: beta plus stable provider and backend coverage for release approvalfull: stable plus broad advisory provider and media coverage
Stable and full validation always run the exhaustive live and 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 or org variable is set, otherwise openai/gpt-5.6-luna, because this lane validates 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.
Use these variants depending 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 npm_telegram_provider_mode=mock-openai
Do not use the full umbrella as the first rerun after a targeted 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.
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 or 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. Newer umbrella runs for the same release/* ref and rerun group automatically supersede in-progress ones. Provide reuse_evidence=false to force a fresh full run.
For bounded recovery, supply rerun_group to the umbrella. all represents the actual release-candidate execution, ci runs only the standard CI child, plugin-prerelease runs only the release-specific plugin child, release-checks runs every release box, and the more constrained release groups are install-smoke, cross-os, live-e2e, package, qa, qa-parity, qa-live, and npm-telegram. Targeted npm-telegram reruns require release_package_spec or npm_telegram_package_spec; full or all runs use the canonical package Telegram E2E inside Package Acceptance. Targeted cross-OS reruns may include cross_os_suite_filter=windows/packaged-upgrade or another OS or suite filter. QA release-check failures block standard release validation, including OpenClaw dynamic tool drift in the core runtime-pair lane. Tideclaw alpha runs may still consider 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 like Discord, WhatsApp, or Slack, the matching OPENCLAW_RELEASE_QA_*_LIVE_CI_ENABLED repo variable must be enabled; otherwise input capture fails rather than silently skipping the lane.
Vitest
The Vitest box is the manual CI child workflow. Manual CI deliberately 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 or reuse by target SHA, with QR, root/gateway, and installer or 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 or uninstall lanes
bundled-plugin-install-uninstall-0throughbundled-plugin-install-uninstall-23 - live or 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 or 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 to the
anthropic/claude-opus-4-8baseline using the agentic parity pack - A Matrix live-adapter release profile that runs in 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 requires explicit local proof
Use this box to answer: "does the release behave correctly in QA scenarios and live channel flows?" When approving the release, keep the artifact URLs for the parity, Matrix, and Telegram lanes. Full Matrix coverage is still available as a manual sharded QA-Lab run rather than the default release-critical lane.
Package
The Package box serves as the gate for installable products. It relies on 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 a public HTTPS.tgzwith requiredpackage_sha256; URL credentials, non-default HTTPS ports, private/internal/special-use hostnames or resolved addresses, and unsafe redirects are rejectedsource=trusted-url: download 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 runs 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 covers 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 expands 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. Use Package Acceptance with source=npm for an already shipped candidate, source=ref for a SHA-backed local npm tarball before publish, source=trusted-url for a maintainer-owned enterprise/private mirror, or source=artifact for a prepared tarball uploaded by another GitHub Actions run.
This is the GitHub-native replacement for most 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/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 within Package Acceptance. The resolved package-under-test tarball is passed by the workflow into the Telegram lane; the standalone Telegram workflow still accepts a published npm spec for post-publish checks.
Regular release publish automation
For beta, latest, plugin, GitHub Release, and platform publication, the normal mutating entrypoint is OpenClaw Release Publish. The monthly .33+ Gateway extended-stable path bypasses this orchestrator. The regular workflow coordinates the trusted-publisher workflows in the required release order:
- 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. - Trigger
Plugin NPM Releasewithpublish_scope=all-publishableandref=<release-sha>. - Trigger
Plugin ClawHub Releaseusing the same scope and SHA. - Trigger
OpenClaw NPM Releasewith the release tag, npm dist-tag, and savedpreflight_run_idafter verifying the savedfull_release_validation_run_idand exact run attempt. - For stable releases, create or update the GitHub release as a draft, trigger
Windows Node Releasewith the explicitwindows_node_tagand candidate-approvedwindows_node_installer_digests, and verify the canonical Windows installer and checksum assets. Also triggerAndroid Releaseto build the exact-tag signed APK plus checksum and provenance. Verify both native asset contracts before publishing the draft.
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 npm_dist_tag=beta
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 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 npm_dist_tag=latest
Use the lower-level Plugin NPM Release and Plugin ClawHub Release workflows only for targeted 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 trigger the child workflow directly.
First-publish ClawHub bootstrap is the exception: trigger 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 and 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 and digest, producer run and attempt, target SHA, and per-package tarball SHA-256 and 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 mandatory release tag, for instancev2026.4.2,v2026.4.2-1,v2026.4.2-beta.1, orv2026.4.2-alpha.1; whenpreflight_only=trueis set, it can also be the full 40 character workflow branch commit SHA used only for a validation preflight.preflight_only:truewhen performing only validation, build, or packaging, andfalsefor the actual publication path.preflight_run_id: an identifier from a prior successful preflight run, mandatory on the real publish path so the workflow reuses the already prepared tarball rather than building it again.full_release_validation_run_id: a successfulFull Release Validationrun identifier for this tag or SHA, required for a real publish. Beta releases may proceed using only a preflight with a warning, but stable orlatestpromotion still demands it.full_release_validation_run_attempt: the exact positive run attempt linked withfull_release_validation_run_id; required whenever the run identifier is supplied so that reruns cannot alter the authorization proof during publishing.release_publish_run_id: an approvedOpenClaw Release Publishrun identifier; required when this workflow is triggered by that parent process (bot actor real publish calls).plugin_npm_run_id: a successful exact headPlugin NPM Releaserun identifier; required for an actualextended-stablecore publish.npm_dist_tag: the npm target tag for the publish path; acceptsalpha,beta,latest, orextended-stableand defaults tobeta. Final patch33and later must useextended-stable; by default,extended-stablerefuses earlier patches, and it always refuses non final tags.bypass_extended_stable_guard: a testing only boolean, defaultfalse; withnpm_dist_tag=extended-stable, it skips monthly extended stable eligibility while keeping the release identity, artifact, approval, and readback checks intact.
Plugin NPM Release accepts npm_dist_tag=default for existing release behavior or npm_dist_tag=extended-stable for the guarded monthly path. The extended stable option requires publish_scope=all-publishable, an empty plugins input, a final patch at or above 33, and the canonical extended-stable/YYYY.M.33 branch at its exact tip. It never moves plugin latest or beta. New package versions receive extended-stable atomically through OIDC trusted publication (npm publish --tag extended-stable); this source workflow does not use token authenticated npm dist-tag add. Retries skip exact versions already present in npm, then fail closed unless complete readback confirms that every exact package and extended-stable tag converged.
OpenClaw Release Publish accepts these operator controlled inputs:
tag: the release tag is mandatory and must already be presentpreflight_run_id: a validOpenClaw NPM Releasepreflight run identifier; required whenpublish_openclaw_npm=trueorplugin_publish_scope=all-publishablefull_release_validation_run_id: a validFull Release Validationrun identifier; required whenpublish_openclaw_npm=trueorplugin_publish_scope=all-publishablefull_release_validation_run_attempt: the exact positive attempt number linked withfull_release_validation_run_id; mandatory whenever the run id is suppliedwindows_node_tag: the exact non-prereleaseopenclaw/openclaw-windows-noderelease tag; mandatory for a stable OpenClaw publicationwindows_node_installer_digests: a candidate-approved compact JSON mapping of current Windows installer names to their pinnedsha256:digests; mandatory for a stable OpenClaw publicationnpm_telegram_run_id: an optional validNPM Telegram Beta E2Erun identifier to embed in the final release evidencenpm_dist_tag: the npm target tag for the OpenClaw package, chosen fromalpha,beta, orlatestplugin_publish_scope: defaults toall-publishable; setselectedonly for targeted plugin-only fixes usingpublish_openclaw_npm=falseplugins: package names from@openclaw/*separated by commas whenplugin_publish_scope=selectedpublish_openclaw_npm: defaults totrue; specifyfalseonly when the workflow serves as a plugin-only repair coordinatorrelease_profile: the release coverage profile used for evidence summaries; defaults tofrom-validation, which reads it from the validation manifest, or override withbeta,stable, orfullwait_for_clawhub: defaults tofalseso npm availability is not blocked by the ClawHub sidecar; specifytrueonly when workflow completion must wait for ClawHub to finish
OpenClaw Release Checks accepts these inputs controlled by the operator:
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 full live/E2E, Docker release-path, and all-since upgrade-survivor soak for beta release checks. This is forced on byrelease_profile=stableandrelease_profile=full.
Rules:
- Regular final and correction versions below patch
33may publish to eitherbetaorlatest. Final versions at patch33or higher must publish toextended-stable, and correction-suffix versions at that boundary are rejected. - Beta prerelease tags may publish only to
beta; alpha prerelease tags may publish only toalpha - For
OpenClaw NPM Release, a full commit SHA is allowed only whenpreflight_only=true OpenClaw Release ChecksandFull Release Validationare always validation-only- The actual publish path must use the same
npm_dist_tagused during preflight; the workflow checks that metadata before proceeding with publication
Regular beta/latest stable release sequence
This older sequence handles the standard orchestrated release that also manages plugins, GitHub Release, Windows, and other platform tasks. It is not the monthly .33+ Gateway extended-stable path described at the top of this page.
When performing a standard orchestrated stable release:
- Execute
OpenClaw NPM Releasetogether withpreflight_only=true. In the absence of a tag, the current full workflow-branch commit SHA can be used for a preflight workflow dry run that only validates. - Select
npm_dist_tag=betafor the standard beta-first approach, or picklatestonly when a direct stable publish is deliberately required. - On the release branch, release tag, or full commit SHA, run
Full Release Validationto get normal CI along with live prompt cache, Docker, QA Lab, Matrix, and Telegram coverage from a single manual workflow. If only the deterministic normal test graph is intentionally needed, run the manualCIworkflow against the release ref instead. - Pick the exact non-prerelease
openclaw/openclaw-windows-noderelease tag whose signed x64 and ARM64 installers must ship. Store it aswindows_node_tag, and store their validated digest map aswindows_node_installer_digests. The release-candidate helper records both and includes them in the publish command it generates. - Save the successful
preflight_run_id,full_release_validation_run_id, and the precisefull_release_validation_run_attempt. - From trusted
main, runOpenClaw Release Publishwith the sametag, the samenpm_dist_tag, the selectedwindows_node_tag, its storedwindows_node_installer_digests, the storedpreflight_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. - When the release landed on
beta, use theopenclaw/releases/.github/workflows/openclaw-npm-dist-tags.ymlworkflow to promote that stable version frombetatolatest. - If the release was intentionally 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 mutation lives in the release ledger repo because NPM_TOKEN is still required there, 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 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.yml.github/workflows/docker-release.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.