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.
This commit is contained in:
parent
3e0055edaf
commit
d98965fbcc
12 changed files with 27 additions and 26 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: 671506aafbad1b03bc66ae137a58a7b11a836f79
|
||||
2026-07-31-code-runtime-python-fd3-protocol.zh.md: b12a7ba0ed0aadb0a1db57bcd59db93825bb4f40
|
||||
2026-07-31-code-runtime-python-fd3-protocol.zh.md: 1568f6366b4651fbb87fcfdfacdc274fa07b4d8e
|
||||
|
|
|
|||
|
|
@ -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,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
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 防护的已接受残余。
|
||||
|
|
|
|||
|
|
@ -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,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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue