Run the GitHub Windows runtime leg under the runner’s native PowerShell instead of inheriting the POSIX Bash body. POSIX and Windows now own explicit output resolution, virtual-environment setup, environment scrubbing, and keyless/live black-box commands, while portable build commands continue to use each runner’s default shell.
Put the pinned uv installation on the GitLab Windows job PATH before either the smoke or release builder invokes it. Reject a runtime executable whose basename does not match the selected platform manifest, and reject Intel macOS at platform selection instead of reporting a misleading missing artifact.
Add a complete PowerShell path to the published Python tutorial and record the three-phase shutdown-time bound in the Windows runtime decision. Workflow, Python, and bilingual documentation tests pin the resulting behavior.
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.
Set DSH_E2E_MAX_WORKERS=4 for the credentialed e2e workflow and pin that environment contract in the workflow test. Profile-launched SDK and ACP scenarios each boot a complete subprocess tree, so the previous file-level fan-out could multiply process and provider pressure far beyond the runner's useful concurrency.
The bound changes scheduling only: every e2e file still runs, the Vitest configuration retains its explicit override knob, and local callers can choose a different positive worker count when their resources allow it.
The documentation site deployed on every master push, with no reviewer and
no version check, while npm, PyPI, and the public source repository all
advance only at a release tag. The Pages site is reachable without
authentication, so a merge published documentation ahead of every artifact
readers could obtain.
docs-pages.yml now declares workflow_dispatch alone and verifies the ref
through the gate npm publication already runs, so the site and the npm
sequence share one definition of a released version.
python-release.yml only triggers on workflow_dispatch, so build.if:
github.event_name == 'workflow_dispatch' is always true and redundant; remove it
(the exact event set is already pinned in the spec). Update the spec assertion
accordingly.
Address PR #2875 review:
- Re-record python/development.i18n.yaml (corpus verify-translation-pairing was
out of sync after editing development.md/zh.md) and the 2026-08-11
python-publication-workflow pair after the dry-run wording tweak.
- Tighten the python-release spec assertion to the exact event set
(['workflow_dispatch']) instead of not.toHaveProperty('pull_request').
- Fix the 'dry-run run' wording in development.md and the note.
Corpus-wide verify-translation-pairing (1001 pairs) and note-format (594) pass;
ci-workflow.spec.ts 14/14.
Remove the pull_request:[labeled] trigger from python-release.yml so the
workflow no longer fires (and shows a gray skipped check) when a PR gets any
non-dry-run label. The credential-free dry-run validation is now manual-only
(workflow_dispatch with publish=false), preserving the validation capability
without a PR gray segment.
- python-release.yml: on is workflow_dispatch only; build.if is
github.event_name == 'workflow_dispatch'.
- ci-workflow.spec.ts: assert python-release has no pull_request event and the
simplified build.if.
- python/development.(md,zh.md) and 2026-08-11-python-publication-workflow note
(en/zh/i18n): describe the manual dispatch-only dry-run path.
Verification: ci-workflow.spec.ts 14/14, typecheck clean, note-format 585,
verify-translation-pairing consistent.
Address the fresh review pass on PR #2798:
- ci-workflow.spec.ts: restore the subscription-type assertions the rewrite had
dropped (issue-lifecycle pull_request types omit ready_for_review and include
review_requested; pull_request_review types == ['submitted']) alongside the
new step-level gate checks, so the 'tests pin the subscribed events' gate
holds.
- 2026-08-10-npm-release-sequences note (en/zh/i18n): the three-sequence table's
Workflow column now lists the pack and publish workflows for dsh/vendor, and
line 114 no longer claims release.yml publishes (the dsh pack job packs the
vendored family for verification; release-publish.yml repacks and publishes).
Follow-up for the pack-job copy drift is filed as #2816.
Address ds-review-bot findings on PR #2798:
- release-publish.yml: use pnpm run build:official (not build) so the dsh
pack step's verifyBuildArtifacts (families.ts:327, readClientBuildRecord with
officialClientBuildEnvironment) finds the official client-build record; build
would fail Pack release tarballs on a clean runner.
- issue-lifecycle.yml: move the previous job-level if to step level on
Create project token and Handle repository event, so approved/commented
reviews pass (job reported success, no gray segment) without minting a
write-capable App token or touching the board — preserving the original
least-privilege property.
- ci-workflow.spec.ts: lock the step-level gate on the two lifecycle steps, and
add a release-workflow invariant test (release.yml/vendor are pack-only;
release-publish.yml/vendor-publish.yml are workflow_dispatch-only with the
npm-publish environment and Release-publish group) to prevent #2797 recurrence.
- Update 2026-08-10-event-directed-pr-review-status and 2026-08-10-npm-release-
sequences notes (en/zh/i18n) to the new split and step-level behavior.
Verification: ci-workflow.spec.ts 14/14, typecheck clean, all five workflows
YAML-parse, verify-translation-pairing consistent, note-format 582.
Remove the three skipped (gray) checks from the PR check panel without changing
functional semantics:
- issue-lifecycle: remove the job-level 'if' that skipped the lifecycle job on
non-changes-requested pull_request_review events, so it now runs and reports
success (the lifecycle handler already no-ops for approved/commented reviews).
The changes-requested board transition is unchanged.
- release.yml / release-vendor.yml: drop the publish job (and its
workflow_dispatch 'publish' input + RELEASE_PUBLISH pass-through) so it no
longer appears as a skipped Publish-to-npm check on PRs; the files keep the
pack job that validates tarballs on PR/push.
- new release-publish.yml / release-vendor-publish.yml: manual workflow_dispatch
only, repack on the current tree then publish, so publication behaves exactly
as the old publish job (explicit dispatch, uses the packed bytes) but never
shows as a PR check.
Update the 2026-08-10 review-status note (en/zh/i18n) and the issue-lifecycle
spec assertion to match the unconditional lifecycle job.
Verification: ci-workflow.spec.ts 19/19, all five workflows YAML-parse, typecheck
clean, verify-translation-pairing consistent, note-format 582.
The exact-event-set assertion called Object.keys on a Record<string, unknown>'s
on field without narrowing, failing typecheck (TS2769). Guard with isRecord
before asserting the full event sets.
Address the 7 remaining review threads on PR #2768:
- spec: assert the exact full event sets for both workflows (ci-master =
[push, workflow_dispatch], ci.yml = [pull_request]) instead of only the
negated checks, so losing/adding a wrong event fails.
- 2026-07-21 note line 29: 'The ci-master and Sandbox workflows keep their
cross-platform references on master pushes' (en+zh) — ci.yml is PR-only.
- failover-runbook line 19 (en+zh): the push-reachable classification now names
ci-master.yml for the drills/wine cache and ci.yml for the PR jobs, dropping
the stale pull-request-gated phrasing.
i18n hashes re-recorded for both notes; spec 13/13, pairs consistent,
note-format 575.
- The pnpm-caching note placed node-compat in ci-master.yml, but it stays a PR
job in ci.yml; only the two runner benchmarks moved. Correct en/zh line 15 and
re-record the pair.
- The pnpm/action-setup destination test only iterated ci.yml; extend it to also
cover ci-master.yml so its five pnpm setups stay regress-tested.
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.
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.
- 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