Repository navigation
ShadowCode 2.1: ARM64, APT repo, installer rollback, Flatpak allow-list, window size, model history - #5
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
scripts/build-apt-repo.mjs builds a pool + Packages/Release index for amd64 and arm64 from already-authenticated .debs, signs InRelease and Release.gpg with an OpenPGP key from APT_REPO_SIGNING_KEY (pinned by fingerprint, imported into a throwaway GNUPGHOME), and emits the public keyring and a deb822 .sources file. The release workflow gains an apt-repository job that re-verifies the .deb against release/trust and publishes apt/ to gh-pages. Tests use a throwaway key, dpkg-deb dummies, gpgv and apt-get in a private root. Docs and changelog updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
|
The The failing test is Generated by Claude Code |
|
My earlier comment needs a correction. The D-Bus test failure on this PR did not happen on Generated by Claude Code |
Alpine replaced 3.12.14-r0 and zlib 1.3.2-r0, so apk add in the runtime build container failed on main (as e923e5e did for openssl). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
Parameterize every architecture-dependent packaging name through a single table (scripts/native-arch.mjs) so the AppImage, .deb, AppImage runtime, Flatpak and release tooling build natively on aarch64 as well as x86_64. x86_64 names, gate scripts and asset sets are unchanged. - AppImage runtime: build.sh names runtime-$(uname -m); native-runtime.mjs builds in linux/amd64 or linux/arm64 (the pinned Alpine digest is a multi-arch index); aarch64 runtimes use a distinct input hash. - build-native.mjs: package names from the host (Tauri's _aarch64.AppImage, _arm64.deb), linuxdeploy ARCH, aarch64 runtime-sources tarball name. - AppRun and the Tauri entry point find WebKit in the aarch64 multiarch dir. - Flatpak: build-flatpak.py --arch (host default), arch-named bundle, --state-dir, --install-deps-from and --cpu-only-llama for CI builds. - Clean-host image pins debian:trixie-20260803-slim per architecture. - Release auth: envelopes carry x86_64 or aarch64 targets with per-target asset names; trust policies may list several targets; a release whose target the policy does not name is refused, as is a target switch against accepted history. Node and shell verifiers agree. - Installer: the host selects the installable role (_amd64 on x86_64, _aarch64 on aarch64), installs -aarch64 names, and requires the signed target to match the host. - native.yml: x86_64/aarch64 matrix on ubuntu-24.04 and ubuntu-24.04-arm. - release.yml: build-aarch64 job runs every required gate on the Arm runner and retains unsigned aarch64 packages; signing stays x86_64-only until the trust policy names aarch64. - Tests: aarch64 cases for release auth, installer (uname shim), deb fixture, packaging names (new test-native-arch.mjs). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
ci.yml gains three pull-request jobs gated by a Git-only change detector (packaging/, scripts/, src-tauri/, native/, .github/workflows/): - packaging-dry-run: x86_64 and aarch64 (ubuntu-24.04-arm) legs run the architecture-name, release-auth, Debian assembly/runtime repack, desktop metadata, packaging PATH, pinned-source and installer suites plus a shell syntax pass over the packaging scripts. - flatpak: builds the Flatpak with flatpak-builder and the GNOME 50 SDK (installed from Flathub by flatpak-builder), llama.cpp CPU-only to save time, caching ~/.flatpak-builder and the SDK Cargo/native build caches, then installs the bundle and starts the app and llama-server. build-in-sdk.sh records a CPU-only CI runtime as backend=cpu and allows it explicitly for the notices pass; release builds are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
DISTRIBUTING, FLATPAK, RELEASING, RELEASE_AUTHENTICATION and the README install section describe the aarch64 package names, the trust-policy target list, the installer's host-architecture rule, the new build-flatpak.py options and the pull-request Flatpak job. CHANGELOG gains a 2.1.0 (unreleased) entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
Host bubblewrap now unshares the network and runs a packaged static relay that forwards loopback :3128 to the allow-list proxy over a Unix socket in the app's shared runtime folder. Fails closed (exit 125, command not run) when the relay, socket or probe is unavailable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
Persist the main window's inner (content) size in logical pixels in a versioned window-content-size.json, separate from the window-state plugin (which still does not remember SIZE). Whatever the window reports beyond the size it was built with (GTK header bar and shadow on Wayland) is measured once and taken off before saving, so save -> restore is a fixed point and repeated launches never grow. The restored size becomes the configured inner size and then goes through the existing 90% / work area / 520x640 fit. Files without version 2 are ignored. Adds unit tests for the fixed point, no growth over 20 launches, small screen clamping, version handling and implausible decoration deltas. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
The suites assumed an x86_64 host; on ubuntu-24.04-arm 28 of 39 install-auth cases failed. A uname shim now fixes the default host and the aarch64 cases put their own shim ahead of it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
The release profile's thin LTO makes Cargo emit bitcode-only rlibs.
rust-lld (x86_64's default) accepts them; the GNU linker used on
aarch64 does not ('file format not recognized'). Reproduced on x86_64
with -fuse-ld=bfd; -C lto=fat links and the six regressions pass.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
…est-passing suggestion Schema 28 adds model_outcomes, written in the agent.completed transaction: duration, tokens, cost only when reported (estimates stored as NULL), and observed verification pass/fail. GET /api/models/outcomes summarizes it and, when routing.suggest_from_history is on, suggests the cheapest model that passed here before, respecting offline mode and spending limits. The picker shows per-row history, a side-by-side table, and the suggestion, which the user must accept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
Before activation the installer snapshots the profile database through the verified candidate's hidden `install-snapshot` command (SQLite VACUUM INTO, no migration) and refuses while ShadowCode holds the profile lock. With a display (or SHADOWCODE_FIRST_START_CHECK=require) it then starts the new version, which writes a first-start marker once its database opened and the main window finished loading. A hang, early exit or wrong-version report stops the started session and restores AppImage, runtime, integrations and the database snapshot. A new first_start_check journal phase lets --recover do the same after an installer crash. The accepted-release record is not lowered. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
Fault-injection and download-mutation cases built PATH from the runner's environment, bypassing the uname pin, so 16 cases failed on aarch64. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
…the Flatpak smoke run a session bus git worktree remove stops at the first entry it cannot delete, so whether q/.git was removed depended on readdir order (fails on tmpfs and on the aarch64 runner). Remove it explicitly to model the intended partial removal; the assertions are unchanged. All worktrees::cleanup tests pass on ext4, tmpfs and overlay as a non-root user. The Flatpak built on CI but 'flatpak run' needs a session bus; run the smoke checks under dbus-run-session. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
The publisher's policy now names both targets, so the Node and shell verifiers and the installer accept a signed aarch64 envelope. Signing and publication remain x86_64-only until the release workflow emits a per-target aarch64 envelope; docs and the workflow comment say so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
The outcome-history suggestion reads routing.suggest_from_history, but Config::default and config.example.yaml lacked it, so config_keys failed. It defaults to false (opt-in). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
Each target is built, handed off, signed and authenticated separately, and both publish into one GitHub release. - Release metadata names are per target. x86_64 keeps the historical RELEASE-AUTH, RELEASE-AUTH.sig, RELEASE-MANIFEST.json and SHA256SUMS; aarch64 uses the same names with an -aarch64 suffix. The requested package selects the names a verifier reads (Node and shell), and the envelope found there must name that target. Verified stages and installer receipts keep the historical names for every target. - Release gate scripts are built per architecture (gatesFor), so an x86_64 signer checks aarch64 receipts against the aarch64 scripts. x86_64 gate scripts and digests are byte-identical. - prepare/sign take a target (the handoff uses the build host; the signer an optional fourth argument) and the signer refuses a target the policy does not trust. publish takes several bundles, authenticates each for its own target, requires x86_64 and refuses repeated targets or names. - release.yml: build-aarch64 hands off like build; sign waits for both and signs each into its own folder; publish passes both bundles; the APT job verifies and indexes amd64 and arm64. - The in-app update notice names the aarch64 AppImage and its signature files on ARM64 and treats a release as signed only when they exist. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
…t SME GGML_CPU_ALL_VARIANTS builds an Armv9.2 SME variant on aarch64 (-march=armv9.2-a+...+sme). Ubuntu 24.04's GCC 13 rejects the +sme modifier, so the aarch64 verify job failed in the managed runtime build. build-llama.cpp.sh now probes the C and C++ compilers on aarch64 and uses gcc-14/g++-14 when the default cannot target armv9.2-a+sme, honours SHADOWCODE_CC/SHADOWCODE_CXX, and otherwise stops with a clear message. The aarch64 CI and release jobs install gcc-14 and g++-14; x86_64 builds are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
Tauri's AppImage bundler copies /usr/bin/xdg-open into the AppImage. The GitHub x86_64 image ships xdg-utils; the ubuntu-24.04-arm image does not, so the aarch64 packages gate failed after the runtime and app built. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
…ture `ARG TARGETARCH=amd64` overrode the TARGETARCH BuildKit sets, so the aarch64 clean-host gate built the amd64 Debian stage and failed with "exec format error". Declare the argument without a default; the gate's docker build command (and its digest) is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu
The installer turns on its first-window check when DISPLAY or WAYLAND_DISPLAY is set. These tests inherited the caller's environment, so on a desktop 25 of them failed at "Could not snapshot the profile database": their fixture AppImages do not implement the check. They now clear those variables, as scripts/test-install-appimage.sh already does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The publisher key's version interval stopped at 1.0.1, so a 2.1.0 envelope would be refused as above the key's range. Raise it to 2.1.0, as each past release commit did, and update the docs that quote the range. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The repository job signs InRelease and Release.gpg with a dedicated RSA-4096 OpenPGP key, fingerprint 1BC07B5ECFDB514673A296FB021CAB3F2F7A1F61, held as NATIVE_APT_SIGNING_KEY with NATIVE_APT_SIGNING_FINGERPRINT in the release-signing environment. This is its public half and fingerprint, so users can check the keyring they download, as README.md and DISTRIBUTING.md describe. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Version 2.1.0 in Cargo, Tauri, the UI package, both desktop entries, the Flatpak package test, the AppStream release list (dated after 2.0.0) and the GitHub Action defaults. The changelog entry gets its title, the release notes describe 2.1.0, the README names the 2.1.0 packages and the APT repository, and the release docs name the v2.1.0 signing rule and tooling pin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Dockerfile selects its Debian stage from TARGETARCH and declares no
default, so BuildKit's own value wins. Docker's classic builder sets no
TARGETARCH at all, so on such a host the stage name was empty ("invalid
reference format") and the clean-host-packages gate failed before
building. Both build commands now pass the host architecture, which is
the value BuildKit would choose; tests check every build command does.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The next version's upgrades, plus a macOS port estimate. Each feature has a
CHANGELOG.mdentry under 2.1.0 (unreleased).CI: every check passes on both x86_64 and aarch64, including the full
verifyjobs: build, Rust suite, native window and endurance, managed llama.cpp runtime, both packages, offline clean-host install, installer and packaged-app checks.Features
.deb(arm64), Flatpak, the AppImage runtime and llama.cpp are built natively on aarch64. x86_64 names and contents are unchanged. Native CI runs onubuntu-24.04andubuntu-24.04-arm.build-aarch64hands off unsigned likebuild.signsigns each target separately, andpublishstages both into one release (14 assets).RELEASE-AUTH-aarch64,RELEASE-AUTH-aarch64.sig,RELEASE-MANIFEST-aarch64.jsonandSHA256SUMS-aarch64. x86_64 keeps the historical names, so existing installers are unaffected.gatesFor), so the x86_64 signer checks aarch64 receipts against the aarch64 scripts. The x86_64 scripts and their digests are byte-identical.release/trust/policytrusts both targets, and the installer only accepts the AppImage for the machine's architecture.ci.yml). A Flatpak build (GNOME 50 SDK, CPU-only llama.cpp) and the packaging test suites run on both architectures for PRs that touch packaging, scripts, the app or workflows.scripts/build-apt-repo.mjsand anapt-repositoryrelease job:.debagainst their publisher signatures;InRelease/Release.gpgwith a dedicated key;gh-pages.VACUUM INTO.--unshare-net.docs/MACOS_PORT_ESTIMATE.md): 17–36 engineer-weeks, with a phased plan.CI fixes included
mainhas been failingverifybecause Alpine replaced pinned packages. This PR pinspython3to 3.12.15-r0 andzlibto 1.3.2-r1.xdg-utilsis installed for the AppImage bundler.TARGETARCH, which had selected the amd64 image.unameshim.dbus-run-session.routing.suggest_from_historynow has its default (false) and is documented inconfig.example.yaml.Verified locally (in addition to CI)
src-tauritests,cargo +1.95.0 clippy -D warningsandfmt --check.actionlinton all workflows.Before tagging 2.1.0
NATIVE_APT_SIGNING_KEY(secret) andNATIVE_APT_SIGNING_FINGERPRINT(variable,1BC07B5ECFDB514673A296FB021CAB3F2F7A1F61) are set in therelease-signingenvironment, andrelease/trust/APT-SIGNING-KEYrecords the public key (227ff15). A local dry run built andgpgv-verified a repository from the signed 1.0.1.debwith it.gh-pagesafter the first release run creates that branch.release/trust/policynow covers 0.33.0–2.1.0 (6d88efb).NATIVE_RELEASE_TOOLING_COMMITto the tagged 2.1.0 release commit (it must contain this multi-target signer). An older pin refuses the aarch64 signing call, so the release fails rather than shipping x86_64 alone.release-signingenvironment must allowv2.1.0.Also fixed:
scripts/test-install-auth.mjsclearsDISPLAY/WAYLAND_DISPLAY, so the installer's first-window check no longer fails 25 tests on a desktop machine (82dd25a).🤖 Generated with Claude Code
https://claude.ai/code/session_01Fn7NbipAkYG7cYZxHk8xRu