Unreleased
These notes describe source-tree progress. They are not a public release announcement.
- Root-level Bunny deployments now pass the post-upload live-site check when
BUNNY_REMOTE_PREFIXis intentionally empty, while an omitted command argument remains an error. - The signed installer is now live at
https://loopwire.app/install.sh; AppImage, deb, and RPM artifacts are available from thev0.1.0GitHub Release, with native files documented as direct downloads rather than distro repositories.
CI selection
- Automatic checks now follow application, AUR, web/docs and workflow-contract path scopes. Site, documentation and README changes avoid unrelated native builds; a dependency-aware lockfile check handles shared pnpm inputs.
- Docs deployment now has explicit web/build/deploy path filters while retaining manual and release-tag runs. Scheduled diagnostics and operator release workflows retain their entrypoints.
- Release auditing now checks the actual successful workspace job and check step, rejecting scope-only or skipped CI success and explaining how to request a full run at the release ref.
- Packaging README assertions moved to lightweight docs validation. The full local
pnpm checkcommand is unchanged. - Native proof freshness now compares application lockfile inputs, so website-only dependencies do not invalidate recorded package evidence. Relevant or unverifiable dependency changes still fail the check.
Landing page
- The root page now uses a flat Sora wordmark and signal-path identity, with the product screenshot integrated into the main composition. Decorative panels, capability cards, pill controls, shadows and glow have been removed.
- A GSAP background responds to pointer movement, clicks, platform tabs and successful copying. Reduced motion keeps the linework static and changes palettes immediately. Existing installation commands remain unchanged.
Installation
- The homepage defaults to a one-command installer with accessible platform tabs, selected-command copying, and a separate source-build option. The obsolete pre-release gating notice has been removed.
- The signed installer detects supported distributions and architectures, reports each operation, embeds the release verification key, and handles repeat installs and upgrades. Portable installs stage and verify files before replacing existing files; native packages use the distro package manager. Automatic preserves earlier portable installations, and incomplete rollback retains recovery backups with explicit restoration paths.
- Multi-step manual package instructions link to repository work for APT, Fedora, and openSUSE.
Packaging
- The AUR now keeps two honest stable recipes:
loopwirecompiles the immutable tagged source archive, whileloopwire-bincontinues to consume signed prebuilt release artifacts. Both are built and inspected before a manual, environment-protected AUR publication workflow may push their separate package repositories. - A third
loopwire-gitAUR recipe follows the protected default branch, derives a monotonic VCS package version, and remains explicitly separate from the stable source and binary package bases.
Docs deployment
- Docs deployment now requests a full Bunny CDN Pull Zone purge after all uploads and manifest generation succeed. Configure the separate
BUNNY_API_KEYaccount secret and numericBUNNY_PULL_ZONE_IDvariable; the guided setup checks both. Upload, manifest, and purge failures fail the deployment, while dry-run makes no requests. Purges invalidate the CDN zone's paths; copies already cached in browsers continue to follow HTTP cache headers.
Desktop UI Rebuild
GitHub Actions setup now has a cross-platform guided command that separates public variables from secrets, explains every source field, validates release keys locally, and transports entered bytes to GitHub CLI without shell interpolation or hidden normalization.
The public web surface now splits cleanly: an Astro homepage at
/and VitePress docs below/docs/, assembled into one Bunny deployment artifact so the homepage, installer endpoint, and docs stay aligned.The desktop shell was rebuilt as a device sidebar plus patch-bay canvas: Sources / Output Channels / Monitors columns with per-channel meters, port dots, and bezier cables between cards.
Devices carry On/Off, mute, and volume controls in the sidebar; device removal shows an undo toast instead of a confirmation dialog, and the device list may now be empty (persisted schema v2 with automatic v1 migration).
Sources and monitors are added from grouped menus backed by host enumeration; buses are added from a small ⊕ menu; new endpoints auto-cable channel-to-channel, and port-to-port drags create routes.
The Output Channels ⊕ now offers Stereo Bus, Mono Bus, and Quad Bus, each appended instantly on pick with channel-count-aware labels (
Channels 3 & 4,Channel 5,Channels 3–6) and cumulative start channels. This diverges from the reference's instant stereo-only add by one pick: bus creation stays one-click-then-pick so wider layouts do not need a separate editor.Source/monitor cards expose On/Off pills and an Options strip (source volume drives outgoing route gains; app sources add mute-when-capturing; monitor volume is configured state applied on host apply).
App settings moved to a Settings dialog (
Ctrl+,) with Appearance (Match System/Light/Dark), the audio backend picker with runtime activity ledger, automatic host-apply status, startup integration, and update policy.Selecting a device now applies its configuration through the saved backend immediately (with preflight and rollback); when live apply cannot run, the switch happens in preview and the reason is reported. Sidebar devices reorder with click-and-drag, UI text is unselectable, and card selection no longer clears itself.
Native PipeWire now creates Loopwire-owned virtual source nodes for sources without a host binding, so the default Pass-Thru → Channels 1 & 2 device applies live end to end instead of being blocked by preflight.
Explicit bus → monitor cables now drive native PipeWire monitor linking (unwired buses stay silent to that monitor); JACK/PulseAudio tolerate those routes and keep their implicit monitor behavior. Routes touching an Off card apply as muted (disconnected), Off devices switch in preview, and muted routes whose host ports are gone no longer fail apply.
Sources now carry a kind (app stream, capture hardware, system source, or pass-thru) recorded from host enumeration and persisted as an optional schema v2 field; card and sidebar icons, add-menu grouping, and the mute-when-capturing option derive from that kind, with the old label heuristics kept only as a fallback for pre-existing saved states.
Removed from the UI in this rebuild (domain/CLI paths remain): custom window chrome mode; meters render silence until a per-port level stream exists in the audio host layer. Configuration export/import, the diagnostics panel, and manual host-binding fields returned in a later power-user slice (see the Settings Transfer/Diagnostics and host-binding entries below).
DSP and JACK provider settings are back in the rebuilt desktop UI: a Settings → Providers section persists the DSP provider command, trust mode, timeout, and frame count plus the JACK provider command, timeout, delegate mode, and readiness delay under the pre-rebuild storage keys. Saving a live DSP provider command makes DSP Provider selectable in the backend picker, live apply re-verifies the DSP provider
capabilitiescontract before provider-backed host transactions, saved JACK provider settings feed native JACK live apply and preflight readiness, and enabling background restore writes the matching provider flags into the user-scoped systemd unit.An end-to-end UI harness now drives the rebuilt shell through its core flows:
pnpm e2e:uibuilds the frontend, serves it locally, and walks create/rename, add-source cabling, On/Off dimming, select/Delete, Hide Monitors, reload persistence, and sidebar drag-reorder in headless Chromium, asserting DOM outcomes with honest preview-mode scope (no host-apply claims).pnpm e2e:shelladds a read-only WebDriver smoke of the real Tauri binary viatauri-driver+WebKitWebDriverwhere the host provides them.pnpm e2e:shell -- --dsp-provider-smokenow adds an opt-in real-shell proof for provider-backed DSP live apply: the app runs under temporaryXDG_CONFIG_HOME/XDG_STATE_HOME, uses a temp wrapper around the bundledloopwire-dsp-provider, enables its explicitLOOPWIRE_DSP_PROVIDER_LIVE_SMOKE=1contract mode, and verifies a rendered output in a temp provider store without touching the operator's saved Loopwire state or real PipeWire/JACK graph.
Supported In Source
The tag-driven GitHub Release workflow now publishes a strict useful-asset set: two portable tarballs, two tag-versioned AppImages, four proven x86_64 native packages, signed checksums, a machine-readable
release-assets.json, and tag-bound release evidence. AArch64 GUI-only deb/RPM bundles are excluded, and the remote inventory is reconciled, downloaded, and re-verified after publication, including same-tag workflow reruns.Native x86_64 package recipes now cover Ubuntu 24.04, Debian 13, Fedora 44, and openSUSE Tumbleweed from the same checksum-bound release tarball. A checksum-pinned QEMU/KVM harness verifies package metadata, installed files, packaged background/provider/backend commands, a Loopwire X11 application window, and clean uninstall in matching guests. All four guests passed at commit
70eee4e; a review-safe proof snapshot is committed undervm/native-package-proof/without promoting unrelated audio-backend support claims.Contributor source install with
pnpm installandpnpm check.Backend detection for PipeWire, PulseAudio compatibility, JACK availability, and ALSA playback/capture visibility.
ALSA capability detection now probes both
aplay -landarecord -l, keeps partial playback/capture visibility available for diagnostics, and reports route controls as unavailable instead of planned routing support.PipeWire source and monitor target pickers can list read-only
pw-linkoutput/input ports in the desktop shell.JACK source and monitor target pickers can list read-only
jack_lsp -poutput/input ports in the desktop shell.Dry-run-by-default native PipeWire adapter for linking, verifying, unlinking, and rolling back existing
pw-linkports configured by endpoint host device names.Native PipeWire can now create Loopwire-owned virtual output sinks with
pw-cli create-node adapter, link host-backed source ports into them, and destroy those nodes during unload or rollback.Native PipeWire can now create Loopwire-owned virtual monitor sinks with
pw-cli create-node adapter, link output monitor ports into them, and destroy those nodes during unload or rollback.Native PipeWire route mute now disconnects configured existing links and verification fails if muted links remain connected.
Native PipeWire monitor routing can link output monitor ports to existing physical monitor sink ports.
Dry-run-by-default native JACK adapter for connecting, verifying, disconnecting, and rolling back existing
jack_connectport routes configured by endpoint host device names.Native JACK can resolve app endpoints without host
deviceNamevalues to deterministic Loopwire-owned JACK port names and connect them when those ports already exist.Native JACK route mute now disconnects configured existing connections and verification fails if muted connections remain connected.
Dry-run-by-default PulseAudio compatibility adapter for Loopwire null sinks, matched stream moves, and stream-level volume/mute controls.
PulseAudio compatibility now rejects one-source-to-many-output routes before any host mutation, matching its stream-level control boundary instead of letting the final stream move silently win.
PulseAudio compatibility now ignores muted saved fan-out routes when an active route for the same source exists, so inactive routing ideas can stay in a configuration without blocking the active stream route.
PulseAudio backend detection and support-bundle summaries now expose
one output per sourceas a known gap, matching the runtime and desktop preflight boundary.Support bundles can now include read-only DSP provider plan summaries with
--include-dsp-provider-plan, writingdsp-provider-plan.jsonandsupport-bundle.jsondspProvidermetadata without running provider execute mode.Support bundles can now include read-only JACK provider plan summaries with
--include-jack-provider-plan, writingjack-provider-plan.jsonandsupport-bundle.jsonjackProvidermetadata without running a JACK provider.VM evidence verification now checks the nested support-bundle command ledger, so failed
detect-audio,ct-host-check, orautostart-statusdiagnostics cannot pass as VM support proof.pnpm verify:vmnow validates rendered launch, SSH, and operator runbook handoffs in addition to target metadata and cloud-init, so VM matrix changes must preserve QEMU launch commands, evidence pull commands, port allocation, evidence directories, and runbook entries.PulseAudio compatibility verification now fails when a configured route has no matching live stream, instead of reporting fake success for an absent app stream.
PulseAudio startup and background restore now keep absent matching streams pending until those apps launch, without weakening normal switch verification.
Source-checkout PulseAudio background restore can retry pending app-stream routes for a bounded live window without recreating the virtual sinks.
Release tarballs now package a
loopwire --backgroundlauncher with bundled restore assets underlibexec/loopwire/, and package templates install those support files.The curl installer now reports whether
nodeis available after install, warning raw tarball users before they enable Restore on boot or bundled provider commands without the Node.js runtime.Loopwire-owned monitor sinks and
module-loopbacklinks from output monitor sources to those monitor sinks.Optional monitor host sink names for routing monitor loopbacks directly to physical PulseAudio-compatible sinks.
Desktop monitor cards can list detected PipeWire input ports or PulseAudio-compatible playback sinks for physical monitor targets, with a manual sink-name override for uncommon host setups.
Desktop source picker can list detected PipeWire output ports, JACK output ports, or PulseAudio-compatible running app streams and keeps static fallback sources when backend stream enumeration is unavailable.
Desktop output picker can add detected PipeWire/JACK target ports as host-backed outputs and only auto-route existing host-backed sources into those native targets.
Desktop host-apply control with preview mode and session-local live apply routed through an allowlisted Tauri bridge for
pactl,pw-cli,pw-link,jack_lsp,jack_connect, andjack_disconnect.The Tauri host-command bridge now validates command arguments against Loopwire's detector/runtime contract before running any live audio command.
Desktop startup backend detection through the allowlisted Tauri bridge for
pw-cli,wpctl,pactl,jack_lsp,aplay, andarecord; browser preview keeps packaged fallback candidates.First-run backend selection now prompts when multiple detected backends are available instead of treating PipeWire as an already persisted choice.
The desktop backend chooser now renders a first-run callout that names multiple detected backend candidates, keeps live apply in preview, and asks the user to save the backend for startup restore.
The backend chooser now names the stale saved backend when that backend disappears and multiple other backends are available, so users know they are replacing a previous startup-restore choice.
Desktop backend selection now has a dedicated chooser panel that shows selected, available, and unavailable backends, explains that the choice is persisted for startup restore, and keeps the active workspace ahead of the sidebar on mobile.
Changing the selected backend now runs a backend-change transaction in preview mode, disarms live host apply, and commits the backend as the saved startup-restore choice only after the active configuration verifies.
Backend-change transactions now keep backend, host-apply, and configuration-switch controls disabled while verification is in flight, and stale backend verification results are ignored when a newer selection starts first.
Automatic single-backend selection now uses the same backend-change transaction path before persisting the detected backend for startup restore.
Editing the active configuration now disarms live apply and tells the user to re-arm before verifying the edited routes, endpoints, host bindings, or metadata on the host.
Background restore now tells users to open Settings > Audio backend and save a verified backend when boot restore finds multiple backends or a saved backend is unavailable, instead of failing with a terse backend name.
The desktop Restore on boot card now blocks new enablement when the saved backend is no longer detected, while keeping the selected configuration visible and still allowing an existing restore unit to be disabled.
Background restore now explains how to recover when the persisted state file is missing, unreadable, corrupt, or incompatible: open Loopwire, choose the desired configuration, and enable Restore on boot again.
Configuration switching and startup restore now show a runtime activity ledger with unload, apply, verify, and rollback entries from the actual runtime plan.
Backend route-control semantics report whether controls are graph-edge, stream-level, link-only, or unavailable.
Desktop route-control status, route gain locking, live-apply preflight, and the configuration-switch guard now consume detected backend mixing semantics instead of hardcoded backend names, so graph-edge-capable reports can unlock per-route gain when a live DSP backend exists without a UI/runtime mismatch.
Desktop live apply now keeps persisted DSP provider backends blocked until the desktop has explicit live provider settings, verifies
capabilitiesforsupportsLiveGraph:trueplus the required read/write/verify/clear operations, then uses those settings for provider-backed graph-edge apply, verify, and rollback.Desktop settings now include DSP provider command, mode, timeout, and frame-count fields. Once a live provider command is saved, DSP Provider can be selected for Restore on boot and the desktop writes the matching
--backend dsp --dsp-provider-*flags into the user-scoped systemd unit.The Tauri audio command bridge now passes provider stdin for DSP rendered buffers and allowlists only the bounded DSP provider protocol shapes used by desktop live apply.
Desktop live-apply preflight and the configuration-switch guard now block the selected backend when current backend detection reports it unavailable, so persisted backend choices cannot arm live apply after that audio system disappears.
Desktop status shows degraded route-control behavior for selected backends, and now names native PipeWire/JACK route mute as implemented link disconnect behavior while keeping route gain marked as planned.
Desktop live-apply preflight now lists every blocker when a configuration has multiple issues, instead of showing only the first blocker plus a count.
Refused live configuration switches now copy every preflight blocker into the runtime activity ledger as failed verification evidence, so the failed switch remains actionable after the click.
The docs home page product screenshot now has descriptive alt text instead of being hidden as decoration, keeping the above-the-fold product preview available to assistive technology.
The final release handoff now prints the operator command that sets final-scope GitHub secrets from the filled local env file before the read-only secret audit, without printing or committing secret values.
pnpm release:agent-ready -- --require-docs-deployment-artifactsnow accepts--docs-artifactand--manifest-artifact, so custom Deploy Docs proof artifact names are checked by the same post-Bunny readiness gate that verifies defaultloopwire-docsandloopwire-docs-deploymentartifacts.The Linux desktop binary now disables WebKitGTK's DMABUF renderer before Tauri starts unless the operator already set
WEBKIT_DISABLE_DMABUF_RENDERER, avoiding the Hyprland WaylandMissing acquire timeline/ GDK Error 71 launch crash without forcing X11.Native-backend live-apply preflight now names routes blocked by non-100% gain and provides a
Reset gainsaction that restores affected routes to 100% without touching host audio.The native-backend
Reset gainsremediation is now covered by a pure desktop helper, so PipeWire/JACK reset behavior, muted saved-gain preservation, PulseAudio no-ops, and graph-edge-capable backend no-ops are regression-tested outside the Svelte component.Native-backend non-100% gain blockers now explain both repair paths: reset affected route gains to 100%, or switch to a graph-edge/DSP-capable backend when one is available.
Native PipeWire/JACK live apply now allows muted routes to retain saved non-100% gain values, because those native adapters disconnect muted links/connections instead of applying route gain.
Native PipeWire/JACK route gain sliders now lock when those link-only backends are selected, while route mute and
Reset gainsremain available.Native-backend live-apply preflight now names missing PipeWire source bindings so the next repair is explicit.
Native JACK apply now probes existing deterministic Loopwire-owned port names for app-only route inputs, route outputs, and monitor paths, then fails before
jack_connectwhen those ports are missing.Desktop JACK live-apply preflight now blocks unbound JACK route and monitor endpoints before arming, so missing JACK port bindings are repairable without a failed host mutation attempt.
Native JACK port requirements now come from a shared audio-host helper that exposes the deterministic Loopwire-owned client names and suggested channel ports used by the runtime adapter.
Native JACK runtime failures,
pnpm jack:verify, and support bundles now use the same readiness matcher, including matched and missing ports for each requirement.Native JACK apply can now call an injected JACK virtual port provider for missing Loopwire-owned ports and re-probe
jack_lspbefore connecting. Release artifacts now includeloopwire-jack-ports, a provider wrapper that records the provision plan and fails closed unless delegated to a live JACK client provider.loopwire-jack-portscan now start long-running JACK provider delegates in detached mode for providers whose ports only exist while the provider process stays alive. Loopwire still re-probesjack_lspafter the wrapper returns.Background restore, source/package autostart rendering, and desktop Settings now carry JACK provider delegate mode and readiness delay, so Restore on boot can use detached
loopwire-jack-portsdelegates without hand-editing unit files.Desktop Host apply now uses saved JACK provider settings for native JACK live apply, so Loopwire-owned deterministic ports can be prepared in-session before the runtime re-probes
jack_lspand connects routes.Background restore now accepts
--jack-provider-command, which wraps that command as the injected JACK virtual port provider and passes stableensure --configuration-id ... --requirement ... --port ...arguments.The autostart helper now renders background systemd units with
--state-file,--mode, retry options, and--jack-provider-commandso source-checkout and packaged boot restore use the same runtime contract.Desktop Settings now persists the optional JACK provider command and timeout, then writes those flags into the Restore-on-boot service when JACK is the selected backend.
@loopwire/corenow has a pure DSP mix planner/renderer plus an injected source/output cycle runner that applies per-edge gain and mute to supplied source buffers, including one source routed to multiple outputs, without claiming live host DSP insertion yet.@loopwire/audio-hostnow has an injected DSP graph adapter that dry-runs source/output plans, renders and writes buffers through supplied ports, verifies rendered outputs through a supplied verifier, clears outputs during unload, restores the rollback configuration through the core switch transaction contract, and exposes a first-class configuration runtime adapter wrapper for startup re-apply without touching live PipeWire or JACK state.@loopwire/audio-hostnow also exposes a command-backed DSP provider helper with stableread-source,write-output,verify-output, andclear-outputoperations. Source buffers are read as JSON stdout, and rendered output buffers are sent as JSON stdin for provider write and verify commands.Command-backed DSP verification now fails closed when
verify-outputexits successfully but emits no JSON result, so live provider integrations must explicitly prove rendered output comparison instead of relying on exit code alone.Command-backed DSP provider writes, verifies, and clears are now scoped by configuration id, preventing stale rendered output from one configuration from satisfying another configuration that reuses the same output id.
Background restore now supports explicit
--backend dspwith--dsp-provider-command, and release artifacts now installloopwire-dsp-provider, a bundled file-backed provider for local preflight and restore-contract smoke. It does not yet capture or inject live PipeWire/JACK streams. Live DSP restore now requires--dsp-provider-mode live, and restore now probes providercapabilitiesforsupportsLiveGraph:true, so file-backed preflight cannot be mistaken for a live audio provider.Persisted
selectedBackend: "dsp"state now survives core restore, and source-checkout background restore rejects live DSP startup until an explicit--dsp-provider-commandand live provider mode are supplied after backend resolution.Live DSP provider preflight now also requires the provider
capabilities.operationslist to includeread-source,write-output,verify-output, andclear-output, so restore cannot arm against a provider that cannot verify or roll back Loopwire-owned outputs.pnpm dsp:planandpnpm dsp:verifynow describe and exercise the command-backed DSP provider contract before a user enables provider-backed boot restore.pnpm dsp:verify -- --require-live-capabilitynow probes providercapabilitiesand fails unless the provider declaressupportsLiveGraph:true.pnpm dsp:verifynow clears rendered provider outputs after execute-mode verification and fails if cleanup fails, so live-provider preflight covers the sameclear-outputpath startup restore depends on.pnpm jack:portscan print JACK port requirements from a configuration export or persisted state as JSON or TSV, giving pro-audio users a read-only session-template handoff.pnpm jack:verifycan compare those JACK requirements against livejack_lspoutput or a saved port-list fixture before users arm native JACK live apply.Support bundles can include read-only JACK readiness by passing a Loopwire configuration export or persisted state, writing
jack-port-requirements.jsonand a parsedjackmanifest summary.Desktop live-apply preflight rules are now covered by focused regression tests, including no-backend, ALSA, PulseAudio, native PipeWire, native JACK blocker behavior, and selected-backend capability lookup for the configuration-switch guard.
pnpm verify:desktop-previewcan build the desktop app, start a Vite preview, drive system Chromium through CDP, capture desktop/mobile screenshots, and verify the hidden-monitor recovery tray has no horizontal overflow.Configuration CRUD, source-picker additions, output-bus additions, monitor additions, import/export, persistence migration, and startup re-apply through the app runtime contract.
Desktop configuration switching is now serialized so in-flight switch, create, duplicate, import, and delete actions cannot let stale async runtime results replace the latest selected configuration.
Desktop route lane now creates and removes individual source-to-output edges, while preserving one route per source/output pair and independent per-edge gain/mute state.
Desktop source, output, and monitor cards now support endpoint removal. Source/output removal prunes dependent routes, monitor removal clears hidden-monitor state, and the last output remains protected.
Desktop source, output, and monitor cards now support manual host binding fields for PipeWire/JACK ports or PulseAudio stream tokens that are not listed by backend enumeration; a successful binding edit re-applies the selected device so the host graph tracks the override.
Settings now includes a Transfer section that exports the selected device's versioned configuration JSON (copying it to the clipboard when available) and imports a pasted export as a new selected device, plus a Diagnostics disclosure under Audio Backend listing each backend capability report: availability, mixing scope, per-operation states, and probe diagnostics.
Monitor visibility is now scoped per configuration, so hiding a monitor in one workspace does not hide same-id monitors in other workspaces.
Hidden monitor cards now move into a compact recovery tray with
Showactions instead of staying dimmed in the main monitor grid.The hidden monitor recovery tray now adds
Show allwhen multiple monitors are hidden in the active configuration.Desktop custom chrome now persists as a preference and requests an undecorated Tauri window before showing Loopwire-owned drag, minimize, maximize/restore, and close controls; the chrome setting is now a native-first segmented control with explicit fallback-mode copy.
Desktop chrome now defaults to Auto: Loopwire prefers desktop or window-manager decorations in the desktop shell and shows fallback controls when decoration control is unavailable.
Desktop settings now groups audio backend selection, host-apply arming, window chrome, and restore-on-boot controls in one operational panel instead of scattering persistent preferences across the routing toolbar.
The public docs product screenshot now reflects the Settings panel, so the homepage preview matches the current desktop shell instead of the older topbar-only backend/chrome controls.
Desktop sidebar start-on-boot control for XDG autostart status, enable, and disable, plus CLI helper fallback.
Desktop sidebar restore-on-boot control for a user-scoped systemd unit that runs packaged background restore without opening the GUI.
Desktop restore-on-boot now resolves the packaged
loopwirelauncher fromloopwire-guibefore writing systemd units, and refuses to install a broken GUI-binary--backgroundunit when the launcher is missing.Restore-on-boot status now stays readable when the packaged background launcher is missing or fails
loopwire --background --help, marks the action blocked, and still allows removal of an already-installed user unit.Restore-on-boot now names the active configuration and saved backend in the desktop sidebar before writing the user-scoped background service.
Source-checkout background restore runner reads the Tauri-written state file and verifies the selected configuration through dry-run or explicit live backend adapters.
Local release artifact packaging, checksum signing, installer smoke, AUR package smoke, and VM target metadata validation.
Published-release verification can now run against a local signed release directory in CI and rejects tampered tarballs before the live GitHub Release smoke path is available.
Published-release verification now rejects duplicate
SHA256SUMSentries for canonical Linux tarballs, so a signed manifest cannot contain ambiguous checksums forloopwire-linux-x86_64.tar.gzorloopwire-linux-aarch64.tar.gzwhile still passing install smoke.Release workflow now has x86_64 and AArch64 Linux build lanes, with a single publish job that signs one combined
SHA256SUMSmanifest before creating or updating the GitHub Release.Release workflow manual dispatch now checks out the resolved tag in detached mode before build and publish work, so a manual release cannot package the default branch for a different tag.
Release workflow readiness now keeps tag verification enabled after the detached checkout, so the build lane also checks that the selected tag points at the checked-out source.
Release workflow and readiness checks now reject non-semver or path-like release tags before deriving release-note, evidence-directory, or archive paths from the tag.
Release evidence collection and verification now enforce the same tag rule, rejecting path-like manifest or expected tags before final release evidence can pass.
Release readiness, published-release verification, and release evidence tools now reject repository values that are URLs or extra path segments instead of plain
OWNER/REPO.Release evidence bundles now record the offline release-readiness check and the strict publish preflight log separately, so current external blockers can be attached without failing rehearsal evidence collection.
Release evidence manifests now expose parsed
release.findingsandrelease.blockersfrom the readiness log, plus a log-summary mode for checking preflight blockers without rerunning release checks.Release signing key preparation helper that refuses repo-local private keys and verifies the generated key pair before printing the GitHub secret setup command.
Release signing key preparation now prints the complete final-proof secret setup command, including
--scope final, Bunny upload fields, pull-zone hostname, and matching public/private key paths, plus the no-value env-template alternative.GitHub secret checks now fail with the underlying
gh secret listerror when repository secret names cannot be read, instead of misreporting API or auth failures as missing release/deploy secrets.GitHub secret checks now support
--scope deployfor Bunny.net upload readiness separately from the default strict final-proof scope.The GitHub secret helper now enforces scope-complete inputs before set or dry-run output: deploy scope requires the Bunny.net upload pair, while final scope also requires the pull-zone hostname plus matching release private/public key files before any
gh secret setcall can run.GitHub secret checks and release readiness now accept a names-only
--secret-list-fileartifact, so final-proof secret blockers can be replayed deterministically without a livegh secret listcall or any secret values.The repo now includes
scripts/fixtures/github-secret-list-final.tsv, a names-only final-proof secret-list fixture thatverify:scriptsruns throughsetup-github-secrets.sh --check --scope finalto keep offline release handoff rehearsal value-free and reproducible.New
pnpm release:handoffrenders the no-side-effect release operator plan, including secret checks, workflow dispatch commands, docs deployment proof download, VM evidence collection, VM evidence asset prep, and final-proof dry-run commands.pnpm release:handoffandpnpm release:statuscan now read the local release secret env file for safe handoff fields, while ignoring Bunny storage credentials so access keys do not appear in rendered command plans.pnpm release:handoffnow preserves that env file in the rendered secret-check, docs proof fetch, and VM evidence asset-prep commands, so operators do not have to copy env-derived release key paths into separate flags unless they are intentionally overriding them.pnpm release:handoffnow starts with anOperator-deferred after agent deliverysection and prints the--write-env-template /secure/loopwire-release-secrets.envcommand, separating repo-ready automation from later operator-only secret entry, workflow dispatch, VM execution, and signed evidence upload.New
pnpm release:agent-readyverifies repo-side release readiness and handoff rendering without secrets or GitHub mutations, then reminds operators that strict final proof still requires published release assets, Bunny deployment proof, final-proof workflow success, and VM evidence from operator-controlled hosts.pnpm release:agent-readynow includes the read-only DSP provider graph-edge plan in its default local gates, so release handoff cannot skip the current gain/mute proof surface by accident.pnpm release:agent-ready -- --require-hosted-checksnow filters hosted CI and Deploy Docs workflow lookups by the exact release commit before the operator-deferred ceremony continues, so newer unrelated runs cannot mask the target SHA's proof state.pnpm release:agent-readynow requires a clean checkout by default, keeping the rendered handoff tied to the exact--git-head; local development rehearsals must opt into--allow-dirty.pnpm release:agent-readynow also requires the current checkoutHEADto equal--git-headby default; fixture rehearsals that intentionally use a synthetic SHA must opt into--allow-head-mismatch.pnpm release:agent-ready --helpnow describes hosted checks as commit-scoped, matching the enforced--require-hosted-checksbehavior.pnpm release:agent-ready -- --require-docs-deployment-artifactscan now require the commit-scoped Deploy Docs run to expose both docs proof artifacts (loopwire-docsplusloopwire-docs-deployment) after Bunny deployment secrets are configured.New
pnpm release:fetch-docs-proofdownloads the Deploy Docsloopwire-docsandloopwire-docs-deploymentartifacts, then verifies the non-dry-run manifest against the expected commit beforepnpm release:statusconsumes it.pnpm release:fetch-docs-proofnow stages downloads and manifest verification before replacing local proof paths, so a missing deployment artifact cannot leave partial docs proof behind.pnpm release:fetch-docs-proofnow accepts--env-filefor missing-deployment-artifact recovery hints, preserving the same local secret-file setup path without reading or printing secret values.pnpm release:fetch-docs-proofnow rejects unsafe docs dist, deployment manifest, and env-file paths before it rewrites local proof outputs or renders Bunny secret recovery commands, including traversal, URL syntax, glob syntax, symlinks, and existing paths with the wrong artifact type.New
pnpm release:select-docs-runfinds a completed successful Deploy Docs run for the expected commit that exposes both docs proof artifacts, andpnpm release:handoffnow reuses that selected run id across docs proof fetch, final proof dispatch, and final status instead of asking operators to manually replace a placeholder.pnpm release:statusnow uses the same artifact-aware Deploy Docs run selector when no run id is pinned, so missing manifest recovery and the embedded handoff cannot use a workflow run that lacks the docs proof artifacts.pnpm release:status --docs-deployment-run-idnow verifies that the pinned Deploy Docs run exposes both docs proof artifacts before reusing that id in missing-manifest recovery or the embedded final handoff.pnpm release:handoffnow rejects absolute or parent-traversal VM handoff output paths before rendering VM SSH plan and runbook commands.VM evidence asset preparation now rejects unsafe custom
--release-dirvalues before dry-run or execution, including parent traversal, URL syntax, glob metacharacters, symlinks, and file paths that could redirect checksum regeneration.VM evidence asset preparation now rejects unsafe env-file, private-key, public-key, and evidence-root paths before reading local release artifacts or rendering the signed VM evidence handoff.
Final release proof dry-runs now reject unsafe local
--release-dirvalues before rendering a signed-release proof plan, including traversal, root/home-expanded paths, URL syntax, glob metacharacters, symlinks, and file paths.Final release proof now validates local public-key, release-evidence, docs deployment manifest, VM evidence root, and support-matrix paths before dry-run rendering or execution, rejecting traversal, URL-like values, glob syntax, symlinks, and wrong artifact types before reading proof claims.
pnpm release:statusnow preserves--env-filein its generatedpnpm release:fetch-docs-proofrecovery command when the docs deployment manifest is missing.pnpm release:statusnow rejects unsafe local env-file, secret-list, docs, VM evidence, and support-matrix paths before auditing final proof surfaces, including traversal, root/home-expanded paths, URL syntax, glob metacharacters, symlinks, and wrong existing file/directory types.pnpm release:status --env-filenow keeps the default release public-key path implicit in its embedded VM evidence asset-prep handoff, while still rendering--public-keywhen the operator supplies that override explicitly.pnpm release:statusnow filters CI, Deploy Docs, and Final Release Proof workflow lookups by the expected release commit before final release status can pass, keeping release handoff tied to the same hosted proof surfaces used on pushes and final-proof dispatches.New
pnpm release:statusaudits the remaining final proof surfaces from one read-only command and exits nonzero until GitHub secrets, a non-draft/non-prerelease release with required assets, completed successful workflow runs for the expected commit, a parseable release signing public key, non-dry-run docs deployment manifest proof, VM evidence, and support-matrix proof are present.Release readiness now rejects local or remote release tags that do not point at the current checkout commit, preventing stale tag preflights from looking publishable.
Release readiness now requires a clean git checkout by default, while release evidence collection opts out with
--skip-clean-gitfor its offline readiness command so work-in-progress evidence can still record its source state.Docs deployment now uses a reusable Bunny.net upload helper with dry-run verification, checksum headers, and optional regional storage endpoint support through
BUNNY_STORAGE_ENDPOINT.The docs deployment workflow and GitHub secret helper now pass optional
BUNNY_REMOTE_PREFIXthrough to Bunny.net uploads for storage zones that serve multiple paths.The Bunny.net docs deploy helper can now write a non-secret
loopwire.docs-deployment.v1manifest, and the docs deploy workflow uploads it as theloopwire-docs-deploymentartifact after successful Bunny uploads.New
pnpm verify:docs-deploymentverifies that deployment manifest against the built docs dist before artifact upload, including file inventory, SHA-256 checksums, remote-prefix paths, and secret-like key rejection.Docs deployment manifests now record the source git head, and final release proof rejects manifests that do not match the requested release commit.
Release readiness now fails if the docs deployment manifest verifier is missing, unparsable, absent from
package.json, or not wired into the docs deploy workflow before the manifest artifact upload.Release readiness now fails if the final release proof workflow,
pnpm verify:final-release,pnpm vm:package-evidence, orpnpm vm:prepare-release-evidencewiring disappears before the release handoff.The v0.1.0 release notes are now publication-ready copy, and agent-ready release checks no longer use
--allow-candidate-notes, so candidate wording cannot slip back into the tag handoff.Release evidence collection no longer uses
--allow-candidate-notesfor its offline readiness command, so evidence bundles also fail if versioned notes regress to candidate-only wording.The GitHub secret helper now rejects Bunny storage zones, endpoints, pull-zone hostnames, and remote prefixes that would later fail the docs deploy or live-smoke helpers.
scripts/setup-github-secrets.shnow preserves the exact bytes entered through--env-fileand direct flags instead of stripping wrapping quotes or normalizing Bunny endpoint/prefix values before upload, so operator-reviewed values reach GitHub unchanged.The GitHub secret helper can now validate the release private key against the release public key before dry-run or secret writes, rejecting invalid or mismatched signing material.
The GitHub secret helper now writes secrets through the current
gh secret setstdin contract, avoiding the removed--body-fileflag while keeping secret values out of command arguments and logs.The GitHub secret helper check now prints no-value next steps when required release/docs secrets are missing and explains when the docs workflow can upload to Bunny.net but will skip live-docs smoke.
The GitHub secret helper check now scopes missing-secret next steps to the actual missing class, so a repository that already has
LOOPWIRE_RELEASE_PRIVATE_KEYbut lacks Bunny.net secrets no longer gets release-key reset guidance.The GitHub secret helper check is now split into smaller required-secret, optional-secret, missing-class, and next-step helpers while preserving the same no-value check output.
Release readiness now prints no-value next steps for missing Bunny secrets and missing release tags, including the guarded
git tag -a <tag>andgit push origin <tag>commands only after required secrets are configured.Release readiness and the GitHub secret helper now require
BUNNY_PULL_ZONE_HOSTNAMEfor final proof, because the published release ceremony must prove the live docs deployment and public installer from the Bunny pull-zone URL. The helper can set that hostname by itself when Bunny storage credentials are already configured.scripts/setup-github-secrets.sh --check --scope deploynow has regression coverage for the optionalBUNNY_PULL_ZONE_HOSTNAMEpath, proving deploy-scope checks report post-upload live-smoke readiness without requiring the release signing secret.The Bunny.net docs deploy helper now fails closed when the built dist omits
index.htmlor the publicinstall.sh, and rejects unsafe remote-prefix path segments before upload planning.The docs deployment workflow now runs a live pull-zone smoke with
scripts/verify-docs-live.shwhenBUNNY_PULL_ZONE_HOSTNAMEis configured, verifying the deployed homepage and public installer after upload.The docs deployment live smoke now forwards
BUNNY_REMOTE_PREFIX, so prefixed Bunny.net deployments verify the same path that received the uploaded VitePress site.Published release verification now rejects release directories missing either canonical Linux tarball (
loopwire-linux-x86_64.tar.gzorloopwire-linux-aarch64.tar.gz) before a release can be called installable.Release evidence collection can now include published-release installer smoke as optional full-profile evidence, or require it with
--require-published-releasefor final release proof after GitHub assets exist.Final release evidence verification now rejects fake
published-release-smokerows unless they executedscripts/verify-published-release.shwith the manifest repo, tag, and public key.Final release evidence verification now rejects
published-release-smokerows that include--release-dir, so local staged artifacts cannot satisfy final proof that must come from the GitHub Release surface.Final release evidence verification can now require a specific signing public key with
--public-key, and published-release evidence archive checks pass through the same key used to verify signed release assets.Final release evidence verification can now require the resolved release tag commit with
--git-head, and the release workflow passes that SHA into the evidence verifier and published-release archive verifier.New
pnpm verify:final-releasecommand composes the final public proof gate across signed release assets, live docs, final release evidence, every VM target bundle, support-matrix promotion, and docs verification.The support-matrix verifier can now require installed-release smoke with
--require-published-release, and the final release proof wrapper uses that stricter mode forVerifiedrows.The support-matrix verifier now validates custom
--matrixand--evidence-rootpaths before reading promotion claims, rejecting symlinks, traversal, URL-like values, glob metacharacters, root/home placeholders, and wrong existing file/directory types.Release evidence collection can now require verified VM evidence with
--require-vm-evidence, including guest installed-release smoke when--require-published-releaseis also enabled.Release evidence collection now records a read-only
dsp-provider-planrow in the full profile, and final release proof requires--require-dsp-provider-planso the command-backed DSP provider contract cannot disappear from the public evidence bundle.Final release evidence now binds
dsp-provider-plan.tsvrows to the configured routed sources and outputs, rejecting placeholder DSP provider rows that do not match the manifest-bound configuration.Final release DSP provider evidence now also requires
clear-outputrows for configured outputs, so release proof covers the same rollback/unload operation required by live DSP restore.Final release JACK provider evidence now requires
--require-jack-provider-plan, requiring a read-onlyjack-provider-planrow in release evidence bundles that validatesscripts/describe-jack-ports.mjs --loopwire-owned-onlyoutput without--verifyso published proof covers deterministic Loopwire-owned JACK port requirements without callingjack_lspor executing a provider.Release tarballs, the curl installer, AUR metadata, and Nix metadata now expose
loopwire-dsp-providerbeside the mainloopwirelauncher.Release evidence collection and verification can now require live docs smoke with
--require-live-docs, binding final release evidence to the deployed homepage and public installer.Final live-docs evidence now must match the
docsLivebase URL or hostname plus remote prefix recorded inrelease-evidence.json, so a green smoke against the wrong deployment cannot satisfy final release proof.Release evidence collection can now expand
--vm-target allacross all declared VM matrix targets for final cross-system release proof.Final release evidence can now require
vm-launch-plan.tsv, validating matrix-wide dry-run launch rows and paired SSH evidence-pull commands before public release proof passes.Published-release final evidence now requires the VM launch plan and each paired SSH evidence-pull command to carry the manifest-bound release tag, GitHub repository, release public key, and GitHub-release-source strictness flags.
New
pnpm verify:release-evidencecommand to verify final release evidence bundles, including required published release smoke, all VM targets, non-empty logs, and blocker-free readiness.The release workflow now collects, verifies, attaches
loopwire-release-evidence-<tag>.tar.gzto the GitHub Release, and uploads a matching workflow artifact after the publish smoke passes.The release workflow now re-signs
SHA256SUMSafter evidence collection soloopwire-release-evidence-<tag>.tar.gzis covered by the same signed checksum manifest as the installable tarballs.A manual
Final Release Proofworkflow now downloads release and VM evidence archives from the GitHub Release, checks the tag commit, verifies live docs, and runs the same final proof script used locally.The final release proof workflow now downloads signed
SHA256SUMSfiles and verifies both release and VM evidence archives are checksum-bound before extraction.The final release proof workflow now validates downloaded release and VM evidence tarballs with
scripts/extract-safe-tar.shbefore extraction, rejecting unsafe member paths or link entries before project-specific evidence verification runs.GitHub workflow contract verification now checks that Final Release Proof's VM evidence archive step verifies every manifest-listed target bundle with
--verify-bundles, requires published-release evidence, and exports the verified evidence root into the final proof script.The final release proof workflow now defaults its live-docs hostname and remote prefix from
BUNNY_PULL_ZONE_HOSTNAMEandBUNNY_REMOTE_PREFIX, so the required secret setup feeds the final proof run without retyping the pull-zone hostname on every manual dispatch.The final release proof workflow now validates custom release and VM evidence asset names before download, rejecting path traversal, URL-like names, glob patterns, wrong evidence-kind prefixes, and tag mismatches.
The final release proof workflow and
pnpm verify:final-releasenow pass validated custom evidence asset names into published-release verification and VM evidence dry-run preparation, so final proof does not fall back to default archive names after downloading custom assets.Final release proof dry-runs can now write the exact command plan to a
--plan-outputfile for release handoff review without touching GitHub, Bunny.net, release assets, docs URLs, or VM evidence.Final release proof plan-output files must now stay under
dist/release/, and the verifier rejects absolute paths or./..traversal before writing release handoff artifacts.Final release proof dry-runs now include the
pnpm vm:prepare-release-evidencehandoff, including VM evidence packaging, signedSHA256SUMSrefresh, signed-checksum verification, and the matchinggh release upload --clobbercommand before the manual proof workflow.New
pnpm vm:package-evidencecommand packages verified VM bundles intoloopwire-vm-evidence-<tag>.tar.gzwith thevm-evidence/<target>layout expected by final release proof.pnpm vm:package-evidencenow validates custom output basenames against the tag-bound VM evidence release asset naming contract before writing archives.New
pnpm vm:prepare-release-evidencecommand prepares that VM evidence tarball inside a release directory, regenerates and re-signsSHA256SUMS, verifies the archive entry, and prints the exact GitHub upload command.pnpm vm:prepare-release-evidencecan now read release signing key paths from the local release env file, matching the secret setup and final handoff ceremony while ignoring Bunny storage credentials.VM evidence packaging now validates the completed tarball with
scripts/extract-safe-tar.sh, so unsafe archive members fail before the archive is attached to a public release.VM evidence archive verification can now run
--verify-bundles, so release status, final proof downloads, and the packager smoke reject signed archives whose manifest names missing or invalid VM target bundles.Published release verification can now require that public evidence archive with
--require-release-evidence, extract it, and reject archives with missing published-release smoke, missing read-only DSP/JACK provider proof, or blocker findings.Published release verification now supports
--require-github-release-source, and final release proof passes it so local--release-dirsmoke cannot satisfy public release proof.Published release evidence archive verification now binds the manifest to the expected
release.tagand repo. It rejects unsafe archive paths before extraction, rejects link members withscripts/extract-safe-tar.sh, and rejects manifest command logs that escape the evidence directory or resolve through symlinks.pnpm release:statusnow downloads the publicloopwire-release-evidence-<tag>.tar.gzasset, verifies its signed checksum entry, safe-extracts it, and rejects release-evidence manifests that do not match the selected tag/repo/commit or omit required DSP/JACK provider proof before final proof can be marked ready.pnpm release:statuscan now audit tag-bound release and VM evidence asset override names, and the final handoff forwards the same archive names from final-proof dispatch into the final status audit.pnpm release:statusnow checks those selected evidence archive names in the GitHub Release asset list itself, so valid custom release assets are not blocked by a default-name-only Release object probe.pnpm release:statusnow forwards selected release and VM evidence asset override names into its embedded recovery handoff, so a blocked status audit cannot print default-archive follow-up commands after auditing custom assets.pnpm release:agent-readynow fails if the rendered final release handoff drops the tag-bound release or VM evidence archive names from either final-proof dispatch or the closingrelease:statusaudit.pnpm release:agent-readynow accepts the same tag-bound release and VM evidence asset override names as the handoff, andpnpm release:handoffforwards those names into both initial and post-deploy agent-ready preflights.pnpm release:handoffnow prints the explicit VM evidencegh release upload --clobbercommand and a post-uploadpnpm release:statusaudit before Final Release Proof dispatch, so evidence packaging cannot be mistaken for published release-asset proof.pnpm release:handoff --vm-evidence-asset NAMEnow passes that same selected name intopnpm vm:prepare-release-evidence -- --asset-name NAME, so VM evidence preparation, upload, final proof, and status audit cannot diverge on archive names.pnpm release:statusnow resolves the GitHub tag ref, including annotated tags, and rejects releases whose tag does not point at the expected--git-headcommit.Final release proof now runs the same live GitHub tag-ref check before published-release downloads, so the manual proof workflow rejects a release whose
refs/tags/<tag>no longer resolves to the expected commit.Local release-directory verification now derives the expected evidence tag from the single
loopwire-release-evidence-<tag>.tar.gzasset when--tagis omitted, rejecting archive-name and manifest tag drift.Release evidence verification now validates source-state metadata such as
git.headandgit.statusShort, and final bundles can require a clean checkout with--require-clean-git.Release evidence verification now rejects malformed VM evidence manifest rows, including unknown or duplicate target ids, unsafe
evidenceDirpaths, and VM command rows that do not invoke the matching VM evidence verifier target.Release evidence verification now tokenizes final proof command rows, rejecting echo-disguised published-release, live-docs, or VM evidence commands that only print the expected verifier path.
Product requirement verification now runs in
pnpm check, keeping the v1 UX, backend, Linux integration, docs, and quality checklist tied to source, docs, workflow, and packaging evidence while leaving SHIP proof pending.Redacted support bundle collection for user bug reports and cross-system compatibility triage.
Support bundle manifests now summarize detected backend availability, route-control scope, per-edge gain/mute flags, diagnostics, and known gaps from
detect-audio.json.VM evidence verification now requires a successful guest command ledger and nested redacted support bundle, so support claims cannot rely on file presence alone.
VM evidence collection now starts the Loopwire desktop shell, records
desktop-launch.log, and requires a successfuldesktop-launchledger row before support claims can be promoted.VM evidence verification now rejects tiny placeholder screenshots;
screenshot.pngmust include PNG header dimensions of at least 320x200 before a target can be promoted.VM evidence collection can now run published-release installer smoke inside the guest and
verify-vm-evidencecan require that installed-release proof for final release gates.VM evidence now writes
published-release.json, and final release proof can require the VM bundle to match the exact release tag instead of accepting any successful published-release smoke log.Final VM evidence checks now require
published-release.jsonto record GitHub release source, so guest-visible local release directories cannot satisfy public support evidence for a published tag.VM evidence promotion now has a guarded
pnpm vm:promote-evidencecommand that verifies target evidence before changing a support-matrix row fromManual VMtoVerified.VM evidence promotion can now require published-release smoke, so final public support rows cannot be promoted from source-checkout-only guest evidence.
VM evidence promotion can now run in
--allmode to promote every verified target-scoped evidence bundle while reporting missing targets and failing invalid bundles.New
pnpm vm:evidence-statuscommand reports missing, invalid, and verified evidence bundles across the VM matrix, with optional--require-published-releasestrictness for final public release proof.pnpm vm:evidence-statuscan now take--release-tagwith published-release strictness, so operators can inventory VM proof for the exact release before promoting support-matrix rows.pnpm vm:evidence-statusnow prints target-specific SSH collection ports from the same--start-portconvention aspnpm vm:render-ssh-plan, so multi-VM proof handoffs no longer repeat port2222for every missing target.pnpm release:statusnow uses the same VM evidence start-port default as the final release handoff, and exposes--vm-start-portwhen an operator chooses a different forwarded-port range.pnpm release:statusnow threads the verified commit-scoped Deploy Docs workflow run id into the final release handoff, so the docs proof fetch and final proof dispatch commands no longer fall back to a placeholder after a successful docs run for the release commit.pnpm release:statusnow reuses the already verified Deploy Docs run id when printing missing-manifest recovery, avoiding a second unverified run lookup for the docs proof fetch command.pnpm release:statusnow keeps its fallback missing-manifest docs proof run-id hint scoped to an artifact-bearing Deploy Docs run for the expected release commit, so recovery commands cannot point at a newer unrelated or artifact-incomplete docs workflow run.pnpm release:statuscan now audit a pinned Deploy Docs run with--docs-deployment-run-id, keeping final proof rehearsals tied to the operator-selected docs deployment instead of the commit-scoped workflow lookup.pnpm release:status --vm-evidence-rootnow passes the selected evidence root into support-matrix verification, so promoted support rows are checked against the same copied-back VM evidence bundle path as the matrix status gate.pnpm release:status --vm-evidence-rootnow also forwards the selected VM evidence root into its embedded recovery handoff, keeping VM evidence collection, asset preparation, local final proof, and status re-audits on the same copied-back evidence directory.Pinned Deploy Docs release-status audits now label the evidence as the selected run, avoiding latest-run wording when an operator intentionally audits a specific workflow run id.
scripts/setup-github-secrets.shnow accepts--env-filefor local uncommitted Bunny.net values and release key file paths, with command-line flags taking precedence and dry-run output still hiding secret values.scripts/setup-github-secrets.shnow rejects unsafe local env-file, secret-list, release private-key, and release public-key paths before reading those artifacts during the release secret ceremony.Missing Bunny secret checks now print the
--write-env-template <secret-env-file>and--env-file <secret-env-file>setup route alongside direct placeholder flags, making the safer local-file ceremony visible at the exact release blocker..env.examplenow mirrors every--env-filekey accepted by the GitHub secret helper, so operators have a checked key-name template without committing secret values.The GitHub secret helper can now print the same no-value env-file template with
--print-env-template, keeping the local release-secret ceremony available from the script itself.The GitHub secret helper can now create the local release-secret env template with
--write-env-template, refusing existing files and writing the no-value template with0600permissions.The Deploy Docs workflow now prints the same safe
--write-env-template /secure/loopwire-release-secrets.envand--env-file /secure/loopwire-release-secrets.envrecovery commands when Bunny.net upload secrets are missing, plus theBUNNY_PULL_ZONE_HOSTNAMEreminder needed for final live-docs proof.JACK live port delegation now preserves the process environment while applying Loopwire-specific overrides, so provider scripts that use
/usr/bin/env nodekeep resolving Node on CI and operator hosts.VM evidence collection now writes
environment.json, and verification rejects bundles whose observed distro, desktop/session, or architecture do not match the selected target row.Host-side SSH VM evidence collection can run the guest collector, copy target evidence back, and verify the bundle without changing support-matrix rows prematurely.
Direct SSH VM evidence collection now rejects unsafe custom remote and local output paths before dry-run or execute mode, including parent traversal and paths that omit the target id as a path segment.
Host-side matrix VM evidence collection can expand a TSV guest plan into target-scoped SSH collectors for several reachable systems while staying dry-run-first.
Matrix VM evidence collection now rejects unsafe local output paths, including parent traversal and paths that do not include the target id as a path segment.
Matrix VM evidence collection can now require all
vm/targets.tsvrows with--require-all-targets, failing a final-release collection plan before SSH runs if any target was omitted.VM matrix planning can now generate that target-scoped SSH TSV with unique forwarded ports, so multi-system guest passes do not start from hand-authored rows.
VM host planning now prints cross-distro virtualization setup hints, operator-owned image policy, target-specific render commands, launch dry runs, and SSH evidence handoff commands.
VM host setup now has a dry-run-only
pnpm vm:host-setupcommand that prints one package-family install command and the matching post-installvm:doctorverification command.VM host setup now supports
--all, printing the all-target QEMU tool requirements and the matchingdoctor --allverifier without installing packages.VM host setup hints are now architecture-scoped, so Fedora and openSUSE all-target setup includes the AArch64 QEMU packages required by the Ubuntu AArch64 VM target.
VM launch dry-runs now stay non-mutating: they print the planned QEMU command and
.vm/runpaths without requiring the image path to exist, rendering cloud-init, or writing VM state.New
pnpm vm:launchcommand exposes those dry-run-first QEMU launch plans alongside the rest of the VM matrix workflow.New
pnpm vm:render-launch-plancommand emits target-scoped launch and evidence-pull rows for all VM targets, with deterministic SSH ports and operator-owned image placeholders.New
pnpm vm:render-runbookcommand emits a markdown VM evidence runbook with host setup, launch, SSH evidence, verification, support-matrix promotion, and AArch64 firmware handoffs.The final release handoff now prints
pnpm vm:host-setup -- --allandpnpm vm:doctor -- --allbefore VM SSH planning and evidence collection, so host virtualization readiness is explicit before operator-run guests.VM evidence runbooks now include the final-release
pnpm vm:collect-matrixcommand with published-release smoke and all-target strictness, so operator handoffs do not silently collect source-checkout-only support evidence.VM evidence collectors now forward
--require-github-release-sourcethrough direct guest, SSH, and matrix collection paths, so final support bundles fail early when published-release smoke uses a guest-visible local directory.VM launch now supports
--ssh-portand prints the matching evidence-pull command, so operators can run or plan multiple guest targets without hardcoding host port2222.VM launch planning now rejects invalid memory, CPU count, SSH port, and backing image-format values before printing or executing a QEMU command.
VM evidence collectors now reject invalid SSH and desktop smoke ports before touching SSH, Vite, or guest evidence commands.
VM doctor now treats
cloud-localdsas a required launch preflight, matching the launch path that creates cloud-init seed media only after--execute.VM doctor now supports
--allfor a non-mutating matrix-wide host preflight that printstarget-check=*blocks and exits nonzero when any target's architecture-specific launch prerequisites are missing.VM cloud-init rendering can now generate guest bootstrap assets for every target in one command.
VM matrix verification now renders and checks cloud-init plus guest command handoffs for every target in CI before any operator-run guest evidence is claimed.
VM evidence verification now rejects bundles whose
detect-audio.jsondoes not report the selected target's expected audio backend as available.VM evidence verification now rejects header-only, truncated, or CRC-corrupt
screenshot.pngplaceholders, requiring decodable PNG image data with desktop-sized dimensions before support evidence can be promoted.Debian and Ubuntu VM cloud-init commands now install the pinned pnpm toolchain before workspace validation.
Non-Nix VM cloud-init commands now install Rust and Tauri Linux build prerequisites before running
pnpm check.NixOS VM cloud-init commands now run evidence collection through
nix develop --command.The VM target matrix now includes
opensuse-kde-pipewirewith zypper-based guest bootstrap validation.The VM target matrix now includes an AArch64 Ubuntu target and prints architecture-specific QEMU launch handoffs.
pnpm checknow includespnpm verify:tauri, which runs Tauri Rust formatting, compile checks, and tests.The Nix flake now binds
packages.<system>.loopwire-binto the signedv0.1.0release hashes forx86_64-linuxandaarch64-linux, whilelib.<system>.mkLoopwireBinPackageremains available for future published releases.pnpm nix:render-releasenow renders a concrete Nix package expression from checksum-bound release tarballs and rejects missing or duplicate checksum manifest entries before any Nix publication claim.pnpm verify:nix-releasenow wraps the Nix render step and runsnix buildon Nix-enabled hosts, with an explicit skip flag reserved for non-Nix wiring checks.pnpm verify:nix-releasecan now download signed assets from--repo OWNER/REPO --tag vX.Y.Z, so final release proof can verify the Nix package from the published GitHub Release instead of a local staging directory.Release evidence collection and verification now support
--require-nix-release, rejecting render-only or skipped Nix proof rows when a release evidence bundle claims package-manager evidence.pnpm verify:final-releasenow includes a direct Nix release package proof step before accepting final release evidence, VM evidence, support-matrix, and docs proof.The final release proof workflow now installs Determinate Nix with a pinned
DeterminateSystems/determinate-nix-action@v3.21.2step before running package proof, so the GitHub runner can execute the non-skipped Nix build gate.The final release proof workflow now passes the GitHub Actions token into the composed proof step, and release readiness fails if that token wiring disappears before the workflow downloads release assets.
The final release proof workflow contract now fails if the composed proof step reintroduces
--release-dir, keeping final proof tied to downloaded GitHub Release assets instead of local staging directories.Release readiness and workflow contract checks now require
scripts/verify-final-release-proof.shto invoke the shared release tag-ref verifier, so final proof cannot silently drift away from the live tag binding gate.pnpm verify:final-releasenow requires the current checkoutHEADto match--git-headby default; offline fixture rehearsals must opt in with--allow-head-mismatch.The final release handoff now prints an exact-commit
pnpm release:agent-ready -- --require-hosted-checkspreflight before secret checks, tagging, workflow dispatch, VM evidence, or final proof steps.The final release handoff now also prints a post-deploy
pnpm release:agent-ready -- --require-docs-deployment-artifacts --skip-local-gatescheck after docs proof fetch, so operators re-run the same release-ready surface once Bunny deployment artifacts exist.The final release handoff now ends with
pnpm release:status, so operators finish publication with the same read-only aggregate audit that checks GitHub Release assets, docs deployment proof, final-proof workflow status, VM evidence, and support-matrix claims.Final Release Proof workflow runs now include the audited tag and commit in their visible run name, and
pnpm release:statusrejects commit-scoped final-proof runs whose title does not match the selected release tag.The final release handoff now prints that expected Final Release Proof run name immediately after the dispatch command, so operators can match the workflow run that
pnpm release:statuswill accept.pnpm release:statusnow stops published release evidence and VM evidence archive checks at the missing download failure, avoiding follow-on checksum, extraction, and manifest errors for absent release assets.The final release proof workflow now requires a docs deployment run id, downloads that run's
loopwire-docs-deploymentartifact, rebuilds docs from the release commit, and verifiesdeployment-manifest.jsonbefore accepting the live docs smoke.Final proof and
pnpm release:fetch-docs-proofnow verify the selected Deploy Docs run completed successfully for the expected commit before downloading docs deployment artifacts.The docs site now carries a VitePress public installer asset at
/install.shthat is verified byte-for-byte against the canonicalscripts/install.sh.The release installer now rejects signed tarballs with unsafe absolute or parent-traversing archive paths before extraction.
Release readiness now fails if the public docs installer drifts from
scripts/install.sh, and the Bunny deploy dry-run contract provesinstall.shwould be uploaded.Release readiness now validates custom public-key and saved secret-list artifacts before reads, rejecting symlinks, traversal, URL-like values, glob metacharacters, root/home placeholders, and existing non-file paths.
Release evidence collection now validates
--output-dirand summarized readiness-log paths before reading or writing artifacts, rejecting symlinks, traversal, URL-like values, glob metacharacters, root/home placeholders, and wrong existing file/directory types.Final release handoffs now print the reviewed annotated tag creation command and exact
refs/tags/<tag>push before workflow dispatch, so the operator ceremony has no implicit tag step.
Known Limitations
- No public signed release artifact exists yet.
packaging/release-signing-public.pemnow contains the project release public key, and the live repository has the matchingLOOPWIRE_RELEASE_PRIVATE_KEYsecret; Bunny deployment secrets and tagged release proof are still required before publishing.- Bundled native JACK client creation and true per-edge gain remain planned. App-only JACK routes and monitors still require a separate JACK client or
loopwire-jack-portsdelegate to create the expected Loopwire-owned ports before live apply. - Live host apply needs Tauri desktop runtime; browser preview fails closed without host mutation.
- Packaged background restore uses the bundled JavaScript restore engine and currently requires
nodeonPATH. - VM host planning and cloud-init rendering do not launch guests, download distro images, or promote support-matrix rows without operator-captured evidence.
- VM desktop launch smoke proves the Loopwire shell responds locally; screenshot commands still need operator care to capture the intended desktop surface in each guest.
- Public AArch64 release proof still requires a tagged workflow run and published
loopwire-linux-aarch64.tar.gzasset. - Nix flake package wiring exists, but non-skipped
pnpm verify:nix-releaseproof must come from a Nix-enabled host or VM target after real release hashes exist; render-only and missing-Nix modes remain wiring checks only.
Verification To Keep Current
pnpm checkpnpm detect:audiopnpm verify:docspnpm verify:vmpnpm verify:tauripnpm e2e:ui(host-dependent manual validation; see the developer e2e guide)