Merge remote-tracking branch 'origin/master' into fix/windows-directory-junction

# Conflicts:
#	.agents/notes/implemented/architecture/2026-09-05-workspace-files-service.i18n.yaml
#	.agents/notes/implemented/architecture/2026-09-05-workspace-files-service.md
#	.agents/notes/implemented/architecture/2026-09-05-workspace-files-service.zh.md
#	packages/api/workspace-files/README.i18n.yaml
This commit is contained in:
turtle1999 committed 2026-09-24 19:41:46 +08:00
commit 74f85e177e
5392 files changed
+261420 -65295

No files matched your search

+45 -5
View File
@@ -1,6 +1,46 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/README.md
README.md: 6872de0a1390fa5a1707b9f464c9e0edeb2da4be
README.zh.md: ced81f77fa904ad0b5cb5219383ef651d87392b8
/agent-notes:
en: a10991a192c7b55d
zh: c2e5b938ece4f366
/agent-notes/layout-and-naming:
en: 6b38cb0eb38c2baf
zh: 535234fb23fc8921
/agent-notes/classification:
en: 055a5e49f9af3dc2
zh: 9f7c78409cccfded
/agent-notes/archiving-and-deletion:
en: 6c393c7058c787d7
zh: 70ce9ca3bd9c2133
/agent-notes/when-to-write-one:
en: 2beb1b94d8fb633c
zh: 889b5542bb771205
/agent-notes/the-file-format:
en: 601f85df49f80fc7
zh: acbd0955d6543b13
/agent-notes/the-file-format/the-header-block:
en: 16fdaab0c74a5bb5
zh: 2553f145a1eb878f
/agent-notes/the-file-format/the-body-skeleton:
en: 740b7e964b9aec37
zh: 8551ddef1ffa776a
/agent-notes/the-file-format/the-body-skeleton/proposed:
en: acc0c035c5ca6fd7
zh: 8a65816dfac9e580
/agent-notes/the-file-format/the-body-skeleton/implemented:
en: f3523d7e40cc4e2f
zh: 574fa8959f8829a1
/agent-notes/the-file-format/the-body-skeleton/rejected:
en: f0ff5d05191f2315
zh: 3f9df0dd01a5cbed
/agent-notes/the-file-format/alternatives-considered-mandatory:
en: fe1bf385aee54033
zh: 37cb4ea86ec6d99d
/agent-notes/the-file-format/moving-between-lifecycles:
en: d3f18ba194dfb677
zh: 3d202868deda2f31
/agent-notes/the-file-format/chinese-counterparts:
en: d72a33b7c63722b2
zh: f8320c91b1f77ae6
@@ -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-08-03-per-session-agent-presets.md
2026-08-03-per-session-agent-presets.md: 47f2e28c2aac583ce4ca810157e9c7abe58256d5
2026-08-03-per-session-agent-presets.zh.md: 88b643ea710364f18ff7c73a8ca0e10de0fbb44c
2026-08-03-per-session-agent-presets.md: a1f2ad294edfdaaf2dab2d02e858e4dcb0a0c746
2026-08-03-per-session-agent-presets.zh.md: b745c22c91b4017131a32796c085a869a2eabaf0
@@ -1,6 +1,7 @@
# Agent Note: A session's agent is composed from a preset cordis.yml
Status: implemented
Archived: 2026-09-18
English | [中文](2026-08-03-per-session-agent-presets.zh.md)
@@ -1,6 +1,7 @@
# Agent Note: 会话的 agent 由一份 preset cordis.yml 组装而成
Status: implemented
Archived: 2026-09-18
[English](2026-08-03-per-session-agent-presets.md) | 中文
@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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/archived/feature/2026-08-25-unified-task-list.md
2026-08-25-unified-task-list.md: f2f955e36a78eee8fa8ff8a804293bcc37a44acd
2026-08-25-unified-task-list.zh.md: 5a4c51a6cc3d0f331d2559debb73dc02e9cf12c5
@@ -0,0 +1,49 @@
# Agent Note: One session-header task list — jobs joined with activities in the UI projection only
Status: implemented
Archived: 2026-09-03
English | [中文](2026-08-25-unified-task-list.zh.md)
Superseded: the two-roster join described here was removed with the activity seam — the job rows are now the whole roster; see [jobs absorb the record](../architecture/2026-09-01-jobs-absorb-activity-record.md).
## Problem
The [activity observation seam](2026-08-24-activity-observation-seam.md) shipped its Web surface as a second session-header button beside the [background-job list](2026-08-08-web-background-job-display.md). A background bash run registers in both planes — `ctx.jobs` for control and `ctx.activities` for observation — so the same work rendered twice: once in "background jobs" with lifecycle and duration, once in "activities" with expandable live output. Two near-identical popovers with different names for overlapping row sets read as a product accident, and the flat activity rows (live and settled interleaved, single-line, no duration) had no visual hierarchy.
## Decision
The service planes stay orthogonal; the join happens once, per row, in the UI projection.
- **`ctx.jobs` and `ctx.activities` remain separate services.** Jobs are the control plane: model-visible ids, a consuming `readOutput` cursor the model drains, `stopping`, `kill`, and the `reported` completion-notice contract. Activities are the transient observation plane: non-consuming absolute offsets, invisible to the model, gone on restart. Merging the services would force one registry to carry both a consuming and a non-consuming cursor and would blur the "model-visible ⟺ logged" line for a plane designed to stay off the session log.
- **`dsh-client-ui-activity` renders the single merged list; `dsh-client-ui-jobs` is deleted** (pre-release, no compatibility shim), and the merged entry takes the job list's slot order. Each `jobsBySession` row is joined with the activity carrying its `correlation.jobId`: the job supplies identity, lifecycle (`stopping` exists only there), duration, and the model-visible `detail`; the activity supplies the expandable output panel. An activity without a job (a workflow run) keeps its own row; an activity whose job is not in the projection is not dropped. Without the activity registry, job rows still render — they just offer no panel, so the merged control degrades to exactly the old job list.
- **User-facing vocabulary is "task" (任务)** — `N tasks running` / `N 个任务进行中` — because every row is running work to the user, while "background job" excludes workflow runs and "activity" names the internal plane, not the user concept. The dictionary namespace and package names stay `activity`: internal names follow the naming ledger, not display copy.
- **Hierarchy**: live rows first (label over a kind-badge-and-status second line, ticking duration), then settled rows compacted to one de-emphasized line; each non-empty section carries its own heading (Running / Finished). Rows without an observable activity render as static rows with no expansion affordance.
Deliberately not joined: subagent delegation rows stay bare job rows (the subagent panel is their surface), and foreground commands stay in their tool cards — neither gains an activity producer.
## Alternatives considered
- **Merge the services** — rejected for the cursor-semantics and model-visibility reasons above.
- **Keep the job list and bolt output onto it** — leaves workflow runs (activities without jobs) homeless, forcing a second list to survive anyway.
## Refinements from browser acceptance
Driving the merged list in the real app produced four presentation decisions, all scoped to the expanded panel and the header band:
- **The header band order is preset → tasks → subagent catalog.** The root-session descendant count moved out of the breadcrumb (`header.lineage`) into the actions band (order 30) and dropped its `/` separator — a root session has no hierarchy to breadcrumb; child sessions keep their `root / child` switcher where the `/` is real. `SubagentCatalogAction` owns the moved seat; the lineage renderer now renders nothing on roots.
- **The panel's copy control copies the command** (`TerminalBlock.copyText`), not the output: a long command ellipsizes in the row, so the control is its only complete source, while output is selectable text below. Supplying `copyText` also keeps the control rendered before any output exists.
- **The panel scrolls instead of folding**: commands and output lines wrap in full (`--dsl-terminal-command-whitespace` / `--dsl-terminal-line-whitespace: pre-wrap`, so the output region never scrolls sideways) and the output region caps at a fixed height (`--dsl-terminal-output-max-height`) with `maxLines: Infinity` disabling the head/tail fold.
- **The panel draws no run-state dot** (`TerminalBlock.runStateDot: false`) — the row above it already carries the same state — and reclaims the dot gutter via `--dsl-terminal-gutter`. The panel's left spine was dropped with it.
All four land as opt-ins on `TerminalBlock` (props or `--dsl-terminal-*` variables), so tool cards keep their shipped fold/ellipsis/dot behavior unchanged.
## Testing
Component suites cover the join (job lifecycle wins, activity supplies the panel, bare-job rows, standalone activities), sections, durations, and the panel options; `pnpm vitest run packages/client/ui-activity packages/client/ui-primitives packages/client/ui-subagent` runs them. The keyless web e2e pair (`background-job-list`, `live-activity-stream`) replays the merged list end to end against ARIA goldens; `agent-preset-selection` pins the header band order.
## Consequences
- The two web e2e scenarios (`background-job-list`, `live-activity-stream`) now assert one "Tasks" list; the job-list scenario's row gained a live-output panel, which is the join working end to end.
- A human kill control on live rows is still blocked on the jobs `reported` contract question recorded in the job-display note.
- The `job` locale namespace is gone with its package; `activity` owns the merged copy including the duration vocabulary.
@@ -0,0 +1,49 @@
# Agent Note: 会话头部单一任务列表——jobs 与 activity 只在 UI 投影层合并
Status: implemented
Archived: 2026-09-03
[English](2026-08-25-unified-task-list.md) | 中文
Superseded: 本文描述的双名册 join 已随 activity seam 一并移除——job 行现在就是完整名册;见 [jobs 吸收 record](../architecture/2026-09-01-jobs-absorb-activity-record.zh.md)。
## 问题
[activity 观察面](2026-08-24-activity-observation-seam.zh.md)的 Web 呈现落地为[后台任务列表](2026-08-08-web-background-job-display.zh.md)旁边的第二个会话头部按钮。一次后台 bash 会同时登记在两个面里——`ctx.jobs` 负责控制、`ctx.activities` 负责观察——于是同一份工作渲染了两次:一次在"后台任务"里带生命周期与时长,一次在"活动"里带可展开的实时输出。两个行集合高度重叠、名字却不同的近似弹层,读起来像产品事故;而活动列表的扁平行(live 与 settled 混排、单行、无时长)也缺乏视觉层次。
## 决策
服务面保持正交;合并只在 UI 投影层逐行发生一次。
- **`ctx.jobs` 与 `ctx.activities` 仍是两个服务。** jobs 是控制面:模型可见的 id、模型消耗式的 `readOutput` 游标、`stopping`、`kill` 与 `reported` 完成通知契约。activity 是瞬态观察面:非消耗式绝对偏移、模型不可见、重启即无。合并服务会迫使一个注册表同时携带消耗式与非消耗式两种游标,并模糊这个刻意不进 session log 的面与"模型可见 ⟺ 已记录"不变量的边界。
- **`dsh-client-ui-activity` 渲染唯一的合并列表;`dsh-client-ui-jobs` 删除**(预发布阶段,不留兼容层),合并入口占用原 job 列表的 slot 顺位。每个 `jobsBySession` 行与携带其 `correlation.jobId` 的 activity 逐行 join:job 提供身份、生命周期(`stopping` 只存在于此)、时长与模型可见 `detail`;activity 提供可展开的输出面板。没有 job 的 activity(workflow 运行)保留自己的行;job 不在投影里的 activity 也不会被丢弃。没有 activity 注册表时 job 行照常渲染——只是没有面板,合并控件退化为与旧 job 列表完全等价。
- **用户可见词汇统一为"任务"(task)**——`N 个任务进行中` / `N tasks running`——因为对用户而言每一行都是在跑的工作,而"后台任务"排除了 workflow 运行、"活动"命名的是内部面而非用户概念。词典命名空间与包名保持 `activity`:内部名遵循命名台账,不跟随展示文案。
- **层次**:进行中的行在前(命令为主行、kind 徽章加状态为副行、时长每秒跳动),已结束的行折为降权单行;每个非空分组带自己的标题(进行中 / 已结束)。没有可观察 activity 的行渲染为无展开交互的静态行。
刻意不合并的:subagent 委托行保持裸 job 行(subagent 面板是它的呈现面),前台命令留在工具卡片里——两者都不接活动生产者。
## 曾考虑的替代方案
- **合并服务层**——因上述游标语义与模型可见性理由否决。
- **保留 job 列表、把输出挂上去**——workflow 运行(无 job 的 activity)无处安放,第二个列表终究得活下来。
## 浏览器验收带来的细化
在真实应用里驱动合并列表得出四个呈现决策,全部限定在展开面板与头部条带:
- **头部条带顺序为 preset → 任务 → subagent 目录。** 根会话的后代数量从面包屑(`header.lineage`)移入操作区(order 30)并去掉 `/` 分隔符——根会话没有可面包屑的层级;子会话保留 `根 / 子` 切换器,那里的 `/` 是真实层级。移位后的席位由 `SubagentCatalogAction` 拥有;谱系 renderer 在根会话上不再渲染任何东西。
- **面板的复制控件复制命令**(`TerminalBlock.copyText`)而非输出:长命令在行内被省略号截断,控件是它唯一的完整来源,而输出本身就是下方可选中的文本。提供 `copyText` 还让控件在任何输出出现之前就保持渲染。
- **面板以滚动取代折叠**:命令与输出行完整换行(`--dsl-terminal-command-whitespace` / `--dsl-terminal-line-whitespace: pre-wrap`,输出区因此永不横向滚动),输出区以固定高度封顶(`--dsl-terminal-output-max-height`),`maxLines: Infinity` 禁用头尾折叠。
- **面板不画运行状态点**(`TerminalBlock.runStateDot: false`)——上方的行已携带同一状态——并通过 `--dsl-terminal-gutter` 收回状态点落区。面板左侧竖线随之移除。
四项全部以 `TerminalBlock` 的可选项落地(prop 或 `--dsl-terminal-*` 变量),工具卡片保持既有的折叠/省略/状态点行为不变。
## 测试
组件套件覆盖 join(job 生命周期优先、activity 提供面板、裸 job 行、独立 activity)、分段、时长与面板选项;`pnpm vitest run packages/client/ui-activity packages/client/ui-primitives packages/client/ui-subagent` 运行它们。无密钥 web e2e 对(`background-job-list`、`live-activity-stream`)按 ARIA golden 端到端回放合并列表;`agent-preset-selection` 钉住头部条带顺序。
## 后果
- 两个 web e2e 场景(`background-job-list`、`live-activity-stream`)现在断言同一个"任务"列表;job 场景的行获得了实时输出面板,这正是 join 端到端生效的证据。
- live 行上的人工 kill 控件仍被 job-display note 记录的 jobs `reported` 契约问题阻塞。
- `job` 词典命名空间随包一起消失;`activity` 拥有合并后的全部文案,包括时长词汇。
+15 -3
View File
@@ -160,6 +160,9 @@
"architecture/2026-08-01-packaged-ripgrep-search.i18n.yaml": "sha256:43c9128079955e974fe1da3ce1a10779b4f5a25ac3629f92e3b1de847ad45050",
"architecture/2026-08-01-packaged-ripgrep-search.md": "sha256:36cf2d6daa654abced690965338aec4628069dc77be3a1da6368a9b097a59ff4",
"architecture/2026-08-01-packaged-ripgrep-search.zh.md": "sha256:45b2fe8e0d492eeff313d2ef3c98fd69761b3257eee3476b8bf53312e8b6095f",
"architecture/2026-08-03-per-session-agent-presets.i18n.yaml": "sha256:3fe057a67e41f9ce4f5cc8b162e264494b39169588fe9c9e48dcf95fd1b208a1",
"architecture/2026-08-03-per-session-agent-presets.md": "sha256:d4c6c6af11f41b57e95ca359e2cbe09780cb0851037998824a5966cab5e12626",
"architecture/2026-08-03-per-session-agent-presets.zh.md": "sha256:c91248b2d9cc5c51c77e9d195aca5d51a06684971b1afafc60b2def72248afca",
"architecture/2026-08-03-pi-ai-declared-provider-catalog.i18n.yaml": "sha256:c1a59c3c04afada633740c808b98e765ccad09220c4c79d8f4207313c9e9aab6",
"architecture/2026-08-03-pi-ai-declared-provider-catalog.md": "sha256:fae0c59ece887f7d9344b6254d20cc671894074d53eefffb85dbf45b9104d2b6",
"architecture/2026-08-03-pi-ai-declared-provider-catalog.zh.md": "sha256:8032cefedd51b292d810051ff32e8825958e6d90b2e523a374294ef2f859ca1e",
@@ -751,12 +754,12 @@
"bug-fix/2026-09-09-content-sized-diagram-previews.i18n.yaml": "sha256:a4404fe8e35ca5b6371f9cdb58fea6724cf3e7737bb2db8a3a321d534454b17c",
"bug-fix/2026-09-09-content-sized-diagram-previews.md": "sha256:5239e98e5c057d6f7e10c3f10a0f67273778d99b0c4f10b31a1921c3c6474b80",
"bug-fix/2026-09-09-content-sized-diagram-previews.zh.md": "sha256:c1ee3790a9d5c3561e1d93d5e649afa904c7d19b9d77248c85ef16daccd953e2",
"bug-fix/2026-09-16-movable-mandatory-update-window.i18n.yaml": "sha256:e526ce14ae9557e24364e3686778b130090445ef2152d976b7cc93e76eac6401",
"bug-fix/2026-09-16-movable-mandatory-update-window.md": "sha256:67546cea0b3de2b3e32957a508dbde097d91dd919fe067c8dbecb2c65b50c366",
"bug-fix/2026-09-16-movable-mandatory-update-window.zh.md": "sha256:20a0aade6ee71c89e84d70e23c89bb51e8a38c674d103dd43022feabb8d27be3",
"bug-fix/2026-09-11-session-controller-fork-turn-cut.i18n.yaml": "sha256:4442529ced1c8e48d30f7b50c65ff03eb92dce9815beb438cedbf29f234bce47",
"bug-fix/2026-09-11-session-controller-fork-turn-cut.md": "sha256:a996f24a896c7fc5d81e015db3eae27d8a46c853287572e815623ce35eae1b12",
"bug-fix/2026-09-11-session-controller-fork-turn-cut.zh.md": "sha256:6486f0eacf5067ef9850dc32f1c27b2109a7d4e9e3c498366f5c38742bb53ac5",
"bug-fix/2026-09-16-movable-mandatory-update-window.i18n.yaml": "sha256:e526ce14ae9557e24364e3686778b130090445ef2152d976b7cc93e76eac6401",
"bug-fix/2026-09-16-movable-mandatory-update-window.md": "sha256:67546cea0b3de2b3e32957a508dbde097d91dd919fe067c8dbecb2c65b50c366",
"bug-fix/2026-09-16-movable-mandatory-update-window.zh.md": "sha256:20a0aade6ee71c89e84d70e23c89bb51e8a38c674d103dd43022feabb8d27be3",
"feature/2026-06-14-acp-agent-client-protocol.i18n.yaml": "sha256:006795baa43ae962a8d125cc0f1e9f134bc2ee9fb758b6e7669e3fa0126e1918",
"feature/2026-06-14-acp-agent-client-protocol.md": "sha256:6828c0af74bb3fb96206ca6b21c0e56a000b50e4744aad4bc2c05092f3a5a31b",
"feature/2026-06-14-acp-agent-client-protocol.zh.md": "sha256:ba104e841a1fb84edbd3b6c8119d50445b7785255a7a8d13bb9ac8a2cb4d2e69",
@@ -1378,6 +1381,9 @@
"feature/2026-08-25-loaded-turn-chat-navigation.i18n.yaml": "sha256:86bd02d56cf95ac465d0f6e326ccf75432ffb9c3db47373ae6a795195cff9ea7",
"feature/2026-08-25-loaded-turn-chat-navigation.md": "sha256:0ee1cb6da76b93e467d747aa8ba07697ba648cb213ba52202c51ee1e85dff1a8",
"feature/2026-08-25-loaded-turn-chat-navigation.zh.md": "sha256:5d3e567027fc65241856bf9f9cf0d73a20d53214c49bfbc884ab2ddd19503918",
"feature/2026-08-25-unified-task-list.i18n.yaml": "sha256:fec0d4a3ecf59aafd440bc801c686b14d63152c937f51bebe0da61ff615f6f33",
"feature/2026-08-25-unified-task-list.md": "sha256:30bd4e338a3de2f59af98d512c7878928c61846e6700d6012fc45e51c0bf94df",
"feature/2026-08-25-unified-task-list.zh.md": "sha256:88fce0a52b5387ea98c1f68742c03b2f475c5465c680befb32c587066e52cfce",
"feature/2026-08-26-web-trigger-menu-presentation-polish.i18n.yaml": "sha256:69179f3056c6d5fc35119e83dd7a5af30213502dac3c1f2d4fd43eae96ee2ecf",
"feature/2026-08-26-web-trigger-menu-presentation-polish.md": "sha256:c54e3bbe528d6be711541c61e777e6e4ed4fbc1374df97d846b015d3693679f4",
"feature/2026-08-26-web-trigger-menu-presentation-polish.zh.md": "sha256:7db49018eebbba539838d734a80fbb330e2b73fea3b343900591a3605c6c03b5",
@@ -1555,6 +1561,9 @@
"process/2026-08-08-api-remotes-generated-contract-build.i18n.yaml": "sha256:da10469121712bd6ac4fb1f665ca8bd59597a94b56324d2fe4bdef5235498b6e",
"process/2026-08-08-api-remotes-generated-contract-build.md": "sha256:8c3d7712cce4913cd3c02d1ac2b87def3f7104a7503681afc3c755896ac45d1f",
"process/2026-08-08-api-remotes-generated-contract-build.zh.md": "sha256:e32e1f53c763e769d152c8c41cf8f8977210e82a0d3f7cc7f0421da7e589e9ad",
"process/2026-08-08-automatic-translation-pairing-merges.i18n.yaml": "sha256:5398ef0c48258d3f3a9881e2b34fc4e2086a0b8084b8d7100798dbca6cc39887",
"process/2026-08-08-automatic-translation-pairing-merges.md": "sha256:fb1f3df3246151da920c14fdf195b0cb3bf595a2eed639c84baf70e3f56d36ce",
"process/2026-08-08-automatic-translation-pairing-merges.zh.md": "sha256:9ce7ff6f511ce973637f001b119ce323a5efe0be57cc11d12691aaa36199a8b8",
"process/2026-08-08-lightweight-routine-documentation-translation.i18n.yaml": "sha256:f3b44e6148941de9840ef54be60e60ed6ec32ee04b42a1a472e38838b6aa7b14",
"process/2026-08-08-lightweight-routine-documentation-translation.md": "sha256:264fe2ee2338053a11fe0f0d5ccf12772897fe9fd4f4a7e8a1d6ba226f853e14",
"process/2026-08-08-lightweight-routine-documentation-translation.zh.md": "sha256:3d309e2fc34a6a99bbce4891c32d681e0a23b233791b29a550884f3e753d593c",
@@ -1777,6 +1786,9 @@
"simplification/2026-08-06-user-bubbles-drop-the-branch-action.i18n.yaml": "sha256:e000606d801984d4ee473779891ffe8c197f64f54b75efd82fb46dc84217cd59",
"simplification/2026-08-06-user-bubbles-drop-the-branch-action.md": "sha256:b93ce0d79ee72306d569d80fd81308a2b5704d95df8854b7cbd2f3d898b3f776",
"simplification/2026-08-06-user-bubbles-drop-the-branch-action.zh.md": "sha256:999e3e1252f771c420506a80b7c0d512b70da6770e3e62bb92169180b4cee3e8",
"simplification/2026-08-08-copy-only-preset-authoring.i18n.yaml": "sha256:43bba45597b198a94e3cbf8df31794239c521ecf002338636dca2c099acd94e1",
"simplification/2026-08-08-copy-only-preset-authoring.md": "sha256:be77d385a3c4db534fbbd5b4a830fcb7f6bcd8401221617859569e2c4d837069",
"simplification/2026-08-08-copy-only-preset-authoring.zh.md": "sha256:4c544a08e741c4a273a89dc2a3fda44dffb46af15d0feb8f7bf8efa816bfbd13",
"simplification/2026-08-08-remove-cli-demo.i18n.yaml": "sha256:1baa8649e186e159afb03f112059f46f7a35c303a6039374db8bc4ca743d4bdf",
"simplification/2026-08-08-remove-cli-demo.md": "sha256:a34ce79b674c67a6a47d99c1fa7141b2ae58e36b99da5989d323d229d1921baa",
"simplification/2026-08-08-remove-cli-demo.zh.md": "sha256:96a2a7cc34c7b0abf71b77d666a6349d681fd8a0d9a9c81e30d2aa538d62797a",
@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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/archived/process/2026-08-08-automatic-translation-pairing-merges.md
2026-08-08-automatic-translation-pairing-merges.md: ed693e376d056378b27a8995a6f26fefcdba34b2
2026-08-08-automatic-translation-pairing-merges.zh.md: 827475a92824c22ee6f4c558de81b645c3c2b8dc
@@ -1,6 +1,7 @@
# Agent Note: Automatically compose translation pairing records
Status: implemented
Archived: 2026-09-23
English | [中文](2026-08-08-automatic-translation-pairing-merges.zh.md)
@@ -1,6 +1,7 @@
# Agent Note: 自动组合翻译配对记录
Status: implemented
Archived: 2026-09-23
[English](2026-08-08-automatic-translation-pairing-merges.md) | 中文
@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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/archived/simplification/2026-08-08-copy-only-preset-authoring.md
2026-08-08-copy-only-preset-authoring.md: 07f8a6553cf9c70d5289a074b6e6d0d677dd4a28
2026-08-08-copy-only-preset-authoring.zh.md: 58757a9774354b116d235f890beb136034f29904
@@ -1,6 +1,7 @@
# Agent Note: Copy-only preset authoring, and the way into a preset's files
Status: implemented
Archived: 2026-09-20
English | [中文](2026-08-08-copy-only-preset-authoring.zh.md)
@@ -1,6 +1,7 @@
# Agent Note: 仅复制的 preset 创作,与通往 preset 文件的入口
Status: implemented
Archived: 2026-09-20
[English](2026-08-08-copy-only-preset-authoring.md) | 中文
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-06-11-content-block-vocabulary.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-11-content-block-vocabulary.md
2026-06-11-content-block-vocabulary.md: 917dd5225fdc4ab391e9e4629769abbb68095731
2026-06-11-content-block-vocabulary.zh.md: 9d228eb34dafbdebab44b45dc3b290c9327d3b2b
/agent-note-provider-neutral-content-block-vocabulary-owned-by-dsh-llm:
en: 64935f5c8e315004
zh: 6a9cbb4578eaa437
/agent-note-provider-neutral-content-block-vocabulary-owned-by-dsh-llm/problem:
en: 4e81df7bca1c1638
zh: f7483d180a613237
/agent-note-provider-neutral-content-block-vocabulary-owned-by-dsh-llm/decision:
en: 9526dfcf4da1d000
zh: ea2bf79a02b26b39
/agent-note-provider-neutral-content-block-vocabulary-owned-by-dsh-llm/alternatives-considered:
en: 1de2e19e711105e6
zh: a2cd5a64cc4e9e73
/agent-note-provider-neutral-content-block-vocabulary-owned-by-dsh-llm/consequences:
en: 999d10e69e447e44
zh: 38370da5b900ac30
@@ -1,6 +1,37 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-06-11-dev-invariants-over-deep-readonly.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-11-dev-invariants-over-deep-readonly.md
2026-06-11-dev-invariants-over-deep-readonly.md: 0784960397f4d198e136e284ef9232b4ed3e2c2c
2026-06-11-dev-invariants-over-deep-readonly.zh.md: 7183813130560bf82426c8719570b668ba86b7e5
/agent-note-source-owned-session-immutability-and-dev-mode-invariants:
en: 052aa271e87074c0
zh: 3ccffc50fc1a28d4
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/problem:
en: 6ea85a4531d5e59f
zh: b4b568eb347f016a
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/decision:
en: 6e701ec64c3bbfae
zh: b8ed0f1cb7a0477a
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/decision/session-owns-immutable-history:
en: ff47e58c377a8dc0
zh: 5edbe4f3642a3fe6
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/decision/derived-requests-remain-detached:
en: 975df574ee6e6df8
zh: 96d765058482835a
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/decision/package-owned-invariant-companions-check-relationships:
en: a88e3a896eedca91
zh: 03e96c7870cba932
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/alternatives-considered:
en: 6119e2aff3b6be5a
zh: 76136ef5249c23eb
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/alternatives-considered/pervasive-deep-readonly-types:
en: ec54af2931616616
zh: 5fd9bc469a6fd3a5
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/alternatives-considered/development-only-freezing:
en: 85591197bb62eabf
zh: ba69b9ccf596a6d7
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/alternatives-considered/clone-only-when-deriving-messages:
en: a9848dec50664b92
zh: 7c558550b054627b
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/consequences:
en: bcccf7d464a070db
zh: eccd442a21e2c99e
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-06-11-event-sourced-sessions.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-11-event-sourced-sessions.md
2026-06-11-event-sourced-sessions.md: b6d17d2db1d9b489f3d4224683b61e62be485014
2026-06-11-event-sourced-sessions.zh.md: 11e5740dc2636fc002ed7158167b1dfbb39a971d
/agent-note-event-sourced-sessions-with-derived-message-history:
en: da3abc821101e4b3
zh: c206fa4830920592
/agent-note-event-sourced-sessions-with-derived-message-history/problem:
en: 63b684d349a48a15
zh: 7603f64b445db129
/agent-note-event-sourced-sessions-with-derived-message-history/decision:
en: d60f161037a10269
zh: 799a15fae2534ec4
/agent-note-event-sourced-sessions-with-derived-message-history/alternatives-considered:
en: 73541e0833eb9559
zh: ddca382d54e498e5
/agent-note-event-sourced-sessions-with-derived-message-history/consequences:
en: d2ea77a5c8e30949
zh: 19dc61cb0d29315f
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-06-11-microkernel-event-taxonomy.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-11-microkernel-event-taxonomy.md
2026-06-11-microkernel-event-taxonomy.md: 6cacbc30f29c863de0f8ddfa4df7251a64bc80ca
2026-06-11-microkernel-event-taxonomy.zh.md: 1c7919392b835c491b9dc606d46f638a708d2948
/agent-note-microkernel-extension-via-cordis-event-taxonomy-one-concrete-loop:
en: e5775d7ec6f1cdc3
zh: a364697f860a545a
/agent-note-microkernel-extension-via-cordis-event-taxonomy-one-concrete-loop/problem:
en: 3bc74749db819441
zh: 19b5497ed3a9378b
/agent-note-microkernel-extension-via-cordis-event-taxonomy-one-concrete-loop/decision:
en: 2153b0cb5773cb08
zh: 82d7ad1b250cd52d
/agent-note-microkernel-extension-via-cordis-event-taxonomy-one-concrete-loop/alternatives-considered:
en: e528c5a20e0c55a3
zh: 004d3bf06241cc26
/agent-note-microkernel-extension-via-cordis-event-taxonomy-one-concrete-loop/consequences:
en: 6acb80cdaa7c010f
zh: acca672d8094d985
@@ -1,6 +1,22 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-06-13-capability-seams.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-13-capability-seams.md
2026-06-13-capability-seams.md: 798739b7ef203b10ea657f9e1c178ea7eab094ad
2026-06-13-capability-seams.zh.md: c8f568aa569fe74146f1e7fcc46e00774a39fb84
/agent-note-capability-seams-service-definition-service-provider-consumer-roles:
en: 4c1875882be571bb
zh: 90ef4d8b27587c6b
/agent-note-capability-seams-service-definition-service-provider-consumer-roles/problem:
en: 3215928333de66f7
zh: 2c72fcacccf25741
/agent-note-capability-seams-service-definition-service-provider-consumer-roles/decision:
en: 774c54c0d3d9acad
zh: 7dd4bfaf0ba2181b
/agent-note-capability-seams-service-definition-service-provider-consumer-roles/terminology-seam-names-the-trio-not-the-interface:
en: 8dca727800bea2f4
zh: 4c4e028520967ca0
/agent-note-capability-seams-service-definition-service-provider-consumer-roles/alternatives-considered:
en: cf6e4b1f188d9e4a
zh: bf2485a5f539746c
/agent-note-capability-seams-service-definition-service-provider-consumer-roles/consequences:
en: 941d8b343162edea
zh: 70904b0716de151d
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-06-13-twin-llm-adapters.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-13-twin-llm-adapters.md
2026-06-13-twin-llm-adapters.md: fe8b0b55e0e027e29eb0920e64a1760d0dc35aee
2026-06-13-twin-llm-adapters.zh.md: 4248b5afeb9f3fd4503914e53203c674e3a80dbf
/agent-note-two-llm-adapters-as-a-design-verification-twin:
en: dcb28a02ba26cb31
zh: 096d0ab60a3ad638
/agent-note-two-llm-adapters-as-a-design-verification-twin/problem:
en: feb8f5213be03a5c
zh: 5ca85048792db7d8
/agent-note-two-llm-adapters-as-a-design-verification-twin/decision:
en: 0dd6ebb29aebc164
zh: 20065ae72f4d131d
/agent-note-two-llm-adapters-as-a-design-verification-twin/alternatives-considered:
en: c523a9b402588189
zh: bced37eb1040360a
/agent-note-two-llm-adapters-as-a-design-verification-twin/consequences:
en: 71cc34560fc2e012
zh: 91ea73e3e009a9a5
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-06-14-session-persistence.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-14-session-persistence.md
2026-06-14-session-persistence.md: d79975e1fedb6efcd0e4ea83bc799bb158082e41
2026-06-14-session-persistence.zh.md: f70b8005a254cc6a9ea8ada31c32e5552ee0c8b2
/agent-note-session-persistence-as-an-abstract-service-over-the-existing-sessionevent:
en: d7cf18702f4ed830
zh: 7e0cc6db7c90a7bd
/agent-note-session-persistence-as-an-abstract-service-over-the-existing-sessionevent/problem:
en: fa1ffb258aee90f6
zh: c25cead52e72f97d
/agent-note-session-persistence-as-an-abstract-service-over-the-existing-sessionevent/decision:
en: a7076073971de601
zh: 5ea9a87705340d91
/agent-note-session-persistence-as-an-abstract-service-over-the-existing-sessionevent/alternatives-considered:
en: e5c9929ca92cc12e
zh: 3e0668f6a822577c
/agent-note-session-persistence-as-an-abstract-service-over-the-existing-sessionevent/consequences:
en: 4f00ed0b90442440
zh: 994a5b03c862178b
@@ -1,6 +1,37 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-06-18-session-surface.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-18-session-surface.md
2026-06-18-session-surface.md: 26780d54a1ea12283900572c6fd0e8f740de5524
2026-06-18-session-surface.zh.md: 328a9ee9f1bed9c52996cfd307549a7745e16d4b
/agent-note-session-surface-an-ordered-projection-over-the-event-log:
en: 9ea7a8765e7f3259
zh: 17e0d51645f01edd
/agent-note-session-surface-an-ordered-projection-over-the-event-log/problem:
en: 4f7a9d20d71a6ab3
zh: 958abbdfefec4f21
/agent-note-session-surface-an-ordered-projection-over-the-event-log/decision:
en: a9944b568ec51fad
zh: 6717d30db31b81d7
/agent-note-session-surface-an-ordered-projection-over-the-event-log/decision/top-level-surface-metadata-on-sessionevent:
en: 788fc16ecdedc252
zh: 14d05c2a1272de5d
/agent-note-session-surface-an-ordered-projection-over-the-event-log/decision/surfaceop-two-operations:
en: ff075eec0881094a
zh: 1f7768f28b8996d5
/agent-note-session-surface-an-ordered-projection-over-the-event-log/decision/surfacemanager-delta-based-not-full-rebuild:
en: 0b10fd9c5166d17b
zh: 02de01f70c03f70e
/agent-note-session-surface-an-ordered-projection-over-the-event-log/decision/persistence:
en: 9bb1f81b86b24760
zh: fe4948645dd0c66d
/agent-note-session-surface-an-ordered-projection-over-the-event-log/decision/crash-recovery:
en: ee71f9c0f12b6a0e
zh: 403b1723f808391d
/agent-note-session-surface-an-ordered-projection-over-the-event-log/decision/invariants:
en: 24b1342fb3b5be29
zh: a62692b0250c072a
/agent-note-session-surface-an-ordered-projection-over-the-event-log/alternatives-considered:
en: 193157129e65e487
zh: a0a73b8a9cbd78e6
/agent-note-session-surface-an-ordered-projection-over-the-event-log/consequences:
en: 801b67f8da564a22
zh: 3c0433ed07083050
@@ -1,6 +1,58 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-06-20-generic-long-running-tool-runtime.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.md
2026-06-20-generic-long-running-tool-runtime.md: c386d3b338c94e0e5bbf8e99c2c7a30971ba92b7
2026-06-20-generic-long-running-tool-runtime.zh.md: 002514740a15c5961960d20976fc18f7fd8071ff
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools:
en: 56e269b2a2839796
zh: 8fc971036985ac0d
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/problem:
en: 70e26df62568c337
zh: a9e6f5f8a5482d0a
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/decision:
en: 277869395ad6f792
zh: 93f13a97d52f10a5
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/runtime-contract:
en: eeb7ed8eec13668a
zh: 3f236f63c72fbba7
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/authorization-and-owner-lifecycle:
en: 3819a73ca70ecdfd
zh: c1a4f461a4e45978
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/service-api:
en: a1a884816aac3d7f
zh: b21129e5cd93b9a1
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/model-facing-control-api:
en: dd3f4d85d0ec136f
zh: ca4209cb856271dd
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/producer-opt-in:
en: a39343bf6f655051
zh: d9894d39e7f4d6e1
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/producer-integrations:
en: ae4a6d6e0d83d3bd
zh: 9072890ba9374426
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/alternatives-considered:
en: 6119e2aff3b6be5a
zh: e01a6c669a9ec6aa
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/alternatives-considered/per-capability-control-tools:
en: 9781c302dc72fd8e
zh: a78e1dd8da4d8ca8
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/alternatives-considered/an-immediate-abstract-task-runtime-backend:
en: 404a5c7c45a71a55
zh: 213621e4a9618a9c
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/alternatives-considered/consumer-owned-authorization-or-cleanup-events:
en: d99de803718d9ca6
zh: e03a97314851ed0f
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/alternatives-considered/blocking-output-or-a-separate-wait-tool:
en: e3beca50b6a57ce0
zh: a77663b817d33247
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/alternatives-considered/runtime-owned-output-sinks:
en: 42eeeba9d84ae681
zh: 1d540f9740675bee
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/alternatives-considered/random-ids-promotion-or-lifecycle-session-events:
en: e706b1b57241d3d2
zh: 1779b7fa05f48283
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/testing:
en: e891db1723828da8
zh: 657a62ed595bd081
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/consequences:
en: b95ecd6052465ad3
zh: 1527c38d1b4631d6
@@ -27,7 +27,7 @@ The literal types live on the [tasks subsystem page](../../../../docs/subsystems
The process-local provider also owns bounded admission, whose rationale is recorded in the [bounded background job admission decision](../../archived/bug-fix/2026-08-11-bounded-background-job-admission.md). Its positive-safe-integer `maxConcurrentJobsPerOwner` config defaults to `10`; `start()` derives each exact `Agent` object's active count from `running` and `stopping` records, while every unowned task shares one service bucket. Capacity rejection occurs before `run()` and id allocation, and producer `done` settlement is the only event that releases a stopping task's place. The provider does not queue, preempt, or retain a second mutable count.
`outputLimitBytes` is producer-owned presentation policy, not a registry buffer. The registry validates and projects it unchanged into `JobSnapshot`; generic control APIs apply the cap to complete model-facing output after adding their own status or notice metadata. Omitting it preserves the existing controller behavior, so the runtime does not impose a hidden default on unrelated producer families.
`outputLimitBytes` is producer-owned presentation policy, not a registry buffer. The registry validates and projects it unchanged into `JobView`; generic control APIs apply the cap to complete model-facing output after adding their own status or notice metadata. Omitting it preserves the existing controller behavior, so the runtime does not impose a hidden default on unrelated producer families.
A model-facing producer exposes that committed id in its canonical success value, normally `{ kind: 'background', jobId }`; Native rendering may keep human-readable prose. A pre-aborted background call fails rather than returning a no-op because no task exists to satisfy the promised handle. Once registration publishes the id, cancellation belongs to the task's own controller and the job runtime: later cancellation of the producing tool call must not kill the published task. `job_kill`, owner disposal, and service teardown request cancellation; foreground execution remains coupled to the call's `exec.signal`.
@@ -62,7 +62,7 @@ For contract-compliant producers, `AgentHandle.dispose()` resolves only after ow
- `read(id, caller?)` for a consuming stream delta or an idempotent final result.
- `kill(id, caller?, reason?)` for cancellation.
- `wait(id, timeoutMs, caller?, signal?)` for bounded terminal waiting.
- `onJobDone(listener)` for effect-scoped observation with exact-owner delivery and listener containment.
- `events.subscribe(filter, listener)` for effect-scoped observation of registration, progress, output, settlement, and removal, filtered by owner or owner scope, with listener containment.
- `attachController(name)` for the task-controller availability fence.
`wait` returns the terminal snapshot when the task settles or the live snapshot when its timeout expires. Aborting a wait cancels only that wait. If settlement has already assigned terminal delivery to the waiter, the terminal snapshot still wins. Waiters unregister synchronously on abort so a same-tick settlement cannot suppress a completion notice on behalf of a reader that receives nothing.
@@ -81,7 +81,7 @@ Stream reads share one task-scoped consuming cursor because the owning model is
The system prompt tells the model to retain job ids, continue independent work instead of busy-polling or duplicating a running task, collect relevant tasks before its final answer, and kill work that no longer matters. Completion delivers a logged message to the exact owner's session. A busy owner is injected; an idle owner is woken, under the bounded policy the [idle-owner wake decision](../feature/2026-08-11-background-job-completion-wakes-an-idle-owner.md) owns.
The runtime marks a terminal task `reported` when a read or wait delivers it, when a live waiter has claimed delivery at settlement, or when the model explicitly kills it. Reported tasks do not inject redundant completion notices. Listener failures are logged independently, do not stop later listeners, and are not awaited by waiters or teardown. When a snapshot carries `outputLimitBytes`, `dsh-tool-jobs` preserves UTF-8 boundaries and reuses an existing producer truncation marker rather than duplicating it. Reads reserve status suffixes and retain the output tail; completion notices reserve the stable `background job <id>` prefix and `job_output` instruction before truncating variable kind, label, status, detail, or the truncation marker itself, so the minimum PTY cap still identifies the task to collect. The job controller resolves the caller-visible producer cap in a prepended pre-execute listener before policy can deny or short-circuit dispatch, then applies it through the task definitions' last-mile `finalizeContent` callback so normalized tool errors, outer pipeline failures, and single-text policy results cannot escape the bound; deliberately structured multi-block policy results retain policy ownership of their shape and size.
`dsh-tool-jobs` keeps the delivery ledger: a wait claims the task when it starts (and withdraws if the task outlives the wait) and a `job_kill` claims it when accepted, so a settlement the model already received through a tool result injects no redundant completion notice; teardown settlements and unowned tasks are never announced ([seam consolidation](2026-09-03-jobs-seam-consolidation.md)). Listener failures are logged independently, do not stop later listeners, and are not awaited by waiters or teardown. When a view carries `outputLimitBytes`, `dsh-tool-jobs` preserves UTF-8 boundaries and reuses an existing producer truncation marker rather than duplicating it. Reads reserve status suffixes and retain the output tail; completion notices reserve the stable `background job <id>` prefix and `job_output` instruction before truncating variable kind, label, status, detail, or the truncation marker itself, so the minimum PTY cap still identifies the task to collect. The job controller resolves the caller-visible producer cap in a prepended pre-execute listener before policy can deny or short-circuit dispatch, then applies it through the task definitions' last-mile `finalizeContent` callback so normalized tool errors, outer pipeline failures, and single-text policy results cannot escape the bound; deliberately structured multi-block policy results retain policy ownership of their shape and size.
## Producer opt-in
@@ -105,7 +105,7 @@ Separate bash and subagent output/stop tools duplicate ids, isolation, cleanup,
### An immediate abstract task-runtime backend
The current `JobStart.run()` contract passes in-process callbacks and exact `Agent` objects. A durable backend changes identity, restart, ownership, and observation semantics, so at introduction time the registry stayed one concrete service rather than freezing the wrong boundary. The [task-registry contract Agent Note](../../archived/architecture/2026-07-26-job-registry-seam.md) later separated the contract from the process-local implementation without changing these in-process semantics.
The current `JobSpec.run()` contract returns in-process hooks and pushes output through an in-process `JobHandle`, and owners resolve to live `Agent`s in-process. A durable backend changes identity, restart, ownership, and observation semantics, so at introduction time the registry stayed one concrete service rather than freezing the wrong boundary. The [task-registry contract Agent Note](../../archived/architecture/2026-07-26-job-registry-seam.md) later separated the contract from the process-local implementation without changing these in-process semantics.
### Consumer-owned authorization or cleanup events
@@ -27,7 +27,7 @@ Status: implemented
进程内 Service Provider 还拥有有界准入,其理由记录在[有界后台任务准入决策](../../archived/bug-fix/2026-08-11-bounded-background-job-admission.md)中。它的 `maxConcurrentJobsPerOwner` 配置必须是正的安全整数,默认值为 `10`;`start()` 从 `running` 与 `stopping` 记录派生每个确切 `Agent` 对象的活动数量,而全部无 owner 任务共享一个服务级桶。容量拒绝发生在 `run()` 与 id 分配之前,处于 stopping 的任务只有在生产方 `done` 结算时才释放名额。Service Provider 不排队或抢占任务,也不保留第二份可变计数。
`outputLimitBytes` 是生产方拥有的呈现策略,而非注册表缓冲区。注册表校验该值,并将其原样投影到 `JobSnapshot`;通用任务控制器添加自身的状态或通知元数据后,再将该上限应用于完整的面向模型输出。省略该值时保持现有控制器行为,因此运行时不会向无关的生产方类别施加隐式默认值。
`outputLimitBytes` 是生产方拥有的呈现策略,而非注册表缓冲区。注册表校验该值,并将其原样投影到 `JobView`;通用任务控制器添加自身的状态或通知元数据后,再将该上限应用于完整的面向模型输出。省略该值时保持现有控制器行为,因此运行时不会向无关的生产方类别施加隐式默认值。
面向模型的生产方会在规范成功值中暴露已提交的 id,通常为 `{ kind: 'background', jobId }`;Native 渲染仍可保留便于人类阅读的行文。预先被中止的后台调用会失败,而不是返回空操作,因为不存在可履行所承诺句柄的任务。一旦注册过程发布 id,取消就归任务自身的控制器与任务运行时所有:随后取消生产工具调用不得终止已发布的任务。`job_kill`、所有者资源释放和服务拆除会请求取消;前台执行仍与调用的 `exec.signal` 耦合。
@@ -62,7 +62,7 @@ job id 在运行时全局可见且可预测,因此注册表会授权每次访
- `read(id, caller?)`:消费式流增量或幂等的最终结果。
- `kill(id, caller?, reason?)`:取消。
- `wait(id, timeoutMs, caller?, signal?)`:有界的终止等待。
- `onJobDone(listener)`:effect 作用域内的观察,具有精确所有者投递和监听器隔离。
- `events.subscribe(filter, listener)`:effect 作用域内对注册、进度、输出、结算与移除的观察,按所有者或所有者 scope 过滤,具有监听器隔离。
- `attachController(name)`:任务控制器可用性防线。
`wait` 在任务完成时返回终止快照,在等待超时时返回当前快照。中止一次等待只取消该次等待。如果结算已经将终止投递分配给该等待方,终止快照仍然优先。等待方在中止时同步注销,因此同一 tick 内发生结算时,不会代表一个实际未收到任何内容的读取方压制完成通知。
@@ -81,7 +81,7 @@ job id 在运行时全局可见且可预测,因此注册表会授权每次访
系统提示词要求模型保留 job id、在后台工作运行时继续处理独立工作而非忙轮询或重复启动同一任务、在给出最终答案前收集相关任务,并终止不再重要的工作。完成时,系统会向确切所有者的会话交付一条已记录的消息:繁忙的所有者走注入,空闲的所有者会被唤醒,其有界策略由[空闲所有者唤醒决策](../feature/2026-08-11-background-job-completion-wakes-an-idle-owner.zh.md)负责。
当读取或等待交付终止任务、尚在等待的等待方在结算时认领了投递,或模型显式终止任务时,运行时将终止任务标为 `reported`。已报告的任务不会注入冗余的完成通知。监听器失败会独立记录,不会阻止后续监听器,也不会被等待方或资源销毁过程等待。当快照携带 `outputLimitBytes` 时,`dsh-tool-jobs` 会保持 UTF-8 边界,并复用生产方已有的截断标记,而不会重复添加。读取会为状态后缀预留空间并保留输出尾部;完成通知会先为稳定的 `background job <id>` 前缀与 `job_output` 指令预留空间,再截断可变的 kind、label、status、detail,乃至截断标记本身,因此 PTY 的最小上限仍能标识需要收集的任务。任务控制器在策略有机会拒绝或短路分发之前,于最先执行的 pre-execute 监听器中解析调用方可见的生产方上限;随后通过任务定义最后一道的 `finalizeContent` 回调应用该上限,使规范化的工具错误、外层流水线失败与单文本策略结果都无法绕过该边界;经特意结构化的多块策略结果仍由策略拥有其形状与大小。
`dsh-tool-jobs` 持有投递台账:等待在开始时认领任务(任务比等待活得更久则撤回),`job_kill` 被接受时也认领,因此模型已经通过工具结果收到的结算不会再注入冗余的完成通知;teardown 结算与无主任务从不播报([seam 收敛](2026-09-03-jobs-seam-consolidation.zh.md))。监听器失败会独立记录,不会阻止后续监听器,也不会被等待方或资源销毁过程等待。当视图携带 `outputLimitBytes` 时,`dsh-tool-jobs` 会保持 UTF-8 边界,并复用生产方已有的截断标记,而不会重复添加。读取会为状态后缀预留空间并保留输出尾部;完成通知会先为稳定的 `background job <id>` 前缀与 `job_output` 指令预留空间,再截断可变的 kind、label、status、detail,乃至截断标记本身,因此 PTY 的最小上限仍能标识需要收集的任务。任务控制器在策略有机会拒绝或短路分发之前,于最先执行的 pre-execute 监听器中解析调用方可见的生产方上限;随后通过任务定义最后一道的 `finalizeContent` 回调应用该上限,使规范化的工具错误、外层流水线失败与单文本策略结果都无法绕过该边界;经特意结构化的多块策略结果仍由策略拥有其形状与大小。
## 生产方显式启用
@@ -105,7 +105,7 @@ bash seam 暴露 `resolve`、`run` 和 `start`。`start(spec)` 返回一个 `She
### 立即抽象任务运行时后端
当前 `JobStart.run()` 约定传入进程内回调与确切的 `Agent` 对象。持久化后端会改变身份、重启、所有权与观察语义,因此在引入之时注册表保持为单一具体服务,而非固化错误的边界。[任务注册表约定 Agent Note](../../archived/architecture/2026-07-26-job-registry-seam.md)后来在不改变这些进程内语义的前提下,将约定与进程内实现分离。
当前 `JobSpec.run()` 约定返回进程内钩子并经进程内的 `JobHandle` 推送输出,所有者也在进程内解析为存活的 `Agent`。持久化后端会改变身份、重启、所有权与观察语义,因此在引入之时注册表保持为单一具体服务,而非固化错误的边界。[任务注册表约定 Agent Note](../../archived/architecture/2026-07-26-job-registry-seam.md)后来在不改变这些进程内语义的前提下,将约定与进程内实现分离。
### 由消费方负责授权或清理事件
@@ -1,6 +1,43 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-06-21-bounded-llm-request-recovery.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-21-bounded-llm-request-recovery.md
2026-06-21-bounded-llm-request-recovery.md: b0a4ebb11b76c4c0068490c9924a88b80a8bc99f
2026-06-21-bounded-llm-request-recovery.zh.md: e8c25f9f6410dc12e34a0272e01e874431624c28
/agent-note-bounded-recovery-for-transient-llm-request-failures:
en: fb8e336ecd4bf571
zh: 23e40e4cb224163f
/agent-note-bounded-recovery-for-transient-llm-request-failures/problem:
en: 83a361538a092dae
zh: e8f33cb95d0d3e09
/agent-note-bounded-recovery-for-transient-llm-request-failures/decision:
en: a15c7c13f167e5ac
zh: 63bcc2ef60c2f344
/agent-note-bounded-recovery-for-transient-llm-request-failures/decision/preserve-failure-facts-without-embedding-policy:
en: 943322e6cdbfa440
zh: 82288531f6194ed2
/agent-note-bounded-recovery-for-transient-llm-request-failures/decision/put-retry-policy-on-the-existing-failed-step-extension-point:
en: ed4d295378d94a26
zh: 1fee5ef4947bac8f
/agent-note-bounded-recovery-for-transient-llm-request-failures/decision/make-one-layer-own-visible-attempts:
en: 57dbdd385f48bb3e
zh: 5e15463fae4be582
/agent-note-bounded-recovery-for-transient-llm-request-failures/decision/bound-stalled-streams-where-they-can-be-stopped:
en: f7369086e87192b9
zh: e2839ed8cc5c23b8
/agent-note-bounded-recovery-for-transient-llm-request-failures/decision/keep-attempts-separate-in-the-existing-log:
en: 8f57db4bfd6e1c22
zh: 67ac62217bb68570
/agent-note-bounded-recovery-for-transient-llm-request-failures/out-of-scope:
en: 985720529b56cda2
zh: 8a649bfa9cd8d93f
/agent-note-bounded-recovery-for-transient-llm-request-failures/alternatives-considered:
en: a6d0306740d470ee
zh: 700bd4b0aa58f3e8
/agent-note-bounded-recovery-for-transient-llm-request-failures/verification:
en: db343f335a9d7cad
zh: 49b8300de55dcfeb
/agent-note-bounded-recovery-for-transient-llm-request-failures/consequences:
en: 08659e8606455ada
zh: 862080f8df5f28ec
/agent-note-bounded-recovery-for-transient-llm-request-failures/related:
en: e85a6ad7387c881b
zh: bb8fb4173ffe613d
@@ -1,6 +1,25 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-06-21-mandatory-app-attribution-headers.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-21-mandatory-app-attribution-headers.md
2026-06-21-mandatory-app-attribution-headers.md: 9e0c029dc03c722512680a563c24e470128ee322
2026-06-21-mandatory-app-attribution-headers.zh.md: 1427daf8f6065ec2dee324075a8381a625d9e960
/agent-note-mandatory-user-agent-attribution-for-provider-requests:
en: 3f804e0236d13aba
zh: ef8b1b7b9c3d8376
/agent-note-mandatory-user-agent-attribution-for-provider-requests/problem:
en: f65797760084b93a
zh: d1fb36ef61a93003
/agent-note-mandatory-user-agent-attribution-for-provider-requests/investigation:
en: 5ea11f54f507ba64
zh: 22a83a0714a2fda3
/agent-note-mandatory-user-agent-attribution-for-provider-requests/decision:
en: b3e29e609e3f0966
zh: e3df0cb13df1cd5d
/agent-note-mandatory-user-agent-attribution-for-provider-requests/verification:
en: 567737dbccdb3a2a
zh: be92a5303247b889
/agent-note-mandatory-user-agent-attribution-for-provider-requests/alternatives-considered:
en: 016678c52ef64e51
zh: a113b57b9e9ddeb5
/agent-note-mandatory-user-agent-attribution-for-provider-requests/consequences:
en: a9010e68445a0008
zh: 1ec6104ab2865919
@@ -1,6 +1,76 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-06-24-web-capability-seam.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md
2026-06-24-web-capability-seam.md: 8c6c088ea5d7345f9955892b2d6054cfae518bbd
2026-06-24-web-capability-seam.zh.md: 4921c4a4647d180dbb00e6493a19d38584f99bdc
/agent-note-web-capability-seam-stable-tools-over-multiple-providers:
en: ca120635fc40431c
zh: 6be7c5ae3c86cdcc
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/problem:
en: c8b932b02a4e1c80
zh: 96c466be1a521f3f
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/decision:
en: b57eb0f268033ff1
zh: 4143382a50181414
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/package-topology:
en: 5ea3ddfae82df181
zh: 2d05d95e51081696
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/ctx-web-contract:
en: b432f80a424c3e49
zh: faa26925fdd98387
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/provider-availability-and-selection:
en: dff78c46432311a1
zh: 58d5db4c3c85b886
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/search-request-and-result-schema:
en: ec3703b7e7c6b23d
zh: 325755e6e90092da
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/fetch-request-and-result-schema:
en: f734fdc57a6546c9
zh: 027c28cbc584a8c2
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/tool-consumer-behavior:
en: 62127883453dd79c
zh: 01503a8177a0ddab
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/errors:
en: 3440f2b34b93f4a1
zh: 57a8f784c7e26eff
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/testing:
en: 7f73699ac4459432
zh: c16be49ac50c34c8
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered:
en: 6119e2aff3b6be5a
zh: 76136ef5249c23eb
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered/let-each-provider-register-its-own-model-facing-tool:
en: e0d84a9b1b9c2123
zh: 9e116a7b96751563
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered/put-provider-dispatch-directly-in-dsh-tool-web:
en: dc01d014d03b49d2
zh: b956b02f41c62682
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered/split-search-and-fetch-into-two-seams-dsh-search-dsh-fetch:
en: 3fb72ba3e554f20a
zh: aff5f0add5773388
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered/choose-the-first-registered-provider:
en: 1800706ea0f6b90b
zh: ced985b7657e2d7f
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered/treat-firecrawl-exa-tavily-parallel-extraction-as-fetch:
en: fc22e6a8bfaeaa20
zh: 64032ea6ab61b836
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered/mirror-claude-code-s-url-prompt-webfetch-shape:
en: 56a080de39e96056
zh: ae4d070aa7657503
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered/validate-dns-and-then-call-an-ordinary-fetch:
en: aa6c1e7e6374a875
zh: 045c8af6cd44c3e1
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered/block-private-looking-hostname-strings-without-pinning-resolved-addresses:
en: 3d906f3056733479
zh: d652723eb5372007
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered/require-per-call-approval-before-public-fetches:
en: f8d1fc8e9c9659cf
zh: da5792520e35cba0
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/consequences:
en: 12fd20ba54818215
zh: c1ca000b13666701
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/deferred-work:
en: 48b7b8e7310cd56b
zh: d406cd6a8a649e58
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/open-questions:
en: 63848c6ef9a6ab44
zh: 041b340802091e60
@@ -1,6 +1,43 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-06-26-file-context-as-event-gate.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-26-file-context-as-event-gate.md
2026-06-26-file-context-as-event-gate.md: 2943f11190533f84f3aebea0a25a88372d1204f1
2026-06-26-file-context-as-event-gate.zh.md: 053f4269b13c8583def01c144badd17b10a5a41a
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface:
en: 950d6bb4d83b39d8
zh: b40458972583b12b
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/problem:
en: 765a679e88ecda60
zh: fccabc8ee516ea00
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/decision:
en: eb8355d4b7a6c66b
zh: 712c6f932f26a0d3
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/the-policy-is-enforced-by-provider-cas-not-by-dsh-fs-observation-policy-stat:
en: 2edc42b8210c995b
zh: 48f4354c9ec625ee
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/provider-contract-change-the-version-guard-is-optional:
en: a282600f92568e07
zh: 3e6b2bec22c170c6
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/event-vocabulary-owned-by-dsh-fs:
en: f57494c21daf90ea
zh: 1a1f8623dc0cbef3
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/tool-contract-dsh-tool-fs:
en: c7f4457a83739520
zh: f2d55d018c7dab4f
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/policy-plugin-contract-dsh-fs-observation-policy:
en: a239deb5dde631df
zh: 68cc6c954b247596
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/bare-provider-behavior-no-dsh-fs-observation-policy:
en: 5aed537454b78157
zh: 9e8e7108be6a9537
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/supersedes:
en: 5cc21706fd0f00ad
zh: 2b51da75a95f1777
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/verification:
en: 1e3de2836160b4c2
zh: a8af173d161f0949
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/alternatives-considered:
en: 768c09662714cf25
zh: cb641e8a77a2e32c
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/consequences:
en: a1c00220fa5c6ce1
zh: 4691374274aa8df9
@@ -1,6 +1,16 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-06-30-event-domain-semantics.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-30-event-domain-semantics.md
2026-06-30-event-domain-semantics.md: 7e0aee220a62777ebe1d8f6a5018aba0f5fa20ee
2026-06-30-event-domain-semantics.zh.md: 14568c7a4660c42cecc47f094373d299380fa563
/agent-note-event-domain-semantics-session-is-the-fact-log-agent-is-the-live-event-channel:
en: e7cdaa7a6029c259
zh: ed13f8158ee0eaeb
/agent-note-event-domain-semantics-session-is-the-fact-log-agent-is-the-live-event-channel/problem:
en: 1222c2b55882b1e5
zh: f81f481f5eb9a684
/agent-note-event-domain-semantics-session-is-the-fact-log-agent-is-the-live-event-channel/decision:
en: ccc0fed9b7388112
zh: 3cc527b11affd941
/agent-note-event-domain-semantics-session-is-the-fact-log-agent-is-the-live-event-channel/consequences:
en: e0c5aa60322e67a1
zh: 7495550f0c863eda
@@ -1,6 +1,37 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-02-tool-render-intent-union.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-02-tool-render-intent-union.md
2026-07-02-tool-render-intent-union.md: 52626d3d9200146df95aee7836d37bbaf7e6a9ec
2026-07-02-tool-render-intent-union.zh.md: bc91b89c53c3c43b6c483dc0d4876a00f5a936b7
/agent-note-tagged-render-intent-union-for-tool-call-presentation:
en: 599dd6f91059580e
zh: b6a46767bb4198e6
/agent-note-tagged-render-intent-union-for-tool-call-presentation/problem:
en: 3a4b92dca651b979
zh: 6b10ce7ba3681180
/agent-note-tagged-render-intent-union-for-tool-call-presentation/decision:
en: aff6d789bde63f17
zh: 73782526b46a3ee5
/agent-note-tagged-render-intent-union-for-tool-call-presentation/decision/why-a-tagged-union-beats-the-field-bag:
en: ed7b15039050e65e
zh: a719562b5fcdbd4e
/agent-note-tagged-render-intent-union-for-tool-call-presentation/decision/producer-mapping:
en: c87f22a29caef002
zh: 7bfd28c1df80b8a1
/agent-note-tagged-render-intent-union-for-tool-call-presentation/decision/terminal-fallback-ownership:
en: 0bb2f60726afc4d9
zh: 60040141447b4a2e
/agent-note-tagged-render-intent-union-for-tool-call-presentation/decision/purity-preserved:
en: 1ba6a480967c524d
zh: 90535e843f346bcf
/agent-note-tagged-render-intent-union-for-tool-call-presentation/alternatives-considered:
en: 2cd4801f3162227b
zh: 76afaa23bc2b9eb0
/agent-note-tagged-render-intent-union-for-tool-call-presentation/consequences:
en: 81d8366d826285c2
zh: b437b862794c146e
/agent-note-tagged-render-intent-union-for-tool-call-presentation/non-goals:
en: e9d60967a9b3f9bd
zh: 6dfa9ac30d847879
/agent-note-tagged-render-intent-union-for-tool-call-presentation/related:
en: fe27f777b3728fa4
zh: 4b648dbf731ace00
@@ -1,6 +1,40 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-05-prompt-variables-and-tool-guidance-ownership.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-05-prompt-variables-and-tool-guidance-ownership.md
2026-07-05-prompt-variables-and-tool-guidance-ownership.md: 8f5542cb09930e62fd1e26960166fbdd6d3f6745
2026-07-05-prompt-variables-and-tool-guidance-ownership.zh.md: 348ae36cf6549d412adab1d3cdb5cc03f0badd01
/agent-note-prompt-variables-and-tool-guidance-ownership:
en: 6f8b4a9d26ab3e50
zh: 9741e5718e647f0a
/agent-note-prompt-variables-and-tool-guidance-ownership/problem:
en: 8ccef8fbd9260dfe
zh: 106b2bafe969c676
/agent-note-prompt-variables-and-tool-guidance-ownership/decision:
en: c551d888282d9c73
zh: 889b5ca3cdf25aff
/agent-note-prompt-variables-and-tool-guidance-ownership/decision/assemble-context:
en: 46e67248692e333a
zh: 51c5f2c6152c94d7
/agent-note-prompt-variables-and-tool-guidance-ownership/decision/prompt-variables:
en: 04b623ed2879fdf1
zh: c111be62834fda93
/agent-note-prompt-variables-and-tool-guidance-ownership/decision/persona-as-the-order-0-section:
en: c2d32c0ac5d28759
zh: 59cd252ba6da6e59
/agent-note-prompt-variables-and-tool-guidance-ownership/decision/tool-guidance-ownership:
en: 308c0d2ef4e41f56
zh: d38f84a517da20df
/agent-note-prompt-variables-and-tool-guidance-ownership/decision/the-subagent-conversation-history-descriptor:
en: 1cb9644f22918749
zh: fb9fdee133159ab2
/agent-note-prompt-variables-and-tool-guidance-ownership/alternatives-considered:
en: 9a114359d2e8988b
zh: ce39453408b2af7f
/agent-note-prompt-variables-and-tool-guidance-ownership/out-of-scope:
en: bbfecc70d0b457fe
zh: 7f207a37a86484f4
/agent-note-prompt-variables-and-tool-guidance-ownership/shipped-invariants:
en: 31ba63101fca5790
zh: af4ceefab2033142
/agent-note-prompt-variables-and-tool-guidance-ownership/consequences:
en: 993f17bf35f6a2e0
zh: acb429176f0eebcc
@@ -1,6 +1,28 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-05-reconstructable-requests.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-05-reconstructable-requests.md
2026-07-05-reconstructable-requests.md: f47d0938b91edf6c9b544223ac44925f02dd8c1f
2026-07-05-reconstructable-requests.zh.md: d2499a6264a3e6bebf31944d8eb056265e082c68
/agent-note-every-llm-request-is-reconstructable-from-the-session-log:
en: 115dd45f40b0d7d8
zh: 536b5a0399e7d06a
/agent-note-every-llm-request-is-reconstructable-from-the-session-log/problem:
en: f8f31da854a5fe2e
zh: ef88856c2c7bdfb8
/agent-note-every-llm-request-is-reconstructable-from-the-session-log/decision:
en: a15c7c13f167e5ac
zh: 63bcc2ef60c2f344
/agent-note-every-llm-request-is-reconstructable-from-the-session-log/decision/the-principle:
en: 6da15cf986d59a91
zh: 40282908b54295f9
/agent-note-every-llm-request-is-reconstructable-from-the-session-log/decision/the-mechanism:
en: 7d86e5058dbab2fb
zh: 9a97481325c8eded
/agent-note-every-llm-request-is-reconstructable-from-the-session-log/decision/the-minicode-shape-adopted-with-the-event-log-as-the-source:
en: e5f2ffaa3d7de0cc
zh: 5ba6b36787a0e189
/agent-note-every-llm-request-is-reconstructable-from-the-session-log/alternatives-considered:
en: 96f19ecf38fae991
zh: 9692252135ef3476
/agent-note-every-llm-request-is-reconstructable-from-the-session-log/consequences:
en: 0d2e97bc421e67cc
zh: 0a000a69b8cc4b4e
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-05-windows-jsonl-durable-publish.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-05-windows-jsonl-durable-publish.md
2026-07-05-windows-jsonl-durable-publish.md: 546cde6086f3c84e22b4d4de144a48bb3425cd4e
2026-07-05-windows-jsonl-durable-publish.zh.md: b99032e9d7e72e2028f39c5af91659278fd81343
/agent-note-windows-native-durable-jsonl-publication:
en: db7fe80708911f2f
zh: 42c6639defea2bde
/agent-note-windows-native-durable-jsonl-publication/problem:
en: dcc3c6238131d302
zh: 4d4e8513a4069af3
/agent-note-windows-native-durable-jsonl-publication/decision:
en: 385565b209f1e739
zh: 0eab0997c49a3c33
/agent-note-windows-native-durable-jsonl-publication/alternatives-considered:
en: 83d5bf5781f89e29
zh: 068835993789e09d
/agent-note-windows-native-durable-jsonl-publication/consequences:
en: 4be0ad03a334c257
zh: 95d473ed5b94e270
@@ -1,6 +1,28 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-06-timeout-deadline-library.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-06-timeout-deadline-library.md
2026-07-06-timeout-deadline-library.md: 6f726938731f18386105ff1180c79fef981c95bf
2026-07-06-timeout-deadline-library.zh.md: 48bd7b4b91efd0045c03e3e1e1e9e37656b4dcf6
/agent-note-a-shared-timeout-deadline-primitive-with-hard-kill-left-to-each-capability:
en: 4a9921fef5e65cc8
zh: 672cd27d68310cb1
/agent-note-a-shared-timeout-deadline-primitive-with-hard-kill-left-to-each-capability/problem:
en: 110ff68b35bd43cb
zh: f1cea15fb29a9ae9
/agent-note-a-shared-timeout-deadline-primitive-with-hard-kill-left-to-each-capability/decision:
en: 18645d82d9e40107
zh: 73e510f1ed1106e6
/agent-note-a-shared-timeout-deadline-primitive-with-hard-kill-left-to-each-capability/decision/the-library-api:
en: c62681afef60a0db
zh: 69827b4b3165b3da
/agent-note-a-shared-timeout-deadline-primitive-with-hard-kill-left-to-each-capability/decision/the-division-of-labor:
en: 263c8e17bbc87ba0
zh: d75a74f47713e79f
/agent-note-a-shared-timeout-deadline-primitive-with-hard-kill-left-to-each-capability/decision/how-each-capability-consumes-it:
en: 333eab4967d753ec
zh: dd7537bb82cc717f
/agent-note-a-shared-timeout-deadline-primitive-with-hard-kill-left-to-each-capability/consequences:
en: 832f4dbd93a47f94
zh: 65ada43f9f23a39b
/agent-note-a-shared-timeout-deadline-primitive-with-hard-kill-left-to-each-capability/alternatives-considered:
en: 7b3445622becbd36
zh: bb358acf2ff28e26
@@ -1,6 +1,28 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-07-tool-call-timeout-policy.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-07-tool-call-timeout-policy.md
2026-07-07-tool-call-timeout-policy.md: 60d82c1d591f0a32350b1a21ed74e148c4c93576
2026-07-07-tool-call-timeout-policy.zh.md: 49ca7f397d15c1a351cba4837d4d531e54120ea6
/agent-note-tool-call-timeout-policy-as-a-plugin:
en: 46fa7d1eac4fe061
zh: 7a62f8f7b1c66722
/agent-note-tool-call-timeout-policy-as-a-plugin/problem:
en: b5fffa80b58fb184
zh: aadf28f95924b1ad
/agent-note-tool-call-timeout-policy-as-a-plugin/decision:
en: 04889f664ab7657d
zh: 2af5913f5e9c1927
/agent-note-tool-call-timeout-policy-as-a-plugin/decision/the-tools-execute-around-dispatch-extension-point:
en: 8c3b46fa8a48a863
zh: 662eb09bb7542be8
/agent-note-tool-call-timeout-policy-as-a-plugin/decision/the-timeout-policy-plugin:
en: 96f5932514a33e41
zh: 5951d9451ccef1bf
/agent-note-tool-call-timeout-policy-as-a-plugin/decision/existing-tool-adaptation:
en: 43add9b1f723ce89
zh: f3ee56f97faa2e60
/agent-note-tool-call-timeout-policy-as-a-plugin/alternatives-considered:
en: dc6da8743b4266fb
zh: 5c28667d952b230a
/agent-note-tool-call-timeout-policy-as-a-plugin/consequences:
en: f7429a5c1fe6b6a1
zh: 748401be79f89b05
@@ -1,6 +1,46 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-08-agent-scope-contexts.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-08-agent-scope-contexts.md
2026-07-08-agent-scope-contexts.md: 45e635b7bc3138d4e90a25a06ff23b3b57a9415e
2026-07-08-agent-scope-contexts.zh.md: aac860734e744843c3b9e7d55e5bc7a150763090
/agent-note-the-agent-is-a-registration-scope:
en: f767894b8308f1a0
zh: 4ff0aead6ee4e27b
/agent-note-the-agent-is-a-registration-scope/problem:
en: 87634b46a5642328
zh: 2adce8b041626437
/agent-note-the-agent-is-a-registration-scope/decision:
en: ac58e62f780b0879
zh: 6b077226de04a8fa
/agent-note-the-agent-is-a-registration-scope/decision/registration-origin-chooses-visibility-and-cleanup:
en: 1ec8e54543272e1b
zh: b5b1695a805574a2
/agent-note-the-agent-is-a-registration-scope/decision/the-operation-chooses-the-view:
en: 2e236d399efdc0b2
zh: 00a7ba20f90862c6
/agent-note-the-agent-is-a-registration-scope/decision/scoped-events-keep-routing-separate-from-event-data:
en: df5f5e4c1de44474
zh: d851c02959d02380
/agent-note-the-agent-is-a-registration-scope/decision/creation-publishes-last-and-disposal-revokes-last:
en: f46920b4945e0e6d
zh: 870a157205883144
/agent-note-the-agent-is-a-registration-scope/security-and-authority-are-non-goals:
en: 5ffc5a8f65ce7dfe
zh: 3362f236356a8033
/agent-note-the-agent-is-a-registration-scope/alternatives-considered:
en: bf43310538280f62
zh: e4940ff47c5d47b5
/agent-note-the-agent-is-a-registration-scope/alternatives-considered/pass-an-agent-option-to-every-registration:
en: 37e7487b1f1eb87a
zh: eeddbaf21eee7ebc
/agent-note-the-agent-is-a-registration-scope/alternatives-considered/filter-events-while-keeping-registries-global:
en: 7eb2628d51ea9ed0
zh: e58f05faf0e95712
/agent-note-the-agent-is-a-registration-scope/alternatives-considered/create-one-service-graph-per-agent:
en: 2fd1c41c3d1bc6ca
zh: cffad44a2c69330e
/agent-note-the-agent-is-a-registration-scope/alternatives-considered/inherit-parent-registration-scopes:
en: 01f989446aab1cf1
zh: 8f5c9018b7b84c94
/agent-note-the-agent-is-a-registration-scope/consequences:
en: 65c8f47d1607b276
zh: 950b86b4682f7a0e
@@ -1,6 +1,40 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-08-tool-output-spill-files.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-08-tool-output-spill-files.md
2026-07-08-tool-output-spill-files.md: fa6697aad63c97b0ef580fe1ca46e50541e3d682
2026-07-08-tool-output-spill-files.zh.md: a995eafc7878b342a2164c5116da1f43ada791a5
/agent-note-tool-output-spill-policy:
en: 06b99197145a4080
zh: 698a61dcd2385985
/agent-note-tool-output-spill-policy/problem:
en: 858cbb874e213697
zh: 1693b618886ac42d
/agent-note-tool-output-spill-policy/decision:
en: 89536b0d2d7b4c92
zh: 341240f445885549
/agent-note-tool-output-spill-policy/decision/spill-seam:
en: 1e92bc9a0548def9
zh: c99cf6878981ba71
/agent-note-tool-output-spill-policy/decision/spill-policy:
en: 3c49c0246188c513
zh: 4b6749c30726903d
/agent-note-tool-output-spill-policy/showcase-web-fetch:
en: d5c334b50f458925
zh: 7631307b5d9fbc55
/agent-note-tool-output-spill-policy/relationship-to-retention-and-early-spill:
en: 7314ba8b0a03c0d9
zh: 8429f79ff3a7bd1f
/agent-note-tool-output-spill-policy/non-goals:
en: f82b5399ecddd8a1
zh: 9675b58631bb5c90
/agent-note-tool-output-spill-policy/deferred:
en: 094f8c71672ea726
zh: 252dbe825d6e34ca
/agent-note-tool-output-spill-policy/testing:
en: c98759345e1aebfa
zh: d1faeadb99bd748a
/agent-note-tool-output-spill-policy/consequences:
en: e023260e52a246d6
zh: 2e49237e564a83da
/agent-note-tool-output-spill-policy/alternatives-considered:
en: d53fb144141de557
zh: 1b851eb64c421803
@@ -66,36 +66,7 @@ interface SpillRef {
### Spill policy
`dsh-spill-policy` is a `tools/post-execute` result transformer with one configuration knob:
```ts ignore-check
interface Config {
/** Omitted means no automatic spill policy. Present means apply to oversized plain text tool results. */
maxInlineBytes?: number
}
```
When `maxInlineBytes` is omitted the plugin registers nothing (a true no-op). When set, it applies a default policy to final plain-text tool results:
1. Let the tool run normally, delegating via `next()` so a downstream listener settles the result first.
2. Flatten the accepted final `ContentBlock[]` only when it is entirely plain text; a result with any non-text block is left untouched.
3. If its UTF-8 byte size is at or below `maxInlineBytes`, leave it unchanged.
4. If it is larger, call `ctx.spillStore.saveText()` with the full final text.
5. Replace the model-facing result with a retained head/tail preview plus the spill reference.
The preview is an implementation default owned by the policy: a head/tail split of `maxInlineBytes` via the retention library's `TextRetainer`. Future config can expose preview sizing only after a second deployment needs it.
The replacement text is intentionally generic because the policy only knows the final formatted tool result, not the tool's internal resource:
```text
<retained preview>
(Omitted N bytes. Full formatted result stored at: /.../session-.../....txt. Use read with offset/limit, or grep this path to search within it.)
```
If `ctx.spillStore.saveText()` fails (permissions, ENOSPC, backend unavailable), or the call has no session owner, or no backend is loaded, the plugin logs the reason and returns the original result unchanged. Spill failure never turns a successful tool call into an `isError` result or hides the inline result.
The policy skips `read` to avoid a circular `read -> spill file -> read again` loop. Additional opt-out configuration is deferred until a real second tool needs it.
`dsh-spill-policy` retains ordered text/image ends under `maxInlineTokens` after post-execute policy accepts the result. `saveText()` stores the complete result with readable image paths; image bytes remain in attachment storage. The [multimodal retention decision](../../implemented/bug-fix/2026-09-21-multimodal-tool-result-retention.md) owns image projection order, atomic image omission, and route pricing. An omitted budget installs no listeners, recovery failures keep the original result, and model-facing `read` results skip retention to avoid a read/spill loop.
## Showcase: web_fetch
@@ -129,7 +100,7 @@ With `dsh-spill-policy` configured, a large formatted fetch result is automatica
- id: spill-policy
name: '@deepseek-ai/dsh-spill-policy'
config:
maxInlineBytes: 50000
maxInlineTokens: 12500
```
This separation is important. `web-fetch-http` still owns resource caps (`maxResponseBytes`, `maxBodyChars`) to protect network, memory, and decoding work. `spill-policy` owns only the model-facing context cap after the result already exists. If the provider already returned `truncated: true`, the spill file contains the full formatted result the tool returned, not the full original webpage; the policy does not claim otherwise.
@@ -186,11 +157,11 @@ The local-backend value proposition depends on the existing `read`/`grep` tools
**Snapshot gap.** No ACP snapshot scenario covers the transcript-visible `web_fetch` spill notice yet. The ACP snapshot harness replays keyless and cannot hit the live web, and a `web_fetch` spill requires a real over-cap HTTP body; a deterministic scenario would need a seeded loopback fetch target the replay tree does not currently wire (the examples do not load `tool-web` at all). The behavior is covered instead by the `dsh-tool-web` integration test against a loopback server. Closing the gap is follow-up work: wire `tool-web` + a seeded fetch target into the ACP example, then record a `web-fetch-spill` scenario.
The policy can become too large if it starts owning tool-specific semantics. It stays narrow: plain-text final results only. Tool-owned early spill remains future work.
The policy can become too large if it starts owning tool-specific semantics. It handles accepted text/image sequences without interpreting tool-specific text. Tool-owned early spill remains future work.
## Alternatives considered
**Require each tool to opt in with a retention declaration.** Rejected: the goal is a default behavior similar to Claude Code's generic tool-result persistence. A single `maxInlineBytes` deployment knob is enough to prove the shape.
**Require each tool to opt in with a retention declaration.** Rejected: the goal is a default behavior similar to Claude Code's generic tool-result persistence. A single `maxInlineTokens` deployment knob is enough to prove the shape.
**Make `tool-results` a broad tool-result platform.** Rejected: a broad package name invites retention policy, result replacement, preview wording, search, and early spill into one seam. The shared storage part is smaller: save text and return a locator plus retrieval hint.
@@ -66,36 +66,7 @@ interface SpillRef {
### spill 策略
`dsh-spill-policy` 是一个 `tools/post-execute` 结果转换器,只提供一个配置项:
```ts ignore-check
interface Config {
/** Omitted means no automatic spill policy. Present means apply to oversized plain text tool results. */
maxInlineBytes?: number
}
```
省略 `maxInlineBytes` 时,插件不会注册任何内容,是真正的无操作。设置该值后,它会对最终的纯文本工具结果应用默认策略:
1. 让工具正常运行,通过 `next()` 委托,使下游监听器先结算结果。
2. 仅当已接受的最终 `ContentBlock[]` 全部是纯文本时,才将其展平;含任何非文本块的结果保持不变。
3. 如果 UTF-8 字节大小不超过 `maxInlineBytes`,保持不变。
4. 如果超出上限,使用完整的最终文本调用 `ctx.spillStore.saveText()`。
5. 把模型可见结果替换为保留的首尾预览和 spill 引用。
预览属于策略所有的实现默认值:以 `maxInlineBytes` 为上限,使用保留库的 `TextRetainer` 进行首尾分割。只有第二个部署证明有此需求后,未来配置才会公开预览大小。
替换文本刻意保持通用,因为策略只知道最终格式化的工具结果,不了解工具的内部资源:
```text
<retained preview>
(Omitted N bytes. Full formatted result stored at: /.../session-.../....txt. Use read with offset/limit, or grep this path to search within it.)
```
如果 `ctx.spillStore.saveText()` 失败(权限、ENOSPC、后端不可用),或调用没有会话所有者,或未加载后端,插件会记录原因并原样返回结果。spill 失败绝不会把成功的工具调用变为 `isError` 结果,也不会隐藏内联结果。
策略跳过 `read`,以避免形成 `read -> spill file -> read again` 循环。额外的选择退出配置要等确实出现第二个有此需求的工具后再引入。
`dsh-spill-policy` 在执行后策略接受结果之后,按 `maxInlineTokens` 对文字和图片共同计量并保留首尾。完整结果仍通过 `saveText()` 保存,图片本体留在附件存储,结果文件记录可读取路径。图片投影顺序、整图省略和模型计量由[图文结果保留决策](../../implemented/bug-fix/2026-09-21-multimodal-tool-result-retention.zh.md)负责。省略配置时不安装监听器,存储失败时保留原结果;`read` 的模型可见结果跳过自动省略,避免重复读取产生循环。
## 示例:web_fetch
@@ -129,7 +100,7 @@ ctx.tools.register(defineTool({
- id: spill-policy
name: '@deepseek-ai/dsh-spill-policy'
config:
maxInlineBytes: 50000
maxInlineTokens: 12500
```
这项分离很重要。`web-fetch-http` 仍负责资源上限(`maxResponseBytes`、`maxBodyChars`),用来保护网络、内存和解码工作。`spill-policy` 只负责结果已经存在后针对模型上下文的上限。如果提供方已经返回 `truncated: true`,spill 文件包含的是工具返回的完整格式化结果,而不是原始网页全文;策略不会做出其他承诺。
@@ -186,11 +157,11 @@ ctx.tools.register(defineTool({
**快照缺口。** 目前没有 ACP 快照场景覆盖 transcript(文本记录)可见的 `web_fetch` spill 提示。ACP 快照 harness 在无密钥环境中回放,无法访问实时 web,而 `web_fetch` spill 需要一个真实的超上限 HTTP 正文;确定性场景需要一个预置的 loopback fetch 目标,但当前回放树尚未接线(示例根本没有加载 `tool-web`)。该行为改由 `dsh-tool-web` 针对 loopback server 的集成测试覆盖。弥补该缺口属于后续工作:把 `tool-web` 和预置 fetch 目标接入 ACP 示例,然后录制 `web-fetch-spill` 场景。
如果策略开始负责工具专用语义,就会膨胀得过大。它的范围保持狭窄:只处理纯文本最终结果。由工具负责的提前 spill 仍留作未来工作。
如果策略开始负责工具专用语义,就会膨胀得过大。它处理已接受的图文序列,不解释工具专用的文字语义。由工具负责的提前 spill 仍留作未来工作。
## 考虑过的替代方案
**要求每个工具通过保留声明选择加入。**不予采纳,因为目标是实现类似 Claude Code 通用工具结果持久化的默认行为。只需一个 `maxInlineBytes` 部署配置项即可验证该形态。
**要求每个工具通过保留声明选择加入。**不予采纳,因为目标是实现类似 Claude Code 通用工具结果持久化的默认行为。只需一个 `maxInlineTokens` 部署配置项即可验证该形态。
**把 `tool-results` 建成宽泛的工具结果平台。** 不予采纳:宽泛的包名会诱使系统把保留策略、结果替换、预览措辞、搜索和提前 spill 合并进一个 seam。可共享的存储部分更小:保存文本,并返回定位符与检索提示。
@@ -1,6 +1,31 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-10-after-call-compaction-pressure-and-overflow-recovery.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-10-after-call-compaction-pressure-and-overflow-recovery.md
2026-07-10-after-call-compaction-pressure-and-overflow-recovery.md: 89c8917484c11057ff2e6b55e2311e83f724f7ed
2026-07-10-after-call-compaction-pressure-and-overflow-recovery.zh.md: 48f954f2c4720894548ecab387965d3a3d1799b0
/agent-note-after-call-compaction-pressure-and-context-overflow-recovery:
en: 8bfe0d8b79d9840f
zh: 6921dc88e5ef9c83
/agent-note-after-call-compaction-pressure-and-context-overflow-recovery/problem:
en: 036da3e545debe29
zh: 82e031a3120ca36c
/agent-note-after-call-compaction-pressure-and-context-overflow-recovery/decision:
en: a15c7c13f167e5ac
zh: 63bcc2ef60c2f344
/agent-note-after-call-compaction-pressure-and-context-overflow-recovery/decision/successful-pressure-runs-at-the-next-pre-step-boundary:
en: 5f5a656b38730ec6
zh: aece66b85cc610cf
/agent-note-after-call-compaction-pressure-and-context-overflow-recovery/decision/request-recovery-is-limited-to-the-final-model-boundary:
en: fb7da851bf6a020e
zh: b40dc932d6c3101c
/agent-note-after-call-compaction-pressure-and-context-overflow-recovery/decision/compactionengine-exposes-intent-not-token-accounting:
en: be9505b3d73c7f6b
zh: ed753f1afec2787a
/agent-note-after-call-compaction-pressure-and-context-overflow-recovery/testing:
en: b0e1704bd3724301
zh: 2279353ff615f183
/agent-note-after-call-compaction-pressure-and-context-overflow-recovery/alternatives-considered:
en: 3cb5363732ef5758
zh: 07746411cc80878f
/agent-note-after-call-compaction-pressure-and-context-overflow-recovery/consequences:
en: dfe515fb04127eb5
zh: 1924b2e1e9997910
@@ -1,6 +1,43 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-10-single-file-executable-sdk-runtime-distribution.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.md
2026-07-10-single-file-executable-sdk-runtime-distribution.md: ff00327c388b0468e5e98d488141aa35eb40d104
2026-07-10-single-file-executable-sdk-runtime-distribution.zh.md: 3f7f18a9907b2f43f7cd8467f054f0d0bfcef14a
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe:
en: 00b5d91d3e44a9f8
zh: eabd3c4b338249b3
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/problem:
en: 112178b76e5209f6
zh: 68726254ae530566
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/decision:
en: a15c7c13f167e5ac
zh: 63bcc2ef60c2f344
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/decision/packaging-route-yao-pkg-pkg-s-sea-mode:
en: f1c2b60e9474111d
zh: 5de398b5e8554429
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/decision/the-serving-interface-is-a-plugin-inside-the-dsh-application:
en: 5fdde26e9e8c6108
zh: 629559d733c1f0c5
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/decision/plugin-resolution-the-vfs-holds-a-real-package-tree-the-closure-manifest-is-the-deploy-root:
en: c35ea4b858448b49
zh: 1f8ff0a9f82ca881
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/decision/build-pipeline-and-artifacts:
en: 53ba44431d2ce411
zh: 4159475549273422
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/decision/python-sdk-distribution-two-carriers-exe-for-production-node-for-development:
en: 9bd60549d4a52ec0
zh: e2343b7210212ee0
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/decision/naming-lineage:
en: 31a5aecb8bf828bb
zh: 2dffb6fd2e0f8194
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/packaged-workflow-and-code-execution:
en: 0426f598f3f44e64
zh: fc66728e17f3bcfb
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/testing:
en: b3c9820f4dc7c6c8
zh: 3b5768ef1770bfcb
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/alternatives-considered:
en: 50d965ca81a401ba
zh: 0c6296245b97b9ac
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/consequences:
en: 601a72b3a7a91fe4
zh: 5baaa866e789923e
@@ -40,7 +40,7 @@ The Python client supplies an explicit Harness home and selects the `sdk` profil
Inside the exe's VFS sits a **real package tree in build-artifact form** (each package's `lib/` plus a real `node_modules`). The packaged JSON-RPC entry supplies its installed harness base to app-boot's root Include: relative plugin specifiers resolve from the external configuration directory, while bare package names resolve from the VFS, so a configuration inside another Node project cannot shadow the packaged plugin set. The ordinary development bin leaves bare packages configuration-owned. Bare specifiers in the packaged entry resolve upward along `node_modules` from the entry's position inside the VFS and land inside the VFS naturally. The closed set needs no allowlist code — the set is whatever the VFS has installed, and importing a name outside the set fails.
The deploy root is [`python/sdk-runtime/package.json`](../../../../python/sdk-runtime/package.json) (`dsh-python-runtime-closure`, a pnpm workspace member and a zero-code pure dependency manifest) — the unified source of truth for "which plugins the exe ships" and "what the Python runtime distributes". Adding a plugin to the exe = adding one dependency line to the manifest and repackaging. [`scripts/verify-runtime-closure.ts`](../../../../scripts/verify-runtime-closure.ts) reads every shipped `packages/preset/agent-presets/presets/*/agent.cordis.yml`, evaluates `disabled` conditions that compare `process.platform` for every target in `python/sdk-runtime/platforms.json`, and requires each active workspace plugin at the runtime root through an explicit `workspace:` dependency. It also traverses every workspace package covered by that manifest and requires every non-optional workspace peer, reporting the complete preset or referencing-package → missing-dependency chain; unknown platform conditions remain active so a plugin cannot be omitted by an unsupported expression. `pnpm run hygiene`, CI static, and the single-exe build run it before packaging. Deploy also packs by each package's `files`, so the shared chunks tsdown splits out must be covered by `files`.
The deploy root is [`python/sdk-runtime/package.json`](../../../../python/sdk-runtime/package.json) (`dsh-python-runtime-closure`, a pnpm workspace member and a zero-code pure dependency manifest) — the unified source of truth for "which plugins the exe ships" and "what the Python runtime distributes". Adding a plugin to the exe = adding one dependency line to the manifest and repackaging. [`scripts/verify-runtime-closure.ts`](../../../../scripts/verify-runtime-closure.ts) reads every shipped `packages/bundle/web-app/cordis.patch.yml*/agent.cordis.yml`, evaluates `disabled` conditions that compare `process.platform` for every target in `python/sdk-runtime/platforms.json`, and requires each active workspace plugin at the runtime root through an explicit `workspace:` dependency. It also traverses every workspace package covered by that manifest and requires every non-optional workspace peer, reporting the complete preset or referencing-package → missing-dependency chain; unknown platform conditions remain active so a plugin cannot be omitted by an unsupported expression. `pnpm run hygiene`, CI static, and the single-exe build run it before packaging. Deploy also packs by each package's `files`, so the shared chunks tsdown splits out must be covered by `files`.
The deploy root includes `@deepseek-ai/dsh-mcp-client` as an explicitly supported custom-configuration plugin even though no shipped preset mounts it. An external config can therefore connect to user-supplied stdio and Streamable HTTP MCP servers and register their tools; the distribution does not carry those servers. The optional resource service provides MCP Resources; MCP Prompts remain unsupported. The executable and installed-wheel smokes start a temporary stdio server, discover its tool, and complete one model-requested call.
@@ -40,7 +40,7 @@ Python 客户端提供显式 Harness home,并选择 `sdk` profile 与有序 pa
exe 的 VFS 内是**构建产物形态的真实包树**(各包的 `lib/` + 真实 `node_modules`)。打包专用 JSON-RPC 入口会向 app-boot 的根 Include 提供自身已安装 harness 的基准位置:相对插件说明符从外部配置目录解析,裸包名则从 VFS 解析,因此位于另一个 Node 项目内的配置无法遮蔽已打包的插件集合。普通开发 bin 仍由配置项目提供裸包。打包入口中的裸包名从该入口在 VFS 内的位置沿 `node_modules` 向上解析,自然落在 VFS 内。封闭集不需要白名单代码——VFS 中安装了什么,集合中就有什么;`import()` 集合外的名称会失败。
部署根目录是 [`python/sdk-runtime/package.json`](../../../../python/sdk-runtime/package.json)(`dsh-python-runtime-closure`,pnpm 工作区成员、零代码纯依赖 manifest),也是「exe 安装哪些插件」与「Python 运行时分发什么」的统一真源。向 exe 添加插件,就是在 manifest 中增加一行依赖后重新打包。[`scripts/verify-runtime-closure.ts`](../../../../scripts/verify-runtime-closure.ts) 读取每个已发布的 `packages/preset/agent-presets/presets/*/agent.cordis.yml`,针对 `python/sdk-runtime/platforms.json` 中的每个目标解析比较 `process.platform` 的 `disabled` 条件,并要求该目标启用的每个工作区插件都通过显式的 `workspace:` 依赖列在运行时根目录。它还遍历该 manifest 覆盖的全部工作区包,要求每个非可选的工作区对等依赖(peer dependency)都显式列出,并报告“preset 或引用包 → 缺失依赖”的完整链路;无法识别的平台条件会保持启用,避免因不支持的表达式遗漏插件。`pnpm run hygiene`、CI 静态检查与 single-exe 构建都会在打包前运行该门禁。部署还会依据各包的 `files` 字段打包,因此 tsdown 拆出的共享分片必须被 `files` 覆盖。
部署根目录是 [`python/sdk-runtime/package.json`](../../../../python/sdk-runtime/package.json)(`dsh-python-runtime-closure`,pnpm 工作区成员、零代码纯依赖 manifest),也是「exe 安装哪些插件」与「Python 运行时分发什么」的统一真源。向 exe 添加插件,就是在 manifest 中增加一行依赖后重新打包。[`scripts/verify-runtime-closure.ts`](../../../../scripts/verify-runtime-closure.ts) 读取每个已发布的 `packages/bundle/web-app/cordis.patch.yml*/agent.cordis.yml`,针对 `python/sdk-runtime/platforms.json` 中的每个目标解析比较 `process.platform` 的 `disabled` 条件,并要求该目标启用的每个工作区插件都通过显式的 `workspace:` 依赖列在运行时根目录。它还遍历该 manifest 覆盖的全部工作区包,要求每个非可选的工作区对等依赖(peer dependency)都显式列出,并报告“preset 或引用包 → 缺失依赖”的完整链路;无法识别的平台条件会保持启用,避免因不支持的表达式遗漏插件。`pnpm run hygiene`、CI 静态检查与 single-exe 构建都会在打包前运行该门禁。部署还会依据各包的 `files` 字段打包,因此 tsdown 拆出的共享分片必须被 `files` 覆盖。
部署根目录显式包含 `@deepseek-ai/dsh-mcp-client`,将其作为自定义配置可用的插件,即使随附 preset 均未挂载该插件。外部配置因此可以连接由用户提供的 stdio 与 Streamable HTTP MCP server 并注册其工具;分发物不包含这些 server。可选资源服务提供 MCP Resources;MCP Prompts 仍不受支持。可执行程序与已安装 wheel 包的冒烟测试会启动临时 stdio server,发现其工具,并完成一次由模型请求的调用。
@@ -1,6 +1,157 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-12-agent-scope-runtime-design.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-12-agent-scope-runtime-design.md
2026-07-12-agent-scope-runtime-design.md: b9b2c837f560c2b8b98da37e3656caf298b705e2
2026-07-12-agent-scope-runtime-design.zh.md: 4b94d1b8449bd619c47f6bee0712ec8ed0b39593
/agent-note-agent-scope-runtime-design-and-correctness:
en: b63ecbd21fc1f427
zh: 4990d96d76888802
/agent-note-agent-scope-runtime-design-and-correctness/problem:
en: ae7b688bd991a6df
zh: 73b6b28755852054
/agent-note-agent-scope-runtime-design-and-correctness/decision:
en: cfd6abca8404c7d4
zh: a9372aae85e49f55
/agent-note-agent-scope-runtime-design-and-correctness/cordis-model-context-fiber-effect-receiver-and-waterfall:
en: 4d4bdb629a57139d
zh: 7b4d21d9eb42d94b
/agent-note-agent-scope-runtime-design-and-correctness/cordis-model-context-fiber-effect-receiver-and-waterfall/a-context-is-an-ownership-path-through-one-service-graph:
en: 201a1882518455e2
zh: 830e25eab7ed37db
/agent-note-agent-scope-runtime-design-and-correctness/cordis-model-context-fiber-effect-receiver-and-waterfall/fibers-and-effects-make-cleanup-structural:
en: d0ef6e1b5d453350
zh: 4a774ac9daf20849
/agent-note-agent-scope-runtime-design-and-correctness/cordis-model-context-fiber-effect-receiver-and-waterfall/receivers-route-listeners-waterfalls-compose-decisions:
en: 594e198a8b566049
zh: 50378e7a2a533dff
/agent-note-agent-scope-runtime-design-and-correctness/scope-routing-one-opaque-key-selects-one-layer:
en: fa59d22549e9e44a
zh: 80904729042e87b3
/agent-note-agent-scope-runtime-design-and-correctness/scope-routing-one-opaque-key-selects-one-layer/scope-identity-uses-object-identity:
en: 3a05a7bfb2197f58
zh: fbb599031788b70b
/agent-note-agent-scope-runtime-design-and-correctness/scope-routing-one-opaque-key-selects-one-layer/registry-reads-overlay-one-exact-layer:
en: 28636ae6d55935d7
zh: 33a989f049de2f3e
/agent-note-agent-scope-runtime-design-and-correctness/scope-routing-one-opaque-key-selects-one-layer/fused-dispatch-helpers-prevent-subject-drift:
en: 638e3711206e3c41
zh: 61d370123d30c1ed
/agent-note-agent-scope-runtime-design-and-correctness/agent-creation-one-transaction-owns-the-complete-operation:
en: ef58215c8554180b
zh: 44571074148d2467
/agent-note-agent-scope-runtime-design-and-correctness/agent-creation-one-transaction-owns-the-complete-operation/registry-entries-are-the-only-live-identity-records:
en: 092b49671e83df98
zh: 330ea6e45c4deb99
/agent-note-agent-scope-runtime-design-and-correctness/agent-creation-one-transaction-owns-the-complete-operation/the-transaction-owns-preparation-before-awaiting-it:
en: 3940920908ec6066
zh: 888e36ca43611d30
/agent-note-agent-scope-runtime-design-and-correctness/agent-creation-one-transaction-owns-the-complete-operation/setup-is-trusted-composition-inside-a-private-world:
en: 40a73b8eede856ee
zh: 7dab8f2548cb92ea
/agent-note-agent-scope-runtime-design-and-correctness/agent-creation-one-transaction-owns-the-complete-operation/publication-has-one-ordered-commit-path:
en: 227eff7a5adacd0e
zh: b9ee423c2dd4212f
/agent-note-agent-scope-runtime-design-and-correctness/agent-creation-one-transaction-owns-the-complete-operation/teardown-preserves-work-before-revoking-registrations:
en: 1cbe77cff192815d
zh: 7f517936a8aa469e
/agent-note-agent-scope-runtime-design-and-correctness/session-append-materialize-validate-commit-notify:
en: cc37e93081fea4cb
zh: daf2234f84e4c9bf
/agent-note-agent-scope-runtime-design-and-correctness/session-append-materialize-validate-commit-notify/durable-data-is-materialized-once:
en: d0a57b0ac227d84c
zh: e9ae6ced0e65fe49
/agent-note-agent-scope-runtime-design-and-correctness/session-append-materialize-validate-commit-notify/pre-commit-listeners-can-veto-post-commit-observers-cannot:
en: 15255d3d0b62fac0
zh: c1995d5aa3c78f0a
/agent-note-agent-scope-runtime-design-and-correctness/trust-boundaries-copy-only-when-ownership-actually-changes:
en: 22b381902fe903f3
zh: 8a2efe9a8b458bba
/agent-note-agent-scope-runtime-design-and-correctness/tools-and-prompts-one-view-authoritative-assembly-committed-outcomes:
en: 456ac0359d3c02f6
zh: 9099e15d22139751
/agent-note-agent-scope-runtime-design-and-correctness/tools-and-prompts-one-view-authoritative-assembly-committed-outcomes/one-resolver-defines-the-tool-view:
en: 120e1c79f0b99b1a
zh: 1c21a5b1d6b08235
/agent-note-agent-scope-runtime-design-and-correctness/tools-and-prompts-one-view-authoritative-assembly-committed-outcomes/tool-execution-owns-identity-and-boundary-materialization:
en: 41f1f2ad73d83d73
zh: e6bff63958ede05e
/agent-note-agent-scope-runtime-design-and-correctness/tools-and-prompts-one-view-authoritative-assembly-committed-outcomes/the-assembly-waterfall-owns-the-final-model-visible-composition:
en: 5c5880ccea139058
zh: 3e5b7d10cb4c6ff8
/agent-note-agent-scope-runtime-design-and-correctness/tools-and-prompts-one-view-authoritative-assembly-committed-outcomes/structured-output-commits-only-authoritative-outcomes:
en: a9a711cf31559765
zh: e9083b000fc89128
/agent-note-agent-scope-runtime-design-and-correctness/tools-and-prompts-one-view-authoritative-assembly-committed-outcomes/three-execution-boundaries-are-deliberately-one-way:
en: a109f3fadf338061
zh: 12eb46fe775fa46a
/agent-note-agent-scope-runtime-design-and-correctness/tools-and-prompts-one-view-authoritative-assembly-committed-outcomes/skill-and-approval-services-trust-typed-callers:
en: 9572833d47f779e6
zh: 7ff491d309060030
/agent-note-agent-scope-runtime-design-and-correctness/subagents-publication-is-the-start-promise:
en: b9216021f8f50bcc
zh: fda52f9434cc8191
/agent-note-agent-scope-runtime-design-and-correctness/subagents-publication-is-the-start-promise/the-service-contract-has-one-cancellation-channel:
en: 84a4be83b78c045b
zh: 043e14cf628413cd
/agent-note-agent-scope-runtime-design-and-correctness/subagents-publication-is-the-start-promise/in-process-providers-reuse-the-core-transaction:
en: b5e0b3dcf0dff750
zh: 63905010383781b9
/agent-note-agent-scope-runtime-design-and-correctness/subagents-publication-is-the-start-promise/acp-providers-own-the-process-until-readiness-or-cleanup:
en: aa0c00cee368c7e6
zh: 767539b0f4d56f55
/agent-note-agent-scope-runtime-design-and-correctness/workflows-and-acp-processes-retain-only-independent-async-facts:
en: effbb0acf7f66bed
zh: e0cc9ad6ac0777de
/agent-note-agent-scope-runtime-design-and-correctness/workflows-and-acp-processes-retain-only-independent-async-facts/workflow-children-are-pending-starts-or-published-records:
en: 9f05eed800f3413c
zh: 8230a28a0f94bffa
/agent-note-agent-scope-runtime-design-and-correctness/workflows-and-acp-processes-retain-only-independent-async-facts/terminal-result-and-physical-cleanup-remain-separate:
en: 5ad141c6df9f4fc3
zh: 63effa4f14f3c530
/agent-note-agent-scope-runtime-design-and-correctness/workflows-and-acp-processes-retain-only-independent-async-facts/acp-prompt-settlement-does-not-depend-on-update-delivery:
en: d39f73f50f0370bd
zh: 3889c1db46de560e
/agent-note-agent-scope-runtime-design-and-correctness/correctness-enforcement:
en: 840564e766d2f05c
zh: 059243afea7eb9c0
/agent-note-agent-scope-runtime-design-and-correctness/correctness-enforcement/types-make-the-ordinary-path-hard-to-misuse:
en: 9183eb29dddfd97f
zh: e6ce13295e6c3e65
/agent-note-agent-scope-runtime-design-and-correctness/correctness-enforcement/runtime-invariants-cover-cross-service-facts:
en: fabafbebc0ab4f95
zh: 06d94a98ed5aa40c
/agent-note-agent-scope-runtime-design-and-correctness/correctness-enforcement/generated-artifacts-keep-public-contracts-aligned:
en: d0ddc5f38289225d
zh: 781d910228d5e334
/agent-note-agent-scope-runtime-design-and-correctness/alternatives-considered:
en: 5eef7873a795c8f0
zh: 3e8ba109a6e29ba5
/agent-note-agent-scope-runtime-design-and-correctness/alternatives-considered/use-a-transparent-proxy-as-the-scope-carrier:
en: 199c7345a237e7e9
zh: b262d5ad0c7cb562
/agent-note-agent-scope-runtime-design-and-correctness/alternatives-considered/reserve-agent-and-session-ids-before-setup:
en: 3a8cb6969139dd84
zh: 2913bb68433c9ec7
/agent-note-agent-scope-runtime-design-and-correctness/alternatives-considered/snapshot-every-typed-same-process-argument:
en: 3e1f19f909f8d138
zh: 0727777e34964afe
/agent-note-agent-scope-runtime-design-and-correctness/alternatives-considered/give-readiness-cancellation-and-disposal-separate-controllers:
en: f2c6ecbd139bbdb0
zh: 0ff5b1e192dcb376
/agent-note-agent-scope-runtime-design-and-correctness/alternatives-considered/keep-synchronous-subagent-start-plus-run-started:
en: 7f5669933cb35c9c
zh: c55e35d4c175af36
/agent-note-agent-scope-runtime-design-and-correctness/alternatives-considered/restore-selected-prompt-or-tool-contributions-after-assembly:
en: a2b2e48d9ccda310
zh: 3a4e925fde9d05b0
/agent-note-agent-scope-runtime-design-and-correctness/alternatives-considered/remove-worker-process-lifecycle-guards-with-same-process-hardening:
en: 662e0904d90a3a94
zh: 84c5e49f7cc59b32
/agent-note-agent-scope-runtime-design-and-correctness/consequences:
en: 0d781b2dc4c41ddb
zh: 844652a4aaac37aa
/agent-note-agent-scope-runtime-design-and-correctness/consequences/what-the-design-guarantees:
en: eb2001592d7bd7b1
zh: e534dbb6daa9af32
/agent-note-agent-scope-runtime-design-and-correctness/consequences/costs-and-limits:
en: e9383713d56b9e10
zh: d3ab00aea8ecf4e0
@@ -1,6 +1,37 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-14-provider-routed-llm-adapters.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-14-provider-routed-llm-adapters.md
2026-07-14-provider-routed-llm-adapters.md: 1001b10e18837399b41578658ffe62065e294ba8
2026-07-14-provider-routed-llm-adapters.zh.md: c5bff0ef407c8a2c22e8cad7e7d32c58c8b0e2da
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend:
en: e57698907c40f783
zh: 47004d8f68af1d7d
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/problem:
en: 2e51f5fa703b0677
zh: 385937219b88c447
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/decision:
en: a15c7c13f167e5ac
zh: 63bcc2ef60c2f344
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/decision/provider-is-the-adapter-registration-key:
en: 4921a060c657b790
zh: 2f9632469c6f0b60
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/decision/explicit-pi-ai-provider-profiles:
en: 5461685553dac663
zh: e5c7e0ad7ac84e29
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/decision/recorded-assistant-route-and-replay-state:
en: 8439e90c9f6d7642
zh: daeda3ce5146c9f5
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/decision/propagate-the-target-through-every-request-producer:
en: ba1908bc1517ed23
zh: 1c9353a422cf74e1
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/alternatives-considered:
en: ad0d610ea92aa9b8
zh: fe09d62762e73f01
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/consequences:
en: a0c98bced8a5e6fb
zh: 23caf082a08ba507
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/testing:
en: 5a36121f12701d08
zh: 90f0f8ed44f7234f
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/risks:
en: 11db2a349f9f26c2
zh: 550d6017d8639854
@@ -1,6 +1,22 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-15-agent-initiator-scope.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-15-agent-initiator-scope.md
2026-07-15-agent-initiator-scope.md: ab11da116a463cd706418e797eb58f1bc4ab9b1c
2026-07-15-agent-initiator-scope.zh.md: 343acba5f99379b6d2c3af41368e8fbe90b20611
/agent-note-initiating-agent-scope-over-asynclocalstorage:
en: b0a59e3a34c41826
zh: 7131428a14901d14
/agent-note-initiating-agent-scope-over-asynclocalstorage/problem:
en: a26991200892c735
zh: 04a7dfaca64e3f0c
/agent-note-initiating-agent-scope-over-asynclocalstorage/decision:
en: 43a4f0c503b30d95
zh: a6a780584f94ed73
/agent-note-initiating-agent-scope-over-asynclocalstorage/verification:
en: 312f5c4b843d515e
zh: a8993e3b84844fab
/agent-note-initiating-agent-scope-over-asynclocalstorage/alternatives-considered:
en: fd2ae1369fb3fbc6
zh: e2a3d7f9331fc8ac
/agent-note-initiating-agent-scope-over-asynclocalstorage/consequences:
en: 625c6afc49489e29
zh: ed7e5c5e56c781fb
@@ -1,6 +1,22 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-16-explicit-turn-cancellation.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-16-explicit-turn-cancellation.md
2026-07-16-explicit-turn-cancellation.md: 09631349226837d7f93112fe5e9c517f2fee099c
2026-07-16-explicit-turn-cancellation.zh.md: baf039d49578895d53ffae4c6b88d29b3d1563b6
/agent-note-explicit-turn-cancellation-capability:
en: 729ed6291e9d4d2c
zh: 32ae526ef41199da
/agent-note-explicit-turn-cancellation-capability/problem:
en: 0a7826345be2a509
zh: 430fccb5c4d6a5e2
/agent-note-explicit-turn-cancellation-capability/decision:
en: 2c15edb35f38e7e5
zh: fa5145d26e3bff20
/agent-note-explicit-turn-cancellation-capability/verification:
en: a7ab1d06542be1c0
zh: 1687979b7f2460fa
/agent-note-explicit-turn-cancellation-capability/alternatives-considered:
en: bf69bbf7eb280306
zh: a434a0ecb5008b2b
/agent-note-explicit-turn-cancellation-capability/consequences:
en: 1066aff1aec4ed01
zh: 31d6a60496e2e730
@@ -12,7 +12,7 @@ The [initiating Agent scope decision](2026-07-15-agent-initiator-scope.md) inten
## Decision
Agent owns the runtime-only `AgentCancelCause` union `{ kind: 'user' } | { kind: 'parent' }`; `agent.cancel()` defaults to `user`. TypeScript enforces that vocabulary at this typed same-process boundary, with no runtime validator, fallback, or special compatibility contract for untyped callers. An active `TurnCancellation` copies the typed discriminant into a fresh frozen signal reason; idle cancellation has no holder to mutate and does not arm later work.
Agent owns the runtime-only `AgentCancelCause` union `{ kind: 'user' } | { kind: 'parent' } | { kind: 'hook'; reason: string } | { kind: 'disposed' }`, and `agent.cancel()` requires one. TypeScript enforces that vocabulary at this typed same-process boundary, with no runtime validator, fallback, or special compatibility contract for untyped callers. The holder aborts with the caller's own object rather than a detached copy, so a transport reaching that signal can extend it: Node's fetch assigns a `stack` onto the reason it receives. The loop therefore copies the declared fields where the cause becomes durable data. Freezing the cause at `cancel()` is not an alternative — undici performs that assignment from strict-mode code, so a frozen reason makes `fetch` reject with `TypeError: Cannot add property stack` in place of the abort reason. Idle cancellation has no holder to mutate and does not arm later work.
An interrupted live turn ends with the coarse durable `{ kind: 'aborted' }` outcome. The terminal event records what happened to the turn, while the runtime signal identifies who requested cancellation; it does not duplicate `user` or `parent` into replay. Session seed/load rejects legacy aborted records with a reason or any other extra field, so replay cannot reintroduce caller-owned cancellation detail. The process-local `agent/cancel-requested` notification is not durable; a future audit requirement uses a separate durable control-request event so a request and its eventual outcome remain distinct. Durable events contain no stack, signal, error object, free-form cancellation text, or backend-private detail.
@@ -22,7 +22,7 @@ The driver keeps only a cause-less pre-run marker for queued work cancelled befo
The explicit event signatures pass a single payload object: agent-scoped events carry `agent` and `signal` in the payload with `next` last, and the remaining APIs keep `signal` immediately before a waterfall's final `next`. `PreStepContext` and `RequestFailureContext` are retired, with their fields folded into the `agent/pre-step` and `agent/request-error` payloads ([payload-object events](../../archived/architecture/2026-08-06-agent-event-payload-objects.md)). Pre-step entry, request configuration, request-error recovery, model generation, tool execution, approval, turn stopping, and subagent or workflow requests all receive the current signal. Hook bridges must also supply `RunHookOptions.signal`, so a turn cancellation reaches the bash executor's provider-managed termination and join boundary; the [native-containment decision](2026-08-28-subprocess-native-containment.md) owns the supported local scope, Job, and fallback mechanics. `SystemPrompt.assemble()` carries `signal?: AbortSignal` in `AssembleContext` because that object is an explicit request value that can also represent signal-less assembly outside a turn. Listeners may cooperate with the signal but must not retain it to control another turn.
`ctx.agents` continues to carry only the initiating Agent. Ambient Agent presence does not imply liveness, a current turn, or cancellation authority. The cause reader is private to the loop and states the machine-private slot invariant (only `cancel()` aborts a turn controller, always with a canonical frozen cause) instead of re-validating the reason structurally; no public helper reads a cause off an arbitrary signal. Concurrent Agents isolate both their initiator identities and their turn signals; a child driver shadows the parent initiator while its parent request signal still travels through the subagent seam.
`ctx.agents` continues to carry only the initiating Agent. Ambient Agent presence does not imply liveness, a current turn, or cancellation authority. The cause reader is private to the loop and states the machine-private slot invariant (only `cancel()` aborts a turn controller, always with a typed cause) instead of re-validating the reason structurally; no public helper reads a cause off an arbitrary signal. Concurrent Agents isolate both their initiator identities and their turn signals; a child driver shadows the parent initiator while its parent request signal still travels through the subagent seam.
Agent disposal requests the runtime-only `{ kind: 'disposed' }` interruption on the active holder. If cancellation already won the controller reason, the reason cannot be rewritten, so terminal classification first checks lifecycle state: disposed wins, then a supported `user` or `parent` cause becomes the coarse aborted outcome, and unrelated exceptions retain the existing error path. ACP cancellation maps to `user`; in-process spawn and fork propagation map to `parent`. Remote ACP subagents retain their existing wire protocol.
@@ -30,7 +30,7 @@ Cancellation remains cooperative. The loop checks interruption before and after
## Verification
Contract tests verify the typed caller union, frozen detachment, default and first-wins behavior, the coarse Session JSON round trip and legacy-record rejection, ACP `user`, in-process subagent `parent`, and disposal precedence. Loop tests make cooperative listeners wait on the signal at pre-step, system-prompt assembly, request, model stream, request-error recovery, tool execution, and turn stopping; they assert one signal within a turn, a fresh signal across turns, and no cancellation authority during terminal publication or a blocked durability flush. A real hook bridge test cancels and reaps a blocked prompt hook before idle.
Contract tests verify the typed caller union, field copying where the cause becomes durable data, default and first-wins behavior, the coarse Session JSON round trip and legacy-record rejection, ACP `user`, in-process subagent `parent`, and disposal precedence. Loop tests make cooperative listeners wait on the signal at pre-step, system-prompt assembly, request, model stream, request-error recovery, tool execution, and turn stopping; they assert one signal within a turn, a fresh signal across turns, and no cancellation authority during terminal publication or a blocked durability flush. A real hook bridge test cancels and reaps a blocked prompt hook before idle.
Initiator-scope tests assert that every hook still observes the exact Agent and no ambient turn signal, concurrent Agents retain independent identities and signals, and a nested child driver shadows only identity. Race tests cover idle cancellation, pre-run cancellation, replacement submission from a `running` listener, repeated cancellation, and cancel-versus-dispose quiescence.
@@ -12,7 +12,7 @@ Status: implemented
## 决策
Agent 拥有仅用于运行时的 `AgentCancelCause` 联合类型 `{ kind: 'user' } | { kind: 'parent' }`;`agent.cancel()` 默认使用 `user`。TypeScript 在这个类型化的同进程边界中强制执行该词汇,不提供运行时校验器、后备行为,也不为无类型调用方提供特殊兼容性约定。活跃的 `TurnCancellation` 会把类型化判别字段复制为一个全新且已冻结的 signal 原因;空闲状态下没有可修改的持有者,也不会让后续工作预先进入取消状态。
Agent 拥有仅用于运行时的 `AgentCancelCause` 联合类型 `{ kind: 'user' } | { kind: 'parent' } | { kind: 'hook'; reason: string } | { kind: 'disposed' }`,`agent.cancel()` 必须显式传入其一。TypeScript 在这个类型化的同进程边界中强制执行该词汇,不提供运行时校验器、后备行为,也不为无类型调用方提供特殊兼容性约定。持有者中止时携带的是调用方自己的那个对象,而非一份分离的拷贝,因此能接触到该 signal 的传输层可以向其添加属性:Node 的 fetch 会给它收到的 reason 赋一个 `stack`。所以循环在 cause 成为持久数据的那一步拷贝已声明字段。在 `cancel()` 处冻结 cause 并非可选方案——undici 是在严格模式代码中执行该赋值的,被冻结的 reason 会让 `fetch` 以 `TypeError: Cannot add property stack` 取代中止原因而拒绝。空闲状态下没有可修改的持有者,也不会让后续工作预先进入取消状态。
正在运行的轮次被中断后,以粗粒度的持久化结果 `{ kind: 'aborted' }` 结束。终态事件记录轮次发生了什么,运行时 signal 标识谁请求了取消;回放不会重复保存 `user` 或 `parent`。会话 seed/load 会拒绝携带取消原因或任何其他额外字段的旧式中止记录,因此回放无法重新引入由调用方持有的取消细节。仅限进程内的 `agent/cancel-requested` 通知不会持久化;未来若有审计需求,应使用独立的持久化控制请求事件,让请求与最终结果保持为两项事实。持久化事件不包含调用栈、signal、错误对象、自由文本取消原因或后端私有细节。
@@ -22,7 +22,7 @@ AgentLoop 为每个待启动轮次私有地持有一个 `TurnCancellation`。它
显式事件签名传递单个 payload 对象:agent 作用域事件在 payload 中携带 `agent` 和 `signal`,`next` 位于最后;其余 API 保持 `signal` 紧邻 waterfall(瀑布式事件)的最终 `next` 之前。`PreStepContext` 与 `RequestFailureContext` 已退役,其字段并入 `agent/pre-step` 与 `agent/request-error` 的 payload([payload-object 事件](../../archived/architecture/2026-08-06-agent-event-payload-objects.md))。进入 pre-step 时、请求配置、请求错误恢复、模型生成、工具执行、审批、轮次停止以及 subagent 或工作流请求都会收到当前 signal。钩子桥接器也必须提供 `RunHookOptions.signal`,使轮次取消能够到达 Bash 执行器由提供方管理的终止与等待边界;[原生 containment 决策](2026-08-28-subprocess-native-containment.zh.md)负责受支持本地路径上的 scope、Job 与 fallback 机制。`SystemPrompt.assemble()` 在 `AssembleContext` 中携带 `signal?: AbortSignal`,因为该对象是显式请求值,也可表示轮次之外不携带 signal 的组装。监听器可以配合该 signal 取消,但不得保留它来控制其他轮次。
`ctx.agents` 仍只携带发起 Agent。环境中的 Agent 并不代表存活、当前轮次或取消权限。cause 读取器是 loop 私有的,它直接陈述机器私有的 slot 不变量(只有 `cancel()` 会中止轮次控制器,且总是携带规范的冻结 cause),而不是对 reason 做结构化再校验;不存在从任意 signal 读取 cause 的公开辅助函数。并发 Agent 会同时隔离各自的发起方身份和轮次 signal;子驱动会遮蔽父发起方,而父请求 signal 仍通过 subagent seam 传递。
`ctx.agents` 仍只携带发起 Agent。环境中的 Agent 并不代表存活、当前轮次或取消权限。cause 读取器是 loop 私有的,它直接陈述机器私有的 slot 不变量(只有 `cancel()` 会中止轮次控制器,且总是携带类型化的 cause),而不是对 reason 做结构化再校验;不存在从任意 signal 读取 cause 的公开辅助函数。并发 Agent 会同时隔离各自的发起方身份和轮次 signal;子驱动会遮蔽父发起方,而父请求 signal 仍通过 subagent seam 传递。
Agent dispose(资源释放)会在活跃持有者上请求仅用于运行时的 `{ kind: 'disposed' }` 中断。若取消已经先占用控制器的中断原因,该原因便无法改写,因此终态分类会先检查生命周期状态:资源释放结果优先,之后受支持的 `user` 或 `parent` 取消原因形成粗粒度的中止结果,其他异常保留现有错误路径。ACP(Agent Client Protocol)取消映射为 `user`;进程内 spawn 和 fork 的传播映射为 `parent`。远程 ACP subagent 保持现有协议。
@@ -30,7 +30,7 @@ Agent dispose(资源释放)会在活跃持有者上请求仅用于运行时
## 验证
约定测试验证类型化调用方联合类型、冻结且与调用方分离、默认行为与首次请求优先行为、粗粒度的会话 JSON 往返与旧式记录拒绝、ACP `user`、进程内 subagent `parent` 以及 dispose 优先级。AgentLoop 测试让协作式监听器在 pre-step、系统提示词组装、请求、模型流、请求错误恢复、工具执行和轮次停止处等待 signal;并断言同一轮次使用一个 signal,不同轮次使用全新的 signal,终态发布期间和持久化刷新受阻期间不存在取消权限。真实钩子桥接器测试会在报告空闲状态前取消并回收受阻的提示词钩子。
约定测试验证类型化调用方联合类型、在 cause 成为持久数据处拷贝字段、默认行为与首次请求优先行为、粗粒度的会话 JSON 往返与旧式记录拒绝、ACP `user`、进程内 subagent `parent` 以及 dispose 优先级。AgentLoop 测试让协作式监听器在 pre-step、系统提示词组装、请求、模型流、请求错误恢复、工具执行和轮次停止处等待 signal;并断言同一轮次使用一个 signal,不同轮次使用全新的 signal,终态发布期间和持久化刷新受阻期间不存在取消权限。真实钩子桥接器测试会在报告空闲状态前取消并回收受阻的提示词钩子。
发起方作用域测试断言所有钩子仍观察到同一个 Agent 且没有环境中的轮次 signal,并发 Agent 保持独立的身份与 signal,嵌套子驱动只遮蔽身份。竞态测试覆盖空闲状态取消、运行前取消、从 `running` 监听器提交替代提示词、重复取消以及取消与 dispose 竞争下的完全停稳。
@@ -1,6 +1,34 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-19-cooperative-tool-cancellation.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-19-cooperative-tool-cancellation.md
2026-07-19-cooperative-tool-cancellation.md: 5ca2b44b24a4af189df27c6f724021a7bf290e2b
2026-07-19-cooperative-tool-cancellation.zh.md: d6d49fb44c5d5629729a8b5b4bad07ea9b2f7ee9
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary:
en: 84c827aa3baa331a
zh: 10cad03e58b10e31
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary/problem:
en: e386b22491b468c1
zh: 82015f5145b679cd
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary/decision:
en: ca66d3b6af50be10
zh: f054b10d0c965e82
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary/decision/mutability-follows-the-pipeline-stage:
en: 0e1399cad4151f87
zh: 960fa0ccbe0f8fea
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary/decision/cancellation-codes-record-whether-dispatch-occurred:
en: c787fba8731ac147
zh: 21b5968ae6f8cd59
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary/decision/pre-aborted-entry-short-circuits-after-materialization:
en: 53362db6a0c71698
zh: 311de45ca26d3fdc
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary/decision/started-work-still-reaches-quiescence:
en: 26e4b71366bebd1b
zh: 10598e12b28c586e
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary/verification:
en: fbd101d4576afa92
zh: 35f5d3c2f6cad6a8
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary/alternatives-considered:
en: 1f205f1a78d4fd5b
zh: 6c17e35da2909302
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary/consequences:
en: 24a9ad2c4c7c86b5
zh: debdd29d272e07ea
@@ -1,6 +1,40 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-19-gui-web-client-architecture.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-19-gui-web-client-architecture.md
2026-07-19-gui-web-client-architecture.md: 4d62d7ddbeddd2d5c02e42194b035ee08b5cf041
2026-07-19-gui-web-client-architecture.zh.md: aeb6c89e677d7b65daef03d5d31372f484ae3117
/agent-note-web-client-architecture-the-client-cordis-plugin-tree-the-slot-system-and-the-react-free-object-layer:
en: e940be9ef95509ff
zh: c06cea53bb49c718
/agent-note-web-client-architecture-the-client-cordis-plugin-tree-the-slot-system-and-the-react-free-object-layer/problem:
en: c5a3dda6ccd57c9e
zh: 122307b113bb1c09
/agent-note-web-client-architecture-the-client-cordis-plugin-tree-the-slot-system-and-the-react-free-object-layer/decision:
en: 29742775aee9fbc3
zh: 54a2df8816e2ea2e
/agent-note-web-client-architecture-the-client-cordis-plugin-tree-the-slot-system-and-the-react-free-object-layer/the-client-cordis-tree-and-the-loading-chain:
en: 23b0b6c3f29e4f5e
zh: 53bf897b502c645b
/agent-note-web-client-architecture-the-client-cordis-plugin-tree-the-slot-system-and-the-react-free-object-layer/the-slot-system-how-the-page-composes:
en: 1661f3dd74dc9df6
zh: 3152467c7dd8e6ef
/agent-note-web-client-architecture-the-client-cordis-plugin-tree-the-slot-system-and-the-react-free-object-layer/services-and-scope-addressing:
en: 9da9311f677c5da6
zh: 9cb16a92cee87055
/agent-note-web-client-architecture-the-client-cordis-plugin-tree-the-slot-system-and-the-react-free-object-layer/the-data-object-layer-packages-api-session-controller-src-client:
en: 909682e20c0d23a1
zh: ed1defbcf7745e8e
/agent-note-web-client-architecture-the-client-cordis-plugin-tree-the-slot-system-and-the-react-free-object-layer/the-react-face-packages-client-ui-renderer:
en: 0971d6196b5358fd
zh: 26175d648feccfd9
/agent-note-web-client-architecture-the-client-cordis-plugin-tree-the-slot-system-and-the-react-free-object-layer/directory-shape:
en: 74c45680c8aab51c
zh: fd431ae5d3656038
/agent-note-web-client-architecture-the-client-cordis-plugin-tree-the-slot-system-and-the-react-free-object-layer/how-to-develop:
en: cbc6abcd9f291868
zh: 0078f15f2d08a02e
/agent-note-web-client-architecture-the-client-cordis-plugin-tree-the-slot-system-and-the-react-free-object-layer/consequences:
en: 56a9086da5783306
zh: 8147576101d22aa0
/agent-note-web-client-architecture-the-client-cordis-plugin-tree-the-slot-system-and-the-react-free-object-layer/alternatives-considered:
en: 8bedf2e688b14322
zh: 7cda12f7474832ee
@@ -1,6 +1,28 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-19-package-invariant-runtime-contracts.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-19-package-invariant-runtime-contracts.md
2026-07-19-package-invariant-runtime-contracts.md: a1b635cc40844f1846c04e203dbb842d1c7328ed
2026-07-19-package-invariant-runtime-contracts.zh.md: d315c440f1c100911386f57d6f82d5f16be631ca
/agent-note-meaningful-package-invariant-contracts:
en: e5db3b3373f72761
zh: 312b83d320d9aaab
/agent-note-meaningful-package-invariant-contracts/problem:
en: 220a4ceb3cd9b9c9
zh: 9eac93e1762b2914
/agent-note-meaningful-package-invariant-contracts/decision:
en: a15c7c13f167e5ac
zh: 63bcc2ef60c2f344
/agent-note-meaningful-package-invariant-contracts/decision/published-assertions-must-be-meaningful:
en: 11a1c080592def10
zh: d1189de665f9e327
/agent-note-meaningful-package-invariant-contracts/decision/representative-implemented-checks:
en: 2f7ae4ed588d6de8
zh: ed7ea9ccc6c54e87
/agent-note-meaningful-package-invariant-contracts/decision/repository-gate-and-tests:
en: 37e646754f13dd65
zh: 355ebf3ce1403117
/agent-note-meaningful-package-invariant-contracts/alternatives-considered:
en: 74c6a5a0cfadbf88
zh: e41356bb1a8c1fdf
/agent-note-meaningful-package-invariant-contracts/consequences:
en: 1f8d53063fb5903e
zh: 5edd23739749b065
@@ -1,6 +1,31 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-19-zstandard-jsonl-session-logs.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-19-zstandard-jsonl-session-logs.md
2026-07-19-zstandard-jsonl-session-logs.md: 96b76febee1c8853f70d7e4897894ea26390f524
2026-07-19-zstandard-jsonl-session-logs.zh.md: 4cf184ce107b9de6dbbf3f0e571d4009d50ca636
/agent-note-zstandard-jsonl-session-logs:
en: b46a6b48493de93e
zh: 0e394abf1d11fd43
/agent-note-zstandard-jsonl-session-logs/problem:
en: da8b3d94d10b5bc4
zh: da9c6d98a300b7bb
/agent-note-zstandard-jsonl-session-logs/decision:
en: a15c7c13f167e5ac
zh: 63bcc2ef60c2f344
/agent-note-zstandard-jsonl-session-logs/decision/configuration-and-suffix-ownership:
en: 1f29970aecc71980
zh: 94414765645bace0
/agent-note-zstandard-jsonl-session-logs/decision/frame-and-write-path:
en: da213ed32dfa6000
zh: a0f3cd11684dbdc9
/agent-note-zstandard-jsonl-session-logs/decision/read-listing-and-crash-recovery:
en: 63d4fe7d9c2a0a8a
zh: 2c4ef3e6aad73195
/agent-note-zstandard-jsonl-session-logs/decision/consumers-and-verification:
en: 6d9d16d610b80e55
zh: efa083ffaa7301e0
/agent-note-zstandard-jsonl-session-logs/alternatives-considered:
en: c5f447029fb644f7
zh: 5b84162e87bc6c86
/agent-note-zstandard-jsonl-session-logs/consequences:
en: e721552f16340e4c
zh: d5be8c3ffd1c7cc2
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-20-canonical-tool-output-contract.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-20-canonical-tool-output-contract.md
2026-07-20-canonical-tool-output-contract.md: 4dbcac3da8381e69809b15a653cdb4987af4e0e7
2026-07-20-canonical-tool-output-contract.zh.md: c2f4ebdfc7266495570766c69b3aa264f91172cc
/agent-note-canonical-tool-output-contract:
en: 01677f7875da9579
zh: 41bae59177ba5125
/agent-note-canonical-tool-output-contract/problem:
en: d0bc9840998f0530
zh: 2601671ec694a78d
/agent-note-canonical-tool-output-contract/decision:
en: db088b8225a4bf3d
zh: bfb0caa015b2b7df
/agent-note-canonical-tool-output-contract/alternatives-considered:
en: d82a0ac0461ab120
zh: bedea17fb4fb4f51
/agent-note-canonical-tool-output-contract/consequences:
en: 32724ff8f6b3b03f
zh: bc7512ff05d00157
@@ -1,6 +1,34 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-20-routed-model-context-and-compaction-policy.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-20-routed-model-context-and-compaction-policy.md
2026-07-20-routed-model-context-and-compaction-policy.md: d276354cb21f45eaec1c4e3202c7be1770745efb
2026-07-20-routed-model-context-and-compaction-policy.zh.md: b6e2a0b914f78e19675d80b86d8d962e8ba8c80f
/agent-note-routed-model-context-and-compaction-policy:
en: eca190695d4857f5
zh: f9d6411b8a8612ae
/agent-note-routed-model-context-and-compaction-policy/problem:
en: f7d1f343e487d725
zh: c7f736180e44d586
/agent-note-routed-model-context-and-compaction-policy/decision:
en: a15c7c13f167e5ac
zh: 63bcc2ef60c2f344
/agent-note-routed-model-context-and-compaction-policy/decision/adapters-own-exact-route-capacity:
en: 7bcf0ae2c74a0eb7
zh: bc0e04a25492d5ba
/agent-note-routed-model-context-and-compaction-policy/decision/token-measurement-remains-model-agnostic:
en: 51d1b39d06407320
zh: 85c88f6b5d8508d6
/agent-note-routed-model-context-and-compaction-policy/decision/compact-basic-resolves-a-target-spec:
en: d8827f9fa70aa65f
zh: a9d29e05dcb0cfdb
/agent-note-routed-model-context-and-compaction-policy/decision/target-specific-pressure-failures-preserve-optional-composition:
en: 1bd81ae0a1409e24
zh: 635c2937d5a94df7
/agent-note-routed-model-context-and-compaction-policy/testing:
en: 1ac13596df50571f
zh: 8605a6f0de049dfc
/agent-note-routed-model-context-and-compaction-policy/alternatives-considered:
en: 0ca0a4b1318188ec
zh: de98cd4494a6c0d0
/agent-note-routed-model-context-and-compaction-policy/consequences:
en: d00f83e85ba5e431
zh: 32665480f0cdc4ea
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-20-unified-json-value-schema-dsl.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-20-unified-json-value-schema-dsl.md
2026-07-20-unified-json-value-schema-dsl.md: 5de3523eab15a91ea32dc09e2e239146fadea6f1
2026-07-20-unified-json-value-schema-dsl.zh.md: 0dc38dc289a32269c0f9e545ae53a8098ba02189
/agent-note-unified-json-value-schema-dsl:
en: 8ba380205c472f4e
zh: de92e20dc90e8037
/agent-note-unified-json-value-schema-dsl/problem:
en: 5c7e79e37c007896
zh: 759f5803141b0960
/agent-note-unified-json-value-schema-dsl/decision:
en: 8f08bbafc8939a46
zh: 2ed8255c1e2b812b
/agent-note-unified-json-value-schema-dsl/alternatives-considered:
en: 1d32d6195d6fca08
zh: ea3a30126dca95f7
/agent-note-unified-json-value-schema-dsl/consequences:
en: 14d0a6a337503e80
zh: c7ffec8760a710af
@@ -1,6 +1,46 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-22-slot-type-chain-implementation.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-22-slot-type-chain-implementation.md
2026-07-22-slot-type-chain-implementation.md: 98585a42f71844594da4ada19d7438a7d8321702
2026-07-22-slot-type-chain-implementation.zh.md: d1093537ccbc5ee5ff2dc18c234233ffca39879d
/agent-note-the-slot-system-standard-single-register-four-props-shares-and-the-framework-store-seat:
en: 43ed5b2dfd8043fc
zh: 04b6fdd0435a265a
/agent-note-the-slot-system-standard-single-register-four-props-shares-and-the-framework-store-seat/problem:
en: 4f8d6891a8ba7061
zh: 5a619e562e00458d
/agent-note-the-slot-system-standard-single-register-four-props-shares-and-the-framework-store-seat/decision:
en: a81cddbebc1a97a3
zh: aa57738c9f08c07e
/agent-note-the-slot-system-standard-single-register-four-props-shares-and-the-framework-store-seat/decision/root-is-the-only-a-priori-slot:
en: 43b856b4a8cf371f
zh: cde298ab8b8a3815
/agent-note-the-slot-system-standard-single-register-four-props-shares-and-the-framework-store-seat/decision/register-is-the-single-api-children-declaration-authorization-runtime-spec:
en: ce28268021a38b89
zh: 7802540e4ef04752
/agent-note-the-slot-system-standard-single-register-four-props-shares-and-the-framework-store-seat/decision/component-props-four-shares-each-from-its-own-source-of-truth:
en: f3fca569fa0c5168
zh: 647a82662f6a887d
/agent-note-the-slot-system-standard-single-register-four-props-shares-and-the-framework-store-seat/decision/the-chain-kind-entries-self-nominate-first-match-renders:
en: 56278be7f3688805
zh: 16602ffbf4baef85
/agent-note-the-slot-system-standard-single-register-four-props-shares-and-the-framework-store-seat/decision/the-store-seat-framework-engine-registrant-schema:
en: 2645acc9d29c20ec
zh: a8a2fd293ef5da04
/agent-note-the-slot-system-standard-single-register-four-props-shares-and-the-framework-store-seat/decision/inject-the-registrant-s-business-face-on-its-own-ctx:
en: 66b311fad441400a
zh: 34f031e7f04d29e6
/agent-note-the-slot-system-standard-single-register-four-props-shares-and-the-framework-store-seat/decision/data-boundary-discipline:
en: 07b919360c8f65be
zh: 4c8a9915a2ed20af
/agent-note-the-slot-system-standard-single-register-four-props-shares-and-the-framework-store-seat/decision/tree-context-and-the-renderer-contract:
en: d77ebd3f6b166194
zh: 57ba9fe864908d46
/agent-note-the-slot-system-standard-single-register-four-props-shares-and-the-framework-store-seat/decision/type-chain-implementation-rulings:
en: 752bc30428dad374
zh: 3d729646468ecfde
/agent-note-the-slot-system-standard-single-register-four-props-shares-and-the-framework-store-seat/consequences:
en: 07228332f3d3c227
zh: 32525e1972acf156
/agent-note-the-slot-system-standard-single-register-four-props-shares-and-the-framework-store-seat/alternatives-considered:
en: 2bd28715f741ac04
zh: 8d6a0cb78a006533
@@ -1,6 +1,40 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-23-client-plugin-loading-model.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-23-client-plugin-loading-model.md
2026-07-23-client-plugin-loading-model.md: a8d016a70792ad4ac6a71083677ce5d82a30af0a
2026-07-23-client-plugin-loading-model.zh.md: 1b94909c9611f01e5a6d7fcb50ec3f91ee88fab1
/agent-note-client-plugin-loading-lazy-factories-cordis-lifecycle-and-hot-reload:
en: 874618fd5ad1d06a
zh: a5e4bfad490fab34
/agent-note-client-plugin-loading-lazy-factories-cordis-lifecycle-and-hot-reload/problem:
en: 46c4b208707e024e
zh: b6f86a6374b251da
/agent-note-client-plugin-loading-lazy-factories-cordis-lifecycle-and-hot-reload/decision:
en: a15c7c13f167e5ac
zh: a15c7c13f167e5ac
/agent-note-client-plugin-loading-lazy-factories-cordis-lifecycle-and-hot-reload/decision/package-membership-and-module-requests:
en: 6af228b03e5e533f
zh: 276a522af6be5d7a
/agent-note-client-plugin-loading-lazy-factories-cordis-lifecycle-and-hot-reload/decision/one-module-system-one-plugin-governor:
en: 575aad62490f32e9
zh: a6c18eb63965fc1e
/agent-note-client-plugin-loading-lazy-factories-cordis-lifecycle-and-hot-reload/decision/combo-external-script-arrival-and-source-maps:
en: 0a4240d88cca240a
zh: 8f5f1527caf571cd
/agent-note-client-plugin-loading-lazy-factories-cordis-lifecycle-and-hot-reload/decision/the-loading-flow-end-to-end:
en: 7dac236d6add3c3c
zh: 2a43a923a0646bb0
/agent-note-client-plugin-loading-lazy-factories-cordis-lifecycle-and-hot-reload/decision/live-graph-reconciliation:
en: 37e2fa1fe5cb2b95
zh: 80e513db87709cb4
/agent-note-client-plugin-loading-lazy-factories-cordis-lifecycle-and-hot-reload/decision/hot-reload-one-driver-plugin-self-watched-bundles:
en: f8b591d4c41ef492
zh: bc70f1cd540b7753
/agent-note-client-plugin-loading-lazy-factories-cordis-lifecycle-and-hot-reload/package-ownership:
en: 94ca0d09e6fd1e3a
zh: d5949a2bdec795ba
/agent-note-client-plugin-loading-lazy-factories-cordis-lifecycle-and-hot-reload/consequences:
en: 6a96d9ac06c222e5
zh: b2814ab58348e831
/agent-note-client-plugin-loading-lazy-factories-cordis-lifecycle-and-hot-reload/alternatives-considered:
en: b8f036f50cff7cd8
zh: 6d623c4a1f4314b1
@@ -46,7 +46,7 @@ A `require.async("./client.<name>.js")` call requests the exact revisioned `/plu
The shared tsdown preset emits a map for every plugin entry and chunk and rewrites first-party source paths into the browser-resolvable repository form `/packages/<group>/<package>/src/...`. The production Client pass consumes `lib/types`; the preset supplies each tsc map to Rolldown and fills `sourcesContent` from the original files, so the final map reaches TypeScript/TSX instead of stopping at emitted JavaScript. Other workspace sources inlined into a bundle likewise resolve to their `packages/` owner, while dependency paths remain unchanged. Combo generation strips each local debug directive, records its generated-line offset, resolves every authored source against the original per-plugin map URL, and emits an Indexed Source Map v3. An authored map supplies its section; otherwise an identity section embeds the generated bundle and uses the packer's `sourceURL` as its source name when present. The absolute combo map URL mirrors the script resource list by changing every `client.js` suffix to `client.js.map`, so `/plugins/??<package-a>/client.js,<package-b>/client.js&rev=<rev>` points to `/plugins/??<package-a>/client.js.map,<package-b>/client.js.map&rev=<rev>`. A chunk script likewise points to its own map URL. Source-map files are read and combined only when those map URLs receive `GET`; `HEAD` materializes neither script nor map bodies. The Vite shell also emits source maps, letting shell code and externally loaded plugins map stacks and performance profiles back to TypeScript/TSX.
The graph retains each row's revisioned one-resource combo URL for HMR and adds a revisioned descriptor for every startup combo request; several descriptors may carry the same scheduling phase. Initial row revisions are opaque process nonces rather than content hashes; they keep the snapshotted one-resource response immutable without hashing every plugin at startup. The shared preset stamps the entry after every package output is written. After the watcher observes that completed-build stamp, `rebuilt(id)` hashes the entry bytes together with its timestamp and publishes the resulting revision; a chunk-only build therefore advances the owner revision without a Host-side sibling scan. Startup combo revisions derive from the ordered row revisions. Script bodies are assembled on their first `GET`; source-map files are read and combined separately on their first map `GET`. `HEAD` materializes neither body. Versioned scripts and maps use immutable caching, and unrelated graph recomposition retains already-materialized chunk responses at the same revision. The Host serves only exact generated URLs; stale revisions and unadvertised resource lists return 404 instead of aliasing different bytes. An external script's `error` event exposes neither response status nor body, so failure diagnostics name only the URL; the same-origin Host and build-stamped registration id form the identity boundary, while the post-`load` factory-presence check rejects an artifact that did not register the expected id.
The graph retains each row's revisioned one-resource combo URL for HMR and adds a revisioned descriptor for every startup combo request; several descriptors may carry the same scheduling phase. Initial publication and `rebuilt(id)` use the same hash of entry mtime, ctime, and size; artifact contents never enter the hash. Ctime distinguishes rewrites that preserve mtime and size. A Host restart over unchanged artifacts therefore retains every row revision, so the reconnecting SSE snapshot does not trigger browser plugin replacement. The shared preset stamps the entry after every package output is written; a chunk-only build therefore advances the owner revision without a Host-side sibling scan. Startup combo revisions derive from the ordered row revisions. Script bodies are assembled on their first `GET`; source-map files are read and combined separately on their first map `GET`. `HEAD` materializes neither body. Versioned scripts and maps use immutable caching, and unrelated graph recomposition retains already-materialized chunk responses at the same revision. The Host serves only exact generated URLs; stale revisions and unadvertised resource lists return 404 instead of aliasing different bytes. An external script's `error` event exposes neither response status nor body, so failure diagnostics name only the URL; the same-origin Host and build-stamped registration id form the identity boundary, while the post-`load` factory-presence check rejects an artifact that did not register the expected id.
### The loading flow, end to end
@@ -56,7 +56,7 @@ What happens between `dsh web` starting and the UI appearing? Three stages: the
1. The composing app (`apps/cli`) ships the roster as ordinary rows in its `cordis.yml` config tree — client plugin packages are entry rows like every host plugin, including the always-mounted `client-hmr` row. `auditStartupEntries` reports failed imports, activation errors with their original stacks, and pending dependencies; optional entries warn and required entries reject startup ([startup policy](2026-09-09-consumer-owned-startup-strictness.md)).
2. The `dsh-client-modules` node half (the package is dual-face: its browser half is the module table) resolves each live Loader entry through the same `name` and owning-tree `baseUrl` inputs that imported its Host face, then reads the nearest owning package.json `dsh.client` declaration and composes `window.__DSH_BOOT__`: `{ rev, entries: [{ id, url, rev, inject?, immediately?, external? }], batches: [{ phase, url, rev, entries }] }`. The manifest package name is the browser module identity even when an overlay names a relative source or built entry file. Distinct active Loader sources resolving to one package name fail composition; after one source unloads, the surviving source supplies the row without a fiber restart. The row's three optional fields come from manifests, never hand-copied. Composition orders requested dynamic rows before their consumers, rejects synchronous request cycles, and assigns every row to exactly one initial batch. It refuses declared plugins without built `./client` bundles and groups their package/path rows under one required source-build instruction; malformed declaration fields also fail activation, and the Host audit reports either error from the FAILED fiber.
3. Scanning is incremental per package — there is no full-rescan code path. Each cordis `internal/plugin` emission marks the fiber's entry name dirty (entry-less fibers drop O(1)); a microtask flush reconciles each dirty name against live loader entries, with package metadata (including the negative "not a client package" verdict) cached per entry name and owning-tree base URL for the process lifetime and bundle re-hashing reachable only through `rebuilt(id)`. The activation pass seeds the same dirty set from current entries and flushes synchronously, so first scan and steady state share one implementation. Initial rows receive an opaque process nonce plus sequence without hashing their artifacts; startup combo revisions hash the combined script inputs plus indexed map, and the rows plus batch descriptors hash into `graph.rev`. The graph types are single-sourced in the modules package's `./client` export — the webserver knows nothing about the graph, while modules registers the combo route and contributes structured index-injection rows.
3. Scanning is incremental per package — there is no full-rescan code path. Each cordis `internal/plugin` emission marks the fiber's entry name dirty (entry-less fibers drop O(1)); a microtask flush reconciles each dirty name against live loader entries, with package metadata (including the negative "not a client package" verdict) cached per entry name and owning-tree base URL for the process lifetime and changed bundle publication reachable only through `rebuilt(id)`. The activation pass seeds the same dirty set from current entries and flushes synchronously, so first scan and steady state share one implementation. Initial rows hash their pre-read filesystem metadata; startup combo revisions hash the ordered row identities and revisions, and the rows plus batch descriptors hash into `graph.rev`. The graph types are single-sourced in the modules package's `./client` export — the webserver knows nothing about the graph, while modules registers the combo route and contributes structured index-injection rows.
Why is the roster yml rows and not a scan? Because which plugins compose into a deployment is a composition decision, not a package property — a package declaring `dsh.client` in the repo does not mean this deployment mounts it, so discovery-by-scan cannot make that call; the node half scans only what the tree actually mounted.
@@ -80,7 +80,7 @@ The Host SSE adapter forwards existing graph-change notifications and sends the
Hot reload is a composition decision: the web bundle mounts the `client-hmr` row (a normal plugin package) unconditionally; its node half brings the bundle watch and the SSE channel, and the chain stays idle until a rebuild watcher rewrites client bundles. A composition that must not expose it disables the row.
How does a rebuilt bundle become a reload signal? The hmr node half observes it itself — no builder tells it. Before reading each startup snapshot, the module host captures the entry stat baseline and exposes it through `ctx.clientModules.artifactBaseline(id)`. One HMR-owned interval compares every current graph row with that baseline. An unchanged row starts watching without a content read or hash; a write after baseline capture is already a stat delta and only that row enters `rebuilt(id)`. This avoids both an initial all-row re-hash and `fs.watchFile`, whose asynchronous first baseline can silently absorb a construction-time rebuild. Watch membership follows `onGraphChanged`; vanished rows drop out, and an entry missing at poll time keeps its row dirty so reappearance forces a new revision even with identical metadata. The shared tsdown preset stamps `client.js` after every sibling output has been written; on an entry mtime or size delta, or a dirty row, `rebuilt(id)` derives the revision from the entry bytes and completed-build timestamp. A chunk-only edit therefore changes the revision, and a partial write followed by the completion stamp supplies a later stat change that self-heals. When the `rev` changes, the node half broadcasts a `rebuilt` frame on `GET /plugins/events` — a system SSE channel that sends the full graph on connect and `rebuilt` frames on change, presentation-only wire that never enters the session log. Polling is deliberate because inotify does not fire on the weka network mount, the same reason the build-side watcher needs `--poll`; one entry stat per row and interval is sufficient, the interval is a validated config field (default 500ms), and disposal clears the one timer. Rebuilding artifacts is any process using the shared Client tsdown preset — `scripts/dev-web.ts` remains the watch-build entry point, discovering its package list through `dsh.client` while scanning `packages/*/*/package.json` at startup — and builder and host share no notification protocol.
How does a rebuilt bundle become a reload signal? The hmr node half observes it itself — no builder tells it. Before reading each startup snapshot, the module host captures the entry stat baseline and exposes it through `ctx.clientModules.artifactBaseline(id)`. One HMR-owned interval compares every current graph row with that baseline. An unchanged row starts watching without a content read or hash; a write after baseline capture is already a stat delta and only that row enters `rebuilt(id)`. This avoids redundant reads when installing the watcher and avoids `fs.watchFile`, whose asynchronous first baseline can silently absorb a construction-time rebuild. Watch membership follows `onGraphChanged`; vanished rows drop out, and an entry missing at poll time keeps its row dirty so reappearance retries publication even when mtime and size match the baseline. The shared tsdown preset stamps `client.js` after every sibling output has been written; on an entry mtime, ctime, or size delta, or a dirty row, `rebuilt(id)` derives the revision from those three metadata values. It reads the new bundle snapshot only if the revision changes. A chunk-only edit therefore changes the revision, and a partial write followed by the completion stamp supplies a later stat change that self-heals. When the `rev` changes, the node half broadcasts a `rebuilt` frame on `GET /plugins/events` — a system SSE channel that sends the full graph on connect and `rebuilt` frames on change, presentation-only wire that never enters the session log. Polling is deliberate because inotify does not fire on the weka network mount, the same reason the build-side watcher needs `--poll`; one entry stat per row and interval is sufficient, the interval is a validated config field (default 500ms), and disposal clears the one timer. Rebuilding artifacts is any process using the shared Client tsdown preset — `scripts/dev-web.ts` remains the watch-build entry point, discovering its package list through `dsh.client` while scanning `packages/*/*/package.json` at startup — and builder and host share no notification protocol.
On the browser side, the transport delegates code replacement to the same modules controller that owns graph reconciliation:
@@ -120,4 +120,4 @@ Roster: it lives in the web bundle's config tree (`packages/bundle/web-app/cordi
| Full ctx-ification now (React and libraries via services, no module table) | Static UI libraries still expose synchronous values, so removing the table would leave those imports without a shared identity |
| Eager instantiation with a frozen table | Runs bundle side effects at script arrival; lazy registration keeps execution at Cordis import while recursive `require` materializes registered requests |
| Fetch response text, then inject an inline `<script>` | Makes the module system buffer the complete source and maintain separate fetch/execute paths; dynamic source execution also breaks the browser-native association among the network resource, source map, and profile |
| Builder-push rebuild channel (`POST /plugins/rebuilt` from the orchestrator's `onSuccess`) | Couples reload to one blessed builder process and a second wire protocol; the webserver already holds every bundle path, and stat polling covers the torn-write race (re-hash on every stat change) that once justified pushing |
| Builder-push rebuild channel (`POST /plugins/rebuilt` from the orchestrator's `onSuccess`) | Couples reload to one blessed builder process and a second wire protocol; the webserver already holds every bundle path, and stat polling covers the torn-write race (publication on every stat change) that once justified pushing |
@@ -46,7 +46,7 @@ Host 会快照每个已构建插件入口 bundle,并把每个调度阶段的
共享 tsdown 预设为每个插件入口与 chunk 产出 map,并把第一方源码路径重写成浏览器可识别的仓库形式 `/packages/<group>/<package>/src/...`。生产 Client 构建会消费 `lib/types`;预设把每份 tsc map 交给 Rolldown,并从原文件补齐 `sourcesContent`,使最终 map 回到 TypeScript/TSX,而不是停在编译后的 JavaScript。内联进 bundle 的其他 workspace 源码同样回到其 `packages/` 归属,依赖包路径保持原样。Combo 生成会移除每个局部调试指令、记录其生成行偏移、以原插件 map URL 解析每个自带 source,再产出 Indexed Source Map v3。插件有自带 map 时直接用于对应 section;没有时则生成 identity section,内嵌构建后 bundle,并在存在时把 packer 写入的 `sourceURL` 用作 source 名。绝对 combo map URL 会平行改写脚本资源列表中的每个 `client.js` 后缀,因此 `/plugins/??<package-a>/client.js,<package-b>/client.js&rev=<rev>` 指向 `/plugins/??<package-a>/client.js.map,<package-b>/client.js.map&rev=<rev>`。chunk 脚本同样指向自己的 map URL。只有在这些 map URL 收到 `GET` 后,source map 文件才会被读取和组合;`HEAD` 不会物化脚本或 map body。Vite 壳同样产出 sourcemap,使壳代码与经外部加载的插件都能从 stack 和性能 profile 回到 TypeScript/TSX。
图为 HMR 保留每个 row 带 revision 的单资源 combo URL,并为每个启动 combo 请求增加带 revision 的描述;多条描述可以使用同一调度阶段。初始 row revision 是进程级不透明 nonce,而不是内容哈希;它无需在启动时哈希每个插件,也能保证已快照的单资源响应不可变。共享预设会在每个包输出写完后标记入口。watcher 观察到该构建完成标记后,`rebuilt(id)` 会把入口字节与其时间戳一起哈希并发布所得 revision;因此只重建 chunk 也会推进 owner revision,无需 Host 扫描 sibling。启动 combo revision 从有序 row revision 派生。脚本 body 在首次 `GET` 时组合;source map 文件在首次 map `GET` 时单独读取并组合。`HEAD` 不会物化任一 body。版本化脚本与 map 使用 immutable 缓存,无关图重组会保留相同 revision 下已经物化的 chunk 响应。Host 只提供精确生成的 URL;陈旧 revision 与未发布资源列表返回 404,不会别名到其他字节。外部脚本的 `error` 事件不给响应状态与正文,因此失败诊断只报告 URL;同源 Host 与构建期写入的 registration id 是身份边界,`load` 后的 factory 存在性检查负责拒绝未登记预期 id 的产物。
图为 HMR 保留每个 row 带 revision 的单资源 combo URL,并为每个启动 combo 请求增加带 revision 的描述;多条描述可以使用同一调度阶段。首次发布与 `rebuilt(id)` 使用相同的入口 mtime、ctime 和大小哈希;产物内容不参与求哈希。ctime 用于区分保留 mtime 和大小的重写。Host 重启时若产物未变,每个 row 的 revision 都保持不变,因此重连后的 SSE 快照不会触发浏览器插件替换。共享预设会在每个包输出写完后标记入口;因此只重建 chunk 也会推进 owner revision,无需 Host 扫描 sibling。启动 combo revision 从有序 row revision 派生。脚本 body 在首次 `GET` 时组合;source map 文件在首次 map `GET` 时单独读取并组合。`HEAD` 不会物化任一 body。版本化脚本与 map 使用 immutable 缓存,无关图重组会保留相同 revision 下已经物化的 chunk 响应。Host 只提供精确生成的 URL;陈旧 revision 与未发布资源列表返回 404,不会别名到其他字节。外部脚本的 `error` 事件不给响应状态与正文,因此失败诊断只报告 URL;同源 Host 与构建期写入的 registration id 是身份边界,`load` 后的 factory 存在性检查负责拒绝未登记预期 id 的产物。
### 装载流程,端到端
@@ -56,7 +56,7 @@ Host 会快照每个已构建插件入口 bundle,并把每个调度阶段的
1. 负责组合的 app(`apps/cli`)把名册作为普通行放进它的 `cordis.yml` 配置树——client 插件包与每个 host 插件一样是 entry 行,包括无条件挂载的 `client-hmr` 行。`auditStartupEntries` 报告 import 失败、带原始 stack 的激活错误,以及待满足的依赖;optional entry 输出 warning,required entry 则使启动失败([启动策略](2026-09-09-consumer-owned-startup-strictness.zh.md))。
2. `dsh-client-modules` 的 node 半(该包是双面的:浏览器半就是模块表)使用 Host face import 时相同的 `name` 与所属 tree `baseUrl` 解析每个 live Loader entry,再读取最近归属 package.json 的 `dsh.client` 声明并组合出 `window.__DSH_BOOT__`:`{ rev, entries: [{ id, url, rev, inject?, immediately?, external? }], batches: [{ phase, url, rev, entries }] }`。即使 overlay 指向相对的 source 或 built entry 文件,manifest 包名仍是浏览器模块身份。若不同的 active Loader source 解析到同一包名,组合会失败;一个来源卸载后,仍存活的来源无需重启 fiber 即可提供该 row。Row 的三个可选字段都来自 manifest,永不人肉抄写。组合会把被请求的动态图 row 排到消费者之前、拒绝同步请求环,并把每个 row 恰好分配给一个初始批次。它会拒绝没有已构建 `./client` bundle 的已声明插件,并把它们的 package/path 行归到一条源码构建要求下;畸形声明字段同样会让激活失败,Host 检查会从 FAILED fiber 报告这两类错误。
3. 扫描是单包增量——不存在全量重扫代码路径。每次 cordis `internal/plugin` 发射把该 fiber 的 entry 名标脏(无 entry 的 fiber O(1) 丢弃);微任务 flush 把每个脏名对账 live loader entries,包元数据(含「非 client 包」的否定结论)按 entry 名与所属 tree base URL 缓存至进程结束,bundle 重哈希只经 `rebuilt(id)` 可达。激活趟从当前 entries 灌同一脏集合并同步 flush,初扫与稳态共享一条实现。初始 row 使用不透明的进程 nonce 加序号,不对其产物求哈希;启动 combo revision 对合并脚本输入及 indexed map 求哈希,row 与批次描述再共同哈希进 `graph.rev`。图类型单源在 modules 包的 `./client` 出口——webserver 对图一无所知;modules 会注册 combo 路由并贡献结构化 index 注入行。
3. 扫描是单包增量——不存在全量重扫代码路径。每次 cordis `internal/plugin` 发射把该 fiber 的 entry 名标脏(无 entry 的 fiber O(1) 丢弃);微任务 flush 把每个脏名对账 live loader entries,包元数据(含「非 client 包」的否定结论)按 entry 名与所属 tree base URL 缓存至进程结束,变化后 bundle 的发布只经 `rebuilt(id)` 可达。激活趟从当前 entries 灌同一脏集合并同步 flush,初扫与稳态共享一条实现。初始 row 对读取前的文件系统元数据求哈希;启动 combo revision 对有序 row 的身份与 revision 求哈希,row 与批次描述再共同哈希进 `graph.rev`。图类型单源在 modules 包的 `./client` 出口——webserver 对图一无所知;modules 会注册 combo 路由并贡献结构化 index 注入行。
为什么名册是 yml 行而不是扫描?因为哪些插件组合进一次部署是组合决策,不是包属性——一个在仓库中声明了 dsh.client 的包,不代表这次部署要挂载它,扫描发现无从替人做这个决定;node 半只扫描配置树实际挂载了的东西。
@@ -80,7 +80,7 @@ Host SSE 适配器转发现有图变化通知,并在连接时发送当前完
热重载是一项组合决策:web 组合包无条件挂载 `client-hmr` 行(一个常规的插件包),其 node 半带来 bundle 监视与 SSE(Server-Sent Events)通道;没有重建 watcher 改写客户端 bundle 时链路保持空闲。不应暴露它的组合可以禁用该行。
重建好的 bundle 怎么变成重载信号?hmr 的 node 半自己观察——没有构建器来通知它。模块 host 在读取每份启动快照前捕获入口 stat 基线,并通过 `ctx.clientModules.artifactBaseline(id)` 暴露它。HMR 自持的单个定时器把当前图的每个 row 与这份基线比较:未变化的 row 直接开始监视,不读取内容也不求哈希;基线捕获后的写入已经形成 stat 差异,只有该 row 会进入 `rebuilt(id)`。这同时消除了启动期的全量重哈希,并避开 `fs.watchFile` 以异步首次 stat 建立基线、可能静默吸收构造期重建的问题。监视集合的成员随 `onGraphChanged` 更新;消失的 row 撤下监视,轮询时缺失的入口则让对应 row 保持标脏状态,文件重现时即使元数据相同也强制生成新 revision。共享 tsdown 预设会在每个 sibling 输出写完后标记 `client.js`;入口 mtime 或 size 变化、或 row 处于标脏状态时,`rebuilt(id)` 从入口字节与构建完成时间戳派生 revision。只修改 chunk 因此也会更换 revision;部分写入之后的完成标记还会提供一次更晚的 stat 变化以完成自愈。`rev` 变化时,node 半在 `GET /plugins/events` 上广播 `rebuilt` 帧——这是一条系统级 SSE 通道,连接即发全量图,变更时发 `rebuilt` 帧,仅供呈现的 wire,永不进会话日志。轮询是刻意选择:inotify 在 weka 网络挂载上不触发,构建侧监视器需要 `--poll` 也是同一原因;每个 row 每个间隔只需一次入口 stat,轮询间隔是一个经校验的配置字段(默认 500ms),dispose(资源释放)会清掉那一个定时器。重建产物的进程必须使用共享 Client tsdown 预设;`scripts/dev-web.ts` 仍作为 watch 构建入口保留,其包清单在启动时扫描 `packages/*/*/package.json` 按 dsh.client 发现,构建器与 host 之间没有通知协议。
重建好的 bundle 怎么变成重载信号?hmr 的 node 半自己观察——没有构建器来通知它。模块 host 在读取每份启动快照前捕获入口 stat 基线,并通过 `ctx.clientModules.artifactBaseline(id)` 暴露它。HMR 自持的单个定时器把当前图的每个 row 与这份基线比较:未变化的 row 直接开始监视,不读取内容也不求哈希;基线捕获后的写入已经形成 stat 差异,只有该 row 会进入 `rebuilt(id)`。这既避免安装 watcher 时重复读取,也避开 `fs.watchFile` 以异步首次 stat 建立基线、可能静默吸收构造期重建的问题。监视集合的成员随 `onGraphChanged` 更新;消失的 row 撤下监视,轮询时缺失的入口则让对应 row 保持标脏状态,文件重现时即使 mtime 和大小与基线相同也重试发布。共享 tsdown 预设会在每个 sibling 输出写完后标记 `client.js`;入口 mtime、ctime 或大小变化、或 row 处于标脏状态时,`rebuilt(id)` 从这三个元数据值派生 revision。只有 revision 变化时,它才读取新的 bundle 快照。只修改 chunk 因此也会更换 revision;部分写入之后的完成标记还会提供一次更晚的 stat 变化以完成自愈。`rev` 变化时,node 半在 `GET /plugins/events` 上广播 `rebuilt` 帧——这是一条系统级 SSE 通道,连接即发全量图,变更时发 `rebuilt` 帧,仅供呈现的 wire,永不进会话日志。轮询是刻意选择:inotify 在 weka 网络挂载上不触发,构建侧监视器需要 `--poll` 也是同一原因;每个 row 每个间隔只需一次入口 stat,轮询间隔是一个经校验的配置字段(默认 500ms),dispose(资源释放)会清掉那一个定时器。重建产物的进程必须使用共享 Client tsdown 预设;`scripts/dev-web.ts` 仍作为 watch 构建入口保留,其包清单在启动时扫描 `packages/*/*/package.json` 按 dsh.client 发现,构建器与 host 之间没有通知协议。
浏览器侧的传输把代码替换交给负责图对账的同一个 modules 控制器:
@@ -120,4 +120,4 @@ Wire 两侧运行同一份治理实现;浏览器特有层只包含一套模块
| 现在就彻底 ctx 化(React 与库全走服务,不设模块表) | 静态 UI 库仍暴露同步实体,因此删除模块表会让这些 import 失去共享身份 |
| 冻结表 + 到达即实例化 | 会在 script 到达时执行 bundle 副作用;惰性登记把执行推迟到 Cordis import,并由递归 `require` 物化已登记请求 |
| fetch 响应文本后注入内联 `<script>` | 模块系统必须缓冲整份源码并维护 fetch/execute 两条路径;动态源码执行也切断浏览器网络资源、sourcemap 与 profile 的原生关联 |
| 构建器推送重建通道(编排器在 `onSuccess` 里 POST `/plugins/rebuilt`) | 把重载耦合到一个钦定的构建器进程和第二套 wire 协议;webserver 本就握有每个 bundle 路径,stat 轮询(每次 stat 变化即重哈希)已兜住当年为推送辩护的撕裂写竞态 |
| 构建器推送重建通道(编排器在 `onSuccess` 里 POST `/plugins/rebuilt`) | 把重载耦合到一个钦定的构建器进程和第二套 wire 协议;webserver 本就握有每个 bundle 路径,stat 轮询(每次 stat 变化即发布)已兜住当年为推送辩护的撕裂写竞态 |
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-24-project-session-directories.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-24-project-session-directories.md
2026-07-24-project-session-directories.md: 0074c8b31304e6a7d32199b7461575356e406448
2026-07-24-project-session-directories.zh.md: 3a1d348255588fd120221dc277a2841359c0a038
/agent-note-project-grouped-session-directories:
en: c8960daf61fa50fa
zh: d8c7c844180fcaae
/agent-note-project-grouped-session-directories/problem:
en: 7df6078347bd7176
zh: bb769760d7abc903
/agent-note-project-grouped-session-directories/decision:
en: cdefd1f4d9d0a55a
zh: 5916d456f3faab2b
/agent-note-project-grouped-session-directories/alternatives-considered:
en: ba4657ba95479806
zh: 5c53c5c964efa932
/agent-note-project-grouped-session-directories/consequences:
en: 228c46a599899be1
zh: 265a233cd41b5c05
@@ -1,6 +1,28 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-24-separate-context-injection-from-turn-execution.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-24-separate-context-injection-from-turn-execution.md
2026-07-24-separate-context-injection-from-turn-execution.md: d22d3966767ae9888f2140141b1c7743792184c0
2026-07-24-separate-context-injection-from-turn-execution.zh.md: 2c567511b21891ada3e0027f666d1163861fb090
/agent-note-separate-context-injection-from-turn-execution:
en: f0090d5d271cbd9d
zh: 7ff28e03f1273093
/agent-note-separate-context-injection-from-turn-execution/problem:
en: 2eefc25e17f62a90
zh: 81bc7ff2649b2704
/agent-note-separate-context-injection-from-turn-execution/decision:
en: 83dba9117127cbb4
zh: 2b6b428a1c97d3b1
/agent-note-separate-context-injection-from-turn-execution/injection-lifecycle:
en: 16005492be54cb4f
zh: db460e0ebf838d54
/agent-note-separate-context-injection-from-turn-execution/extension-and-caller-semantics:
en: e184d8cd9676e24f
zh: 22465b570ae35f59
/agent-note-separate-context-injection-from-turn-execution/alternatives-considered:
en: 0efad389c38dfe95
zh: 13dd73de20226540
/agent-note-separate-context-injection-from-turn-execution/verification:
en: 3f3db450a3fc5848
zh: b2027393d570339d
/agent-note-separate-context-injection-from-turn-execution/consequences:
en: 71079e4dede5e12f
zh: deb46b5a4f151678
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-24-single-harness-home-resolver.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-24-single-harness-home-resolver.md
2026-07-24-single-harness-home-resolver.md: 1191c52bfa222b807e9aa301b250d2efcc8b0953
2026-07-24-single-harness-home-resolver.zh.md: cefa124b7cb46bab92157af34576f59d3053da9f
/agent-note-one-harness-home-resolver:
en: 4177acbdd51411da
zh: 53f10d4c54b431b2
/agent-note-one-harness-home-resolver/problem:
en: fa4d3622fb18dd58
zh: 2b98640594c8344b
/agent-note-one-harness-home-resolver/decision:
en: bbab99c7a1aae2fc
zh: 87453b98ca265699
/agent-note-one-harness-home-resolver/alternatives-considered:
en: b1c9535540171d47
zh: 7df816d42945db94
/agent-note-one-harness-home-resolver/consequences:
en: 7d0f569b98feadf5
zh: 5c84624e7cc8d1d4
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-24-web-config-tree-boot-and-transport-layering.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-24-web-config-tree-boot-and-transport-layering.md
2026-07-24-web-config-tree-boot-and-transport-layering.md: c8a1db3cd7bd715d8912b22a0b41a9ef660c1316
2026-07-24-web-config-tree-boot-and-transport-layering.zh.md: 41fcf65b06829199c203faa806bd17a310b68bcf
/agent-note-dsh-web-config-tree-boot-and-the-web-transport-layering:
en: 2d06ffcaaeb373e7
zh: 01822cfd7339167f
/agent-note-dsh-web-config-tree-boot-and-the-web-transport-layering/problem:
en: e5d603f77bff9dd7
zh: c9e9a64f0a4db3c9
/agent-note-dsh-web-config-tree-boot-and-the-web-transport-layering/decision:
en: 866ebaaf4fe1e0d1
zh: 8075a708c9042941
/agent-note-dsh-web-config-tree-boot-and-the-web-transport-layering/consequences:
en: 47f8a6beba1f320b
zh: 5f444699dc52cabf
/agent-note-dsh-web-config-tree-boot-and-the-web-transport-layering/alternatives-considered:
en: bf6fbf972eab0700
zh: 0f3449e5e6ace7e2
@@ -1,6 +1,43 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-25-web-client-session-scope-and-provide-channel.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-25-web-client-session-scope-and-provide-channel.md
2026-07-25-web-client-session-scope-and-provide-channel.md: 32be87f3a0a4f8da92100ec7351af788862532f7
2026-07-25-web-client-session-scope-and-provide-channel.zh.md: b2e7efae98efb69d5f34d6719a382221ffc7a00d
/agent-note-web-client-agent-scope-parity-model-and-the-provisioning-channel-agents-scope-blank-reuse-provide:
en: 64d8701a9f2574bd
zh: 938991d424943547
/agent-note-web-client-agent-scope-parity-model-and-the-provisioning-channel-agents-scope-blank-reuse-provide/problem:
en: 1738c071cb9824bc
zh: 7af7770739d5430a
/agent-note-web-client-agent-scope-parity-model-and-the-provisioning-channel-agents-scope-blank-reuse-provide/decision:
en: a397a3f2e0bd7c21
zh: a179a646c148ecc1
/agent-note-web-client-agent-scope-parity-model-and-the-provisioning-channel-agents-scope-blank-reuse-provide/decision/the-parity-model-client-and-host-share-one-root-state-axis:
en: e117f541a2f55c07
zh: c6a5cf9c9d6b7692
/agent-note-web-client-agent-scope-parity-model-and-the-provisioning-channel-agents-scope-blank-reuse-provide/decision/agent-scope-the-actx-is-the-sole-session-carrier-in-the-client-side-cordis-world:
en: 6e6488b3eab757c2
zh: 4ee3d1cc415234df
/agent-note-web-client-agent-scope-parity-model-and-the-provisioning-channel-agents-scope-blank-reuse-provide/decision/scope-lifecycle-anchored-to-explicit-references:
en: e2ed0052678a2b9b
zh: e0fe1b87dc3766af
/agent-note-web-client-agent-scope-parity-model-and-the-provisioning-channel-agents-scope-blank-reuse-provide/decision/the-blank-bit-the-empty-session-s-visible-projection-conversion-and-reuse:
en: ee88908c085b80c5
zh: 5ddb65bbac371f02
/agent-note-web-client-agent-scope-parity-model-and-the-provisioning-channel-agents-scope-blank-reuse-provide/decision/connectworkspace-the-sole-entry-point-of-new-session:
en: 833df42c5a87afbd
zh: 82d789a99fd2b968
/agent-note-web-client-agent-scope-parity-model-and-the-provisioning-channel-agents-scope-blank-reuse-provide/decision/per-session-provisioning-the-uisession-provide-standard-kit-channel:
en: 3c739c21ea490f09
zh: 5508153f313a86d9
/agent-note-web-client-agent-scope-parity-model-and-the-provisioning-channel-agents-scope-blank-reuse-provide/decision/input-delivery:
en: 2073e96f851d1e6e
zh: f0433bf5dfd0a23d
/agent-note-web-client-agent-scope-parity-model-and-the-provisioning-channel-agents-scope-blank-reuse-provide/decision/host-wire-smalls:
en: 5d1339b5a243812a
zh: a4be4d3c30056f42
/agent-note-web-client-agent-scope-parity-model-and-the-provisioning-channel-agents-scope-blank-reuse-provide/alternatives-considered:
en: 2a69d71f4bdf0f76
zh: dd768c273728d354
/agent-note-web-client-agent-scope-parity-model-and-the-provisioning-channel-agents-scope-blank-reuse-provide/consequences:
en: 6750378aca400a75
zh: 6eba20215ff255a1
@@ -26,7 +26,7 @@ The reference-owned lifetime and Provider targeting now follow [Client Session r
Host-side `session.create(workspaceId)` produces Session + Agent + cwd in one piece (an atomic bundle, never split); the client side is the mirror of that birth — the instant a session row enters the list mirror, the client mints its Agent scope (actx + provide + the full input surface mounted):
- Session identity is the host's true form from birth: the sessionId arrives via the `session.create` response / the `host/session-added` frame, and every client-side address (the scope tag, slot store keys, RPC addressing) uses that same id.
- The materialization moment = the instant the user picks a Workspace (cwd settled): the client calls `session.create({workspaceId})` on the spot and receives the complete entity.
- A manual Workspace pick or successful [first-use startup initialization](../feature/2026-09-20-default-workspace.md) establishes cwd before the client calls `session.create({workspaceId})` and receives the complete entity.
- "New Session with no workspace picked" is a **pure view state** (a navigation position) corresponding to no session/scope entity; until the pick, the composer is locked whole (no slash, no plain text).
- A "blank session" is an ordinary materialized session with no turn yet; to Agent-scope plugins on the host (goal/plan/skill/…) it remains an ordinary Session, so slash/plan are naturally live.
@@ -26,7 +26,7 @@ web client 只有一张全局会话面:slot 全部从根上下文渲染,插
host 侧 `session.create(workspaceId)` 一体产出 Session + Agent + cwd(作为不可拆分的原子整体);client 侧就是这次出生的镜像——会话行进入 list mirror 的瞬间,client 为它铸 Agent scope(actx + provide + 输入面全套挂上):
- 会话身份自出生即为 host 真身:sessionId 由 `session.create` 响应 / `host/session-added` 帧带来,client 侧一切寻址(scope tag、slot store 键、RPC 地址)用的都是同一个 id。
- 实体化时点 = 用户选定 Workspace(cwd 确定)的瞬间:client 当场调 `session.create({workspaceId})`,拿到完整实体。
- 手动选定 Workspace 或完成[首次使用的启动初始化](../feature/2026-09-20-default-workspace.zh.md) 后,cwd 已确定,client 再调 `session.create({workspaceId})`,拿到完整实体。
- 「New Session 且未选 workspace」是**纯视图态**(一个导航位置),不对应任何会话/scope 实体;选定之前 composer 整体锁死(无 slash、无纯文本)。
- 「空会话」是尚无轮次的普通实体化会话;对 host 上的 Agent-scope 插件(goal/plan/skill(技能)/…)而言,它仍是普通 Session,因此 slash/plan 自然可用。
@@ -1,6 +1,22 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-27-compiler-independent-typert-model.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-27-compiler-independent-typert-model.md
2026-07-27-compiler-independent-typert-model.md: 5083c55176b2f4d342d14d0c1cf2a7f0c2c14b3c
2026-07-27-compiler-independent-typert-model.zh.md: 70d6954fae0fcb48e76137231168d5f2417668bf
/agent-note-compiler-independent-typert-type-model:
en: 6943b47c9de69922
zh: 2fb08c1de4e6ea63
/agent-note-compiler-independent-typert-type-model/problem:
en: 77713a6c0d15207e
zh: 2dc30d4c0182d8ba
/agent-note-compiler-independent-typert-type-model/decision:
en: 9ecb064f733f9f1b
zh: 471aee71053174cd
/agent-note-compiler-independent-typert-type-model/verification-contract:
en: c02d3f09e54f9a32
zh: c14c15ffb7316b07
/agent-note-compiler-independent-typert-type-model/alternatives-considered:
en: fa503dcfaa6f438f
zh: 26052212a124e133
/agent-note-compiler-independent-typert-type-model/consequences:
en: 4a472acf377f8361
zh: cb83602b123a4aae
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-28-api-browser-trust-boundary.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-28-api-browser-trust-boundary.md
2026-07-28-api-browser-trust-boundary.md: 397c93e084f84579ce3f90654f514428e696ffcd
2026-07-28-api-browser-trust-boundary.zh.md: 6d3896fd2c1fd6c607b9d92376eee76ab03df3c7
/agent-note-one-carrier-level-browser-trust-boundary-for-all-api-routes:
en: 491d0faf230d0278
zh: 40c8eef7719fe354
/agent-note-one-carrier-level-browser-trust-boundary-for-all-api-routes/problem:
en: c25db2ef111b2276
zh: 557891ca9e030ae5
/agent-note-one-carrier-level-browser-trust-boundary-for-all-api-routes/decision:
en: 1a1af1e8125ba4b0
zh: dd6c282651a06af5
/agent-note-one-carrier-level-browser-trust-boundary-for-all-api-routes/alternatives-considered:
en: 1a4b0ae8072e8e50
zh: d469553ad3b5d112
/agent-note-one-carrier-level-browser-trust-boundary-for-all-api-routes/consequences:
en: 8acf5e6f55a747c2
zh: bbd0b10927302965
@@ -1,6 +1,22 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-28-identified-immutable-message-values.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-28-identified-immutable-message-values.md
2026-07-28-identified-immutable-message-values.md: 73c9c14479117cf654d10b3da23d155cca77054d
2026-07-28-identified-immutable-message-values.zh.md: 7a5b9d6524beff01ac8a9e2020f75093271b7ab3
/agent-note-create-every-message-as-an-identified-immutable-value:
en: 0bb4f6acecd9b6f1
zh: 11e17fde272119f1
/agent-note-create-every-message-as-an-identified-immutable-value/problem:
en: 9334a7a325a88fda
zh: c21c8cee318c6a35
/agent-note-create-every-message-as-an-identified-immutable-value/decision:
en: a4434de753a41d41
zh: f16e5cd634245f0e
/agent-note-create-every-message-as-an-identified-immutable-value/alternatives-considered:
en: bf73901dd2b977ed
zh: 5ba5d4d05051b1da
/agent-note-create-every-message-as-an-identified-immutable-value/consequences:
en: 9f2c40ccfcf03ee1
zh: 0e8ba6c97f2e32af
/agent-note-create-every-message-as-an-identified-immutable-value/related:
en: 7c476f1a5195dff9
zh: c878154dbf766e82
@@ -1,6 +1,25 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-28-portable-execution-world-consumers.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-28-portable-execution-world-consumers.md
2026-07-28-portable-execution-world-consumers.md: 5a687a552f322f3929b3f3937caf36c3373c05e7
2026-07-28-portable-execution-world-consumers.zh.md: 6bc0e20bd29d0b0a01068c004655cc90ac3b6699
/agent-note-portable-consumers-over-filesystem-and-subprocess-execution-worlds:
en: 42609904ffe19d80
zh: fcacbf7912df216c
/agent-note-portable-consumers-over-filesystem-and-subprocess-execution-worlds/problem:
en: 959a378a04f28e89
zh: ff496169735b4d7b
/agent-note-portable-consumers-over-filesystem-and-subprocess-execution-worlds/decision:
en: 23eca65b89ae572a
zh: 630d844a7c6438df
/agent-note-portable-consumers-over-filesystem-and-subprocess-execution-worlds/remote-provider-ownership:
en: bde2e1fa8f3aeee0
zh: 42a13bb4cf540d6d
/agent-note-portable-consumers-over-filesystem-and-subprocess-execution-worlds/verification:
en: b34540c3548ea98f
zh: 79e53bda3981802c
/agent-note-portable-consumers-over-filesystem-and-subprocess-execution-worlds/alternatives-considered:
en: a5f455ad35d0615c
zh: df4f501a6d723838
/agent-note-portable-consumers-over-filesystem-and-subprocess-execution-worlds/consequences:
en: 3e8426e4a6788505
zh: 143b8c07d21d95d1
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-29-dsh-source-launch-tsx-esm.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-29-dsh-source-launch-tsx-esm.md
2026-07-29-dsh-source-launch-tsx-esm.md: 700577cb9b137d67f20baeb639f99f4c0877011d
2026-07-29-dsh-source-launch-tsx-esm.zh.md: 4d322d3dcf49442ee62f82203f17bd2ab16467fe
/agent-note-dsh-source-launch-through-the-tsx-esm-hook:
en: 55846ac57e07eeda
zh: 3de03730d4b28863
/agent-note-dsh-source-launch-through-the-tsx-esm-hook/problem:
en: 68385f7e47d3ac1f
zh: 285ca290832e2939
/agent-note-dsh-source-launch-through-the-tsx-esm-hook/decision:
en: 12adf8ed56b4d5c3
zh: fbbb9add935730c0
/agent-note-dsh-source-launch-through-the-tsx-esm-hook/alternatives-considered:
en: c6eec3d899a61df1
zh: 128edd753d49c0da
/agent-note-dsh-source-launch-through-the-tsx-esm-hook/consequences:
en: 7c8eb105520ccae3
zh: 9dc85ecda408de5a
@@ -1,6 +1,22 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-29-projected-token-usage-and-request-context.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-29-projected-token-usage-and-request-context.md
2026-07-29-projected-token-usage-and-request-context.md: 10056ac8ef85562035d4fc4591e90aec603a7dd8
2026-07-29-projected-token-usage-and-request-context.zh.md: 0e4cd68791f0ee65dd700b64493be3c33b78a920
/agent-note-projected-token-usage-and-context-occupancy:
en: 293fcae41011ed29
zh: 9a018a07b6491173
/agent-note-projected-token-usage-and-context-occupancy/problem:
en: 081098cb08ca80aa
zh: f829b6630a68fc3c
/agent-note-projected-token-usage-and-context-occupancy/decision:
en: 231a6f4a4c00dca6
zh: e90c76e425826ca0
/agent-note-projected-token-usage-and-context-occupancy/context-occupancy-is-approximate-and-that-is-the-decision:
en: 9df83c0a48f462d2
zh: 94c2ad19af4b13fc
/agent-note-projected-token-usage-and-context-occupancy/alternatives-considered:
en: 50272313b4f061cc
zh: 1cfd7374e4bdfed9
/agent-note-projected-token-usage-and-context-occupancy/consequences:
en: c7a407dc3964fb9d
zh: b1ac7c53abb5cb09
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-29-terminal-llm-stream-failures.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-29-terminal-llm-stream-failures.md
2026-07-29-terminal-llm-stream-failures.md: c5d160c5dffe6171dd79714f2402f3bd6ca4d3fc
2026-07-29-terminal-llm-stream-failures.zh.md: 297898d8f94ae4f00ab1c5fef192ce633aee99cd
/agent-note-terminal-llm-stream-failures:
en: 6195cb1d9b4dd423
zh: 0c93d3a39e2bc1f4
/agent-note-terminal-llm-stream-failures/problem:
en: 41363fca57ae20e6
zh: 1d05eeeecaafa7f3
/agent-note-terminal-llm-stream-failures/decision:
en: c3bfde5f736f8b27
zh: f51ebb4089df6406
/agent-note-terminal-llm-stream-failures/alternatives-considered:
en: 46153a92b2135aae
zh: 0b8fdaf1f7edeb77
/agent-note-terminal-llm-stream-failures/consequences:
en: 9bf05473682c5cef
zh: b93f32470eb08cf4
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-30-credential-boundaries-and-atomic-registration.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-30-credential-boundaries-and-atomic-registration.md
2026-07-30-credential-boundaries-and-atomic-registration.md: 0e65bb1093bb21c3a0dbee71b4e80ba4276b9d00
2026-07-30-credential-boundaries-and-atomic-registration.zh.md: cbc66efa26065beb54ee1deea0f69221ebd92337
/agent-note-credential-boundaries-whole-snapshot-requests-and-atomic-route-registration:
en: 0b33f9d64be7149a
zh: 365ea54cf9fd4924
/agent-note-credential-boundaries-whole-snapshot-requests-and-atomic-route-registration/problem:
en: 6228c81e4965b688
zh: 04b702be0cfbf195
/agent-note-credential-boundaries-whole-snapshot-requests-and-atomic-route-registration/decision:
en: d2aa88cf1e9ec97b
zh: da9422723fc9ac93
/agent-note-credential-boundaries-whole-snapshot-requests-and-atomic-route-registration/alternatives-considered:
en: 90c5883b247f7301
zh: 6d2a660d8653f805
/agent-note-credential-boundaries-whole-snapshot-requests-and-atomic-route-registration/consequences:
en: 99b678779110e0d1
zh: 5790590caab41e0c
@@ -1,6 +1,22 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-30-followup-enqueue-and-owned-runs.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-30-followup-enqueue-and-owned-runs.md
2026-07-30-followup-enqueue-and-owned-runs.md: c9b3b992dffb39c94b476cd6541b8ec9e2256047
2026-07-30-followup-enqueue-and-owned-runs.zh.md: 7f272484cad4f9d0fd918e5c1b05fb8fcb0384c0
/agent-note-follow-up-enqueue-and-owned-run-boundaries:
en: 30b533c813f80a2c
zh: 5f56ae990ca597f2
/agent-note-follow-up-enqueue-and-owned-run-boundaries/problem:
en: 33387f4ed29e967b
zh: b61ab718327d4cc9
/agent-note-follow-up-enqueue-and-owned-run-boundaries/decision:
en: 9d68149d8090d355
zh: d3efa8ac850603bf
/agent-note-follow-up-enqueue-and-owned-run-boundaries/alternatives-considered:
en: 70a57101ffa08e81
zh: 36c3539ee9c759af
/agent-note-follow-up-enqueue-and-owned-run-boundaries/verification:
en: 4c65688fc0bc1f6c
zh: 04f1fd160e38a69d
/agent-note-follow-up-enqueue-and-owned-run-boundaries/consequences:
en: 7de608183c0bd34d
zh: 598eeb85cfd2993b
@@ -1,6 +1,25 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-30-session-end-seed-log-boundary.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-30-session-end-seed-log-boundary.md
2026-07-30-session-end-seed-log-boundary.md: 9cf7c7f20701688208e8b1c343904f2a9f2cab9e
2026-07-30-session-end-seed-log-boundary.zh.md: fdf4ec9de610f17e792de98334dd5d37f5e4c355
/agent-note-the-end-seed-log-boundary:
en: 0f53ca9c0166d7ad
zh: e16b2376c2afb1bc
/agent-note-the-end-seed-log-boundary/problem:
en: e7192f854b24129c
zh: 74a38ee95988e338
/agent-note-the-end-seed-log-boundary/decision:
en: 519aa4faadd01960
zh: 1430cc9bd81e7df9
/agent-note-the-end-seed-log-boundary/persistence-needs-no-changes:
en: 5df69ed0156e50c8
zh: 9ad6caad6d33b183
/agent-note-the-end-seed-log-boundary/scope-of-the-guarantee:
en: 31c23e4e25640fb1
zh: d207c2a8aa7d936c
/agent-note-the-end-seed-log-boundary/alternatives-considered:
en: cd1ed7dfa77722ae
zh: 4ad834f3cf3b5443
/agent-note-the-end-seed-log-boundary/consequences:
en: 69eb86480b191135
zh: 51ef88fb78701b1f
@@ -1,6 +1,22 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-31-claimed-pre-step-inbox-lifecycle.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# 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-claimed-pre-step-inbox-lifecycle.md
2026-07-31-claimed-pre-step-inbox-lifecycle.md: 3ebb73279e49c2aaffa05bea647fa3f93ba6a36f
2026-07-31-claimed-pre-step-inbox-lifecycle.zh.md: 809470e5b52b29cdcbe7b4d81bb584b476f5cfce
/agent-note-claim-inbox-input-before-one-pre-step-decision:
en: 4ee4c56f27c9bf27
zh: 72321b4c735e106f
/agent-note-claim-inbox-input-before-one-pre-step-decision/problem:
en: f2a920b8770c2f99
zh: 1c111f175131714e
/agent-note-claim-inbox-input-before-one-pre-step-decision/decision:
en: 2e58afbd8ffbce60
zh: 40e0c0e3d24fc7ad
/agent-note-claim-inbox-input-before-one-pre-step-decision/alternatives-considered:
en: 03496db1c0547f71
zh: c0932cfcb5d5d93b
/agent-note-claim-inbox-input-before-one-pre-step-decision/verification:
en: 007a79d6db18cbab
zh: 611306fcb5edfda0
/agent-note-claim-inbox-input-before-one-pre-step-decision/consequences:
en: ba68c3ce7ed64bcc
zh: 8fe29186526b258a
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-31-goal-owned-durable-events.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# 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-goal-owned-durable-events.md
2026-07-31-goal-owned-durable-events.md: 0d3e632ba275f38e48fdf1f9ee6747f4bc460aab
2026-07-31-goal-owned-durable-events.zh.md: fd29a6f36eed42f5ba26a46a32acb165d1e42873
/agent-note-goal-owned-durable-events:
en: a8fca44de335547c
zh: e0cc7072f2247a19
/agent-note-goal-owned-durable-events/problem:
en: 882023626c792880
zh: 1966501718e96f92
/agent-note-goal-owned-durable-events/decision:
en: cc99d9ce1f6ebb9a
zh: 34e519f16d8d5e3e
/agent-note-goal-owned-durable-events/alternatives-considered:
en: 7d79dfa834d9168f
zh: 0b3e82a7d0ef71b9
/agent-note-goal-owned-durable-events/consequences:
en: 0e4513ea5e3e1e2e
zh: 69d81ba52ee2f4b6
@@ -1,6 +1,25 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-07-31-ptc-runtime-python-fd3-protocol.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# 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-ptc-runtime-python-fd3-protocol.md
2026-07-31-ptc-runtime-python-fd3-protocol.md: 097bcfd55f333a0973084f378a6c97cb630a4bec
2026-07-31-ptc-runtime-python-fd3-protocol.zh.md: ac656e421bd822994c50c33d0dfaf65ae46aa817
/agent-note-the-ptc-runtime-python-fd-3-frame-protocol:
en: fc43bcfc72cc4476
zh: c81279cb0da1481c
/agent-note-the-ptc-runtime-python-fd-3-frame-protocol/problem:
en: 2c36946bbff637b7
zh: f290de0866ba7caa
/agent-note-the-ptc-runtime-python-fd-3-frame-protocol/decision:
en: 1f93159850fc7f48
zh: dcc2a4788e3254f7
/agent-note-the-ptc-runtime-python-fd-3-frame-protocol/wire-contract:
en: 913f9465320dc191
zh: f8e0338645d6c204
/agent-note-the-ptc-runtime-python-fd-3-frame-protocol/mirror-alignment:
en: 26128b65f2763920
zh: df24359faebcbfed
/agent-note-the-ptc-runtime-python-fd-3-frame-protocol/alternatives-considered:
en: cc42636bd7793305
zh: e196f980daec3037
/agent-note-the-ptc-runtime-python-fd-3-frame-protocol/consequences:
en: 16df6efd46d71e85
zh: 4062475bec04ab5f
@@ -1,6 +1,76 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-08-02-typert-remote-method-calls.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-08-02-typert-remote-method-calls.md
2026-08-02-typert-remote-method-calls.md: b599b3f9a353738bbb44a4da9b5a72be8309e2fb
2026-08-02-typert-remote-method-calls.zh.md: 64dc84f0ae07b10d50452ef7e36c30db102953cf
/agent-note-typert-gateway-targeted-method-calls:
en: 4d77bacdc36f246b
zh: b884bf274df490af
/agent-note-typert-gateway-targeted-method-calls/problem:
en: 14a83a0440499136
zh: 15587f8e821c5a17
/agent-note-typert-gateway-targeted-method-calls/decision:
en: 44d946b53496974c
zh: 403447c25a5b2d7c
/agent-note-typert-gateway-targeted-method-calls/components-and-cordis-services:
en: aa7f509189ade32e
zh: ef2841bc793f31b2
/agent-note-typert-gateway-targeted-method-calls/business-declarations:
en: c6b70d442b137d2e
zh: 6d0dbefe89937ef1
/agent-note-typert-gateway-targeted-method-calls/decorators-and-the-explicit-gateway-facet:
en: 155afbe4b8af600b
zh: 14705698a9cdbd84
/agent-note-typert-gateway-targeted-method-calls/lookup-and-remote-scope-registration:
en: 9f7448898cf5cadc
zh: 419573c589ed6f7d
/agent-note-typert-gateway-targeted-method-calls/invocationdescriptor:
en: aad682229b400d49
zh: 60c2857fca1f4b2b
/agent-note-typert-gateway-targeted-method-calls/typert-runtime-registry:
en: 14ad652e20e699ca
zh: 9272bc04a35e3c6a
/agent-note-typert-gateway-targeted-method-calls/canonical-types-symbols-and-zod:
en: a244f6a88fdabf3d
zh: e4feedb7297f4865
/agent-note-typert-gateway-targeted-method-calls/three-artifact-kinds-and-two-typescript-programs:
en: 6ea4bddcf35a834d
zh: 4af474c6818b1cf0
/agent-note-typert-gateway-targeted-method-calls/the-remote-package-entry:
en: 75e977fe0fb71d59
zh: 00760c79da173cb7
/agent-note-typert-gateway-targeted-method-calls/strict-consumer-api-types:
en: 983f55c0ed4a8edc
zh: 5a736e00e4b57e6a
/agent-note-typert-gateway-targeted-method-calls/client-typert-and-the-api-gateway-client-face:
en: 9dc732c13ffaee63
zh: 4977aaef0856956d
/agent-note-typert-gateway-targeted-method-calls/cross-environment-isomorphism-constraints:
en: 5d14e1b7afc53efb
zh: e2f4b5814083738f
/agent-note-typert-gateway-targeted-method-calls/src-and-lib-operating-modes:
en: 1e366dcfab74831b
zh: 14199f25f20a9352
/agent-note-typert-gateway-targeted-method-calls/host-gateway-resolution:
en: 88a95d7ab4621caf
zh: 89b63fb6440fca79
/agent-note-typert-gateway-targeted-method-calls/the-shared-api-call-chain:
en: 391a59d0ba24cb34
zh: b7294d6bb5f9d297
/agent-note-typert-gateway-targeted-method-calls/connection-and-protocol-boundaries:
en: e8f9d48c42e27fb6
zh: 445bc192d67c71f1
/agent-note-typert-gateway-targeted-method-calls/package-boundaries:
en: df2c448d3a0680eb
zh: 47327d4d26ec5887
/agent-note-typert-gateway-targeted-method-calls/shipped-scope-and-deferred-work:
en: b1c0c3dd77c56ce8
zh: 769ffd4aeefd949c
/agent-note-typert-gateway-targeted-method-calls/alternatives-considered:
en: 0d68c499b7780f4f
zh: bdd1e57232b996e2
/agent-note-typert-gateway-targeted-method-calls/verification:
en: 7433bdb522bb2083
zh: 545c17613b636f00
/agent-note-typert-gateway-targeted-method-calls/consequences:
en: c3459afdb606cfbe
zh: ec69f2bb39170a7c
@@ -31,8 +31,8 @@ The Remote consumer projection contains `.d.ts`, `.d.ts.map`, and `.js` files. T
| `@deepseek-ai/dsh-typert-protocol` | Declares only the minimal `ctx.typert` protocol | `TypertRemoteService`, decorators, binding fallback, descriptors, lookup/Context, and the Remote map; no dependency on the compiler, Zod, Connection, or Browser |
| Typert registry | `ctx.typert` | Separately stores reflection for the current environment, imported Remote contributions, lookup providers, and Context providers |
| Typert generator/loader | No new business service | Generates three kinds of `lib` artifacts from the Host/Client Programs and registers the current environment's artifacts with `ctx.typert` |
| API Gateway's Host face | `ctx.typertGateway` | Associates Host definitions with live Services, decodes parameters, resolves receivers, and invokes methods |
| Connection | `ctx.connection` | Exclusively owns the HTTP Server/future WebSocket, the shared `/api` route, RPC envelope, rpcId, serialization, trust, error transport, Typert interception, and owner-registered exact Fetch routes on the same channel |
| API Gateway's Host face | `ctx.typertGateway` | Associates Host definitions with live Services, decodes parameters, resolves receivers, invokes methods, and projects unary results into carrier-neutral fields and attachments |
| Connection | `ctx.connection` | Exclusively owns the HTTP Server/future WebSocket, the shared `/api` route, RPC envelope, rpcId, physical serialization, trust, error transport, Typert interception, and owner-registered exact Fetch routes on the same channel |
| API Gateway's Client face | `ctx.remote`, `ctx.remote.<namespace>` | Mounts Remote contributions, materializes each namespace as a traced `remote.<namespace>` child Service, and delegates canonical calls to `ctx.connection.rpc` |
| API Remotes | No new service | Owns Host Agent/Session lookup policy and serves as the only Client business facade, selecting and mounting `/remote` contributions while exposing the selected API declarations |
| Agent/Session owning packages | Existing domain services | Provide both static interface merges and runtime lookup/Context providers |
@@ -181,7 +181,7 @@ Consequently, `SessionId`, the Agent wire ID, the request, and the result all re
Remote methods themselves use declaration-map navigation. Typert anchors `InvocationModel.location` to the decorated Host method-name token and emits a source-map segment on the corresponding property of the namespace interface. For an adapter-backed endpoint, after the TypeScript editor resolves `ctx.remote.models.list` to its generated declaration, `typert.remote-client.d.ts.map` takes it to the Host Service's `remoteExportList` entry point. That entry point explicitly calls the existing, unrenamed `list()` method; the map does not misidentify the decorator, class, or full signature as the method definition.
Typert generates a wire Zod codec for the same symbol key. The Host Gateway uses parameter and identity codecs to validate input. Client Remote trusts its generated TypeScript arguments and successful Host results instead of executing invocation codecs. If a complex type cannot produce a strict codec, the LIB build fails instead of degrading to `unknown` or unchecked JSON.
Typert generates a wire Zod codec for the same symbol key. The Host Gateway uses parameter and identity codecs to validate input. Client Remote trusts its generated TypeScript arguments and JSON success results. Binary success results use their generated codec after multipart decoding, as specified by [binary Remote transfer](2026-09-17-workspace-file-binary-transfer.md). If a complex type cannot produce a strict codec, the LIB build fails instead of degrading to `unknown` or unchecked JSON.
Named business types referenced by Remote methods must be exported from public, type-only subpaths. If the only reachable entry also imports Host Services, Cordis `Context` merges, or Host-only implementations, the build fails and requires the business package to provide a safe type entry. Primitives, literals, and simple compositions explicitly supported by Typert need no additional names.
@@ -514,7 +514,7 @@ Canonical public types require business DTOs to have type-only entries, which ma
Type imports and runtime contributions have different effects. `import type {}` extends only the static Remote surface. If a real calling environment omits the value contribution, the Client Remote Service must fail with an explicit "Remote not mounted" error.
Generated Host and Client artifacts carry matching Zod factories, but Client Remote does not materialize invocation schemas. Canonical symbol keys, the same generated model, and Host wire validation keep the two sides aligned without comparing schema object identities across realms.
Generated Host and Client artifacts carry matching Zod factories; Client Remote materializes only binary result schemas. Canonical symbol keys, the same generated model, and Host wire validation keep the two sides aligned without comparing schema object identities across realms.
A consumer may import a Remote contract that is not currently mounted on the Host. The types mean "this protocol capability was selected by the consumer," not that a corresponding Service currently exists in the target process; an unavailable endpoint must fail explicitly at runtime.
@@ -31,8 +31,8 @@ Remote 消费端投影同时包含 `.d.ts`、`.d.ts.map` 和 `.js`。`.d.ts` 只
| `@deepseek-ai/dsh-typert-protocol` | 只声明 `ctx.typert` 的最小协议 | `TypertRemoteService`、decorator、binding 回退、descriptor、lookup/Context 和 Remote map;不依赖 compiler、Zod、Connection 或 Browser |
| Typert registry | `ctx.typert` | 分开保存当前环境 reflection、导入的 Remote contribution、lookup provider 和 Context provider |
| Typert generator/loader | 无新增业务服务 | 从 Host/Client Program 生成三类 `lib` 产物,并把当前环境产物注册到 `ctx.typert` |
| API Gateway 的 Host face | `ctx.typertGateway` | 关联 Host definition 与活 Service,解码参数、解析 receiver 并调用方法 |
| Connection | `ctx.connection` | 独占 HTTP Server/未来 WebSocket、共享 `/api` route、RPC envelope、rpcId、序列化、trust、错误传输、Typert 拦截,以及各 owner 在同一 channel 上注册的精确 Fetch route |
| API Gateway 的 Host face | `ctx.typertGateway` | 关联 Host definition 与活 Service,解码参数、解析 receiver、调用方法,并将一元结果投影为载体无关的字段与附件 |
| Connection | `ctx.connection` | 独占 HTTP Server/未来 WebSocket、共享 `/api` route、RPC envelope、rpcId、物理序列化、trust、错误传输、Typert 拦截,以及各 owner 在同一 channel 上注册的精确 Fetch route |
| API Gateway 的 Client face | `ctx.remote`、`ctx.remote.<namespace>` | mount Remote contribution,把每个 namespace 实体化为可追踪的 `remote.<namespace>` 子 Service,并把规范调用交给 `ctx.connection.rpc` |
| API Remotes | 无新增服务 | 负责 Host Agent/Session lookup 策略,并作为 Client 业务的唯一 facade,选择并挂载 `/remote` contribution,同时暴露所选 API 声明 |
| Agent/Session owning 包 | 既有领域服务 | 同时提供静态 interface merge 与运行时 lookup/Context provider |
@@ -181,7 +181,7 @@ import type { CreateGoalRequest, CreateGoalResult } from '@deepseek-ai/dsh-goal/
Remote 方法本身使用 declaration map 导航。Typert 把 `InvocationModel.location` 固定在 Host 被装饰方法的方法名 token,并在 namespace interface 的对应属性上写入 source-map segment。对于由适配器支撑的 endpoint,TypeScript editor 从 `ctx.remote.models.list` 取得生成 declaration 后,再沿 `typert.remote-client.d.ts.map` 跳到 Host Service 的 `remoteExportList` 远程出口。该出口继续显式调用不改名的存量 `list()`,map 不把 decorator、class 或整个签名误当成方法定义位置。
Typert 为同一 symbol key 生成 wire Zod codec。Host Gateway 用参数与 identity codec 校验输入;Client Remote 信任生成的 TypeScript 参数与成功的 Host 结果,不执行调用 codec。复杂类型无法生成严格 codec 时,LIB 构建失败,不降级为 `unknown` 或无校验 JSON。
Typert 为同一 symbol key 生成 wire Zod codec。Host Gateway 用参数与身份 codec 校验输入。Client Remote 信任生成的 TypeScript 参数与 JSON 成功结果。二进制成功结果在 multipart 解码后执行生成的结果 codec,具体由[二进制 Remote 传输](2026-09-17-workspace-file-binary-transfer.zh.md)规定。复杂类型若无法生成严格 codec,LIB 构建失败,不降级为 `unknown` 或未校验 JSON。
Remote 方法引用的命名业务类型必须从纯类型公共 subpath 导出。如果唯一可达入口会带入 Host Service、Cordis `Context` merge 或 Host-only 实现,构建失败并要求业务包提供安全的类型出口。原始值、字面量和 Typert 明确支持的简单组合不需要额外命名。
@@ -514,7 +514,7 @@ SRC 弱 descriptor 不验证普通 JSON 内部结构。Host Remote 签名变化
类型 import 与运行时 contribution 是两种不同效果。`import type {}` 只扩展静态 Remote surface;真实调用环境遗漏 value contribution 时,Client Remote Service 必须以明确的「Remote 未挂载」错误失败。
生成的 Host 与 Client 产物携带匹配的 Zod factory,但 Client Remote 不实例化调用 schema。规范 symbol key、同一生成模型和 Host wire 校验让两侧保持一致,而无需跨 realm 比较 schema 对象 identity。
生成的 Host 与 Client 产物携带匹配的 Zod factory;Client Remote 仅实例化二进制结果 schema。规范 symbol key、同一生成模型和 Host wire 校验让两侧保持一致,而无需跨 realm 比较 schema 对象 identity。
消费端可以导入 Host 当前未挂载的 Remote contract。类型表示「该协议能力已被消费端选择」,不保证目标进程当前存在对应 Service;运行时 endpoint 不可用必须明确失败。
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-08-04-configuration-source-ownership.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-08-04-configuration-source-ownership.md
2026-08-04-configuration-source-ownership.md: 6dea1f08a9f2a0319f894a504082ff70bbe1118f
2026-08-04-configuration-source-ownership.zh.md: 1ccf2c266c3e52f2f10d3bceb3b1505ae6266b15
/agent-note-one-ordering-for-configuration-sources-and-what-a-discovered-file-may-not-decide:
en: 1f6ee603f36c2e09
zh: e08197958663219c
/agent-note-one-ordering-for-configuration-sources-and-what-a-discovered-file-may-not-decide/problem:
en: d94bb81479bfa4a1
zh: af44ceaecf84ee51
/agent-note-one-ordering-for-configuration-sources-and-what-a-discovered-file-may-not-decide/decision:
en: aea80ece13f2905b
zh: a880bc1a7839cf12
/agent-note-one-ordering-for-configuration-sources-and-what-a-discovered-file-may-not-decide/consequences:
en: 640b7ee4e8c57ed0
zh: 1c17b3fba16861a8
/agent-note-one-ordering-for-configuration-sources-and-what-a-discovered-file-may-not-decide/alternatives-considered:
en: ac43499cfe7b8495
zh: e5ab599e7d3ed753
@@ -4,6 +4,8 @@ Status: implemented
English | [中文](2026-08-04-configuration-source-ownership.zh.md)
The non-secret settings tier below is superseded by [profile-owned live configuration](2026-09-19-profile-owned-live-configuration.md). Credential ordering and environment restrictions remain current.
## Problem
`$DSH_HOME/.env` had just [become an ordinary environment layer](../../archived/architecture/2026-08-04-credentials-yaml-and-user-environment-layer.md), which left the harness resolving user-facing values from a flattened `process.env` that could no longer say where a value came from. Three consequences followed.
@@ -4,6 +4,8 @@ Status: implemented
[English](2026-08-04-configuration-source-ownership.md) | 中文
下文的非秘密 settings 层已由 [profile 所属实时配置](2026-09-19-profile-owned-live-configuration.zh.md) 替代。凭据优先级与环境限制仍然适用。
## Problem
`$DSH_HOME/.env` 刚刚[变成普通环境层](../../archived/architecture/2026-08-04-credentials-yaml-and-user-environment-layer.md),这使得 harness 解析面向用户的值时面对的是一个压平的 `process.env`,再也说不清某个值来自哪里。由此产生三个后果。
@@ -1,6 +1,25 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-08-04-draft-provider-endpoint-interrogation.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-08-04-draft-provider-endpoint-interrogation.md
2026-08-04-draft-provider-endpoint-interrogation.md: 469ab38b0f5609808a9df03237d4d21c0080d843
2026-08-04-draft-provider-endpoint-interrogation.zh.md: 74c6bc7ed73572d5e99ea973c9ea94d22319cbdf
/agent-note-interrogating-a-draft-provider-endpoint:
en: a465a218bbc2f74e
zh: 60d1eae3c79337a0
/agent-note-interrogating-a-draft-provider-endpoint/problem:
en: c50e44492b4b30a2
zh: 74a17b3d3ec6cf0d
/agent-note-interrogating-a-draft-provider-endpoint/decision:
en: dc323940d59008f4
zh: fc94284fcda71542
/agent-note-interrogating-a-draft-provider-endpoint/decision/why-not-pi-ai-s-own-refresh-machinery:
en: a9654499e32c91b3
zh: cfb5a76500b6fe1a
/agent-note-interrogating-a-draft-provider-endpoint/alternatives-considered:
en: 3b4b4c33401d862a
zh: bb79062a431576f1
/agent-note-interrogating-a-draft-provider-endpoint/consequences:
en: a4911a205e713f60
zh: 04adc6be1f4f34c7
/agent-note-interrogating-a-draft-provider-endpoint/testing:
en: 40cf0cf6141eba6e
zh: 54a6097cf125b846
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-08-05-profile-plugin-bundles.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-08-05-profile-plugin-bundles.md
2026-08-05-profile-plugin-bundles.md: 0607f1c9a2414cc16515967b4520da8a325853fd
2026-08-05-profile-plugin-bundles.zh.md: 9d25d3bea6337c472d161c721e44a66dca8470c9
/agent-note-profile-plugin-bundles-replace-the-fixed-surface-overlays:
en: 178252acff6e206f
zh: 2e5785ca3485f1e7
/agent-note-profile-plugin-bundles-replace-the-fixed-surface-overlays/problem:
en: 504dd5f06475d707
zh: 6557fd5649f48944
/agent-note-profile-plugin-bundles-replace-the-fixed-surface-overlays/decision:
en: 4c58d379cd59d879
zh: a6b6322fe82d7b6a
/agent-note-profile-plugin-bundles-replace-the-fixed-surface-overlays/alternatives-considered:
en: d906d7a421c6b5c0
zh: b230cd58c1b7ac79
/agent-note-profile-plugin-bundles-replace-the-fixed-surface-overlays/consequences:
en: 1aef147a0f31dfaf
zh: f0a8c6cbb9f0506b
@@ -1,6 +1,94 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-08-09-client-conversation-node-assembly.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-08-09-client-conversation-node-assembly.md
2026-08-09-client-conversation-node-assembly.md: bb1d68cc045710d46a44ffb295c2307628338521
2026-08-09-client-conversation-node-assembly.zh.md: 6291211d589b3389e7dc9a42d15fe6ac0d9e7ab9
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots:
en: 32abbd757c29e1ee
zh: ea0b9de97fd04196
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/problem:
en: ebdd3ce57ca5b24d
zh: 1aa034b4c3ed515f
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/decision:
en: af502b4eb9c09d33
zh: a20cd538e66d3a4b
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/decision/responsibility-layers:
en: 36b54ef989c331af
zh: 58cad4e07a800ba9
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/decision/overall-conversationnodedefinition-contract:
en: 74f17ca7ae05af83
zh: 591fbc6c98f90262
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/decision/overall-conversationnodedefinition-contract/kind-business-id-and-context-key:
en: 3081736d55350c67
zh: bfa89f127c16c59f
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/decision/overall-conversationnodedefinition-contract/match-event:
en: 5c97a2a4e91325a7
zh: d29e52647b699810
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/decision/overall-conversationnodedefinition-contract/conversationmatch:
en: 616c50e24ab990d1
zh: 2c4a6d129f491046
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/decision/overall-conversationnodedefinition-contract/conversationnodecontext:
en: 7d1ce8db92084e90
zh: 7b7e6bf3840f6986
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/decision/overall-conversationnodedefinition-contract/start-context-match-reader:
en: 1167bbc860581e33
zh: 549896c06507ce57
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/decision/overall-conversationnodedefinition-contract/reader-previous-kind:
en: 48e127652f2dab8d
zh: 35f48d4cefc8ce52
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/decision/overall-conversationnodedefinition-contract/update-context-match:
en: 66bd752825ad2c41
zh: 1cec352eb3d7ab28
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/decision/overall-conversationnodedefinition-contract/publication-match:
en: 43be4c019d79e37a
zh: 54978ef8317e777b
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/decision/overall-conversationnodedefinition-contract/buildlocationdata-context-scope:
en: 8c2b8eab071f5f7b
zh: d3207b1fcfff0a4b
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/decision/overall-conversationnodedefinition-contract/buildviewnode-context-target:
en: c8091375cf986eaa
zh: 0c3226e3f42e51e4
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/decision/overall-conversationnodedefinition-contract/no-generic-end:
en: d5a57346207b0da3
zh: cb4a4f22ce237c34
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/decision/location-is-a-first-class-engine-fact:
en: c66d870529588ea6
zh: c9af12feb1e3fae2
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/three-input-window-paths:
en: cc8d60a4ceba6f41
zh: 552220db9f839429
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/three-input-window-paths/initial-history-tail-and-logical-backward-scanning:
en: a777deacfd73ed3f
zh: 2a9c75dd0aeedcd5
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/three-input-window-paths/prepending-a-newly-loaded-older-page:
en: 3aa4c0a9006b35e8
zh: 9627f4aaa18c8066
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/three-input-window-paths/forward-live-append:
en: 484172cce965aad7
zh: 15fffdd32c66cc95
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/three-input-window-paths/consistency-across-replace-prepend-and-append:
en: a9cf356610f46a53
zh: abc1149bf06b230e
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/how-built-in-businesses-use-definitions:
en: 2a7cae3607dcbc1a
zh: 86f6d8eb7871e253
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/how-built-in-businesses-use-definitions/matching-id-and-state:
en: 130f5db917574545
zh: 9bf13c96abdc3a4e
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/how-built-in-businesses-use-definitions/chat-node-and-history-live-behavior:
en: 0c52c9ae98f84a86
zh: d1c7587ad427d8fc
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/view-builder-and-react-identity:
en: ced7ab385e5a81a8
zh: 5c319ed7ca40e5b8
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/runtime-and-render-path:
en: 114ca8db361d22e5
zh: 37b6d474e855c187
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/verification:
en: cf36507c86d1139c
zh: 1fcdd4e2c2cc106b
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/alternatives-considered:
en: e150870d4e2525ed
zh: 34eafb435036af9a
/agent-note-client-conversation-business-node-assembly-and-keyed-chat-snapshots/consequences:
en: 0da343d3b6b29da3
zh: d7b3774a23be7311
@@ -14,6 +14,8 @@ Business events also use different correlation models. Tool has call IDs, Assist
## Decision
The [three-stage Tool lifecycle](2026-09-22-tool-call-three-phases.md) owns transient initialization, repeated start matches for one ID, and tool preparation; this record's other node-assembly responsibilities remain applicable.
Client Runtime provides a target-neutral Conversation Node assembly engine. Business plugins register Event Definitions, and view plugins register per-Session View Builders. `ui-conversation` registers the first built-in Definitions and the `chat` builder; Session only submits the current contiguous `SessionEventLikeEntry` window to the engine and publishes its snapshot instead of interpreting individual conversation businesses. The entry's outer discriminator distinguishes standard and packed records, while both carry an aligned inner `SessionEventLike` for Definition dispatch.
This Note retains the derivation, business-by-business validation, responsibilities, algorithms, and trade-offs that remain relevant after implementation.
@@ -14,6 +14,8 @@ Client Session 既维护传输窗口、连接状态和待处理交互,也在
## 决策
start 的瞬态创建入口、同 ID 多次 start 及工具准备阶段以[工具调用三阶段](2026-09-22-tool-call-three-phases.zh.md)为准;本记录的其他节点组装职责继续适用。
Client Runtime 提供 target-neutral 的 Conversation Node 组装引擎,业务插件注册 Event Definition,视图插件注册 per-Session View Builder。`ui-conversation` 注册第一批内建 Definition 和 `chat` builder;Session 只负责把当前连续 `SessionEventLikeEntry` window 送入引擎并发布它的 snapshot,且不解释具体 conversation 业务。entry 的外层 discriminator 区分标准与 packed record,两者都携带字段对齐的内部 `SessionEventLike`,供 Definition dispatch。
本 Note 保留实现后仍有价值的方案推导、逐业务适配、职责、算法和取舍。
@@ -1,6 +1,22 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-08-10-cancelled-stream-prefix-finalize.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-08-10-cancelled-stream-prefix-finalize.md
2026-08-10-cancelled-stream-prefix-finalize.md: 1e6fe59bcc1b323941b69d0e9232f0bcf9e56f53
2026-08-10-cancelled-stream-prefix-finalize.zh.md: 7aa81f179b80925ef47a8820f8a80c1ef37ec5ea
/agent-note-cancelled-streams-finalize-their-delivered-prefix:
en: d727a01958e5724c
zh: b2d11741f70caf24
/agent-note-cancelled-streams-finalize-their-delivered-prefix/problem:
en: 142c716d174403a5
zh: bbb906ca25d7c9f4
/agent-note-cancelled-streams-finalize-their-delivered-prefix/decision:
en: 28e166977c0dffde
zh: d7c6b175984627fc
/agent-note-cancelled-streams-finalize-their-delivered-prefix/alternatives-considered:
en: ca4363e11e8eff48
zh: 834152cbe57e1f3e
/agent-note-cancelled-streams-finalize-their-delivered-prefix/consequences:
en: 2d58504acfc4fffe
zh: a6a7ca872c003099
/agent-note-cancelled-streams-finalize-their-delivered-prefix/testing:
en: 241507aff996c16a
zh: 599eed3162f3ba8d
@@ -1,6 +1,22 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-08-10-fork-children-stay-one-shot.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-08-10-fork-children-stay-one-shot.md
2026-08-10-fork-children-stay-one-shot.md: 0edf6ca9347dcf57313365e570daed22589f69fd
2026-08-10-fork-children-stay-one-shot.zh.md: c2e3504bd21ec6dd6b3feba4ed8abdaec3ee45a4
/agent-note-forked-children-preserve-the-parent-request-prefix:
en: 5254ea4573dedd96
zh: ba4ab4517dad0d9f
/agent-note-forked-children-preserve-the-parent-request-prefix/problem:
en: 1fe344c95a0de36d
zh: 656c3e0f1117f64e
/agent-note-forked-children-preserve-the-parent-request-prefix/decision:
en: 7461852090348b34
zh: ad6c9e0ce65a3e85
/agent-note-forked-children-preserve-the-parent-request-prefix/alternatives-considered:
en: 80504ffd8331e6c5
zh: 193261bdde24b4bb
/agent-note-forked-children-preserve-the-parent-request-prefix/consequences:
en: 54c4ce3ee0fee4d2
zh: 8a63fb3486c76551
/agent-note-forked-children-preserve-the-parent-request-prefix/consequences/accepted-risks:
en: f634caa9973eaedb
zh: 820291096c8e7352
@@ -1,6 +1,22 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-08-10-host-plane-ownership-after-presets.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-08-10-host-plane-ownership-after-presets.md
2026-08-10-host-plane-ownership-after-presets.md: 78410368cdc66b14fe478a4de9f0ae7a1cbefac5
2026-08-10-host-plane-ownership-after-presets.zh.md: 862b793fab23b209f6f43b2e8045ad7330c30ba0
/agent-note-what-stays-host-plane-once-presets-own-the-agent-plane:
en: 4b22d7def09af6eb
zh: 89b43fb2761cb17b
/agent-note-what-stays-host-plane-once-presets-own-the-agent-plane/problem:
en: 5a5d4de7d40ed86b
zh: abfae08f9c291c54
/agent-note-what-stays-host-plane-once-presets-own-the-agent-plane/decision:
en: 60be2f515ff5f46d
zh: ee8514deadb08260
/agent-note-what-stays-host-plane-once-presets-own-the-agent-plane/testing:
en: a7b7ca354607dd21
zh: f88356bfc7dc770e
/agent-note-what-stays-host-plane-once-presets-own-the-agent-plane/alternatives-considered:
en: eac46307265e647d
zh: acfad02f8ca1dc3f
/agent-note-what-stays-host-plane-once-presets-own-the-agent-plane/consequences:
en: d8576d7db9dea547
zh: 428bb5a7e609d170
@@ -6,7 +6,7 @@ English | [中文](2026-08-10-host-plane-ownership-after-presets.zh.md)
## Problem
[Per-session agent presets](2026-08-03-per-session-agent-presets.md) moved every model-facing row onto the agent plane, and each later fix has been one reader that assumed the world before the move. `tasks` came back to the host because a preset row outside its realm resolved it; `goals` never left for the same reason; a child agent's `toolFilter` was repaired once every model-facing tool became an ancestor contribution rather than a global one ([child agents join their parent's preset](../bug-fix/2026-08-10-child-agents-join-their-parent-preset.md)).
[Per-session agent presets](2026-09-18-declarative-agent-presets.md) moved every model-facing row onto the agent plane, and each later fix has been one reader that assumed the world before the move. `tasks` came back to the host because a preset row outside its realm resolved it; `goals` never left for the same reason; a child agent's `toolFilter` was repaired once every model-facing tool became an ancestor contribution rather than a global one ([child agents join their parent's preset](../bug-fix/2026-08-10-child-agents-join-their-parent-preset.md)).
Two more readers were still on the wrong side of that line.
@@ -18,15 +18,15 @@ Nothing named an agent that joined no preset. The join is a scope-parent link; w
**The meter is host-plane.** `dsh-token-meter` returns to the host composition and leaves the presets' `isolate` map, so `compaction-basic` and `tool-result-pruner` resolve the one host instance from inside their realm. The presets keep the realm and the backend — what a preset chooses is whether its agent compacts, not whether its tokens are counted. This is the criterion `tasks` and `goals` are already read by, applied to a Service whose *projection* reach is what made preset ownership wrong: a unit whose empty value is indistinguishable from a real one cannot be per-composition while the table it registers into is per-process.
**An unjoined agent is named twice, at two different points.** `AgentPresets` logs one warning per agent published with a scope chain of length one while a roster is configured. The invariant companion fails instead — and at `system-prompt/assemble`, not at publication, because an unjoined agent is legal until it addresses a model: `recompose` binds exactly such an agent as its first link, and prompt assembly is the only caller that supplies an agent scope, so a host assembly and a standing mount are both correctly out of range.
**An unjoined agent fails at model use.** The invariant companion checks `system-prompt/assemble`, because a bare Agent can legally be bound later through `recompose`. Host-only and cold-scope prompt reads have no Agent and remain outside this check.
Three limits stay open and are recorded where they bite rather than fixed here: projection key presence is not a per-session capability signal ([`dsh-session-projection`](../../../../packages/session/session-projection/README.md)); a superseded standing generation is never reclaimed, which the settings-page authoring flow turns into a per-save cost ([`dsh-agent-presets`](../../../../packages/preset/agent-presets/README.md)); and a temporary plugin mounted through `cordis_mount` belongs to the composition rather than the session that mounted it ([`dsh-tool-cordis`](../../../../packages/extensions/tool-cordis/README.md)).
Projection key presence is not a per-session capability signal ([session projection](../../../../packages/session/session-projection/README.md)). Temporary plugins mounted through `cordis_mount` belong to the composition rather than the invoking session ([tool Cordis](../../../../packages/extensions/tool-cordis/README.md)). [Declarative presets](2026-09-18-declarative-agent-presets.md) own revision retention and reclaim retired trees after their final reference releases.
## Testing
`apps/cli/tests/web-agent-presets.e2e.ts` reads `ctx.get('tokenMeter')` on the booted Web composition before any preset in the file mounts — a preset-side meter sits behind an `isolate` realm and is invisible to `ctx.get`, so the read is an ownership assertion rather than a mount-order coincidence — then asserts a `minimal` session's snapshot carries all three units.
`apps/cli/tests/web-agent-presets.e2e.ts` reads `ctx.get('tokenMeter')` on the booted Web composition before any Agent is created — a preset-side meter sits behind an `isolate` realm and is invisible to `ctx.get`, so the read is an ownership assertion rather than a mount-order coincidence — then asserts a `minimal` session's snapshot carries all three units.
`packages/preset/agent-presets/tests/mount.spec.ts` asserts the warning fires exactly once for a bare agent and not at all for a joined one. `tests/invariant.spec.ts` carries the negative control: an unjoined agent's assembly rejects, while a joined agent's assembly and a scopeless host assembly both pass.
`packages/preset/agent-preset-registry/tests/invariant.spec.ts` rejects an unjoined Agent's assembly and accepts a joined Agent, a Host read and a cold-scope read.
## Alternatives considered
@@ -42,4 +42,4 @@ Three limits stay open and are recorded where they bite rather than fixed here:
The context meter becomes a per-session fact instead of a function of mount history. A preset can no longer opt out of token accounting; no shipped preset did, and `minimal` now says it drops auto-compaction rather than the accounting.
The warning is advisory, so a deployment that adds a roster to the ACP or SDK-server entry points still starts agents with no tools — it just says so once per agent instead of silently. The invariant reaches only compositions that load `dsh-invariants`, which fences package tests and development hosts, not a shipped one.
The invariant reaches compositions loading `dsh-invariants`. Production entry points must compose Agents explicitly; installing the registry alone does not bind them.
@@ -6,7 +6,7 @@ Status: implemented
## 问题
[逐会话 agent preset](2026-08-03-per-session-agent-presets.zh.md) 把每一个面向模型的行搬上了 agent 平面,此后的每一处修复都是一个仍按搬迁之前的世界写成的读取点。`tasks` 因为 realm 之外的 preset 行要解析它而搬回宿主;`goals` 因为同样的理由从未离开;而当所有面向模型的工具都变成祖先贡献之后,子 agent 的 `toolFilter` 也已被修好([子 agent 加入父方 preset](../bug-fix/2026-08-10-child-agents-join-their-parent-preset.zh.md))。
[逐会话 agent preset](2026-09-18-declarative-agent-presets.zh.md) 把每一个面向模型的行搬上了 agent 平面,此后的每一处修复都是一个仍按搬迁之前的世界写成的读取点。`tasks` 因为 realm 之外的 preset 行要解析它而搬回宿主;`goals` 因为同样的理由从未离开;而当所有面向模型的工具都变成祖先贡献之后,子 agent 的 `toolFilter` 也已被修好([子 agent 加入父方 preset](../bug-fix/2026-08-10-child-agents-join-their-parent-preset.zh.md))。
还有两个读取点仍站在这条线的错误一侧。
@@ -18,15 +18,15 @@ Status: implemented
**meter 属于宿主平面。** `dsh-token-meter` 回到宿主组装,并离开各 preset 的 `isolate` 映射,于是 `compaction-basic` 与 `tool-result-pruner` 在自己的 realm 内部解析到那一份宿主实例。preset 保留 realm 与压缩后端——preset 选择的是它的 agent 是否压缩,而不是它的 token 是否被计。这正是 `tasks` 与 `goals` 已经采用的判据,只是这次适用于一个因**投影**触达面而不该归 preset 所有的 Service:当一个单元的空值与真实值无法区分时,只要它注册进的那张表是进程级的,它就不能是逐组装的。
**未加入的 agent 在两个不同的点上被指出两次。** 在配置了名单的前提下,`AgentPresets` 对每个作用域链长度为一就发布的 agent 记录一条警告。invariant 配套则直接失败——并且发生在 `system-prompt/assemble` 而非发布时,因为一个未加入的 agent 在它对模型说话之前都是合法的:`recompose` 绑定的正是这样一个 agent 作为它的首次链接;而提示词组装是唯一会提供 agent 作用域的调用方,因此宿主组装与常驻挂载都正确地落在检查范围之外。
**未加入的 Agent 在使用模型时失败。** 不变量 companion 检查 `system-prompt/assemble`,因为未绑定的 Agent 可以合法地稍后通过 `recompose` 绑定。纯 Host 和历史 scope 提示词读取没有 Agent,不属于此检查范围。
有三处限制不在此处修复,而是记录在会咬到它们的地方:投影 key 是否存在不能当作逐会话的能力信号([`dsh-session-projection`](../../../../packages/session/session-projection/README.zh.md));被替代的常驻代际永不回收,而设置页的编写流程把它变成每次保存的代价([`dsh-agent-presets`](../../../../packages/preset/agent-presets/README.zh.md));通过 `cordis_mount` 挂上的临时插件属于组装而非挂载它的会话([`dsh-tool-cordis`](../../../../packages/extensions/tool-cordis/README.zh.md))。
投影 key 是否存在不能代表逐会话能力([会话投影](../../../../packages/session/session-projection/README.zh.md))。通过 `cordis_mount` 挂载的临时插件属于组装,而非调用会话([Cordis 工具](../../../../packages/extensions/tool-cordis/README.zh.md))。[声明式 preset](2026-09-18-declarative-agent-presets.zh.md) 负责代际保留,在最后一个引用释放后回收退役树。
## 测试
`apps/cli/tests/web-agent-presets.e2e.ts` 在本文件中任何 preset 挂载**之前**,于已启动的 Web 组装上读取 `ctx.get('tokenMeter')`——preset 侧的 meter 会待在 `isolate` realm 里,对 `ctx.get` 不可见,因此这次读取是一次所有权断言而不是挂载顺序的巧合——随后断言一个 `minimal` 会话的快照带齐三个单元。
`apps/cli/tests/web-agent-presets.e2e.ts` 在创建任何 Agent **之前**,于已启动的 Web 组装上读取 `ctx.get('tokenMeter')`——preset 侧的 meter 会待在 `isolate` realm 里,对 `ctx.get` 不可见,因此这次读取是一次所有权断言而不是挂载顺序的巧合——随后断言一个 `minimal` 会话的快照带齐三个单元。
`packages/preset/agent-presets/tests/mount.spec.ts` 断言警告对裸 agent 恰好触发一次、对已加入的 agent 完全不触发。`tests/invariant.spec.ts` 承担负控:未加入 agent 的组装被拒绝,而已加入 agent 的组装与不带作用域的宿主组装都通过。
`packages/preset/agent-preset-registry/tests/invariant.spec.ts` 拒绝未加入的 Agent 组装,并接受已加入的 Agent、Host 读取和历史 scope 读取。
## 考虑过的替代方案
@@ -42,4 +42,4 @@ Status: implemented
context meter 成为逐会话的事实,而不再是挂载历史的函数。代价是 preset 不能再选择不做 token 记账;随附的 preset 没有一个这么做,`minimal` 现在也写明它放弃的是自动压缩而非记账。
那条警告是建议性的,因此给 ACP 或 SDK server 入口加上名单的部署依然会启动没有工具的 agent——只是每个 agent 会说一次,而不再静默。invariant 只触达装载了 `dsh-invariants` 的组装,因此它把关的是包测试与开发宿主,不是随附宿主。
不变量覆盖加载了 `dsh-invariants` 的组装。生产入口必须显式组装 Agent;仅安装注册表不会自动绑定。
@@ -1,6 +1,40 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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:
# Bilingual-pair consistency record for 2026-08-10-remote-event-delivery.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-08-10-remote-event-delivery.md
2026-08-10-remote-event-delivery.md: 1706cc525bd7707874353a6658ec2f52597044a9
2026-08-10-remote-event-delivery.zh.md: ac79642e90791892870c8920e02867faea180b07
/agent-note-remote-event-delivery-ctx-remote-on:
en: 4b64b9fab76b5185
zh: 57a11b8a480a49dd
/agent-note-remote-event-delivery-ctx-remote-on/problem:
en: d3016e40cefe047f
zh: 83e83c25a13383e5
/agent-note-remote-event-delivery-ctx-remote-on/decision:
en: 83f6f48ce1fc517b
zh: abcfcd1c0eb777ea
/agent-note-remote-event-delivery-ctx-remote-on/decision/consumer-contract-dsh-typert-protocol:
en: 8f30b121dd59a3a3
zh: 92a5e0e63936c393
/agent-note-remote-event-delivery-ctx-remote-on/decision/the-allowlist-one-declaration-read-by-both-faces:
en: ce8c2e030baf7049
zh: bb6beb40228e40ae
/agent-note-remote-event-delivery-ctx-remote-on/decision/wire-protocol-api-gateway-remote-mux:
en: 5c89d238a469e79f
zh: d0cf485f0d245e7d
/agent-note-remote-event-delivery-ctx-remote-on/decision/the-apps-web-browser-e2e-belongs-to-the-host-face:
en: a29e07b8013f7f9f
zh: 4f066efa96f2d22f
/agent-note-remote-event-delivery-ctx-remote-on/decision/change-inventory:
en: 49fc44d242a87b69
zh: 42c4c36296849a88
/agent-note-remote-event-delivery-ctx-remote-on/alternatives-considered:
en: b75743ab277c1557
zh: e8e05f41ce1bc2f3
/agent-note-remote-event-delivery-ctx-remote-on/verification:
en: 4ec0e1c76da8d3b6
zh: 23de66f8fc659c15
/agent-note-remote-event-delivery-ctx-remote-on/consequences:
en: c50a0968e3f65df7
zh: 786f33cf1e95dae4
/agent-note-remote-event-delivery-ctx-remote-on/related:
en: b64e771dafa6c05b
zh: 4c2f47884f5a2d19
@@ -195,3 +195,7 @@ The few required Client symbols are mirrored on the test side: `scaffold.ts` exp
- **Capabilities deliberately omitted.** Payload projection and redaction are unsupported, scopes other than Agent are unsupported, and ordinary notifications are not replayed. Recoverable state needs a query, cursor, or opening baseline; a waterfall is replayed only while its original Host invocation remains pending.
- **Some Client packages remain in the Host graph.** Twelve projects, including `connection`, `runtime`, and `ui-slots`, remain reachable through unsplit `directory-picker-browse`/`-native` and `api/gateway → client/connection`. They compile and no longer pull in API Remotes' Client face, so this change does not split them. Direct `dsh-client-runtime/client` imports in two chat e2e files rely on Runtime's current presence in that graph rather than a general guarantee.
- **The package intentionally publishes no invariant companion.** A prior revision asserted delivery form on the live event bus, coupling diagnostics to the allowlist and causing Rolldown to emit a third bundle chunk omitted by the mechanically derived publication list. The Host-face `TypertForwardableEventEntry` assertion already rejects those mismatches at compile time, and the package README records why no independent runtime relation remains.
## Related
- [Remote duplex stream](2026-09-19-remote-duplex-stream.md): every Remote stream carries a Client uplink on the same logical stream; the duplex `$events` listed under its Deferred section replaces the unary `$events/result` path once it lands.
@@ -197,3 +197,7 @@ Client 要求首项是带非空 `clientId` 与 `host.home` 的 `ready`;后续
- **放弃的能力**:不支持投影或脱敏载荷,不支持 Agent 以外的 Scope,也不为普通通知提供重放。需要可靠恢复的状态必须拥有查询、cursor 或 opening baseline;waterfall 只重放仍处于同一次 Host 调用生命周期内的 pending request。
- **仍有 client 包留在 host 图里**:12 个工程(`connection`、`runtime`、`ui-slots` 等)经未拆分的 `directory-picker-browse`/`-native` 与 `api/gateway → client/connection` 仍可达 host 图。它们都能编译且不再牵连 api/remotes 的 client face,因此没有阻塞本次改动;拆分那些包能减少几个,但经评估后不做。两个 chat e2e 直接引 `dsh-client-runtime/client` 依赖 `runtime` 本来就在图里——属偶然而非保证。
- **本包不发布 invariant companion**:早先的修订曾在活事件总线上断言投递形状(`thisArg === null`、`mode === 'emit'`),这让诊断逻辑与名单值耦合,并使 rolldown 把它提成第三个 bundle chunk——而机械推导的发布文件清单并不携带它。Host 面的 `TypertForwardableEventEntry` 断言已在编译期拒绝这些偏离,包 README 也记录了不再存在独立运行时关系的原因。
## 相关
- [Remote 双工流](2026-09-19-remote-duplex-stream.zh.md):所有 Remote 流在同一逻辑流上承载客户端上行;其「后续」列出的双工 `$events` 落地后取代 unary `$events/result` 路径。
Loaded 100 of 5392 files, more files were not shown because too many files have changed in this diff. Show more