Skip to content

Latest commit

 

History

History
145 lines (102 loc) · 31.3 KB

RELEASE_CHECKLIST.md

File metadata and controls

145 lines (102 loc) · 31.3 KB

Release Readiness Checklist

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.

1. Source Validation

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 3600

readiness-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. For a release/v* source it also requires exactly one successful push run of .github/workflows/release-readiness.yml for the same branch/SHA; that push run is the precomputed release-source evidence. The operator records both immutable run ids and attempts in the mode-0600 local state before dispatch. The later readiness dispatch re-fetches both exact attempts with read-only Actions authority and fails closed on workflow/event/ref/SHA/repository/result mismatch. A main source has no precomputed evidence requirement and retains the slower in-dispatch evidence fallback. 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. A release/v* push concurrently precomputes the remaining exact-SHA evidence in release-readiness.yml: extended-native.yml supplies native Linux ARM64, macOS Intel/Desktop, and Windows ARM64/Desktop validation; WebSocket/polling zero-config E2E and coding-loop compare eval run independently; and disposable native linux/amd64 plus linux/arm64 Server images verify runtime/health/non-root/bootstrap generation before being discarded. Once both push workflows are green, the operator-dispatched readiness gate only revalidates their exact immutable run attempts, so the release window does not serially repeat the expensive native work. A main source runs those expensive jobs inside the dispatch instead, keeping ordinary main pushes free of scarce runners. 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.

2. Focused Runtime Tests

During implementation/review, run focused lanes when touching runtime metadata, schemas, MCP, session, handoff, validation, or coding-task behavior. Exact-source CI owns the full Linux package suites plus deterministic metadata/schema/MCP and release-tooling evidence; a release-branch push owns the additional scarce-native/E2E/eval/disposable-image evidence. The final release-readiness dispatch binds those successful exact-source attempts instead of repeating them. Re-run an individual lane only to diagnose a failure or when a review explicitly requires separate evidence.

3. Product Documentation Check

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, session, handoff, validation, review/hygiene, and run_shell as 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 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.

4. Legacy Surface Guard

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.md

Allowed 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.

5. E2E Smoke

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.sh

These 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.

6. Eval Harness

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.

7. Security And Leakage Checks

Confirm:

  • No secrets, .env, credentials, token files, generated deployment env files, or Authorization headers were touched or printed.
  • finish_coding_task and read_session_handoff compact outputs do not expose raw stdout/stderr bodies, command text, tails, excerpts, env values, tokens, or secrets.
  • run_shell is 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.

8. Packaging And Artifact Checks

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 through python3 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-check is 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. doctor is read-only: it combines publication preflight, the five-way release-version fence, exact-source daily-CI proof, the release-branch source-evidence proof when <SOURCE_REF> is release/v*, 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, and actionlint when installed. It validates that rare native runners stay out of ordinary CI and that public macOS distribution requires a persistent self-signed or explicitly selected Developer ID identity, while disposable CI remains credential-free. 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 use release-resume --state-file <PLAN_STATE> --wait-secs <N> and release-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 with needs_authorization before 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 main and 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 to main as focused commits/PRs; release-only version metadata does not need to be merged back mechanically.
  • Cargo.toml, every local WebCodex workspace entry in Cargo.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.json is 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 exact v<VERSION> tag through the reviewed release-build workflow. Before any scarce native matrix starts, the exact tagged workflow source must pass the cheap preflight job, including bash scripts/release_check.sh --static-only. A deterministic YAML/shell/tooling-contract failure must stop here rather than after platform builds.
  • Dispatch release-build.yml through release_operator.py build-start with a fresh mode-0600 state file, then observe that same state with build-status. The operator-dispatched default is the core release: include_unified_installers=false. Unified distro installers are an explicit opt-in extension and are not part of ordinary release success unless include_unified_installers=true was deliberately requested.
  • 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-arm64 uses the native Windows ARM64 runner, darwin-x64 still uses GitHub's native Intel runner for the primary runtime archive, and darwin-arm64 uses native Apple Silicon. Starting with v0.4.3, the Intel lane stops after its runtime archive in the primary build; the later release-desktop-darwin-x64.yml workflow 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.
  • For both linux-x64 and linux-arm64, build in the native-architecture manylinux2014 userspace used by the release-build workflow. Before packaging, inspect all three ELF binaries with readelf and fail the release if any required GLIBC_* symbol version exceeds 2.17 or an unexpected host-specific DT_NEEDED dependency appears. The published Linux x64 and arm64 artifacts therefore share the glibc 2.17 floor.
  • Pin one WEBCODEX_BUILT_AT value for the release. Every final webcodex, webcodex-server, and webcodex-runner binary must report <VERSION>, the same concrete tagged source, dirty=false, and the shared built_at. Cross-workflow consumers should validate the machine-readable --build-info-json contract instead of reconstructing --version strings or assuming a particular displayed commit length.
  • Windows packaging must use scripts/package_release_artifact.ps1 in its default provenance-checked mode. -AllowDevelopmentBuild is for local/CI smoke only and its output must never be uploaded.
  • macOS ordinary CI/readiness remains ad-hoc and credential-free, but formal public releases and long-lived dogfood use a persistent self-signed identity by default. Keep the same certificate and private key across upgrades; recreating a certificate with the same name changes code identity. Desktop (dev.webcodex.desktop) and bundled Runner (dev.webcodex.runner) use certificate-anchored designated requirements without binary cdhash so rebuilt binaries can keep one stable TCC identity.
    • Protect release signing configuration: MACOS_SIGNING_MODE defaults to self-signed; set MACOS_SIGNING_IDENTITY and pin the long-lived certificate SHA-1 in MACOS_CERTIFICATE_SHA1. Inject the same P12/private key through protected MACOS_SIGNING_P12 and MACOS_SIGNING_P12_PASSWORD secrets. Missing material or a changed fingerprint fails closed. Do not generate a new certificate per run.
    • Self-signed distribution is intentionally not Apple notarized. developer-id remains an optional future mode for users who have Apple credentials; it must never become a prerequisite for ordinary WebCodex releases.
  • Before closing a TCC-related release issue under the persistent signing contract, validate one release candidate on a clean macOS user/host: Screen Recording must prompt and remain usable after a full Desktop/Runner restart, Accessibility must become trusted and remain usable, and upgrading to another build signed by the same identity must be recorded. Code-identity tests are necessary but do not by themselves prove TCC grant continuity.
  • After all six native targets succeed, release-build.yml must aggregate only artifacts from that same workflow run and upload one <ARCHIVE_STEM>-bundle. Historical releases through v0.4.2 retain the four-Desktop primary contract. Starting with v0.4.3, the core bundle contains the six native archives, both Windows Desktop installers, the macOS Apple-Silicon DMG, one immutable SHA256SUMS, both Linux ELF reports, release-build.json, and the runtime compatibility manifest when applicable. The generated npm manifest.json may remain inside the retained bundle for staging, but a core-only GitHub Release does not need to publish it and the download-page workflow must skip cleanly when no public installer manifest exists.
  • If include_unified_installers=true, require the complete eight-target set (DEB+RPM for both Linux runtime platforms, PKG for both macOS platforms, EXE for both Windows platforms), all six canonical webcodex-source-v<VERSION>-<PLATFORM>.json assets, and the installer-bearing manifest.json. Partial installer/source sets still fail closed. release-build.json includes installer_artifacts only for this opt-in mode. The Intel unified .pkg is part of that optional complete installer set even though the supplemental Intel .dmg remains independent.
  • 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. collect resolves exactly one *-bundle artifact from the locked successful run, validates its run/source/expiry/SHA-256 metadata, downloads it by artifact id through the GitHub REST API (not gh run download), verifies the artifact zip digest, extracts it with bounded path/type/size checks, and validates release-build.json, SHA256SUMS, archive membership, and release manifest consistency before atomically exposing <BUNDLE_DIR>. It reuses GH_TOKEN/GITHUB_TOKEN or the current gh auth login 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 verified linux-x64 binaries into a bounded temporary directory, then runs the existing staging helper and npm_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 primary SHA256SUMS; do not wait for or pre-create the Intel Desktop DMG. Before making the Release public, run python3 scripts/release_operator.py verify-draft --bundle-dir <BUNDLE_DIR> and require the primary draft asset set, sizes, states, and GitHub-provided sha256: digests to match retained bytes. For an opt-in unified bundle, also upload its installer-bearing manifest.json, all eight unified installer targets, and all six source manifests; verify-draft rejects a missing/duplicate/mismatched asset. Do not publish a partial updater source.
  • Server container publication is owned by .github/workflows/release-image.yml, separate from the read-only release-build.yml candidate workflow. It runs only after a GitHub Release is public (or by guarded manual backfill of that already-public immutable tag), builds native linux/amd64 and linux/arm64 images from the exact annotated tag, validates Server/CLI through structured build metadata, verifies the non-root runtime, health check, and absence of the Runner, then publishes immutable v<VERSION> / <VERSION> image tags. From the final immutable multi-arch digest it also generates one self-contained webcodex-server-bootstrap.sh; existing Release assets are reconciled byte-for-byte on rerun.
  • 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 reviewed main). It downloads the exact published darwin-x64 runtime archive and primary SHA256SUMS, validates structured runtime identity against the immutable tagged source on the native Intel runner, then builds/smokes the supplemental DMG under the same explicit persistent signing mode and attaches webcodex-desktop-v<VERSION>-darwin-x64.dmg plus its dedicated .sha256 sidecar. It never rewrites SHA256SUMS; duplicate/conflicting assets 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-server package 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.

9. Release Sequence

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.

  1. Select the reviewed source commit and create <SOURCE_REF>: preferably release/v<VERSION> from that main commit, 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. main may continue merging unrelated work after the release branch is cut. A release/v* push now starts ordinary source CI and the expensive source-evidence readiness run in parallel; require both exact-SHA push runs to succeed before the release window. If an explicitly approved failed pre-publication tag for <VERSION> exists, run the guarded release_operator.py reclaim-tag --source-ref <SOURCE_REF> now and require successful remote-ref reconciliation. Run release_operator.py doctor --source-ref <SOURCE_REF> before the release window, then create the durable plan with release-init --source-ref <SOURCE_REF>; require all three publication namespaces (Git tag, GitHub Release, npm version) to be unused and both publication identities to be available.

  2. release-resume dispatches 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 is readiness-start --source-ref <SOURCE_REF> plus readiness-status --wait-secs 3600. For release/v*, readiness binds the exact successful source-branch CI run id/attempt and the exact successful source-evidence push run id/attempt, independently revalidates both immutable proofs, and skips rebuilding the already-completed extended-native, E2E/eval, and disposable Server-image evidence. A main source retains the previous slow fallback and executes those jobs in the dispatch itself. 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.

  3. After readiness success, the plan stops at awaiting_tag_authorization. Only after explicit human authorization create and push the immutable annotated v<VERSION> tag at that exact source; never move it. From this point onward the tag, not any branch tip, is the source authority: main and 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 is build-start --source-sha <TAG_COMMIT> --tag v<VERSION> --state-file <BUILD_STATE> once, then build-status --state-file <BUILD_STATE> --wait-secs 7200. Require the cheap tagged-source preflight, all six native runtime targets, the version-appropriate primary Desktop candidates/smokes, native macOS primary signing evidence, and assemble to succeed in that bound workflow run. For v0.4.3+, the supplemental Intel Desktop DMG is not part of this primary build gate. The unified installer matrix is required only when the release was explicitly dispatched with include_unified_installers=true; otherwise it is skipped and cannot block core publication.

    Bounded post-build source-fix recovery: if this authoritative build fails before any GitHub Release/npm publication and diagnosis proves a release-only build/packaging/installer/provenance/workflow defect, do not repeat readiness merely to exercise the same pre-tag evidence again. Require a previously successful readiness for the release line, repair only those release/CI/test/doc surfaces on release/v<VERSION>, require exact-source push CI plus focused regression tests on the repaired SHA, and cancel/ignore auto-started readiness evidence for that recovery push. After separate explicit authorization for tag mutation, use guarded reclaim-tag, recreate the annotated tag at the repaired SHA, and start a fresh low-level build-start state. Never reuse the old high-level plan/build state or any earlier candidate bytes. Any product/runtime behavior change returns to the normal readiness path.

  4. After build success, release-resume collects only that run's <ARCHIVE_STEM>-bundle and records it in the plan. The low-level collect command remains available for recovery. Existing bundle bytes are reconciled against exact source/tag rather than silently replaced.

  5. 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_reconciliation rather than deleting/re-running it. stage-npm remains the low-level primitive.

  6. The plan then stops at awaiting_draft_authorization. After explicit authorization, create a draft GitHub Release from the version-appropriate retained primary assets; for v0.4.3+, upload the six archives, the three primary Desktop distributions, SHA256SUMS, and webcodex-release-manifest.json when the retained bundle includes that runtime metadata asset. For a unified bundle, also upload the exact retained manifest.json, the eight unified installer targets, and the six source manifests from that same immutable tag/workflow run. The next resume runs the same verify-draft digest gate before advancing to the publication authorization boundary.

  7. 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.json also pins the same public registry through publishConfig. If publish success is followed by delayed registry visibility, poll rather than publishing twice.

  8. Require .github/workflows/release-image.yml to finish successfully for the same public v<VERSION> Release. It must publish/reconcile ghcr.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. For v0.4.3+, release-desktop-darwin-x64.yml may 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.

  9. 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 before 0.4.0, three for 0.4.0/0.4.1, four for 0.4.2, and three primary Desktop assets from 0.4.3+. For v0.4.3+, absent Intel supplemental assets do not fail core verification; a one-file intermediate state is reported as publication_in_progress, and once both DMG and dedicated checksum sidecar exist the verifier checks the pair. The verifier cross-checks npm manifest / primary SHA256SUMS / GitHub asset digests, validates archive membership and foreign binary architecture without executing foreign binaries, hashes bounded public Desktop bytes, and rechecks Linux GLIBC/DT_NEEDED metadata. Native Mac workflows continue to own code-signature, notarization, stable Runner identity, and DMG execution evidence.

10. Post-Deployment Acceptance Smoke

After deploying a new server, Runner, or runtime build:

  1. Refresh the MCP schema if runtime tool schemas changed.
  2. Run compact get_runtime_status.
  3. Run focused tool discovery.
  4. Run list_projects and pick a Runner-registered project marked appropriate for smoke when available.
  5. Run a read-only coding task: work_on_project, read_files or search_project_texts, read_workspace_changes(include_diff=false), check_workspace_hygiene, and finish_coding_task(summary_only=true).
  6. 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.