fix(code-runtime-python): correct Chinese translation quality

- Translate README.zh.md's Model Experience body and KV Cache line, which
  were left verbatim in English.
- Convert half-width punctuation to full-width across the README.zh.md
  Known Limitations bullets and the entire Agent Note Chinese side, per
  docs/i18n translation-rules.md Typography (MUST use ,。:()in Chinese prose).
- Re-record both README and Agent Note i18n.yaml pairing hashes.
- Reword the workspace-constraints extra-files comment: this layer's py/
  ships only the wire-protocol mirror; the spawned bootstrap arrives later.
This commit is contained in:
Chinesezjc
2026-08-07 13:27:54 +08:00
parent 8a77f201f2
commit 31506dec2d
4 changed files with 19 additions and 19 deletions
@@ -3,4 +3,4 @@
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-31-code-runtime-python-fd3-protocol.md
2026-07-31-code-runtime-python-fd3-protocol.md: 32cc80278af6b5f894c8d972854dae8c92ac63b7
2026-07-31-code-runtime-python-fd3-protocol.zh.md: ea8df78826dabf64c0132dc61952c533481e1444
2026-07-31-code-runtime-python-fd3-protocol.zh.md: 24bb9dbb7b8df03c5c82c551449f49b4d306f248
@@ -6,38 +6,38 @@ Status: implemented
## Problem
CPython code-runtime 后端(`@deepseek-ai/dsh-code-runtime-python`,分多个 PR 落地)在一个全新的 `python3 -I` 子进程里运行每个模型程序,并把 binding 调用和完成值通过子进程的 fd 3 桥接。这条通道需要两侧一致的 wire protocol,而 host 不能信任它:模型代码对 fd 3 有完全访问权、可以伪造任意帧,所以每个入站帧都是 host 必须先校验并重建才能读取的敌意输入。协议还必须承载无深度限制的 lossless JSON,因为 seam 的 `CodeJsonValue` 深度无界,`JSON.stringify`/`json.dumps` 都有递归深度限制。
CPython code-runtime 后端`@deepseek-ai/dsh-code-runtime-python`分多个 PR 落地在一个全新的 `python3 -I` 子进程里运行每个模型程序并把 binding 调用和完成值通过子进程的 fd 3 桥接。这条通道需要两侧一致的 wire protocol而 host 不能信任它模型代码对 fd 3 有完全访问权、可以伪造任意帧所以每个入站帧都是 host 必须先校验并重建才能读取的敌意输入。协议还必须承载无深度限制的 lossless JSON因为 seam 的 `CodeJsonValue` 深度无界`JSON.stringify`/`json.dumps` 都有递归深度限制。
本层只交付这个协议,使得庞大的 `PythonCodeRuntime` 实现及其真子进程集成测试能落在一个已 review 的 wire contract 之上,而不是与它揉在一起到达。父 stack 把 [#436](https://github.com/deepseek-harness/deepseek-harness/pull/436)——一个 9000 行的单一 PR——拆成可 review 的层;本 PR 是协议层,base 是 [seam 扩展](2026-07-31-code-runtime-portable-identifier-seam.md)。
本层只交付这个协议使得庞大的 `PythonCodeRuntime` 实现及其真子进程集成测试能落在一个已 review 的 wire contract 之上而不是与它揉在一起到达。父 stack 把 [#436](https://github.com/deepseek-harness/deepseek-harness/pull/436)——一个 9000 行的单一 PR——拆成可 review 的层本 PR 是协议层base 是 [seam 扩展](2026-07-31-code-runtime-portable-identifier-seam.md)。
## Decision
`src/protocol.ts` 是 wire vocabulary 的 host 侧及其敌意帧编解码:
`src/protocol.ts` 是 wire vocabulary 的 host 侧及其敌意帧编解码
- **`validateChildFrame`** 对每个入站帧做形状校验并重建。编译期 union 在 fd 3 上毫无意义——伪造帧可携带 `null`、被污染的字段,或省略必需字段——所以每个被接受的帧都逐字段重建:伪造的额外字段绝不随行,非有限的 call id 绝不会被回显进 reply,垃圾返回 `undefined` 被丢弃,而不是在 host 的 message handler 里抛错。
- **`encodeJsonPlain` / `checkDoneValue` / `hasUnsafeIntegerToken` / `hasNonLosslessNumber`** 是 lossless-JSON 编解码器与计量器。它们迭代遍历(显式栈,非递归),使低于字节预算的深层值能完整穿越;`checkDoneValue` 把字节计量和数字无损性折进一次有界遍历,在把子节点入栈之前就拒绝超预算 payload,防止一个低于帧上限的伪造值迫使 host 分配数百 MB。超出安全范围的整数型 double 通过 `BigInt` 数字序列化,穿越的是精确整数而非 `String()` 的舍入形式。
- **`validateChildFrame`** 对每个入站帧做形状校验并重建。编译期 union 在 fd 3 上毫无意义——伪造帧可携带 `null`、被污染的字段或省略必需字段——所以每个被接受的帧都逐字段重建伪造的额外字段绝不随行非有限的 call id 绝不会被回显进 reply垃圾返回 `undefined` 被丢弃而不是在 host 的 message handler 里抛错。
- **`encodeJsonPlain` / `checkDoneValue` / `hasUnsafeIntegerToken` / `hasNonLosslessNumber`** 是 lossless-JSON 编解码器与计量器。它们迭代遍历显式栈非递归),使低于字节预算的深层值能完整穿越`checkDoneValue` 把字节计量和数字无损性折进一次有界遍历在把子节点入栈之前就拒绝超预算 payload防止一个低于帧上限的伪造值迫使 host 分配数百 MB。超出安全范围的整数型 double 通过 `BigInt` 数字序列化穿越的是精确整数而非 `String()` 的舍入形式。
- **`logTruncationMarker`** 产出日志 ledger 耗尽字节预算时发出的带内标记文本。
`py/protocol.py``TypedDict` 镜像消息形状,并重新声明两侧都会 EXECUTE 的两个面——`PROTOCOL_FD = 3``log_truncation_marker`——文本逐字节一致。
`py/protocol.py``TypedDict` 镜像消息形状并重新声明两侧都会 EXECUTE 的两个面——`PROTOCOL_FD = 3``log_truncation_marker`——文本逐字节一致。
包骨架(`package.json``tsconfig.json``tsdown.config.ts``src/index.ts``src/invariant.ts`、README 三件套)在此交付,而非放到后续 stack 层:`check-workspace-constraints` 无条件读取每个 `packages/<group>/<pkg>` 的 package.json,coverage 与 invariant-topology gate 也要求包在其目录出现的那一刻即存在且可构建。后续的 backend-core PR 会用 `PythonCodeRuntime` 扩展 `src/index.ts` 并增补 `package.json` 的依赖;因为它 base 在本分支上,那些是编辑,不是冲突。
包骨架`package.json``tsconfig.json``tsdown.config.ts``src/index.ts``src/invariant.ts`、README 三件套在此交付而非放到后续 stack 层`check-workspace-constraints` 无条件读取每个 `packages/<group>/<pkg>` 的 package.jsoncoverage 与 invariant-topology gate 也要求包在其目录出现的那一刻即存在且可构建。后续的 backend-core PR 会用 `PythonCodeRuntime` 扩展 `src/index.ts` 并增补 `package.json` 的依赖因为它 base 在本分支上那些是编辑不是冲突。
## Wire contract
帧是 fd 3 上的 JSON-lines,每行一个对象,让 stdout/stderr 空出给程序自己的输出。Child → host:`boot-ack``call``log``done`。Host → child:`boot`(首帧)`run`(`boot-ack` 之后)、以及每个 `call` 对应一个 `reply``log` 帧的 `truncated` 标志标记那个本身就是子进程 ledger 截断标记的帧,使 host 在与子进程相同的点停止捕获,而不是从自己的预算去推断。`done.error.kind``exception``invalid-output``output-limit` 之一;wall/CPU 预算、abort、substrate 死亡都在 host 侧观测,不作为帧携带。
帧是 fd 3 上的 JSON-lines每行一个对象让 stdout/stderr 空出给程序自己的输出。Child → host`boot-ack``call``log``done`。Host → child`boot`首帧`run``boot-ack` 之后、以及每个 `call` 对应一个 `reply``log` 帧的 `truncated` 标志标记那个本身就是子进程 ledger 截断标记的帧使 host 在与子进程相同的点停止捕获而不是从自己的预算去推断。`done.error.kind``exception``invalid-output``output-limit` 之一wall/CPU 预算、abort、substrate 死亡都在 host 侧观测不作为帧携带。
## Mirror alignment
#436 的 round-12 review 发现 `py/protocol.py` 相对 `src/protocol.ts` 有三处声明陈旧——`LogMessage` 缺 `truncated`、`DoneMessage.error` 缺 `kind`、`Namespace` 缺可选的 `errorClass`。本 PR 在搬运该文件时对齐了这三处,不把陈旧镜像带过来。由于这些声明是 `TypedDict`(在受信任的 Python 侧无运行时强制),自动化 guard 只覆盖两侧都会执行的部分:`tests/protocol-mirror.e2e.ts` 启动一个真实 `python3`,从 `py/protocol.py` 读取 `PROTOCOL_FD` 与 `log_truncation_marker`,并在若干字节预算下断言它们等于 TypeScript 常量。
#436 的 round-12 review 发现 `py/protocol.py` 相对 `src/protocol.ts` 有三处声明陈旧——`LogMessage` 缺 `truncated`、`DoneMessage.error` 缺 `kind`、`Namespace` 缺可选的 `errorClass`。本 PR 在搬运该文件时对齐了这三处不把陈旧镜像带过来。由于这些声明是 `TypedDict`在受信任的 Python 侧无运行时强制),自动化 guard 只覆盖两侧都会执行的部分`tests/protocol-mirror.e2e.ts` 启动一个真实 `python3`从 `py/protocol.py` 读取 `PROTOCOL_FD` 与 `log_truncation_marker`并在若干字节预算下断言它们等于 TypeScript 常量。
## Alternatives considered
**把 Python JSON codec(`_encode_json_plain` / `_decode_json_plain`)挪进 `py/protocol.py` 以与 `protocol.ts` 跨侧对称。** 拒绝。仓库的 "prefer symmetry for parallel values" 规则指向真正平行的值;这两者不是。`protocol.ts` 里的 host 侧 codec 校验的是敌意输入,自包含。Python codec 在受信任侧产出输出,且耦合于 bootstrap 内部 helper(`_Emit``_dump_scalar`/`_dump_string`/`_dump_float``LogBuffer` 的成本核算、`_check_done_value``_lossless_json_violation`);只把两个入口挪过去会把这一整片拖进 `protocol.py`,或制造 `bootstrap.py``protocol.py` 的 import 环。真正的跨侧平行是 "host 校验入站(`protocol.ts`) ↔ child 信任 host 并发出(`bootstrap.py`)",这个对称性被保留:`protocol.py` 保持它在 TS 侧一样的纯 wire-vocabulary 镜像定位。Python codec 留在 `bootstrap.py`,由 backend-core PR 交付。
**把 Python JSON codec`_encode_json_plain` / `_decode_json_plain`挪进 `py/protocol.py` 以与 `protocol.ts` 跨侧对称。** 拒绝。仓库的 prefer symmetry for parallel values 规则指向真正平行的值这两者不是。`protocol.ts` 里的 host 侧 codec 校验的是敌意输入自包含。Python codec 在受信任侧产出输出且耦合于 bootstrap 内部 helper`_Emit``_dump_scalar`/`_dump_string`/`_dump_float``LogBuffer` 的成本核算、`_check_done_value``_lossless_json_violation`);只把两个入口挪过去会把这一整片拖进 `protocol.py`或制造 `bootstrap.py``protocol.py` 的 import 环。真正的跨侧平行是 host 校验入站`protocol.ts` ↔ child 信任 host 并发出`bootstrap.py`)”,这个对称性被保留`protocol.py` 保持它在 TS 侧一样的纯 wire-vocabulary 镜像定位。Python codec 留在 `bootstrap.py`由 backend-core PR 交付。
**把包骨架推迟到"拥有" package.json 的 backend-core PR。** 拒绝:workspace-constraint、coverage、invariant-topology gate 会在 `code-runtime-python` 目录一存在而包不可构建时立即失败。stacked 拆分无法在一个尚不能编译的包里创建源文件。
**把包骨架推迟到拥有 package.json 的 backend-core PR。** 拒绝workspace-constraint、coverage、invariant-topology gate 会在 `code-runtime-python` 目录一存在而包不可构建时立即失败。stacked 拆分无法在一个尚不能编译的包里创建源文件。
## Consequences
收获:fd-3 协议及其敌意输入 codec 作为自包含、unit 全覆盖的一层落地,round-12 review 发现的 py/ts 镜像漂移被修复,并有一个执行中的 guard 防其复发。backend-core PR 建立在已 review 的 wire contract 之上。
收获fd-3 协议及其敌意输入 codec 作为自包含、unit 全覆盖的一层落地round-12 review 发现的 py/ts 镜像漂移被修复并有一个执行中的 guard 防其复发。backend-core PR 建立在已 review 的 wire contract 之上。
代价:`src/index.ts``package.json` 在此以最小形态引入,并由 backend-core PR 编辑(而非创建)`py/protocol.py` 中两个可执行面之外的 `TypedDict` 形状仍由 review 加后端真子进程套件守护,而非 mirror e2e 测试——这是跨语言比较类型声明的固有局限。
代价`src/index.ts``package.json` 在此以最小形态引入并由 backend-core PR 编辑而非创建`py/protocol.py` 中两个可执行面之外的 `TypedDict` 形状仍由 review 加后端真子进程套件守护而非 mirror e2e 测试——这是跨语言比较类型声明的固有局限。
@@ -3,4 +3,4 @@
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/code-runtime/code-runtime-python/README.md
README.md: f68a45a5420469555eeaf9f88463fbda547d1a1d
README.zh.md: 439d4ef87a26202cc6b537651fa0b768c28637a4
README.zh.md: fe7927e8f8c488ed6a7e6b9e5cdc76bc9dd3609c
@@ -17,13 +17,13 @@ host 与 CPython 子进程在子进程的 fd 3 上交换一个无版本号的 JS
## Model Experience
Indirectly, through Code Mode in [`dsh-tools`](../../core/tools/README.md), which renders this backend's exact completion value when it fits (or an explicit `invalid-output` / `output-limit` failure), plus the exact `[dsh-code-runtime-python] log capture truncated at <maxLogBytes> bytes` log marker, into a retained `run_code` result.
经由 [`dsh-tools`](../../core/tools/README.md) 里的 Code Mode 间接生效:Code Mode 把本后端的精确完成值(放得下时)或一个明确的 `invalid-output` / `output-limit` 失败,连同精确的 `[dsh-code-runtime-python] log capture truncated at <maxLogBytes> bytes` 日志标记,渲染进一个保留的 `run_code` 结果。
#### KV Cache effect
No direct invalidation; the named consumer owns any request-prefix changes.
无直接失效;具名消费者拥有任何请求前缀的变更。
## Known Limitations and Deferred Work
- **跨语言 guard 只覆盖两个运行时执行的面** —— `PROTOCOL_FD` 与日志截断标记。`py/protocol.py` 中的 `TypedDict` 帧形状靠 review 而非自动化检查来镜像 `src/protocol.ts`:跨 TypeScript 与 Python 比较类型声明在此无机械等价物,故未来的形状漂移由 review 加后端真子进程套件捕获,而非本包的测试。
- **`PythonCodeRuntime` 实现与 Python 侧 JSON codec 不在本层** —— 它们在基于本分支的 backend-core PR 中交付;在那之前 `src/index.ts` 只 re-export 协议词汇。
- **跨语言 guard 只覆盖两个运行时执行的面** —— `PROTOCOL_FD` 与日志截断标记。`py/protocol.py` 中的 `TypedDict` 帧形状靠 review 而非自动化检查来镜像 `src/protocol.ts`跨 TypeScript 与 Python 比较类型声明在此无机械等价物故未来的形状漂移由 review 加后端真子进程套件捕获而非本包的测试。
- **`PythonCodeRuntime` 实现与 Python 侧 JSON codec 不在本层** —— 它们在基于本分支的 backend-core PR 中交付在那之前 `src/index.ts` 只 re-export 协议词汇。