feat: register a local development build without building an MSIX - #41
Conversation
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: needs maintainer review before merge. Reviewed September 15, 2026, 1:42 PM ET / 17:42 UTC (Revision 3). ClawSweeper reviewWhat this changesAdds a PowerShell command that builds and registers a runnable Windows development package without creating an MSIX, with cached downloads, scenario tests, and usage documentation. Merge readiness✅ Ready for maintainer review Keep open: this remains a distinct, useful development workflow absent from main. Both prior findings are resolved, and the supplied Windows evidence supports deployment, ownership checks, and release round trips. No blocking defect was found. Priority: P2 Review scores
Verification
How this fits togetherThe Windows launcher runs the packaged OpenClaw application using a bundled Node.js runtime. This development command assembles those inputs into a local directory, registers Windows execution aliases, and prepares the runtime through clawctl setup. flowchart TD
A[Application payload and Node archive] --> C[Local development layout]
B[Published native launcher] --> C
C --> D{Registration owned or replacement approved?}
D -->|No| E[Stop with guidance]
D -->|Yes| F[Register Windows package]
F --> G[Prepare runtime with clawctl setup]
G --> H[Runnable openclaw alias]
Before mergeNone. Agent review detailsSecurityNone. Review metrics
Technical reviewBest possible solution: Retain the additive development workflow with explicit replacement consent, installation ownership checks, and the demonstrated release-switching guidance. Do we have a high-confidence way to reproduce the issue? Not applicable as a bug reproduction: this adds a development mode. The supplied Windows transcript directly demonstrates the new registration workflow and its refusal and recovery paths. Is this the best way to solve the issue? Yes: using Windows loose-package registration avoids MSIX composition while preserving the existing launcher and setup owners; explicit consent and release round-trip proof address the installation transition. AGENTS.md: not found in the target repository. Codex review notes: model internal, reasoning medium; reviewed against 9a8cd4af1395. LabelsLabel changes:
Label justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (2 earlier review cycles)
|
Registration ownership is checked by install location, so the no-change short circuit cannot report "already up to date" for a registration belonging to another checkout. Without that check the identity takeover requested by -ReplaceExistingInstall silently did not happen and the aliases kept running the other checkout's layout. Returning to a released package requires -Unregister first. Windows will not replace a loose registration with a packaged install: Add-AppxPackage fails with 0x80073CFB, reporting that an unpackaged version is already installed and a packaged version cannot replace it. That is the same mutual exclusion as the packaged-to-local direction and is unrelated to version ordering.
8338297 to
ab94011
Compare
What Problem This Solves
Running a local build of the gateway requires composing, signing, and installing an MSIX, so a contributor cannot get a runnable
openclaw.exefrom a clean checkout in one step.User Impact
Contributors can run
.\scripts\Deploy-LocalPackage.ps1to go from a clean checkout to a registered, runnableOpenClaw.Gatewayin about a minute, and re-run it after an edit in seconds. There is no end-user behavior change: the launcher, packaged application, MSIX composition, signing policy, and release workflow are untouched.Two things contributors need to know:
OpenClaw.Gateway. Windows refuses to replace a packaged install with a local layout and cannot preserve that package's app data across the switch, so the script stops and explains rather than removing anything implicitly.-ReplaceExistingInstallaccepts that trade. Returning to a released package requires running-Unregisterfirst: Windows will not replace a loose registration with a packaged install either, regardless of version.artifacts\local-packageor removing the checkout breaks the registration until the command runs again; run-Unregisterfirst if you plan to delete the checkout.Why This Change Was Made
Windows already has a primitive for this. With Developer Mode,
Add-AppxPackage -Registertakes a manifest and a directory and registers a real package with real identity — no package file and no signature — so the compress, sign, and stage steps are not needed to run local code.The script acquires the payload and the matching Node.js runtime, publishes the NativeAOT launcher, assembles a layout, registers it, and runs
clawctl setupsoopenclawworks immediately. It is idempotent: the up-to-date check verifies the live layout rather than trusting that a previous run wrote one, and records completion only after setup succeeds. The expanded application is linked into the layout instead of copied, and the payload cache commits its selection only after the whole deployment succeeds, so a failed refresh leaves the previously working payload selected.Nothing in the packaging path changes. The layout is assembled from the published launcher and the source manifest rather than from packaging content, so
Build-LocalMSIX.ps1,Build-MSIX.ps1,Sign-TestMSIX.ps1, the launcher project, and the build properties are untouched. The change is purely additive.Evidence
All evidence below is from head
ab940113341f4eaed184fbab5dc17848dbaa9199, on Windows 11 x64 with Developer Mode enabled.Scenario tests
They inject every GitHub, publish, registration, and deployment operation, so no test registers, removes, or modifies a real package. Covered: clean checkout, idempotent re-runs, a launcher change reaching the layout, each individually damaged layout input, payload refresh and its failure recovery, skipped and failed setup, the conflicting and foreign-install paths with and without consent, and the failures that must stop before registering.
Clean checkout to runnable — cold cache
Idempotency — two consecutive runs, nothing changed
The remaining time is
dotnet publishdeciding it has nothing to do; registration is skipped entirely.Registered package actually runs
OpenClaw 2026.8.2 (0965053)matches the payload's recordedpackageVersionandresolvedCommit, confirming the linked application tree is what the package actually serves.Defect-injection checks for the two highest-severity review findings
Tests written alongside a fix can pass for the wrong reason, so each was run against the defect restored:
A run after -SkipSetup did not complete the setup it skipped.A failed deployment left the unusable payload selected.Both fail against the defect and pass against the fix.
A registration whose layout was deleted underneath it was also verified by hand: the package still reports
Status: Okwhile both aliases fail withThe process has no package identity, and re-registering does not repair it. Registration now removes the prior development registration first, preserving app data, and recovery was confirmed by deleting the live layout and re-running.Round trip against the real signed release
Using
OpenClawGateway-0.0.0.0-x64.msixfrom releasev0.0.0.0. Installing the release over a local registration is refused:The cause is the packaged/unpackaged mutual exclusion in the other direction, not version ordering. After
-Unregisterthe release installs and runs:Returning to the local build is refused without consent, then succeeds with it:
Packaged app data is lost on that final step, which is the documented trade.
Registration ownership, against a real foreign registration
The machine carried a registration from a different worktree, so this was exercised for real rather than simulated. Deployment refuses it:
-Unregisterrefuses the same registration, and-ReplaceExistingInstallperforms a real takeover rather than reporting no change:Ownership is decided by normalized
InstallLocationthrough one helper shared by the up-to-date short circuit, the deployment gate, and-Unregister. The regression test covering a foreign registration whose version matches retained local state was confirmed to fail against the unfixed short circuit withA same-version foreign registration was reported as up to date.