fix(windows): stabilize native coverage watchers

This commit is contained in:
Tianyi Cui
2026-08-08 21:26:38 +08:00
parent ded7f8ffd1
commit b1ccca71ef
9 changed files with 58 additions and 30 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.md
2026-08-08-native-windows-pull-request-ci.md: c824111cbd3d5f4126b0a383c99d0600b3e33ecf
2026-08-08-native-windows-pull-request-ci.zh.md: 76e719d073669e4af551224ebf04bbf9284126a2
2026-08-08-native-windows-pull-request-ci.md: a798aa906c2e22bceb021d1a95c081e9fa534d7c
2026-08-08-native-windows-pull-request-ci.zh.md: 58fed00e1f324a8d61af179421c7bc5703c25678

View File

@@ -22,6 +22,8 @@ The coverage follow-up then exercised the serial heavy suites on the native host
The blocking coverage gate exposed two more fixture contracts that had never run on the native lane. The JSONL materialization fault now asserts the structured filesystem error code because the Windows durable-directory implementation owns an `ENOTDIR` code without copying it into human prose. The ACP teardown ladder now uses Node children instead of assuming a POSIX shell and asserts Windows' force-termination outcome rather than POSIX signal names; POSIX still proves the `SIGTERM` and `SIGKILL` tiers. Those suites load native bindings or own real process trees, so the Windows thread pool runs them in the existing fork-isolated project while still merging their coverage into the same per-file threshold.
After the branch incorporated a newer `master`, the next native coverage run found the last uncatalogued watcher path and a stress-test budget. `skill-local` opened existing Chokidar roots with the configured spelling, so `%TEMP%` could still reach libuv through `C:\\Users\\RUNNER~1` while events used the long directory name; its root and ancestor modes now share the canonical watch-path contract, while discovery retains the configured path. The newly added 10,000-session descendant walk also exceeded Vitest's default timeout under Windows coverage instrumentation, so that unchanged stack-safety workload has an explicit twenty-second stress-test budget rather than a smaller depth or a platform skip.
The next exact-head run exposed one remaining observational built-bin failure: its lifecycle fixtures used `process.kill()` or `subprocess.kill()` to send `SIGTERM`, which unconditionally terminates a Windows target instead of delivering the registered process event for graceful disposal. POSIX acceptance still sends the real signal. On Windows the fixture requests that same registered event from inside the child, directly for a self-terminating probe and through a marker for parent-controlled lifecycle cases, so the assembled shutdown and disposal path remains covered without asserting an operating-system facility that does not exist. That acceptance then exposed the underlying early-shutdown race: a signal could dispose the root after boot returned while fallback HMR watchers were mounting, and the resulting inactive-service error escaped as a boot failure. Post-boot setup now admits work only while the authoritative root fiber is active and contains a concurrent setup error only when the same invocation's recorded signal already owns shutdown; unrelated HMR failures remain loud.
Wine-only infrastructure is absent from the supported workflow: there is no apt-cache producer, compatibility script, hoisted snapshot install, Windows Node download, or local `check:windows-wine` command. The [archived Wine experiment](../../archived/process/2026-07-27-wine-windows-gates-experiment.md) remains historical evidence for its measured latency and fidelity trade-offs, not a current execution path.

View File

@@ -22,6 +22,8 @@ Status: implemented
这项阻断覆盖率门禁又暴露出两项从未在原生通道上运行过的 fixture 契约。JSONL 实体化故障场景现在断言结构化文件系统错误码,因为 Windows 的持久目录实现拥有 `ENOTDIR` 错误码却不会将其复制进人类可读文本。ACPAgent Client Protocol拆卸阶梯现在使用 Node 子进程,不再假定 POSIX shell并断言 Windows 的强制终止结果而非 POSIX 信号名称POSIX 仍会证明 `SIGTERM``SIGKILL` 两级。这些套件会加载原生绑定或拥有真实进程树,因此 Windows 线程池会让它们在现有的 fork 隔离项目中运行,同时仍将这些套件的覆盖率汇入同一项逐文件阈值。
分支纳入更新的 `master` 后,下一次原生覆盖率运行发现了最后一条未纳入统一契约的 watcher 路径和一项压力测试预算。`skill-local` 曾以配置时的路径拼写打开现有 Chokidar 根,因此 `%TEMP%` 仍可能以 `C:\\Users\\RUNNER~1` 进入 libuv而事件使用长目录名现在它的根模式与祖先模式共用规范化监听路径契约发现过程仍保留配置路径。新增的 10,000 会话后代遍历在 Windows 覆盖率插桩下还会超过 Vitest 默认超时,因此该栈安全工作负载保持原有规模并获得显式的 20 秒压力测试预算,而不是缩小深度或按平台跳过。
下一次分支头精确运行暴露出观测项中剩余的一项 built-bin 故障:其生命周期 fixture 通过 `process.kill()``subprocess.kill()` 发送 `SIGTERM`;在 Windows 上这种调用会无条件终止目标进程而不会交付为优雅释放所注册的进程事件。POSIX 验收仍发送真实信号。在 Windows 上fixture 改为从子进程内部请求同一个已注册事件自终止探测直接请求由父进程控制的生命周期场景则通过标记请求因此完整组装后的关闭与释放路径仍得到覆盖也无需断言操作系统提供了本不存在的信号机制。该项验收随即暴露出底层的提前关闭竞态boot 返回后,回退 HMR watcher 仍在挂载,此时信号可能对根 fiber 执行 dispose资源释放由此产生的服务未激活错误会逸出并被报告为 boot 失败。boot 后 setup 现在只会在权威根 fiber 仍处于活跃状态时接纳工作;只有当本次调用所记录的信号已取得关闭流程所有权时,才会隔离并发 setup 错误,无关的 HMR 故障仍会响亮失败。
受支持的工作流不含 Wine 专属基础设施:不存在 apt 缓存生产者、兼容性脚本、对仓库快照执行的 hoisted 安装、Windows Node 下载或本地 `check:windows-wine` 命令。[已归档的 Wine 实验](../../archived/process/2026-07-27-wine-windows-gates-experiment.md)仍作为其实测延迟与保真度取舍的历史证据,而非当前执行路径。