fix(windows): resolve the Job Object native helper outside the daemon bootstrap - #2
Merged
Merged
Conversation
… bootstrap `localapp server run`, `localapp dev`, and browser opening all spawn owned process trees, which on Windows needs the packaged native helper for atomic Job Object ownership. The helper was resolved only from LOCALAPP_RELEASE_PATH, which just the daemon bootstrap exports, so a direct shell invocation always failed. Resolve it from LOCALAPP_RELEASE_PATH first, then from the CLI's own artifact directory (the parent of bin/localapp.mjs), and accept only a candidate that exists. When neither yields a helper, fail closed with the structured native_adapter_unsupported code; a bare Error was flattened to command_failed by the CLI entrypoint, hiding the cause. Reported symptom was `localapp server start` aborting with native_adapter_failed. Reproduced against the installed 0.2.1 helper: it wrote HKCU\Software\Classes\localapp and the Start Menu shortcut, then exited 0xC0000374. Clearing APPDATA returns exit 1 instead, which isolates the crash to the COM shortcut-identity step after the registry write, and 0.2.2 already fixed it (the PROPVARIANT drop freed a Rust Vec through CoTaskMemFree). Pin that fix so it cannot regress silently.
…tests The public source gate pins each credential-scan exception to the reviewed file content by sha256, so editing packages/localapp/tests/native-adapter.test.ts invalidated its exception and failed the export gate. The only credential-keyed assignment in that file is unchanged (`LOCALAPP_API_KEY` in the redaction fixture) before and after the edit, so the entry is re-reviewed with the new digest rather than narrowed or dropped.
The Platform regression workflow never built packages/web, so verification-isolation ran against a Server whose Platform Shell static export was missing. The app entry then answered 404, and the check reported a missing shell as a failed verification boundary: all 46 runs of this workflow failed, back to the commit that introduced it. ci.yml builds packages/web before running the same suite, which is why the identical check was green there. Confirmed by building packages/web locally: verification-sessions.test.ts goes from 1 failed to 8 passed with no product change. The suite's build prerequisites are now asserted so the workflow cannot silently drop them again, and documented in the benchmark README.
The export gate pins every reviewed scan exception to the digest of the file it pins, so touching a baselined file fails the gate until the digest is refreshed. That cost two CI round trips on this branch because nothing reported it locally. Add a check that every baseline exception still matches its file. It hashes LF-normalized content because the export hashes committed content, while a Windows checkout materializes the same file with CRLF; the normalization is a no-op on Linux. Verified on the real baseline: all 29 exceptions match, and the check reports the two stale digests created by editing the test that carries it. Refresh those digests, plus the one for scripts/release-workflow.node-test.mjs that the workflow guard commit invalidated. The flagged content is unchanged in each file: the baseline review covers the same canonical package assertions and the same credential fixture as before.
Patodo
added a commit
that referenced
this pull request
Sep 17, 2026
Windows helper resolution fix (#2) plus the Platform regression workflow fix: `localapp server run` and browser opening now resolve the packaged Job Object helper from the CLI's own artifact, and the deterministic suite builds the Platform Shell before it runs. Version-bound test assertions move to 0.2.5 and the reviewed public source baseline digests are re-recorded for the two files this touches. The flagged content in both files is unchanged: the same three canonical package markers and the same apiKey fixture as before.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
处理 #1 的第二部分,并修复了一条长期红灯的 CI 流水线。
背景:issue 里的两件事状态不同
localapp server start崩溃(native adapter--register以0xC0000374退出,daemon 永不安装)482e800,Rust 侧 PROPVARIANT double-free),本 PR 只补回归守卫localapp server run在 Windows 上无法按 README 直接使用、且只报command_failed崩溃部分:已在 0.2.2 修复(附复现证据)
在报告者机器上直接对真实二进制做对照实验:
--register --config <真实配置>0xC000037400另外修正 issue 里的一张表:报告者认为「config 位于
%TEMP%就不崩」,据此推断崩溃由路径位置决定。实测同一份配置放在临时目录、或放到支持目录下的第二个文件,三次全部崩溃,位置无关。崩溃点定位:把
APPDATA置空后退出码变为1且不崩溃。由于APPDATA检查是注册表写入之后的下一行代码,这把崩溃锁死在 COM 快捷方式身份注册段,与482e800的结论一致。0.2.1 的二进制也确实在快捷方式写成功之后才崩。本 PR 在
native-adapter.node-test.mjs增加源码断言把该修复钉住(已验证这些断言在482e800之前的main.rs上会失败)。Windows helper 解析(主要修复)
LOCALAPP_RELEASE_PATH只由 daemon bootstrap 导出,而 helper 解析只认它。0.2.4 的 bundle 仍然如此(bin/localapp.mjs:29802),因此不只是server run,openValidatedExternalUrl(打开浏览器)同样必然失败。src/artifact-directory.ts:把「CLI 自身所在发行 artifact 目录」抽出为独立模块(同时修正 bundle 内import.meta.url的相对深度)。resolveWindowsNativeExecutable():依次从LOCALAPP_RELEASE_PATH、CLI 自身 artifact 目录解析 helper,且只在文件存在时才采用,仍然失败关闭。spawnOwnedProcess改为抛native_adapter_unsupported;裸Error会被入口压成command_failed。用真实 0.2.4 release artifact 做过端到端验证:解析路径与包内布局一致,并经该 helper 真实完成一次
--job-owner的 Job Object 受控启动。CI:Platform regression 长期红灯的根因
Platform regression工作流的 46 次运行全部失败,可追溯到引入它的那次提交。失败项固定是verification-isolation:根因不在产品代码:该工作流只构建了
packages/server-core,从未构建packages/web。而verification-isolation会驱动生产应用入口,该入口从 Next.js 静态导出packages/web/out/platform-shell/placeholder/placeholder.html读取 Platform Shell;缺失时路由走 catch 分支返回 404,于是「缺 Shell」被报成了「验证边界失效」。ci.yml在跑同一个套件前会构建packages/web,这就是同一个检查在verify里是绿的原因。实测确认:本地构建
packages/web后,verification-sessions.test.ts从 1 failed 变为 8 passed,无需改动任何产品代码。修复:工作流补上 web 构建;
release-workflow.node-test.mjs增加断言锁住「先构建 Platform Shell、再跑确定性套件」的顺序(已验证该断言对旧工作流会失败);benchmarks/agent-first-run/README.md补记前置构建。提交
078c9ae7fe2a4enative-adapter.test.ts的基线摘要943cbda2c741a3验证
CI 全绿:
deterministic-platform-regressionverifysecrets本地:
tsc --noEmit通过;node --test scripts/native-adapter.node-test.mjs5 passed / 0 failed;process-tree.test.ts12 passed;构建packages/web后verification-sessions.test.ts8 passed;test:public-source通过且基线 29 条例外全部一致。未做完整
localapp server start验收:会在本机注册 Windows 计划任务并拉起 daemon。本机无 Rust 工具链,Rust 侧结论基于已发布二进制验证。Windows 本地已知失败(与本次改动无关,HEAD 上同样失败)
pnpm test:platform-regression的capability-contract与server-core-capability-parity:core.autocrlf=true使工作树为 CRLF,哈希与记录值不符;Linux CI 通过。test:release-workflow2 条失败(CRLF 正则匹配release.yml、new URL(...).pathname与path.join拼出E:\E:\...)。test:windows-release-script1 条失败(同一.pathname路径 bug)。后两类去掉
new URL(...).pathname、改用fileURLToPath即可修复,未纳入本 PR。未包含
localapp-native.exe任何代码。release.yml的守卫与docs/npm-release.md的「维护者手动发布」边界保持不变。