Work in progress: msix installer#732
Conversation
|
Codex review: found issues before merge. Reviewed June 12, 2026, 4:11 PM ET / 20:11 UTC. Summary Reproducibility: not applicable. as a bug reproduction; this is a distribution architecture change, although its install, upgrade, update, recovery, and uninstall behavior is concretely testable and currently unproven. Review metrics: 3 noteworthy metrics.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Remove every rehearsal override, restore durable feeds and strict production release gates, implement an explicit Inno-to-MSIX migration and uninstall-cleanup experience, and demonstrate the full lifecycle on real Windows systems before merge. Do we have a high-confidence way to reproduce the issue? Not applicable as a bug reproduction; this is a distribution architecture change, although its install, upgrade, update, recovery, and uninstall behavior is concretely testable and currently unproven. Is this the best way to solve the issue? No, not in its current form; MSIX is a plausible direction, but a rehearsal-configured branch without upgrade and uninstall parity is not a safe permanent replacement. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against ea36b12f9e4c. Label changesLabel justifications:
Evidence reviewedSecurity concerns:
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
3559f81 to
4b0d617
Compare
Master shipped sizes 24/32/48/256; Windows down-scaled larger PNGs for
Start Menu / taskbar / Alt+Tab surfaces that prefer 16/20/44. These three
PNGs fill the gap and are auto-discovered by MakePri via the existing
Assets\**\* content include and the targetsize-NN_altform-unplated
filename convention. No code, csproj, or manifest changes required.
Cherry-picked from origin/pr-468 (Square44x44Logo.targetsize-{16,20,44}_altform-unplated.png).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the conditional dispatch that produced an unpackaged WindowsPackageType=None + app.manifest build for the Inno installer path. Default packaging mode is now unconditionally MSIX; only the PackageMsix=true opt-in for .msix file production remains. Changes: - Make <WindowsPackageType>MSIX</WindowsPackageType> + <WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained> unconditional. - Delete the <PropertyGroup Condition=\'$(Unpackaged)' == 'true'\> block (WindowsPackageType=None + ApplicationManifest=app.manifest). - Delete the CopyWebView2Loader target (only needed for the unpackaged layout; MSIX bundles the loader automatically). The unrelated CopyWebView2Loader target in OpenClaw.SetupPreview is untouched. - Rewrite the explanatory comment block to drop the Unpackaged mode paragraph (now describes one opt-in flag instead of two). src/OpenClaw.Tray.WinUI/app.manifest is now orphaned but left in place; Phase 3 will delete it together with the Inno installer. Callers that still pass -p:Unpackaged=true (scripts/build-inno-local.ps1 and the Inno publish job in .github/workflows/ci.yml) are transiently non-functional between Phase 2 and Phase 3 — the property becomes a no-op so the build emits an MSIX layout that Inno cannot consume. Both callers are deleted in Phase 3, per the all-phases-land-together branch workflow. Audit of App.xaml.cs:355-405 _isPostSetupRestart retry: KEEP. The branch is not Inno-specific. The tray itself spawns a fresh tray with --post-setup-restart --wait-for-pid <oldPid> after in-process SetupWindow completes (RestartAfterSetupAsync, line 3097). The 15s retry + AbandonedMutexException handler prevents the new tray from giving up on the single-instance mutex while the old tray is still exiting. AppRefactorContractTests:135-140 enforces the call pattern. Validation (per AGENTS.md): - build.ps1: all 5 projects built. - Shared.Tests: 2049 passed, 29 skipped (env-only), 0 failed. - Tray.Tests: 958 passed, 0 skipped, 0 failed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Delete Inno Setup distribution path now that MSIX is the always-on package type. Phase 3B will follow up with Updatum removal; Phase 4 will rebuild the release pipeline around the .msix file produced by `-p:PackageMsix=true`. Deleted files (5 source + 2 test): - installer.iss (256 lines) - scripts/build-inno-local.ps1 - scripts/Uninstall-LocalGateway.ps1 - src/OpenClaw.Tray.WinUI/app.manifest (orphaned by Phase 2) - tests/PackagingTests/Test-InnoUninstallOrdering.ps1 (parent dir removed) - tests/OpenClaw.Tray.Tests/InstallerIssAssertionTests.cs (9 tests) - tests/OpenClaw.Tray.Tests/ReleaseSigningWorkflowTests.cs (4 tests; Phase 5 will replace with MSIX-signing assertions) ci.yml: drop -p:Unpackaged=true from build/publish (Phase 2 cleanup), retire the Download VC Redist + Install Inno Setup + Build x64/arm64 Installer + Sign Installers steps in the release job, remove .exe entries from the release files: list and body, and update the paused build-msix comment. App.xaml.cs: remove the AppMutex coordination comment that referenced installer.iss; the OpenClawTray mutex itself stays unchanged. SetupEngine.UI/LogFileLauncher.cs: rewrite the "Unpackaged process" comment to cover both the no-package-identity and library-only call sites. Ship-guard ported from installer.iss to MSBuild: two new targets on OpenClaw.Tray.WinUI.csproj (ValidateSetupEngineUiNotShipped after Build, ValidateSetupEngineUiNotPublished after Publish) fail the build if OpenClaw.SetupEngine.UI.exe lands in the tray bin/publish output. Pairs with a new "Hazards" section in docs/SETUP_ENGINE_REDESIGN.md explaining the in-process design and pointing at PR #468's bootstrapper diffs as the worked example anyone splitting SetupEngine into its own process would need to study first. Test-ReleaseNativeDependencies.ps1: remove -RequireInstallerVCRedist / -InstallerVCRedistPath params and their dead handler (only Inno called them); -RequireAppLocalVCRuntime and -SkipNativeLoadProbe stay (still used by ci.yml's Verify Native Runtime Payload steps). Docs: drop the Inno helper section + .exe-installer references from DEVELOPMENT.md, docs/RELEASING.md, docs/VERSIONING.md, and the Inno comment in scripts/validate-msix-storage-paths.ps1. README.md + docs/SETUP.md download tables are replaced with TODO placeholders that Phase 7 will fill with MSIX-flavored content. Validation (on user/kmahone/msix, Windows): - ./build.ps1 green - Shared.Tests: 2049 passed / 29 skipped (unchanged from Phase 2) - Tray.Tests: 945 passed (was 958; -13 = 9 InstallerIssAssertion + 4 ReleaseSigningWorkflow tests removed, as expected) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Updatum becomes dead under MSIX-primary publishing once <AutomaticBackgroundTask /> in the .appinstaller XML (Phase 4) is the update mechanism. No in-app updater under MSIX, no manual "Check for updates" button. Removed: - Updatum NuGet PackageReference from OpenClaw.Tray.WinUI.csproj - App.xaml.cs: using Updatum, AppUpdater static field, BuildInitialUpdateInfo call, startup update-check gate, IAppCommands.CheckForUpdates impl, dispatcher case "checkupdates", HandleDeepLink wiring, and the entire #region Updates block (~460 lines). - IAppCommands.CheckForUpdates declaration. - DeepLinkHandler.cs: case "updates"/"update"/"check-updates"/"update-check" block + CheckForUpdates Func field. - AboutPage.xaml CheckUpdatesButton + AboutPage.xaml.cs OnCheckUpdatesClick. - HubWindow.xaml.cs orphan CheckForUpdatesAction property. - SettingsData.SkippedUpdateTag + 4 SettingsManager references. - Dialogs/UpdateDialog.cs (deleted file). - Dialogs/DownloadProgressDialog.cs (deleted file). - Update*, CheckUpdates*, DownloadProgress* resource keys from all 5 locale resw files (en-us, zh-tw, zh-cn, nl-nl, fr-fr; 18 keys per file). - ci.yml: Updatum auto-update ZIP comment + x64/arm64 "Create Release ZIP" steps + ZIP entries from release files: + Portable bullets from release body. Release will have no binary artifacts until Phase 4 MSIX pipeline. - Test fixtures: SettingsRoundTrip (4 SkippedUpdateTag refs), DeepLinkParser (2 InlineData rows + fixture init), TrayMenuWindowMarkup (2 Assert.Contains), AppRefactorContract (CheckForUpdatesAsync from AssertInOrder), LocalizationValidation (WindowTitle_Update + Update_OK invariants). - Docs: README.md + docs/SETUP.md (openclaw://check-updates row); docs/RELEASING.md (Portable ZIP Updatum block); docs/VERSIONING.md (Updatum Library reference). Kept: - UpdateCommandCenterInfo DTO in OpenClaw.Shared/Models.cs - public protocol type sent to external agent clients; default-initialized (Status="Unknown", CurrentVersion=null). AppStateSnapshot.LastUpdateInfo wiring stays. Validation: - ./build.ps1 green - Shared.Tests: 2049 passed, 29 skipped (unchanged) - Tray.Tests: 943 passed (was 945; -2 = DeepLinkParserTests InlineData rows) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Symptom (caught while smoke-testing the MSIX-primary build): asking the agent to show a Windows notification throws InvalidOperationException: Your app manifest must have a toastNotificationActivation extension with a valid ToastActivatorCLSID specified. at ToastNotificationManagerCompat.CreateToastNotifier() at ToastContentBuilder.Show() at ToastService.ShowToast(...) Root cause: Microsoft.Toolkit.Uwp.Notifications (which we still use for all toasts via App.OnToastActivated + interactive AddButton flows) has two code paths -- an unpackaged shortcut/COM-self-registration path and a packaged path that reads ToastActivatorCLSID from the appx manifest. Phase 2 of the MSIX-primary branch dropped -p:Unpackaged=true, so we now always hit the packaged path. With no manifest extension declared, the toolkit cannot find a CLSID and throws on first ShowToast call. Fix: declare a stable CLSID for the toast activator in the manifest: - Add desktop:Extension Category="windows.toastNotificationActivation" with ToastActivatorCLSID="EF9297B3-EEEB-4E50-8306-D1D118E04BC7". - Add the matching com:Extension/com:ComServer/com:ExeServer entry so the COM server is wired to OpenClaw.Tray.WinUI.exe with the conventional -ToastActivated arg. - Declare the desktop + com namespaces and include them in IgnorableNamespaces. The CommunityToolkit generates the actual activator type at runtime and binds it to this CLSID; no extra C# is needed. App.ToastActivation.cs already wires ToastNotificationManagerCompat.OnActivated to OnToastActivated and parses arguments via ToastArguments.Parse, so the button-click roundtrip works as soon as the CLSID is reachable. Validation: - ./build.ps1 green (manifest passes MakeAppx schema check). - Tray.Tests still pass (no source changes; manifest-only edit). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Previously the precheck only warned and the post-build summary suggested `Add-AppxPackage -AllowUnsigned`. That command does not work for this MSIX package on stock Windows (AllowUnsigned only applies to a narrow set of developer-mode scenarios), so users following the suggestion would fail at install time. Now: missing cert => Write-Error + exit 1 in the preflight, with a clear message pointing at scripts\setup-dev-msix-cert.ps1. The post-build install hint always shows the signed Add-AppxPackage form (the unsigned branch is now unreachable). Docstring updated. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… workflow Adopts the publishing-infrastructure pattern from PR #468 (treated as a reference design only, not cherry-picked) and adapts it to our WindowsAppSDKSelfContained=true MSIX. Because the WindowsAppRuntime is bundled inside the .msix, the AppInstaller feed has no <Dependencies> block, no runtime-URI rendering, and no separate runtime MSIX release asset. What this commit adds - installer/openclaw-companion.appinstaller.template — 6 placeholders (VERSION, PUBLISHER, IDENTITY_NAME, PROCESSOR_ARCHITECTURE, MSIX_URI, APPINSTALLER_URI), AutomaticBackgroundTask-only UpdateSettings. - installer/appinstaller/openclaw-{x64,arm64}.appinstaller — bootstrap feed files at version 0.0.0.0; the appinstaller-feed-pr workflow rewrites these on each stable release tag. - installer/appinstaller/README.md — explains the stable-feed model. - scripts/render-appinstaller.ps1 — substitutes placeholders, asserts the rendered XML parses and contains no <Dependencies> block. - scripts/validate-appinstaller-hosting.ps1 — Content-Type / Content- Length / Range checks against the hosted .appinstaller and .msix URLs, with -AllowGitHubContentTypes for raw.githubusercontent.com. - scripts/test-appinstaller-update.ps1 — local HttpListener-backed vN -> vN+1 upgrade smoke using PackageManager .AddPackageByAppInstallerFileAsync. - .github/workflows/appinstaller-feed-pr.yml — workflow_dispatch input takes a release tag, renders the two feed files, validates them, and opens a PR to advance the stable feed. Uses OpenClaw Foundation publisher; rejects pre-release tags; here-string PR body uses Set-Content -Value so the body renders as Markdown (fixes the 8-space-indent code-block bug in PR #468's workflow). - tests/OpenClaw.Tray.Tests/AppInstallerTemplateAssertionTests.cs — 8 test methods covering template shape, the new Template_HasNoDependenciesBlock invariant, the two bootstrap feed files, the validation script, the smoke script, and the feed-update workflow. - README.md — replaces the Phase-7 TODO placeholder with x64 and ARM64 Install links pointing at the raw GitHub .appinstaller URLs. What this commit does NOT add - No in-app "Check for updates" button or AppInstallerUpdateService. Windows AppInstaller's AutomaticBackgroundTask handles all polling at OS level under MSIX. - No Microsoft.WindowsAppRuntime.2 release asset or feed dependency — the runtime is bundled (WindowsAppSDKSelfContained=true). Validation - ./build.ps1: green. - Shared.Tests: 2049 passed / 29 skipped (matches baseline). - Tray.Tests: 957 passed (was 943; +14 effective test cases from the new file). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The Phase 4 appinstaller feed workflow expected release assets named
'OpenClawCompanion-<3partVersion>-win-<arch>.msix', which would have required a
rename step in the Phase 5 release job (Option A). Switching to Option B:
match whatever MSBuild emits by default for GenerateAppxPackageOnBuild=true,
i.e. 'OpenClaw.Companion_<4partVersion>_<arch>.msix'.
* appinstaller-feed-pr.yml: Get-RequiredAsset patterns updated to use the
4-part $version (not the 3-part $versionText), dotted identity, and
underscore separators. Uses ${version} to keep _ from being absorbed
into the variable name.
* AppInstallerTemplateAssertionTests: matching Assert.Contains /
Assert.DoesNotContain updates so the pin reflects the new convention.
Inside the rendered .appinstaller, <MainPackage Uri> uses the actual
GitHub release asset name, so AppInstaller behavior is unaffected.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Unpause the build-msix matrix job and wire its outputs into the release
job so that tagged builds produce signed .msix artifacts attached to the
GitHub Release.
- ci.yml build-msix: drop `if: false` paused gate and
`continue-on-error: true` placeholder; the job is now load-bearing.
- ci.yml release: add `build-msix` to `needs:` plus matching
`needs.build-msix.result == 'success'` guard.
- Download the per-arch `openclaw-msix-win-{x64,arm64}` artifacts.
- Sign each .msix in place using `azure/artifact-signing-action@v2`
with `files-folder-filter: msix` (mirrors the existing exe signing
pattern: same endpoint, signing account, certificate profile, OIDC
auth via azure/login).
- Attach both signed .msix files to the release via `files:` and
rewrite the release body so it points users at the AppInstaller links
in the README (primary install path) and notes the .msix assets as a
direct-install fallback.
Validation:
- ./build.ps1 green
- Shared.Tests: 2049 passed / 29 skipped (baseline)
- Tray.Tests: 957 passed (baseline)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
After Phase 3A removed Inno and Phase 5 wired the MSIX into the release,
the `build` job's loose unpackaged-tray artifact ceased to be shipped
to any user. The release job was still downloading it, signing the
loose exe, and running signature/native-dep validation against bits
that were then discarded. This commit removes that dead infrastructure
and preserves the most valuable validation against what we actually
ship.
ci.yml changes:
- Delete the `build` job in its entirety (loose `dotnet publish`,
Test-ReleaseNativeDependencies on publish/, GitVersion verify,
Upload Tray Artifact -> openclaw-tray-{rid}).
- Drop `build` from `release.needs:` and from the corresponding
`needs.build.result == 'success'` guard.
- In `release`, remove: 2 tray-artifact download steps, 2 stage exe
for signing steps, 2 sign-loose-exe steps, and 4 verify steps
(Test-ReleaseExecutableSignatures and Test-ReleaseNativeDependencies
against artifacts/tray-win-*).
- In `build-msix`, add a new `Verify MSIX Package Contents` step
that runs immediately after the .msix is produced. It extracts the
.msix (a zip), confirms `OpenClaw.Tray.WinUI.dll` is present with
the correct GitVersion ProductVersion, and runs the existing
Test-ReleaseNativeDependencies.ps1 against the extracted payload so
the libsodium / VC++ runtime presence canary continues to fire --
but now against the actual shipped MSIX bits, not a phantom
unpackaged build.
Net diff: -108 lines from ci.yml; pipeline shape simplified from
six jobs to five (release no longer depends on a parallel build job
whose output it never used).
Validation:
- ./build.ps1 green
- Shared.Tests: 2049 passed / 29 skipped (baseline)
- Tray.Tests: 957 passed (baseline)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Phase 4 AppInstaller infrastructure was authored against master but the default branch was renamed to main (commit 37b0ea6). The stale refs would cause silent failure: AppInstaller polling would forever fetch frozen XML from the now-inactive origin/master branch, and the feed-update PR workflow would target a branch that doesn't accept commits. Fixed: - installer/appinstaller/openclaw-{x64,arm64}.appinstaller: <AppInstaller Uri> -> main - installer/appinstaller/README.md: hosting URLs + prose -> main - README.md: end-user install links -> main - .github/workflows/appinstaller-feed-pr.yml: ref/raw URL/PR --base -> main - scripts/render-appinstaller.ps1: docstring URLs -> main - scripts/validate-appinstaller-hosting.ps1: docstring -> main - tests/OpenClaw.Tray.Tests/AppInstallerTemplateAssertionTests.cs: assertions tracking the above Also swept pre-existing master refs that the rename PR (37b0ea6) missed: - docs/RELEASING.md, docs/VERSIONING.md: prerelease prose - tests/.../LocalizationValidationTests.cs: comment - src/.../ConnectionPage.xaml.cs: comment Left alone (per main's rename PR intent): dual [main, master] CI triggers, GitVersion ^(master|main)$ regex, third-party URLs, and all 'Master switch/toggle/control' UX terminology (unrelated to git branch). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
build-msix invokes VS MSBuild without first running GitVersion, so the GitVersion.MsBuild package can't compute version metadata and the WinUI .dll inside the MSIX falls back to AssemblyVersion 1.0.0. The Verify MSIX Package Contents step then correctly fails: MSIX-internal ProductVersion '1.0.0' did not match GitVersion SemVer '0.6.4-PullRequest732.54'. Mirror the gitversion/setup + gitversion/execute steps from the test job before Build MSIX Package. The execute action exports GitVersion_* environment variables that GitVersion.MsBuild picks up to inject Assembly/File/InformationalVersion, satisfying the verify assertion. fetch-depth: 0 is already set on the checkout, so GitVersion can read git history. The existing manifest-patch step (which sets Appx package identity version) is unaffected. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t PR iteration
build-msix only consumed needs.test.outputs.{semVer,majorMinorPatch}, which are now produced locally by the gitversion/execute step inside the job. e2etests was a pure gate (no outputs).
Swap manifest-patch + verify references from needs.test.outputs.* to steps.gitversion.outputs.*, then drop the needs:[] list so build-msix starts in parallel with test/e2etests on every push.
REVERT before merge — release job still gates on all four (line 491), so production releases are unaffected by this temporary change; the only effect is faster PR feedback. Restore 'needs: [test, e2etests]' on build-msix and switch the two version refs back to needs.test.outputs.*.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…X payload Test-ReleaseNativeDependencies.ps1 -RequireAppLocalVCRuntime fails after the MSIX-payload extract because vcruntime140.dll is missing next to libsodium.dll: Missing app-local vcruntime140.dll next to libsodium.dll. Root cause: the CopyOpenClawVCRuntime* targets in src/Directory.Build.targets only ship a current VS-resolved runtime via CopyOpenClawVCRuntimeToPublish (AfterTargets=Publish). The pre-fix CI step ran 'msbuild /t:Build', which only triggers CopyOpenClawVCRuntimeToOutput - x64-only AND sourced from the stale 14.29 NuGet that the comment explicitly warns is too old for onnxruntime >= 1.20. Worse, the WinUI single-project AppX packaging task collects payload from publish output, not from the build TargetDir, so even the stale copies wouldn't end up inside the MSIX. Switching to 'dotnet publish ... -p:PackageMsix=true' matches what build.ps1 does locally and what produces working MSIX packages on dev machines. publish triggers CopyOpenClawVCRuntimeToPublish (VS-install resolution -> current 14.40+ DLLs) and ValidateOpenClawVCRuntimePublished, which guarantees vcruntime140.dll lands in PublishDir before the AppX packager collects payload. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…a is invalid" on install The 2018 schema can choke on validators in newer Windows AppInstaller builds. Switching to the 2021 namespace makes Windows use the newer parser, which accepts the same element set we already use (MainPackage, OnLaunch, AutomaticBackgroundTask). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…feed install issues Local-file install of the standalone openclaw-msixtest-x64.appinstaller fails with LogHr 8007000D on the second-pass parse after AppInstaller refetches from raw.githubusercontent.com. Two underlying gaps in the external-feed approach we discovered: 1. raw.githubusercontent.com serves .appinstaller as text/plain instead of application/appinstaller. AppInstaller's strict parser rejects the redirected fetch. 2. ms-appinstaller://?source= protocol has been disabled by default on consumer devices since December 2023. Docs: https://learn.microsoft.com/en-us/windows/msix/app-installer/installing-windows10-apps-web https://learn.microsoft.com/en-us/windows/msix/app-installer/how-to-embed-an-appinstaller-file Embedded approach sidesteps both: ship openclaw-update.appinstaller inside the MSIX payload, reference it from the manifest's <uap13:AutoUpdate><uap13:AppInstaller File='...' />. Install path becomes 'download MSIX, double-click' - the .appinstaller is parsed locally from the extracted payload, no HTTP fetch, no MIME issue. Windows registers the embedded file's <AppInstaller Uri> as the canonical update-poll endpoint for the background update task. Changes: - src/OpenClaw.Tray.WinUI/Package.appxmanifest: add xmlns:uap13, add uap13 to IgnorableNamespaces, add <uap13:AutoUpdate><uap13:AppInstaller File='openclaw-update.appinstaller' /></uap13:AutoUpdate> in <Properties>. - src/OpenClaw.Tray.WinUI/openclaw-update.appinstaller: new file, identical content to the on-disk installer/appinstaller/openclaw-msixtest-x64.appinstaller for the rehearsal (pinned to v0.6.4-msixtest.3 release, 0.6.4.0). - src/OpenClaw.Tray.WinUI/OpenClaw.Tray.WinUI.csproj: add <Content Include='openclaw-update.appinstaller'> so the file ships in the MSIX payload. Local validation: - dotnet publish -p:PackageMsix=true succeeds. - MSIX payload contains openclaw-update.appinstaller (1270 bytes). - AppxManifest.xml carries the uap13:AutoUpdate Properties block. - Add-AppxPackage installed OpenClaw.Companion 0.6.4.0 in 406 ms with no schema errors - <uap13:AutoUpdate> accepted by the Windows AppX deployment engine. Still TEMP-tracked for revert before merge: revert-embedded-appinstaller-manifest revert-embedded-appinstaller-content ... plus the earlier msixtest reverts. Not yet known: whether the background update poll (after install) hits the same raw.githubusercontent.com MIME issue as the install-time parse. That's the next thing to test once a higher-version MSIX is published. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ate rehearsal Phase 2 of the embedded-AppInstaller rehearsal. With v0.6.4-msixtest.4 installed, bump both feed copies to 0.6.5.0 pointing at the next test release. Order matters - push feed bump first so raw.githubusercontent.com is already serving the bumped XML by the time CI publishes the new MSIX release; otherwise the OnLaunch poll would see the new XML and 404 on MainPackage Uri. - installer/appinstaller/openclaw-msixtest-x64.appinstaller: what raw.githubusercontent.com serves to the update poller. This is the URL Windows registered at install time via the embedded copy. - src/OpenClaw.Tray.WinUI/openclaw-update.appinstaller: kept in lockstep for consistency; only affects future installs (existing installs read Uri once at install time, then poll that URL forever). Next: push tag v0.6.5-msixtest.1 to produce the matching release. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…alse Phase 3 of the embedded-AppInstaller rehearsal: test non-blocking update behavior. ShowPrompt stays true (per user preference) so the update dialog still surfaces; UpdateBlocksActivation=false means the app launches immediately with the OLD version while the update stages in the background. Quit and relaunch applies the new version. The currently-installed 0.6.5.0 has embedded UpdateBlocksActivation=true, so it will use blocking behavior to install 0.6.6.0 (one more time). 0.6.6.0 has the new non-blocking settings embedded. A subsequent bump (Phase 4: 0.6.7-msixtest.1) is then needed to exercise the non-blocking path from 0.6.6 to 0.6.7. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… source files
Commit 1 of the three-channel embedded-AppInstaller production rollout. Pure additions; no behavior changes yet.
Four new committed XML files in installer/appinstaller/:
- openclaw-alpha-x64.appinstaller, openclaw-alpha-arm64.appinstaller
Polled-feed bootstrap files for the Alpha channel, mirroring the existing
Stable bootstrap pattern (openclaw-{x64,arm64}.appinstaller). Version=0.0.0.0
placeholders; bumped by the operator-driven feed-bump workflow after each
Alpha release.
- openclaw-update.stable.appinstaller, openclaw-update.alpha.appinstaller
Source files for the AppInstaller content shipped INSIDE each MSIX as
openclaw-update.appinstaller (referenced from Package.appxmanifest's
<uap13:AppInstaller File='...'/>). Hardcoded channel-specific identity +
polled-feed URL; {{VERSION}}, {{ARCH}}, {{MAIN_PACKAGE_URI}} placeholders
patched by MSBuild XmlPoke at build time in Commit 2. <OnLaunch> settings
pinned to ShowPrompt=true / UpdateBlocksActivation=false / 24h interval
per the locked-in design.
See three-channel-msix-plan.md (session state) for the full design.
Nothing in the build pipeline references these files yet; that wiring lands in
Commit 2 alongside the csproj XmlPoke target and the manifest cleanup.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Hi! Looks like this PR would also make the Companion app eligible for the Windows 11 Copilot hardware key. Would you consider adding the corresponding extension to the According to the Microsoft docs (https://learn.microsoft.com/en-us/windows/apps/develop/windows-integration/microsoft-copilot-key-provider), it only requires a section like this: ...
<Extensions>
<uap3:Extension Category="windows.appExtension">
<uap3:AppExtension Name="com.microsoft.windows.copilotkeyprovider"
Id="OpenClawCompanion"
DisplayName="OpenClaw Companion"
Description="Launch OpenClaw Companion"
PublicFolder="Public" />
</uap3:Extension>
</Extensions>
... |
…nClawChannel property
Commit 2 of the three-channel embedded-AppInstaller production rollout. Wires the channel logic into the WinUI csproj and build.ps1; consumes the per-channel embedded-AppInstaller source files added in Commit 1.
Changes
=======
.gitignore
Ignore the generated src/OpenClaw.Tray.WinUI/openclaw-update.appinstaller
(output of the RenderEmbeddedAppInstaller MSBuild target; per-build payload).
src/OpenClaw.Tray.WinUI/OpenClaw.Tray.WinUI.csproj
- Top-level OpenClawChannel property, defaulting to Dev. CI overrides with
-p:OpenClawChannel=Stable|Alpha based on the tag pattern.
- Extended the existing SyncAppxManifestVersion inline Roslyn task with three
new parameters - IdentityName, DisplayName, RemoveAutoUpdate. The task now
rewrites Identity/@name, Properties/DisplayName, and VisualElements/@DisplayName
in addition to Identity/@Version; for Dev it also strips the uap13:AutoUpdate
element so Dev MSIXs do not poll for updates.
- New RenderEmbeddedAppInstaller target (Stable/Alpha only). Copies the
per-channel source file installer/appinstaller/openclaw-update.{stable,alpha}.appinstaller
to the WinUI project as openclaw-update.appinstaller, then XmlPokes
placeholder values (Version, ProcessorArchitecture, MainPackage Uri, and
the feed self-Uri for arm64).
- Conditional <Content Include='openclaw-update.appinstaller'> picks up the
rendered file for non-Dev channels and ships it inside the MSIX payload.
src/OpenClaw.Tray.WinUI/Package.appxmanifest
- Identity/@Version baseline restored to 1.0.0.0 (was left at 0.6.4.0 by the
rehearsal).
- TEMP rehearsal comments rewritten as production language. The uap13:AutoUpdate
element stays committed (Stable default; Dev builds strip it).
build.ps1
- New -OpenClawChannel Dev|Alpha|Stable parameter (default Dev) and
-OpenClawReleaseTag parameter. Threaded through to dotnet publish via
-p:OpenClawChannel and -p:OpenClawReleaseTag.
- Preflight: -OpenClawChannel Stable|Alpha requires -OpenClawReleaseTag.
Dev with a tag warns. Channel/tag without -PackageMsix warns.
Deletions (rehearsal artifacts now superseded by the production wiring):
- installer/appinstaller/openclaw-msixtest-x64.appinstaller
- src/OpenClaw.Tray.WinUI/openclaw-update.appinstaller (now generated)
Local validation
================
- ./build.ps1: green.
- Shared.Tests: 2199 passed, 29 skipped.
- Tray.Tests: 991 passed.
- Dev MSIX via ./build.ps1 -Project WinUI -PackageMsix:
Identity OpenClaw.Companion.Dev, no AutoUpdate, no embedded file. Confirmed.
- Alpha MSIX via ./build.ps1 -Project WinUI -PackageMsix -OpenClawChannel Alpha -OpenClawReleaseTag v0.6.4-alpha.1:
Identity OpenClaw.Companion.Alpha, embedded openclaw-update.appinstaller
with alpha feed Uri and release-asset Uri. Confirmed.
- Stable MSIX via -OpenClawChannel Stable -OpenClawReleaseTag v0.6.7:
Identity OpenClaw.Companion, embedded file with stable feed Uri. Confirmed.
- Preflight: missing tag for Alpha/Stable hard-fails. Confirmed.
Resolves session todos:
- delete-msixtest-appinstaller-file
- revert-embedded-appinstaller-manifest (Package.appxmanifest now in production shape)
- revert-embedded-appinstaller-content (no more committed openclaw-update.appinstaller)
Next: Commit 3 wires CI (.github/workflows/ci.yml) to pass -p:OpenClawChannel
based on the tag pattern and reverts the remaining TEMP rehearsal CI edits.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…hannel/ReleaseTag Rename the MSBuild property and matching build.ps1 parameter to drop the OpenClaw prefix. The names are scoped enough to be unambiguous without it and shorter to type. OpenClawChannel -> ReleaseChannel OpenClawReleaseTag -> ReleaseTag Mechanical rename across 3 files (50 total swaps): src/OpenClaw.Tray.WinUI/OpenClaw.Tray.WinUI.csproj, src/OpenClaw.Tray.WinUI/Package.appxmanifest, build.ps1. The internal csproj-local properties (_OpenClawIdentityName, _OpenClawDisplayName, _OpenClawRemoveAutoUpdate, _OpenClawArch, _OpenClawEmbedArch, etc.) keep their _OpenClaw prefix since they are private to the csproj and the convention is that private MSBuild properties are prefixed with _. No behavior change. build.ps1 -Project WinUI -PackageMsix -ReleaseChannel Alpha -ReleaseTag v0.6.4-alpha.1 produces the same MSIX it did before this commit under the old parameter names. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ReleaseTag
Commit 3 of the three-channel embedded-AppInstaller production rollout. Wires CI's build-msix job to the channel mechanism the csproj and build.ps1 now consume.
Changes
=======
.github/workflows/ci.yml (build-msix job):
- Replaces the inline 'Patch MSIX manifest metadata' pwsh step (which
hand-rolled the Stable/Alpha identity rewrite via XML manipulation) with
a tiny 'Determine release channel' step that maps the tag pattern to
one of Stable / Alpha / Dev:
v0.6.7 -> Stable
v0.6.7-alpha.N -> Alpha
anything else -> Dev
- Build MSIX Package step adds -p:ReleaseChannel=<channel> and
-p:ReleaseTag=<tag>. SyncAppxManifestVersionTarget (csproj) consumes
them to set Identity Name / DisplayName / strip-or-keep AutoUpdate, and
RenderEmbeddedAppInstaller uses them to render the per-channel embedded
AppInstaller file with the correct release-asset URL.
- The Channel/IdentityName mapping is now expressed in one place per
layer instead of three (was: ci.yml inline pwsh + .csproj Sync logic).
Not included in this commit (still TEMP; intentional, per user instruction
to keep the rehearsal pipeline working):
- build-msix needs:[] (revert-msix-needs-temp todo)
- Verify tag version output msixtest skip (revert-verify-tag-msixtest-skip todo)
- Upload Signed MSIX (TEMP) artifact-upload steps (revert-msixtest-prerelease-create todo)
- Create Prerelease (TEMP - msixtest tags only) (revert-msixtest-prerelease-create todo)
- Original Create Release step (still commented out)
All of the above will be reverted in a final cleanup commit before the PR
merges to main.
No push, no tag - user controls CI runs.
Local validation (Commits 1 + 2 + 2.5 + 3) was done end-to-end on a previous build of build.ps1 -PackageMsix -ReleaseChannel Alpha/Stable/Dev; CI exercise of the new channel detection requires pushing a tag, which is left to the user.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…mahone/msix branch and treat msixtest tags as Alpha Four TEMP edits to enable an end-to-end Alpha-channel install + silent-update rehearsal on the user/kmahone/msix branch without affecting main. All four are tracked in session todos and will be reverted before merging. Changes ======= installer/appinstaller/openclaw-alpha-x64.appinstaller installer/appinstaller/openclaw-alpha-arm64.appinstaller Alpha polled-feed bootstrap files. Self-Uri swapped from .../main/... to .../user%2Fkmahone%2Fmsix/... so installed Alpha builds poll this branch's copy of the feed during the rehearsal. (revert-alpha-feed-branch-url todo) src/OpenClaw.Tray.WinUI/OpenClaw.Tray.WinUI.csproj _OpenClawFeedUri literal swapped from .../main/... to .../user%2Fkmahone%2Fmsix/.... XmlPoke writes this into the embedded openclaw-update.appinstaller's self-Uri at build time, so each Alpha MSIX built from this branch registers the branch's feed as its update-poll endpoint. (revert-embedded-feed-branch-url todo) .github/workflows/ci.yml Determine release channel regex now treats vX.Y.Z-msixtest(.N)? as Alpha (was: only vX.Y.Z-alpha(.N)?). Lets us push throwaway msixtest tags that exercise the full Alpha channel pipeline (signed MSIX, prerelease Release, embedded AppInstaller for auto-update) without burning real alpha version numbers. (revert-msixtest-as-alpha todo) Local validation ================ build.ps1 -PackageMsix -ReleaseChannel Alpha -ReleaseTag v0.6.7-msixtest.1 builds an MSIX with the embedded openclaw-update.appinstaller correctly pointing at user/kmahone/msix's openclaw-alpha-x64.appinstaller. Both URL forms (with %2F and with literal /) return 200 from raw.githubusercontent.com. Test plan (executed by hand after this push) ============================================ 1. Push v0.6.7-msixtest.1. CI builds Alpha-channel MSIX, signs, publishes prerelease. Download and install. 2. Edit installer/appinstaller/openclaw-alpha-x64.appinstaller: bump Version + MainPackage Version to 0.6.8.0; MainPackage Uri to point at v0.6.8-msixtest.1's release asset (OpenClaw.Tray.WinUI_0.6.8.0_x64.msix). Commit + push. 3. Push v0.6.8-msixtest.1. CI publishes new prerelease. 4. Quit and relaunch the installed app; OS prompt should offer the update. Verify Get-AppxPackage OpenClaw.Companion.Alpha shows 0.6.8.0. 5. Cleanup: gh release delete v0.6.7-msixtest.1 v0.6.8-msixtest.1 --cleanup-tag, Get-AppxPackage OpenClaw.Companion.Alpha | Remove-AppxPackage, then run the 7 pending TEMP-revert todos before opening the merge PR. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
UpdateBlocksActivation=false never applies on a persistent tray app - Windows downloads then deletes the staged package because the app is still running. Switch to the canonical persistent-app settings and sync OnLaunch across all six .appinstaller files. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Not yet ready for review.