From 444e75f13c3512d57c226b39d6edf59fdb08a4c6 Mon Sep 17 00:00:00 2001 From: ShadowfetchStudio <209457103+ShadowfetchStudio@users.noreply.github.com> Date: Sat, 17 Oct 2026 12:09:09 -0400 Subject: [PATCH] ShadowCode 2.2.0 Version 2.2.0 everywhere it is shipped or documented as current; the signing key's range in release/trust/policy now ends at 2.2.0. Release notes, changelog and AppStream entry for 2.2.0: macOS, Flatpak downloads and your own model servers. Flatpak bundles join every release: release-flatpak.yml builds the x86_64 and aarch64 bundles (Vulkan runtime) from the release tag, installs and starts them, and attaches them with ShadowCode_VERSION_flatpak.sha256; the publisher leaves these and the macOS images alone when it re-checks a published release. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/release-flatpak.yml | 111 ++++++++++++++++++ CHANGELOG.md | 32 ++++- Cargo.lock | 4 +- Cargo.toml | 2 +- README.md | 34 +++--- docs/DISTRIBUTING.md | 5 + docs/FLATPAK.md | 20 +++- docs/RELEASE_AUTHENTICATION.md | 6 +- docs/RELEASE_NOTES.md | 50 ++++++++ docs/RELEASING.md | 12 +- docs/USER_GUIDE.md | 2 +- integrations/github-action/README.md | 2 +- integrations/github-action/action.yml | 2 +- .../github-action/examples/issue-comment.yml | 2 +- .../github-action/examples/pr-label.yml | 2 +- .../com.shadowfetch.shadowcode.appdata.xml | 3 + .../com.shadowfetch.shadowcode.desktop | 2 +- packaging/shadow-agent.desktop | 2 +- release/trust/policy | 2 +- scripts/publish-native-release.mjs | 11 +- scripts/test-flatpak-package.mjs | 6 +- scripts/test-native-release.mjs | 4 +- src-tauri/tauri.conf.json | 2 +- ui/package-lock.json | 4 +- ui/package.json | 2 +- 25 files changed, 268 insertions(+), 56 deletions(-) create mode 100644 .github/workflows/release-flatpak.yml diff --git a/.github/workflows/release-flatpak.yml b/.github/workflows/release-flatpak.yml new file mode 100644 index 00000000..832c8a5d --- /dev/null +++ b/.github/workflows/release-flatpak.yml @@ -0,0 +1,111 @@ +name: Flatpak release +# ShadowCode__x86_64.flatpak and ShadowCode__aarch64.flatpak +# (GNOME Platform, bundled llama.cpp with the Vulkan module), built from the +# release tag inside the SDK on each architecture, installed and started, then +# attached to the published GitHub release with +# ShadowCode__flatpak.sha256. Pull requests already build the +# Flatpak in ci.yml; this runs only for releases. +on: + release: + types: [published] + workflow_dispatch: + inputs: + tag: + description: 'Release tag to build and attach (for example v2.2.0)' + required: true +permissions: + contents: read +concurrency: + group: release-flatpak-${{ github.event.release.tag_name || inputs.tag }} + cancel-in-progress: false +jobs: + build: + strategy: + fail-fast: false + matrix: + include: + - runner: ubuntu-24.04 + arch: x86_64 + - runner: ubuntu-24.04-arm + arch: aarch64 + runs-on: ${{ matrix.runner }} + timeout-minutes: 240 + env: + RUSTUP_TOOLCHAIN: '1.95.0' + TAG: ${{ github.event.release.tag_name || inputs.tag }} + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + ref: ${{ env.TAG }} + persist-credentials: false + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version: '22' + - name: Require the tag to match the app version + run: | + version="$(node -p "require('./src-tauri/tauri.conf.json').version")" + test "v$version" = "$TAG" || { echo "Tag $TAG does not match app version $version" >&2; exit 1; } + - name: Install the pinned Rust toolchain + run: rustup toolchain install 1.95.0 --profile minimal + - name: Flatpak tools and Flathub + run: | + sudo apt-get update + sudo apt-get install -y flatpak flatpak-builder dbus-daemon + # flatpak-builder's bubblewrap needs unprivileged user namespaces, + # which Ubuntu 24.04 restricts through AppArmor by default. + sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 + flatpak remote-add --user --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo + - name: Build the Flatpak with the GNOME 50 SDK (Vulkan + CPU llama.cpp) + env: + SHADOWCODE_COMMIT: ${{ github.sha }} + run: python3 scripts/build-flatpak.py --install-deps-from=flathub --state-dir ~/.flatpak-builder + - name: Install and start the bundle + run: | + version="${TAG#v}" + bundle="target/flatpak/ShadowCode_${version}_${{ matrix.arch }}.flatpak" + test -f "$bundle" + flatpak install --user --noninteractive "$bundle" + # `flatpak run` needs a session bus; the runner has no desktop session. + dbus-run-session -- flatpak run com.shadowfetch.shadowcode --version | grep -Fx "ShadowCode $version" + dbus-run-session -- flatpak run --command=/app/lib/shadowcode/llama-server com.shadowfetch.shadowcode --version + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: flatpak-${{ matrix.arch }} + path: target/flatpak/ShadowCode_*_${{ matrix.arch }}.flatpak + if-no-files-found: error + compression-level: 0 + retention-days: 7 + attach: + needs: build + runs-on: ubuntu-24.04 + timeout-minutes: 20 + permissions: + contents: write + env: + TAG: ${{ github.event.release.tag_name || inputs.tag }} + GH_TOKEN: ${{ github.token }} + steps: + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + pattern: flatpak-* + path: flatpak + merge-multiple: true + - name: Attach the bundles and their checksums without replacing anything + run: | + version="${TAG#v}" + cd flatpak + ls + test -f "ShadowCode_${version}_x86_64.flatpak" + test -f "ShadowCode_${version}_aarch64.flatpak" + sha256sum "ShadowCode_${version}_x86_64.flatpak" "ShadowCode_${version}_aarch64.flatpak" > "ShadowCode_${version}_flatpak.sha256" + cat "ShadowCode_${version}_flatpak.sha256" + existing="$(gh release view "$TAG" --repo "$GITHUB_REPOSITORY" --json assets -q '.assets[].name')" + for file in "ShadowCode_${version}_x86_64.flatpak" "ShadowCode_${version}_aarch64.flatpak" "ShadowCode_${version}_flatpak.sha256"; do + if grep -Fxq "$file" <<<"$existing"; then + # Never overwrite a published file: an existing one must match. + gh release download "$TAG" --repo "$GITHUB_REPOSITORY" --pattern "$file" --output "existing-$file" + cmp -s "$file" "existing-$file" || { echo "$file on the release differs from this build; not replacing it" >&2; exit 1; } + else + gh release upload "$TAG" "$file" --repo "$GITHUB_REPOSITORY" + fi + done diff --git a/CHANGELOG.md b/CHANGELOG.md index 375029ae..382cf369 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,35 @@ # Changelog -## 2.2.0 (unreleased) - +## 2.2.0: macOS, Flatpak downloads and your own model servers + +- **macOS.** ShadowCode builds and runs as a Mac app: `ShadowCode.app` in + `ShadowCode_VERSION_aarch64.dmg` (Apple silicon) and `_x64.dmg` (Intel), + macOS 12 or later, ad-hoc signed and not notarized (GitHub is the channel; + `scripts/install-macos.sh` installs from a release after checking + `ShadowCode_VERSION_macos.sha256`). Settings and history live in + `~/Library/Application Support/ShadowCode`; opened from Finder the app + adopts the login shell's `PATH`; agent shell commands run under Seatbelt + (`sandbox-exec`) mirroring bubblewrap: hidden home and other volumes, an + empty `HOME` with read-only toolchains, writes only in the project and + scratch, network off, on or limited to the allow-list proxy; API keys can + live in the login Keychain; terminals, the dev-server preview, worktree + cleanup and SQLite inspection work without `/proc`; helpers die with the + app through a kqueue watcher; llama.cpp is built with Metal and + precompiled shaders. `.github/workflows/release-macos.yml` attaches the + images to each published release. Details: `docs/MACOS_PORT_ESTIMATE.md`. +- **Flatpak bundles on every release.** `.github/workflows/release-flatpak.yml` + builds `ShadowCode_VERSION_x86_64.flatpak` and `_aarch64.flatpak` (Vulkan + runtime) from the release tag, installs and starts them, and attaches them + with `ShadowCode_VERSION_flatpak.sha256`. The publisher leaves these + later attachments alone when it re-checks a published release. +- **Paths on approval cards.** The high-entropy secret rule judges a path + under a well-known root (`/Users`, `/Volumes`, `/home`, ...) one segment at a + time, so a command's folder is no longer shown as `[redacted secret]`; a + secret that is itself a segment is still hidden. +- **Free memory.** Local models that run in RAM (or Apple silicon's shared + memory) note when they need more memory than is free right now + (`MemAvailable` on Linux, free and reclaimable pages on macOS); + `hardware.available_bytes` reports it. - **Your own model servers.** **Settings › Accounts › Your own endpoints** connects Ollama, LM Studio, a llama.cpp or vLLM server, xAI, OpenAI or any OpenAI-compatible API. **Find models** lists what the server offers; the diff --git a/Cargo.lock b/Cargo.lock index b2a74d80..4fbbb110 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4512,7 +4512,7 @@ dependencies = [ [[package]] name = "shadowcode-core" -version = "2.1.0" +version = "2.2.0" dependencies = [ "anyhow", "base64 0.22.1", @@ -4572,7 +4572,7 @@ dependencies = [ [[package]] name = "shadowcode-desktop" -version = "2.1.0" +version = "2.2.0" dependencies = [ "anyhow", "gdk", diff --git a/Cargo.toml b/Cargo.toml index 7cb6c3f4..46c225ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ exclude = ["vendor/glib-0.18.5"] resolver = "2" [workspace.package] -version = "2.1.0" +version = "2.2.0" edition = "2021" rust-version = "1.95" license = "Apache-2.0" diff --git a/README.md b/README.md index 17475324..a7656d9b 100644 --- a/README.md +++ b/README.md @@ -70,27 +70,31 @@ The code is open source; the Shadowfetch and ShadowCode product identity is cove own terminal, go from commit to pull request, preview the app you're building, dictate with your voice, and follow along from your phone. -ShadowCode **2.1.0** is available in [GitHub releases](https://github.com/ShadowfetchStudio/ShadowCode/releases/tag/v2.1.0) for x86_64 and, for the first time, 64-bit ARM, and from the signed APT repository below. -See the [2.1.0 release notes](docs/RELEASE_NOTES.md) for changes and qualification +ShadowCode **2.2.0** is available in [GitHub releases](https://github.com/ShadowfetchStudio/ShadowCode/releases/tag/v2.2.0) for x86_64 and 64-bit ARM Linux, from the signed APT repository below and, for the first time, for macOS (Apple silicon and Intel). +See the [2.2.0 release notes](docs/RELEASE_NOTES.md) for changes and qualification limits, and the [release history](CHANGELOG.md). ## Install Releases target x86_64 Linux with glibc 2.39 or newer (Ubuntu 24.04 or later). From 2.1.0, aarch64 (64-bit ARM) packages are built and qualified too: -`ShadowCode_VERSION_aarch64.AppImage`, `ShadowCode_VERSION_arm64.deb` and -`ShadowCode_VERSION_aarch64.flatpak`. Each is signed for its own target and +`ShadowCode_VERSION_aarch64.AppImage` and `ShadowCode_VERSION_arm64.deb`. +Each is signed for its own target and published next to the x86_64 files, with its signature files named `RELEASE-AUTH-aarch64`, `RELEASE-AUTH-aarch64.sig`, `RELEASE-MANIFEST-aarch64.json` and `SHA256SUMS-aarch64`; download those with the package and use the same installer and verifier commands with the aarch64 file name. See [Distributing](docs/DISTRIBUTING.md#arm64-aarch64). +From 2.2.0 each release also carries Flatpak bundles for both architectures +(`ShadowCode_VERSION_x86_64.flatpak`, `ShadowCode_VERSION_aarch64.flatpak`, +checked with `ShadowCode_VERSION_flatpak.sha256`; see [Flatpak](docs/FLATPAK.md)) +and macOS disk images (see [macOS](#macos)). Check [GitHub releases](https://github.com/ShadowfetchStudio/ShadowCode/releases) -for published versions. The 2.1.0 x86_64 packages and checksums are: +for published versions. The 2.2.0 x86_64 packages and checksums are: -- `ShadowCode_2.1.0_amd64.AppImage` -- `ShadowCode_2.1.0_amd64.deb` +- `ShadowCode_2.2.0_amd64.AppImage` +- `ShadowCode_2.2.0_amd64.deb` - `SHA256SUMS`, `RELEASE-MANIFEST.json`, `RELEASE-AUTH` and `RELEASE-AUTH.sig` (download these beside the package; the installer checks the publisher's signature before running anything) @@ -129,7 +133,7 @@ assets are checksum-only and cannot be installed by this new entry point; use the instructions shipped with that released version for those existing assets. The 0.33.0 release attempt failed before signing and publication. Its tag stays unchanged. Version 0.33.1 was the first signed release; the public trust policy -in `release/trust` now authorizes 0.33.0 through 2.1.0. +in `release/trust` now authorizes 0.33.0 through 2.2.0. For development, use [Build from source](#build-from-source). Obtain an independently authenticated installer bundle as described below, @@ -143,7 +147,7 @@ bundle and bootstrap requirements. From that independently authenticated installer bundle, run: ```bash -bash /path/to/trusted-bundle/scripts/install-appimage.sh /path/to/downloads/ShadowCode_2.1.0_amd64.AppImage +bash /path/to/trusted-bundle/scripts/install-appimage.sh /path/to/downloads/ShadowCode_2.2.0_amd64.AppImage ``` The installer takes the AppImage path (or `--recover`), resolves its own trusted @@ -189,7 +193,7 @@ as `--trust-dir` are not installer options. cannot corrupt it. After obtaining and verifying the intended package, run the AppImage without installing it: -`./ShadowCode_2.1.0_amd64.AppImage --appimage-extract-and-run`. FUSE is not +`./ShadowCode_2.2.0_amd64.AppImage --appimage-extract-and-run`. FUSE is not required. ### Debian package @@ -237,16 +241,16 @@ installed. The repository is published by the release workflow only; nothing in ShadowCode adds or contacts it by itself. To install one release by hand instead, verify the Debian artifact using the independently trusted verifier bundle. -`verified-deb-2.1.0` must not already exist; install the verified snapshot: +`verified-deb-2.2.0` must not already exist; install the verified snapshot: ```bash bash /path/to/trusted-bundle/scripts/verify-native-release.sh \ --bundle-dir /path/to/downloads \ --trust-dir /path/to/trusted-bundle/release/trust \ - --artifact ShadowCode_2.1.0_amd64.deb \ - --stage-dir ./verified-deb-2.1.0 \ - --expect-version 2.1.0 -sudo apt install ./verified-deb-2.1.0/ShadowCode_2.1.0_amd64.deb + --artifact ShadowCode_2.2.0_amd64.deb \ + --stage-dir ./verified-deb-2.2.0 \ + --expect-version 2.2.0 +sudo apt install ./verified-deb-2.2.0/ShadowCode_2.2.0_amd64.deb ``` A `.deb` installed by hand this way gets no updates and none of the APT diff --git a/docs/DISTRIBUTING.md b/docs/DISTRIBUTING.md index b11c4098..60ec7f69 100644 --- a/docs/DISTRIBUTING.md +++ b/docs/DISTRIBUTING.md @@ -45,6 +45,11 @@ bash /path/to/trusted-bundle/scripts/verify-native-release.sh \ --stage-dir ./verified-deb-VERSION ``` +The Flatpak bundles are attached after publication by +`.github/workflows/release-flatpak.yml` (from 2.2.0), with SHA-256 checksums +in `ShadowCode_VERSION_flatpak.sha256` rather than publisher signatures; the +macOS disk images likewise (`release-macos.yml`, `ShadowCode_VERSION_macos.sha256`). + Releases before 2.1.0 have no aarch64 packages; build them from source (below) on an aarch64 machine. Cross-building is not supported: each architecture is built on its own hardware. diff --git a/docs/FLATPAK.md b/docs/FLATPAK.md index 698a48b3..7d4da92b 100644 --- a/docs/FLATPAK.md +++ b/docs/FLATPAK.md @@ -1,19 +1,27 @@ -# ShadowCode 2.1 Flatpak +# ShadowCode 2.2 Flatpak The Flatpak runs the native GTK/WebKit desktop, application engine, SQLite profile, and bundled CPU/Vulkan llama.cpp runtime on GNOME Platform 50. It is an x86_64 or aarch64 package built from source inside the SDK on a host of -the same architecture. Version 2.1.0 is a local -build until a publisher signs and publishes it; it is not listed on Flathub. +the same architecture. From 2.2.0 every GitHub release carries both bundles +(`.github/workflows/release-flatpak.yml` builds, installs and starts them +from the release tag) with their SHA-256 checksums in +`ShadowCode_VERSION_flatpak.sha256`. They are checked by that checksum, not +by the publisher signature the AppImage and deb carry. It is not listed on +Flathub. -## Install the local bundle +## Install the bundle + +Download the bundle for your computer and the checksum file from the +release, then: ```sh -flatpak install --user ./ShadowCode_2.1.0_x86_64.flatpak +sha256sum --check --ignore-missing ShadowCode_2.2.0_flatpak.sha256 +flatpak install --user ./ShadowCode_2.2.0_x86_64.flatpak flatpak run com.shadowfetch.shadowcode ``` -On 64-bit ARM, install `ShadowCode_VERSION_aarch64.flatpak` instead. +On 64-bit ARM, install `ShadowCode_2.2.0_aarch64.flatpak` instead. The bundle points to Flathub for the GNOME runtime. Installation exports the application launcher and icons into the desktop's Applications menu. diff --git a/docs/RELEASE_AUTHENTICATION.md b/docs/RELEASE_AUTHENTICATION.md index 2a1be0d9..3176b184 100644 --- a/docs/RELEASE_AUTHENTICATION.md +++ b/docs/RELEASE_AUTHENTICATION.md @@ -102,7 +102,7 @@ Each key has an inclusive version range and exactly one epoch. Unknown keys, dif For a reviewed rotation, distribute a new authenticated trust bundle with the new public key and higher minimum epoch/version. Retain the old public key with its historical version range only when needed to verify an existing accepted-state receipt. The internal history check may ignore current minimum floors, but it still verifies the old signature, identity, key epoch and historical key range. This exception is not exposed as an install-verification API. Deleting an old key outright can make old state unverifiable; the installer must then fail pending explicit migration, not erase the state or assume a fresh install. -The tracked `release/trust` bundle contains the public Ed25519 key with ID `f0c60ff8228314616985712f8918c9798c0ecf72b7271e19343a041c25663b7f`. Its epoch is 1, minimum version is 0.33.0, and its inclusive key range is 0.33.0–2.1.0. It authorizes no later version without a reviewed policy update. The private key is not distributed in the repository or installer bundle. Fixture keys remain temporary and separate. Public fingerprint distribution, custody and future rotation/revocation remain owner responsibilities. +The tracked `release/trust` bundle contains the public Ed25519 key with ID `f0c60ff8228314616985712f8918c9798c0ecf72b7271e19343a041c25663b7f`. Its epoch is 1, minimum version is 0.33.0, and its inclusive key range is 0.33.0–2.2.0. It authorizes no later version without a reviewed policy update. The private key is not distributed in the repository or installer bundle. Fixture keys remain temporary and separate. Public fingerprint distribution, custody and future rotation/revocation remain owner responsibilities. ## Downgrade, replay and accepted state @@ -149,8 +149,8 @@ A separate publisher runner receives the signing job's immutable artifact ID and The workflow deliberately refuses missing owner configuration. The following records the 0.33.1 setup; recheck it before dispatching a release: - The tracked `release/trust` public policy and key bundle must be included in the reviewed tooling commit and distributed through an authenticated channel. It contains public material only; no default fixture key is trusted. -- Repository variable `NATIVE_RELEASE_TOOLING_COMMIT` must pin the exact 40-character reviewed and pushed commit containing the current gate definitions, signing/publisher code, public trust and release-appropriate notes. The reviewed pin for 0.33.1 was `e15c4480e65db5650af012bb2a9773dbe89acf84`; for 2.1.0 it is the tagged `v2.1.0` release commit (`v1.0.1` for 1.0.1, `v1.0.0` for 1.0.0, `v0.34.2` for 0.34.2). Never infer this pin from an unreviewed tag. -- Repository variable `NATIVE_RELEASE_SIGNING_ENVIRONMENT` is set to `release-signing`. Its verified configuration requires the `ShadowfetchStudio` User reviewer (ID `209457103`, unchanged after the account rename), allows self-review and retains GitHub's default administrator override. Its sole deployment rule allows the tag being released (`v2.1.0` for 2.1.0; `v1.0.1`, `v1.0.0`, `v0.34.2` and `v0.33.1` before). This is an owner-reviewed gate, not a two-person approval guarantee; a later release needs an explicit rule/policy update. +- Repository variable `NATIVE_RELEASE_TOOLING_COMMIT` must pin the exact 40-character reviewed and pushed commit containing the current gate definitions, signing/publisher code, public trust and release-appropriate notes. The reviewed pin for 0.33.1 was `e15c4480e65db5650af012bb2a9773dbe89acf84`; for 2.2.0 it is the tagged `v2.2.0` release commit (`v2.1.0` for 2.1.0, `v1.0.1` for 1.0.1, `v1.0.0` for 1.0.0, `v0.34.2` for 0.34.2). Never infer this pin from an unreviewed tag. +- Repository variable `NATIVE_RELEASE_SIGNING_ENVIRONMENT` is set to `release-signing`. Its verified configuration requires the `ShadowfetchStudio` User reviewer (ID `209457103`, unchanged after the account rename), allows self-review and retains GitHub's default administrator override. Its sole deployment rule allows the tag being released (`v2.2.0` for 2.2.0; `v2.1.0`, `v1.0.1`, `v1.0.0`, `v0.34.2` and `v0.33.1` before). This is an owner-reviewed gate, not a two-person approval guarantee; a later release needs an explicit rule/policy update. - Environment secret `NATIVE_RELEASE_SIGNING_KEY_PEM` has been uploaded to `release-signing`. It is scoped to the signing environment, not repository-wide secrets or the build job. Its presence does not prove that a candidate has been signed. Owner review of the release workflow/source and repository protections remains necessary: another authorized workflow could request the same environment secret. Local gate receipts are validated assertions, not independent attestations that an adversarial producer executed the commands. Workflow dependencies and exact artifact IDs bind the proposed job flow; local fixtures do not prove GitHub control-plane behavior. Remote checks are observations, not atomic compare-and-swap against independently authorized concurrent changes. diff --git a/docs/RELEASE_NOTES.md b/docs/RELEASE_NOTES.md index 9f49728e..6fda0c88 100644 --- a/docs/RELEASE_NOTES.md +++ b/docs/RELEASE_NOTES.md @@ -1,3 +1,53 @@ +# ShadowCode 2.2.0 + +ShadowCode 2.2.0 runs on Macs, both Apple silicon and Intel, and its Linux +Flatpak is now a download on every release. It also connects to your own +model servers and adds find in conversation, a smarter command palette and +text size. The 2.1.0 notes follow below. + +## New + +- **ShadowCode for macOS.** `ShadowCode_2.2.0_aarch64.dmg` for Apple silicon + and `ShadowCode_2.2.0_x64.dmg` for Intel Macs (macOS 12 or later). Local + models run on llama.cpp with Metal; agent shell commands run in the macOS + sandbox, with your home folder and other drives hidden; API keys can be + kept in the Keychain. Install or update with one command, or open the + `.dmg` (see the [README](../README.md#macos); a copy downloaded in a + browser needs **Open Anyway** in Privacy & Security the first time). +- **The Flatpak on every release.** `ShadowCode_2.2.0_x86_64.flatpak` and + `ShadowCode_2.2.0_aarch64.flatpak`, with the Vulkan GPU runtime, built, + installed and started from the release before they are attached. +- **Your own model servers.** **Settings › Accounts › Your own endpoints** + connects Ollama, LM Studio, llama.cpp or vLLM servers, xAI, OpenAI or any + OpenAI-compatible API; the models you pick run with ShadowCode's own agent. +- **Settings › Agent.** Steps, budgets, time limits, retries, history + shortening, checkpoints and more, each with its range, default and Reset. +- **Find in conversation** (`Ctrl+F`), search that also matches answers, a + command palette that matches letters in order and lists conversations and + projects, **text size** (`Ctrl+=`, `Ctrl+-`, `Ctrl+0`), message times, and + **Show all** and **Copy** for long tool output. + +## Fixed + +- **Approval cards show the folder a command runs in.** Long paths such as + `/Volumes/Disk2/projects/app` could be hidden as if they were secrets. +- **Low memory is named before a model loads.** A local model that needs + more memory than is free right now says so, instead of running very slowly. +- The theme follows the desktop by default, and screen readers hear + milestones rather than every streamed update. + +## Download + +Linux x86_64: `ShadowCode_2.2.0_amd64.AppImage`, `ShadowCode_2.2.0_amd64.deb` +and `ShadowCode_2.2.0_appimage-runtime-sources.tar.gz`, with `SHA256SUMS`, +`RELEASE-MANIFEST.json`, `RELEASE-AUTH` and `RELEASE-AUTH.sig`. For ARM64 the +packages end in `_aarch64` (AppImage) or `_arm64` (`.deb`), with signature +files ending in `-aarch64`. Install the AppImage with the authenticated +installer described in the [README](../README.md#install); the signature is +checked before anything runs. The Flatpak bundles and the macOS disk images +are attached shortly after publication, with their SHA-256 checksums in +`ShadowCode_2.2.0_flatpak.sha256` and `ShadowCode_2.2.0_macos.sha256`. + # ShadowCode 2.1.0 ShadowCode 2.1.0 runs on 64-bit ARM computers, installs and updates from a diff --git a/docs/RELEASING.md b/docs/RELEASING.md index 1b1eaf4d..e6e3b1ab 100644 --- a/docs/RELEASING.md +++ b/docs/RELEASING.md @@ -7,7 +7,7 @@ and authentication receipts to the exact candidate before publication. Pushing a `v*` tag starts `.github/workflows/release.yml`. Publication follows build/qualification, protected signing review and verification of all seven public assets. The signing environment permits only the tag being released -(`v2.1.0` for 2.1.0); every later version needs reviewed trust-policy, +(`v2.2.0` for 2.2.0); every later version needs reviewed trust-policy, deployment-rule and tooling-pin updates. The workflow uses `docs/RELEASE_NOTES.md` as the release text. @@ -185,15 +185,15 @@ 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. -Public trust in `release/trust` currently allows the x86_64 and aarch64 targets, epoch 1 and versions 0.33.0–2.1.0 +Public trust in `release/trust` currently allows the x86_64 and aarch64 targets, epoch 1 and versions 0.33.0–2.2.0 (raise the key's maximum version in the release commit, as for earlier releases); `release/install-policy` fixes the first authenticated version at 0.33.0. The `release-signing` environment has the signing secret and requires review by `Shadowfetchapps` (User ID `209457103`). Self-review is allowed and GitHub's -default administrator override remains unchanged. For 2.1.0 its sole -deployment rule is the tag `v2.1.0` (it was `v1.0.1` for 1.0.1, `v1.0.0` for -1.0.0, `v0.34.2` for 0.34.2 and `v0.33.1` for 0.33.1); -`NATIVE_RELEASE_SIGNING_ENVIRONMENT` points to that environment. For 2.1.0, +default administrator override remains unchanged. For 2.2.0 its sole +deployment rule is the tag `v2.2.0` (it was `v2.1.0` for 2.1.0, `v1.0.1` for +1.0.1, `v1.0.0` for 1.0.0, `v0.34.2` for 0.34.2 and `v0.33.1` for 0.33.1); +`NATIVE_RELEASE_SIGNING_ENVIRONMENT` points to that environment. For 2.2.0, `NATIVE_RELEASE_TOOLING_COMMIT` pins the tagged release commit itself, as it did for 0.33.1 (`e15c4480e65db5650af012bb2a9773dbe89acf84`). diff --git a/docs/USER_GUIDE.md b/docs/USER_GUIDE.md index 0837e390..272fc3d8 100644 --- a/docs/USER_GUIDE.md +++ b/docs/USER_GUIDE.md @@ -1,6 +1,6 @@ # ShadowCode user guide -This guide describes the 2.1.0 workflow: open a +This guide describes the 2.2.0 workflow: open a project, pick a model, describe the task, watch the agent work, then review what changed. Installation and a feature overview are in the [README](../README.md). diff --git a/integrations/github-action/README.md b/integrations/github-action/README.md index e61f0537..60767b47 100644 --- a/integrations/github-action/README.md +++ b/integrations/github-action/README.md @@ -50,7 +50,7 @@ command line runs directly. | `github-token` | `github.token` | Used only for the comment or pull request, after ShadowCode finished. | | `issue-number` | the event's issue or pull request | Where to comment. | | `base` | the checked-out branch | Target branch of the pull request. | -| `version` | `2.1.0` | ShadowCode release to run. `approval: approve` needs the release that ships this action or later. | +| `version` | `2.2.0` | ShadowCode release to run. `approval: approve` needs the release that ships this action or later. | | `appimage-sha256` | empty | Optional extra pin for the AppImage's SHA-256. | | `working-directory` | the workspace | Project folder. | diff --git a/integrations/github-action/action.yml b/integrations/github-action/action.yml index 2f7c1957..91277b90 100644 --- a/integrations/github-action/action.yml +++ b/integrations/github-action/action.yml @@ -81,7 +81,7 @@ inputs: version: description: ShadowCode release to download (without the leading v). required: false - default: 2.1.0 + default: 2.2.0 appimage-sha256: description: >- Optional SHA-256 of the AppImage. When set it must match as well as the diff --git a/integrations/github-action/examples/issue-comment.yml b/integrations/github-action/examples/issue-comment.yml index f35b0b14..898659bd 100644 --- a/integrations/github-action/examples/issue-comment.yml +++ b/integrations/github-action/examples/issue-comment.yml @@ -39,7 +39,7 @@ jobs: persist-credentials: false # Pin to a release tag or, better, a full commit SHA. - - uses: ShadowfetchStudio/ShadowCode/integrations/github-action@v2.1.0 + - uses: ShadowfetchStudio/ShadowCode/integrations/github-action@v2.2.0 with: task: ${{ github.event.comment.body }} api-key: ${{ secrets.OPENROUTER_API_KEY }} diff --git a/integrations/github-action/examples/pr-label.yml b/integrations/github-action/examples/pr-label.yml index 0bb7da02..77c02996 100644 --- a/integrations/github-action/examples/pr-label.yml +++ b/integrations/github-action/examples/pr-label.yml @@ -35,7 +35,7 @@ jobs: persist-credentials: false fetch-depth: 0 - - uses: ShadowfetchStudio/ShadowCode/integrations/github-action@v2.1.0 + - uses: ShadowfetchStudio/ShadowCode/integrations/github-action@v2.2.0 with: task: >- Review the changes on this branch against diff --git a/packaging/com.shadowfetch.shadowcode.appdata.xml b/packaging/com.shadowfetch.shadowcode.appdata.xml index 7d2ebccc..04a3678d 100644 --- a/packaging/com.shadowfetch.shadowcode.appdata.xml +++ b/packaging/com.shadowfetch.shadowcode.appdata.xml @@ -29,6 +29,9 @@ shadowcode + +

Your own model servers (Ollama, LM Studio, vLLM, OpenAI-compatible APIs), Settings › Agent, find in conversation, a smarter command palette, text size, and a native macOS app for Apple silicon and Intel Macs.

+

Signed ARM64 builds, a signed APT repository, an installer that checks the new version's first window and can roll back, the hostname allow-list in the Flatpak, a window that remembers its size on Wayland, and per-model history in the picker.

diff --git a/packaging/flatpak/com.shadowfetch.shadowcode.desktop b/packaging/flatpak/com.shadowfetch.shadowcode.desktop index 357de985..5b958392 100644 --- a/packaging/flatpak/com.shadowfetch.shadowcode.desktop +++ b/packaging/flatpak/com.shadowfetch.shadowcode.desktop @@ -11,4 +11,4 @@ Keywords=agent;llm;coding;shadowfetch; StartupNotify=true StartupWMClass=shadowcode X-GNOME-UsesNotifications=true -X-ShadowCode-Version=2.1.0 +X-ShadowCode-Version=2.2.0 diff --git a/packaging/shadow-agent.desktop b/packaging/shadow-agent.desktop index 34bdc195..ec8cd055 100644 --- a/packaging/shadow-agent.desktop +++ b/packaging/shadow-agent.desktop @@ -13,4 +13,4 @@ Keywords=agent;llm;coding;shadowfetch; StartupNotify=true StartupWMClass=shadowcode X-GNOME-UsesNotifications=true -X-ShadowCode-Version=2.1.0 +X-ShadowCode-Version=2.2.0 diff --git a/release/trust/policy b/release/trust/policy index cf8feed2..4da6c311 100644 --- a/release/trust/policy +++ b/release/trust/policy @@ -7,4 +7,4 @@ channel=stable minimum-epoch=1 minimum-version=0.33.0 keys=ed25519-spki-sha256 -key=1 f0c60ff8228314616985712f8918c9798c0ecf72b7271e19343a041c25663b7f 0.33.0 2.1.0 +key=1 f0c60ff8228314616985712f8918c9798c0ecf72b7271e19343a041c25663b7f 0.33.0 2.2.0 diff --git a/scripts/publish-native-release.mjs b/scripts/publish-native-release.mjs index 3d6c48b0..cc0c4c6d 100644 --- a/scripts/publish-native-release.mjs +++ b/scripts/publish-native-release.mjs @@ -11,10 +11,11 @@ import { IDENTITY, TARGETS } from './native-release-auth.mjs'; import { withReleaseSnapshot, validateContext, validateStagedRelease, readReceipts, requireTransportLayout } from './native-release-assets.mjs'; export { digest } from './native-release-verification.mjs'; -// After publication, .github/workflows/release-macos.yml attaches the macOS -// disk images and their checksums. They are outside this signed asset set: -// a published-release retry leaves them alone; a draft never has them. -const MACOS_ASSET = /^ShadowCode_\d+\.\d+\.\d+_(x64|aarch64)\.dmg$|^ShadowCode_\d+\.\d+\.\d+_macos\.sha256$/; +// After publication, .github/workflows/release-macos.yml and +// release-flatpak.yml attach the macOS disk images, the Flatpak bundles and +// their checksums. They are outside this signed asset set: a +// published-release retry leaves them alone; a draft never has them. +const ATTACHED_LATER = /^ShadowCode_\d+\.\d+\.\d+_((x64|aarch64)\.dmg|(x86_64|aarch64)\.flatpak|(macos|flatpak)\.sha256)$/; const command = (args) => execFileSync('gh', args, { encoding: 'utf8', maxBuffer: 16 * 1024 * 1024, stdio: ['ignore', 'pipe', 'pipe'] }); // One release carries every target's signed bundle. Each bundle is snapshotted @@ -90,7 +91,7 @@ async function publishVerified({ repo, tag, commit, expected, gh, sleep }) { const scratch = await mkdtemp(path.join(tmpdir(), 'shadowcode-release-')); try { for (const asset of record.assets) { - if (!record.draft && MACOS_ASSET.test(asset.name)) continue; + if (!record.draft && ATTACHED_LATER.test(asset.name)) continue; assert(expected.has(asset.name), `Unexpected remote asset ${asset.name}; review the draft`); assert(!names.has(asset.name), `Duplicate remote asset ${asset.name}`); names.add(asset.name); diff --git a/scripts/test-flatpak-package.mjs b/scripts/test-flatpak-package.mjs index 3f0ce794..3ae6d267 100644 --- a/scripts/test-flatpak-package.mjs +++ b/scripts/test-flatpak-package.mjs @@ -58,7 +58,7 @@ await writeFile(path.join(profile, "config/config.yaml"), JSON.stringify({ })); let owner, lease; try { - assert.equal(await cli(["--version"]), "ShadowCode 2.1.0"); + assert.equal(await cli(["--version"]), "ShadowCode 2.2.0"); assert.equal((await cli(["health"])).runtime, "rust"); await cli(["trust"]); const exec = await cli(["exec", "printf host-command > host.txt; git --version; node --version; readlink /proc/self/ns/net"]); @@ -98,7 +98,7 @@ try { } const view = (await exchange("POST", "/api/views", null, null, true)).view; const about = await exchange("GET", "/api/about", null, view); - assert.equal(about.version, "2.1.0"); assert.equal(about.publisher, "Shadowfetch"); + assert.equal(about.version, "2.2.0"); assert.equal(about.publisher, "Shadowfetch"); assert.equal(about.install.kind, "flatpak"); assert.equal(about.links.website, "https://www.shadowfetchlinux.org/shadowcode"); assert.equal(about.links.publisher, "https://shadowfetch.com"); @@ -136,7 +136,7 @@ try { return result.stdout === "dead"; }, 5000); checks.push("persistent engine, attached view, real host PTY, shell job control, resize, Ctrl-C and descendant cleanup"); - await writeFile(path.join(output, "package-result.json"), JSON.stringify({ version: "2.1.0", profile, project, checks, terminal, terminal_child_pid: terminalChild, host_network: hostNetwork }, null, 2) + "\n"); + await writeFile(path.join(output, "package-result.json"), JSON.stringify({ version: "2.2.0", profile, project, checks, terminal, terminal_child_pid: terminalChild, host_network: hostNetwork }, null, 2) + "\n"); console.log(JSON.stringify(checks, null, 2)); } finally { if (lease) lease.destroy(); diff --git a/scripts/test-native-release.mjs b/scripts/test-native-release.mjs index fd427eb2..7808db46 100644 --- a/scripts/test-native-release.mjs +++ b/scripts/test-native-release.mjs @@ -69,10 +69,12 @@ test('published retry verifies bytes without mutations', () => fixture(async ({ assert.equal((await execute()).status, 'already-published'); assert(state.calls.every(args => args[0] === 'api' || args[1] === 'download')); })); -test('a published retry leaves the macOS images alone but a draft refuses them', () => fixture(async ({ state, execute }) => { +test('a published retry leaves the macOS images and Flatpaks alone but a draft refuses them', () => fixture(async ({ state, execute }) => { await execute(); state.calls = []; state.assets.set('ShadowCode_1.0.0_x64.dmg', Buffer.from('macOS image')); state.assets.set('ShadowCode_1.0.0_macos.sha256', Buffer.from('checksums')); + state.assets.set('ShadowCode_1.0.0_aarch64.flatpak', Buffer.from('Flatpak bundle')); + state.assets.set('ShadowCode_1.0.0_flatpak.sha256', Buffer.from('checksums')); assert.equal((await execute()).status, 'already-published'); assert(state.calls.every(args => args[0] === 'api' || args[1] === 'download')); state.release.draft = true; diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index ce53fa79..6a576f93 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "ShadowCode", - "version": "2.1.0", + "version": "2.2.0", "identifier": "com.shadowfetch.shadowcode", "build": { "beforeDevCommand": { diff --git a/ui/package-lock.json b/ui/package-lock.json index 89a4f0f4..d185dd38 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -1,12 +1,12 @@ { "name": "shadow-agent-ui", - "version": "2.1.0", + "version": "2.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "shadow-agent-ui", - "version": "2.1.0", + "version": "2.2.0", "license": "Apache-2.0", "dependencies": { "@codemirror/commands": "6.11.1", diff --git a/ui/package.json b/ui/package.json index 87a5b27a..29bb8a9e 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "shadow-agent-ui", - "version": "2.1.0", + "version": "2.2.0", "private": true, "license": "Apache-2.0", "type": "module",