[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M698QEPAAXVVCFQCZMEWMW6H":3,"skill-same:01M698QEPAAXVVCFQCZMEWMW6H":71},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":43,"linkOnly":44,"markdownContent":45,"markdownBody":46,"frontMatter":47,"refName":48,"commitSha":49,"skillDirectory":50,"forksCount":51,"repositoryHtmlUrl":52,"repositoryHomepageUrl":53,"ownerHtmlUrl":54,"ownerBlogUrl":53,"ownerDescription":55,"updatedAt":56,"install":57,"resources":70},"01M698QEPAAXVVCFQCZMEWMW6H","native-gateway-from-source",null,"Run side-by-side named Gateway patches as the default for local and future cloud native-Gateway E2E on capable Windows clients. Build from npm latest, a published packaging release with -GatewayChannel Packaged, or explicit sources; select the patch with OPENCLAW_NATIVE_GATEWAY_DEV_PATCH and remove only owned instances.","openclaw\u002Fopenclaw-windows-node","openclaw","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F252820863?v=4","01M698P3FSAZ6B4R928ZF19KPT","01M698Q6SND6RHZDPP8ZM0NSP7",2197,"MIT","https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw-windows-node\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fnative-gateway-from-source\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",[23,24,25,26,27,9,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],"native gateway from source","source","native","gateway","default","for","with","windows","sources","as","local","instances","dev","patch","only","packaging","remove","select","e2e","cloud native","2026-11-10 10:12:30",false,"---\nname: native-gateway-from-source\ndescription: Run side-by-side named Gateway patches as the default for local and future cloud native-Gateway E2E on capable Windows clients. Build from npm latest, a published packaging release with -GatewayChannel Packaged, or explicit sources; select the patch with OPENCLAW_NATIVE_GATEWAY_DEV_PATCH and remove only owned instances.\n---\n\n# Native Gateway from source\n\n`scripts\\Build-NativeGatewayFromSource.ps1` packages npm `latest` by default with\n`openclaw\u002Fopenclaw-windows-packaging`, and registers a Developer Mode loose package named\n`OpenClawFoundation.OpenClawGateway-\u003Cpatch>` with aliases `openclaw-\u003Cpatch>.exe` and\n`clawctl-\u003Cpatch>.exe`. A \"patch\" is a side-by-side identity slot (upstream\n`Deploy-LocalPackage.ps1 -Patch`), not a version: each patch has its own app data, isolated\nagent account, and Gateway configuration, and never touches the Store package.\nDistinct identities do not automatically allocate distinct listening ports.\n\nCompanion uses the patch only when started with `OPENCLAW_NATIVE_GATEWAY_DEV_PATCH=\u003Cpatch>`.\nWithout it, Companion resolves the Store package and installs it with WinGet only when\nmissing. The local launcher now sets the development patch automatically; installed\nCompanion behavior is unchanged. See `docs\u002FONBOARDING_WIZARD.md` and\n`docs\u002FARCHITECTURE.md` (native Gateway section).\n\n## Prerequisites\n\nCheck before building; the script fails fast on most of these:\n\n- Windows Developer Mode on, isolated-session-capable Windows (native setup's device check).\n- PowerShell 7.4 or later (`pwsh`). Windows PowerShell 5.1 cannot run the script.\n- git, .NET SDK 10.0.400 or later, Visual Studio Build Tools with C++ and the Windows SDK\n  (the packaging repo builds NativeAOT executables).\n- For npm\u002Fsource builds, Node.js satisfying the selected Gateway's engines requirement\n  (currently 24.16 or later) whose `process.platform\u002Fprocess.arch` is `win32\u002F\u003COS arch>`.\n- For Packaged, authenticated GitHub CLI (`gh`). No local Node\u002Fpnpm build is needed;\n  deployment obtains the Node runtime version recorded in the released MSIX.\n- For explicit source builds only, pnpm with the same major as the source's `packageManager` (main uses pnpm 12):\n  `npm install -g pnpm@\u003Cversion>`. The script prints the exact version on mismatch.\n\n## Default multi-instance native Gateway testing\n\nFor isolated test builds that need a real native Gateway, use task-owned named\nside-by-side patches by default, including single-instance tests, local E2E and\nfuture cloud E2E. Use one authorized, capability-qualified Windows 11 client\nhost instead of one Hyper-V VM per Gateway. Each patch owns a package family,\napp data, isolated session and sign-in recovery task. They still share host CPU\u002FRAM, networking and\ndesktop resources; cap concurrent work to the host's available capacity.\nThis is test-target guidance, not a CI migration or evidence that a cloud lane ran.\nDeveloper Mode and actual isolated-session\u002Flistener-ownership support are required;\n`windows-latest`, Windows Server, or a successful registration alone proves neither.\n\nKeep [fixture-backed app tests](..\u002F..\u002F..\u002Fdocs\u002FGATEWAY_FIXTURE_TESTING.md) as the\ncheaper default for app-only behavior. Use a separate reusable local or approved\ncloud VM for clean-image\u002Finstall\u002Fupgrade tests, genuine OS isolation, or a host\nwithout the required capabilities. Development patches do not prove signed\nStore\u002FMSIX installation or upgrade behavior. Keep required real MXC containment,\nGateway-to-node invocation and WSL proof; do not substitute patch startup for\n`.\\scripts\\validate-mxc-e2e.ps1` when that suite is required.\n\n### Prepare an isolated test build\n\nBuild Companion in the task-owned **openclaw-windows-node** worktree, not the\nmain\u002Fshared checkout. Prepare the real Gateway with the helper's explicit\n`-Patch` and `-WorkRoot` before launching Companion. This is the recommended\npath for test instances; the direct packaging workflow below is an alternative\nwhen testing packaging itself.\n\nAfter obtaining runtime authority and checking the prerequisites above, run\nfrom that worktree root. Replace `t42` consistently with a unique task ID:\n\n```powershell\n$ErrorActionPreference = 'Stop'\n$patch = 't42-alpha'\n$workRoot = 'C:\\OpenClawDev\\t42\\native-gateway'\nif (Get-AppxPackage -Name \"OpenClawFoundation.OpenClawGateway-$patch\") {\n    throw 'Choose an unused patch, or verify ownership before reusing this instance.'\n}\n.\\build.ps1\nif ($LASTEXITCODE -ne 0) { throw 'Companion build failed.' }\n.\\scripts\\Build-NativeGatewayFromSource.ps1 -GatewayChannel Latest -Patch $patch -WorkRoot $workRoot\n```\n\nExpected: Companion output belongs to this worktree and the helper registers\n`OpenClawFoundation.OpenClawGateway-t42-alpha` from the task-owned work root.\nUse `-GatewayChannel Packaged` for released-payload compatibility, or\n`-OpenClawRef \u003Cfull-sha>` \u002F `-OpenClawSourceDirectory \u003Ctask-owned-checkout>`\ninstead of `-GatewayChannel` for explicit source changes. Keep the same unique\npatch and work root for each instance's rebuild and ownership-checked removal.\n\nFollow [selection, startup and verification](#select-start-and-verify-each-instance)\nbefore running tests. For helper-built instances, `$packagingRoot` is\n`Join-Path $workRoot 'openclaw-windows-packaging'`; use the build's architecture\nfor the registration\u002Flayout checks. Set `OPENCLAW_NATIVE_GATEWAY_DEV_PATCH`\nbefore launching with `-NoBuild -Isolated -DataDir \u003Ctask-instance-directory>`.\nThat variable reuses the prepared patch without rebuilding it.\n\n`-Isolated` \u002F `-DataDir` isolates Companion's profile, not its build output or\nGateway package. An unqualified `.\\run-app-local.ps1 -Isolated` still selects\nthe shared `npm-latest` patch (or an inherited patch), not a new task instance.\nDo not use it as the isolated real-Gateway test recipe. Build Companion once;\nfor a second Gateway, prepare `t42-beta` serially with the helper, then launch\nit with its own profile after alpha is verified listening. Remove helper-built\ninstances with [the ownership-checking wrapper](#remove-it), passing the same\n`-WorkRoot`.\n\n### Alternative: deploy directly from the packaging repository\n\nThe direct command belongs to **openclaw\u002Fopenclaw-windows-packaging**, not this\nrepository. Start with a clean task-owned clone outside the user profile, under\na trusted parent readable by the isolated account and not writable by unrelated\naccounts. Do not deploy from a main\u002Fshared checkout or relax ACLs to make one work.\nUse its pinned .NET SDK, NativeAOT C++\u002FWindows SDK tools, PowerShell 7 and Developer\nMode prerequisites. The default payload download also needs authenticated `gh`;\nit obtains the bundled Node runtime, without a local Gateway npm\u002Fsource build.\n\nThe minimal examples are `.\\scripts\\Deploy-LocalPackage.ps1 -Patch alpha`, then\n`.\\scripts\\Deploy-LocalPackage.ps1 -Patch beta`. On shared hosts, qualify both\nwith a unique task identifier as below. Replace `t42` and its path consistently:\nnames must be 1 to 15 letters, digits or hyphens, starting and ending with a\nletter or digit, with no whitespace. They are lowercased. Do not reuse another\ntask's patch or rely on the shared helper defaults `npm-latest` \u002F `packaged`.\nAuthorization must cover registration, session setup, startup-task creation and\neventual teardown, not just building source.\n\n```powershell\n$ErrorActionPreference = 'Stop'\n$packagingRoot = 'C:\\OpenClawDev\\t42\\openclaw-windows-packaging'\n$architecture = [Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString().ToLowerInvariant()\n$patches = @('t42-alpha', 't42-beta')\nif (Test-Path -LiteralPath $packagingRoot) { throw 'Choose a new task-owned clone path.' }\ngit clone https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw-windows-packaging.git $packagingRoot\nif ($LASTEXITCODE -ne 0) { throw 'Packaging clone failed.' }\nSet-Location $packagingRoot\nforeach ($patch in $patches) {\n    if (Get-AppxPackage -Name \"OpenClawFoundation.OpenClawGateway-$patch\") {\n        throw \"Patch $patch already exists. Confirm ownership or choose another task name.\"\n    }\n}\n.\\scripts\\Deploy-LocalPackage.ps1 -Patch $patches[0] -Architecture $architecture\n.\\scripts\\Deploy-LocalPackage.ps1 -Patch $patches[1] -Architecture $architecture\n```\n\nExpected: two `OpenClawFoundation.OpenClawGateway-\u003Cpatch>` registrations with\ntheir own `openclaw-\u003Cpatch>` and `clawctl-\u003Cpatch>` aliases, beside the unchanged\nbase package and other patches. Deploy normally runs `clawctl setup`: it\nprovisions\u002Freuses the session, installs Node in the agent profile and enables\nsign-in recovery, but **does not start a listening Gateway**. `-SkipSetup` leaves\nthat setup work outstanding. A setup failure may leave a registration; inspect\nonly the owned patch, then retry or clean it up rather than claiming readiness.\n\nSerialize deployment, rebuild, refresh and unregister operations, including\nacross agents using the same checkout\u002Fcache. The node repo's build helper also\nenforces a machine-wide build\u002Funregister lock; do not assume direct packaging\ncommands have that same guard. Once prepared, separate running instances can\nserve independent tests concurrently. Do not rebuild or remove a layout\u002Fpayload\nwhile a test uses it.\n\n**Cache scope:** rerunning the same patch reuses valid downloads and unchanged\nbuild output. Current packaging keeps payload and Node caches per patch under\n`artifacts\\local-package\\patches\\\u003Cpatch>\\\u003Carchitecture>`; beta's first deployment\ndoes not automatically reuse alpha's payload download. To share an already\nprepared payload, pass the same validated, task-owned immutable\n`-PayloadDirectory \u003Cabsolute-payload-root>` on each deployment. It must contain\n`app` and `payload-metadata.json`. Keep it alive until every referencing patch\nis unregistered; never borrow a cache generation another patch may refresh\u002Fdelete.\nFor npm Latest, Packaged or source-ref selection, use the helper workflows below\nwith explicit unique `-Patch` names and a task-owned `-WorkRoot` instead.\n\n### Select, start and verify each instance\n\nResolve aliases from the actual registration, not a guessed publisher suffix,\nPATH's base `clawctl`, or a shared default endpoint. In the packaging shell,\nrepeat this block for each owned patch:\n\n```powershell\n$patch = 't42-alpha'\n$packages = @(Get-AppxPackage -Name \"OpenClawFoundation.OpenClawGateway-$patch\")\n$expectedLayout = Join-Path $packagingRoot \"artifacts\\local-package\\patches\\$patch\\$architecture\\layout\"\nif ($packages.Count -ne 1 -or -not $packages[0].IsDevelopmentMode -or\n    $packages[0].InstallLocation.TrimEnd('\\') -ine $expectedLayout.TrimEnd('\\')) {\n    throw 'The expected task-owned development registration was not found.'\n}\n$package = $packages[0]\n$aliasRoot = Join-Path $env:LOCALAPPDATA \"Microsoft\\WindowsApps\\$($package.PackageFamilyName)\"\n$clawctl = Join-Path $aliasRoot \"clawctl-$patch.exe\"\n$openclaw = Join-Path $aliasRoot \"openclaw-$patch.exe\"\nif (-not (Test-Path -LiteralPath $clawctl) -or -not (Test-Path -LiteralPath $openclaw)) {\n    throw 'Enable this package''s app execution aliases in Windows Settings, then retry.'\n}\n& $clawctl --version\nif ($LASTEXITCODE -ne 0) { throw 'Owned Gateway version check failed.' }\n```\n\nBuild Companion once from its task-owned **openclaw-windows-node** worktree\nbefore launching tests. In a separate shell at that worktree root, select one\npatch and a fresh task\u002Finstance-specific data directory:\n\n**Setup-local boundary:** `-DataDir` separates Companion's app profile, but\ndoes not redirect setup-local or Local AI state. Without separate overrides,\nthose paths still resolve under the user's normal `%LOCALAPPDATA%\\OpenClawTray`.\nThe recipe below covers Gateway setup and client behavior, not isolated Local\nAI acquisition, removal or concurrent Local AI setup. Before any such operation,\nconfigure and verify a task-owned `OPENCLAW_TRAY_LOCALAPPDATA_DIR` root;\nsetup appends `OpenClawTray`. If the legacy `OPENCLAW_TRAY_LOCAL_DATA_DIR` is\nalso set, align it with that effective directory. Do not use the normal user's\nLocal AI manifest or runtime state as test-owned data.\n\n```powershell\n$env:OPENCLAW_NATIVE_GATEWAY_DEV_PATCH = 't42-alpha'\n.\\run-app-local.ps1 -NoBuild -Isolated -DataDir \"$env:TEMP\\oc-t42-alpha\"\nRemove-Item Env:\\OPENCLAW_NATIVE_GATEWAY_DEV_PATCH\n```\n\nChoose **Install a local native gateway**, then **Set up gateway**. This path\nconfigures and starts the selected patch. Verify alpha is listening before\nlaunching beta with `t42-beta` and `oc-t42-beta`. Companion chooses an available\nport for a new draft, but separate drafts do not reserve ports. Serializing\ninitial setup\u002Fstart avoids both choosing the same unused default. Preserve the\nvariable for any relaunch of that profile; an already-running app cannot switch\npatches. Never share profiles, copy real user credentials, or omit selection and\naccidentally configure the base Gateway.\n\nFor CLI-only testing, configure a distinct `gateway.port` in each owned\ninstance before `& $clawctl gateway-service start --json`, using the resolved\npatched aliases and that scenario's normal configuration flow. Both unconfigured\nGateways otherwise use the upstream default. After either startup path, in the\nmatching packaging shell:\n\n```powershell\n& $clawctl gateway-service status --json\n```\n\nThis command is a status sample, not a readiness assertion. It can return a\nnonzero exit code while still `starting`, and failure JSON can omit `gateway`.\nConversely, `not-started` can return zero. Do not put an immediate throw on every\nnonzero exit into a readiness loop. Retry pending startup within the scenario's\nconfigured startup timeout, inspect each JSON result, and fail explicitly with\nthe last status\u002Ferror if readiness is not reached. Malformed JSON or an explicit\nconfiguration\u002Fownership error is a blocker, not a pending state to ignore.\n\nRequire `integration.kind = isolated-session`, `gateway.state = running`, the\nactual `gateway.port` and non-null `gateway.ownership` for each instance. Match\nthe port\u002Ffamily to that Companion profile and require distinct ports before\nparallel tests. `start` may exit zero with `state = starting`; use bounded status\npolling, not a successful exit alone. Status can probe\u002Fstart an already-recorded\nsession, so it is not a passive host inventory command. A port collision or\nmissing ownership support is a blocker, not permission to kill another listener.\nKeep test artifacts and, when enabled, local MCP endpoints\u002Ftokens separate too.\n\n### Remove only the owned patch\n\nClose only that task's Companion\u002Ftest clients. Re-run the exact registration,\nlayout and alias checks above immediately before teardown. From the same\npackaging checkout and architecture, with `$patch` and `$clawctl` resolved for\nthe instance being removed:\n\n```powershell\n& $clawctl teardown --force\nif ($LASTEXITCODE -ne 0) { throw 'Teardown failed. Keep the registration for recovery.' }\n.\\scripts\\Deploy-LocalPackage.ps1 -Unregister -Patch $patch -Architecture $architecture\nif (Get-AppxPackage -Name \"OpenClawFoundation.OpenClawGateway-$patch\") {\n    throw 'The owned patch is still registered.'\n}\n```\n\nThis is `clawctl-\u003Cname> teardown --force` followed by\n`.\\scripts\\Deploy-LocalPackage.ps1 -Unregister -Patch \u003Cname>`, not wildcard\nremoval or `-ReplaceExistingInstall`. Teardown removes that session\u002Fdata and\nstartup task; unregister preserves remaining package app data and caches.\nDo not delete the checkout\u002Fshared payload until all its registrations are gone.\nIf unregister happened first, restore the same owned patch to reach teardown.\nFor helper-created patches, prefer [the ownership-checking wrapper](#remove-it).\n\nContracts checked against packaging\n[local-development guidance](https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw-windows-packaging\u002Fblob\u002F2062d05176bdc2ff6732fc439986fcefe2f3e4fe\u002Fdocs\u002Flocal-development.md#side-by-side-patched-identities)\nand [deployment owner](https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw-windows-packaging\u002Fblob\u002F2062d05176bdc2ff6732fc439986fcefe2f3e4fe\u002Fscripts\u002FLocalPackage.psm1).\nRecord the actual packaging commit, payload version\u002Fcommit, package families,\ndistinct ports, selected tests\u002Fresults and cleanup outcome for each future run.\nSource inspection is not exercised local\u002Fcloud E2E proof.\n\n## Latest and Packaged development\n\nUse one Companion branch for both Gateway compatibility targets. Do not create or\ncontinually synchronize a `release\u002Fextended-stable` fork.\nThe shorthand commands below describe the launcher's channel defaults for\nsingle-developer compatibility work. For isolated test instances, use\n[unique task-owned builds and patches](#prepare-an-isolated-test-build) instead.\n\n```powershell\n.\\run-app-local.ps1 -Isolated\n.\\run-app-local.ps1 -Isolated -GatewayChannel Packaged\n.\\run-app-local.ps1 -Isolated -GatewayChannel Packaged -PackagingRelease v2026.9.9-msix.0\n```\n\nThe first command resolves npm `latest` and builds\u002Fregisters patch `npm-latest`.\nThe second selects the latest published packaging release and uses patch `packaged`.\nThe third pins a specific published release. GitHub publication does not establish\nStore availability; select the known shipping release explicitly when needed. Both\nretain MSIX isolation and package through `openclaw\u002Fopenclaw-windows-packaging`.\nThe launcher uses separate worktree\u002Fchannel data directories automatically and\nrestores its environment after launch. The Store package is not updated or replaced.\n`-NoBuild` skips the Companion build, not Gateway resolution\u002Fpackaging.\n\nTo prepare only the native Gateway:\n\n```powershell\n.\\scripts\\Build-NativeGatewayFromSource.ps1\n.\\scripts\\Build-NativeGatewayFromSource.ps1 -GatewayChannel Packaged\n.\\scripts\\Build-NativeGatewayFromSource.ps1 -OpenClawNpmVersion 2026.8.35 -Patch pinned\n```\n\nLatest is resolved to an exact npm version on every build. Archive SHA-512\nintegrity, package version and embedded build commit are verified before packaging.\n`source.json` records the selector, exact version, commit, npm integrity and archive\nSHA-256. For reproducible reruns, specify that exact npm version and a packaging\ncommit with `-PackagingRef`. Cached archives are reverified before payload reuse.\nAn incompatible or unavailable release fails explicitly, never falls back to Store\nor the other channel.\n\nPackaged verifies the published architecture-specific MSIX SHA-256 and reads its\nembedded package version, build commit\u002Fbuild ID and Node runtime. Never derive the\nGateway version from the MSIX tag: packaging can ship an older payload under a newer\nMSIX identity. The helper reuses released `app` bytes, checks each file against the\nrelease inventory on extraction and cache reuse, and writes `packaging-release.json`.\nIt checks out the exact packaging tag commit to build the side-by-side development\nlauncher. This is released Gateway payload proof, not installation of the original\nsigned MSIX. `-PackagingRef` and `-PackagingDirectory` cannot override Packaged's\nprovenance. Pin with `-PackagingRelease`; `-Force` re-registers without changing\nthe released payload bytes.\n\nUse `-UseStoreGateway` on the local launcher to test the installed Store runtime.\nAn existing `OPENCLAW_NATIVE_GATEWAY_DEV_PATCH` selects that patch without rebuilding\nit. Like Companion, the launcher trims and lowercases patch names and treats blank\nvalues as unset. Clear the variable before explicitly using `-GatewayChannel`.\nNeither flag changes WSL setup defaults. For a WSL version-specific setup, explicitly\nset `Gateway.Version` to the exact version.\n\nWSL CI follows npm Latest only, matching normal WSL setup. It resolves Latest once\nper workflow and runs each selected setup\u002Fconnect, revocation and network recovery\njob once at that exact version via `OPENCLAW_E2E_GATEWAY_VERSION`. Each job's\nartifact contains `gateway-release.json`. CI does not download a native MSIX or\nduplicate WSL tests against Packaged.\n\nNative Latest\u002FPackaged runtime CI is not implemented. Existing unit\u002Fhelper and\npackaging checks do not prove live isolated-session startup, pairing or recovery;\nnative runtime proof needs a capability-qualified Windows client host. See the\nGateway development and CI matrix in the repository's `DEVELOPMENT.md`.\n\n## Build and register an explicit source ref\n\n```powershell\npwsh -File .\\scripts\\Build-NativeGatewayFromSource.ps1 -OpenClawRef main -Patch source\n```\n\n- First run clones both repos under `%SystemDrive%\\OpenClawDev\\native-gateway-source` and takes\n  roughly 25 to 30 minutes (`pnpm build` dominates). Run it in the background and do not poll.\n- Success ends with `Registered OpenClawFoundation.OpenClawGateway-source_\u003Chash>` and\n  `OpenClaw \u003Cversion> (\u003Cfull sha>)`. Compare the sha with\n  `git ls-remote https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw refs\u002Fheads\u002Fmain`.\n- `main` of both repos moves often. Each rerun fetches them again; a new commit in either\n  repo builds and re-registers a new payload. To get a reproducible rerun, pin both:\n  `-OpenClawRef \u003Cfull sha> -PackagingRef \u003Cfull sha>`. A pinned rerun prints\n  `Reusing payload` and `Already up to date` without rebuilding. ACL validation still\n  walks the checkouts and selected payload; large dependency trees take longer.\n- Other sources: `-OpenClawSourceDirectory \u003Ccheckout>` builds a local checkout as-is\n  (uncommitted changes allowed, always a fresh payload). `-OpenClawPackageDirectory \u003Cdir>`\n  takes an existing `openclaw.tgz` + `source.json` and only builds the payload (about\n  2 to 3 minutes); previous builds leave these under `\u003CWorkRoot>\\packages\\\u003Cid>`.\n- `-Force` builds a new payload and re-registers even when nothing changed.\n- Relative `-WorkRoot` paths are anchored to the invoking PowerShell location before\n  any directory changes.\n- Only one source build or unregister can run on a machine at a time, even across\n  different patches and work roots. A concurrent invocation fails before changing files.\n  Payload installation also uses a fresh per-run staging directory, removed on exit.\n- Prebuilt packages must include valid commit\u002Fhash\u002Fversion metadata. The archive hash\n  is checked before payload-cache reuse, not just on a fresh build.\n\nVerify the registration:\n\n```powershell\nGet-AppxPackage -Name OpenClawFoundation.OpenClawGateway-source |\n    Format-List PackageFamilyName, Version, Publisher, IsDevelopmentMode, InstallLocation\n$alias = \"$env:LOCALAPPDATA\\Microsoft\\WindowsApps\\OpenClawFoundation.OpenClawGateway-source_rfcbke2p71se2\"\n& \"$alias\\clawctl-source.exe\" --version        # Payload line shows the source sha\n& \"$alias\\clawctl-source.exe\" status --json    # integration.kind = isolated-session\n```\n\n## Run Companion against it\n\nUse isolated tray data so the user's real settings and gateways are untouched:\n\n```powershell\n.\\build.ps1\n$env:OPENCLAW_NATIVE_GATEWAY_DEV_PATCH = 'source'\n$env:OPENCLAW_FORCE_ONBOARDING = '1'\n.\\run-app-local.ps1 -NoBuild -DataDir \"$env:TEMP\\oc-devgw-source\"\n```\n\nIn setup choose **Install a local native gateway**, then **Set up gateway**. Expected:\nall four native steps complete and **Connect your AI** loads from the source-built Gateway.\n`\u003Cdata-dir>\\gateways\\native-setup-draft.json` records\n`PackageFamilyName = OpenClawFoundation.OpenClawGateway-source_rfcbke2p71se2`, and\n`clawctl-source gateway-service status` reports `[ok] listening` on the recorded port.\nNo `winget.exe` should start. Clear both variables afterwards.\n\nThe variable must be set in the shell that launches Companion; a running Companion does not\npick it up. Profiles created this way resolve only while the variable names the same patch.\n\n## Remove it\n\n```powershell\npwsh -File .\\scripts\\Build-NativeGatewayFromSource.ps1 -Unregister -Patch source\n```\n\nUse `-Patch npm-latest` or `-Patch packaged` for the channel builds.\nUnregister always requires the explicit patch. This runs the selected patch's\n`clawctl-\u003Cpatch> teardown --force` (removes the isolated session, Gateway records and\nagent profile), then unregisters. The Store package stays. Payloads and checkouts under the\nwork root are kept; delete them manually only after unregistering. Pass the same\n`-WorkRoot`\u002F`-PackagingDirectory`\u002F`-Architecture` used to register, or the ownership check\nrefuses before teardown.\n\n## Pitfalls\n\n- **Never put the work root or packaging checkout under the user profile.** The Gateway runs as\n  a separate isolated agent account that must read the payload through every parent folder;\n  under `C:\\Users\\\u003Cyou>` Node fails with `EPERM ... lstat 'C:\\Users\\\u003Cyou>\\AppData'` and setup\n  reports \"OpenClaw could not read the effective Gateway configuration\". The script refuses\n  such paths. Do not \"fix\" it with ACL grants.\n- **Build trees must not be writable by other accounts.** Newly created work directories\n  have protected ACLs: the current user, Administrators and SYSTEM can write; other\n  authenticated accounts, Users and application-package groups get read\u002Fexecute only.\n  Existing trees, supplied checkouts and\n  prebuilt packages are checked, including linked targets and replaceable ancestors.\n  Unsafe paths are rejected without changing their ACLs. Use a fresh root under a trusted\n  parent (for example `C:\\OpenClawSourceSafe`), not another child of an unsafe directory.\n  For an existing registration, have an administrator verify its files and repair its\n  permissions before retrying unregister. Do not execute potentially modified aliases\n  merely to bypass the check.\n- **Never move or delete the work root while registered.** The layout links the payload with a\n  junction. Moving keeps the old ACLs (the agent account loses access); `icacls \u002Freset \u002FT`\n  over the openclaw checkout loops through pnpm symlinks for a long time. Unregister, then\n  rebuild in the new location.\n- **A cancelled source build leaves `openclaw\\.artifacts\\dist-artifacts.lock`.** The next\n  `pnpm build` refuses with \"Could not acquire ... dist-artifacts.lock\". After confirming no\n  build process is still running, remove that directory and rerun.\n- **Do not run native setup without the variable on a host whose Store Gateway is in use.** It\n  pairs a new device with that live Gateway. Prove Store resolution without side effects\n  instead (unit tests, or call `NativeGatewayPackageResolver` from a throwaway program).\n- Payloads are architecture-specific. An x64 payload on ARM64 registers but `clawctl setup`\n  fails there (upstream note); build on the target architecture.\n\n## Error messages and what they mean\n\n| Message | Cause | Action |\n|---|---|---|\n| `The development Gateway package ...-\u003Cpatch> is not registered ...` (new setup) | Variable set, patch not registered | Run the build, or clear the variable to use the Store Gateway |\n| `This Gateway profile uses the development Gateway package ...-\u003Cpatch>. Set OPENCLAW_NATIVE_GATEWAY_DEV_PATCH=\u003Cpatch> ...` | Saved profile bound to a patch, variable unset or different | Restart Companion with that variable |\n| `This Gateway profile uses ... which is not registered ...` | Saved profile bound to a patch that was unregistered | Re-register the patch, or remove the gateway in Connection settings and set up again |\n| `OPENCLAW_NATIVE_GATEWAY_DEV_PATCH must be 1 to 15 letters ...` | Invalid variable value | Use lowercase letters, digits, hyphens |\n| `-WorkRoot '...' is inside your user profile ...` | Profile path passed | Use a path such as `C:\\OpenClawDev` |\n| `The package-qualified aliases were not found ...` | App execution aliases disabled | Enable them in Settings > Apps > Advanced app settings > App execution aliases |\n| `Another native Gateway source build or unregister is running ...` | Shared build\u002Fregistration resources are locked | Wait for that operation to finish, then retry |\n| `Native Gateway build path ... grants write or replacement access ...` | Another account can modify code or replace a parent | Use a fresh root under a trusted parent, or have an administrator verify and repair the existing tree |\n| `Prebuilt package metadata ... requires ...` | Missing, malformed or truncated provenance | Recreate `source.json` with the package producer; do not invent hashes |\n\n## Proof for PRs\n\nFor PRs that depend on a source-built Gateway, follow `openclaw-proof-validation`: report the\nregistered family, `clawctl-\u003Cpatch> --version`, the commit tested, and focused app-window\nscreenshots. Never publish `gateways.json`, setup drafts beyond family and port, tokens, or\nidentity files.\n","# Native Gateway from source\n\n`scripts\\Build-NativeGatewayFromSource.ps1` packages npm `latest` by default with\n`openclaw\u002Fopenclaw-windows-packaging`, and registers a Developer Mode loose package named\n`OpenClawFoundation.OpenClawGateway-\u003Cpatch>` with aliases `openclaw-\u003Cpatch>.exe` and\n`clawctl-\u003Cpatch>.exe`. A \"patch\" is a side-by-side identity slot (upstream\n`Deploy-LocalPackage.ps1 -Patch`), not a version: each patch has its own app data, isolated\nagent account, and Gateway configuration, and never touches the Store package.\nDistinct identities do not automatically allocate distinct listening ports.\n\nCompanion uses the patch only when started with `OPENCLAW_NATIVE_GATEWAY_DEV_PATCH=\u003Cpatch>`.\nWithout it, Companion resolves the Store package and installs it with WinGet only when\nmissing. The local launcher now sets the development patch automatically; installed\nCompanion behavior is unchanged. See `docs\u002FONBOARDING_WIZARD.md` and\n`docs\u002FARCHITECTURE.md` (native Gateway section).\n\n## Prerequisites\n\nCheck before building; the script fails fast on most of these:\n\n- Windows Developer Mode on, isolated-session-capable Windows (native setup's device check).\n- PowerShell 7.4 or later (`pwsh`). Windows PowerShell 5.1 cannot run the script.\n- git, .NET SDK 10.0.400 or later, Visual Studio Build Tools with C++ and the Windows SDK\n  (the packaging repo builds NativeAOT executables).\n- For npm\u002Fsource builds, Node.js satisfying the selected Gateway's engines requirement\n  (currently 24.16 or later) whose `process.platform\u002Fprocess.arch` is `win32\u002F\u003COS arch>`.\n- For Packaged, authenticated GitHub CLI (`gh`). No local Node\u002Fpnpm build is needed;\n  deployment obtains the Node runtime version recorded in the released MSIX.\n- For explicit source builds only, pnpm with the same major as the source's `packageManager` (main uses pnpm 12):\n  `npm install -g pnpm@\u003Cversion>`. The script prints the exact version on mismatch.\n\n## Default multi-instance native Gateway testing\n\nFor isolated test builds that need a real native Gateway, use task-owned named\nside-by-side patches by default, including single-instance tests, local E2E and\nfuture cloud E2E. Use one authorized, capability-qualified Windows 11 client\nhost instead of one Hyper-V VM per Gateway. Each patch owns a package family,\napp data, isolated session and sign-in recovery task. They still share host CPU\u002FRAM, networking and\ndesktop resources; cap concurrent work to the host's available capacity.\nThis is test-target guidance, not a CI migration or evidence that a cloud lane ran.\nDeveloper Mode and actual isolated-session\u002Flistener-ownership support are required;\n`windows-latest`, Windows Server, or a successful registration alone proves neither.\n\nKeep [fixture-backed app tests](..\u002F..\u002F..\u002Fdocs\u002FGATEWAY_FIXTURE_TESTING.md) as the\ncheaper default for app-only behavior. Use a separate reusable local or approved\ncloud VM for clean-image\u002Finstall\u002Fupgrade tests, genuine OS isolation, or a host\nwithout the required capabilities. Development patches do not prove signed\nStore\u002FMSIX installation or upgrade behavior. Keep required real MXC containment,\nGateway-to-node invocation and WSL proof; do not substitute patch startup for\n`.\\scripts\\validate-mxc-e2e.ps1` when that suite is required.\n\n### Prepare an isolated test build\n\nBuild Companion in the task-owned **openclaw-windows-node** worktree, not the\nmain\u002Fshared checkout. Prepare the real Gateway with the helper's explicit\n`-Patch` and `-WorkRoot` before launching Companion. This is the recommended\npath for test instances; the direct packaging workflow below is an alternative\nwhen testing packaging itself.\n\nAfter obtaining runtime authority and checking the prerequisites above, run\nfrom that worktree root. Replace `t42` consistently with a unique task ID:\n\n```powershell\n$ErrorActionPreference = 'Stop'\n$patch = 't42-alpha'\n$workRoot = 'C:\\OpenClawDev\\t42\\native-gateway'\nif (Get-AppxPackage -Name \"OpenClawFoundation.OpenClawGateway-$patch\") {\n    throw 'Choose an unused patch, or verify ownership before reusing this instance.'\n}\n.\\build.ps1\nif ($LASTEXITCODE -ne 0) { throw 'Companion build failed.' }\n.\\scripts\\Build-NativeGatewayFromSource.ps1 -GatewayChannel Latest -Patch $patch -WorkRoot $workRoot\n```\n\nExpected: Companion output belongs to this worktree and the helper registers\n`OpenClawFoundation.OpenClawGateway-t42-alpha` from the task-owned work root.\nUse `-GatewayChannel Packaged` for released-payload compatibility, or\n`-OpenClawRef \u003Cfull-sha>` \u002F `-OpenClawSourceDirectory \u003Ctask-owned-checkout>`\ninstead of `-GatewayChannel` for explicit source changes. Keep the same unique\npatch and work root for each instance's rebuild and ownership-checked removal.\n\nFollow [selection, startup and verification](#select-start-and-verify-each-instance)\nbefore running tests. For helper-built instances, `$packagingRoot` is\n`Join-Path $workRoot 'openclaw-windows-packaging'`; use the build's architecture\nfor the registration\u002Flayout checks. Set `OPENCLAW_NATIVE_GATEWAY_DEV_PATCH`\nbefore launching with `-NoBuild -Isolated -DataDir \u003Ctask-instance-directory>`.\nThat variable reuses the prepared patch without rebuilding it.\n\n`-Isolated` \u002F `-DataDir` isolates Companion's profile, not its build output or\nGateway package. An unqualified `.\\run-app-local.ps1 -Isolated` still selects\nthe shared `npm-latest` patch (or an inherited patch), not a new task instance.\nDo not use it as the isolated real-Gateway test recipe. Build Companion once;\nfor a second Gateway, prepare `t42-beta` serially with the helper, then launch\nit with its own profile after alpha is verified listening. Remove helper-built\ninstances with [the ownership-checking wrapper](#remove-it), passing the same\n`-WorkRoot`.\n\n### Alternative: deploy directly from the packaging repository\n\nThe direct command belongs to **openclaw\u002Fopenclaw-windows-packaging**, not this\nrepository. Start with a clean task-owned clone outside the user profile, under\na trusted parent readable by the isolated account and not writable by unrelated\naccounts. Do not deploy from a main\u002Fshared checkout or relax ACLs to make one work.\nUse its pinned .NET SDK, NativeAOT C++\u002FWindows SDK tools, PowerShell 7 and Developer\nMode prerequisites. The default payload download also needs authenticated `gh`;\nit obtains the bundled Node runtime, without a local Gateway npm\u002Fsource build.\n\nThe minimal examples are `.\\scripts\\Deploy-LocalPackage.ps1 -Patch alpha`, then\n`.\\scripts\\Deploy-LocalPackage.ps1 -Patch beta`. On shared hosts, qualify both\nwith a unique task identifier as below. Replace `t42` and its path consistently:\nnames must be 1 to 15 letters, digits or hyphens, starting and ending with a\nletter or digit, with no whitespace. They are lowercased. Do not reuse another\ntask's patch or rely on the shared helper defaults `npm-latest` \u002F `packaged`.\nAuthorization must cover registration, session setup, startup-task creation and\neventual teardown, not just building source.\n\n```powershell\n$ErrorActionPreference = 'Stop'\n$packagingRoot = 'C:\\OpenClawDev\\t42\\openclaw-windows-packaging'\n$architecture = [Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString().ToLowerInvariant()\n$patches = @('t42-alpha', 't42-beta')\nif (Test-Path -LiteralPath $packagingRoot) { throw 'Choose a new task-owned clone path.' }\ngit clone https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw-windows-packaging.git $packagingRoot\nif ($LASTEXITCODE -ne 0) { throw 'Packaging clone failed.' }\nSet-Location $packagingRoot\nforeach ($patch in $patches) {\n    if (Get-AppxPackage -Name \"OpenClawFoundation.OpenClawGateway-$patch\") {\n        throw \"Patch $patch already exists. Confirm ownership or choose another task name.\"\n    }\n}\n.\\scripts\\Deploy-LocalPackage.ps1 -Patch $patches[0] -Architecture $architecture\n.\\scripts\\Deploy-LocalPackage.ps1 -Patch $patches[1] -Architecture $architecture\n```\n\nExpected: two `OpenClawFoundation.OpenClawGateway-\u003Cpatch>` registrations with\ntheir own `openclaw-\u003Cpatch>` and `clawctl-\u003Cpatch>` aliases, beside the unchanged\nbase package and other patches. Deploy normally runs `clawctl setup`: it\nprovisions\u002Freuses the session, installs Node in the agent profile and enables\nsign-in recovery, but **does not start a listening Gateway**. `-SkipSetup` leaves\nthat setup work outstanding. A setup failure may leave a registration; inspect\nonly the owned patch, then retry or clean it up rather than claiming readiness.\n\nSerialize deployment, rebuild, refresh and unregister operations, including\nacross agents using the same checkout\u002Fcache. The node repo's build helper also\nenforces a machine-wide build\u002Funregister lock; do not assume direct packaging\ncommands have that same guard. Once prepared, separate running instances can\nserve independent tests concurrently. Do not rebuild or remove a layout\u002Fpayload\nwhile a test uses it.\n\n**Cache scope:** rerunning the same patch reuses valid downloads and unchanged\nbuild output. Current packaging keeps payload and Node caches per patch under\n`artifacts\\local-package\\patches\\\u003Cpatch>\\\u003Carchitecture>`; beta's first deployment\ndoes not automatically reuse alpha's payload download. To share an already\nprepared payload, pass the same validated, task-owned immutable\n`-PayloadDirectory \u003Cabsolute-payload-root>` on each deployment. It must contain\n`app` and `payload-metadata.json`. Keep it alive until every referencing patch\nis unregistered; never borrow a cache generation another patch may refresh\u002Fdelete.\nFor npm Latest, Packaged or source-ref selection, use the helper workflows below\nwith explicit unique `-Patch` names and a task-owned `-WorkRoot` instead.\n\n### Select, start and verify each instance\n\nResolve aliases from the actual registration, not a guessed publisher suffix,\nPATH's base `clawctl`, or a shared default endpoint. In the packaging shell,\nrepeat this block for each owned patch:\n\n```powershell\n$patch = 't42-alpha'\n$packages = @(Get-AppxPackage -Name \"OpenClawFoundation.OpenClawGateway-$patch\")\n$expectedLayout = Join-Path $packagingRoot \"artifacts\\local-package\\patches\\$patch\\$architecture\\layout\"\nif ($packages.Count -ne 1 -or -not $packages[0].IsDevelopmentMode -or\n    $packages[0].InstallLocation.TrimEnd('\\') -ine $expectedLayout.TrimEnd('\\')) {\n    throw 'The expected task-owned development registration was not found.'\n}\n$package = $packages[0]\n$aliasRoot = Join-Path $env:LOCALAPPDATA \"Microsoft\\WindowsApps\\$($package.PackageFamilyName)\"\n$clawctl = Join-Path $aliasRoot \"clawctl-$patch.exe\"\n$openclaw = Join-Path $aliasRoot \"openclaw-$patch.exe\"\nif (-not (Test-Path -LiteralPath $clawctl) -or -not (Test-Path -LiteralPath $openclaw)) {\n    throw 'Enable this package''s app execution aliases in Windows Settings, then retry.'\n}\n& $clawctl --version\nif ($LASTEXITCODE -ne 0) { throw 'Owned Gateway version check failed.' }\n```\n\nBuild Companion once from its task-owned **openclaw-windows-node** worktree\nbefore launching tests. In a separate shell at that worktree root, select one\npatch and a fresh task\u002Finstance-specific data directory:\n\n**Setup-local boundary:** `-DataDir` separates Companion's app profile, but\ndoes not redirect setup-local or Local AI state. Without separate overrides,\nthose paths still resolve under the user's normal `%LOCALAPPDATA%\\OpenClawTray`.\nThe recipe below covers Gateway setup and client behavior, not isolated Local\nAI acquisition, removal or concurrent Local AI setup. Before any such operation,\nconfigure and verify a task-owned `OPENCLAW_TRAY_LOCALAPPDATA_DIR` root;\nsetup appends `OpenClawTray`. If the legacy `OPENCLAW_TRAY_LOCAL_DATA_DIR` is\nalso set, align it with that effective directory. Do not use the normal user's\nLocal AI manifest or runtime state as test-owned data.\n\n```powershell\n$env:OPENCLAW_NATIVE_GATEWAY_DEV_PATCH = 't42-alpha'\n.\\run-app-local.ps1 -NoBuild -Isolated -DataDir \"$env:TEMP\\oc-t42-alpha\"\nRemove-Item Env:\\OPENCLAW_NATIVE_GATEWAY_DEV_PATCH\n```\n\nChoose **Install a local native gateway**, then **Set up gateway**. This path\nconfigures and starts the selected patch. Verify alpha is listening before\nlaunching beta with `t42-beta` and `oc-t42-beta`. Companion chooses an available\nport for a new draft, but separate drafts do not reserve ports. Serializing\ninitial setup\u002Fstart avoids both choosing the same unused default. Preserve the\nvariable for any relaunch of that profile; an already-running app cannot switch\npatches. Never share profiles, copy real user credentials, or omit selection and\naccidentally configure the base Gateway.\n\nFor CLI-only testing, configure a distinct `gateway.port` in each owned\ninstance before `& $clawctl gateway-service start --json`, using the resolved\npatched aliases and that scenario's normal configuration flow. Both unconfigured\nGateways otherwise use the upstream default. After either startup path, in the\nmatching packaging shell:\n\n```powershell\n& $clawctl gateway-service status --json\n```\n\nThis command is a status sample, not a readiness assertion. It can return a\nnonzero exit code while still `starting`, and failure JSON can omit `gateway`.\nConversely, `not-started` can return zero. Do not put an immediate throw on every\nnonzero exit into a readiness loop. Retry pending startup within the scenario's\nconfigured startup timeout, inspect each JSON result, and fail explicitly with\nthe last status\u002Ferror if readiness is not reached. Malformed JSON or an explicit\nconfiguration\u002Fownership error is a blocker, not a pending state to ignore.\n\nRequire `integration.kind = isolated-session`, `gateway.state = running`, the\nactual `gateway.port` and non-null `gateway.ownership` for each instance. Match\nthe port\u002Ffamily to that Companion profile and require distinct ports before\nparallel tests. `start` may exit zero with `state = starting`; use bounded status\npolling, not a successful exit alone. Status can probe\u002Fstart an already-recorded\nsession, so it is not a passive host inventory command. A port collision or\nmissing ownership support is a blocker, not permission to kill another listener.\nKeep test artifacts and, when enabled, local MCP endpoints\u002Ftokens separate too.\n\n### Remove only the owned patch\n\nClose only that task's Companion\u002Ftest clients. Re-run the exact registration,\nlayout and alias checks above immediately before teardown. From the same\npackaging checkout and architecture, with `$patch` and `$clawctl` resolved for\nthe instance being removed:\n\n```powershell\n& $clawctl teardown --force\nif ($LASTEXITCODE -ne 0) { throw 'Teardown failed. Keep the registration for recovery.' }\n.\\scripts\\Deploy-LocalPackage.ps1 -Unregister -Patch $patch -Architecture $architecture\nif (Get-AppxPackage -Name \"OpenClawFoundation.OpenClawGateway-$patch\") {\n    throw 'The owned patch is still registered.'\n}\n```\n\nThis is `clawctl-\u003Cname> teardown --force` followed by\n`.\\scripts\\Deploy-LocalPackage.ps1 -Unregister -Patch \u003Cname>`, not wildcard\nremoval or `-ReplaceExistingInstall`. Teardown removes that session\u002Fdata and\nstartup task; unregister preserves remaining package app data and caches.\nDo not delete the checkout\u002Fshared payload until all its registrations are gone.\nIf unregister happened first, restore the same owned patch to reach teardown.\nFor helper-created patches, prefer [the ownership-checking wrapper](#remove-it).\n\nContracts checked against packaging\n[local-development guidance](https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw-windows-packaging\u002Fblob\u002F2062d05176bdc2ff6732fc439986fcefe2f3e4fe\u002Fdocs\u002Flocal-development.md#side-by-side-patched-identities)\nand [deployment owner](https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw-windows-packaging\u002Fblob\u002F2062d05176bdc2ff6732fc439986fcefe2f3e4fe\u002Fscripts\u002FLocalPackage.psm1).\nRecord the actual packaging commit, payload version\u002Fcommit, package families,\ndistinct ports, selected tests\u002Fresults and cleanup outcome for each future run.\nSource inspection is not exercised local\u002Fcloud E2E proof.\n\n## Latest and Packaged development\n\nUse one Companion branch for both Gateway compatibility targets. Do not create or\ncontinually synchronize a `release\u002Fextended-stable` fork.\nThe shorthand commands below describe the launcher's channel defaults for\nsingle-developer compatibility work. For isolated test instances, use\n[unique task-owned builds and patches](#prepare-an-isolated-test-build) instead.\n\n```powershell\n.\\run-app-local.ps1 -Isolated\n.\\run-app-local.ps1 -Isolated -GatewayChannel Packaged\n.\\run-app-local.ps1 -Isolated -GatewayChannel Packaged -PackagingRelease v2026.9.9-msix.0\n```\n\nThe first command resolves npm `latest` and builds\u002Fregisters patch `npm-latest`.\nThe second selects the latest published packaging release and uses patch `packaged`.\nThe third pins a specific published release. GitHub publication does not establish\nStore availability; select the known shipping release explicitly when needed. Both\nretain MSIX isolation and package through `openclaw\u002Fopenclaw-windows-packaging`.\nThe launcher uses separate worktree\u002Fchannel data directories automatically and\nrestores its environment after launch. The Store package is not updated or replaced.\n`-NoBuild` skips the Companion build, not Gateway resolution\u002Fpackaging.\n\nTo prepare only the native Gateway:\n\n```powershell\n.\\scripts\\Build-NativeGatewayFromSource.ps1\n.\\scripts\\Build-NativeGatewayFromSource.ps1 -GatewayChannel Packaged\n.\\scripts\\Build-NativeGatewayFromSource.ps1 -OpenClawNpmVersion 2026.8.35 -Patch pinned\n```\n\nLatest is resolved to an exact npm version on every build. Archive SHA-512\nintegrity, package version and embedded build commit are verified before packaging.\n`source.json` records the selector, exact version, commit, npm integrity and archive\nSHA-256. For reproducible reruns, specify that exact npm version and a packaging\ncommit with `-PackagingRef`. Cached archives are reverified before payload reuse.\nAn incompatible or unavailable release fails explicitly, never falls back to Store\nor the other channel.\n\nPackaged verifies the published architecture-specific MSIX SHA-256 and reads its\nembedded package version, build commit\u002Fbuild ID and Node runtime. Never derive the\nGateway version from the MSIX tag: packaging can ship an older payload under a newer\nMSIX identity. The helper reuses released `app` bytes, checks each file against the\nrelease inventory on extraction and cache reuse, and writes `packaging-release.json`.\nIt checks out the exact packaging tag commit to build the side-by-side development\nlauncher. This is released Gateway payload proof, not installation of the original\nsigned MSIX. `-PackagingRef` and `-PackagingDirectory` cannot override Packaged's\nprovenance. Pin with `-PackagingRelease`; `-Force` re-registers without changing\nthe released payload bytes.\n\nUse `-UseStoreGateway` on the local launcher to test the installed Store runtime.\nAn existing `OPENCLAW_NATIVE_GATEWAY_DEV_PATCH` selects that patch without rebuilding\nit. Like Companion, the launcher trims and lowercases patch names and treats blank\nvalues as unset. Clear the variable before explicitly using `-GatewayChannel`.\nNeither flag changes WSL setup defaults. For a WSL version-specific setup, explicitly\nset `Gateway.Version` to the exact version.\n\nWSL CI follows npm Latest only, matching normal WSL setup. It resolves Latest once\nper workflow and runs each selected setup\u002Fconnect, revocation and network recovery\njob once at that exact version via `OPENCLAW_E2E_GATEWAY_VERSION`. Each job's\nartifact contains `gateway-release.json`. CI does not download a native MSIX or\nduplicate WSL tests against Packaged.\n\nNative Latest\u002FPackaged runtime CI is not implemented. Existing unit\u002Fhelper and\npackaging checks do not prove live isolated-session startup, pairing or recovery;\nnative runtime proof needs a capability-qualified Windows client host. See the\nGateway development and CI matrix in the repository's `DEVELOPMENT.md`.\n\n## Build and register an explicit source ref\n\n```powershell\npwsh -File .\\scripts\\Build-NativeGatewayFromSource.ps1 -OpenClawRef main -Patch source\n```\n\n- First run clones both repos under `%SystemDrive%\\OpenClawDev\\native-gateway-source` and takes\n  roughly 25 to 30 minutes (`pnpm build` dominates). Run it in the background and do not poll.\n- Success ends with `Registered OpenClawFoundation.OpenClawGateway-source_\u003Chash>` and\n  `OpenClaw \u003Cversion> (\u003Cfull sha>)`. Compare the sha with\n  `git ls-remote https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw refs\u002Fheads\u002Fmain`.\n- `main` of both repos moves often. Each rerun fetches them again; a new commit in either\n  repo builds and re-registers a new payload. To get a reproducible rerun, pin both:\n  `-OpenClawRef \u003Cfull sha> -PackagingRef \u003Cfull sha>`. A pinned rerun prints\n  `Reusing payload` and `Already up to date` without rebuilding. ACL validation still\n  walks the checkouts and selected payload; large dependency trees take longer.\n- Other sources: `-OpenClawSourceDirectory \u003Ccheckout>` builds a local checkout as-is\n  (uncommitted changes allowed, always a fresh payload). `-OpenClawPackageDirectory \u003Cdir>`\n  takes an existing `openclaw.tgz` + `source.json` and only builds the payload (about\n  2 to 3 minutes); previous builds leave these under `\u003CWorkRoot>\\packages\\\u003Cid>`.\n- `-Force` builds a new payload and re-registers even when nothing changed.\n- Relative `-WorkRoot` paths are anchored to the invoking PowerShell location before\n  any directory changes.\n- Only one source build or unregister can run on a machine at a time, even across\n  different patches and work roots. A concurrent invocation fails before changing files.\n  Payload installation also uses a fresh per-run staging directory, removed on exit.\n- Prebuilt packages must include valid commit\u002Fhash\u002Fversion metadata. The archive hash\n  is checked before payload-cache reuse, not just on a fresh build.\n\nVerify the registration:\n\n```powershell\nGet-AppxPackage -Name OpenClawFoundation.OpenClawGateway-source |\n    Format-List PackageFamilyName, Version, Publisher, IsDevelopmentMode, InstallLocation\n$alias = \"$env:LOCALAPPDATA\\Microsoft\\WindowsApps\\OpenClawFoundation.OpenClawGateway-source_rfcbke2p71se2\"\n& \"$alias\\clawctl-source.exe\" --version        # Payload line shows the source sha\n& \"$alias\\clawctl-source.exe\" status --json    # integration.kind = isolated-session\n```\n\n## Run Companion against it\n\nUse isolated tray data so the user's real settings and gateways are untouched:\n\n```powershell\n.\\build.ps1\n$env:OPENCLAW_NATIVE_GATEWAY_DEV_PATCH = 'source'\n$env:OPENCLAW_FORCE_ONBOARDING = '1'\n.\\run-app-local.ps1 -NoBuild -DataDir \"$env:TEMP\\oc-devgw-source\"\n```\n\nIn setup choose **Install a local native gateway**, then **Set up gateway**. Expected:\nall four native steps complete and **Connect your AI** loads from the source-built Gateway.\n`\u003Cdata-dir>\\gateways\\native-setup-draft.json` records\n`PackageFamilyName = OpenClawFoundation.OpenClawGateway-source_rfcbke2p71se2`, and\n`clawctl-source gateway-service status` reports `[ok] listening` on the recorded port.\nNo `winget.exe` should start. Clear both variables afterwards.\n\nThe variable must be set in the shell that launches Companion; a running Companion does not\npick it up. Profiles created this way resolve only while the variable names the same patch.\n\n## Remove it\n\n```powershell\npwsh -File .\\scripts\\Build-NativeGatewayFromSource.ps1 -Unregister -Patch source\n```\n\nUse `-Patch npm-latest` or `-Patch packaged` for the channel builds.\nUnregister always requires the explicit patch. This runs the selected patch's\n`clawctl-\u003Cpatch> teardown --force` (removes the isolated session, Gateway records and\nagent profile), then unregisters. The Store package stays. Payloads and checkouts under the\nwork root are kept; delete them manually only after unregistering. Pass the same\n`-WorkRoot`\u002F`-PackagingDirectory`\u002F`-Architecture` used to register, or the ownership check\nrefuses before teardown.\n\n## Pitfalls\n\n- **Never put the work root or packaging checkout under the user profile.** The Gateway runs as\n  a separate isolated agent account that must read the payload through every parent folder;\n  under `C:\\Users\\\u003Cyou>` Node fails with `EPERM ... lstat 'C:\\Users\\\u003Cyou>\\AppData'` and setup\n  reports \"OpenClaw could not read the effective Gateway configuration\". The script refuses\n  such paths. Do not \"fix\" it with ACL grants.\n- **Build trees must not be writable by other accounts.** Newly created work directories\n  have protected ACLs: the current user, Administrators and SYSTEM can write; other\n  authenticated accounts, Users and application-package groups get read\u002Fexecute only.\n  Existing trees, supplied checkouts and\n  prebuilt packages are checked, including linked targets and replaceable ancestors.\n  Unsafe paths are rejected without changing their ACLs. Use a fresh root under a trusted\n  parent (for example `C:\\OpenClawSourceSafe`), not another child of an unsafe directory.\n  For an existing registration, have an administrator verify its files and repair its\n  permissions before retrying unregister. Do not execute potentially modified aliases\n  merely to bypass the check.\n- **Never move or delete the work root while registered.** The layout links the payload with a\n  junction. Moving keeps the old ACLs (the agent account loses access); `icacls \u002Freset \u002FT`\n  over the openclaw checkout loops through pnpm symlinks for a long time. Unregister, then\n  rebuild in the new location.\n- **A cancelled source build leaves `openclaw\\.artifacts\\dist-artifacts.lock`.** The next\n  `pnpm build` refuses with \"Could not acquire ... dist-artifacts.lock\". After confirming no\n  build process is still running, remove that directory and rerun.\n- **Do not run native setup without the variable on a host whose Store Gateway is in use.** It\n  pairs a new device with that live Gateway. Prove Store resolution without side effects\n  instead (unit tests, or call `NativeGatewayPackageResolver` from a throwaway program).\n- Payloads are architecture-specific. An x64 payload on ARM64 registers but `clawctl setup`\n  fails there (upstream note); build on the target architecture.\n\n## Error messages and what they mean\n\n| Message | Cause | Action |\n|---|---|---|\n| `The development Gateway package ...-\u003Cpatch> is not registered ...` (new setup) | Variable set, patch not registered | Run the build, or clear the variable to use the Store Gateway |\n| `This Gateway profile uses the development Gateway package ...-\u003Cpatch>. Set OPENCLAW_NATIVE_GATEWAY_DEV_PATCH=\u003Cpatch> ...` | Saved profile bound to a patch, variable unset or different | Restart Companion with that variable |\n| `This Gateway profile uses ... which is not registered ...` | Saved profile bound to a patch that was unregistered | Re-register the patch, or remove the gateway in Connection settings and set up again |\n| `OPENCLAW_NATIVE_GATEWAY_DEV_PATCH must be 1 to 15 letters ...` | Invalid variable value | Use lowercase letters, digits, hyphens |\n| `-WorkRoot '...' is inside your user profile ...` | Profile path passed | Use a path such as `C:\\OpenClawDev` |\n| `The package-qualified aliases were not found ...` | App execution aliases disabled | Enable them in Settings > Apps > Advanced app settings > App execution aliases |\n| `Another native Gateway source build or unregister is running ...` | Shared build\u002Fregistration resources are locked | Wait for that operation to finish, then retry |\n| `Native Gateway build path ... grants write or replacement access ...` | Another account can modify code or replace a parent | Use a fresh root under a trusted parent, or have an administrator verify and repair the existing tree |\n| `Prebuilt package metadata ... requires ...` | Missing, malformed or truncated provenance | Recreate `source.json` with the package producer; do not invent hashes |\n\n## Proof for PRs\n\nFor PRs that depend on a source-built Gateway, follow `openclaw-proof-validation`: report the\nregistered family, `clawctl-\u003Cpatch> --version`, the commit tested, and focused app-window\nscreenshots. Never publish `gateways.json`, setup drafts beyond family and port, tokens, or\nidentity files.\n",{"name":5,"description":7},"main","a4dd026cc5f85a444a0fcd05eef5b86282dbda8c",".agents\u002Fskills\u002Fnative-gateway-from-source",348,"https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw-windows-node","https:\u002F\u002Fopenclaw.ai","https:\u002F\u002Fgithub.com\u002Fopenclaw","Your personal, open source AI assistant.","2026-11-14 02:54:19",{"source":8,"skillName":5,"commands":58,"prompt":68,"zipAvailable":69},[59,62,65],{"tool":60,"command":61},"npx","npx skills add openclaw\u002Fopenclaw-windows-node --skill native-gateway-from-source",{"tool":63,"command":64},"bunx","bunx skills add openclaw\u002Fopenclaw-windows-node --skill native-gateway-from-source",{"tool":66,"command":67},"pnpm","pnpm dlx skills add openclaw\u002Fopenclaw-windows-node --skill native-gateway-from-source","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw-windows-node\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fnative-gateway-from-source\u002FSKILL.md",true,[],[72,95,112,130,146,166],{"skillNo":73,"name":74,"nameZh":6,"description":75,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":76,"categories":77,"keywords":78,"publishedAt":43},"01M6KZCXK5PCYWWW5FCVDYPAXK","retrigger-flaky-ci","Triage failed CI on a pull request or the active branch, decide whether the failures come from its changes, and rerun only failures that are unrelated. Use when asked to retrigger, rerun, or kick CI on a PR with failing checks.","https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw-windows-node\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fretrigger-flaky-ci\u002FSKILL.md",[],[79,80,81,82,83,84,85,86,37,87,88,89,90,91,92,93,29,94],"retrigger flaky ci","ci","when","unrelated","failing","rerun","use","triage","decide","request","active","pull request","pr","changes","branch","pull",{"skillNo":96,"name":97,"nameZh":6,"description":98,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":99,"categories":100,"keywords":101,"publishedAt":43},"01M698QMQN5TQES4R7ZPTYAZF5","technical-documentation","Write, review, or restructure Windows node documentation and agent instructions using current source, task-focused explanations, and explicit fact preservation.","https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw-windows-node\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Ftechnical-documentation\u002FSKILL.md",[],[102,103,104,105,30,24,106,107,108,109,110,111],"technical documentation","technical","documentation","agent instructions","preservation","node","write","instructions","review","task",{"skillNo":113,"name":114,"nameZh":6,"description":115,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":116,"categories":117,"keywords":118,"publishedAt":43},"01M698QKPXJ8ZG34MYHPPCAT4T","pr-simplify","Simplify your own Windows-node change to its smallest complete fix while preserving distinct regressions, platform contracts, and required proof. Use after implementation before PR preparation, after large repairs, or when asked to shrink a change or remove slop.","https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw-windows-node\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fpr-simplify\u002FSKILL.md",[],[119,91,120,121,122,123,124,125,107,126,81,85,127,128,39,30,129],"pr simplify","simplify","contracts","slop","proof","implementation","preparation","change","fix","complete","platform",{"skillNo":131,"name":132,"nameZh":6,"description":133,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":134,"categories":135,"keywords":137,"publishedAt":43},"01M698QJEA384YPM8R9CPZ1YFD","openclaw-testing","Choose proportional OpenClaw Windows node tests, builds, packaging checks, and runtime proof, then diagnose failures without weakening required gates.","https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw-windows-node\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fopenclaw-testing\u002FSKILL.md",[136],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},[138,9,139,30,123,107,140,141,142,143,38,144,145],"testing","openclaw testing","gates","runtime proof","tests","choose","runtime","diagnose",{"skillNo":147,"name":148,"nameZh":6,"description":149,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":150,"categories":151,"keywords":155,"publishedAt":43},"01M698QH7JVVA09769ER9P2TKY","openclaw-proof-validation","Plan and collect OpenClaw Windows validation\u002Fproof: tests, rubber-duck review, UI evidence, MCP output, and gateway runtime proof.","https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw-windows-node\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fopenclaw-proof-validation\u002FSKILL.md",[152],{"categoryNo":153,"categoryName":154,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",[156,9,157,123,158,30,26,159,144,160,161,162,163,164,110,141,142,165],"openclaw proof validation","validation","evidence","MCP","duck","ui","ui evidence","plan","output","collect",{"skillNo":167,"name":168,"nameZh":6,"description":169,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":9,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":170,"categories":171,"keywords":177,"publishedAt":43},"01M698QFXW9PDK8YZ467MBW5P1","openclaw-debugging","Debug OpenClaw Windows Companion, setup, Gateway connection, node capabilities, packaged permissions, updates, installers, and system.run by selecting the failing boundary and proof path before changing code.","https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Fopenclaw-windows-node\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fopenclaw-debugging\u002FSKILL.md",[172],{"categoryNo":173,"categoryName":174,"taxonomyType":175,"taxonomyTypeDesc":176},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[178,179,9,30,180,123,181,182,183,184,26,185,186,107,187,188,189,190,191,83],"openclaw debugging","debugging","setup","connection","boundary","debug","system","path","companion","run","permissions","capabilities","code","updates"]