Skip to content

Latest commit

 

History

History
384 lines (325 loc) · 22.5 KB

RELEASING.md

File metadata and controls

384 lines (325 loc) · 22.5 KB

Release procedure

Current publication: 2.4.1

Release 2.4.1, ID 442808765, was published at 2026-11-12 10:46:44 UTC. Its immutable tag resolves to a3b09eca6333c2befda3504850f357f09cc25542. Linux 43192014736, macOS 43203354756, Flatpak 43203358489 and Windows 43203362035 all completed successfully on attempt 1.

The full public audit passed at 11:28:33 UTC: 23 assets, nine installers, three source archives, five checksum sets/12 rows and six authenticated Linux payloads. Public Windows qualification records separate installation, payload equality, native UI, scripted endurance and real-model outcomes.

Main independently rechecked all 15 required gates for x86_64 and aarch64, including source/run/attempt, immutable artifact identities and script/package hashes. The protected-source activation pinned a3b09ec and added the exact v2.4.1 allowance with existing review protections retained. Fresh environment, tag-rule and tooling readbacks preceded signing approval at 10:44:07 UTC.

APT verification passed at 10:50:26 UTC after job 131132225135. Both signatures verified against current fingerprint 1BC07B5ECFDB514673A296FB021CAB3F2F7A1F61; six signed index sizes/hashes matched and both 2.4.1 pool DEBs matched the verified public release. This verifier installed no package.

Current Linux download names:

Role x86_64 aarch64
AppImage ShadowCode_2.4.1_amd64.AppImage ShadowCode_2.4.1_aarch64.AppImage
Debian package ShadowCode_2.4.1_amd64.deb ShadowCode_2.4.1_arm64.deb
Runtime sources ShadowCode_2.4.1_appimage-runtime-sources.tar.gz ShadowCode_2.4.1_aarch64_appimage-runtime-sources.tar.gz

Checksums/manifests/envelopes/signatures retain their per-target filenames. Ed25519 authentication covers the six Linux payloads; other platforms have separate checksum and qualification records. No new physical Mac/Linux installation acceptance is claimed for 2.4.1. Tags and versioned assets remain immutable.

Historical 2.4.0 publication and configuration checkpoint

The following is the retained November 12 checkpoint. Its current/pending wording describes that historical state, not the new release.

The current published Linux release is 2.4.0, from immutable tag v2.4.0 at 25c8345f99f246b37ea45bf9306eb551da9c0819. Release run 43145082420, attempt 1, passed all 15 required gates for each of x86_64 and aarch64, then protected signing, publication and APT publication. GitHub release 442500290 became public on November 12, 2026 at 04:35:24 UTC (November 11 in US Eastern time). At 04:37:08 UTC, all 14 Linux public assets were downloaded and their hashes checked; all six payloads were authenticated against the tracked Ed25519 trust bundle. Required gates had no required skips; explicitly optional live checks retain the exclusions recorded in their receipts.

Windows, macOS and Flatpak 2.4.0 are also published. Their separate workflows passed and all 23 final public assets were downloaded and checked against their published hashes. See platform workflow results and public-byte verification. Physical Windows qualification then exposed composer overlap with the terminal Hide control at 175% zoom in a short window. A 2.4.1 source candidate is being prepared for that fix; the immutable 2.4.0 release remains unchanged and the website download promotion waits for the corrected installer’s qualification. The local Mac development qualification in MAC_FLAGSHIP_UPGRADE.md remains separate from native platform acceptance.

The verified 14-asset Linux publication contains exactly these seven files per target; later platform attachments are outside this inventory:

Role x86_64 aarch64
AppImage ShadowCode_2.4.0_amd64.AppImage ShadowCode_2.4.0_aarch64.AppImage
Debian package ShadowCode_2.4.0_amd64.deb ShadowCode_2.4.0_arm64.deb
Runtime sources ShadowCode_2.4.0_appimage-runtime-sources.tar.gz ShadowCode_2.4.0_aarch64_appimage-runtime-sources.tar.gz
Checksums SHA256SUMS SHA256SUMS-aarch64
Manifest RELEASE-MANIFEST.json RELEASE-MANIFEST-aarch64.json
Signed envelope RELEASE-AUTH RELEASE-AUTH-aarch64
Ed25519 signature RELEASE-AUTH.sig RELEASE-AUTH-aarch64.sig

The APT job succeeded at 04:38:26 UTC. Independent live verification at 04:40:38 UTC confirmed 2.4.0 for amd64 and arm64, both repository signatures, all six signed index files and byte-for-byte equality of the APT pool packages with the public GitHub DEBs. The pinned GPG fingerprint is 1BC07B5ECFDB514673A296FB021CAB3F2F7A1F61; see APT repository. The external publication evidence is retained under publication-2.4.0/: release-handoffs/{x86_64,aarch64}-verified.json, public-linux/public-verification.json, and apt-public-verification/proof.json. A portable copy of the public Linux verification, APT verification, and x86_64/aarch64 handoff checks is tracked with this documentation.

Pushing a v* tag starts .github/workflows/release.yml. Publication follows both Linux architectures' build/qualification, protected signing review and verification of the signed public assets. The publish job then dispatches the Windows, macOS and Flatpak workflows. Confirm their assets independently before advertising that platform's new version. Existing versioned assets and tags are immutable; do not move v2.4.0 or overwrite its published assets.

Live configuration was read back for this publication: the independently reviewed NATIVE_RELEASE_TOOLING_COMMIT is 25c8345f99f246b37ea45bf9306eb551da9c0819, and release-signing permits the exact tag v2.4.0 alongside the retained v2.3.1, v2.3.2 and v2.3.3 rules. Required owner review and self-review settings are unchanged. All environment settings must be read live for later releases. Historical preparation snapshot, November 11, 2026: before the 2.4.0 update, only those three 2.3.x tags were allowed and the reviewed tooling pin was fd13dc10dbdcc6aac63cdfb292f9ec4d47838347. The reviewed policy extension through 2.4.0 preserved the existing key identity, epoch, historical floor and targets.

1. Version files

These application and packaging fields must carry the same version, and the tag must be v<version>. The release tag gate checks the four application fields; the Debian metadata suite independently compares the newest AppStream entry with Cargo, UI and Tauri versions before packaging:

File Field
Cargo.toml [workspace.package] version
src-tauri/tauri.conf.json version
ui/package.json version
packaging/shadow-agent.desktop X-ShadowCode-Version=
packaging/com.shadowfetch.shadowcode.appdata.xml Newest <release version=...> and its date; preserve earlier entries

Update the workspace package entries in Cargo.lock and the root package versions in ui/package-lock.json alongside those files; keep locked builds reproducible. Update CHANGELOG.md and docs/RELEASE_NOTES.md. The notes file becomes the GitHub release text as it is, so it should start with this release. Notes of earlier releases may follow below it, as they do now.

2. Managed llama.cpp runtime

The runtime is built from tools/llama.cpp.pin (commit= and spirv_headers_commit=). On Ubuntu 24.04:

sudo apt-get install cmake ninja-build libssl-dev libvulkan-dev glslc spirv-headers
bash scripts/build-llama.cpp.sh --no-user-install
node --test scripts/test-llama-runtime.mjs
  • glslc. Without it or the Vulkan headers, the script falls back to a CPU-only runtime with only a warning. Before packaging, check that packaging/llama.cpp/bin/COMMIT says backend=vulkan+cpu. The script looks for glslc in SHADOWCODE_GLSLC, then on PATH, then in a user-installed org.freedesktop.Sdk flatpak (tools/glslc-flatpak.sh).
  • cmake. Found in SHADOWCODE_CMAKE, then .venv/bin/cmake, then on PATH.
  • Notices. The script copies the license texts of llama.cpp/ggml, cpp-httplib, nlohmann/json, stb_image, miniaudio, subprocess.h and SPIRV-Headers into NOTICES/. The same texts are pinned with SHA-256 digests in licenses/native (llama.cpp-<short>/, SPIRV-Headers-<short>/).
  • Moving the pin. Update tools/llama.cpp.pin and those notice directories together. Run --notices-only to refresh NOTICES/ and COMMIT of an existing build without recompiling. Packaging refuses a runtime whose commit or notices don't match the pin.

3. Local checks

npm --prefix ui ci
npm --prefix ui run typecheck
npm --prefix ui test
npm --prefix ui run build
(cd ui && npm run test:e2e)
cargo +1.95.0 fmt --all --check
cargo +1.95.0 clippy --workspace --all-targets --locked -- -D warnings
cargo +1.95.0 build -p shadowcode-desktop --locked
cargo +1.95.0 test --workspace --locked
node scripts/test-native-cli.mjs
node scripts/test-native-stress.mjs
node scripts/test-native-tui.mjs
node scripts/check-secrets.mjs

Build the desktop executable before running the Rust suite: the process tests launch target/debug/shadowcode. The scripts need Node.js 22.12 or newer, like the UI: with an older node first on PATH, test-native-cli.mjs stops with ERR_UNKNOWN_BUILTIN_MODULE (node:sqlite). A change to the window also needs the window test on X11 and on a private Wayland compositor (see NATIVE_DESKTOP.md; Weston 13 and WebKitWebDriver can be unpacked copies):

node scripts/run-native-x11.mjs node scripts/test-native-desktop.mjs
node scripts/run-native-wayland.mjs node scripts/test-native-desktop.mjs

check-secrets.mjs also runs in the CI "Checks" workflow, not in release.yml; run it before pushing the tag. Live turns against real accounts (live_vendor_turn) are described under Tests in the README.

4. Packages

On the pinned Ubuntu 24.04 build environment, with Docker, or Podman plus SHADOW_CONTAINER_ENGINE=podman, for the pinned AppImage runtime build:

node --test scripts/test-native-packaging-env.mjs
node scripts/build-native.mjs
node scripts/check-native-package.mjs \
  target/release/bundle/appimage/ShadowCode_VERSION_amd64.AppImage \
  target/release/bundle/deb/ShadowCode_VERSION_amd64.deb
node scripts/test-native-runtime-write-errors.mjs
node scripts/test-native-runtime-sources.mjs
node scripts/test-native-runtime.mjs
bash scripts/test-install-appimage.sh
  • build-native.mjs checks packaging/llama.cpp/bin (pin, SPIRV-Headers commit, architectures.txt, notices) before it builds. It copies the runtime into the AppDir with its relative links kept, and repacks the deb with /usr/lib/shadowcode. It sets its own clean PATH and records the Git commit (SHADOWCODE_COMMIT, -dirty for local changes) for Settings › About. The deb repack (scripts/native-deb.mjs) adds the Debian copyright and changelog (from the AppStream releases), the manual page and shell completions generated by the packaged executable, hicolor icons, lintian overrides and the libc6 floor, strips the runtime and fixes modes.
  • check-native-package.mjs checks both packages:
    • no absolute, escaping or dangling links;
    • COMMIT matches the pin;
    • every NEEDED library is bundled or an allowed system library;
    • llama-server --version prints the pinned commit and --list-devices runs with LD_LIBRARY_PATH unset;
    • notice digests match, and there are no Python or Node sidecars;
    • the deb depends on libgomp1 and libssl3;
    • the deb is what distributions expect: root-owned 0755/0644 modes, no maintainer scripts or conffiles, copyright with the NOTICE, changelog, manual page and completions matching the executable, icons at every hicolor size, a stripped runtime and libc6 (>= …) covering every binary. When installed, lintian must report no errors (SHADOWCODE_REQUIRE_LINTIAN=1 makes it mandatory) and desktop-file-validate must pass. node --test scripts/test-native-deb.mjs covers these checks. See Distributing ShadowCode.
  • test-install-appimage.sh uses fake AppImages in a temporary HOME. It covers checksum refusal, broken runtimes, --unverified, rollback after the runtime swap and a changed download. If packaging/llama.cpp/bin exists, it also runs the real llama-server. Scenarios 20–24 cover the first-window check: a version that hangs, exits or reports another version is stopped and the AppImage, runtime, launchers and database snapshot are restored without lowering the accepted-release record; the check refuses while ShadowCode holds the profile lock; and --recover after an installer killed during the check waits for the started version to close, then restores all of it. Run it as an ordinary user: as root, permission-based failure injection (scenario 5) cannot fail. The real VACUUM INTO snapshot and the first-start marker are covered by cargo test -p shadowcode-core --lib -- install_snapshot first_start.

5. Protected signing review and tag

The v0.33.0 attempt at 9e385cb failed before signing/publication in run 36414378697. Do not move or overwrite that tag. The v0.34.0 attempt at 3409d59 likewise stopped in the native-source gate (run 36499751141) because two new opt-in network tests were not on the optional-test list, and the v0.34.1 attempt at 206fd03 stopped in native-window (run 36507326107) because the window test expected a ready model on the clean CI host; nothing was signed and both tags stay unchanged. Version 0.33.1 was published from e15c4480e65db5650af012bb2a9773dbe89acf84, with all 15 required build gates and protected signing passing in run 36427024374. The workflow publication job failed on a transient draft-listing response; publication resumed locally with the same frozen publisher and signed artifact, verifying all seven remote asset files before publication. This does not make that workflow run green. Existing 0.33.0 receipts do not qualify the new package bytes. The first-authenticated install boundary remains 0.33.0; do not silently move this durable boundary.

The release workflow also runs every required gate on aarch64 (build-aarch64, on ubuntu-24.04-arm) and hands off its packages and receipts unsigned, exactly like x86_64 (unsigned-release-aarch64-RUN-ATTEMPT). The trust policy trusts both targets (target=x86_64-unknown-linux-gnu,aarch64-unknown-linux-gnu). sign waits for both builds and signs each target separately with the same key: node scripts/sign-native-release.mjs BUNDLE TRUST OUTPUT [TARGET], where the aarch64 bundle's receipts are checked against the aarch64 gate scripts (the package names in three gates differ by architecture) and its metadata is written as RELEASE-AUTH-aarch64, RELEASE-AUTH-aarch64.sig, RELEASE-MANIFEST-aarch64.json and SHA256SUMS-aarch64. publish takes the x86_64 bundle and then the aarch64 bundle, authenticates each for its own target and stages all fourteen assets in one draft before publishing; the x86_64 bundle is required and no asset name may repeat. apt-repository verifies and indexes both .deb files. The pinned tooling commit must include this multi-target signer and publisher; an older pin refuses the aarch64 signing call, so the release fails rather than shipping x86_64 alone.

The tagged 2.4.1 public trust allows the x86_64 and aarch64 targets, epoch 1 and versions 0.33.0–2.4.1. The immutable 2.4.0 policy retains its 2.4.0 ceiling. The key, epoch, targets and historical floor are unchanged. release/install-policy retains the first authenticated version 0.33.0. This source change alone does not update GitHub's independently pinned tooling or signing environment.

The release-signing environment requires review by ShadowfetchStudio (User ID 209457103), with self-review allowed. Preserve those protections. NATIVE_RELEASE_SIGNING_ENVIRONMENT points to that environment. After candidate qualification, add the exact release tag to its deployment policy and set NATIVE_RELEASE_TOOLING_COMMIT to the independently reviewed immutable release commit. Read back both settings. A permitted tag is not proof of publication.

Before tagging, finish review and push the tooling commit, then set NATIVE_RELEASE_TOOLING_COMMIT to that exact 40-character SHA. Read back this pin from GitHub configuration before dispatching the release. Verify the environment protections and source/candidate receipts before approving signing. Neither the public key nor configured secret proves that a package has been built, signed or published. See the authentication contract for bootstrap and custody.

git tag -a vVERSION -m "ShadowCode VERSION"
git push origin vVERSION

release.yml then:

  1. Checks the tag against the version files.
  2. Builds and tests the UI.
  3. Runs Rust fmt, clippy and tests.
  4. Exercises the CLI, stress suite, TUI, both MCP transports and the real WebKit window.
  5. Builds the llama.cpp runtime, then both packages, and inspects them.
  6. Rebuilds the AppImage runtime sources without network access.
  7. Runs the packaged CLI, TUI, window and MCP checks.
  8. Writes SHA256SUMS and runs the installer test.
  9. Prepares an unsigned handoff with required receipts. After protected review, a fresh runner verifies that immutable handoff using pinned tooling and signs private snapshots; the build job never receives the key.
  10. A separate publisher verifies and stages seven assets per target (fourteen for this two-target Linux release), compares every remote asset's bytes, then publishes. The x86_64 names are:
  • ShadowCode_VERSION_amd64.AppImage
  • ShadowCode_VERSION_amd64.deb
  • ShadowCode_VERSION_appimage-runtime-sources.tar.gz
  • SHA256SUMS
  • RELEASE-MANIFEST.json
  • RELEASE-AUTH
  • RELEASE-AUTH.sig

Identical published retries are read-only; changed bytes under an existing version are refused. Do not overwrite published versioned assets.

Don't announce a tag until this job succeeds. Afterwards, compare the uploaded checksums and the release text with what you expect.

APT repository

The historical 2.4.0 checkpoint above verified InRelease and the detached Release.gpg against the independently tracked public key in release/trust/APT-SIGNING-KEY. The downloaded binary and armored public keys both matched fingerprint 1BC07B5ECFDB514673A296FB021CAB3F2F7A1F61. Signed index sizes and hashes matched, Packages.gz decompressed to Packages, and both DEBs' control fields identified shadow-code 2.4.0 with the correct architecture. Verification installed no package.

After publish, the apt-repository job re-verifies the .deb with verify-native-release.sh against release/trust, rebuilds the repository with scripts/build-apt-repo.mjs (keeping every package already in the gh-pages pool; changed bytes under an existing file name are refused), checks InRelease with gpgv and pushes apt/ to gh-pages. Pages must be set to deploy from that branch.

It needs, in the protected signing environment:

  • secrets.NATIVE_APT_SIGNING_KEY: the ASCII-armored OpenPGP secret key (gpg --armor --export-secret-keys FPR), without a passphrase. Generate it offline; never commit it or a copy of it.
  • vars.NATIVE_APT_SIGNING_FINGERPRINT: its 40-digit uppercase primary fingerprint. The builder refuses a secret holding any other key.

Record the public fingerprint in release/trust/APT-SIGNING-KEY through a reviewed commit before the first repository publication, so users can check the keyring they download. Rotating the key is a reviewed change to that file and the two settings; announce it, since every installed source must import the new keyring.

Check afterwards:

node --test scripts/test-build-apt-repo.mjs   # locally, before tagging
curl -fsSL https://shadowfetchstudio.github.io/ShadowCode/apt/dists/stable/InRelease | gpgv --keyring ./shadowcode-archive-keyring.gpg

6. Install check

Use the complete independently authenticated installer bundle, including its release/trust, install policy, verifier helpers, icon and desktop entry. Keep the downloaded AppImage beside SHA256SUMS, RELEASE-MANIFEST.json, RELEASE-AUTH and RELEASE-AUTH.sig.

bash /path/to/trusted-bundle/scripts/install-appimage.sh /path/to/downloads/ShadowCode_2.4.1_amd64.AppImage

The installer accepts a single AppImage path or --recover; it does not accept --bundle-dir, --trust-dir or --expect-version. Those belong to the separate read-only verifier. No checksum-only or --unverified bypass is supported. For manual Debian verification/install, see the README.

With a display, the installer starts the new version itself and waits for its first window (see the README); a failed first start rolls back the AppImage, runtime and database snapshot. Then use the ShadowCode it opened, or open it from the desktop entry, and check:

  • Settings, conversations and accounts are still there.
  • Settings › Local models › Runtime shows the pinned commit and the vulkan+cpu backend.
  • A local model loads.