docs: scope the local Wine gate to Windows-failure diagnosis only

AGENTS.md and the Wine Agent Note pair state the run policy: CI owns the
everyday win32 signal; run check:windows-wine only while investigating a
known Windows-related failure, and pre-push selection never includes it.
This commit is contained in:
Tianyi Cui
2026-07-27 17:15:37 +08:00
parent 625094905d
commit 8be70e72d2
4 files changed
+5 -5

No files matched your search

@@ -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-07-27-wine-windows-gates-experiment.md
2026-07-27-wine-windows-gates-experiment.md: 918d4ab4a1974c6f8ea4bebeb48025aeecf0ef57
2026-07-27-wine-windows-gates-experiment.zh.md: e1de3395ccd59307b520cb59210923f7fe1a21fd
2026-07-27-wine-windows-gates-experiment.md: fd36a3322b0d63a0fa605ecfcec95c7522b43b25
2026-07-27-wine-windows-gates-experiment.zh.md: 97a54161bb851785a9108cc45d59617e1a449e68
@@ -18,7 +18,7 @@ Dependencies install natively on Linux with `supportedArchitectures` extended to
The lane holds the wall clock of the Linux CI jobs through four levers: the master-refreshed pnpm store cache (restore-only, same key as the Linux jobs), Wine provisioning (apt install, Windows Node download, `wineboot`) running concurrently with `pnpm install`, the two blocking surfaces running concurrently — the same shape `run-gates` gives them on native Windows — and an apt-archive cache keyed on the runner image, seeded from master by the `wine apt cache` job so every pull request restores from the default-branch scope.
The gate logic lives in one script, [scripts/wine-windows-gates.sh](../../../../scripts/wine-windows-gates.sh): the ci.yml job provisions runner state (caches, apt Wine) and calls it, and the optional local gate `pnpm run check:windows-wine` runs the identical script on a developer machine that has Wine installed — one implementation, so local reproduction of a red CI lane needs no translation between environments. The script never mutates the working tree: it snapshots tracked plus untracked-unignored files into a scratch directory, applies the Wine-specific pnpm overrides to the snapshot only, and installs there against the shared store; the Wine prefix and the checksum-verified Windows Node zip persist under `.cache/wine-windows/` so local reruns skip provisioning, with an offline fallback to the newest cached zip when nodejs.org is unreachable.
The gate logic lives in one script, [scripts/wine-windows-gates.sh](../../../../scripts/wine-windows-gates.sh): the ci.yml job provisions runner state (caches, apt Wine) and calls it, and the optional local gate `pnpm run check:windows-wine` runs the identical script on a developer machine that has Wine installed — one implementation, so local reproduction of a red CI lane needs no translation between environments. The local gate is a diagnosis tool, not a routine check: run it only when investigating a known Windows-related failure; CI owns the everyday win32 signal, and [dsh-pre-push-checks](../../../skills/dsh-pre-push-checks/SKILL.md) never selects it. The script never mutates the working tree: it snapshots tracked plus untracked-unignored files into a scratch directory, applies the Wine-specific pnpm overrides to the snapshot only, and installs there against the shared store; the Wine prefix and the checksum-verified Windows Node zip persist under `.cache/wine-windows/` so local reruns skip provisioning, with an offline fallback to the newest cached zip when nodejs.org is unreachable.
Four environment constraints shape the job, each found as a red run: Ubuntu's `wine64` package alone puts nothing on PATH (install `wine`, the dispatcher); Node under Wine cannot attach stdio to the Actions runner's pipes (`Socket open EBADF` at bootstrap — every invocation routes stdio through a file); Wine does not realpath pnpm's isolated-layout Unix symlinks (the hoisted layout above); and Wine cannot create Windows symlinks (`ENOTSUP` from VitePress's `linkVue` — the `vue` link is laid down host-side before the gate).
@@ -18,7 +18,7 @@ Pull request 的 Windows 通道存在的意义是证明两个阻断性 win32 表
该通道靠四个杠杆保持 Linux CI 作业的墙钟:master 刷新的 pnpm store 缓存(只恢复,与 Linux 作业同键)、Wine 供给(apt 安装、Windows Node 下载、`wineboot`)与 `pnpm install` 并发运行、两个阻断表面并发运行——与 `run-gates` 在原生 Windows 上给它们的形状相同——以及按 runner 镜像为键的 apt 归档缓存,由 master 的 `wine apt cache` 作业播种,使每个 pull request 都能从默认分支作用域恢复。
门禁逻辑集中在一个脚本里,[scripts/wine-windows-gates.sh](../../../../scripts/wine-windows-gates.sh)ci.yml 作业只供给 runner 状态(缓存、apt Wine)然后调用它,可选的本地门禁 `pnpm run check:windows-wine` 在装有 Wine 的开发机上运行同一个脚本——单一实现,因此本地复现红色 CI 通道不需要在环境之间做任何转译。脚本从不改动工作树:把被跟踪加未跟踪未忽略的文件快照进一个临时目录,只对快照施加 Wine 特有的 pnpm 覆盖,并在那里对着共享 store 安装;Wine prefix 与校验和验证过的 Windows Node zip 持久存放在 `.cache/wine-windows/` 下,本地重跑跳过供给,nodejs.org 不可达时回退到最新的已缓存 zip。
门禁逻辑集中在一个脚本里,[scripts/wine-windows-gates.sh](../../../../scripts/wine-windows-gates.sh)ci.yml 作业只供给 runner 状态(缓存、apt Wine)然后调用它,可选的本地门禁 `pnpm run check:windows-wine` 在装有 Wine 的开发机上运行同一个脚本——单一实现,因此本地复现红色 CI 通道不需要在环境之间做任何转译。该本地门禁是诊断工具而非例行检查:仅在排查已知的 Windows 相关失败时运行;日常 win32 信号归 CI 所有,[dsh-pre-push-checks](../../../skills/dsh-pre-push-checks/SKILL.md) 也从不选择它。脚本从不改动工作树:把被跟踪加未跟踪未忽略的文件快照进一个临时目录,只对快照施加 Wine 特有的 pnpm 覆盖,并在那里对着共享 store 安装;Wine prefix 与校验和验证过的 Windows Node zip 持久存放在 `.cache/wine-windows/` 下,本地重跑跳过供给,nodejs.org 不可达时回退到最新的已缓存 zip。
四条环境约束塑造了该作业,每条都以一次红色运行被发现:Ubuntu 的 `wine64` 包本身不往 PATH 放任何东西(要装 `wine` 调度器);Wine 下的 Node 无法把 stdio 接到 Actions runner 的管道上(引导期 `Socket open EBADF`——所有调用都经文件中转 stdio);Wine 不对 pnpm isolated 布局的 Unix 符号链接做 realpath(即上文的 hoisted 布局);Wine 无法创建 Windows 符号链接(VitePress 的 `linkVue``ENOTSUP`——`vue` 链接在门禁前由宿主侧铺好)。
+1 -1
View File
@@ -59,7 +59,7 @@ pnpm run typecheck
pnpm run lint
pnpm run duplication # cross-file TypeScript clone detection
pnpm run build # tsc emits lib/types, tsdown bundles runtime
pnpm run check:windows-wine # optional: CI's blocking Windows gates locally (needs wine)
pnpm run check:windows-wine # ONLY when diagnosing a known Windows failure (needs wine); CI owns this signal
pnpm run hygiene # knip + publint + workspace constraints + NodeNext consumer check
pnpm run doc-sync # all documentation gates; leaf list in scripts/run-gates.ts
pnpm run website:build # VitePress build (doubles as dead-link check)