This checklist is for final release readiness before tagging, publishing artifacts, updating client schemas, or deploying a new WebCodex server/Runner/runtime build.
It governs release/publish rollouts and deployment of published releases. An explicitly requested development/dogfood deployment of a reviewed commit is governed by AGENTS.md and Runner Release Process Notes: it does not require the version/tag/publication/artifact steps below, but it still uses the focused post-deployment smoke in section 10 where applicable.
Do not create tags, push commits, publish npm packages, create GitHub Releases, rewrite history, deploy, or touch secrets while running this checklist unless the operator explicitly requests that action.
Choose the exact release source before release prep. The preferred path is to cut release/v<VERSION> from the reviewed main commit selected for the release; a hotfix may cut that branch from the previous immutable release tag instead. Put version bumps, release-facing metadata, and release-only fixes on that branch (normally through a PR targeting the release branch). Once the release branch exists, main may continue accepting unrelated development PRs. main remains a supported source ref for simple releases, but it no longer has to stay frozen while a release is validated or published. Final pre-tag validation is a reviewed GitHub Actions workflow, not a sequence of hand-run release-host commands:
python3 scripts/release_operator.py readiness-start \
--source-ref <SOURCE_REF> \
--source-sha <SOURCE_COMMIT> \
--state-file <STATE_FILE>
python3 scripts/release_operator.py readiness-status \
--state-file <STATE_FILE> \
--wait-secs 3600readiness-start first requires the selected GitHub <SOURCE_REF> (main or exactly release/v<VERSION>) to equal <SOURCE_COMMIT> and requires exactly one successful push CI run for that exact branch/source pair. It records the source ref plus that CI run id and attempt in the mode-0600 operator-local state before dispatch, then passes the proof into .github/workflows/release-readiness.yml. The workflow runs from the selected source branch, re-fetches that exact immutable CI attempt with read-only Actions authority, and fails closed unless it is the successful .github/workflows/ci.yml push run for that source ref and source SHA. Readiness never tags, publishes, deploys, uploads release candidates, rebuilds the six native release archives, or produces formal release candidates.
If dispatch delivery becomes uncertain or the run is not resolved before the short start timeout, do not create a second state file and do not redispatch. Continue with readiness-status on the original state; its unique request id recovers the exact workflow run when present. Only terminal success (operator exit 0) satisfies the pre-tag gate. A nonterminal/unresolved status is not release approval.
The evidence graph deliberately avoids making scarce native runners part of every development cycle. Exact source-branch push CI remains the common correctness authority: it runs formatting/frontend/workspace boundaries, complete Linux Rust package shards, the deterministic release static/tooling contract, and path-aware Windows x64, macOS Apple-Silicon, Desktop, and amd64 Server-image checks. Release readiness first proves that exact CI attempt, then invokes extended-native.yml for native Linux ARM64, macOS Intel/Desktop, and Windows ARM64/Desktop validation of the same source while release-specific WebSocket/polling zero-config E2E and coding-loop compare eval run independently. After E2E/eval succeed, readiness also builds the disposable native linux/amd64 and linux/arm64 Server images, verifies runtime/health/non-root/bootstrap generation, and discards them. The six native release-profile/ABI/PE/Mach-O/package surfaces and four formal Desktop distribution artifacts are intentionally not built before tagging; .github/workflows/release-build.yml remains their single authoritative builder after the immutable tag exists. The eval job explicitly builds debug Server/Runner fixtures before running the harness so cold-runner compilation is not misclassified as a service-start timeout.
For focused diagnosis outside the final workflow, the underlying commands remain available, but a local pass does not replace the exact-source readiness run.
During implementation/review, run focused lanes when touching runtime metadata, schemas, OpenAPI, MCP, session, handoff, validation, or coding-task behavior. Exact-source CI owns the full Linux package suites plus deterministic metadata/schema/OpenAPI/MCP and release-tooling evidence; release-readiness binds that successful source-branch CI attempt instead of repeating it. Re-run an individual lane only to diagnose a failure or when a review explicitly requires separate evidence.
Confirm the user-facing docs tell one story:
- README states the product position in the first screen and clearly separates full daily use from temporary
share. - Full Setup has one recommended regular Server + Runner path for ordinary daily use; Quick Trial stays focused on temporary single-project
share. - Concepts explains server, Runner, Runner-registered projects, runtime project ids, ToolRuntime, MCP, GPT Actions, session, handoff, validation, review/hygiene, and
run_shellas a bounded shell primitive for real shell semantics or short related command chains. - Architecture starts with client/server/Runner/codebase, security-boundary, and runtime-module diagrams before Rust module notes.
- MCP and GPT Actions both say they call the same WebCodex ToolRuntime.
- Security explains what the model can and cannot do, project access, Runner trust boundary, shell/job risk, token handling, session/audit evidence, and revocation.
- The release PR / GitHub Release notes read like external release notes and include highlights, compatibility or breaking changes, known limitations, upgrade notes, and validation. Do not restore per-version release-note files as a second documentation source.
- Roadmap stays short and does not promise a full IDE replacement, autonomous ops, arbitrary computer use, or universal client compatibility.
Run python3 scripts/check_markdown_links.py (also included in release_check.sh) and require zero missing repository-local links. Product narrative and allowed legacy-term matches remain review judgments in the release-prep PR; the readiness workflow automates only deterministic checks.
Scan docs and scripts for stale onboarding guidance:
rg "run_codex|Codex delegation|retained runner|future explicit opt-in|WEBCODEX_ENABLE_LEGACY_CODEX_RUN|PROJECTS_CONFIG|server_static|/api/codex|api/codex|projects.toml" README.md README.zh-CN.md docs deploy scripts SECURITY.mdAllowed matches are negative statements, release-note breaking changes, guard tests, and deployment comments that explicitly say the legacy path is removed or not required.
Do not allow docs that ask users to configure server-side project onboarding, imply legacy routes exist, imply run_codex exists, or describe retained runner / future opt-in behavior as the current plan.
After exact-source CI proof succeeds, the release-readiness workflow builds dedicated debug webcodex-server / webcodex-runner fixtures once for both supported zero-config transports while the compare eval runs independently. Disposable Server-image validation waits for both release-specific gates. The debug fixtures and images are never uploaded or promoted; .github/workflows/release-build.yml remains the only native release-candidate producer after the immutable tag exists.
The underlying smoke commands remain:
bash scripts/e2e_zero_config_ws.sh
E2E_TRANSPORT=polling bash scripts/e2e_zero_config_ws.shThese commands remain useful for diagnosis, but do not rerun them manually after a successful readiness workflow merely to duplicate evidence. They must never target a production repository; any write checks stay within disposable probe files or a temporary project.
The exact-source release-readiness workflow runs EVAL_MODE=compare bash scripts/eval_coding_loop.sh. Run it separately only for focused diagnosis. The eval harness measures scripted WebCodex tool-call mechanics; it is not a full model-behavior evaluation.
Confirm:
- No secrets,
.env, credentials, token files, generated deployment env files, or Authorization headers were touched or printed. finish_coding_taskandsession_handoff_summarycompact outputs do not expose raw stdout/stderr bodies, command text, tails, excerpts, env values, tokens, or secrets.run_shellis documented as a bounded shell primitive, while structured validators remain the default validation source.- Model-facing runtime docs keep admin, account, pairing, token-management, and Runner-token management outside MCP and GPT Actions.
For every new binary and npm release, choose one candidate <VERSION> first and treat its tag and uploaded bytes as immutable once published:
- If
<VERSION>already has a tag only because an earlier pre-publication attempt failed, reclaim it before preflight only throughpython3 scripts/release_operator.py reclaim-tag --version <VERSION> --source-ref <SOURCE_REF> --confirm v<VERSION> --root <EXACT_SOURCE_WORKTREE>. The command requires a clean checkout at the exact remote source ref, matching Cargo/npm/Desktop/Tauri versions, an annotated tag, no GitHub Release, no npm version, no active matching release-build, and no successful authoritative release-build. Keep failed historical runs as evidence. The normal Release check is authenticated;--allow-public-release-checkis permitted only after the human operator separately confirms there is no draft Release. - Before pre-tag readiness, run
python3 scripts/release_operator.py preflight --version <VERSION> --source-ref <SOURCE_REF> --source-sha <SOURCE_COMMIT> --root <EXACT_SOURCE_WORKTREE>. It requires a clean exact source; matching workspace Cargo, npm, Desktop package, Desktop Cargo, and Tauri app versions; the selected GitHub source ref at that source; an unused Git tag/GitHub Release/npm version; and usable GitHub/npm publication identities without printing credentials. - Prefer
python3 scripts/release_operator.py doctor --version <VERSION> --source-ref <SOURCE_REF> --source-sha <SOURCE_COMMIT> --root <EXACT_SOURCE_WORKTREE>before release day.doctoris read-only: it combines publication preflight, the five-way release-version fence, exact-source daily-CI proof, the explicit/reusable extended-native workflow, the six-platform npm runtime, the primary Windows x64/ARM64 + macOS Apple-Silicon Desktop contract, the supplemental macOS Intel publication workflow, draft-capable authenticated Release-list access, verifier parsing, required tool availability, andactionlintwhen installed. It validates that rare native runners stay out of ordinary CI and that both macOS distribution paths remain ad-hoc signed without paid Apple signing credentials. It reports all failed checks together and performs no tag, dispatch, draft, publish, or deployment mutation. - For normal operator flow, initialize one durable high-level plan with
release-init --version <VERSION> --source-ref <SOURCE_REF> --source-sha <SOURCE_COMMIT> --root <EXACT_SOURCE_WORKTREE> --state-file <PLAN_STATE> --work-dir <PLAN_WORK_DIR>, then userelease-resume --state-file <PLAN_STATE> --wait-secs <N>andrelease-status --state-file <PLAN_STATE>. The plan automatically advances only safe-to-initiate/recoverable phases (readiness observation, bound build observation, same-run bundle collection, npm staging, draft verification) and stops withneeds_authorizationbefore tag creation, draft creation, and public publication. Existing low-level commands remain the recovery/debug primitives and the plan never substitutes a second dispatch after uncertainty. - Keep the selected source branch stable until readiness succeeds and the annotated tag is created. After the tag exists, development may continue on both
mainand the release branch without invalidating final build, collection, staging, or publication; those phases bind the tag/source/run/bundle identities instead of the moving branch tip. Product fixes made only on a release branch should be forward-ported tomainas focused commits/PRs; release-only version metadata does not need to be merged back mechanically. Cargo.toml, every local WebCodex workspace entry inCargo.lock,npm/webcodex/package.json,apps/desktop/package.json,apps/desktop/src-tauri/Cargo.toml,apps/desktop/src-tauri/tauri.conf.json,manifest.example.json, and the relevant package self-tests must agree on<VERSION>before tagging.npm/webcodex/manifest.jsonis generated release metadata and is intentionally not tracked. Do not commit real checksums or create a post-tag checksum-only PR.- Build the six published runtime platforms (
linux-x64,linux-arm64,darwin-x64,darwin-arm64,win32-x64,win32-arm64) natively from the exactv<VERSION>tag through the reviewed release-build workflow. Both Windows jobs and the macOS Apple-Silicon job stage their already-built and verified runtime binaries into the matching primary Desktop distribution without recompiling a second runtime.win32-arm64uses the native Windows ARM64 runner,darwin-x64still uses GitHub's native Intel runner for the primary runtime archive, anddarwin-arm64uses native Apple Silicon. Starting withv0.4.3, the Intel lane stops after its runtime archive in the primary build; the laterrelease-desktop-darwin-x64.ymlworkflow uses that exact published archive as its Desktop input. Platform code signing may change Mach-O bytes copied into an.app, so native smoke/evidence records signed output identity rather than claiming byte-for-byte equality after signing. - Dispatch
release-build.ymlthroughrelease_operator.py build-startwith a fresh mode-0600 state file, then observe that same state withbuild-status. After tagging, the annotated tag is the source authority: the operator requires that remote tag to resolve to the exact readiness-approved source, dispatches the workflow from that immutable tag, injects one durablerb_<24 hex>request id into the workflow run name, and never rechecks or freezesmain/the release branch. Only terminal success for the bound run/source satisfies the build gate. - For both
linux-x64andlinux-arm64, build in the native-architecture manylinux2014 userspace used by the release-build workflow. Before packaging, inspect all three ELF binaries withreadelfand fail the release if any requiredGLIBC_*symbol version exceeds 2.17 or an unexpected host-specificDT_NEEDEDdependency appears. The published Linux x64 and arm64 artifacts therefore share the glibc 2.17 floor. - Pin one
WEBCODEX_BUILT_ATvalue for the release. Every finalwebcodex,webcodex-server, andwebcodex-runnerbinary must report<VERSION>, the same concrete tag commit,dirty=false, and the sharedbuilt_at. - Windows packaging must use
scripts/package_release_artifact.ps1in its default provenance-checked mode.-AllowDevelopmentBuildis for local/CI smoke only and its output must never be uploaded. - macOS verification and formal GitHub Release candidates use ad-hoc signing and are explicitly not notarized. This keeps Desktop distribution free of Apple Developer Program credentials. Native CI still verifies the app code signature, runtime identity, architecture, DMG contents, and exact release provenance. Gatekeeper may require the user to approve a newly downloaded build through System Settings → Privacy & Security → Open Anyway; do not instruct users to disable Gatekeeper globally. Developer ID signing and notarization can be introduced later as a separate distribution upgrade if the project chooses to pay for that trust path.
- After all six native targets succeed,
release-build.ymlmust aggregate only artifacts from that same workflow run and upload one<ARCHIVE_STEM>-bundle. Historical releases throughv0.4.2retain the four-Desktop primary contract. Starting withv0.4.3, the primary bundle contains the six unchanged native archives, both Windows Desktop installers, the macOS Apple-Silicon DMG,manifest.json, one immutableSHA256SUMS, both Linux ELF reports, andrelease-build.json. Unified-installation releases additionally require all eight unified installer targets (DEB+RPM for both Linux runtime platforms, PKG for both macOS platforms, EXE for both Windows platforms) and all six canonicalwebcodex-source-v<VERSION>-<PLATFORM>.jsonassets.SHA256SUMScovers these product/source bytes and the exact retainedmanifest.json(plus the separate runtime compatibility manifest when present).release-build.jsonkeeps the six runtime entries underartifacts, three primary Desktop distributions underdesktop_artifacts, and the complete eight-targetinstaller_artifacts. The existing npm/download-pagemanifest.jsonincludes that same installer/source-hash contract; it is also the public Desktop updater source, not a third manifest. The Intel unified.pkgis mandatory even though the supplemental Intel.dmgremains independent. The later Intel Desktop DMG is deliberately absent from this bundle and from the primarySHA256SUMS. - The release control host collects that single assembled bundle instead of fetching six target artifacts independently. Use
python3 scripts/release_operator.py collect --run-id <RUN_ID> --source-sha <TAG_COMMIT> --tag v<VERSION> --output-dir <BUNDLE_DIR>as the canonical path.collectresolves exactly one*-bundleartifact from the locked successful run, validates its run/source/expiry/SHA-256 metadata, downloads it by artifact id through the GitHub REST API (notgh run download), verifies the artifact zip digest, extracts it with bounded path/type/size checks, and validatesrelease-build.json,SHA256SUMS, archive membership, and release manifest consistency before atomically exposing<BUNDLE_DIR>. It reusesGH_TOKEN/GITHUB_TOKENor the currentgh authlogin without printing credentials. Never substitute an archive from another workflow run. - Create and validate the npm publication tree with
python3 scripts/release_operator.py stage-npm --bundle-dir <BUNDLE_DIR> --source-root <EXACT_TAG_WORKTREE> --output-dir <STAGE_DIR>. It revalidates the retained bundle, requires a clean worktree at the immutable tag, extracts only the exact verifiedlinux-x64binaries into a bounded temporary directory, then runs the existing staging helper andnpm_package_smoke.sh --binary-dir. The release path never invokes Cargo and compares installed native files byte-for-byte with the retained CI candidates. - Create a draft GitHub Release from exactly the retained primary bundle product assets. For
v0.4.3+, that means the six native archives, both Windows Desktop installers, the macOS Apple-Silicon DMG, and the primarySHA256SUMS; do not wait for or pre-create the Intel Desktop DMG. Before making the Release public, runpython3 scripts/release_operator.py verify-draft --bundle-dir <BUNDLE_DIR>and require the primary draft asset set, sizes, states, and GitHub-providedsha256:digests to match retained bytes. Do not re-download the same retained draft bytes on the control host. The post-public verifier hashes Desktop distributions but does not claim to prove macOS code signing/notarization. For a unified bundle, also upload itsmanifest.json, all eight unified installer targets, and all six source manifests;verify-draftrejects a missing/duplicate/mismatched asset. Do not publish a partial six-platform updater source. Public verification fetches the canonical Releasemanifest.json, rejects duplicate JSON fields, verifies its own SHA-256/size, and compares it to the retained npm manifest before hashing the installers and their source manifests. - Server container publication is owned by
.github/workflows/release-image.yml, separate from the read-onlyrelease-build.ymlcandidate workflow. It runs only after a GitHub Release is public (or by guarded manual backfill of that already-public immutable tag), builds nativelinux/amd64andlinux/arm64images from the exact annotated tag with the release build identity, verifies the non-root runtime, exact Server/CLI identity, health check, and absence of the Runner, then publishes immutablev<VERSION>/<VERSION>image tags (with SemVer+build metadata encoded as_, since Docker tags do not allow+). From the final immutable multi-arch digest it also generates one self-containedwebcodex-server-bootstrap.shfrom the reviewed publication-workflow source; that script embeds and materializes a Compose definition pinned to the exact image digest, which keeps guarded backfill usable for Releases whose application tags predate the deployment tooling.webcodex-server-image.jsonrecords the application source SHA, deployment-tooling source SHA, manifest/child digests, and bootstrap SHA-256. Existing Release assets are reconciled byte-for-byte on rerun; only the current latest stable GitHub Release may move the mutablelatesttag. - Starting with
v0.4.3, macOS Intel Desktop publication is owned by.github/workflows/release-desktop-darwin-x64.yml, also triggered only after the GitHub Release is public (or by guarded manual backfill from reviewedmain). It downloads the exact publisheddarwin-x64runtime archive and primarySHA256SUMS, verifies release provenance and runtime identity on the native Intel runner, builds/smokes the ad-hoc signed DMG, then attacheswebcodex-desktop-v<VERSION>-darwin-x64.dmgplus its dedicated.sha256sidecar. It never rewritesSHA256SUMS. On rerun, each existing supplemental asset must match byte-for-byte; a missing counterpart may be added, while conflicting or duplicate bytes fail closed. - GitHub creates the first GHCR package as private by default. On the first WebCodex Server image publication only, the repository owner must change
webcodex-serverpackage visibility to Public in GitHub Packages, then rerun the failed anonymous-availability gate. After activation, require anonymous inspection/pull availability for every release; do not distribute registry credentials to end users.
For the normal path, the sequence below may be driven by one release-init + repeated release-resume calls. Each needs_authorization result is a hard human boundary, not a request for the operator to infer consent. Low-level commands listed in the individual steps remain authoritative recovery/debug operations.
- Select the reviewed source commit and create
<SOURCE_REF>: preferablyrelease/v<VERSION>from thatmaincommit, or from the previous immutable tag for a focused hotfix. Put version bumps, release notes, platform docs, packaging changes, and release tests in one release-prep PR targeting that source branch and resolve its exact merged commit.mainmay continue merging unrelated work after the release branch is cut. If an explicitly approved failed pre-publication tag for<VERSION>exists, run the guardedrelease_operator.py reclaim-tag --source-ref <SOURCE_REF>now and require successful remote-ref reconciliation. Runrelease_operator.py doctor --source-ref <SOURCE_REF>before the release window, then create the durable plan withrelease-init --source-ref <SOURCE_REF>; require all three publication namespaces (Git tag, GitHub Release, npm version) to be unused, both publication identities to be available, and the exact source branch's push CI to be successful. release-resumedispatches one readiness run from the selected source branch and keeps its nested durable state; repeated resumes observe that same run until terminal. The low-level equivalent isreadiness-start --source-ref <SOURCE_REF>plusreadiness-status --wait-secs 3600. Readiness binds the exact successful source-branch CI run id/attempt, independently revalidates that proof, callsextended-native.ymlfor Linux ARM64, macOS Intel/Desktop, and Windows ARM64/Desktop validation of the same source, then runs release-specific E2E/eval and the two disposable Server-image architectures. Keep<SOURCE_REF>fixed at that SHA until the immutable tag is created. No six-platform native release-profile candidate is built in readiness. If dispatch/observation is uncertain, recover from the same state instead of blind redispatch.- After readiness success, the plan stops at
awaiting_tag_authorization. Only after explicit human authorization create and push the immutable annotatedv<VERSION>tag at that exact source; never move it. From this point onward the tag, not any branch tip, is the source authority:mainand the release branch may advance without invalidating the release. On the next resume the plan reconciles the remote annotated tag and dispatches/observes one bound authoritative build from that tag. The low-level equivalent isbuild-start --source-sha <TAG_COMMIT> --tag v<VERSION> --state-file <BUILD_STATE>once, thenbuild-status --state-file <BUILD_STATE> --wait-secs 7200. Require all six native runtime targets, the version-appropriate primary Desktop candidates/smokes, native macOS primary signing evidence, andassembleto succeed in that bound workflow run. Forv0.4.3+, the supplemental Intel Desktop DMG is not part of this primary build gate; unified releases still require the native Intel.pkgin the complete eight-target installer set. - After build success,
release-resumecollects only that run's<ARCHIVE_STEM>-bundleand records it in the plan. The low-levelcollectcommand remains available for recovery. Existing bundle bytes are reconciled against exact source/tag rather than silently replaced. - The same resume stages npm from the retained bundle and exact tag worktree without recompilation. If the stage path already exists but the successful state transition was not durably recorded, the plan stops with
needs_reconciliationrather than deleting/re-running it.stage-npmremains the low-level primitive. - The plan then stops at
awaiting_draft_authorization. After explicit authorization, create a draft GitHub Release from the version-appropriate retained primary assets; forv0.4.3+, upload the six archives, the three primary Desktop distributions,SHA256SUMS, andwebcodex-release-manifest.jsonwhen the retained bundle includes that runtime metadata asset. For a unified bundle, also upload the exact retainedmanifest.json, the eight unified installer targets, and the six source manifests from that same immutable tag/workflow run. The next resume runs the sameverify-draftdigest gate before advancing to the publication authorization boundary. - After explicit human authorization, make the verified GitHub Release public. From the release control host only, publish npm from
<STAGE_DIR>/npm-package(npm publish --access public --registry https://registry.npmjs.org/) and verify the requested version/dist-tag;package.jsonalso pins the same public registry throughpublishConfig. If publish success is followed by delayed registry visibility, poll rather than publishing twice. - Require
.github/workflows/release-image.ymlto finish successfully for the same publicv<VERSION>Release. It must publish/reconcileghcr.io/yyjeqhc/webcodex-server:v<VERSION>for both Linux architectures, attach the digest metadata plus the self-contained clone-free bootstrap, verify its public SHA-256 and embedded pinned-digest contract, and pass its anonymous GHCR availability gate. Forv0.4.3+,release-desktop-darwin-x64.ymlmay run independently in parallel: it is intentionally non-blocking for the core Release, and a failed/slow Intel DMG can be retried or manually backfilled against the same immutable public tag without changing primary assets. - From one trusted, well-connected Linux verification host, run
python3 scripts/verify_public_release.py <VERSION>. This remains the full public-byte acceptance pass for npm plus the six native GitHub archives and the primary Desktop distributions required by that release generation: none before0.4.0, three for0.4.0/0.4.1, four for0.4.2, and three primary Desktop assets from0.4.3+. Forv0.4.3+, absent Intel supplemental assets do not fail core verification; a one-file intermediate state is reported aspublication_in_progress, and once both DMG and dedicated checksum sidecar exist the verifier checks the pair. The verifier cross-checks npm manifest / primarySHA256SUMS/ GitHub asset digests, validates archive membership and foreign binary architecture without executing foreign binaries, hashes bounded public Desktop bytes, and rechecks Linux GLIBC/DT_NEEDEDmetadata. Native Mac workflows continue to own ad-hoccodesignand DMG execution evidence.
After deploying a new server, Runner, or runtime build:
- Refresh the GPT Action or MCP schema if runtime tool schemas changed.
- Run compact
runtime_status. - Run focused tool discovery.
- Run
list_projectsand pick a Runner-registered project marked appropriate for smoke when available. - Run a read-only coding task:
work_on_project,read_filesorsearch_project_texts,show_changes(include_diff=false),workspace_hygiene_check, andfinish_coding_task(summary_only=true). - Run one small reversible edit task on a safe project and review the diff before accepting it.
Do not run production mutations as acceptance smoke.