refactor: apply repository naming contract
Apply the accepted pre-release package, service, type, directory, and role renames as one repository-wide change.
This commit is contained in:
@@ -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-06-17-ts-build-config.md
|
||||
2026-06-17-ts-build-config.md: a44e86844113250c8b99575102d7ea2e611e97ed
|
||||
2026-06-17-ts-build-config.zh.md: 4e3381a23ee17ebcf242dc449b6b7f6300db5f8b
|
||||
2026-06-17-ts-build-config.md: a9745baefbce97e0613a1c07d8e4d1de1e7f40f5
|
||||
2026-06-17-ts-build-config.zh.md: 0fdac8e5fc371a61592affe4a33a0268e819a2f7
|
||||
|
||||
@@ -32,8 +32,8 @@ In-package relative imports use explicit `.ts` specifiers.
|
||||
|
||||
`pnpm run build` orders Host lib, Client lib, and Web; each lib phase keeps tsc emission before tsdown bundling:
|
||||
|
||||
- Host tsc runs `tsc -b` against `tsconfig.host.json`, emitting per-module `.js`, `.d.ts`, `.js.map`, and `.d.ts.map` into `lib/types` for each package in the Host graph; Host tsdown then reads that JavaScript, produces published entries, and runs Host TypeRT.
|
||||
- Client tsc runs `tsc -b` against `tsconfig.client.json` after Host TypeRT has generated the Remote Client declarations; Client tsdown then reads the JavaScript emitted by the Client graph and produces the Client packages' Node loader entries and browser bundles.
|
||||
- Host tsc runs `tsc -b` against `tsconfig.host.json`, emitting per-module `.js`, `.d.ts`, `.js.map`, and `.d.ts.map` into `lib/types` for each package in the Host graph; Host tsdown then reads that JavaScript, produces published entries, and runs Host Typert.
|
||||
- Client tsc runs `tsc -b` against `tsconfig.client.json` after Host Typert has generated the Remote Client declarations; Client tsdown then reads the JavaScript emitted by the Client graph and produces the Client packages' Node loader entries and browser bundles.
|
||||
- The Web build starts only after both lib phases complete.
|
||||
|
||||
`tsdown` is no longer the owner of TypeScript compilation or declaration output.
|
||||
|
||||
@@ -32,8 +32,8 @@ Status: implemented
|
||||
|
||||
`pnpm run build` 依次执行 Host lib、Client lib 和 Web;每个 lib 阶段都保持 tsc 先发射、tsdown 后打包:
|
||||
|
||||
- Host tsc 对 `tsconfig.host.json` 执行 `tsc -b`,把逐模块 `.js`、`.d.ts`、`.js.map` 与 `.d.ts.map` 输出到 Host 图各包的 `lib/types`;Host tsdown 随后读取这些 JS,生成发布入口并运行 Host TypeRT。
|
||||
- Client tsc 在 Host TypeRT 已生成 Remote Client 声明后对 `tsconfig.client.json` 执行 `tsc -b`;Client tsdown 再读取 Client 图发射的 JS,生成 Client 包的 Node loader 入口与 browser bundle。
|
||||
- Host tsc 对 `tsconfig.host.json` 执行 `tsc -b`,把逐模块 `.js`、`.d.ts`、`.js.map` 与 `.d.ts.map` 输出到 Host 图各包的 `lib/types`;Host tsdown 随后读取这些 JS,生成发布入口并运行 Host Typert。
|
||||
- Client tsc 在 Host Typert 已生成 Remote Client 声明后对 `tsconfig.client.json` 执行 `tsc -b`;Client tsdown 再读取 Client 图发射的 JS,生成 Client 包的 Node loader 入口与 browser bundle。
|
||||
- Web build 只在两个 lib 阶段完成后启动。
|
||||
|
||||
`tsdown` 不再负责 TypeScript 编译或声明文件输出。
|
||||
|
||||
@@ -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-06-20-core-data-structures-catalog.md
|
||||
2026-06-20-core-data-structures-catalog.md: b793b65c7cd55a4b0fe7de97fcd8e43f7056d2ea
|
||||
2026-06-20-core-data-structures-catalog.zh.md: e6a054dbf9447aac603d90f7b07aee61888f9403
|
||||
2026-06-20-core-data-structures-catalog.md: 489dc488b82883dc1ab23fb0685c9467651cb60f
|
||||
2026-06-20-core-data-structures-catalog.zh.md: 3da11cf42d9fe3c4e89160bdbb725c3cf2e1112f
|
||||
|
||||
@@ -18,7 +18,7 @@ A new `docs/subsystems/` folder catalogs the vocabulary, with a new `verify-type
|
||||
|
||||
> **Superseded as the page-scoping rule** by [package-anchored subsystem pages](2026-08-03-package-anchored-subsystem-pages.md): each page now anchors to the package group that declares its vocabulary. The `ts type-equiv` mechanism below remains current.
|
||||
|
||||
The decisive test for the scoping line is `BashExecRequest`/`BashExecSpec`/`BashRunResult`: bash is a capability *seam*, not part of the agent-loop spine, so if those are "core" then "core" means *all cross-package vocabulary* and the catalog is a flat dump; if they are not, "core" means *the central spine* and bash vocabulary belongs on its own subsystem page. The latter won, which set the whole structure: a **tiered folder**, not a flat document.
|
||||
The decisive test for the scoping line is `ShellExecRequest`/`ShellExecSpec`/`ShellRunResult`: bash is a capability *seam*, not part of the agent-loop spine, so if those are "core" then "core" means *all cross-package vocabulary* and the catalog is a flat dump; if they are not, "core" means *the central spine* and bash vocabulary belongs on its own subsystem page. The latter won, which set the whole structure: a **tiered folder**, not a flat document.
|
||||
|
||||
The rule that settled the remaining cases: ***the type you write, hold, or receive is core; the machinery that types it, renders it, or persists it is a subsystem-page detail.*** Worked through:
|
||||
|
||||
@@ -27,7 +27,7 @@ The rule that settled the remaining cases: ***the type you write, hold, or recei
|
||||
- `ToolSchema` is core (it is a field of `GenerateOptions`, the model request that flows through every step) even though it is conceptually part of the tool pipeline — *flows through the spine* wins over *conceptual home* when they conflict.
|
||||
- The tool-presentation vocabulary (`ToolCallView`/`ToolResultView`, …), the `SessionPersistence` durability seam, and bash vocabulary belong on subsystem pages.
|
||||
|
||||
`core.md` is a **self-contained spine doc**: it states the exact type definition of each spine structure with minimal prose and links to sibling subsystem pages for package-owned detail; the folder's [README](../../../../docs/subsystems/README.md) indexes every page. The original subsystem pages are `llm-streaming.md`, `session.md`, `persistence.md` (split from session along the in-memory-model vs. durability-seam line), `tools.md`, and `bash.md`.
|
||||
`core.md` is a **self-contained spine doc**: it states the exact type definition of each spine structure with minimal prose and links to sibling subsystem pages for package-owned detail; the folder's [README](../../../../docs/subsystems/README.md) indexes every page. The original subsystem pages are `llm-streaming.md`, `session.md`, `persistence.md` (split from session along the in-memory-model vs. durability-seam line), `tools.md`, and `shell.md`.
|
||||
|
||||
### The `ts type-equiv` mechanism — literal AND drift-proof
|
||||
|
||||
@@ -44,7 +44,7 @@ The durability requirement was specific: the doc shows the **literal** current t
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
- **A flat dump of all cross-package vocabulary** — the `BashExecRequest` test case killed it: if seam vocabulary is "core", the catalog helps no one; the tiered spine-vs-subsystem structure won.
|
||||
- **A flat dump of all cross-package vocabulary** — the `ShellExecRequest` test case killed it: if seam vocabulary is "core", the catalog helps no one; the tiered spine-vs-subsystem structure won.
|
||||
- **A compiled `_Check` assignability assertion** instead of the source match — rejected because assignability does not preserve names or JSDoc: a renamed field with the same type or a changed contract comment would pass.
|
||||
- **Put each type block's source in a directive comment** — rejected for the central manifest, whose enforced 1:1 correspondence means a block can never be silently unchecked and an entry can never rot.
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ Status: implemented
|
||||
|
||||
> **作为页面范围界定规则已被取代**,见[按包锚定的子系统页面](2026-08-03-package-anchored-subsystem-pages.md):每页现在锚定到声明其词汇的包分组。下文的 `ts type-equiv` 机制仍然有效。
|
||||
|
||||
范围界定的决定性测试是 `BashExecRequest`/`BashExecSpec`/`BashRunResult`:bash 是一个能力 *seam*,不属于 agent loop(智能体循环)主干;如果这些算「核心」,那么「核心」就意味着*所有跨包词汇*,目录沦为平铺罗列;如果不算,「核心」就意味着*中央主干*,bash 词汇归入其自身的子系统页面。后者胜出,由此确定了整体结构:一个**分层文件夹**,而非一份平铺文档。
|
||||
范围界定的决定性测试是 `ShellExecRequest`/`ShellExecSpec`/`ShellRunResult`:bash 是一个能力 *seam*,不属于 agent loop(智能体循环)主干;如果这些算「核心」,那么「核心」就意味着*所有跨包词汇*,目录沦为平铺罗列;如果不算,「核心」就意味着*中央主干*,bash 词汇归入其自身的子系统页面。后者胜出,由此确定了整体结构:一个**分层文件夹**,而非一份平铺文档。
|
||||
|
||||
确定其余案例的规则是:***你编写、持有或接收的类型是核心;为其提供类型推导、渲染或持久化的机制是子系统页面细节。*** 逐一验证如下:
|
||||
|
||||
@@ -27,7 +27,7 @@ Status: implemented
|
||||
- `ToolSchema` 是核心(它是流经每个步骤的模型请求 `GenerateOptions` 的一个字段),即使它在概念上属于工具流水线——当*流经主干*与*概念归属*冲突时,前者胜出。
|
||||
- 工具展示词汇(`ToolCallView`/`ToolResultView` 等)、`SessionPersistence` 持久性 seam 以及 bash 词汇归入子系统页面。
|
||||
|
||||
`core.md` 是一份**自包含的主干文档**:它给出每个主干结构的确切类型定义,辅以最少的行文,并链接到同级子系统页面获取包所拥有的细节;目录的 [README](../../../../docs/subsystems/README.md) 索引全部页面。最初的子系统页面包括 `llm-streaming.md`、`session.md`、`persistence.md`(沿内存模型与持久性 seam 的分界线从会话页面拆出)、`tools.md` 和 `bash.md`。
|
||||
`core.md` 是一份**自包含的主干文档**:它给出每个主干结构的确切类型定义,辅以最少的行文,并链接到同级子系统页面获取包所拥有的细节;目录的 [README](../../../../docs/subsystems/README.md) 索引全部页面。最初的子系统页面包括 `llm-streaming.md`、`session.md`、`persistence.md`(沿内存模型与持久性 seam 的分界线从会话页面拆出)、`tools.md` 和 `shell.md`。
|
||||
|
||||
### `ts type-equiv` 机制——既逐字又防漂移
|
||||
|
||||
@@ -44,7 +44,7 @@ Status: implemented
|
||||
|
||||
## 曾考虑的替代方案
|
||||
|
||||
- **平铺罗列所有跨包词汇**:`BashExecRequest` 测试案例否决了它。如果 seam 词汇算「核心」,目录对谁都没帮助;分层的主干与子系统结构胜出。
|
||||
- **平铺罗列所有跨包词汇**:`ShellExecRequest` 测试案例否决了它。如果 seam 词汇算「核心」,目录对谁都没帮助;分层的主干与子系统结构胜出。
|
||||
- **用编译式 `_Check` 可赋值性断言**代替源码匹配:否决。可赋值性不会保留名称或 JSDoc;同类型字段改名或约定注释变化仍会通过。
|
||||
- **将每个类型块的源文件写进指令注释**:否决,改用集中 manifest;其强制的 1:1 对应确保一个块永远不会被静默漏检,一条条目也永远不会腐烂。
|
||||
|
||||
|
||||
@@ -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-07-02-tool-schema-catalog.md
|
||||
2026-07-02-tool-schema-catalog.md: 1339d6631cb6abd7abc3cf193ed805de612b8425
|
||||
2026-07-02-tool-schema-catalog.zh.md: 55bbbdaab0745e00e9d57d3876ad8ab4b06ea66f
|
||||
2026-07-02-tool-schema-catalog.md: 5ae396d0942379f625b6e0ccb89030d8a34c2283
|
||||
2026-07-02-tool-schema-catalog.zh.md: 278a9e17dc9f8462ea70694f67ae7944a43765aa
|
||||
|
||||
@@ -10,7 +10,7 @@ The repository had no single reference for the names, descriptions, and JSON Sch
|
||||
|
||||
## Decision
|
||||
|
||||
Generate the catalog by **booting each tool plugin and reading its registered schemas**, not by parsing source. `scripts/gen-tool-catalog.ts` mounts each shipped tool package on a fresh cordis `Context` (with `SystemPrompt` + `ToolRegistry` and the injected services the plugin's `apply` reads), calls `ctx.tools.schemas()` — exactly the `ToolSchema[]` the model is sent — disposes the context, and renders one `## <package>` section per package with a ` ```json ` `parameters` block per tool. It mirrors the `gen-cordis-catalog` / `gen-module-graph` CLI shape: default `--write` regenerates, `--check` fails if the committed copy is stale, output is deterministic (manifest-ordered, tools sorted by name). `verify-tool-catalog` (the `--check`) runs inside `doc-sync`, so relevant documentation changes and CI exercise the same freshness check.
|
||||
Generate the catalog by **booting each tool plugin and reading its registered schemas**, not by parsing source. `scripts/gen-tool-catalog.ts` mounts each shipped tool package on a fresh cordis `Context` (with `SystemPrompt` + `ToolRuntime` and the injected services the plugin's `apply` reads), calls `ctx.tools.schemas()` — exactly the `ToolSchema[]` the model is sent — disposes the context, and renders one `## <package>` section per package with a ` ```json ` `parameters` block per tool. It mirrors the `gen-cordis-catalog` / `gen-module-graph` CLI shape: default `--write` regenerates, `--check` fails if the committed copy is stale, output is deterministic (manifest-ordered, tools sorted by name). `verify-tool-catalog` (the `--check`) runs inside `doc-sync`, so relevant documentation changes and CI exercise the same freshness check.
|
||||
|
||||
### Why boot, not parse (the crux)
|
||||
|
||||
@@ -33,7 +33,7 @@ The filesystem discovers the tool-package inventory and the completeness guard r
|
||||
|
||||
### Scope
|
||||
|
||||
Shipped product tool packages under `packages/*/tool-*`, each booted with its default config, including `dsh-tool-bash` (`bash`), `dsh-tool-tasks` (`task_output`, `task_list`, `task_kill`), and `dsh-tool-subagent` (`subagent`). Example-only tools are excluded.
|
||||
Shipped product tool packages under `packages/*/tool-*`, each booted with its default config, including `dsh-tool-bash` (`bash`), `dsh-tool-jobs` (`job_output`, `job_list`, `job_kill`), and `dsh-tool-subagent` (`subagent`). Example-only tools are excluded.
|
||||
|
||||
The catalog unit is a package, not every configured tool instance. Each package boots once with default config; load-time aliases such as `subagent_fork` are noted without enumerating every deployment permutation. A deployment inventory is a separate, unbounded surface.
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ Status: implemented
|
||||
|
||||
## 决策
|
||||
|
||||
目录通过**启动每个工具插件并读取其已注册 schema** 来生成,而不是解析源码。`scripts/gen-tool-catalog.ts` 在全新的 Cordis `Context` 上挂载每个已发布工具包;该上下文还提供 `SystemPrompt`、`ToolRegistry` 以及插件 `apply` 所读取的注入服务。生成器调用 `ctx.tools.schemas()`——也就是发送给模型的确切 `ToolSchema[]`——随后 dispose(资源释放)上下文,并为每个包渲染一个 `## <package>` 章节,每个工具附带一个 ` ```json ` `parameters` 块。它与 `gen-cordis-catalog` / `gen-module-graph` 的 CLI 形状一致:默认 `--write` 重新生成;提交副本陈旧时 `--check` 失败;输出具有确定性(按清单排序,工具按名称排序)。`verify-tool-catalog`(即 `--check`)在 `doc-sync` 内运行,因此相关文档变更和 CI 会执行同一项新鲜度检查。
|
||||
目录通过**启动每个工具插件并读取其已注册 schema** 来生成,而不是解析源码。`scripts/gen-tool-catalog.ts` 在全新的 Cordis `Context` 上挂载每个已发布工具包;该上下文还提供 `SystemPrompt`、`ToolRuntime` 以及插件 `apply` 所读取的注入服务。生成器调用 `ctx.tools.schemas()`——也就是发送给模型的确切 `ToolSchema[]`——随后 dispose(资源释放)上下文,并为每个包渲染一个 `## <package>` 章节,每个工具附带一个 ` ```json ` `parameters` 块。它与 `gen-cordis-catalog` / `gen-module-graph` 的 CLI 形状一致:默认 `--write` 重新生成;提交副本陈旧时 `--check` 失败;输出具有确定性(按清单排序,工具按名称排序)。`verify-tool-catalog`(即 `--check`)在 `doc-sync` 内运行,因此相关文档变更和 CI 会执行同一项新鲜度检查。
|
||||
|
||||
### 为何启动而非解析(核心要点)
|
||||
|
||||
@@ -33,7 +33,7 @@ Cordis 目录是纯 TypeScript AST 遍历,因为每个事件/服务名都是
|
||||
|
||||
### 范围
|
||||
|
||||
`packages/*/tool-*` 下已发布的产品工具包,每个都使用默认配置启动,包括 `dsh-tool-bash`(`bash`)、`dsh-tool-tasks`(`task_output`、`task_list`、`task_kill`)和 `dsh-tool-subagent`(`subagent`)。仅供示例使用的工具不在范围内。
|
||||
`packages/*/tool-*` 下已发布的产品工具包,每个都使用默认配置启动,包括 `dsh-tool-bash`(`bash`)、`dsh-tool-jobs`(`job_output`、`job_list`、`job_kill`)和 `dsh-tool-subagent`(`subagent`)。仅供示例使用的工具不在范围内。
|
||||
|
||||
目录的单位是包,而非经过配置的每个工具实例。每个包以默认配置启动一次;加载时的别名(如 `subagent_fork`)会注明,但不枚举所有部署配置组合。部署清单覆盖的是一个独立且无界的范围。
|
||||
|
||||
|
||||
@@ -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-07-21-serial-cross-platform-ci-reference.md
|
||||
2026-07-21-serial-cross-platform-ci-reference.md: c2ed11d40f7f5487117b5c72f11bc1709042f68a
|
||||
2026-07-21-serial-cross-platform-ci-reference.zh.md: 16beefd37c5b86a4e583c97cafd1aacff8ed650c
|
||||
2026-07-21-serial-cross-platform-ci-reference.md: cfe6fd1028d03056e5ac6da7f014db2ac6db8fab
|
||||
2026-07-21-serial-cross-platform-ci-reference.zh.md: 8ac7e087c3d015c0ed6bdf71feed9806bd6fb997
|
||||
|
||||
@@ -20,7 +20,7 @@ Real-kernel sandbox proofs require specific hosted operating systems and archite
|
||||
|
||||
Each reference job runs `pnpm run check:ci` without any shard selector. `DSH_GATE_CONCURRENCY=1` makes the top-level aggregate execute one ready gate at a time; coverage, snapshot replay, built-bin smoke, and publication validation also receive worker counts of one. The reference jobs may run beside one another, but each host's repository gates are serial and complete. Linux installs bubblewrap before replaying snapshots, and Windows enables Developer Mode before installing the symlinked workspace.
|
||||
|
||||
Platform ownership remains explicit inside that complete aggregate. `pty-local` supports Linux and macOS and therefore owns its unit and per-file coverage contract on POSIX rather than loading a backend that rejects `win32`; the Windows run still executes every portable package. Portable fixtures derive native paths through `node:path`, compare canonical identities with the same native realpath implementation as production, and use filenames legal on every host. ACP snapshot runs also pass both JavaScript and native realpath spellings of their generated cwd to the normalizer, which replaces aliases longest-first so Windows short and long paths cannot churn shared fixtures.
|
||||
Platform ownership remains explicit inside that complete aggregate. `terminal-bash` supports Linux and macOS and therefore owns its unit and per-file coverage contract on POSIX rather than loading a backend that rejects `win32`; the Windows run still executes every portable package. Portable fixtures derive native paths through `node:path`, compare canonical identities with the same native realpath implementation as production, and use filenames legal on every host. ACP snapshot runs also pass both JavaScript and native realpath spellings of their generated cwd to the normalizer, which replaces aliases longest-first so Windows short and long paths cannot churn shared fixtures.
|
||||
|
||||
The macOS reference runs the ordinary Vitest project in forked processes. Node 24 on macOS arm64 has aborted in its CJS lexer from a worker thread; the process boundary contains that external runtime failure without removing any test from the aggregate, while Linux and Windows retain the lower-overhead thread pool. Repository-owned races are fixed at their observation boundaries: dev bundle polling stages each candidate table, graph, and watch-baseline map before publishing a rescan, and a missing bundle remains dirty until a successful content hash. PTY readiness retains a prompt candidate while polling checks foreground ownership; the ordinary silence bound covers inherited markers from interactive children. Real PTY fixtures assemble synchronization tokens at runtime so the interactive shell's input echo cannot satisfy a child-readiness wait. The live-link package-manager e2e preserves the workflow-prepared Corepack home and pnpm metadata/store caches while isolating the other managers' mutable caches, so it does not discard reusable package-manager state before the install.
|
||||
|
||||
@@ -47,6 +47,6 @@ The reference may expose platform failures that the optimized blocking set does
|
||||
|
||||
A sandbox regression visible only to a real host kernel or the packed Landlock install can merge before the master run reports it. That post-merge detection window is accepted in exchange for removing four non-blocking jobs from every pull request; the default branch retains the complete signal.
|
||||
|
||||
The explicit `pty-local` ownership boundary means Windows does not claim coverage for a backend it cannot load, and forked macOS unit workers cost more process startup time. In return, every supported surface has an honest platform oracle, a native runtime abort cannot erase the rest of the unit result, and timing-sensitive observers start from state established before callers can mutate it.
|
||||
The explicit `terminal-bash` ownership boundary means Windows does not claim coverage for a backend it cannot load, and forked macOS unit workers cost more process startup time. In return, every supported surface has an honest platform oracle, a native runtime abort cannot erase the rest of the unit result, and timing-sensitive observers start from state established before callers can mutate it.
|
||||
|
||||
Removing strict duration timeouts means a latency regression is observed rather than automatically cancelled. Hosted measurements must therefore accompany performance changes, while the completed logs retain the information needed to optimize the slow lane.
|
||||
|
||||
@@ -20,7 +20,7 @@ Status: implemented
|
||||
|
||||
每个参考作业均在不设置任何分片选择器的情况下运行 `pnpm run check:ci`。`DSH_GATE_CONCURRENCY=1` 使顶层聚合每次只执行一个已经就绪的门禁;覆盖率、快照回放、built-bin 冒烟测试和发布验证的 worker 数量也设为 1。各参考作业可以彼此并行,但每台主机上的仓库门禁都串行运行且完整执行。Linux 在回放快照前安装 bubblewrap,Windows 则在安装采用符号链接的工作区前启用开发人员模式。
|
||||
|
||||
该完整聚合流程仍明确划分平台归属。`pty-local` 支持 Linux 与 macOS,因此其单元测试和逐文件覆盖率约定由 POSIX 平台负责,而不会在 Windows 上加载一个明确拒绝 `win32` 的后端;Windows 仍会执行所有可移植包。可移植 fixture(测试前置数据)通过 `node:path` 派生原生路径,使用与生产代码相同的原生 realpath 实现比较规范化后的路径标识,并采用所有宿主机均允许的文件名。ACP(Agent Client Protocol)快照运行还会把生成的 cwd 分别通过 realpath 的 JavaScript 实现与原生实现得到的两种表示一并传给规范化器;规范化器按长度从长到短替换这些别名,避免 Windows 的短路径与长路径表示差异导致共享 fixture 反复变化。
|
||||
该完整聚合流程仍明确划分平台归属。`terminal-bash` 支持 Linux 与 macOS,因此其单元测试和逐文件覆盖率约定由 POSIX 平台负责,而不会在 Windows 上加载一个明确拒绝 `win32` 的后端;Windows 仍会执行所有可移植包。可移植 fixture(测试前置数据)通过 `node:path` 派生原生路径,使用与生产代码相同的原生 realpath 实现比较规范化后的路径标识,并采用所有宿主机均允许的文件名。ACP(Agent Client Protocol)快照运行还会把生成的 cwd 分别通过 realpath 的 JavaScript 实现与原生实现得到的两种表示一并传给规范化器;规范化器按长度从长到短替换这些别名,避免 Windows 的短路径与长路径表示差异导致共享 fixture 反复变化。
|
||||
|
||||
macOS 参考流程使用 fork 进程运行常规 Vitest 项目。macOS arm64 上的 Node 24 曾在工作线程中执行 CJS 词法分析器时异常终止;进程边界能够隔离这一外部运行时故障,且无需从聚合流程中删除任何测试,而 Linux 与 Windows 仍使用开销更低的线程池。仓库自身引入的竞态均在相应的观测边界修复:开发构建产物的轮询逻辑每次发布重新扫描结果前,都会先暂存候选表、候选图和候选监视基线映射;构建产物缺失后会一直保持脏状态,直到成功计算内容哈希。PTY 就绪检测会在轮询检查前台进程组归属期间保留提示符候选项;常规静默时限也涵盖从交互式子进程继承而来的标记。真实 PTY fixture 会在运行时拼接同步标记,使就绪等待逻辑不会把交互式 shell 的输入回显误判为子进程已就绪。实时链接场景下的包管理器 e2e 会保留由工作流预先准备的 Corepack 主目录、pnpm 元数据缓存和 store 缓存,同时隔离其他包管理器的可变缓存,因此不会在安装前丢弃可复用的包管理器状态。
|
||||
|
||||
@@ -47,6 +47,6 @@ master 分支的参考作业仅用于诊断,不参与拉取请求所要求的
|
||||
|
||||
仅在真实宿主内核或打包后的 Landlock 安装中可见的沙箱回归,可能在 master 上的运行报告前已经合并。我们接受这个合并后检测窗口,以换取从每个拉取请求中移除四个非阻塞作业;默认分支仍保留完整信号。
|
||||
|
||||
明确的 `pty-local` 归属边界意味着 Windows 不会声称覆盖一个无法加载的后端,而 macOS 采用 fork 的单元测试工作进程会增加进程启动开销。这些代价换来的是:支持范围内的每个方面都有能够如实反映对应平台行为的判据,原生运行时异常终止不会抹掉其余单元测试结果,各项对时序敏感的观测逻辑也都会以调用方有机会修改状态前已建立的状态作为起点。
|
||||
明确的 `terminal-bash` 归属边界意味着 Windows 不会声称覆盖一个无法加载的后端,而 macOS 采用 fork 的单元测试工作进程会增加进程启动开销。这些代价换来的是:支持范围内的每个方面都有能够如实反映对应平台行为的判据,原生运行时异常终止不会抹掉其余单元测试结果,各项对时序敏感的观测逻辑也都会以调用方有机会修改状态前已建立的状态作为起点。
|
||||
|
||||
移除严格的时长超时后,系统会观测到延迟回归,而不是在发生回归时自动取消运行。因此,性能改动必须附带托管环境测量结果,已完成的日志则保留优化最慢通道所需的信息。
|
||||
|
||||
@@ -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-07-22-fast-local-git-hooks.md
|
||||
2026-07-22-fast-local-git-hooks.md: c3d3579b2e91419fad64f0e64a10926d2362881e
|
||||
2026-07-22-fast-local-git-hooks.zh.md: f85daa9c74a23987cc560f14c5e087fdfb3d7f5e
|
||||
2026-07-22-fast-local-git-hooks.md: ad187c5cfd021ca76ad5f569a17fb12c82dcf4e7
|
||||
2026-07-22-fast-local-git-hooks.zh.md: 87f9a86ea94e56335026f4069a74de6dec1e5a8b
|
||||
|
||||
@@ -12,7 +12,7 @@ Fast hooks still need to reject cheap, high-confidence defects before work leave
|
||||
|
||||
## Decision
|
||||
|
||||
[lefthook.yml](../../../../lefthook.yml) keeps both hooks as bounded local checkpoints. Pre-commit runs sequentially: a project-free [Oxlint](2026-07-29-oxlint-linter.md) profile validates changed JavaScript and TypeScript, applies safe fixes with a [bounded retry](2026-08-09-oxlint-only-fix-workflow.md), and re-stages them; `git diff --cached --check` rejects staged whitespace errors, and the vendor manifest guard checks vendored-source metadata. Pre-push runs `pnpm run typecheck`, which prepares the generated Host TypeRT contracts before the Client incremental typecheck.
|
||||
[lefthook.yml](../../../../lefthook.yml) keeps both hooks as bounded local checkpoints. Pre-commit runs sequentially: a project-free [Oxlint](2026-07-29-oxlint-linter.md) profile validates changed JavaScript and TypeScript, applies safe fixes with a [bounded retry](2026-08-09-oxlint-only-fix-workflow.md), and re-stages them; `git diff --cached --check` rejects staged whitespace errors, and the vendor manifest guard checks vendored-source metadata. Pre-push runs `pnpm run typecheck`, which prepares the generated Host Typert contracts before the Client incremental typecheck.
|
||||
|
||||
Pre-commit does not run type analysis, tests, snapshots, documentation checks, builds, hygiene, or the gate scheduler. Pre-push adds only the Host contract build required by repository typecheck. The opt-in `check:all` package script selects the `check-all` scheduler inventory in [scripts/run-gates.ts](../../../../scripts/run-gates.ts) independently of the hooks; it is a contributor command, not an agent instruction.
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ agent(智能体)已经会运行能够覆盖自身改动的测试和检查,
|
||||
|
||||
## 决策
|
||||
|
||||
[lefthook.yml](../../../../lefthook.yml) 将两个钩子都保留为有界的本地检查点。Pre-commit 按顺序运行:不加载项目的 [Oxlint](2026-07-29-oxlint-linter.md) 配置验证改动过的 JavaScript 和 TypeScript 文件,应用带[一次有界重试](2026-08-09-oxlint-only-fix-workflow.md)的安全修复,并重新暂存这些文件;`git diff --cached --check` 拒绝暂存 diff 中的空白错误,vendor manifest(元数据清单)守卫检查 vendor 源码元数据。Pre-push 运行 `pnpm run typecheck`;该命令会先准备好生成的 Host TypeRT 约定,再运行 Client 增量类型检查。
|
||||
[lefthook.yml](../../../../lefthook.yml) 将两个钩子都保留为有界的本地检查点。Pre-commit 按顺序运行:不加载项目的 [Oxlint](2026-07-29-oxlint-linter.md) 配置验证改动过的 JavaScript 和 TypeScript 文件,应用带[一次有界重试](2026-08-09-oxlint-only-fix-workflow.md)的安全修复,并重新暂存这些文件;`git diff --cached --check` 拒绝暂存 diff 中的空白错误,vendor manifest(元数据清单)守卫检查 vendor 源码元数据。Pre-push 运行 `pnpm run typecheck`;该命令会先准备好生成的 Host Typert 约定,再运行 Client 增量类型检查。
|
||||
|
||||
Pre-commit 不运行类型分析、测试、快照、文档检查、构建、`hygiene` 或门禁调度器。Pre-push 只增加仓库类型检查所需的 Host 约定构建。可选运行的 `check:all` 包脚本独立于这些钩子,从 [scripts/run-gates.ts](../../../../scripts/run-gates.ts) 中选择 `check-all` 调度器清单;它是贡献者命令,而非对 agent 的指令。
|
||||
|
||||
|
||||
@@ -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-07-28-per-subsystem-cordis-surface-regions.md
|
||||
2026-07-28-per-subsystem-cordis-surface-regions.md: f6d4494d4195ba27f2898eecb27af32b433af88b
|
||||
2026-07-28-per-subsystem-cordis-surface-regions.zh.md: a83cb1c75d280ef7603605f16e9e9e486d575879
|
||||
2026-07-28-per-subsystem-cordis-surface-regions.md: 66973223ec443fdd2a150fdd32d722ae3cad261b
|
||||
2026-07-28-per-subsystem-cordis-surface-regions.zh.md: 4978bcc032bbff016a92e8e59a5d50aa31dafae7
|
||||
|
||||
@@ -6,7 +6,7 @@ English | [中文](2026-07-28-per-subsystem-cordis-surface-regions.zh.md)
|
||||
|
||||
## Problem
|
||||
|
||||
One subsystem's documentation was split across three homes: its hand-written subsystems page (introduction, data structures, verbs), its `ctx.<key>` slice of the flat generated `docs/cordis-catalog/services.md`, and its event scope's slice of the flat `docs/cordis-catalog/events.md`. A reader of bash.md had to open two more documents to see the service interface and events the page was describing, and nothing tied the three views together beyond hand-maintained links. The flat catalogs also sat outside the bilingual corpus (excluded from pairing because generated output is English-only), so the reference surface had no Chinese route at all.
|
||||
One subsystem's documentation was split across three homes: its hand-written subsystems page (introduction, data structures, verbs), its `ctx.<key>` slice of the flat generated `docs/cordis-catalog/services.md`, and its event scope's slice of the flat `docs/cordis-catalog/events.md`. A reader of shell.md had to open two more documents to see the service interface and events the page was describing, and nothing tied the three views together beyond hand-maintained links. The flat catalogs also sat outside the bilingual corpus (excluded from pairing because generated output is English-only), so the reference surface had no Chinese route at all.
|
||||
|
||||
The [generated-catalog decision](../../archived/process/2026-06-20-generated-cordis-catalog.md) — generate from source, `@mode` tags cross-checked, fail-closed type-link coverage, the `ts cordis-catalog` fence — is not in question; what changed is WHERE the generated output lands.
|
||||
|
||||
@@ -18,7 +18,7 @@ The [generated-catalog decision](../../archived/process/2026-06-20-generated-cor
|
||||
- **Byte-identical regions across the pair.** The generator writes the SAME English region bytes into `foo.md` and `foo.zh.md`, extending the existing rule that verbatim code fences match across a pair. `verify-translation-pairing` gained a dedicated region-identity check (`partitionGeneratedRegions` in `translation-pairing.ts` owns the marker grammar) that names a divergent or malformed region precisely; the whole-document structural signature still covers the region content a second time.
|
||||
- **Guarded pair auto-record.** A regeneration that changes region bytes would leave every touched pair out-of-sync, so the generator re-records a pair's `.i18n.yaml` itself — but ONLY when the write is region-confined: both sides' recorded blob hashes must match the pre-write bytes, and the region-STRIPPED content must be unchanged on both sides. Human-prose drift leaves the record stale so the pairing gate still forces the normal translation flow; a brand-new pair is never auto-recorded (the author's reviewed `--write` owns that). This keeps `.i18n.yaml` as plain `git hash-object` values — no stripped-hash semantics change.
|
||||
- **The inherited tier moved, not died.** The vendor `ctx` members and `internal/*`/loader/hmr/timer events render to `docs/cordis-api/inherited.md`, next to the relocated Cordis core API pages (`docs/cordis-catalog/core/` → `docs/cordis-api/`). Framework surface lives under a framework home; the harness pages stay repository-owned vocabulary.
|
||||
- **In-page links.** Signature `Types:` lines link sibling pages (`core.md`, `bash.md`); a type whose primary page is the rendering page is dropped from the line instead of self-linking. Pages reference their own region with `#cordis-surface` or a `#ctx<key>--<class>` anchor — every generated heading is preceded by an explicit `<a id>` carrying the GitHub slug (the historical flat-catalog anchor), so the fragments resolve identically on GitHub and the VitePress site, whose own slugger treats the punctuation-heavy headings differently.
|
||||
- **In-page links.** Signature `Types:` lines link sibling pages (`core.md`, `shell.md`); a type whose primary page is the rendering page is dropped from the line instead of self-linking. Pages reference their own region with `#cordis-surface` or a `#ctx<key>--<class>` anchor — every generated heading is preceded by an explicit `<a id>` carrying the GitHub slug (the historical flat-catalog anchor), so the fragments resolve identically on GitHub and the VitePress site, whose own slugger treats the punctuation-heavy headings differently.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
@@ -32,5 +32,5 @@ The [generated-catalog decision](../../archived/process/2026-06-20-generated-cor
|
||||
- A subsystem's whole story is one page: `docs/subsystems/<name>.md` (and its pair) carries introduction, data structures/verbs, and the generated service/event surface; `docs/cordis-catalog/` no longer exists.
|
||||
- A new service or event scope cannot ship undocumented or unmapped: the generator fails until `SERVICE_PAGE`/`EVENT_SCOPE_PAGE` names its owning page, and the page must already exist with markers in both language sides.
|
||||
- Regeneration after a source-JSDoc change touches the affected pages in both languages plus (when region-confined) their pair records — a mechanical, reviewable diff; prose edits keep demanding the translation flow because the auto-record guard refuses them.
|
||||
- The website's subsystem nav lists every page (38 routes per locale: 35 translated pairs plus the three still-English-mirrored goal/pty/commands), replacing the two flat catalog nav entries; the Cordis API section gained `inherited.md`.
|
||||
- The website's subsystem nav lists every page (38 routes per locale: 35 translated pairs plus the three still-English-mirrored goal/terminal/commands), replacing the two flat catalog nav entries; the Cordis API section gained `inherited.md`.
|
||||
- `packages/typert/generator/tests/cordis-catalog-contract.spec.ts` pins the region renderer (`renderPageRegion`), the same-page link-drop rule, and the fail-loud JSDoc/type-link validation; `scripts/translation-pairing.spec.ts` pins the marker grammar and blob-hash primitive; `scripts/gen-cordis-catalog-record.spec.ts` proves the auto-record guard refuses every invalid state (stale record, malformed or renamed-key sidecar, extra entries, prose drift, missing record, missing snapshot).
|
||||
|
||||
@@ -6,7 +6,7 @@ Status: implemented
|
||||
|
||||
## 问题
|
||||
|
||||
一个子系统的文档过去分散在三个归属:手写的 subsystems 页面(介绍、数据结构、动词)、平铺生成的 `docs/cordis-catalog/services.md` 中属于它的 `ctx.<key>` 切片,以及平铺的 `docs/cordis-catalog/events.md` 中属于其事件作用域的切片。bash.md 的读者必须再打开两份文档,才能看到该页面正在描述的服务接口与事件;除了手工维护的链接,没有任何机制把这三个视图联系在一起。平铺目录还游离在双语语料之外(生成输出只有英文,故被排除在配对之外),因此,这套参考内容完全没有中文入口。
|
||||
一个子系统的文档过去分散在三个归属:手写的 subsystems 页面(介绍、数据结构、动词)、平铺生成的 `docs/cordis-catalog/services.md` 中属于它的 `ctx.<key>` 切片,以及平铺的 `docs/cordis-catalog/events.md` 中属于其事件作用域的切片。shell.md 的读者必须再打开两份文档,才能看到该页面正在描述的服务接口与事件;除了手工维护的链接,没有任何机制把这三个视图联系在一起。平铺目录还游离在双语语料之外(生成输出只有英文,故被排除在配对之外),因此,这套参考内容完全没有中文入口。
|
||||
|
||||
[生成式目录决策](../../archived/process/2026-06-20-generated-cordis-catalog.md)本身(从源码生成、`@mode` 标签交叉校验、失败关闭的类型链接覆盖、`ts cordis-catalog` 围栏)不在质疑之列;改变的只是生成输出「落在哪里」。
|
||||
|
||||
@@ -18,7 +18,7 @@ Status: implemented
|
||||
- **区块在配对两侧按字节一致。** 生成器把同一份英文区块字节写入 `foo.md` 和 `foo.zh.md`,是对「围栏代码块在配对两侧逐字节一致」这一既有规则的延伸。`verify-translation-pairing` 新增了专门的区块一致性检查(标记语法归 `translation-pairing.ts` 中的 `partitionGeneratedRegions` 所有),能精确点名出现分歧或格式错误的区块;整篇文档的结构签名仍会把区块内容再覆盖一遍。
|
||||
- **带防护的配对自动记录。** 一次改变区块字节的重新生成会让每个被触及的配对失去同步,因此生成器会自行重新记录配对的 `.i18n.yaml`,但仅限本次写入完全限定在区块内的情况:两侧记录的 blob hash 必须与写入前的字节相符,且两侧剥离区块后的内容必须没有变化。人工行文若有漂移,记录就保持陈旧,配对门禁因此仍会强制走正常翻译流程;全新的配对绝不自动记录(那归作者经评审的 `--write` 所有)。这样 `.i18n.yaml` 保持为纯粹的 `git hash-object` 值:不引入任何「剥离后 hash」的语义变化。
|
||||
- **继承层搬了家,而非消亡。** vendor 的 `ctx` 成员与 `internal/*`/loader/hmr/timer 事件渲染到 `docs/cordis-api/inherited.md`,紧邻迁移后的 Cordis 核心 API 页面(`docs/cordis-catalog/core/` → `docs/cordis-api/`)。框架表面落在框架自己的归属之下;harness 页面仍是仓库自有的词汇。
|
||||
- **页内链接。** 签名的 `Types:` 行链接到兄弟页面(`core.md`、`bash.md`);若某个类型的主要页面就是正在渲染的页面,该类型会从该行去掉,而不是链接到自身。页面用 `#cordis-surface` 或 `#ctx<key>--<class>` 锚点引用自己的区块:每个生成标题前都有一个显式 `<a id>`,携带 GitHub slug(即平铺目录时期的历史锚点),因此这些片段在 GitHub 与 VitePress 站点上解析一致——后者自带的 slugger 对含大量标点的标题会得出不同结果。
|
||||
- **页内链接。** 签名的 `Types:` 行链接到兄弟页面(`core.md`、`shell.md`);若某个类型的主要页面就是正在渲染的页面,该类型会从该行去掉,而不是链接到自身。页面用 `#cordis-surface` 或 `#ctx<key>--<class>` 锚点引用自己的区块:每个生成标题前都有一个显式 `<a id>`,携带 GitHub slug(即平铺目录时期的历史锚点),因此这些片段在 GitHub 与 VitePress 站点上解析一致——后者自带的 slugger 对含大量标点的标题会得出不同结果。
|
||||
|
||||
## 曾考虑的替代方案
|
||||
|
||||
@@ -32,5 +32,5 @@ Status: implemented
|
||||
- 一个子系统的完整说明集中在一个页面上:`docs/subsystems/<name>.md`(及其配对文件)承载介绍、数据结构/动词,以及生成的服务/事件接口参考;`docs/cordis-catalog/` 不复存在。
|
||||
- 新的服务或事件作用域无法在未记录、未映射的状态下落地:在 `SERVICE_PAGE`/`EVENT_SCOPE_PAGE` 点名其所属页面之前,生成器一直失败,而且该页面必须已经存在,并在两个语言侧都带有标记。
|
||||
- 源码 JSDoc 变更后的重新生成会触及两种语言的受影响页面,外加(当写入限定在区块内时)它们的配对记录:一份机械、可评审的 diff。行文编辑仍然要走翻译流程,因为自动记录防护会拒绝它们。
|
||||
- 网站的子系统导航列出每个页面(每个 locale 38 条路由:35 个已翻译配对,加上仍为英文镜像的 goal/pty/commands 三页),取代两个平铺目录导航项;Cordis API 一节新增 `inherited.md`。
|
||||
- 网站的子系统导航列出每个页面(每个 locale 38 条路由:35 个已翻译配对,加上仍为英文镜像的 goal/terminal/commands 三页),取代两个平铺目录导航项;Cordis API 一节新增 `inherited.md`。
|
||||
- `packages/typert/generator/tests/cordis-catalog-contract.spec.ts` 固定区块渲染器(`renderPageRegion`)、同页链接去除规则,以及异常时明确报错的 JSDoc 与类型链接校验;`scripts/translation-pairing.spec.ts` 固定标记语法与 blob hash 原语;`scripts/gen-cordis-catalog-record.spec.ts` 证明自动重录守卫拒绝每一种非法状态(陈旧记录、格式错误或键被改名的伴随记录、多余条目、行文漂移、记录缺失、快照缺失)。
|
||||
|
||||
@@ -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-07-30-generated-third-party-notices.md
|
||||
2026-07-30-generated-third-party-notices.md: d13eef8412ecd5c8387a7239b812c835671b6bce
|
||||
2026-07-30-generated-third-party-notices.zh.md: f750c9a11bb75fa4813307cfd0807a60f6291f1a
|
||||
2026-07-30-generated-third-party-notices.md: 9ca24c9634b0410f9b7cc255902344cd6014bb90
|
||||
2026-07-30-generated-third-party-notices.zh.md: b49e60565bbae62cf17026db17babc1ba7a408dc
|
||||
|
||||
@@ -20,7 +20,7 @@ One trigger gap is accepted rather than worked around: lefthook inspects only fi
|
||||
|
||||
The file discloses **direct** dependencies by default. The complete npm closure with pinned versions already lives in `pnpm-lock.yaml` (`pnpm licenses list` renders it) and the Python closure in `python/sdk/uv.lock`; re-materializing either as prose would be a second, worse copy. The one explicit transitive disclosure is the official Claude platform payload set declared by `@anthropic-ai/claude-agent-sdk` through `optionalDependencies`, because those packages carry the distributed Claude Code executable rather than ordinary library implementation detail.
|
||||
|
||||
**Tiering is by declaring area, not by manifest section.** A package is a runtime dependency when any manifest outside `DEV_ONLY_AREAS` — the root manifest, `packages/support/`, `packages/client/test-runtime/`, `website/`, `examples/`, `native/` — names it under `dependencies` or `optionalDependencies`. Section names alone are wrong in both directions: a test-support package declares `vitest` under `dependencies` without shipping it, and the root source-run scripts execute through `tsx`, which no manifest declares as a runtime dependency at all (the generator marks it runtime explicitly).
|
||||
**Tiering is by declaring area, not by manifest section.** A package is a runtime dependency when any manifest outside `DEV_ONLY_AREAS` — the root manifest, `packages/test-support/`, `packages/test-support/client-runtime/`, `website/`, `examples/`, `native/` — names it under `dependencies` or `optionalDependencies`. Section names alone are wrong in both directions: a test-support package declares `vitest` under `dependencies` without shipping it, and the root source-run scripts execute through `tsx`, which no manifest declares as a runtime dependency at all (the generator marks it runtime explicitly).
|
||||
|
||||
The runtime tier deliberately covers **every mountable plugin**, not just what the CLI, Web UI, and Python runtime load by default. Source execution can mount any plugin package from a user's `cordis.yml`; `@modelcontextprotocol/sdk` and the OpenTelemetry packages therefore reach real users even though no default assembly imports them. Under-disclosure is the costly direction for a legal notice.
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ Status: implemented
|
||||
|
||||
文件默认只披露**直接**依赖。完整的 npm 闭包连同锁定版本已记录在 `pnpm-lock.yaml`(`pnpm licenses list` 可渲染),Python 闭包记录在 `python/sdk/uv.lock`;再用散文誊一遍只会得到一份更差的副本。唯一明确披露的传递依赖,是 `@anthropic-ai/claude-agent-sdk` 通过 `optionalDependencies` 声明的官方 Claude 平台载荷集合,因为这些包承载随产品分发的 Claude Code 可执行文件,而非普通的库实现细节。
|
||||
|
||||
**分层依据是声明方所在区域,而非 manifest 字段名。** 只要 `DEV_ONLY_AREAS` 之外的任一 manifest——即根 manifest、`packages/support/`、`packages/client/test-runtime/`、`website/`、`examples/`、`native/` 之外——在 `dependencies` 或 `optionalDependencies` 里点名某个包,它就是运行时依赖。单看字段名在两个方向上都会出错:测试支撑包把 `vitest` 写在 `dependencies` 里却并不交付它;而根目录的源码运行脚本通过 `tsx` 执行,根本没有任何 manifest 把它声明为运行时依赖,只能由生成器显式标记。
|
||||
**分层依据是声明方所在区域,而非 manifest 字段名。** 只要 `DEV_ONLY_AREAS` 之外的任一 manifest——即根 manifest、`packages/test-support/`、`packages/test-support/client-runtime/`、`website/`、`examples/`、`native/` 之外——在 `dependencies` 或 `optionalDependencies` 里点名某个包,它就是运行时依赖。单看字段名在两个方向上都会出错:测试支撑包把 `vitest` 写在 `dependencies` 里却并不交付它;而根目录的源码运行脚本通过 `tsx` 执行,根本没有任何 manifest 把它声明为运行时依赖,只能由生成器显式标记。
|
||||
|
||||
运行时层刻意覆盖**所有可挂载的插件**,而不止 CLI、Web UI 与 Python 运行时默认加载的那些。从源码运行时,用户可以通过 `cordis.yml` 挂载任何插件包;因此,`@modelcontextprotocol/sdk` 与 OpenTelemetry 系列即使没有任何默认装配引入,也会触达真实用户。对法务披露而言,披露不足才是代价更高的那个方向。
|
||||
|
||||
|
||||
@@ -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-08-api-remotes-generated-contract-build.md
|
||||
2026-08-08-api-remotes-generated-contract-build.md: 947465b19a7c399038ae8a3106f7563592365a8d
|
||||
2026-08-08-api-remotes-generated-contract-build.zh.md: 26108bc840f701cb02db4a41138024a1be3c549f
|
||||
2026-08-08-api-remotes-generated-contract-build.md: 2f5da20c947e60a3c76514631d1c64c38e07b4cd
|
||||
2026-08-08-api-remotes-generated-contract-build.zh.md: b27e90ce3bd6d54500db48ed5ec3865c5e0634b4
|
||||
|
||||
@@ -6,13 +6,13 @@ English | [中文](2026-08-08-api-remotes-generated-contract-build.zh.md)
|
||||
|
||||
## Problem
|
||||
|
||||
TypeRT must generate `/remote` declarations and runtime contributions from the Host's `@Remote` methods before the Client's `api-remotes/src/client/index.ts` can typecheck and bundle those contributions. If the root build hands both the Host and Client Project Reference graphs to tsc together, the Client compiles before the generated artifacts exist. Adding a separate contracts preprocessing step would instead compile the generator again outside the normal Host graph and let stale artifacts hide incorrect dependencies.
|
||||
Typert must generate `/remote` declarations and runtime contributions from the Host's `@Remote` methods before the Client's `api-remotes/src/client/index.ts` can typecheck and bundle those contributions. If the root build hands both the Host and Client Project Reference graphs to tsc together, the Client compiles before the generated artifacts exist. Adding a separate contracts preprocessing step would instead compile the generator again outside the normal Host graph and let stale artifacts hide incorrect dependencies.
|
||||
|
||||
This ordering dependency must not change the repository's ordinary package rule. A normal package belongs to exactly one TypeScript face: Host packages are registered in `tsconfig.host.json`, and Client packages in `tsconfig.client.json`. A Client plugin having both a Node loader entry and a browser entry describes its bundled artifact shapes, not a reason to split its TypeScript project.
|
||||
|
||||
## Decision
|
||||
|
||||
The root build completes Host tsc and Host tsdown first, with Host tsdown running TypeRT and generating the Remote Client contract. It then completes Client tsc, Client tsdown, and the Web build:
|
||||
The root build completes Host tsc and Host tsdown first, with Host tsdown running Typert and generating the Remote Client contract. It then completes Client tsc, Client tsdown, and the Web build:
|
||||
|
||||
~~~text
|
||||
tsc -b tsconfig.host.json
|
||||
@@ -49,11 +49,11 @@ The two projects use disjoint `files` and separate `.tsbuildinfo` files, so they
|
||||
|
||||
This exception follows from the real generated-contract ordering and is not a template available to ordinary packages. New packages remain restricted to one aggregate; adding another exception requires changing this decision and proving another generated dependency that cannot be eliminated.
|
||||
|
||||
## TypeRT and tsdown
|
||||
## Typert and tsdown
|
||||
|
||||
Host tsdown enables `typertPlugin({ mode: 'workspace', faces: ['host'] })` in the normal root config. The generator uses only `tsconfig.host.json` as its program seed and produces both `typert.host.*` and the `typert.remote-client.*` projection of Host contracts; Client tsdown neither starts TypeRT nor analyzes the Client aggregate.
|
||||
Host tsdown enables `typertPlugin({ mode: 'workspace', faces: ['host'] })` in the normal root config. The generator uses only `tsconfig.host.json` as its program seed and produces both `typert.host.*` and the `typert.remote-client.*` projection of Host contracts; Client tsdown neither starts Typert nor analyzes the Client aggregate.
|
||||
|
||||
The TypeRT analyzer distinguishes compiler faces from runtime faces. Direct Project References in the aggregate determine which compiler face analyzes a project; only a split project explicitly referenced through `tsconfig.host.json` or `tsconfig.client.json` is restricted to that corresponding face. Runtime models follow package subpath contributions instead, so an ordinary single-project `dshClient` package may contribute both Host and Client runtime models. Consequently, Host analysis of `api-remotes` does not also register its Client entry, while an ordinary dual-entry package does not lose its Host model.
|
||||
The Typert analyzer distinguishes compiler faces from runtime faces. Direct Project References in the aggregate determine which compiler face analyzes a project; only a split project explicitly referenced through `tsconfig.host.json` or `tsconfig.client.json` is restricted to that corresponding face. Runtime models follow package subpath contributions instead, so an ordinary single-project `dshClient` package may contribute both Host and Client runtime models. Consequently, Host analysis of `api-remotes` does not also register its Client entry, while an ordinary dual-entry package does not lose its Host model.
|
||||
|
||||
Both the Host and Client tsdown passes receive the same complete workspace of `vendor/*`, `packages/*/*`, and `apps/cli`. The root config does not scan `lib/types/client/index.js`, maintain a package classification table, or use a tsdown filter; package-local configs return entries for the current phase according to `DSH_BUILD_FACE`.
|
||||
|
||||
@@ -69,7 +69,7 @@ An ordinary Client plugin returns an empty config during the Host pass and produ
|
||||
|
||||
**Scan Client compilation artifacts or maintain two workspace lists.** Artifact scanning would make package participation depend on residual files, while hand-maintained lists and package-name filters would drift as directories change. A complete workspace with package-local face selection already provides deterministic behavior.
|
||||
|
||||
**Run TypeRT again during the Client pass.** Remote Client is a projection of the Host contract and has no independent Client reflection source; a second TypeRT program would only duplicate work and increase the risk of mixing both sides' declarations into one analysis.
|
||||
**Run Typert again during the Client pass.** Remote Client is a projection of the Host contract and has no independent Client reflection source; a second Typert program would only duplicate work and increase the risk of mixing both sides' declarations into one analysis.
|
||||
|
||||
## Consequences
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@ Status: implemented
|
||||
|
||||
## 问题
|
||||
|
||||
Host 的 `@Remote` 方法需要先由 TypeRT 生成 `/remote` 声明和运行时贡献,Client 的 `api-remotes/src/client/index.ts` 才能通过类型检查并打包这些贡献。若根构建先把 Host 与 Client 两张 Project Reference 图一起交给 tsc,Client 会在生成产物存在之前编译;若增加独立 contracts 预处理,又会让 generator 脱离正常 Host 图重复编译,并允许陈旧产物掩盖错误依赖。
|
||||
Host 的 `@Remote` 方法需要先由 Typert 生成 `/remote` 声明和运行时贡献,Client 的 `api-remotes/src/client/index.ts` 才能通过类型检查并打包这些贡献。若根构建先把 Host 与 Client 两张 Project Reference 图一起交给 tsc,Client 会在生成产物存在之前编译;若增加独立 contracts 预处理,又会让 generator 脱离正常 Host 图重复编译,并允许陈旧产物掩盖错误依赖。
|
||||
|
||||
该顺序依赖不能改变仓库的普通 package 规则。正常 package 只属于一个 TypeScript face:Host package 登记在 `tsconfig.host.json`,Client package 登记在 `tsconfig.client.json`。一个 Client plugin 同时具有 Node loader 入口与 browser 入口,只是打包产物形态,不是拆分 TypeScript project 的理由。
|
||||
|
||||
## 决策
|
||||
|
||||
根构建先完成 Host tsc 和 Host tsdown,由 Host tsdown 运行 TypeRT 并生成 Remote Client 约定;随后完成 Client tsc、Client tsdown 和 Web 构建:
|
||||
根构建先完成 Host tsc 和 Host tsdown,由 Host tsdown 运行 Typert 并生成 Remote Client 约定;随后完成 Client tsc、Client tsdown 和 Web 构建:
|
||||
|
||||
~~~text
|
||||
tsc -b tsconfig.host.json
|
||||
@@ -49,11 +49,11 @@ packages/api/remotes/
|
||||
|
||||
这个例外由生成约定的真实先后关系决定,不是可供普通 package 选择的模板。新增 package 仍只能登记进一个 aggregate;只有修改本决策并证明存在另一条不可消除的生成依赖,才能增加例外。
|
||||
|
||||
## TypeRT 与 tsdown
|
||||
## Typert 与 tsdown
|
||||
|
||||
Host tsdown 在普通根配置中启用 `typertPlugin({ mode: 'workspace', faces: ['host'] })`。generator 只以 `tsconfig.host.json` 为 program 种子,生成 `typert.host.*` 以及 Host 约定投影出的 `typert.remote-client.*`;Client tsdown 不启动 TypeRT,也不分析 Client aggregate。
|
||||
Host tsdown 在普通根配置中启用 `typertPlugin({ mode: 'workspace', faces: ['host'] })`。generator 只以 `tsconfig.host.json` 为 program 种子,生成 `typert.host.*` 以及 Host 约定投影出的 `typert.remote-client.*`;Client tsdown 不启动 Typert,也不分析 Client aggregate。
|
||||
|
||||
TypeScript compiler face 与 TypeRT 运行时产物 face 是两层概念。普通 `dshClient` package 即使只有一个 compiler project,也可以按公开 subpath 同时贡献 Host 与 Client 运行时模型;aggregate 显式引用 `tsconfig.host.json` 或 `tsconfig.client.json` 时,analyzer 才把该 project 限定到对应 face。因此 `api-remotes` 的 Host 分析不会顺带注册其 Client 入口,普通双入口 package 的 Host 模型也不会丢失。
|
||||
TypeScript compiler face 与 Typert 运行时产物 face 是两层概念。普通 `dshClient` package 即使只有一个 compiler project,也可以按公开 subpath 同时贡献 Host 与 Client 运行时模型;aggregate 显式引用 `tsconfig.host.json` 或 `tsconfig.client.json` 时,analyzer 才把该 project 限定到对应 face。因此 `api-remotes` 的 Host 分析不会顺带注册其 Client 入口,普通双入口 package 的 Host 模型也不会丢失。
|
||||
|
||||
Host 与 Client 两次 tsdown 都接收 `vendor/*`、`packages/*/*` 和 `apps/cli` 这组完整 workspace。根配置不扫描 `lib/types/client/index.js`,不维护 package 分类表,也不使用 tsdown filter;包内配置根据 `DSH_BUILD_FACE` 返回本阶段入口。
|
||||
|
||||
@@ -69,7 +69,7 @@ Host 与 Client 两次 tsdown 都接收 `vendor/*`、`packages/*/*` 和 `apps/cl
|
||||
|
||||
**扫描 Client 编译产物或维护两份 workspace 清单。** 产物扫描会让 package 是否参与构建取决于残留文件,手工清单和 package 名过滤则会随目录调整产生漂移。完整 workspace 加包内 face 选择已经提供确定行为。
|
||||
|
||||
**在 Client pass 再运行 TypeRT。** Remote Client 是 Host 约定的投影,没有独立 Client 反射源;第二个 TypeRT program 只会重复工作并增加两侧声明混入同一分析的风险。
|
||||
**在 Client pass 再运行 Typert。** Remote Client 是 Host 约定的投影,没有独立 Client 反射源;第二个 Typert program 只会重复工作并增加两侧声明混入同一分析的风险。
|
||||
|
||||
## 后果
|
||||
|
||||
|
||||
@@ -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-08-unified-github-label-taxonomy.md
|
||||
2026-08-08-unified-github-label-taxonomy.md: 8005629861f306d20293af6b348f19bf79cbe1c3
|
||||
2026-08-08-unified-github-label-taxonomy.md: 625c5c1cac951bdc97187c17c964d677f31131c7
|
||||
2026-08-08-unified-github-label-taxonomy.zh.md: 855a2b98f44d517abe1f7718ae4e81262cb031b6
|
||||
|
||||
@@ -36,7 +36,7 @@ Repository policy rejects unsupported `kind/*` values and reserves every alias r
|
||||
Areas name durable product or engineering subjects rather than temporary initiatives, ownership, or every path touched incidentally. A pull request carries multiple areas when it changes distinct behavior or APIs, but it does not combine an umbrella and a narrower label for the same change. GitHub's live `area/*` names and descriptions own the current inventory; this record defines selection cases that cannot fit reliably in short label descriptions.
|
||||
|
||||
- `area/web` covers browser and Electron graphical interfaces, `area/vscode` covers the editor extension, and `area/api` covers cross-interface protocols and language SDKs.
|
||||
- `area/planning` covers goals, plans, todos, and scheduling, while `area/workflow` covers executable workflows and background task runtimes.
|
||||
- `area/planning` covers goals, plans, todos, and scheduling, while `area/workflow` covers executable workflows and background job runtimes.
|
||||
- `area/artifact` deliberately combines artifacts, attachments, and multimodal delivery. Split labels become justified only when those concerns again need independent review or queries.
|
||||
- `area/tools` applies to generic registry, schema, and execution contracts. A concrete capability uses its own area unless it also changes one of those contracts.
|
||||
- `area/hooks` means the Claude Code and Codex bridges, `area/infra` covers build, release, CI, repository gates, generators, dependencies, and developer tooling, and `area/windows` covers native Windows product support rather than CI runner selection.
|
||||
|
||||
@@ -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-10-npm-release-sequences.md
|
||||
2026-08-10-npm-release-sequences.md: df81756ab84163b21996b5e2f12c5c8db994d9a5
|
||||
2026-08-10-npm-release-sequences.zh.md: 03269aeb987509034564bd0cac92f5d26c7f9b58
|
||||
2026-08-10-npm-release-sequences.md: 13f343911b6d684ec8738b2245ceae8d848e2f0c
|
||||
2026-08-10-npm-release-sequences.zh.md: 4116b74b54e84d33df29fd0ab9169f8d38d5514d
|
||||
|
||||
@@ -22,7 +22,7 @@ Two hard blockers sat in the way. All 217 workspace manifests set `private: true
|
||||
|
||||
| Sequence | Members | Version baseline | Tag | Workflow |
|
||||
|---|---|---|---|---|
|
||||
| dsh | `packages/*/*` + `apps/*` (`@deepseek-ai/dsh` and `@deepseek-ai/dsh-frontend`) | one version for the family and the workspace root, `0.0.x` | `dsh-v<version>` | `release.yml` |
|
||||
| dsh | `packages/*/*` + `apps/*` (`@deepseek-ai/dsh` and `@deepseek-ai/dsh-web-frontend`) | one version for the family and the workspace root, `0.0.x` | `dsh-v<version>` | `release.yml` |
|
||||
| vendored framework | the nine `vendor/*` packages | each package on its own version line | `vendor-<package>-v<version>` (one per package) | `release-vendor.yml` |
|
||||
| native | `native/landlock-run/packages/*` | its own `0.0.x` | `landlock-run-v<version>` | `landlock-run-release.yml` |
|
||||
|
||||
@@ -134,7 +134,7 @@ This Agent Note replaces the version scheme and the release-set boundary in [art
|
||||
|
||||
**Verifying only the packed install, with no local registry.** The reference flow unpacks tarballs into a tree and drives it with plain Node, which bypasses version-range resolution. Running a local registry in CI to cover that layer was rejected: artifact correctness is covered by existing tests, the publication path is exercised by the master rehearsal, and a pull request only needs to prove the release set packs. Installing from `file:` specifiers still exercises range resolution for every internal dependency.
|
||||
|
||||
**Selecting a subset by entry closure.** Crawling `dependencies` from `@deepseek-ai/dsh` and `@deepseek-ai/dsh-frontend` yields 156 packages, 61 fewer than the whole set. But this repository's plugins are mounted by name from `cordis.yml` rather than imported: `vendor/cordis-plugin-group` and `vendor/cordis-plugin-logger-console` fall outside the dependency closure while being required at runtime. Selecting by code dependency fails as "the consumer installs it and it will not start", and it would need a standing proof that no mounted package was missed. Under a private scope the extra packages are invisible outside the organization. `python/`, the root `examples/`, `docs/`, and `website/` are not members.
|
||||
**Selecting a subset by entry closure.** Crawling `dependencies` from `@deepseek-ai/dsh` and `@deepseek-ai/dsh-web-frontend` yields 156 packages, 61 fewer than the whole set. But this repository's plugins are mounted by name from `cordis.yml` rather than imported: `vendor/cordis-plugin-group` and `vendor/cordis-plugin-logger-console` fall outside the dependency closure while being required at runtime. Selecting by code dependency fails as "the consumer installs it and it will not start", and it would need a standing proof that no mounted package was missed. Under a private scope the extra packages are invisible outside the organization. `python/`, the root `examples/`, `docs/`, and `website/` are not members.
|
||||
|
||||
**Extending `scripts/publish-npm-baseline.ts`.** It is a local publication script that packs and publishes in one process, the opposite of separating credential-free packing from protected publication. Its verified parts — payload validation and installed-artifact probes — are reused so `pnpm run duplication` does not report clones.
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ Status: implemented
|
||||
|
||||
| 序列 | 成员 | 版本基线 | tag | workflow |
|
||||
|---|---|---|---|---|
|
||||
| dsh | `packages/*/*` + `apps/*`(`@deepseek-ai/dsh` 与 `@deepseek-ai/dsh-frontend`) | 全族与 workspace 根共用一个 `0.0.x` | `dsh-v<版本>` | `release.yml` |
|
||||
| dsh | `packages/*/*` + `apps/*`(`@deepseek-ai/dsh` 与 `@deepseek-ai/dsh-web-frontend`) | 全族与 workspace 根共用一个 `0.0.x` | `dsh-v<版本>` | `release.yml` |
|
||||
| vendored framework | `vendor/*` 九个包 | 每包各自一条版本线 | `vendor-<包名>-v<版本>`(每包一个) | `release-vendor.yml` |
|
||||
| native | `native/landlock-run/packages/*` | 自己的 `0.0.x` | `landlock-run-v<版本>` | `landlock-run-release.yml` |
|
||||
|
||||
@@ -134,7 +134,7 @@ dsh 的验证会一并安装 vendored 族的 pack 产物。harness 的包把 ven
|
||||
|
||||
**只做打包后安装验证,不起本地 registry。** 参照流程是把 tarball 解包成一棵树、用普通 Node 驱动,这绕过了版本范围解析。曾提议在 CI 里起本地 registry 补这一层,被否:产物正确性已由既有测试覆盖,发布路径由 master 的排练覆盖,而 pull request 只需证明发布集能打出来。用 `file:` 说明符安装依然会对每个内部依赖走一遍范围解析。
|
||||
|
||||
**按入口闭包挑一部分包发。** 从 `@deepseek-ai/dsh` 与 `@deepseek-ai/dsh-frontend` 沿 `dependencies` 爬得到 156 个包,比全量少 61 个。但本仓的插件是 `cordis.yml` 按名字挂载的、不是被 import 的:`vendor/cordis-plugin-group` 与 `vendor/cordis-plugin-logger-console` 落在依赖闭包之外,却是运行时必需。照代码依赖挑的失败形态是「消费方装完起不来」,而且要额外持续证明「没漏任何挂载项」。私有 scope 下多出来的包对组织外不可见。`python/`、根 `examples/`、`docs/` 与 `website/` 不是成员。
|
||||
**按入口闭包挑一部分包发。** 从 `@deepseek-ai/dsh` 与 `@deepseek-ai/dsh-web-frontend` 沿 `dependencies` 爬得到 156 个包,比全量少 61 个。但本仓的插件是 `cordis.yml` 按名字挂载的、不是被 import 的:`vendor/cordis-plugin-group` 与 `vendor/cordis-plugin-logger-console` 落在依赖闭包之外,却是运行时必需。照代码依赖挑的失败形态是「消费方装完起不来」,而且要额外持续证明「没漏任何挂载项」。私有 scope 下多出来的包对组织外不可见。`python/`、根 `examples/`、`docs/` 与 `website/` 不是成员。
|
||||
|
||||
**在 `scripts/publish-npm-baseline.ts` 上扩展。** 它是本机发布脚本,把 pack 与 publish 放在同一进程,与「无凭据 pack、受保护 publish」的分离相反。它验证过的零件——payload 校验与已安装产物探针——被搬运复用,以免 `pnpm run duplication` 判重复。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user