mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
test(windows): enforce native coverage
This commit is contained in:
@@ -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: 926eec04cff63aaf25d1e85b3dcbc41464f25660
|
||||
2026-08-08-native-windows-pull-request-ci.zh.md: 8728f0eb08adcb1501f036bb19ff523ded406ccc
|
||||
2026-08-08-native-windows-pull-request-ci.md: 0249730adcba307123af17bf89f71c90d5ea18e2
|
||||
2026-08-08-native-windows-pull-request-ci.zh.md: 0b3755d5757b6ba7721caec9b45e72ac29c40ad1
|
||||
|
||||
@@ -8,11 +8,13 @@ English | [中文](2026-08-08-native-windows-pull-request-ci.zh.md)
|
||||
|
||||
The required pull-request Windows verdict must protect behavior that depends on the operating system, not only toolchain branches selected by `process.platform`. The Wine lane executed Windows Node and PE binaries over a Linux kernel and case-sensitive ext4, required a hoisted dependency layout and host-created symlinks, and omitted NTFS, DACL, ConPTY, crash-durability, and the broader observational Windows inventory. With the native serial references disabled, ordinary CI had no real Windows-kernel signal.
|
||||
|
||||
The coverage audit found that PR #499 had restored deterministic native-Windows LSP coverage, but a later GUI branch replayed its three temporary source exclusions from stale branch state. The current LSP fixtures skip only genuinely POSIX primitives and otherwise exercise the supported Windows process, transport, and lifecycle paths, so excluding `connection.ts`, `index.ts`, and `instance.ts` hid supported behavior rather than a platform limitation.
|
||||
|
||||
## Decision
|
||||
|
||||
The required `windows` job in [ci.yml](../../../../.github/workflows/ci.yml) runs on GitHub's standard `windows-2025` image under native PowerShell. It enables Developer Mode for workspace symlinks, provisions the repository-pinned pnpm through `pnpm/action-setup`, performs an immutable install without a transferred store archive, and runs `pnpm run check:ci:windows-complete`. The stable `windows` job id remains a dependency of `all checks passed`; its display name is `windows node 24 / native complete`.
|
||||
|
||||
The aggregate keeps workspace build and production-site failures blocking while reporting the broader static, documentation, package, and built-artifact portability inventory as observational. One runner shares installation and build outputs across those gates, and serial gate and publint worker bounds keep the standard image within a predictable resource envelope. Linux remains the owner of duplicate lint, coverage, and snapshot enforcement until those suites have an explicit native-Windows contract.
|
||||
The aggregate keeps workspace build, production-site, and 100%-per-file coverage failures blocking while reporting the broader static, documentation, package, and built-artifact portability inventory as observational. Coverage has a four-worker budget; one runner shares installation and build outputs across those gates, and serial gate and publint worker bounds keep the standard image within a predictable resource envelope. Linux remains the owner of duplicate lint and snapshot enforcement.
|
||||
|
||||
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.
|
||||
|
||||
@@ -30,4 +32,4 @@ Wine-only infrastructure is absent from the supported workflow: there is no apt-
|
||||
|
||||
Pull requests receive a real NT kernel, NTFS, PowerShell, Windows process, and native addon signal before the aggregate can pass. The job is slower than the Wine compatibility lane and can queue on Windows capacity, but its green result now describes the supported host rather than an approximation.
|
||||
|
||||
Removing the Wine cache producer and local script deletes a separate install topology and its recurring compatibility failures. Native coverage and snapshots remain a named gap rather than being implied by the job name; they require their own tested contract before becoming part of this required lane.
|
||||
Removing the Wine cache producer and local script deletes a separate install topology and its recurring compatibility failures. Native coverage now runs through the same required job and enforces the repository's per-file threshold without Windows-only source exclusions for supported LSP behavior. Native snapshots remain a named gap rather than being implied by the job name; they require their own tested contract before becoming part of this required lane.
|
||||
|
||||
@@ -8,11 +8,13 @@ Status: implemented
|
||||
|
||||
拉取请求必需的 Windows 判定必须为依赖操作系统的行为提供保障,而不能只覆盖由 `process.platform` 选择的工具链分支。Wine 通道在 Linux 内核与区分大小写的 ext4 之上执行 Windows Node 和 PE 二进制文件,要求采用 hoisted 依赖布局和由宿主侧创建的符号链接,也没有覆盖 NTFS、DACL、ConPTY、崩溃持久性与更广泛的观测性 Windows 清单。原生串行参考流程停用期间,常规 CI 没有任何真实的 Windows 内核信号。
|
||||
|
||||
覆盖率审计发现,PR(Pull Request)#499 已恢复确定性的原生 Windows LSP 覆盖率,后续的 GUI 分支却回放了陈旧分支状态中的 3 个临时源码排除项。当前的 LSP fixture(测试前置数据)只跳过真正属于 POSIX 的原语,除此之外还会检验受支持的 Windows 进程、传输与生命周期路径;因此,排除 `connection.ts`、`index.ts` 和 `instance.ts` 所掩盖的是受支持的行为,而非平台限制。
|
||||
|
||||
## 决策
|
||||
|
||||
[ci.yml](../../../../.github/workflows/ci.yml) 中必需的 `windows` 作业在 GitHub 标准 `windows-2025` 镜像上使用原生 PowerShell 运行。该作业为工作区符号链接启用开发人员模式,通过 `pnpm/action-setup` 提供仓库固定版本的 pnpm,在不传输 store 归档的情况下执行不可变安装,并运行 `pnpm run check:ci:windows-complete`。稳定的 `windows` 作业 ID 仍是 `all checks passed` 的依赖项;其显示名称为 `windows node 24 / native complete`。
|
||||
|
||||
聚合作业继续将工作区构建与生产网站故障设为阻断项,同时将更广泛的静态检查、文档、包和构建产物可移植性清单作为观测项报告。同一台运行器在这些门禁之间共享安装结果与构建输出,串行门禁与 publint 工作线程上限使标准镜像的资源使用保持在可预测范围内。在这些套件明确建立原生 Windows 契约之前,重复执行的 lint、覆盖率与快照强制检查仍由 Linux 负责。
|
||||
工作区构建、生产网站和逐文件 100% 覆盖率检查失败时,聚合作业会继续阻断;更广泛的静态检查、文档、包和构建产物可移植性清单则作为观测项报告。覆盖率检查的工作线程预算为 4 个;同一台运行器在这些门禁之间共享安装结果与构建输出,串行门禁与 publint 工作线程上限使标准镜像的资源使用保持在可预测范围内。重复执行的 lint 与快照强制检查仍由 Linux 负责。
|
||||
|
||||
受支持的工作流不含 Wine 专属基础设施:不存在 apt 缓存生产者、兼容性脚本、对仓库快照执行的 hoisted 安装、Windows Node 下载或本地 `check:windows-wine` 命令。[已归档的 Wine 实验](../../archived/process/2026-07-27-wine-windows-gates-experiment.md)仍作为其实测延迟与保真度取舍的历史证据,而非当前执行路径。
|
||||
|
||||
@@ -30,4 +32,4 @@ Status: implemented
|
||||
|
||||
在聚合作业通过之前,拉取请求会获得来自真实 NT 内核、NTFS、PowerShell、Windows 进程和原生插件的信号。该作业比 Wine 兼容性通道更慢,也可能因 Windows 容量而排队,但其绿灯结果描述的是受支持的宿主,而非近似环境。
|
||||
|
||||
移除 Wine 缓存生产者和本地脚本后,独立的安装拓扑及其反复出现的兼容性故障也随之消失。原生 Windows 覆盖率与快照仍是明确列出的缺口,不会仅由作业名称暗示已经纳入;二者都必须先建立各自经过测试的契约,才能成为该必需通道的一部分。
|
||||
移除 Wine 缓存生产者和本地脚本后,独立的安装拓扑及其反复出现的兼容性故障也随之消失。原生 Windows 覆盖率现在通过同一项必需作业运行,并强制执行仓库的逐文件覆盖率阈值;该覆盖率门禁不会为受支持的 LSP 行为设置仅针对 Windows 的源码排除项。原生 Windows 快照仍是明确列出的缺口,不会仅由作业名称暗示已经纳入;必须先为其建立专门且经过测试的契约,才能成为该必需通道的一部分。
|
||||
|
||||
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
@@ -302,7 +302,7 @@ jobs:
|
||||
|
||||
# One standard Windows box shares setup across the required build/site checks
|
||||
# and the observational portability inventory. Serial worker bounds keep this
|
||||
# recovery path portable; Linux owns duplicate lint, coverage, and snapshots.
|
||||
# recovery path portable; Linux owns duplicate lint and snapshots.
|
||||
# See the native-Windows pull-request CI decision:
|
||||
# .agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.md
|
||||
windows:
|
||||
@@ -310,6 +310,7 @@ jobs:
|
||||
runs-on: windows-2025
|
||||
name: windows node 24 / native complete
|
||||
env:
|
||||
DSH_COVERAGE_MAX_WORKERS: '4'
|
||||
DSH_GATE_CONCURRENCY: '1'
|
||||
DSH_PUBLINT_CONCURRENCY: '1'
|
||||
steps:
|
||||
|
||||
@@ -42,12 +42,21 @@ describe('CI workflow', () => {
|
||||
|
||||
expect(windows['runs-on']).toBe('windows-2025')
|
||||
expect(windows.name).toBe('windows node 24 / native complete')
|
||||
expect(windows.env).toMatchObject({ DSH_COVERAGE_MAX_WORKERS: '4' })
|
||||
expect(commandSteps).toHaveLength(3)
|
||||
expect(commandSteps.every(step => step.shell === 'pwsh')).toBe(true)
|
||||
expect(commandSteps.map(step => step.run)).toContain('pnpm run check:ci:windows-complete')
|
||||
expect(JSON.stringify(windows)).not.toMatch(/wine/i)
|
||||
expect(workflow.jobs).not.toHaveProperty('wine-apt-cache')
|
||||
})
|
||||
|
||||
it('keeps supported LSP source under native Windows coverage', () => {
|
||||
const config = readFileSync(resolve(root, 'vitest.config.ts'), 'utf8')
|
||||
|
||||
expect(config).not.toContain('packages/lsp/lsp-local/src/connection.ts')
|
||||
expect(config).not.toContain('packages/lsp/lsp-local/src/index.ts')
|
||||
expect(config).not.toContain('packages/lsp/lsp-local/src/instance.ts')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Issue lifecycle workflow', () => {
|
||||
|
||||
@@ -83,6 +83,15 @@ describe('gate graph validation', () => {
|
||||
expect(ids).toContain('public-repository-links')
|
||||
})
|
||||
|
||||
it('keeps native Windows coverage blocking while portability inventory remains observational', () => {
|
||||
const gates = withPnpmEntrypoint(() => gatesForMode('ci-windows-complete'))
|
||||
const byId = new Map(gates.map(subject => [subject.id, subject]))
|
||||
|
||||
expect(byId.get('coverage')?.allowFailure).not.toBe(true)
|
||||
expect(byId.get('coverage-exempt-heavy')?.allowFailure).not.toBe(true)
|
||||
expect(byId.get('duplication')?.allowFailure).toBe(true)
|
||||
})
|
||||
|
||||
it.each([
|
||||
['empty', [], /gate graph has no gates/],
|
||||
['duplicate ids', [gate('same'), gate('same')], /duplicate gate id "same"/],
|
||||
|
||||
@@ -434,6 +434,7 @@ function ciWindowsCompleteGates(): Gate[] {
|
||||
return [
|
||||
pnpmScript('build', 'build'),
|
||||
pnpmScript('windows-site', 'docs:build', { label: 'production site' }),
|
||||
...coverageGates(),
|
||||
...observational,
|
||||
]
|
||||
}
|
||||
@@ -441,7 +442,7 @@ function ciWindowsCompleteGates(): Gate[] {
|
||||
function ciWindowsObservationalGates(): Gate[] {
|
||||
return [
|
||||
...ciStaticGates({ ownsBuild: true }),
|
||||
// Linux owns required lint, coverage, and snapshots; Windows omits those duplicates.
|
||||
// Linux owns required lint and snapshots; Windows omits those duplicates.
|
||||
pnpmScript('duplication', 'duplication'),
|
||||
pnpmScript('publint', 'publint', { needs: ['build'] }),
|
||||
pnpmScript('node-next-types', 'verify-node-next-types', {
|
||||
|
||||
@@ -37,17 +37,7 @@ const windowsUnsupportedPackages = process.platform === 'win32'
|
||||
]
|
||||
: []
|
||||
|
||||
// These files retain 100% per-file coverage on POSIX, where their process-pipe and terminal timing
|
||||
// tests are deterministic; Windows skips those cases and must not fail solely on their uncovered paths.
|
||||
const windowsCoverageExclusions = process.platform === 'win32'
|
||||
? [
|
||||
'packages/lsp/lsp-local/src/connection.ts',
|
||||
'packages/lsp/lsp-local/src/index.ts',
|
||||
'packages/lsp/lsp-local/src/instance.ts',
|
||||
]
|
||||
: []
|
||||
|
||||
// Mirrors windowsCoverageExclusions: pwsh-local's run/start/lifecycle suites
|
||||
// pwsh-local's run/start/lifecycle suites
|
||||
// self-skip without a real pwsh (executor.spec.ts hasPwsh), leaving this file
|
||||
// far below per-file 100% on pwsh-less hosts; the exemption keeps those hosts
|
||||
// green while CI runners ship pwsh and still enforce the full bar. The probe
|
||||
@@ -226,7 +216,6 @@ export default defineConfig({
|
||||
'packages/ui/commands/src/invariant.ts',
|
||||
'packages/session-projection/session-projection/src/index.ts',
|
||||
...windowsUnsupportedPackages.map(path => `${path}/src/**/*.ts`),
|
||||
...windowsCoverageExclusions,
|
||||
...pwshCoverageExclusions,
|
||||
],
|
||||
// 100% or it doesn't merge (docs/testing.md: excessive tests are welcome).
|
||||
|
||||
Reference in New Issue
Block a user