Stacked on #3115: keep its windows-* setup-pnpm-js-<run_id>-<run_attempt>-<job>
destination, and extend the same isolation to non-Windows jobs in ci.yml
and ci-master.yml with setup-pnpm-<run_id>-<run_attempt>. This prevents
sequential self-hosted Windows jobs from tripping over a stale locked
pnpm.exe/reflink native module.
The per-case 15-30s budgets on the Windows native and coverage lanes fire
before oxlint, workflow-worker-thread, and other subprocess-spawning cases
finish under the loaded self-hosted pool; the failures rotate across cases
as load shifts, so per-case widening only moved the flake. Raise the lane
defaults (DSH_COVERAGE_TEST_TIMEOUT_MS and the native --testTimeout) to 90s,
align the oxlint and workflow-worker-thread case budgets, and keep the
built-bin SPAWN_TIMEOUT_MS at 60s under a 90s outer budget.
The windows-* jobs now install pnpm under a run/attempt/job-suffixed
destination, so the pre-install step that cleared the old fixed
setup-pnpm-js path no longer touches the actual destination and its
comment claims stale state. The suffix already gives every job a fresh
directory, so remove the four cleanup steps.
The windows-* jobs keep a separate standalone pnpm executable under
runner.temp/setup-pnpm-js. A previous job on the same self-hosted runner
can leave a locked @reflink native module there, so the next job's
pnpm/action-setup fails with EPERM during unlink before any test runs.
Suffix the destination with run_id, run_attempt, and job so every job
gets a fresh directory even when sequential jobs land on the same
runner; apply the same to the python SDK exe build. Update the pnpm
setup isolation note to record the Windows-specific destination.
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.
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.
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.
Keep the 4-partition coverage profile, split the monolithic windows-native
job into smaller required jobs (build, coverage, native-tests) plus a
non-blocking observational job. Update ci-workflow.spec for the new topology.
Under high self-hosted concurrency, 8 partitions per Windows native job
triggered vitest fork worker startup timeouts. This branch lowers Windows
coverage to the same 4 partitions Linux uses, trading some single-job
coverage wall time for lower process-creation pressure.
Add node24-win-x64 to the required pull-request and public-release matrices on a native windows-2025 runner, and publish the same win_amd64 artifact from the GitLab tag pipeline. GitHub uses Git Bash for the shared release script while selecting the Windows venv's Scripts/python.exe explicitly; the Linux and macOS legs retain their existing commands and native checks.
Run the complete installed-wheel keyless suite and the trusted two-turn DeepSeek smoke on Windows exactly as on the existing targets. Make the minimal blackbox choose persistent PowerShell on Windows, keep advanced and restart snapshots platform-stable by disabling both one-shot shell variants, locate the generated dsh.exe console command, and validate text lines without assuming POSIX newlines.
Workflow tests pin the four-target matrix, Windows runner and wheel tag, cross-platform venv selection, GitLab publication dependency, and full blackbox invocation. The existing POSIX minimal snapshot changes only its platform-neutral prompt wording; Windows owns a separate model-visible snapshot.
* test(python): exercise installed wheels as black boxes
Add an installed-wheel mode that refuses source/editable imports, repository working directories, mismatched SDK/runtime versions, unpinned runtime dependencies, and executables outside the installed runtime distribution. The mode resolves the wheel-owned executable itself, so callers cannot accidentally prove an explicit checkout artifact.
Add a real-API scenario that drives two tool-using turns through the public synchronous SDK, verifies the file bytes outside the agent, checks completed turn/tool events and persistence, and projects provider failures without retaining credential-bearing error text. The existing deterministic scenario set remains the keyless behavior oracle.
Refs #2952.
* ci(python): require installed-wheel checks on every release target
Move the complete deterministic runtime scenarios behind construction and clean installation of the SDK and matching runtime wheels. Each native leg runs outside the checkout with source-resolution environment variables removed; Linux manylinux smokes assert the same installed provenance.
Expand the required pull-request call from Linux x64 to Linux x64, Linux arm64, and macOS arm64. Trusted heads receive only DEEPSEEK_API_KEY_EXTERNAL for a fail-loud live two-turn smoke on each carrier, while fork and Dependabot heads retain the full keyless path without exposing secrets.
Pin the reusable secret declaration, matrix call, aggregate dependency, untrusted-head condition, and live/keyless commands in the workflow contract test.
Refs #2952.
* docs(testing): make installed wheels the Python CI authority
Record the clean-wheel provenance boundary, complete keyless scenario set, trusted real-API contract, secret handling, and three-target required topology in a new implemented testing decision. Update the SEA distribution and portable-CI authorities plus the Python contributor reference to describe the same current state.
Archive the fully superseded Linux-x64-only decision after consolidating its rationale and alternatives into the new owner. Preserve its bilingual triplet as a sealed historical snapshot and redirect every active current-state reference.
Refs #2952.
Address the second review pass on PR #2768:
- Restore the serial-linux-selfhosted drill comment in ci-master.yml (it was
lost in the split boundary, leaving serial-linux-selfhosted as the only
comment-less job); adapted to the current-state fact that this workflow never
listens to pull_request while keeping the no-cache-steps reason, the
DSH_CI_FAILOVER_LINUX switch guidance, and push-triggered semantics.
- Update 2026-07-29-pnpm-setup-runner-isolation (en/zh + i18n): the regression
test and setup steps now span ci.yml and ci-master.yml.
- failover-runbook line 19: the push-reachable classification now names
ci-master.yml for the drills/wine cache and ci.yml for the pull-request jobs,
dropping the stale pull-request-gated phrasing.
- all-checks-passed comment in ci.yml notes that needs cannot reach across
workflow files (ci-master job are deliberately outside this PR verdict).
Verification: ci-workflow.spec.ts 13/13, both workflows YAML-parse with correct
concurrency, 3 translation pairs consistent, note-format 575.
Per review on PR #2768:
- Restore a concurrency block in ci.yml (cancel-in-progress: true) so a fresh
PR push cancels the superseded run; GitHub has no default PR auto-cancel,
so removing it would stack a second full 9-job run on every push.
Update the ci-workflow.spec assertion accordingly.
- Fix comment misplacements from the split boundary: ci.yml's all-checks-passed
now carries its own branch-protection comment (the drill comment that was
orphaned above it is gone), and ci-master.yml no longer ends with an orphaned
all-checks-passed comment.
- Restore the DeepSeek e2e workflow describe-block in ci-workflow.spec.ts that
the rewrite had silently deleted (e2e.yml is unchanged).
- serial-windows comment no longer claims non-blocking-for-PR/absent-from-needs
since ci-master never listens to pull_request.
- DSH_TELEMETRY_DISABLED safe-use comment restored in ci-master.yml env; split
rationale (mi gray segments in PR check) documented in .github/AGENTS.md.
Verification: ci-workflow.spec.ts 13/13, both workflows YAML-parse with correct
concurrency, git diff --check clean.
Split the single ci.yml into two workflows so the PR check panel stops listing
master-only obs jobs that skip (gray) and block the aggregate green-check:
- ci.yml is now pull_request-only, holding only the 9 PR jobs (node-24,
node-24-coverage, node-24-consumers, node-compat, python-sdk, python-runtime,
windows, windows-native, all-checks-passed). It drops the workflow-level
concurrency block since master carve-outs no longer apply.
- ci-master.yml (new) carries the six master/dispatch jobs (wine-apt-cache,
serial-linux-selfhosted, serial-macos, serial-windows, and both runner
benchmarks) with the push-exempt cancel-in-progress block and suite input.
It does not listen to pull_request, so its jobs never appear in PR checks.
ci.yml keeps the wine apt cache seed/restore (repo-scoped by key), so moving the
producer to ci-master.yml does not break the PR windows job's restore.
Update ci-workflow.spec.ts to assert the two-workflow split: ci-master owns the
drills/benchmarks and the push-exemption concurrency, ci.yml is PR-only without
concurrency. Update the serial-reference, portable-required, failover-runbook,
and pnpm-caching notes (en/zh + i18n) and .github/AGENTS.md to reflect ci-master.
Verification: scripts/ci-workflow.spec.ts 12/12, both workflows YAML-parse,
verify-translation-pairing consistent, verify-agent-note-format passes.
Address the review findings from the fresh pass on PR #2744:
- 2026-07-21 note L31: the enabled serial references run on the self-hosted
vm-backup/dsh-win-ci pools and the only remaining disabled hosted serial is
serial-macos (macos-latest); removed the stale hosted ubuntu-latest/windows-2025
serial framing and the outdated 'when enabled, serial / windows' clause.
- Drop remaining change-narrative from both notes: L19 (serial / linux, macos)
and the 2026-07-26 caching note L16/L34 now state only current facts without
deletion dates/PR numbers; the no-producer fact has one home (L16). zh.ms'
'直至其过期为逐出' corrected to '直至其被逐出'. Bilingual hashes re-recorded.
- ci.yml TODO notes that re-enabling serial-macos does not restore a Linux
hosted-cache producer and records the seeder-vs-remove decision direction.
- The Playwright restore's failover-skip comment is now self-contained (the
VM's persistent browser cache is warm) instead of pointing at the coveragelane
rationale, which is pnpm-store-specific.
Verification: scripts/ci-workflow.spec.ts passes (12/12), YAML re-parses,
both translation pairs consistent, git diff --check clean.
Apply review feedback on the serial-linux removal (PR #2744):
ci.yml:
- Rewrite the new comments as current-state statements, not change
narrative (dsh-prose-standard): the TODO names serial-macos as the one
remaining disabled hosted serial job; serial-macos's intro and the
self-hosted standby's frozen-archive note no longer narrate the deletion.
- The self-hosted standby's frozen-archive comment states its own reason
(full history to resolve DSH_ARCHIVE_BASE_REF against github.event.before)
instead of referenceing a now-nonexistent hosted serial reference.
- Move the hosted-cache comment above the pnpm restore so it covers both
restore-keys fallback steps, and describe the real consequence (matches the
archived entry until evict, then cold) instead of the false
'cold on a lockfile change'. Restore the per-step failover-skip note.
Agent Note 2026-07-26-pnpm-action-setup-for-symmetric-ci-caching:
- Update the restore-only bullet and the consequences closing line (it
described serial-linux as the active master-push producer of the pnpm store
cache) to state that no master job produces these hosted keys since the
producer was removed; the Problem and Alternatives sections are historical
context and are left unchanged. Re-record the bilingual pair hashes.
Verification: scripts/ci-workflow.spec.ts passes (12/12), YAML re-parses,
both translation pairs consistent, git diff --check clean.
serial-linux (hosted ubuntu-latest) has been `if: false` since 2026-07-30 and
never runs. Remove the dead job block and retire the dangling references:
- TODO(hosted-serial-ci) narrowed to the single remaining disabled hosted
serial job (serial-macos); the hosted linux definition is gone.
- The cache producer comment no longer claims serial-linux refreshes the
hosted pnpm/Playwright caches; there is currently no active master producer
for them, so restores are cold on a lockfile change.
- The self-hosted standby's frozen-archive comment no longer cross-references
the deleted job.
- serial-macos gains its own intro comment since the shared 'hosted reference
jobs below are disabled' lede was removed.
No runner allocation, required gate, or all-checks-passed.needs reference this
job; the aggregate is unchanged.
The windows wine-blocking job installs Wine with apt-get over the local
.deb archive, but apt re-downloads the full 100+ MB closure from the
Ubuntu mirror anyway. A degraded runner network stalled that transfer
past the job's 15-minute budget and cancelled the check. Install the
restored archive directly with dpkg (no repository access) and keep the
apt network install as the fallback when the archive cannot satisfy the
closure.
Replace the single DSH_CI_FAILOVER variable with two independent
switches so an outage on one platform no longer retargets the other:
- DSH_CI_FAILOVER_LINUX: the three required Linux workers (node-24,
node-24-coverage, node-24-consumers) and the all-checks-passed verdict,
which resolves its pool to vm-backup and keeps its concurrency and
cache-restore branches.
- DSH_CI_FAILOVER_WINDOWS: the non-blocking windows-native job, which
resolves to the dsh-win-ci pool.
all-checks-passed rides the Linux switch because it aggregates the
required Linux workers and runs on the vm-backup pool. The Dependabot
exclusion is preserved on both switches. The failover runbook (EN/ZH)
and its translation pairing, plus the docs that referenced the old
variable, are updated in the same change.
cancel-in-progress is evaluated against the newly triggered run, so
exempting push means one master merge does not cancel the drill still
running from the previous one — not that a drill always finishes. A
benchmark dispatched on master shares the group and does cancel a
mid-flight drill. Record that bound in the runbook and drop the
overstated wording from the workflow comment and the spec name.
Also repair two gates that fail on master and block every pull request:
the telemetry note referenced an SDK proposal deleted in 408721954a,
and the ui-settings-general README pair carried stale recorded hashes
after both sides were updated together in aa1ec02bc6.
The two self-hosted standby drills each run their complete unsharded
aggregate with one gate worker, which takes longer than the interval
between master merges, so unconditional cancel-in-progress supersedes a
drill before it reaches a verdict and the lane yields no readiness
evidence for the failover runbook to point a responder at.
Exempt push and nothing else. This has to be decided at workflow level:
cancellation applies to the whole superseded run, so a job-level
concurrency group cannot exempt its job. The negated form is
load-bearing — naming pull_request alone would also stop cancelling
workflow_dispatch, and each runner benchmark fans out to twelve larger
runners for up to fifteen minutes in this same group on master, so a
re-dispatch would queue ahead of a drill instead of replacing a stale
measurement. It does not promise every push run finishes: a newer
pending run still displaces an older one, only that the lanes
periodically reach a verdict.
A master push carries only wine-apt-cache and the two drills; every other
job is pull-request-gated, workflow_dispatch-gated, or if: false. The
spec pins that set and classifies by exact condition, since a negated
event test mentions the event it excludes.
Restore the Wine-emulated windows job as the required pull-request
Windows signal. Add DSH_CI_FAILOVER switch to windows-native so it
retargets onto the self-hosted [self-hosted, dsh-win-ci, windows]
pool under failover. Enable serial-windows as a master-only
self-hosted standby mirroring serial-linux-selfhosted.
The windows-native job remains absent from all-checks-passed.needs —
Wine owns the required verdict, native Windows reports independently.
Restore wine-apt-cache, wine-windows-gates.sh, check:windows-wine
script, and the original Agent Note topology.
Resolve modify/delete conflict on
.agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.i18n.yaml:
accept deletion — the note triplet was archived to archived/process/.
- Rewrite ci-workflow.spec.ts to assert new single-job native Windows topology
- Remove check:windows-wine from root AGENTS.md command list
- Archive 2026-08-08-native-windows-pull-request-ci (dual-lane topology
superseded) with Archived: metadata and inbound-link updates
- Update cross-references in serial-cross-platform-ci-reference,
portable-required-pull-request-ci, and pnpm-action-setup notes
- Add Windows pool coverage to the failover runbook (EN + zh)
- Remove dead wine-windows-gates.sh
- Remove unnecessary Playwright Chromium install from serial-windows
- Fix .github/AGENTS.md windows-* label wording
- Fix PR description before-state accuracy
Replace the Wine-emulated windows job and the independent windows-native
job with a single required native Windows job that runs
check:ci:windows-complete on the hosted larger runner, falling back to
the self-hosted [self-hosted, dsh-win-ci, windows] pool under failover
(DSH_CI_FAILOVER=selfhosted). The serial-windows standby mirrors
serial-linux-selfhosted: master-only, unsharded, self-hosted, absent
from all-checks-passed.
Remove wine-apt-cache, the check:windows-wine script reference, and the
dual-lane topology the two Windows notes described.