From 3073107ec4f70a67f886ae153dc28d7ea09bd69d Mon Sep 17 00:00:00 2001 From: Chinesezjc Date: Tue, 25 Aug 2026 15:56:32 +0800 Subject: [PATCH 1/4] ci(windows): raise coverage test timeout to 60s After the 4-partition split, other PRs' windows coverage now fails on process-bound subagent-acp tests timing out at 30s under self-hosted concurrency. Give the coverage lane the same 60s per-test budget that the earlier failover profile used. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aa36a92dc8..55716101a2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -446,7 +446,7 @@ jobs: env: DSH_COVERAGE_MAX_WORKERS: '6' DSH_COVERAGE_PARTITIONS: '4' - DSH_COVERAGE_TEST_TIMEOUT_MS: '30000' + DSH_COVERAGE_TEST_TIMEOUT_MS: '60000' DSH_GATE_CONCURRENCY: '3' steps: - uses: actions/checkout@v6 From 5e7c567dc87aff473ae0c81e507e748a707db2cb Mon Sep 17 00:00:00 2001 From: Chinesezjc Date: Tue, 25 Aug 2026 16:07:38 +0800 Subject: [PATCH 2/4] test(subagent-acp): double the per-test timeout relative to default These tests spawn real ACP child subprocesses. On contended self-hosted Windows runners the default 30s budget times out. Instead of raising the global coverage timeout, give this file 2x the configured default (DSH_COVERAGE_TEST_TIMEOUT_MS) so it follows future default changes. --- .github/workflows/ci.yml | 2 +- packages/subagent/subagent-acp/tests/subagent-acp.spec.ts | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 55716101a2..aa36a92dc8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -446,7 +446,7 @@ jobs: env: DSH_COVERAGE_MAX_WORKERS: '6' DSH_COVERAGE_PARTITIONS: '4' - DSH_COVERAGE_TEST_TIMEOUT_MS: '60000' + DSH_COVERAGE_TEST_TIMEOUT_MS: '30000' DSH_GATE_CONCURRENCY: '3' steps: - uses: actions/checkout@v6 diff --git a/packages/subagent/subagent-acp/tests/subagent-acp.spec.ts b/packages/subagent/subagent-acp/tests/subagent-acp.spec.ts index 841c0d8f45..a7e5693148 100644 --- a/packages/subagent/subagent-acp/tests/subagent-acp.spec.ts +++ b/packages/subagent/subagent-acp/tests/subagent-acp.spec.ts @@ -1,4 +1,4 @@ -import { describe, expect, it } from 'vitest' +import { describe, expect, it, vi } from 'vitest' import { Context } from '@deepseek-ai/cordis' import Loader from '@deepseek-ai/cordis-plugin-loader' import { chmodSync, existsSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from 'node:fs' @@ -14,6 +14,12 @@ import { acpStopReason, acpContentText, DEFAULT_DISPOSE_EOF_GRACE_MS, DEFAULT_DI import LocalSubprocessRuntime from '@deepseek-ai/dsh-subprocess-local' import { spawnSubprocess } from '@deepseek-ai/dsh-subprocess-local/src/spawn.ts' +// These tests spawn real ACP child subprocesses. On contended self-hosted +// Windows runners the default per-test budget is too tight, so give this file +// twice the configured default timeout (DSH_COVERAGE_TEST_TIMEOUT_MS in CI). +const DEFAULT_TEST_TIMEOUT_MS = Number(process.env.DSH_COVERAGE_TEST_TIMEOUT_MS ?? 5_000) +vi.setConfig({ testTimeout: DEFAULT_TEST_TIMEOUT_MS * 2 }) + /** * Keyless integration tests for the ACP subagent backend. Each spawns a REAL * subprocess — the scripted mock ACP server (tests/mock-acp-server.ts) — and From eea3c132ff4d93af8bc9317819457cc1784b9464 Mon Sep 17 00:00:00 2001 From: Chinesezjc Date: Tue, 25 Aug 2026 16:36:28 +0800 Subject: [PATCH 3/4] test(subagent-acp): skip stdout half-close tests on Windows Windows anonymous pipes do not surface a child stdout EOF while the child process stays alive. The three tests that simulate 'child closes protocol but stays alive' therefore cannot be reproduced on Windows and hang until the test timeout. Skip them on win32. --- .../subagent-acp/tests/subagent-acp.spec.ts | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/subagent/subagent-acp/tests/subagent-acp.spec.ts b/packages/subagent/subagent-acp/tests/subagent-acp.spec.ts index a7e5693148..28007f4a6e 100644 --- a/packages/subagent/subagent-acp/tests/subagent-acp.spec.ts +++ b/packages/subagent/subagent-acp/tests/subagent-acp.spec.ts @@ -1,4 +1,4 @@ -import { describe, expect, it, vi } from 'vitest' +import { describe, expect, it } from 'vitest' import { Context } from '@deepseek-ai/cordis' import Loader from '@deepseek-ai/cordis-plugin-loader' import { chmodSync, existsSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from 'node:fs' @@ -14,12 +14,6 @@ import { acpStopReason, acpContentText, DEFAULT_DISPOSE_EOF_GRACE_MS, DEFAULT_DI import LocalSubprocessRuntime from '@deepseek-ai/dsh-subprocess-local' import { spawnSubprocess } from '@deepseek-ai/dsh-subprocess-local/src/spawn.ts' -// These tests spawn real ACP child subprocesses. On contended self-hosted -// Windows runners the default per-test budget is too tight, so give this file -// twice the configured default timeout (DSH_COVERAGE_TEST_TIMEOUT_MS in CI). -const DEFAULT_TEST_TIMEOUT_MS = Number(process.env.DSH_COVERAGE_TEST_TIMEOUT_MS ?? 5_000) -vi.setConfig({ testTimeout: DEFAULT_TEST_TIMEOUT_MS * 2 }) - /** * Keyless integration tests for the ACP subagent backend. Each spawns a REAL * subprocess — the scripted mock ACP server (tests/mock-acp-server.ts) — and @@ -595,7 +589,10 @@ describe('dsh-subagent-acp', () => { ) }) - it('reports initialize-stage transport when the child closes the protocol but stays alive', async () => { + it.skipIf( + process.platform === 'win32', + 'Windows anonymous pipes do not surface a child stdout half-close while the child stays alive', + )('reports initialize-stage transport when the child closes the protocol but stays alive', async () => { const error = await startAcpRun(request(), { command: process.execPath, args: [mockServer], @@ -942,7 +939,10 @@ describe('dsh-subagent-acp', () => { await run.dispose() }) - it('classifies a prompt transport failure without copying SDK text', async () => { + it.skipIf( + process.platform === 'win32', + 'Windows anonymous pipes do not surface a child stdout half-close while the child stays alive', + )('classifies a prompt transport failure without copying SDK text', async () => { const run = await startAcpRun(request('private prompt text'), { command: process.execPath, args: [mockServer], @@ -963,7 +963,10 @@ describe('dsh-subagent-acp', () => { await run.dispose() }) - it('lets local cancellation interrupt prompt-failure process observation', async () => { + it.skipIf( + process.platform === 'win32', + 'Windows anonymous pipes do not surface a child stdout half-close while the child stays alive', + )('lets local cancellation interrupt prompt-failure process observation', async () => { const controller = new AbortController() const protocolEnded = Promise.withResolvers() let boundedExitWaits = 0 From ac2f00070e0ea80218b993c0768cecec7a8bc350 Mon Sep 17 00:00:00 2001 From: Chinesezjc Date: Tue, 25 Aug 2026 17:02:16 +0800 Subject: [PATCH 4/4] ci(windows): make windows-coverage temporarily non-blocking Other PRs are blocked by Windows ACP half-close tests timing out. Keep the coverage job running for signal, but remove it from all-checks-passed.needs until the Windows skip fix is validated. --- .github/workflows/ci.yml | 2 +- scripts/ci-workflow.spec.ts | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aa36a92dc8..b486e5df30 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -568,7 +568,7 @@ jobs: && github.event.pull_request.user.login != 'dependabot[bot]' && fromJSON('["self-hosted", "linux", "x64", "vm-backup"]') || 'ubuntu-latest' }} - needs: [node-24, node-24-coverage, node-24-consumers, node-compat, python-sdk, python-runtime, windows, windows-build, windows-coverage, windows-native-tests] + needs: [node-24, node-24-coverage, node-24-consumers, node-compat, python-sdk, python-runtime, windows, windows-build, windows-native-tests] if: always() && github.event_name == 'pull_request' steps: - name: Fail if any needed job did not succeed diff --git a/scripts/ci-workflow.spec.ts b/scripts/ci-workflow.spec.ts index e5aceb8e25..a4011ba06c 100644 --- a/scripts/ci-workflow.spec.ts +++ b/scripts/ci-workflow.spec.ts @@ -129,11 +129,12 @@ describe('CI workflow', () => { expect(serialWindows['runs-on']).toEqual(['self-hosted', 'dsh-win-ci', 'windows']) expect(serialWindows.name).toBe('serial / windows (self-hosted standby)') - // Aggregate: Wine and the three required split native jobs are needed; - // observational stays out of the verdict. + // Aggregate: Wine and the required split native jobs are needed; + // windows-coverage is temporarily non-blocking while Windows ACP + // half-close tests are stabilized; observational stays out too. expect(aggregate.needs).toContain('windows') expect(aggregate.needs).toContain('windows-build') - expect(aggregate.needs).toContain('windows-coverage') + expect(aggregate.needs).not.toContain('windows-coverage') expect(aggregate.needs).toContain('windows-native-tests') expect(aggregate.needs).not.toContain('windows-observational') expect(aggregate.needs).not.toContain('serial-windows')