diff --git a/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.i18n.yaml b/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.i18n.yaml index a2a0848eab..be124ffcbd 100644 --- a/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.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-31-code-runtime-portable-identifier-seam.md -2026-07-31-code-runtime-portable-identifier-seam.md: bd1876fc459dc85bb5d9f42ac04f4cc801d6398a -2026-07-31-code-runtime-portable-identifier-seam.zh.md: 2fd5e97c562d1e51cbad906cd37998b8ffccc58a +2026-07-31-code-runtime-portable-identifier-seam.md: 72796458d75dc04d094372f13d7253a6a4dad511 +2026-07-31-code-runtime-portable-identifier-seam.zh.md: ce709d5924d0835cd475af6d439c07e1dbceecd0 diff --git a/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.md b/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.md index bd1876fc45..72796458d7 100644 --- a/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.md +++ b/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.md @@ -17,9 +17,9 @@ The seam package (`@deepseek-ai/dsh-code-runtime`) exports the portable-identifi - `PORTABLE_RESERVED_WORDS` — the union of ECMAScript and Python reserved words. A namespace global or error-class name matching any is refused on all backends, so `lambda` is refused even though it is a legal JS parameter name. Adding a language widens this union, which is a deliberate breaking review of existing binding names. - `RESERVED_BINDING_GLOBALS` — globals some backend owns in the program's namespace: `console` (the worker's log capture) and `__dsh_main__`/`__builtins__`/`__name__`/`__debug__` (the Python bootstrap's wrapper and seeded module globals). Refused everywhere so a namespace list cannot pick a name that works on one backend and collides on another. - `RESERVED_ERROR_MEMBERS` — error-member names every backend refuses: the JS `Error` slots (`name`, `message`, `stack`) and Python's exception-protocol members (`args`, `with_traceback`, `add_note`). -- `DUNDER_MEMBER` — the dunder-form regex (`__*__`), refused as an error member wholesale because several are constrained CPython descriptors whose exact set is an interpreter-version detail. +- `DUNDER_MEMBER` — the dunder-form regex (`__x__`, non-empty middle), refused as an error member wholesale because several are constrained CPython descriptors whose exact set is an interpreter-version detail. -The seam also narrows the portable identifier subset to `[A-Za-z_][A-Za-z0-9_]*` (documented on `CodeBindingNamespace.global` and `CodeBindingErrorClass`), dropping the JS-only `$`. The worker consumes the shared constants: `RESERVED_WORDS = PORTABLE_RESERVED_WORDS`, `RESERVED_ERROR_PROPERTIES = RESERVED_ERROR_MEMBERS`, its `IDENTIFIER` regex loses `$`, and its error-member check adds `DUNDER_MEMBER`. +The seam also narrows the portable identifier subset to `[A-Za-z_][A-Za-z0-9_]*` (documented on `CodeBindingNamespace.global` and `CodeBindingErrorClass`), dropping the JS-only `$`. The worker consumes the shared constants directly by their seam names — `PORTABLE_RESERVED_WORDS` for both binding-global and error-class names, `RESERVED_BINDING_GLOBALS` for backend-owned slots, `RESERVED_ERROR_MEMBERS` plus `DUNDER_MEMBER` for error members — with no local re-alias; its `IDENTIFIER` regex loses `$`. The constants live at the seam even though only one backend ships in this PR: the whole point is that the contract is language-agnostic and owned above any single language. A backend that violated it would be the bug, and the shared set is where a reviewer looks to see what "portable" means. diff --git a/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.zh.md b/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.zh.md index 2fd5e97c56..ce709d5924 100644 --- a/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.zh.md +++ b/.agents/notes/implemented/architecture/2026-07-31-code-runtime-portable-identifier-seam.zh.md @@ -17,9 +17,9 @@ seam 包(`@deepseek-ai/dsh-code-runtime`)以四个具名常量导出可移 - `PORTABLE_RESERVED_WORDS`——ECMAScript 与 Python 保留字的联集。任何命名空间 global 或 error-class 名称匹配其中之一,都在所有后端上被拒绝,因此 `lambda` 即便是合法的 JS 参数名也被拒绝。新增一门语言即扩宽此联集,这是对现有绑定名称的一次有意的破坏性复审。 - `RESERVED_BINDING_GLOBALS`——某个后端在程序命名空间中拥有的 global:`console`(worker 的日志捕获)与 `__dsh_main__`/`__builtins__`/`__name__`/`__debug__`(Python bootstrap 的包装器与预置模块 global)。在所有后端上被拒绝,使命名空间列表无法选到一个在某后端能用、在另一后端冲突的名称。 - `RESERVED_ERROR_MEMBERS`——每个后端都拒绝的 error-member 名称:JS `Error` 槽位(`name`、`message`、`stack`)与 Python 异常协议成员(`args`、`with_traceback`、`add_note`)。 -- `DUNDER_MEMBER`——dunder 形式正则(`__*__`),作为 error member 被整体拒绝,因为其中若干是受约束的 CPython 描述符,其确切集合是解释器版本细节。 +- `DUNDER_MEMBER`——dunder 形式正则(`__x__`,非空中缀),作为 error member 被整体拒绝,因为其中若干是受约束的 CPython 描述符,其确切集合是解释器版本细节。 -seam 同时把可移植标识符子集收窄为 `[A-Za-z_][A-Za-z0-9_]*`(记录在 `CodeBindingNamespace.global` 与 `CodeBindingErrorClass` 上),去掉 JS 专有的 `$`。worker 消费这些共享常量:`RESERVED_WORDS = PORTABLE_RESERVED_WORDS`、`RESERVED_ERROR_PROPERTIES = RESERVED_ERROR_MEMBERS`,其 `IDENTIFIER` 正则去掉 `$`,其 error-member 检查加上 `DUNDER_MEMBER`。 +seam 同时把可移植标识符子集收窄为 `[A-Za-z_][A-Za-z0-9_]*`(记录在 `CodeBindingNamespace.global` 与 `CodeBindingErrorClass` 上),去掉 JS 专有的 `$`。worker 直接以 seam 名消费这些共享常量——binding-global 与 error-class 名称用 `PORTABLE_RESERVED_WORDS`、后端拥有槽位用 `RESERVED_BINDING_GLOBALS`、error member 用 `RESERVED_ERROR_MEMBERS` 加 `DUNDER_MEMBER`——不再本地起别名;其 `IDENTIFIER` 正则去掉 `$`。 尽管本 PR 只交付一个后端,这些常量仍置于 seam:要点正是该契约与语言无关,且拥有权在任何单一语言之上。违反它的后端才是 bug,而共享集合正是复审者查看"可移植"含义的地方。 diff --git a/docs/core-data-structures/code-runtime.i18n.yaml b/docs/core-data-structures/code-runtime.i18n.yaml index ac7dae06af..c4bbc64d27 100644 --- a/docs/core-data-structures/code-runtime.i18n.yaml +++ b/docs/core-data-structures/code-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 docs/core-data-structures/code-runtime.md -code-runtime.md: 522fe29deae8cac01462a336a02d082502b61fb4 -code-runtime.zh.md: 6d16f8ed2ab3b99620f30a8e81dc3718cf1419d1 +code-runtime.md: e7b5a86513abcab90eb81fc0b24296760bf3b926 +code-runtime.zh.md: 17ddbb0f685d97ba3c2dd6a23744771e88a40ed0 diff --git a/docs/core-data-structures/code-runtime.md b/docs/core-data-structures/code-runtime.md index 522fe29dea..e7b5a86513 100644 --- a/docs/core-data-structures/code-runtime.md +++ b/docs/core-data-structures/code-runtime.md @@ -76,9 +76,9 @@ interface CodeBindingErrorClass { name: string /** * Non-empty own property for the member name. The portable exclusion set is - * `RESERVED_ERROR_MEMBERS` plus dunder-form names (`__*__`), enforced - * identically by every backend; any other name — identifiers or not — is - * accepted everywhere. + * `RESERVED_ERROR_MEMBERS` plus dunder-form names (`__x__`, non-empty + * middle), enforced identically by every backend; any other name — + * identifiers or not — is accepted everywhere. */ memberNameProperty: string } @@ -98,7 +98,10 @@ interface CodeBindingNamespace { * identifier subset `[A-Za-z_][A-Za-z0-9_]*` and no language's reserved * words, so the same namespace list works against every backend regardless * of `language` — a JS-only spelling like `$tools` is rejected by design, - * not just by the Python backend. + * not just by the Python backend. Names that satisfy the identifier rule but + * name a backend-owned slot (`RESERVED_BINDING_GLOBALS`: `console`, + * `__dsh_main__`, `__builtins__`, `__name__`, `__debug__`) are also refused + * everywhere, since some backend seeds that slot in the program's namespace. */ global: string /** The callable members, keyed by the exact name the program calls. */ diff --git a/docs/core-data-structures/code-runtime.zh.md b/docs/core-data-structures/code-runtime.zh.md index 6d16f8ed2a..17ddbb0f68 100644 --- a/docs/core-data-structures/code-runtime.zh.md +++ b/docs/core-data-structures/code-runtime.zh.md @@ -76,9 +76,9 @@ interface CodeBindingErrorClass { name: string /** * Non-empty own property for the member name. The portable exclusion set is - * `RESERVED_ERROR_MEMBERS` plus dunder-form names (`__*__`), enforced - * identically by every backend; any other name — identifiers or not — is - * accepted everywhere. + * `RESERVED_ERROR_MEMBERS` plus dunder-form names (`__x__`, non-empty + * middle), enforced identically by every backend; any other name — + * identifiers or not — is accepted everywhere. */ memberNameProperty: string } @@ -98,7 +98,10 @@ interface CodeBindingNamespace { * identifier subset `[A-Za-z_][A-Za-z0-9_]*` and no language's reserved * words, so the same namespace list works against every backend regardless * of `language` — a JS-only spelling like `$tools` is rejected by design, - * not just by the Python backend. + * not just by the Python backend. Names that satisfy the identifier rule but + * name a backend-owned slot (`RESERVED_BINDING_GLOBALS`: `console`, + * `__dsh_main__`, `__builtins__`, `__name__`, `__debug__`) are also refused + * everywhere, since some backend seeds that slot in the program's namespace. */ global: string /** The callable members, keyed by the exact name the program calls. */ diff --git a/packages/code-runtime/code-runtime/src/types.ts b/packages/code-runtime/code-runtime/src/types.ts index e96d8bc959..e6c3b5ddc2 100644 --- a/packages/code-runtime/code-runtime/src/types.ts +++ b/packages/code-runtime/code-runtime/src/types.ts @@ -32,9 +32,9 @@ export interface CodeBindingErrorClass { name: string /** * Non-empty own property for the member name. The portable exclusion set is - * `RESERVED_ERROR_MEMBERS` plus dunder-form names (`__*__`), enforced - * identically by every backend; any other name — identifiers or not — is - * accepted everywhere. + * `RESERVED_ERROR_MEMBERS` plus dunder-form names (`__x__`, non-empty + * middle), enforced identically by every backend; any other name — + * identifiers or not — is accepted everywhere. */ memberNameProperty: string } @@ -52,7 +52,10 @@ export interface CodeBindingNamespace { * identifier subset `[A-Za-z_][A-Za-z0-9_]*` and no language's reserved * words, so the same namespace list works against every backend regardless * of `language` — a JS-only spelling like `$tools` is rejected by design, - * not just by the Python backend. + * not just by the Python backend. Names that satisfy the identifier rule but + * name a backend-owned slot (`RESERVED_BINDING_GLOBALS`: `console`, + * `__dsh_main__`, `__builtins__`, `__name__`, `__debug__`) are also refused + * everywhere, since some backend seeds that slot in the program's namespace. */ global: string /** The callable members, keyed by the exact name the program calls. */