Przeglądaj źródła

docs(code-runtime-python): remove the ack-gate v8 ignore and align the remaining doc drift

The forged-second-boot-ack regression makes the re-entry guard covered, so its
v8 ignore is removed. Doc drift: the python README and run() JSDoc state the
resolve-with-value/resolve-with-error contract without inversion; the README
Known Limitations gains the setsid-escaped-orphan entry (the settlement note
referenced it); the settlement note drops the stale drops/discard phrasing and
the two 256 MiB references; the fd-3 protocol zh note no longer claims the
codec is undelivered; the code-runtime seam README (en + zh) says both
backends ship. Pairings re-recorded.
Chinesezjc 2 tygodni temu
rodzic
commit
d98965fbcc

+ 1 - 1
.agents/notes/implemented/architecture/2026-07-31-code-runtime-python-fd3-protocol.i18n.yaml

@@ -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: 671506aafbad1b03bc66ae137a58a7b11a836f79
-2026-07-31-code-runtime-python-fd3-protocol.zh.md: b12a7ba0ed0aadb0a1db57bcd59db93825bb4f40
+2026-07-31-code-runtime-python-fd3-protocol.zh.md: 1568f6366b4651fbb87fcfdfacdc274fa07b4d8e

+ 1 - 1
.agents/notes/implemented/architecture/2026-07-31-code-runtime-python-fd3-protocol.zh.md

@@ -32,7 +32,7 @@ Status: implemented
 
 ## 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 校验敌意输入且自包含。Child 侧 codec 会产出受信任输出,应与 bootstrap 拥有的发出逻辑和成本核算放在一起;只把入口强塞进 `protocol.py` 会让 vocabulary 镜像耦合 runtime 内部实现,或制造 import 环。`protocol.py` 保持纯 wire-vocabulary 镜像。本包尚未交付 Python codec
+**要求未来的 Python JSON codec(`_encode_json_plain` / `_decode_json_plain`)放进 `py/protocol.py`,以便与 `protocol.ts` 跨侧对称。**拒绝。仓库的 “prefer symmetry for parallel values” 规则指向真正平行的值;这两者不是。`protocol.ts` 中的 host 侧 codec 校验敌意输入且自包含。Child 侧 codec 会产出受信任输出,应与 bootstrap 拥有的发出逻辑和成本核算放在一起;只把入口强塞进 `protocol.py` 会让 vocabulary 镜像耦合 runtime 内部实现,或制造 import 环。`protocol.py` 保持纯 wire-vocabulary 镜像;codec(`_encode_json_plain`/`_decode_json_plain`)与它所服务的 runtime 一起位于 `bootstrap.py`
 
 **在 runtime 交付前把协议文件放在不可构建的包外。**拒绝:workspace-constraint、coverage 与 invariant-topology 检查要求 `packages/<group>/<pkg>` 下的每个目录都是可构建包,而协议本身拥有独立测试与公开 wire vocabulary。
 

+ 2 - 2
.agents/notes/implemented/bug-fix/2026-07-31-code-runtime-python-settlement-fixes.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/bug-fix/2026-07-31-code-runtime-python-settlement-fixes.md
-2026-07-31-code-runtime-python-settlement-fixes.md: 98c0df43bead1c12e7cc2d8b1960ba1d6d652b37
-2026-07-31-code-runtime-python-settlement-fixes.zh.md: 62d45d21b0dc6f88a9b10844c3b4c4c8cfa19901
+2026-07-31-code-runtime-python-settlement-fixes.md: de34c1ce448a1c866fede4c141f8c2af922d6c6b
+2026-07-31-code-runtime-python-settlement-fixes.zh.md: 5658a5ccf7acdeea869deb17faa0c03ebec516fa

Plik diff jest za duży
+ 1 - 1
.agents/notes/implemented/bug-fix/2026-07-31-code-runtime-python-settlement-fixes.md


Plik diff jest za duży
+ 1 - 1
.agents/notes/implemented/bug-fix/2026-07-31-code-runtime-python-settlement-fixes.zh.md


+ 2 - 2
packages/code-runtime/code-runtime-python/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 packages/code-runtime/code-runtime-python/README.md
-README.md: eab1adebcf3189d7bec812dd4b1a16a3e9d0a78c
-README.zh.md: d52545f3fcc8884341f3fdfad0d387808eafcd62
+README.md: 3d2b7631393a08d1980fc0a3fdf9c89e73077593
+README.zh.md: f91d712b947dcd6b57651f7744c5f49754190019

+ 2 - 1
packages/code-runtime/code-runtime-python/README.md

@@ -25,7 +25,7 @@ English | [中文](README.zh.md)
 <a id="use-this-package"></a>
 ## Use this package
 
-Choose this package to run Python model code through the code-runtime seam: register `PythonCodeRuntime` with `dsh-tools` and `run()` executes each program in a fresh `python3 -I` subprocess, resolves with an `error` FIELD for every program outcome (the orthogonal `CodeRunFailure.kind` taxonomy classifies parse failures, thrown exceptions, invalid completions, output overflows, budget expiry, aborts, and substrate death), and rejects only for seam misuse — a malformed binding namespace, or a call after disposal. Configuration is rejected at load: a non-Unix platform, a non-positive or non-integer budget, a `maxLogBytes` below the truncation-marker floor (64), a timer value `setTimeout` would clamp, a budget larger than one fd-3 frame can carry, and an `addressSpaceMb`/output-budget pair whose worst-case peak would breach `RLIMIT_AS`.
+Choose this package to run Python model code through the code-runtime seam: register `PythonCodeRuntime` with `dsh-tools` and `run()` executes each program in a fresh `python3 -I` subprocess, resolving with `result.value` on success and `result.error` on failure (the orthogonal `CodeRunFailure.kind` taxonomy classifies parse failures, thrown exceptions, invalid completions, output overflows, budget expiry, aborts, and substrate death). It rejects only for seam misuse — a malformed binding namespace, or a call after disposal. Configuration is rejected at load: a non-Unix platform, a non-positive or non-integer budget, a `maxLogBytes` below the truncation-marker floor (64), a timer value `setTimeout` would clamp, a budget larger than one fd-3 frame can carry, and an `addressSpaceMb`/output-budget pair whose worst-case peak would breach `RLIMIT_AS`.
 
 ### What you get
 
@@ -111,6 +111,7 @@ No direct invalidation; the named consumer owns any request-prefix changes.
 These limits define what the package does and does not cover; they are current package constraints, not a task backlog.
 
 - **The cross-language guard covers the executed surfaces and the frame field shapes, not the field types** — the mirror e2e compares required/optional field sets, not that `cpuSeconds` is an `int` on both sides; a type-level drift is caught by review plus the backend's real-subprocess suite.
+- **A descendant that escapes the child's process group with `setsid()` is not reaped by the group teardown** — `kill(-pid)` cannot reach it; the run still settles on the value the done frame decided, and the close-deadline backstop forces settlement if the orphan holds the pipes open, but the orphan itself outlives the fiber until it exits on its own.
 - **`run()` is one-shot** — `logs` become available only after `CodeRunResult` resolves; there is no streaming-log or progress interface for output produced by a running program.
 - **No state persists across runs** — every request executes in a fresh subprocess; a persistent REPL-style kernel stays deferred until a backend brings its own logging scheme.
 - **An fd-3 frame whose raw length exceeds 64 MiB settles the run as a worker-exit** — `maxLogBytes`/`maxValueBytes` are load-bounded to the same parser cap so an honest child's frames always fit; a model-constructed binding ARGUMENT above 64 MiB (a value with no seam-level budget) trips the same cap — an accepted residual of the OOM guard.

+ 2 - 1
packages/code-runtime/code-runtime-python/README.zh.md

@@ -25,7 +25,7 @@ kind: "package-reference"
 <a id="use-this-package"></a>
 ## 使用本包
 
-在需要通过 code-runtime seam 运行 Python 模型代码时选择本包:向 `dsh-tools` 注册 `PythonCodeRuntime`,`run()` 就在全新的 `python3 -I` 子进程中执行每个程序,并对每种程序结果都通过 resolve 结果的 error 字段报告(正交的 `CodeRunFailure.kind` 分类涵盖解析失败、抛出异常、无效完成值、输出溢出、预算到期、中止与执行基底终止);只有 seam 误用才 reject——绑定命名空间畸形,或已释放后仍调用。配置在加载期被拒绝:非 Unix 平台、非正或非整数的预算、低于截断标记下限(64)的 `maxLogBytes`、`setTimeout` 会收敛的定时器值、超过单个 fd-3 帧可承载的预算,以及最坏峰值会突破 `RLIMIT_AS` 的 `addressSpaceMb`/输出预算组合。
+在需要通过 code-runtime seam 运行 Python 模型代码时选择本包:向 `dsh-tools` 注册 `PythonCodeRuntime`,`run()` 就在全新的 `python3 -I` 子进程中执行每个程序,成功时以 `result.value` resolve、失败时以 `result.error` resolve(正交的 `CodeRunFailure.kind` 分类涵盖解析失败、抛出异常、无效完成值、输出溢出、预算到期、中止与执行基底终止);只有 seam 误用才 reject——绑定命名空间畸形,或已释放后仍调用。配置在加载期被拒绝:非 Unix 平台、非正或非整数的预算、低于截断标记下限(64)的 `maxLogBytes`、`setTimeout` 会收敛的定时器值、超过单个 fd-3 帧可承载的预算,以及最坏峰值会突破 `RLIMIT_AS` 的 `addressSpaceMb`/输出预算组合。
 
 ### 你得到什么
 
@@ -111,6 +111,7 @@ kind: "package-reference"
 这些限制定义本包覆盖与不覆盖的内容;它们是当前包约束,不是任务积压。
 
 - **跨语言 guard 覆盖执行的表面与帧字段形状,而非字段类型**——mirror e2e 比较必填/可选字段集,而非 `cpuSeconds` 在两侧是否都是 `int`;类型级漂移由评审加后端的真实子进程套件捕获。
+- **以 `setsid()` 逃出子进程组后代不被组拆卸回收**——`kill(-pid)` 够不到它;运行仍按 done 帧决定的值结算,若该孤儿持有管道,close 截止兜底会强制结算,但孤儿本身在自行退出前一直存活到 fiber 之外。
 - **`run()` 是一次性的**——`logs` 只有在 `CodeRunResult` resolve 后才能获得;没有为运行中程序产生的输出提供流式日志或进度接口。
 - **运行之间不保留状态**——每次请求都在全新子进程中执行;持久 REPL 风格内核在某个后端带来自己的日志方案之前保持延期。
 - **原始长度超过 64 MiB 的 fd-3 帧会让本次运行以 worker-exit 结算**——`maxLogBytes`/`maxValueBytes` 在加载期被限制到同一解析器上限,因此诚实子进程的帧总能放得下;模型构造的超过 64 MiB 的 binding 实参(一个在 seam 层没有预算的值)会触发同一上限——这是该 OOM 防护的已接受残余。

+ 5 - 6
packages/code-runtime/code-runtime-python/src/index.ts

@@ -874,11 +874,11 @@ export class PythonCodeRuntime extends CodeRuntime {
   }
 
   /**
-   * Execute one program in a fresh Python subprocess. Every program outcome —
-   * parse failure, thrown exception, invalid completion, output overflow,
-   * budget expiry, abort, or substrate death — resolves with `result.error` set
-   * (classified by `CodeRunFailure.kind`); the method rejects only for seam
-   * misuse.
+   * Execute one program in a fresh Python subprocess. Success resolves with
+   * `result.value` (and no `result.error`); failure — parse failure, thrown
+   * exception, invalid completion, output overflow, budget expiry, abort, or
+   * substrate death — resolves with `result.error` set (classified by
+   * `CodeRunFailure.kind`). The method rejects only for seam misuse.
    */
   async run(request: CodeRunRequest): Promise<CodeRunResult> {
     if (this.disposed) throw new Error('dsh-code-runtime-python: run() after disposal')
@@ -1995,7 +1995,6 @@ export class PythonCodeRuntime extends CodeRuntime {
       }
       // Register the ack gate with the frame handler before any data arrives.
       bootAckGate.run = (): void => {
-        /* v8 ignore next -- a forged second boot-ack would re-enter; the honest child sends exactly one. */
         if (runSent) return
         runSent = true
         try {

+ 2 - 2
packages/code-runtime/code-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 packages/code-runtime/code-runtime/README.md
-README.md: 56decf8fc86c37f08e0ee266006efabaf6436712
-README.zh.md: 46fd55891c84d971ed453791f44af831919b8bca
+README.md: 4e53febeb3f3db967420e2eec363e83132669dbc
+README.zh.md: fc7127e2d03d88baacde725d7cbaa1f05327a1f7

+ 2 - 2
packages/code-runtime/code-runtime/README.md

@@ -121,8 +121,8 @@ No direct invalidation; the named consumer owns any request-prefix changes.
 These limits define what the seam cannot do; they are current package constraints, not a task backlog.
 
 - **`run()` is one-shot** — `logs` arrive only on the resolved `CodeRunResult`; the seam exposes no streaming-log or progress API for a live program's output.
-- **A persistent REPL-style kernel is recorded future work** — the no-state-between-runs contract stands until a persistent-kernel backend brings its own logging story ([Code Mode Agent Note](../../../.agents/notes/implemented/feature/2026-06-15-code-mode.md)).
-- **The worker-thread and Python (process) backends ship; `'container'` is future work** — `'process'` is implemented by the `dsh-code-runtime-python` backend, while `'container'` remains a declared well-known `isolation` value with no implementation; a hard security boundary awaits a container backend.
+- **No state survives between runs** — every request runs against a fresh world; a persistent REPL-style kernel is deferred until a backend brings its own logging story.
+- **The worker-thread and Python (process) backends ship; `'container'` does not** — `'container'` is a declared well-known `isolation` value with no implementation; a hard security boundary awaits a container backend.
 - **Intermediate binding values have no byte cap** — implementations remain subject to structured-clone cost and process memory, while a provider or executor may already have imposed its own acquisition bound.
 
 <a id="dev-note"></a>

+ 2 - 2
packages/code-runtime/code-runtime/README.zh.md

@@ -121,8 +121,8 @@ binding-global 与 error-class 名称是语言可移植的:必须匹配标识
 这些限制说明 seam 不能做什么;它们是当前包约束,不是任务积压。
 
 - **`run()` 是一次性的**——`logs` 只有在 `CodeRunResult` resolve 后才能获得;seam 不提供正在运行的程序所产生输出的流式日志或进度接口。
-- **持久 REPL 风格内核已记录为未来工作**——在持久内核后端带来自己的日志方案前,运行之间不保留状态的约定继续有效(参见 [Code Mode Agent Note](../../../.agents/notes/implemented/feature/2026-06-15-code-mode.zh.md))
-- **目前提供 worker 线程与 Python(process)后端;`'container'` 是未来工作**——`'process'` 由 `dsh-code-runtime-python` 后端实现,而 `'container'` 仍是已声明但没有实现的已知 `isolation` 值;强安全边界需要等待容器后端。
+- **运行之间不保留状态**——每次请求都在全新环境中运行;持久 REPL 风格内核在某个后端带来自己的日志方案之前保持延期
+- **目前提供 worker 线程与 Python(process)后端;`'container'` 没有实现**——`'container'` 是已声明但没有实现的已知 `isolation` 值;强安全边界需要等待容器后端。
 - **中间绑定值没有字节上限**——实现仍受 structured-clone 成本与进程内存约束,而提供方或执行器可能已经应用自己的获取上限。
 
 <a id="dev-note"></a>

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików