Просмотр исходного кода

Merge branch 'master' into fix/fork-resume-system-prompt

Dudu-0223 1 месяц назад
Родитель
Сommit
2f396feca8
39 измененных файлов с 217 добавлено и 91 удалено
  1. 2 2
      .agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.i18n.yaml
  2. 0 0
      .agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.md
  3. 0 0
      .agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.zh.md
  4. 2 2
      .agents/notes/implemented/architecture/2026-08-22-single-dsh-application-launcher.i18n.yaml
  5. 1 1
      .agents/notes/implemented/architecture/2026-08-22-single-dsh-application-launcher.md
  6. 1 1
      .agents/notes/implemented/architecture/2026-08-22-single-dsh-application-launcher.zh.md
  7. 2 2
      .agents/notes/implemented/architecture/2026-08-23-python-sdk-dsh-profile-runtime.i18n.yaml
  8. 1 1
      .agents/notes/implemented/architecture/2026-08-23-python-sdk-dsh-profile-runtime.md
  9. 1 1
      .agents/notes/implemented/architecture/2026-08-23-python-sdk-dsh-profile-runtime.zh.md
  10. 2 2
      .agents/notes/implemented/architecture/2026-08-23-python-sdk-windows-x64-runtime.i18n.yaml
  11. 2 2
      .agents/notes/implemented/architecture/2026-08-23-python-sdk-windows-x64-runtime.md
  12. 2 2
      .agents/notes/implemented/architecture/2026-08-23-python-sdk-windows-x64-runtime.zh.md
  13. 2 2
      .agents/notes/implemented/process/2026-08-11-python-publication-workflow.i18n.yaml
  14. 3 3
      .agents/notes/implemented/process/2026-08-11-python-publication-workflow.md
  15. 3 3
      .agents/notes/implemented/process/2026-08-11-python-publication-workflow.zh.md
  16. 2 2
      .agents/notes/implemented/testing/2026-08-23-installed-python-wheel-black-box-ci.i18n.yaml
  17. 3 3
      .agents/notes/implemented/testing/2026-08-23-installed-python-wheel-black-box-ci.md
  18. 3 3
      .agents/notes/implemented/testing/2026-08-23-installed-python-wheel-black-box-ci.zh.md
  19. 22 10
      .github/workflows/build-exe-for-python-sdk.yml
  20. 1 1
      .github/workflows/ci.yml
  21. 3 2
      .github/workflows/python-release.yml
  22. 24 3
      .gitlab-ci.yml
  23. 10 2
      packages/shell/tool-pwsh-persistent/tests/loader-composition.spec.ts
  24. 2 2
      python/development.i18n.yaml
  25. 3 3
      python/development.md
  26. 3 3
      python/development.zh.md
  27. 2 2
      python/sdk-runtime/README.i18n.yaml
  28. 1 1
      python/sdk-runtime/README.md
  29. 1 1
      python/sdk-runtime/README.zh.md
  30. 4 0
      python/sdk-runtime/platforms.json
  31. 1 2
      python/sdk-runtime/src/deepseek_harness_runtime/__init__.py
  32. 30 1
      python/sdk/tests/test_macos_deployment_target.py
  33. 3 1
      python/sdk/tests/test_release_version.py
  34. 2 3
      python/sdk/tests/test_runtime_resolution.py
  35. 13 0
      scripts/build-exe-for-python-sdk.spec.ts
  36. 1 1
      scripts/build-exe-for-python-sdk.ts
  37. 26 10
      scripts/check-macos-deployment-target.py
  38. 29 8
      scripts/ci-workflow.spec.ts
  39. 4 3
      scripts/verify-runtime-closure.spec.ts

+ 2 - 2
.agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.i18n.yaml

@@ -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/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.md
-2026-07-10-single-file-executable-sdk-runtime-distribution.md: ab09691b48684b8ebae269df4d585b499423e671
-2026-07-10-single-file-executable-sdk-runtime-distribution.zh.md: d986105b087357bd8301251dca14736a5b427bbb
+2026-07-10-single-file-executable-sdk-runtime-distribution.md: 558358167a5e7d37bc79c42003a183b0c4c40d17
+2026-07-10-single-file-executable-sdk-runtime-distribution.zh.md: 0f7daec5b79e6f526dde7a01c5ef85b07e955707

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
.agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.md


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
.agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.zh.md


+ 2 - 2
.agents/notes/implemented/architecture/2026-08-22-single-dsh-application-launcher.i18n.yaml

@@ -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/architecture/2026-08-22-single-dsh-application-launcher.md
-2026-08-22-single-dsh-application-launcher.md: feac31b3eafced8158a8d79a0e5967a8de5e2f87
-2026-08-22-single-dsh-application-launcher.zh.md: 88fe4ef4d4e0436ecb450e3f5319be7acee6882b
+2026-08-22-single-dsh-application-launcher.md: 068c59c1695ac41216e4df7012eaeb9f80e1e5a6
+2026-08-22-single-dsh-application-launcher.zh.md: 1e082a3d6de391c70a38031caafc44781bc2c7e4

+ 1 - 1
.agents/notes/implemented/architecture/2026-08-22-single-dsh-application-launcher.md

@@ -48,7 +48,7 @@ Direct SDK use follows normal Harness-home resolution: explicit `dshHome`, inher
 
 The Python runtime wheel packages the ordinary `@deepseek-ai/dsh` CLI from `node_modules/@deepseek-ai/dsh/lib/bin.js` through the private `dsh-python-runtime-closure` deploy manifest. The Python client selects `dsh --profile sdk` by default, ordered patch files, and an explicit Harness home; the runnable example under `python/sdk/examples` selects `sdk-minimal`. The installed `dsh` console command exposes the same profile grammar and the separately packaged `web` application.
 
-The executable family is `deepseek-harness-sdk-runtime-<platform>-<arch>`. The SDK wire, wheel and import distribution names, sidecar names, and wire identity `deepseek-harness-sdk-runtime` remain stable. The SDK package family is `@deepseek-ai/dsh-sdk-client`, `@deepseek-ai/dsh-sdk-protocol`, and `@deepseek-ai/dsh-sdk-jsonrpc-server`; `@deepseek-ai/dsh-acp` remains the ACP protocol plugin. There is no Python-specific Node application, checked-in complete config, compatibility package, forwarding executable, fallback parser, or SDK/ACP launcher alias. The [Python profile-runtime decision](2026-08-23-python-sdk-dsh-profile-runtime.md) owns this launch, and the [Windows x64 runtime decision](2026-08-23-python-sdk-windows-x64-runtime.md) owns the fourth carrier.
+The executable family is `deepseek-harness-sdk-runtime-<platform>-<arch>`. The SDK wire, wheel and import distribution names, sidecar names, and wire identity `deepseek-harness-sdk-runtime` remain stable. The SDK package family is `@deepseek-ai/dsh-sdk-client`, `@deepseek-ai/dsh-sdk-protocol`, and `@deepseek-ai/dsh-sdk-jsonrpc-server`; `@deepseek-ai/dsh-acp` remains the ACP protocol plugin. There is no Python-specific Node application, checked-in complete config, compatibility package, forwarding executable, fallback parser, or SDK/ACP launcher alias. The [Python profile-runtime decision](2026-08-23-python-sdk-dsh-profile-runtime.md) owns this launch, and the [Windows x64 runtime decision](2026-08-23-python-sdk-windows-x64-runtime.md) owns the Windows carrier.
 
 ### Enforcement
 

+ 1 - 1
.agents/notes/implemented/architecture/2026-08-22-single-dsh-application-launcher.zh.md

@@ -48,7 +48,7 @@ SDK 用户通过 profile 自定义插件。`dsh plugin --profile <name> ...` 管
 
 Python 运行时 wheel 通过私有 `dsh-python-runtime-closure` 部署 manifest,打包来自 `node_modules/@deepseek-ai/dsh/lib/bin.js` 的普通 `@deepseek-ai/dsh` CLI。Python 客户端默认选择 `dsh --profile sdk`、有序 patch 文件与显式 Harness home;`python/sdk/examples` 下的可运行示例选择 `sdk-minimal`。安装的 `dsh` 控制台命令暴露相同 profile 语法与单独打包的 `web` 应用。
 
-可执行文件族是 `deepseek-harness-sdk-runtime-<platform>-<arch>`。SDK 协议格式、wheel 与 import 分发名称、伴随文件名称,以及协议 identity `deepseek-harness-sdk-runtime` 保持稳定。SDK 包族是 `@deepseek-ai/dsh-sdk-client`、`@deepseek-ai/dsh-sdk-protocol` 与 `@deepseek-ai/dsh-sdk-jsonrpc-server`;`@deepseek-ai/dsh-acp` 继续作为 ACP 协议插件。仓库不保留 Python 专用 Node 应用、检入的完整配置、兼容包、转发可执行文件、后备解析器或 SDK/ACP 启动别名。[Python profile 运行时决策](2026-08-23-python-sdk-dsh-profile-runtime.zh.md)负责该启动方式,[Windows x64 运行时决策](2026-08-23-python-sdk-windows-x64-runtime.zh.md)负责第四个载体。
+可执行文件族是 `deepseek-harness-sdk-runtime-<platform>-<arch>`。SDK 协议格式、wheel 与 import 分发名称、伴随文件名称,以及协议 identity `deepseek-harness-sdk-runtime` 保持稳定。SDK 包族是 `@deepseek-ai/dsh-sdk-client`、`@deepseek-ai/dsh-sdk-protocol` 与 `@deepseek-ai/dsh-sdk-jsonrpc-server`;`@deepseek-ai/dsh-acp` 继续作为 ACP 协议插件。仓库不保留 Python 专用 Node 应用、检入的完整配置、兼容包、转发可执行文件、后备解析器或 SDK/ACP 启动别名。[Python profile 运行时决策](2026-08-23-python-sdk-dsh-profile-runtime.zh.md)负责该启动方式,[Windows x64 运行时决策](2026-08-23-python-sdk-windows-x64-runtime.zh.md)负责 Windows 载体。
 
 ### 强制校验
 

+ 2 - 2
.agents/notes/implemented/architecture/2026-08-23-python-sdk-dsh-profile-runtime.i18n.yaml

@@ -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/architecture/2026-08-23-python-sdk-dsh-profile-runtime.md
-2026-08-23-python-sdk-dsh-profile-runtime.md: 4af7812db6818b65c754a43ec1a7f973d1cbcbf9
-2026-08-23-python-sdk-dsh-profile-runtime.zh.md: 155e7d2ae0b0ba3e4163dd85a31de90bef9d588a
+2026-08-23-python-sdk-dsh-profile-runtime.md: 07e3bd522b1952a8e6257f79eb292fa0ef18e5ef
+2026-08-23-python-sdk-dsh-profile-runtime.zh.md: 1b68c50d93e0fd6d2555115891772b00f95bb7d4

+ 1 - 1
.agents/notes/implemented/architecture/2026-08-23-python-sdk-dsh-profile-runtime.md

@@ -34,7 +34,7 @@ The zero-code deployment manifest is `dsh-python-runtime-closure`. It packages `
 
 Plain Node profiles use symlinks in `$DSH_HOME/profiles/node_modules` to share installation packages with external plugins. An operating-system symlink cannot traverse pkg's `/snapshot` filesystem, so the packaged CLI writes small real ESM proxy packages instead. Each proxy resolves the source package's explicit ESM export map directly under Node import conditions, exposes targets that exist in the installation, and re-exports their virtual module URLs. Export rows without an ESM runtime target and executable-only or declaration-only packages produce no unusable proxy entry; malformed export maps fail startup. A complete matching generation returns without acquiring the cross-process writer lock. A missing or stale entry acquires the lock, rechecks the generation, and repairs it without exposing partial proxies; either carrier can replace the other carrier's managed entry. Loader rows and external plugin peers therefore resolve through the normal profile parent walk while retaining one Cordis and one instance of each bundled module.
 
-The published target set is Linux x64, Linux arm64, macOS arm64, and Windows x64. Installed-wheel black-box CI owns artifact provenance, default and patched profiles, external bundle installation, native tools, MCP, direct JSON-RPC, snapshots, and trusted real-provider turns on every target. The [Windows x64 runtime decision](2026-08-23-python-sdk-windows-x64-runtime.md) owns the fourth artifact and its platform-specific shell surface.
+The published target set is Linux x64, Linux arm64, macOS arm64, macOS x64, and Windows x64. Installed-wheel black-box CI owns artifact provenance, default and patched profiles, external bundle installation, native tools, MCP, direct JSON-RPC, snapshots, and trusted real-provider turns on every target. The [Windows x64 runtime decision](2026-08-23-python-sdk-windows-x64-runtime.md) owns the Windows artifact and its platform-specific shell surface.
 
 ## Existing decisions and supersession
 

+ 1 - 1
.agents/notes/implemented/architecture/2026-08-23-python-sdk-dsh-profile-runtime.zh.md

@@ -34,7 +34,7 @@ Python SDK 分发一个私有 Node 应用,直接启动完整外部 `cordis.yml
 
 普通 Node profile 在 `$DSH_HOME/profiles/node_modules` 中使用符号链接,让外部插件共享安装包。操作系统符号链接无法进入 pkg 的 `/snapshot` 文件系统,因此打包 CLI 改为写入小型真实 ESM 代理包。每个代理直接按 Node import 条件解析源包的显式 ESM exports map,公开安装中实际存在的目标,并重新导出其虚拟模块 URL。没有 ESM 运行时目标的 export 项以及仅含可执行入口或类型声明入口的包不会产生不可用的代理条目;格式错误的 exports map 会导致启动失败。完整且匹配的 generation 不会获取跨进程写入锁。缺失或过期的配置项会获取该锁、重新检查 generation,并在不暴露半成品代理的前提下修复;任一载体都可以替换另一载体留下的受管配置项。Loader 配置项和外部插件 peer 因而可以通过普通 profile 逐级向上查找解析,同时保留一个 Cordis 和每个内置模块的单一实例。
 
-已发布目标集合是 Linux x64、Linux arm64、macOS arm64 与 Windows x64。Installed-wheel 黑盒 CI 在每个目标上负责产物来源、默认及 patched profile、外部 bundle 安装、原生工具、MCP、直接 JSON-RPC、快照,以及可信真实提供方轮次。[Windows x64 运行时决策](2026-08-23-python-sdk-windows-x64-runtime.zh.md)负责第四个产物及其平台专属 shell surface。
+已发布目标集合是 Linux x64、Linux arm64、macOS arm64、macOS x64 与 Windows x64。Installed-wheel 黑盒 CI 在每个目标上负责产物来源、默认及 patched profile、外部 bundle 安装、原生工具、MCP、直接 JSON-RPC、快照,以及可信真实提供方轮次。[Windows x64 运行时决策](2026-08-23-python-sdk-windows-x64-runtime.zh.md)负责 Windows 产物及其平台专属 shell surface。
 
 ## 既有决策与取代关系
 

+ 2 - 2
.agents/notes/implemented/architecture/2026-08-23-python-sdk-windows-x64-runtime.i18n.yaml

@@ -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/architecture/2026-08-23-python-sdk-windows-x64-runtime.md
-2026-08-23-python-sdk-windows-x64-runtime.md: 59a46d99f9e7ed411aeffbb541bbe3bb0c752078
-2026-08-23-python-sdk-windows-x64-runtime.zh.md: 3ab972aabb8135c8bc6285d129ba7bc9335eb11f
+2026-08-23-python-sdk-windows-x64-runtime.md: 1b59dec47036e7351b212b408a31847a1a1c9639
+2026-08-23-python-sdk-windows-x64-runtime.zh.md: 75cea660c3e5cc8e0222e72dc2d07a0c802aeecd

+ 2 - 2
.agents/notes/implemented/architecture/2026-08-23-python-sdk-windows-x64-runtime.md

@@ -20,7 +20,7 @@ The Python process still launches the ordinary `dsh --profile sdk` application a
 
 The executable builder accepts `win` as a pkg platform only with x64, requires the Windows build to run under x64 Node on a Windows host, preserves `.exe` names, and copies `@vscode/ripgrep-win32-x64` as the conventional `-rg.exe` sidecar. Pnpm subprocesses use a caller-supplied JavaScript entry through `process.execPath`. When the caller exposes a `.cmd` shim, the builder resolves the installed `pnpm.mjs` or `pnpm.cjs` through `PNPM_HOME`; it fails if no JavaScript entry exists instead of spawning the shim or enabling a command shell.
 
-The required GitHub matrix builds `node24-win-x64` on `windows-2025` beside the three existing targets. The public GitHub release and GitLab tag pipeline each publish the same four runtime wheels plus the pure SDK wheel. Windows arm64 is absent from target parsing, manifests, matrices, release contents, and documentation.
+The required GitHub matrix builds `node24-win-x64` on `windows-2025` beside Linux x64, Linux arm64, macOS arm64, and macOS x64. The public GitHub release and GitLab tag pipeline each publish the same five runtime wheels plus the pure SDK wheel. Windows arm64 is absent from target parsing, manifests, matrices, release contents, and documentation.
 
 ### Installed-wheel behavior
 
@@ -48,4 +48,4 @@ This decision partially supersedes the Windows non-goal in the [single-file runt
 
 ## Consequences
 
-Python installation now selects a Node-free Windows x64 runtime with the same explicit-home and profile customization model as Linux and macOS. Every pull request pays for a fourth executable, runtime wheel, full keyless blackbox, and—on trusted heads—real provider task. Release validation retains five wheels instead of four. Windows arm64 users receive an explicit unsupported-platform failure until a separate native product decision supplies and proves that carrier.
+Python installation selects a Node-free Windows x64 runtime with the same explicit-home and profile customization model as Linux and macOS. Every pull request builds the Windows executable and runtime wheel as one of five native targets, runs the full keyless blackbox, and—on trusted heads—runs the real-provider task. Release validation retains six wheels. Windows arm64 users receive an explicit unsupported-platform failure until a separate native product decision supplies and proves that carrier.

+ 2 - 2
.agents/notes/implemented/architecture/2026-08-23-python-sdk-windows-x64-runtime.zh.md

@@ -20,7 +20,7 @@ Python 进程仍按 [Python profile 运行时决策](2026-08-23-python-sdk-dsh-p
 
 可执行文件构建器仅允许 x64 使用 pkg 的 `win` 平台,并要求 Windows 构建在 Windows 宿主的 x64 Node 下运行;构建器保留 `.exe` 文件名,并把 `@vscode/ripgrep-win32-x64` 复制为常规 `-rg.exe` sidecar。Pnpm 子进程通过 `process.execPath` 执行调用方提供的 JavaScript 入口。当调用方暴露 `.cmd` shim 时,构建器会通过 `PNPM_HOME` 解析已安装的 `pnpm.mjs` 或 `pnpm.cjs`;如果不存在 JavaScript 入口,构建会失败,而不会启动 shim 或启用命令 shell。
 
-必需 GitHub 矩阵会在 `windows-2025` 上构建 `node24-win-x64`,与现有三个目标并列。公开 GitHub 发布与 GitLab 标签流水线都会发布同一组四个运行时 wheel 加纯 SDK wheel。目标解析、manifest、矩阵、发布内容与文档均不包含 Windows arm64。
+必需 GitHub 矩阵会在 `windows-2025` 上构建 `node24-win-x64`,与 Linux x64、Linux arm64、macOS arm64 和 macOS x64 并列。公开 GitHub 发布与 GitLab 标签流水线都会发布同一组五个运行时 wheel 加纯 SDK wheel。目标解析、manifest、矩阵、发布内容与文档均不包含 Windows arm64。
 
 ### Installed-wheel 行为
 
@@ -48,4 +48,4 @@ Windows lane 会创建干净的 Windows 虚拟环境,安装版本精确匹配
 
 ## Consequences
 
-Python 安装现在会选择无需 Node 的 Windows x64 运行时,并与 Linux、macOS 使用同一套显式 home 与 profile 自定义模型。每个拉取请求都要承担第四个可执行文件、运行时 wheel 与完整 keyless 黑盒测试;可信 head 还要承担真实提供方任务。候选发行版验证会保留五个而不是四个 wheel。Windows arm64 用户会收到明确的不支持平台错误,直到另一项原生产品决策提供并证明该载体。
+Python 安装会选择无需 Node 的 Windows x64 运行时,并与 Linux、macOS 使用同一套显式 home 与 profile 自定义模型。每个拉取请求都会把 Windows 可执行文件和运行时 wheel 作为五个原生目标之一进行构建,运行完整 keyless 黑盒测试,并在可信 head 上运行真实提供方任务。候选发行版验证会保留六个 wheel。Windows arm64 用户会收到明确的不支持平台错误,直到另一项原生产品决策提供并证明该载体。

+ 2 - 2
.agents/notes/implemented/process/2026-08-11-python-publication-workflow.i18n.yaml

@@ -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-11-python-publication-workflow.md
-2026-08-11-python-publication-workflow.md: 282bd453013da9b745c601f7b1f4be2cbd133629
-2026-08-11-python-publication-workflow.zh.md: 279dc4b5798d5ceb5968f92c58a7f57c4f2c5cdd
+2026-08-11-python-publication-workflow.md: afb18ee97d0708d8a79885a8f6639681e97eef72
+2026-08-11-python-publication-workflow.zh.md: f2d045f686c41c3e45a3cd6739dc5e1b37c58478

+ 3 - 3
.agents/notes/implemented/process/2026-08-11-python-publication-workflow.md

@@ -6,15 +6,15 @@ English | [中文](2026-08-11-python-publication-workflow.zh.md)
 
 ## Problem
 
-The Python SDK comprises one platform-independent client wheel and four native runtime wheels that must carry one version and become installable as a set. Public PyPI uploads expose package metadata and files immediately, cannot replace an uploaded filename, and create a temporarily unusable SDK if its exact runtime dependency has not arrived. The private repository needs to exercise the complete native build and validation sequence without publishing any artifact externally.
+The Python SDK comprises one platform-independent client wheel and five native runtime wheels that must carry one version and become installable as a set. Public PyPI uploads expose package metadata and files immediately, cannot replace an uploaded filename, and create a temporarily unusable SDK if its exact runtime dependency has not arrived. The private repository needs to exercise the complete native build and validation sequence without publishing any artifact externally.
 
 ## Decision
 
-The `Release (Python)` GitHub workflow exposes credential-free validation to manual runs with `publish=false`. The run calls the native wheel builder for all four platforms, installs the Linux release set on Python 3.10 and 3.14, downloads the five resulting artifacts, verifies their exact filenames and package metadata, enforces PyPI's default per-file size limit, records SHA-256 hashes, and retains one aggregate release candidate. These jobs have only repository read permission and no registry credential or OIDC permission, and a dry run cannot enter either publication job.
+The `Release (Python)` GitHub workflow exposes credential-free validation to manual runs with `publish=false`. The run calls the native wheel builder for all five targets, installs the Linux release set on Python 3.10 and 3.14, downloads the six resulting artifacts, verifies their exact filenames and package metadata, enforces PyPI's default per-file size limit, records SHA-256 hashes, and retains one aggregate release candidate. These jobs have only repository read permission and no registry credential or OIDC permission, and a dry run cannot enter either publication job.
 
 A run with `publish=true` must use the `python-v<repository-version>` tag in the private automation repository, match that repository's `github.repository` to its repository-scoped `PYPI_PUBLISHER_REPOSITORY` variable, find `PUBLIC_PYPI_RELEASE_ENABLED=true`, and receive approval from the `pypi-runtime` and `pypi` GitHub environments for runtime and SDK publication, respectively. The read-only public mirror supplies the package metadata URLs but does not run release Actions. Only the two publication jobs receive `id-token: write`; PyPI Trusted Publishing exchanges the private repository identity for short-lived project credentials, so the repository stores no PyPI token.
 
-Publication consumes the aggregate artifact produced and checked in the same workflow run. Each publication job verifies the retained `SHA256SUMS` before selecting its upload set. A runtime job uploads all four platform wheels before a dependent job uploads the SDK wheel because PyPI uploads are not atomic and the SDK pins the runtime distribution at the exact same version. Neither job checks out source or rebuilds a wheel. Separating them lets GitHub's failed-job retry resume an SDK failure without attempting to replace immutable runtime files.
+Publication consumes the aggregate artifact produced and checked in the same workflow run. Each publication job verifies the retained `SHA256SUMS` before selecting its upload set. A runtime job uploads all five platform wheels before a dependent job uploads the SDK wheel because PyPI uploads are not atomic and the SDK pins the runtime distribution at the exact same version. Neither job checks out source or rebuilds a wheel. Separating them lets GitHub's failed-job retry resume an SDK failure without attempting to replace immutable runtime files.
 
 Both publication actions disable public attestations. The action still uses Trusted Publishing for authentication, while omitting provenance that would disclose the private publisher repository instead of the public source mirror.
 

+ 3 - 3
.agents/notes/implemented/process/2026-08-11-python-publication-workflow.zh.md

@@ -6,15 +6,15 @@ Status: implemented
 
 ## 问题
 
-Python SDK 由一个平台无关的客户端 wheel 包和四个原生运行时 wheel 包组成,它们必须使用同一版本,并作为一组可安装。public PyPI 上传会立即公开包元数据和文件,无法替换已上传的同名文件;如果精确版本的运行时依赖尚未到达,还会产生暂时不可用的 SDK。私有仓库需要在不向外发布任何产物的情况下,执行完整的原生构建与验证流程。
+Python SDK 由一个平台无关的客户端 wheel 包和五个原生运行时 wheel 包组成,它们必须使用同一版本,并作为一组可安装。public PyPI 上传会立即公开包元数据和文件,无法替换已上传的同名文件;如果精确版本的运行时依赖尚未到达,还会产生暂时不可用的 SDK。私有仓库需要在不向外发布任何产物的情况下,执行完整的原生构建与验证流程。
 
 ## 决策
 
-GitHub 的 `Release (Python)` 工作流为设置 `publish=false` 的手动运行提供无凭据验证。该运行会为全部四个平台调用原生 wheel 包构建器,在 Python 3.10 和 3.14 上安装 Linux 发行集合,下载所得五份产物,验证其精确文件名和包元数据,执行 PyPI 默认单文件大小限制,记录 SHA-256 哈希,并保留一份汇总候选发行版。这些作业只有仓库读取权限,没有注册表凭据或 OIDC 权限,dry-run 运行无法进入任何发布作业。
+GitHub 的 `Release (Python)` 工作流为设置 `publish=false` 的手动运行提供无凭据验证。该运行会为全部五个目标调用原生 wheel 包构建器,在 Python 3.10 和 3.14 上安装 Linux 发行集合,下载所得六份产物,验证其精确文件名和包元数据,执行 PyPI 默认单文件大小限制,记录 SHA-256 哈希,并保留一份汇总候选发行版。这些作业只有仓库读取权限,没有注册表凭据或 OIDC 权限,dry-run 运行无法进入任何发布作业。
 
 设置 `publish=true` 时,运行必须在私有自动化仓库使用 `python-v<repository-version>` 标签,将该仓库的 `github.repository` 与其仓库级 `PYPI_PUBLISHER_REPOSITORY` 变量匹配,找到 `PUBLIC_PYPI_RELEASE_ENABLED=true`,并分别获得 GitHub `pypi-runtime` 和 `pypi` 环境对运行时与 SDK 发布的批准。只读公开镜像提供包元数据 URL,但不运行发布 Actions。只有两个发布作业获得 `id-token: write`;PyPI Trusted Publishing 会把私有仓库身份换成短期项目凭据,因此仓库不保存 PyPI token。
 
-发布过程使用同一次工作流运行中生成并检查过的汇总产物。每个发布作业都会在选择上传文件前验证保留的 `SHA256SUMS`。一个运行时作业先上传全部四个平台 wheel 包,再由依赖它的作业上传 SDK wheel 包,因为 PyPI 上传不是原子操作,而 SDK 会把运行时分发包固定到完全相同的版本。两个作业都不会检出源码,也不会重新构建 wheel 包。将它们拆开后,GitHub 的失败作业重试可以在 SDK 上传失败时继续执行,而不会尝试替换不可变的运行时文件。
+发布过程使用同一次工作流运行中生成并检查过的汇总产物。每个发布作业都会在选择上传文件前验证保留的 `SHA256SUMS`。一个运行时作业先上传全部五个平台 wheel 包,再由依赖它的作业上传 SDK wheel 包,因为 PyPI 上传不是原子操作,而 SDK 会把运行时分发包固定到完全相同的版本。两个作业都不会检出源码,也不会重新构建 wheel 包。将它们拆开后,GitHub 的失败作业重试可以在 SDK 上传失败时继续执行,而不会尝试替换不可变的运行时文件。
 
 两个发布 action 都会禁用公开 attestation。action 仍使用 Trusted Publishing 进行身份认证,同时不上传会披露私有发布仓库而非公开源码镜像的 provenance。
 

+ 2 - 2
.agents/notes/implemented/testing/2026-08-23-installed-python-wheel-black-box-ci.i18n.yaml

@@ -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/testing/2026-08-23-installed-python-wheel-black-box-ci.md
-2026-08-23-installed-python-wheel-black-box-ci.md: 0ac3bc63ef391536a761ad6db9d0854a3beebe01
-2026-08-23-installed-python-wheel-black-box-ci.zh.md: 365da458d3eb33dbc82dcdafaebea593cc4fe971
+2026-08-23-installed-python-wheel-black-box-ci.md: a1c5d5f0a8040747caa2148f6b4990fd58828cbe
+2026-08-23-installed-python-wheel-black-box-ci.zh.md: ab2b6c11a2aa49a78bad990b780019f704edef51

+ 3 - 3
.agents/notes/implemented/testing/2026-08-23-installed-python-wheel-black-box-ci.md

@@ -30,7 +30,7 @@ Fork and Dependabot pull requests never receive the repository secret. Their nat
 
 ### Required targets
 
-The pull-request `python-runtime` job calls the reusable builder for Linux x64, Linux arm64, macOS arm64, and Windows x64. Its aggregate result remains a dependency of `all checks passed`, so a failed, cancelled, or missing native carrier blocks the required verdict. The [Windows x64 runtime decision](../architecture/2026-08-23-python-sdk-windows-x64-runtime.md) owns the fourth target and its PowerShell-specific minimal snapshot.
+The pull-request `python-runtime` job calls the reusable builder for Linux x64, Linux arm64, macOS arm64, macOS x64, and Windows x64. Its aggregate result remains a dependency of `all checks passed`, so a failed, cancelled, or missing native carrier blocks the required verdict. The [Windows x64 runtime decision](../architecture/2026-08-23-python-sdk-windows-x64-runtime.md) owns the Windows target and its PowerShell-specific minimal snapshot.
 
 ## Existing decisions and supersession
 
@@ -38,7 +38,7 @@ This decision supersedes the single-target topology in the archived [required Py
 
 ## Alternatives considered
 
-**Keep Linux x64 as the only required carrier.** Rejected because native addons, executable construction, wheel tags, and helper files differ across the four published targets. Release-time discovery is too late for an artifact that every Python SDK installation selects by platform.
+**Keep Linux x64 as the only required carrier.** Rejected because native addons, executable construction, wheel tags, and helper files differ across the five published targets. Release-time discovery is too late for an artifact that every Python SDK installation selects by platform.
 
 **Run full behavior before wheel construction and keep two small installed smokes.** Rejected because that proves the executable against source imports, then proves too little through the distribution users install. The clean installed environment is the stronger common location for the same scenarios.
 
@@ -48,4 +48,4 @@ This decision supersedes the single-target topology in the archived [required Py
 
 ## Consequences
 
-Every pull request pays for four native executable and wheel builds plus deterministic installed-artifact scenarios. Trusted same-repository pull requests also pay for one two-turn DeepSeek task per target. In exchange, the required result describes the files Python users install, proves every published carrier before merge, and cannot pass by importing the checkout or silently skipping the real provider.
+Every pull request pays for five native executable and wheel builds plus deterministic installed-artifact scenarios. Trusted same-repository pull requests also pay for one two-turn DeepSeek task per target. In exchange, the required result describes the files Python users install, proves every published carrier before merge, and cannot pass by importing the checkout or silently skipping the real provider.

+ 3 - 3
.agents/notes/implemented/testing/2026-08-23-installed-python-wheel-black-box-ci.zh.md

@@ -30,7 +30,7 @@ Fork 与 Dependabot 拉取请求永远不会获得仓库密钥。它们的原生
 
 ### 必需目标
 
-拉取请求的 `python-runtime` job 会针对 Linux x64、Linux arm64、macOS arm64 与 Windows x64 调用可复用构建器。其聚合结果仍是 `all checks passed` 的依赖项,因此任一原生载体失败、取消或缺失都会阻止必需判定通过。[Windows x64 运行时决策](../architecture/2026-08-23-python-sdk-windows-x64-runtime.zh.md)负责第四个目标及其 PowerShell 专属极简快照。
+拉取请求的 `python-runtime` job 会针对 Linux x64、Linux arm64、macOS arm64、macOS x64 与 Windows x64 调用可复用构建器。其聚合结果仍是 `all checks passed` 的依赖项,因此任一原生载体失败、取消或缺失都会阻止必需判定通过。[Windows x64 运行时决策](../architecture/2026-08-23-python-sdk-windows-x64-runtime.zh.md)负责 Windows 目标及其 PowerShell 专属极简快照。
 
 ## Existing decisions and supersession
 
@@ -38,7 +38,7 @@ Fork 与 Dependabot 拉取请求永远不会获得仓库密钥。它们的原生
 
 ## Alternatives considered
 
-**只保留 Linux x64 必需载体。** 否决:四个已发布目标的原生 addon、可执行文件构建、wheel 包标签与 helper 文件不同。等到发布时才发现问题,对每个 Python SDK 安装都会按平台选择的产物而言太晚。
+**只保留 Linux x64 必需载体。** 否决:五个已发布目标的原生 addon、可执行文件构建、wheel 包标签与 helper 文件不同。等到发布时才发现问题,对每个 Python SDK 安装都会按平台选择的产物而言太晚。
 
 **在 wheel 构建前运行完整行为,并保留两个很小的安装后冒烟测试。** 否决:这只能证明可执行文件配合源码 import 工作,再通过 distribution 证明很少的行为。干净安装环境是在同一批场景中验证用户实际安装内容的更强位置。
 
@@ -48,4 +48,4 @@ Fork 与 Dependabot 拉取请求永远不会获得仓库密钥。它们的原生
 
 ## Consequences
 
-每个拉取请求都会承担四个原生可执行文件及 wheel 包构建,并运行确定性的安装后产物场景。可信的同仓库拉取请求还会在每个目标上承担一次双轮 DeepSeek 任务。相应地,必需结果描述 Python 用户实际安装的文件,在合并前证明每个已发布载体,并且不能通过导入 checkout 或静默跳过真实提供方而通过。
+每个拉取请求都会承担五个原生可执行文件及 wheel 包构建,并运行确定性的安装后产物场景。可信的同仓库拉取请求还会在每个目标上承担一次双轮 DeepSeek 任务。相应地,必需结果描述 Python 用户实际安装的文件,在合并前证明每个已发布载体,并且不能通过导入 checkout 或静默跳过真实提供方而通过。

+ 22 - 10
.github/workflows/build-exe-for-python-sdk.yml

@@ -2,7 +2,7 @@ name: Build single-exe
 
 # Native builds for the release targets; see
 # .agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.md.
-# A full target run retains one SDK wheel and four runtime wheels; subset
+# A full target run retains one SDK wheel and five runtime wheels; subset
 # dispatch retains the SDK wheel and selected runtime wheels. Bare executables
 # and source closures are test inputs. Run manually or call it from the Python
 # release workflow. There is no `pull_request` trigger: a label trigger would
@@ -12,7 +12,7 @@ on:
   workflow_call:
     inputs:
       targets:
-        description: Comma-separated pkg targets to build; empty builds all four.
+        description: Comma-separated pkg targets to build; empty builds all five.
         type: string
         required: false
         default: ''
@@ -36,7 +36,7 @@ on:
         description: >-
           Comma-separated pkg targets to build. Any subset of:
           node24-linux-x64, node24-linux-arm64, node24-macos-arm64,
-          node24-win-x64. Empty builds all four.
+          node24-macos-x64, node24-win-x64. Empty builds all five.
         type: string
         required: false
         default: ''
@@ -89,7 +89,7 @@ jobs:
         id: plan
         env:
           # Blank dispatch inputs build all targets.
-          TARGETS: ${{ inputs.targets || 'node24-linux-x64,node24-linux-arm64,node24-macos-arm64,node24-win-x64' }}
+          TARGETS: ${{ inputs.targets || 'node24-linux-x64,node24-linux-arm64,node24-macos-arm64,node24-macos-x64,node24-win-x64' }}
         run: |
           set -euo pipefail
           matrix='[]'
@@ -98,14 +98,15 @@ jobs:
             t="$(echo "$raw" | xargs)" # trim surrounding whitespace
             [ -z "$t" ] && continue
             # Native-only: hosted arm64 Linux uses ubuntu-24.04-arm, while
-            # macos-latest is Apple Silicon.
+            # macos-latest is Apple Silicon; macos-15-intel is native x64.
             case "$t" in
               node24-linux-x64)   runner=ubuntu-latest ;;
               node24-linux-arm64) runner=ubuntu-24.04-arm ;;
               node24-macos-arm64) runner=macos-latest ;;
+              node24-macos-x64)   runner=macos-15-intel ;;
               node24-win-x64)     runner=windows-2025 ;;
               *)
-                echo "::error::Unknown target '$t'. Supported: node24-linux-x64, node24-linux-arm64, node24-macos-arm64, node24-win-x64."
+                echo "::error::Unknown target '$t'. Supported: node24-linux-x64, node24-linux-arm64, node24-macos-arm64, node24-macos-x64, node24-win-x64."
                 exit 1
                 ;;
             esac
@@ -251,6 +252,7 @@ jobs:
             linux-x64) wheel=deepseek_harness_runtime_bin-$VERSION-py3-none-manylinux_2_28_x86_64.whl ;;
             linux-arm64) wheel=deepseek_harness_runtime_bin-$VERSION-py3-none-manylinux_2_28_aarch64.whl ;;
             macos-arm64) wheel=deepseek_harness_runtime_bin-$VERSION-py3-none-macosx_14_0_arm64.whl ;;
+            macos-x64) wheel=deepseek_harness_runtime_bin-$VERSION-py3-none-macosx_14_0_x86_64.whl ;;
             *) echo "::error::Unsupported runtime platform $platform"; exit 1 ;;
           esac
           [ -x "$exe" ] || { echo "::error::$exe missing or not executable"; exit 1; }
@@ -432,13 +434,23 @@ jobs:
             exit 1
           }
 
-      - name: Check macOS deployment target
+      - name: Check macOS payload architecture and deployment target
         if: runner.os == 'macOS'
         env:
           EXE: ${{ steps.runtime-posix.outputs.exe }}
-        run: >-
-          python3 scripts/check-macos-deployment-target.py
-          "$EXE" "$EXE-spawn-helper"
+          PLATFORM: ${{ steps.runtime-posix.outputs.platform }}
+        run: |
+          set -euo pipefail
+          case "$PLATFORM" in
+            macos-arm64) macho_arch=arm64 ;;
+            macos-x64) macho_arch=x86_64 ;;
+            *) echo "::error::Unsupported macOS platform $PLATFORM"; exit 1 ;;
+          esac
+          for payload in "$EXE" "$EXE-rg" "$EXE-spawn-helper"; do
+            lipo "$payload" -verify_arch "$macho_arch"
+          done
+          python3 scripts/check-macos-deployment-target.py \
+            --platform "$PLATFORM" "$EXE" "$EXE-rg" "$EXE-spawn-helper"
 
       - name: Run wheel in a manylinux 2.28 container
         if: runner.os == 'Linux'

+ 1 - 1
.github/workflows/ci.yml

@@ -328,7 +328,7 @@ jobs:
     name: python runtime / release-shaped matrix
     uses: ./.github/workflows/build-exe-for-python-sdk.yml
     with:
-      targets: node24-linux-x64,node24-linux-arm64,node24-macos-arm64,node24-win-x64
+      targets: node24-linux-x64,node24-linux-arm64,node24-macos-arm64,node24-macos-x64,node24-win-x64
       ci: true
     secrets:
       DEEPSEEK_API_KEY_EXTERNAL: ${{ secrets.DEEPSEEK_API_KEY_EXTERNAL }}

+ 3 - 2
.github/workflows/python-release.yml

@@ -24,10 +24,10 @@ concurrency:
 
 jobs:
   build:
-    name: Build five wheels
+    name: Build six wheels
     uses: ./.github/workflows/build-exe-for-python-sdk.yml
     with:
-      targets: node24-linux-x64,node24-linux-arm64,node24-macos-arm64,node24-win-x64
+      targets: node24-linux-x64,node24-linux-arm64,node24-macos-arm64,node24-macos-x64,node24-win-x64
       release: true
 
   python-compat:
@@ -149,6 +149,7 @@ jobs:
           actual="$(mktemp)"
           printf '%s\n' \
             "deepseek_harness_runtime_bin-$VERSION-py3-none-macosx_14_0_arm64.whl" \
+            "deepseek_harness_runtime_bin-$VERSION-py3-none-macosx_14_0_x86_64.whl" \
             "deepseek_harness_runtime_bin-$VERSION-py3-none-manylinux_2_28_aarch64.whl" \
             "deepseek_harness_runtime_bin-$VERSION-py3-none-manylinux_2_28_x86_64.whl" \
             "deepseek_harness_runtime_bin-$VERSION-py3-none-win_amd64.whl" \

+ 24 - 3
.gitlab-ci.yml

@@ -60,8 +60,16 @@ sdk-wheel:
         docker run --rm -v "$PWD:/work" -w /work "$image" bash -euxo pipefail -c "/opt/python/cp310-cp310/bin/python -m venv /tmp/dsh-sdk && /tmp/dsh-sdk/bin/python -m pip install --find-links /work/release/$PLATFORM --find-links /work/release/sdk deepseek-harness-sdk==$DSH_WHEEL_VERSION && /tmp/dsh-sdk/bin/python /work/scripts/smoke-python-runtime.py --scenario sdk-default && /tmp/dsh-sdk/bin/python /work/scripts/smoke-python-runtime.py --scenario sdk-mcp"
       fi
     - |
-      if [ "$PLATFORM" = macos-arm64 ]; then
-        python3 scripts/check-macos-deployment-target.py "$EXE" "$EXE-spawn-helper"
+      if [ "${PLATFORM#macos-}" != "$PLATFORM" ]; then
+        case "$PLATFORM" in
+          macos-arm64) macho_arch=arm64 ;;
+          macos-x64) macho_arch=x86_64 ;;
+          *) echo "Unsupported macOS platform $PLATFORM"; exit 1 ;;
+        esac
+        for payload in "$EXE" "$EXE-rg" "$EXE-spawn-helper"; do
+          lipo "$payload" -verify_arch "$macho_arch"
+        done
+        python3 scripts/check-macos-deployment-target.py --platform "$PLATFORM" "$EXE" "$EXE-rg" "$EXE-spawn-helper"
       fi
   artifacts:
     paths: [release/$PLATFORM/*.whl]
@@ -97,6 +105,16 @@ runtime-macos-arm64:
     - job: sdk-wheel
       artifacts: true
 
+runtime-macos-x64:
+  extends: .runtime-wheel
+  tags: [macos-x64]
+  variables:
+    PKG_TARGET: node24-macos-x64
+    PLATFORM: macos-x64
+  needs:
+    - job: sdk-wheel
+      artifacts: true
+
 runtime-windows-x64:
   stage: build
   tags: [windows-x64]
@@ -147,6 +165,8 @@ publish-python:
       artifacts: true
     - job: runtime-macos-arm64
       artifacts: true
+    - job: runtime-macos-x64
+      artifacts: true
     - job: runtime-windows-x64
       artifacts: true
   before_script:
@@ -157,11 +177,12 @@ publish-python:
     - test "$CI_COMMIT_TAG" = "python-v$DSH_VERSION" || { echo "Tag $CI_COMMIT_TAG does not match package.json version $DSH_VERSION"; exit 1; }
     - python -m pip install twine==6.2.0
   script:
-    - test "$(find release -name '*.whl' | wc -l | tr -d ' ')" = 5
+    - test "$(find release -name '*.whl' | wc -l | tr -d ' ')" = 6
     - test -f "release/sdk/deepseek_harness_sdk-${DSH_WHEEL_VERSION}-py3-none-any.whl"
     - test -f "release/linux-x64/deepseek_harness_runtime_bin-${DSH_WHEEL_VERSION}-py3-none-manylinux_2_28_x86_64.whl"
     - test -f "release/linux-arm64/deepseek_harness_runtime_bin-${DSH_WHEEL_VERSION}-py3-none-manylinux_2_28_aarch64.whl"
     - test -f "release/macos-arm64/deepseek_harness_runtime_bin-${DSH_WHEEL_VERSION}-py3-none-macosx_14_0_arm64.whl"
+    - test -f "release/macos-x64/deepseek_harness_runtime_bin-${DSH_WHEEL_VERSION}-py3-none-macosx_14_0_x86_64.whl"
     - test -f "release/win-x64/deepseek_harness_runtime_bin-${DSH_WHEEL_VERSION}-py3-none-win_amd64.whl"
     - python -m twine check release/*/*.whl
     - export TWINE_USERNAME=gitlab-ci-token

+ 10 - 2
packages/shell/tool-pwsh-persistent/tests/loader-composition.spec.ts

@@ -95,11 +95,19 @@ describe.skipIf(!hasPwsh)('persistent pwsh through a real cordis.yml Loader comp
       '    idleSilenceMs: 300',
       '    handoffGraceMs: 300',
       '    scrollbackLines: 20000',
-      '    timeoutMs: 60000',
+      // The first call pays the full pwsh cold-start latency (spawn + .NET +
+      // PSReadLine + Defender) inside the tool deadline; a 60s bound on the
+      // fully loaded self-hosted Windows pool is exceeded often enough to
+      // reset the session mid-test (2026-09-01, two runs ~62s each). 300s
+      // matches the dsh-tool-pwsh-persistent product default; the
+      // dsh-terminal-bash value bounds one send plus the complete startup
+      // sequence, so it covers the same cold start (its 30s product default
+      // would not).
+      '    timeoutMs: 300000',
       '    disposeGraceMs: 500',
       "- name: '@deepseek-ai/dsh-tool-pwsh-persistent'",
       '  config:',
-      '    timeoutMs: 60000',
+      '    timeoutMs: 300000',
       '',
     ].join('\n'))
 

+ 2 - 2
python/development.i18n.yaml

@@ -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 python/development.md
-development.md: 72acaec2b3ec2142fc176d940f1a2854e44ebad8
-development.zh.md: 8bd17ad7e604b1cdc4456053bcec95c9e8e503cb
+development.md: aa0144d7eaa66711d0f08316d4445da060918ca8
+development.zh.md: a35f6fc8de1bdbd282fd8999a1440fde0c400b34

+ 3 - 3
python/development.md

@@ -13,7 +13,7 @@ pnpm install
 pnpm exec tsx scripts/build-exe-for-python-sdk.ts
 ```
 
-Use `--skip-build` when the required `lib/` artifacts already exist, or `--targets=node24-linux-x64,node24-linux-arm64,node24-macos-arm64,node24-win-x64` to select platforms. Build each target on its native architecture. Products land in `dist-exe/` and the script syncs the selected carriers into `python/sdk-runtime/`. Windows emits `.exe` and `-rg.exe`; macOS also syncs the matching spawn helper required by `node-pty`.
+Use `--skip-build` when the required `lib/` artifacts already exist, or `--targets=node24-linux-x64,node24-linux-arm64,node24-macos-arm64,node24-macos-x64,node24-win-x64` to select platforms. Build each target on its native architecture. Products land in `dist-exe/` and the script syncs the selected carriers into `python/sdk-runtime/`. Windows emits `.exe` and `-rg.exe`; macOS also syncs the matching spawn helper required by `node-pty`.
 
 ## Validate the SDK
 
@@ -79,11 +79,11 @@ pip install \
   "dist-python/deepseek_harness_runtime_bin-$version-py3-none-macosx_14_0_arm64.whl"
 ```
 
-The runtime distribution is wheel-only. The release pipeline publishes four platform wheels with the pure SDK wheel: Linux x64, Linux arm64, macOS 14 or newer on arm64, and Windows x64 (`win_amd64`). A `python-v<repository-version>` tag is accepted only when it matches the repository version; prerelease repository versions such as `0.0.1-rc.1` use their normalized PEP 440 spelling, such as `0.0.1rc1`, inside wheel filenames and metadata.
+The runtime distribution is wheel-only. The release pipeline publishes five platform wheels with the pure SDK wheel: Linux x64, Linux arm64, macOS 14 or newer on arm64 and x64, and Windows x64 (`win_amd64`). A `python-v<repository-version>` tag is accepted only when it matches the repository version; prerelease repository versions such as `0.0.1-rc.1` use their normalized PEP 440 spelling, such as `0.0.1rc1`, inside wheel filenames and metadata.
 
 ## Validate a release candidate
 
-Manually run the GitHub `Release (Python)` workflow with `publish=false` to build all five wheels, install the Linux release set on Python 3.10 and 3.14, check exact filenames and metadata, enforce PyPI's default per-file size limit, and retain one aggregate artifact with SHA-256 hashes. The run has no registry credentials; a dry run cannot enter either publication job.
+Manually run the GitHub `Release (Python)` workflow with `publish=false` to build all six wheels, install the Linux release set on Python 3.10 and 3.14, check exact filenames and metadata, enforce PyPI's default per-file size limit, and retain one aggregate artifact with SHA-256 hashes. The run has no registry credentials; a dry run cannot enter either publication job.
 
 Public publication runs from the private automation repository. Package metadata points to the separate read-only public source mirror, which does not run release Actions. The private repository defines the repository variable `PYPI_PUBLISHER_REPOSITORY` as its own `owner/name` and keeps `PUBLIC_PYPI_RELEASE_ENABLED=false` except during an intentional release.
 

+ 3 - 3
python/development.zh.md

@@ -13,7 +13,7 @@ pnpm install
 pnpm exec tsx scripts/build-exe-for-python-sdk.ts
 ```
 
-所需 `lib/` 产物已存在时使用 `--skip-build`;如需选择平台,请使用 `--targets=node24-linux-x64,node24-linux-arm64,node24-macos-arm64,node24-win-x64`。每个目标都应在其原生架构上构建。产物写入 `dist-exe/`,脚本会将所选载体同步到 `python/sdk-runtime/`。Windows 会生成 `.exe` 与 `-rg.exe`;macOS 构建还会同步 `node-pty` 所需的配套 spawn 辅助程序。
+所需 `lib/` 产物已存在时使用 `--skip-build`;如需选择平台,请使用 `--targets=node24-linux-x64,node24-linux-arm64,node24-macos-arm64,node24-macos-x64,node24-win-x64`。每个目标都应在其原生架构上构建。产物写入 `dist-exe/`,脚本会将所选载体同步到 `python/sdk-runtime/`。Windows 会生成 `.exe` 与 `-rg.exe`;macOS 构建还会同步 `node-pty` 所需的配套 spawn 辅助程序。
 
 ## 验证 SDK
 
@@ -79,11 +79,11 @@ pip install \
   "dist-python/deepseek_harness_runtime_bin-$version-py3-none-macosx_14_0_arm64.whl"
 ```
 
-运行时分发包仅提供 wheel 包。发布流水线会连同纯 SDK wheel 包一起发布四个平台 wheel 包:Linux x64、Linux arm64、macOS 14 或更高版本的 arm64,以及 Windows x64(`win_amd64`)。只有与仓库版本匹配时,才接受 `python-v<repository-version>` 标签;`0.0.1-rc.1` 之类的仓库预发布版本在 wheel 包文件名和元数据中使用规范化的 PEP 440 写法,例如 `0.0.1rc1`。
+运行时分发包仅提供 wheel 包。发布流水线会连同纯 SDK wheel 包一起发布五个平台 wheel 包:Linux x64、Linux arm64、macOS 14 或更高版本的 arm64 与 x64,以及 Windows x64(`win_amd64`)。只有与仓库版本匹配时,才接受 `python-v<repository-version>` 标签;`0.0.1-rc.1` 之类的仓库预发布版本在 wheel 包文件名和元数据中使用规范化的 PEP 440 写法,例如 `0.0.1rc1`。
 
 ## 验证候选发行版
 
-手动运行 GitHub 的 `Release (Python)` 工作流并设置 `publish=false`,即可构建全部五个 wheel 包,在 Python 3.10 和 3.14 上安装 Linux 发行集合,检查精确文件名和元数据,执行 PyPI 默认单文件大小限制,并保留一份带 SHA-256 哈希的汇总产物。该运行没有注册表凭据,dry-run 运行无法进入任何发布作业。
+手动运行 GitHub 的 `Release (Python)` 工作流并设置 `publish=false`,即可构建全部六个 wheel 包,在 Python 3.10 和 3.14 上安装 Linux 发行集合,检查精确文件名和元数据,执行 PyPI 默认单文件大小限制,并保留一份带 SHA-256 哈希的汇总产物。该运行没有注册表凭据,dry-run 运行无法进入任何发布作业。
 
 公开发布从私有自动化仓库运行。包元数据指向独立的只读公开源码镜像,该镜像不运行发布 Actions。私有仓库把仓库变量 `PYPI_PUBLISHER_REPOSITORY` 定义为自身的 `owner/name`,并且只在有意发布期间把 `PUBLIC_PYPI_RELEASE_ENABLED` 从 `false` 改为 `true`。
 

+ 2 - 2
python/sdk-runtime/README.i18n.yaml

@@ -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 python/sdk-runtime/README.md
-README.md: 28695259928a7edc6e6cf67e737f1012729df5a4
-README.zh.md: f23b253cfe47d9f1ae24568b51d9db810c7a4a9f
+README.md: 050ae85d9b0a38b82a3c66a84c3d8f34e137be6c
+README.zh.md: 7066d7224752294c25b58cfe8fb6a94524a2013d

+ 1 - 1
python/sdk-runtime/README.md

@@ -8,7 +8,7 @@ Platform runtime wheel for the DeepSeek Harness Python SDK. It packages the norm
 
 The wheel installs a `dsh` console command and the `deepseek_harness_runtime` Python module. `dsh` forwards its arguments to the bundled executable and requires a non-empty `DSH_HOME`; it never falls back to `~/.dsh`.
 
-Production executables are named `deepseek-harness-sdk-runtime-<platform>-<arch>` under the module's `runtime/` directory; Windows uses the `.exe` suffix. Linux and macOS wheels include a target-native `-rg` sidecar, Windows includes `-rg.exe`, and macOS also includes `-spawn-helper` for `node-pty`. Published targets are Linux x64, Linux arm64, macOS arm64, and Windows x64. The wheel tag and payload must match exactly; no Windows arm64 wheel is published.
+Production executables are named `deepseek-harness-sdk-runtime-<platform>-<arch>` under the module's `runtime/` directory; Windows uses the `.exe` suffix. Linux and macOS wheels include a target-native `-rg` sidecar, Windows includes `-rg.exe`, and macOS also includes `-spawn-helper` for `node-pty`. Published targets are Linux x64, Linux arm64, macOS arm64, macOS x64, and Windows x64. The wheel tag and payload must match exactly; no Windows arm64 wheel is published.
 
 Repository builds also materialize a dev-only `runtime/node/` carrier. It runs `node runtime/node/node_modules/@deepseek-ai/dsh/lib/bin.js` on system Node 22.19 or newer. It is never selected automatically and is excluded from wheels and sdists.
 

+ 1 - 1
python/sdk-runtime/README.zh.md

@@ -8,7 +8,7 @@ DeepSeek Harness Python SDK 的平台运行时 wheel。它把普通 `dsh` CLI 
 
 Wheel 会安装 `dsh` 控制台命令和 `deepseek_harness_runtime` Python 模块。`dsh` 将参数转发给内置可执行程序,并要求非空 `DSH_HOME`;它不会回退到 `~/.dsh`。
 
-生产可执行程序位于模块的 `runtime/` 目录,命名为 `deepseek-harness-sdk-runtime-<platform>-<arch>`;Windows 使用 `.exe` 后缀。Linux 与 macOS wheel 包含目标平台原生的 `-rg` 伴随程序,Windows 包含 `-rg.exe`,macOS 还包含 `node-pty` 使用的 `-spawn-helper`。已发布目标是 Linux x64、Linux arm64、macOS arm64 与 Windows x64。Wheel tag 必须与载荷严格匹配;不发布 Windows arm64 wheel。
+生产可执行程序位于模块的 `runtime/` 目录,命名为 `deepseek-harness-sdk-runtime-<platform>-<arch>`;Windows 使用 `.exe` 后缀。Linux 与 macOS wheel 包含目标平台原生的 `-rg` 伴随程序,Windows 包含 `-rg.exe`,macOS 还包含 `node-pty` 使用的 `-spawn-helper`。已发布目标是 Linux x64、Linux arm64、macOS arm64、macOS x64 与 Windows x64。Wheel tag 必须与载荷严格匹配;不发布 Windows arm64 wheel。
 
 仓库构建还会物化仅限开发的 `runtime/node/` 载体。它在系统 Node 22.19 或更高版本上运行 `node runtime/node/node_modules/@deepseek-ai/dsh/lib/bin.js`。系统不会自动选择它,而且 wheel 与 sdist 均不包含它。
 

+ 4 - 0
python/sdk-runtime/platforms.json

@@ -11,6 +11,10 @@
     "tag": "macosx_14_0_arm64",
     "executable": "deepseek-harness-sdk-runtime-macos-arm64"
   },
+  "macos-x64": {
+    "tag": "macosx_14_0_x86_64",
+    "executable": "deepseek-harness-sdk-runtime-macos-x64"
+  },
   "win-x64": {
     "tag": "win_amd64",
     "executable": "deepseek-harness-sdk-runtime-win-x64.exe"

+ 1 - 2
python/sdk-runtime/src/deepseek_harness_runtime/__init__.py

@@ -120,12 +120,11 @@ def _current_platform_tag() -> str:
         plat is None
         or arch is None
         or (plat == "win" and arch != "x64")
-        or (plat == "macos" and arch != "arm64")
     ):
         raise FileNotFoundError(
             "no bundled DeepSeek Harness SDK runtime exists for this platform "
             f"(sys.platform={sys.platform!r}, machine={platform.machine()!r}); supported: "
-            "Linux x64/arm64, macOS arm64, and Windows x64. " + _EXE_ACQUISITION_HINT
+            "Linux x64/arm64, macOS x64/arm64, and Windows x64. " + _EXE_ACQUISITION_HINT
         )
     return f"{plat}-{arch}"
 

+ 30 - 1
python/sdk/tests/test_macos_deployment_target.py

@@ -16,8 +16,15 @@ checker = SimpleNamespace(**runpy.run_path(str(SCRIPT)))
 
 def test_otool_parser_uses_the_newest_macho_slice() -> None:
     output = """
+Load command 8
+      cmd LC_VERSION_MIN_MACOSX
+  cmdsize 16
+  version 10.7
+      sdk 11.1
+Load command 9
       cmd LC_BUILD_VERSION
     minos 11.0
+Load command 10
       cmd LC_BUILD_VERSION
     minos 13.5
     """
@@ -26,12 +33,34 @@ def test_otool_parser_uses_the_newest_macho_slice() -> None:
 
 
 def test_otool_parser_requires_a_deployment_target() -> None:
-    with pytest.raises(ValueError, match="contains no LC_BUILD_VERSION"):
+    with pytest.raises(ValueError, match="contains no macOS deployment target"):
         checker.parse_otool_deployment_target("Load command 0\n")
 
 
+def test_otool_parser_ignores_unrelated_version_fields() -> None:
+    output = """
+Load command 1
+          cmd LC_ID_DYLIB
+      cmdsize 48
+      current version 14.1.0
+compatibility version 1.0.0
+    """
+
+    with pytest.raises(ValueError, match="contains no macOS deployment target"):
+        checker.parse_otool_deployment_target(output)
+
+
 def test_wheel_tag_rejects_a_newer_executable_target() -> None:
     checker.ensure_compatible(Path("runtime"), (13, 5), "macosx_14_0_arm64")
+    checker.ensure_compatible(Path("runtime-x64"), (10, 7), "macosx_14_0_x86_64")
 
     with pytest.raises(RuntimeError, match="requires macOS 14.1"):
         checker.ensure_compatible(Path("spawn-helper"), (14, 1), "macosx_14_0_arm64")
+
+
+def test_wheel_tag_accepts_only_supported_macos_architectures() -> None:
+    assert checker.claimed_version("macosx_14_0_arm64") == (14, 0)
+    assert checker.claimed_version("macosx_14_0_x86_64") == (14, 0)
+
+    with pytest.raises(ValueError, match="unsupported macOS wheel platform tag"):
+        checker.claimed_version("macosx_14_0_universal2")

+ 3 - 1
python/sdk/tests/test_release_version.py

@@ -60,6 +60,8 @@ def test_pep440_version_spells_a_prerelease_the_python_way() -> None:
 def test_macos_wheel_tag_does_not_claim_unsupported_node_platforms() -> None:
     assert build_python_release.PLATFORMS["macos-arm64"][0] == "macosx_14_0_arm64"
     assert build_python_release.PLATFORMS["macos-arm64"][1] == "deepseek-harness-sdk-runtime-macos-arm64"
+    assert build_python_release.PLATFORMS["macos-x64"][0] == "macosx_14_0_x86_64"
+    assert build_python_release.PLATFORMS["macos-x64"][1] == "deepseek-harness-sdk-runtime-macos-x64"
 
 
 def test_windows_wheel_tag_and_payload_are_x64_only() -> None:
@@ -95,7 +97,7 @@ def test_stage_sdk_keeps_distribution_module_and_runtime_pin_distinct(tmp_path:
 
 @pytest.mark.parametrize(
     ("target", "with_helper"),
-    [("linux-x64", False), ("macos-arm64", True), ("win-x64.exe", False)],
+    [("linux-x64", False), ("macos-arm64", True), ("macos-x64", True), ("win-x64.exe", False)],
 )
 def test_stage_runtime_copies_platform_payload(
     tmp_path: Path, target: str, with_helper: bool

+ 2 - 3
python/sdk/tests/test_runtime_resolution.py

@@ -79,12 +79,11 @@ def test_current_platform_supports_windows_x64_only(monkeypatch: pytest.MonkeyPa
         runtime._current_platform_tag()
 
 
-def test_current_platform_rejects_macos_x64(monkeypatch: pytest.MonkeyPatch) -> None:
+def test_current_platform_supports_macos_x64(monkeypatch: pytest.MonkeyPatch) -> None:
     monkeypatch.setattr(runtime.sys, "platform", "darwin")
     monkeypatch.setattr(runtime.platform, "machine", lambda: "x86_64")
 
-    with pytest.raises(FileNotFoundError, match="macOS arm64"):
-        runtime._current_platform_tag()
+    assert runtime._current_platform_tag() == "macos-x64"
 
 
 def test_runtime_requires_ripgrep_sidecar(

+ 13 - 0
scripts/build-exe-for-python-sdk.spec.ts

@@ -59,6 +59,19 @@ describe('Python runtime executable builder CLI', () => {
     expect(result.stdout).not.toMatch(/pnpm\.cmd/i)
   })
 
+  it('accepts the macOS x64 pkg target', () => {
+    const result = run(
+      { npm_execpath: 'C:\\tools\\pnpm.cjs' },
+      '--skip-build',
+      '--dry-run',
+      '--targets=node24-macos-x64',
+    )
+
+    expect(result.status).toBe(0)
+    expect(result.stdout).toContain('exec pkg')
+    expect(result.stdout).toContain('--sea --targets node24-macos-x64')
+  })
+
   it('rejects a Windows arm64 product before any build step', () => {
     const result = run(
       { npm_execpath: 'C:\\tools\\pnpm.cjs' },

+ 1 - 1
scripts/build-exe-for-python-sdk.ts

@@ -207,7 +207,7 @@ class BuildCli {
     return [
       'Usage: pnpm exec tsx scripts/build-exe-for-python-sdk.ts [flags]',
       '',
-      '  --targets=<t1,t2,...>  pkg targets, e.g. node24-linux-x64,node24-linux-arm64,node24-macos-arm64,node24-win-x64.',
+      '  --targets=<t1,t2,...>  pkg targets, e.g. node24-linux-x64,node24-linux-arm64,node24-macos-arm64,node24-macos-x64,node24-win-x64.',
       '                         Default: the host platform only (on node24).',
       '  --skip-build           skip `pnpm run build` (lib/ artifacts must already exist).',
       '  --dry-run              print every command and config patch without executing.',

+ 26 - 10
scripts/check-macos-deployment-target.py

@@ -12,7 +12,11 @@ from pathlib import Path
 
 ROOT = Path(__file__).resolve().parents[1]
 RELEASE = runpy.run_path(str(ROOT / "scripts" / "build-python-release.py"))
-MACOS_PLATFORM_TAG = RELEASE["PLATFORMS"]["macos-arm64"][0]
+MACOS_PLATFORMS = {
+    name: details[0]
+    for name, details in RELEASE["PLATFORMS"].items()
+    if name.startswith("macos-")
+}
 
 
 def parse_version(value: str) -> tuple[int, ...]:
@@ -24,7 +28,7 @@ def parse_version(value: str) -> tuple[int, ...]:
 
 def claimed_version(platform_tag: str) -> tuple[int, ...]:
     """Return the minimum macOS version encoded by a wheel platform tag."""
-    match = re.fullmatch(r"macosx_(\d+)_(\d+)_arm64", platform_tag)
+    match = re.fullmatch(r"macosx_(\d+)_(\d+)_(?:arm64|x86_64)", platform_tag)
     if match is None:
         raise ValueError(f"unsupported macOS wheel platform tag: {platform_tag!r}")
     return int(match.group(1)), int(match.group(2))
@@ -32,12 +36,22 @@ def claimed_version(platform_tag: str) -> tuple[int, ...]:
 
 def parse_otool_deployment_target(output: str) -> tuple[int, ...]:
     """Return the newest deployment target from one or more Mach-O slices."""
-    versions = [
-        parse_version(match.group(1))
-        for match in re.finditer(r"^\s*minos\s+(\d+(?:\.\d+)*)\s*$", output, re.MULTILINE)
-    ]
+    versions: list[tuple[int, ...]] = []
+    command: str | None = None
+    for line in output.splitlines():
+        stripped = line.strip()
+        if re.fullmatch(r"Load command \d+", stripped):
+            command = None
+        elif stripped == "cmd LC_BUILD_VERSION":
+            command = "build"
+        elif stripped == "cmd LC_VERSION_MIN_MACOSX":
+            command = "minimum"
+        elif command == "build" and (match := re.fullmatch(r"minos\s+(\d+(?:\.\d+)*)", stripped)):
+            versions.append(parse_version(match.group(1)))
+        elif command == "minimum" and (match := re.fullmatch(r"version\s+(\d+(?:\.\d+)*)", stripped)):
+            versions.append(parse_version(match.group(1)))
     if not versions:
-        raise ValueError("otool output contains no LC_BUILD_VERSION deployment target")
+        raise ValueError("otool output contains no macOS deployment target load command")
     return max(versions)
 
 
@@ -73,7 +87,7 @@ def ensure_compatible(
 
 
 def validate_deployment_targets(
-    executables: list[Path], platform_tag: str = MACOS_PLATFORM_TAG
+    executables: list[Path], platform_tag: str
 ) -> list[tuple[Path, tuple[int, ...]]]:
     """Validate every executable and return its measured deployment target."""
     measured = [(executable, deployment_target(executable)) for executable in executables]
@@ -84,11 +98,13 @@ def validate_deployment_targets(
 
 def main() -> None:
     parser = argparse.ArgumentParser(description=__doc__)
+    parser.add_argument("--platform", choices=tuple(MACOS_PLATFORMS), required=True)
     parser.add_argument("executables", type=Path, nargs="+")
     args = parser.parse_args()
-    for executable, version in validate_deployment_targets(args.executables):
+    platform_tag = MACOS_PLATFORMS[args.platform]
+    for executable, version in validate_deployment_targets(args.executables, platform_tag):
         rendered = ".".join(str(part) for part in version)
-        print(f"{executable}: macOS {rendered} <= {MACOS_PLATFORM_TAG}")
+        print(f"{executable}: macOS {rendered} <= {platform_tag}")
 
 
 if __name__ == "__main__":

+ 29 - 8
scripts/ci-workflow.spec.ts

@@ -370,7 +370,7 @@ describe('CI workflow', () => {
       name: 'python runtime / release-shaped matrix',
       uses: './.github/workflows/build-exe-for-python-sdk.yml',
       with: {
-        targets: 'node24-linux-x64,node24-linux-arm64,node24-macos-arm64,node24-win-x64',
+        targets: 'node24-linux-x64,node24-linux-arm64,node24-macos-arm64,node24-macos-x64,node24-win-x64',
         ci: true,
       },
       secrets: {
@@ -462,7 +462,7 @@ describe('Python release workflows', () => {
     expect(build).toMatchObject({
       uses: './.github/workflows/build-exe-for-python-sdk.yml',
       with: {
-        targets: 'node24-linux-x64,node24-linux-arm64,node24-macos-arm64,node24-win-x64',
+        targets: 'node24-linux-x64,node24-linux-arm64,node24-macos-arm64,node24-macos-x64,node24-win-x64',
         release: true,
       },
     })
@@ -531,7 +531,7 @@ describe('Python release workflows', () => {
 
     const buildSteps: unknown[] = build.steps
     const manylinuxAddon = buildSteps.find(step => isRecord(step) && step.name === 'Rebuild Linux node-pty against manylinux 2.28')
-    const macosCheck = buildSteps.find(step => isRecord(step) && step.name === 'Check macOS deployment target')
+    const macosCheck = buildSteps.find(step => isRecord(step) && step.name === 'Check macOS payload architecture and deployment target')
     const manylinuxSmoke = buildSteps.find(step => isRecord(step) && step.name === 'Run wheel in a manylinux 2.28 container')
     const cleanVenvPosix = buildSteps.find(step => isRecord(step) && step.name === 'Install local SDK and runtime wheels into a clean venv (POSIX)')
     const cleanVenvWindows = buildSteps.find(step => isRecord(step) && step.name === 'Install local SDK and runtime wheels into a clean venv (Windows)')
@@ -541,7 +541,8 @@ describe('Python release workflows', () => {
     const realApiPreflightWindows = buildSteps.find(step => isRecord(step) && step.name === 'Preflight installed-wheel real API test (Windows)')
     const installedRealApiPosix = buildSteps.find(step => isRecord(step) && step.name === 'Run installed-wheel real API black-box test (POSIX)')
     const installedRealApiWindows = buildSteps.find(step => isRecord(step) && step.name === 'Run installed-wheel real API black-box test (Windows)')
-    if (!isRecord(cleanVenvPosix) || !isRecord(cleanVenvWindows)
+    if (!isRecord(macosCheck) || typeof macosCheck.run !== 'string'
+      || !isRecord(cleanVenvPosix) || !isRecord(cleanVenvWindows)
       || !isRecord(installedKeylessPosix) || !isRecord(installedKeylessWindows)
       || !isRecord(realApiPreflightPosix) || !isRecord(realApiPreflightWindows)
       || !isRecord(installedRealApiPosix) || !isRecord(installedRealApiWindows)) {
@@ -564,6 +565,9 @@ describe('Python release workflows', () => {
     expect(JSON.stringify(plan.steps)).toContain('pep440_version')
     const workflowJson = JSON.stringify(workflow)
     expect(workflowJson).toContain('macosx_14_0_arm64')
+    expect(workflowJson).toContain('macosx_14_0_x86_64')
+    expect(workflowJson).toContain('node24-macos-x64')
+    expect(workflowJson).toContain('macos-15-intel')
     expect(workflowJson).toContain('win_amd64')
     expect(workflowJson).toContain('node24-win-x64')
     expect(workflowJson).toContain('windows-2025')
@@ -583,8 +587,10 @@ describe('Python release workflows', () => {
     expect(JSON.stringify(manylinuxAddon)).toContain('node-pty-glibc-versions.txt')
     expect(JSON.stringify(manylinuxAddon)).toContain('le 2.28')
     expect(macosCheck).toMatchObject({ if: "runner.os == 'macOS'" })
-    expect(JSON.stringify(macosCheck)).toContain('scripts/check-macos-deployment-target.py')
-    expect(JSON.stringify(macosCheck)).toContain('$EXE-spawn-helper')
+    expect(macosCheck.run).toContain('scripts/check-macos-deployment-target.py')
+    expect(macosCheck.run).toContain('lipo "$payload" -verify_arch')
+    expect(macosCheck.run).toContain('$EXE-rg')
+    expect(macosCheck.run).toContain('$EXE-spawn-helper')
     expect(JSON.stringify(installedKeylessPosix)).toContain('--scenario all')
     expect(JSON.stringify(installedKeylessPosix)).toContain('env -u PYTHONPATH')
     expect(JSON.stringify(installedKeylessWindows)).toContain('--scenario all --installed-wheel')
@@ -620,14 +626,29 @@ describe('Python release workflows', () => {
     }
     const runtimeScript: unknown[] = runtimeWheel.script
     const macosCheck = runtimeScript.find(
-      step => typeof step === 'string' && step.includes('PLATFORM" = macos-arm64'),
+      step => typeof step === 'string' && step.includes('${PLATFORM#macos-}'),
     )
     if (typeof macosCheck !== 'string') {
       throw new TypeError('GitLab CI must check the macOS deployment target')
     }
 
     expect(macosCheck).toContain('scripts/check-macos-deployment-target.py')
-    expect(macosCheck).toContain('"$EXE" "$EXE-spawn-helper"')
+    expect(macosCheck).toContain('lipo "$payload" -verify_arch')
+    expect(macosCheck).toContain('"$EXE" "$EXE-rg" "$EXE-spawn-helper"')
+  })
+
+  it('builds the macOS x64 wheel on the matching GitLab runner', () => {
+    const workflow = loadWorkflow('.gitlab-ci.yml')
+    const macosX64 = workflow['runtime-macos-x64']
+    const publish = workflow['publish-python']
+    if (!isRecord(macosX64) || !isRecord(publish) || !Array.isArray(publish.needs)) {
+      throw new TypeError('GitLab CI must define the macOS x64 runtime and publication jobs')
+    }
+
+    expect(macosX64.tags).toEqual(['macos-x64'])
+    expect(macosX64.variables).toMatchObject({ PKG_TARGET: 'node24-macos-x64', PLATFORM: 'macos-x64' })
+    expect(publish.needs).toContainEqual({ job: 'runtime-macos-x64', artifacts: true })
+    expect(JSON.stringify(publish.script)).toContain('macosx_14_0_x86_64.whl')
   })
 
   it('builds and black-box tests the Windows x64 wheel in GitLab', () => {

+ 4 - 3
scripts/verify-runtime-closure.spec.ts

@@ -21,6 +21,7 @@ const platforms = {
   'linux-x64': { tag: 'manylinux_2_28_x86_64', executable: 'runtime-linux-x64' },
   'linux-arm64': { tag: 'manylinux_2_28_aarch64', executable: 'runtime-linux-arm64' },
   'macos-arm64': { tag: 'macosx_14_0_arm64', executable: 'runtime-macos-arm64' },
+  'macos-x64': { tag: 'macosx_14_0_x86_64', executable: 'runtime-macos-x64' },
   'win-x64': { tag: 'win_amd64', executable: 'runtime-win-x64.exe' },
 }
 
@@ -64,7 +65,7 @@ describe('verifyRuntimeClosure', () => {
     expect(result.presetCount).toBe(1)
     expect(result.failures).toEqual([
       'standard preset -> @scope/linux (linux-arm64, linux-x64)',
-      'standard preset -> @scope/macos (macos-arm64)',
+      'standard preset -> @scope/macos (macos-arm64, macos-x64)',
       'standard preset -> @scope/windows (win-x64)',
     ])
   })
@@ -83,7 +84,7 @@ describe('verifyRuntimeClosure', () => {
     const result = await verifyRuntimeClosure(root)
 
     expect(result.failures).toEqual([
-      'standard preset -> @scope/conditional (linux-arm64, linux-x64, macos-arm64, win-x64)',
+      'standard preset -> @scope/conditional (linux-arm64, linux-x64, macos-arm64, macos-x64, win-x64)',
     ])
   })
 
@@ -117,7 +118,7 @@ describe('verifyRuntimeClosure', () => {
     const result = await verifyRuntimeClosure(root)
 
     expect(result.failures).toEqual([
-      'standard preset -> @scope/plugin [runtime dependency is "1.2.3"; expected workspace:] (linux-arm64, linux-x64, macos-arm64, win-x64)',
+      'standard preset -> @scope/plugin [runtime dependency is "1.2.3"; expected workspace:] (linux-arm64, linux-x64, macos-arm64, macos-x64, win-x64)',
     ])
   })
 

Некоторые файлы не были показаны из-за большого количества измененных файлов