Merge remote-tracking branch 'origin/master' into worktree/acp-automation-protocol

# Conflicts:
#	.agents/notes/implemented/architecture/2026-06-14-session-persistence.md
#	.agents/notes/implemented/architecture/2026-06-20-package-hierarchy.md
#	.agents/notes/implemented/architecture/2026-07-02-tool-render-intent-union.md
#	.agents/notes/implemented/feature/2026-06-14-acp-agent-client-protocol.md
#	.agents/notes/implemented/feature/2026-06-14-acp-multi-session.md
#	.agents/notes/implemented/feature/2026-06-18-acp-terminal-and-tool-rendering.md
#	.agents/notes/implemented/feature/2026-07-19-model-facing-goal-tools.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-19-model-facing-goal-tools.md
#	.agents/notes/implemented/feature/2026-07-19-model-facing-goal-tools.zh.md
#	.agents/notes/implemented/simplification/2026-07-04-trim-acp-bridge-unreachable-surface.md
#	docs/architecture.i18n.yaml
#	docs/cookbook/extension-cookbook.i18n.yaml
#	docs/cookbook/extension-cookbook.md
#	docs/cookbook/extension-cookbook.zh.md
#	docs/core-data-structures/approval.md
#	docs/core-data-structures/user-interaction.md
#	docs/event-producer-consumer.md
#	docs/persistence-catalog.md
#	docs/testing.md
#	docs/tool-catalog.md
#	examples/acp-agent/tests/fixtures/live-mode-switching-2026-07-07.session.jsonl
#	examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/stdout.expected.jsonl
#	examples/acp-agent/tests/snapshots/permission-switching/session.jsonl
#	packages/goal/tool-goal/README.md
#	packages/ui/acp/README.md
#	packages/ui/acp/acp-feature-support.md
#	packages/ui/acp/src/index.ts
#	packages/ui/acp/tests/bridge.spec.ts
#	packages/ui/acp/tests/dispose.spec.ts
#	packages/ui/acp/tests/edges.spec.ts
#	packages/ui/acp/tests/turns.spec.ts
This commit is contained in:
Tianyi Cui
2026-07-24 23:43:10 +08:00
829 changed files with 23607 additions and 1815 deletions

View File

@@ -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
2026-06-20-assembled-assistant-messages-only.md: ba8135a3d63f292cfedd23de8b4b9d43b4455e8c
2026-06-20-assembled-assistant-messages-only.zh.md: 9a42a202425158edd85d7a3f2ef4b0b97e00da90

View File

@@ -2,6 +2,8 @@
Status: rejected — high-fidelity chunk replay, partial failed streams, and snapshot replay currently depend on persisted `assistant/chunk` events. Dropping chunks is only viable with a no-information-loss replay/artifact replacement.
English | [中文](2026-06-20-assembled-assistant-messages-only.zh.md)
## Problem
The canonical session log currently persists every `assistant/chunk` exactly as streamed by the model. The [session persistence Agent Note](../../implemented/architecture/2026-06-14-session-persistence.md) chose this for token-level replay fidelity and contiguous `seq`, but the cost has grown: JSONL fixtures are dominated by tiny delta records, snapshot scenarios replay the model by grouping chunk events, ACP load reconstructs prior assistant output from chunks, and any future log reader must distinguish durable message history from token-level trace.

View File

@@ -0,0 +1,36 @@
# Agent Note: 仅持久化组装后的 assistant 消息,不存储流式分片
Status: rejected — 高保真分片回放、部分失败流与快照回放目前依赖持久化的 `assistant/chunk` 事件。只有具备不丢失信息的回放/产物替代方案后,才能删除分片。
[English](2026-06-20-assembled-assistant-messages-only.md) | 中文
## 问题
当前的规范会话日志会持久化模型流式输出的每一个 `assistant/chunk`。[会话持久化 Agent Noteagent 决策记录)](../../implemented/architecture/2026-06-14-session-persistence.md)选择这一方案是为了 token 级别的回放保真度和连续的 `seq`但其代价日益增长JSONL fixture测试前置数据被大量微小的 delta 记录占据快照场景通过对分片事件分组来回放模型ACPAgent Client Protocol加载时从分片重建先前的 assistant 输出,而任何未来的日志读取方都必须区分持久的消息历史与 token 级别的追踪。
对于成功组装出完整内容的步骤agent loop智能体循环已经追加了一条 `assistant/message`。这正是 `deriveMessages()` 用来构造下一次模型请求的事件。换言之,正常的可恢复会话状态无需分片即已具备;分片是实时渲染和确定性测试的产物,不是必需的会话历史。失败或中止的流则不同:部分 assistant 输出可能仅以分片形式存在,而空的 max-token 步骤可能根本不产生 `assistant/message`
## 提案
停止在规范会话日志中存储 `assistant/chunk`。持久日志保留 `assistant/message``tool/call``tool/result``usage`(如保留)以及轮次边界。实时 UI 仍可通过一个刻意设计为瞬态的流事件接收 token 增量。快照回放应将其模型脚本移入显式的 fixture 伴随文件,或从记录的适配器产物中派生,而非将规范的用户会话当作 token 磁带。需要部分失败流输出的场景必须在回放 fixture 中记录该输出。
ACP `session/load` 可以将先前的 assistant 消息作为完整内容块回放,而非模拟原始的 token 流。加载后的 transcript文本记录无需重现每一个历史 delta它必须展示相同的已完成 assistant 内容,并以有效的提供方历史恢复运行。
## 验收标准
- `SessionEventMap` 移除 `assistant/chunk`,或在需要过渡性实时事件时将其标记为非持久化。
- [会话持久化文档](../../../../packages/session-persistence/session-persistence/README.md)不再要求逐字存储每个流式分片。
- `llm-replay` 和 ACP 快照使用显式的回放 fixture 格式或伴随文件来存储模型分片。
- `session/load``assistant/message` 渲染已完成的 assistant 消息。
- 存储的日志大幅缩小,且在没有分片缺口的情况下保持 `seq` 连续。
- 会话格式版本与已记录的 fixture 一并刷新;按预发布格式策略拒绝非当前版本的存储日志。
## 放弃了什么
规范的用户会话不再能重建旧轮次的精确 token 流。它也会丢失失败或中止流的部分 assistant 输出,除非另有事件或 fixture 记录。对于当前的恢复、加载和快照契约而言,这是过大的信息损失。需要精确确定性流的测试应当直接拥有该 fixture前提是生产会话日志为用户可见的恢复保留了足够的保真度。
## 相关
本 Agent Note 取代 [会话持久化](../../implemented/architecture/2026-06-14-session-persistence.md) 中关于分片持久化的决策,并影响 [ACP 快照测试](../../implemented/testing/2026-06-19-acp-snapshot-tests.md)——其当前的回放插件从 `assistant/chunk` 事件派生脚本。
<!-- agent-note-format: alternatives-not-recorded (pre-format Agent Note) -->

View File

@@ -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
2026-06-20-drop-acp-session-load.md: 2b6edf173506929f2d64e910b47aa70fb4f1d854
2026-06-20-drop-acp-session-load.zh.md: 8e03acad17cf2831a15d5992a0419a73f275719d

View File

@@ -2,6 +2,8 @@
Status: rejected — Zed is the current target ACP client, advertises and exercises load-capable sessions, and keeps pending-load state for concurrent `session/load`. The bridge should keep `session/load` and make the resume contract solid.
English | [中文](2026-06-20-drop-acp-session-load.zh.md)
## Problem
ACP advertises `loadSession: true` and implements `session/load` by injecting persistence into the bridge, validating cwd against stored metadata, reconstructing an agent from the persisted log, and replaying prior transcript updates to the client. That path has its own race handling, loading-id guard, replay presenter logic, and tests. It also depends on the canonical log retaining enough UI data to reconstruct old chunks and tool presentations.

View File

@@ -0,0 +1,29 @@
# Agent Note: 移除 ACPAgent Client Protocolsession/load直到恢复具备产品形态
Status: rejected — Zed 是当前目标 ACP 客户端,它声明并实际使用支持加载的会话,还为并发的 `session/load` 保留待加载状态。桥接层应保留 `session/load` 并巩固恢复契约。
[English](2026-06-20-drop-acp-session-load.md) | 中文
## 问题
ACP 声明 `loadSession: true` 并实现 `session/load`:向 bridge 注入持久化能力、校验 cwd 与存储元数据的一致性、从持久化日志重建 agent智能体并向客户端回放先前的 transcript文本记录更新。该路径有自己的竞态处理、loading-id 守卫、回放展示逻辑和测试。它还依赖规范日志保留足够的 UI 数据,以重建旧的分片和工具展示。
持久化仍然是基础能力,但编辑器可见的恢复尚未经过产品流程设计。目前没有会话选择器、没有标题/预览元数据也没有明确的加载失败或部分加载的用户体验。bridge 正在为一个仅被测试、文档和当前目标客户端的会话模型所使用的功能付出复杂度代价。
## 提案
当前阶段ACP 仅启动全新会话。`initialize` 声明 `loadSession: false` 或省略该能力,`session/load` 不予支持。持久化仍可供 agent loop智能体循环和测试使用如果其他消费方需要恢复仍可作为底层工厂存在。编辑器 bridge 应在具备真正的会话选择 UX 和稳定的 load transcript 契约后,再重新引入 `session/load`
## 验收标准
- ACP 不再注入 `sessionPersistence`;它原本仅供 `session/load` 使用。
- `initialize` 不再声明 load 支持。
- `session/load` handler、loading-id 追踪、已加载会话的 cwd 预检以及 load 回放测试均被移除。
- 快照 fixture测试前置数据不再依赖 load 回放展示。
- [ACP 文档](../../../../packages/ui/acp/README.md)仅描述全新会话的支持。
## 放弃的能力
编辑器无法通过 ACP 重新打开先前持久化的会话。这确实是一项产品功能,但当前实现超前于 UX 设计,且将 bridge 绑定到 token 级别的日志回放。保留持久化但移除编辑器 load可将 bridge 收窄到它当前能干净呈现的工作流。
<!-- agent-note-format: alternatives-not-recorded (pre-format Agent Note) -->

View File

@@ -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
2026-06-20-drop-acp-terminal-meta.md: 79da387ac1a7a0e6767e3bf24baa6039e39ef90d
2026-06-20-drop-acp-terminal-meta.zh.md: d29fd54618611f56fd071a0ee4a63bc207895d89

View File

@@ -2,6 +2,8 @@
Status: rejected — Zed is the current target client, and the terminal `_meta` convention is intentional Zed UX with a plain ACP fallback for other clients.
English | [中文](2026-06-20-drop-acp-terminal-meta.zh.md)
## Problem
The ACP bridge implements a Zed-specific terminal-card convention through `_meta.terminal_info`, `_meta.terminal_output`, and `_meta.terminal_exit`. The implemented [rich ACP bash rendering Agent Note](../../implemented/feature/2026-06-18-acp-terminal-and-tool-rendering.md) deliberately avoided ACP's client-side `terminal/create` because bash execution belongs in the harness, but still adopted the reference agents' display-only `_meta` convention. That gives a nicer Zed card at the cost of bridge state, capability negotiation, terminal ids, special update mapping, text fallback tests, and exit-pill parsing in `dsh-tool-bash`.

View File

@@ -0,0 +1,31 @@
# Agent Note: 移除 ACPAgent Client Protocol终端 `_meta` 渲染
Status: rejected — Zed 是当前目标客户端terminal `_meta` 约定是有意设计的 Zed UX同时为其他客户端保留普通 ACP 回退。
[English](2026-06-20-drop-acp-terminal-meta.md) | 中文
## 问题
ACP 桥接层通过 `_meta.terminal_info``_meta.terminal_output``_meta.terminal_exit` 实现了一套 Zed 特有的终端卡片约定。已实现的[富 ACP bash 渲染 Agent Noteagent 决策记录)](../../implemented/feature/2026-06-18-acp-terminal-and-tool-rendering.md)刻意回避了 ACP 客户端侧的 `terminal/create`(因为 bash 执行属于 harness 职责),但仍采用了参考 agent智能体的纯展示 `_meta` 约定。这在 Zed 中带来了更好的卡片效果,代价是桥接状态、能力协商、终端 id、特殊的 update 映射、文本回退测试,以及 `dsh-tool-bash` 中的 exit-pill 解析。
回退路径已经存在:将工具调用和完成输出渲染为普通 ACP 内容块。非 Zed 客户端本来就依赖这条路径,但 Zed 终端卡片是当前目标客户端的功能特性,而非推测性装饰。
## 提案
忽略 `clientCapabilities._meta.terminal_output`,通过纯 ACP 内容路径渲染 bash 结果。执行仍由 agent 侧的 `dsh-bash` 完成;仅移除展示相关的终端元数据。如果 ACP 日后标准化了 agent 执行的终端,或产品决定 Zed 特有展示值得其维护成本,终端卡片可以再回来。
本提案比[收拢工具自有 UI 展示](2026-06-20-generic-tool-rendering.md)更窄:如果通用的 `presentCall`/`presentResult` 保留,本提案不影响它们,只移除终端子形态与 `_meta` 映射。
## 验收标准
- ACP 不再读取或存储 `_meta.terminal_output` 能力状态。
- `TerminalRendering`、终端 id、终端 cwd 解析与 `_meta.terminal_*` update 映射从 `@deepseek-ai/dsh-acp` 中消失。
- `ToolTerminal``@deepseek-ai/dsh-tools` 中消失,或在展示清理中因未使用而删除。
- Bash 结果展示不再为终端 pill 解析退出状态。
- 已实现的[富 ACP bash 渲染 Agent Note](../../implemented/feature/2026-06-18-acp-terminal-and-tool-rendering.md) 作为已交付历史保留在 `implemented/` 中;如被本提案取代,则加上交叉链接。
## 放弃的内容
Zed 用户将失去专用终端卡片:没有 cwd 头部、终端展示或 exit pill。他们仍能以纯内容形式看到命令和输出。在 ACP 桥接层尚未发布、`_meta` 键只是约定而非标准的阶段,这是合理的简化。
<!-- agent-note-format: alternatives-not-recorded (pre-format Agent Note) -->

View File

@@ -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
2026-06-20-drop-bash-output-spill-files.md: b2bd1a04ee1524bab29814ffa7c22712a83ee5f7
2026-06-20-drop-bash-output-spill-files.zh.md: c1b5670fac28a90cc4eb229ba0013e39067af8eb

View File

@@ -2,6 +2,8 @@
Status: rejected — full-output recovery is a real bash behavior. A future artifact/blob service may generalize it, but dropping spill files before that replacement would lose useful command output.
English | [中文](2026-06-20-drop-bash-output-spill-files.zh.md)
## Problem
`dsh-bash-local` keeps bounded in-memory output and spills large stdout/stderr streams into private temp files. That requires a private directory, random owner-only file creation, close-failure handling, byte-offset incremental reads, lossy read reporting, path rendering in model-facing text, and cleanup discipline. The tool then tells the model to read a local spill path when output was truncated.

View File

@@ -0,0 +1,31 @@
# Agent Note: 移除 bash 完整输出溢出文件
Status: rejected — 完整输出恢复是真实的 bash 行为。未来的产物/blob 服务或许能将其泛化,但在替代方案就位前删除溢出文件会丢失有用的命令输出。
[English](2026-06-20-drop-bash-output-spill-files.md) | 中文
## 问题
`dsh-bash-local` 在内存中保留有界的输出,并将大体量的 stdout/stderr 流溢出到私有临时文件。这要求一个私有目录、仅所有者可写的随机文件创建、关闭失败处理、基于字节偏移的增量读取、有损读取报告、在面向模型的文本中渲染路径,以及清理纪律。当输出被截断时,该工具会告知模型去读取一个本地溢出路径。
这解决了一个真实问题,但方式狭隘且有泄漏。溢出路径是一个暴露在模型输出中的进程级文件系统产物,而非具有作用域访问控制、保留策略或 UI 支持的持久化 harness 产物。它还使后台任务的读取变得复杂,因为有损增量读取必须指向一个或两个溢出文件。
## 提案
保留尾部截断移除完整输出溢出文件。bash 结果包含有界的尾部内容加一个明确的截断标记;不输出路径。如果用户需要恢复完整输出,则添加一个通用的产物/blob 服务(具有明确的所有权、清理和 UI 渲染),然后让 bash 将大体量输出附加到该服务。
本提案可以独立于[通用长时间运行工具运行时](../../implemented/architecture/2026-06-20-generic-long-running-tool-runtime.md)落地。如果后台任务保留,`bash_output` 仍应报告输出已被丢弃,但不再提供溢出路径。
## 验收标准
- `CollectedOutput` 不再携带溢出路径。
- `OutputCollector` 仅保留有界缓冲区,删除临时文件机制。
- `renderResult()` 报告截断时不包含文件系统路径。
- 测试覆盖尾部截断,不再断言完整输出文件的内容。
- [docs/defensive-patterns.md](../../../../docs/defensive-patterns.md) 中的安全指导不再将私有溢出文件视为面向模型的接口。
## 放弃的能力
模型或用户无法再从临时文件恢复大体量命令输出中被省略的前缀。在真正的产物服务出现之前,这是可以接受的。当前的溢出路径为一个生命周期和权限均未经设计的功能引入了过多的定制机制。
<!-- agent-note-format: alternatives-not-recorded (pre-format Agent Note) -->

View File

@@ -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
2026-06-20-drop-durable-step-boundaries.md: c5c4f269a378e334c4dc509d1288146d77d9a520
2026-06-20-drop-durable-step-boundaries.zh.md: f2150699c74b16557d936d6833fcba02e7d76e69

View File

@@ -2,6 +2,8 @@
Status: rejected — `step/end` is the durable indication that a model step finished, and keeping the symmetric `step/start` / `step/end` pair makes crash repair, invariants, and transcript inspection clearer than inferring completion from adjacent step-scoped events.
English | [中文](2026-06-20-drop-durable-step-boundaries.zh.md)
## Problem
The session log stores `step/start` and `step/end` events even though every step-scoped event already carries `{ turn, step }`: assistant chunks, assistant messages, tool calls, tool results, usage, and errors. `deriveMessages()` ignores step boundaries, ACP ignores them for UI, and the main consumers are invariants, tests, snapshot expected outputs, and crash repair.

View File

@@ -0,0 +1,32 @@
# Agent Note: 移除持久化的步骤边界事件
Status: rejected — `step/end` 是模型步骤已完成的持久信号;保留对称的 `step/start` / `step/end` 对,比从相邻的步骤作用域事件推断完成状态更便于理解崩溃修复、不变式与 transcript文本记录检查。
[English](2026-06-20-drop-durable-step-boundaries.md) | 中文
## 问题
会话日志存储了 `step/start``step/end` 事件,尽管每个步骤作用域的事件本身已经携带 `{ turn, step }`assistant 分片、assistant 消息、工具调用、工具结果、用量和错误。`deriveMessages()` 忽略步骤边界ACPAgent Client Protocol在 UI 层面也忽略它们,主要消费方是不变式检查、测试、快照预期输出和崩溃恢复。
被否决的论点是:边界事件使日志更像仪式而非信息。实际上,`step/end` 是具体信息:读者无需从下一个事件推导状态,就能判断一次模型请求是已完成、已崩溃还是正在修复。同样,一个孤立的 `step/start` 对于「模型请求已发起但在产生任何分片之前就失败了」的场景也有价值。
## 提案
将轮次作为唯一的持久化边界。`step/start``step/end` 将从 `SessionEventMap` 中移除;在需要分组的事件上保留数值型 `step` 字段。agent loop智能体循环递增步骤计数器并以该编号记录步骤作用域的事件但不再追加开/关边界事件。消费方通过共享 `(turn, step)` 的连续事件推断步骤分组。
不变式插件应当强制步骤作用域的事件在一个已打开的轮次内具有有效的正整数步骤编号,而非要求独立的边界记录包围它们。崩溃恢复不应合成 `step/end`;如果一个被中断的轮次被保留,修复路径仍然可以关闭该轮次而无需捏造步骤边界记录。
## 验收标准
- `SessionEventMap` 不再包含 `step/start``step/end`
- agent loop 中不再有 `closeStep()` 终结路径。
- ACP 快照和持久化契约 fixture测试前置数据不再期望步骤边界行。
- `deriveMessages()` 和回放从步骤作用域的事件推导出相同的消息历史。
- [事件分类体系文档](../../../../docs/architecture.md)将轮次描述为持久化边界,将步骤描述为步骤作用域记录上的一个字段。
- 会话格式版本和已记录的 fixture 被刷新;按预发布格式策略,非当前版本的已存储日志被拒绝。
## 放弃了什么
日志不再将「一次模型请求已发起但进程死亡前未产生任何事件」记录为持久化事实,也不再有显式的「此步骤已完成」标记。在会话日志仍是持久化回放与审计表面的当下,这一损失不可接受。
<!-- agent-note-format: alternatives-not-recorded (pre-format Agent Note) -->

View File

@@ -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
2026-06-20-drop-unused-session-lineage.md: 605f1949999435b24404e0c5a72320416303ae52
2026-06-20-drop-unused-session-lineage.zh.md: 981f44189f4b8f11f513261db7094afdc650dffa

View File

@@ -2,6 +2,8 @@
Status: rejected — `parentSession` is part of the documented fork/sub-agent seam and is already preserved by the agent/session resume path. The field is future-facing, but it is not accidental dead state.
English | [中文](2026-06-20-drop-unused-session-lineage.zh.md)
## Problem
`SessionHeader.parentSession` records the session a new session was forked from. It is defined in `dsh-session`, preserved by persistence backends, copied through resume, documented as lineage metadata, and covered by round-trip tests. The repo has no production fork UI or sub-agent flow that reads it. The planned sub-agent/fork seam is still a TODO, so the field is currently stored future shape.

View File

@@ -0,0 +1,31 @@
# Agent Note: 移除未使用的会话血缘元数据
Status: rejected — `parentSession` 是已记录的 fork/subagent seam 的一部分,并已由 agent智能体/会话恢复路径保留。该字段面向未来,但并非意外遗留的死状态。
[English](2026-06-20-drop-unused-session-lineage.md) | 中文
## 问题
`SessionHeader.parentSession` 记录新会话从哪个会话 fork 而来。它在 `dsh-session` 中定义,被持久化后端保留,在恢复流程中复制,作为血缘元数据被文档记录,并有往返测试覆盖。然而仓库中没有任何生产环境的 fork UI 或 subagent 流程读取它。计划中的 subagent/fork seam 仍是 TODO因此该字段目前只是预存的未来形状。
单个文件的成本虽小,但在格式层面影响面广:每个后端 schema 和元数据序列化器都在保留一个尚无已完成功能读取的值。由于 header 是磁盘契约,即使是占位字段也会成为未来重构必须维护、迁移或有意打破的东西。
## 提案
移除 `parentSession`,使其不再属于 `SessionHeader`,直到真正的 fork/恢复功能需要血缘信息时再引入。如果存在相应 APIfork 仍然可以用先前事件来初始化新会话,但持久化的父指针应当与读取它的功能和解释它的 UX 一同引入。
如果血缘信息回归,届时再决定它应放在不可变 header 中、会话图索引中,还是作为一等事件。当前字段不应预先锁定那个设计。
## 验收标准
- `SessionHeader` 仅包含 version、id、createdAt 和可选的 cwd。
- JSONL 与 SQLite 元数据 schema 不再存储父会话 id。
- 恢复与列表 API 不再往返传递 `parentSession`
- 文档和测试移除没有生产消费方支撑的 fork 血缘声明。
- 会话格式版本、后端 schema 版本与记录的 fixture测试前置数据按需刷新按预发布格式策略非当前版本的存储数据将被拒绝不提供迁移路径。
## 放弃了什么
代码库失去了一个为未来 fork/subagent UX 预备的现成血缘钩子。这是有意为之。该字段在功能存在时很容易重新引入,而未发布的立场允许格式变更无需迁移。
<!-- agent-note-format: alternatives-not-recorded (pre-format Agent Note) -->

View File

@@ -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
2026-06-20-fold-session-persistence-interface.md: 895b868b2a80d8655284bae1364a85e19e174da7
2026-06-20-fold-session-persistence-interface.zh.md: c124b16531f904eb72cb8ac3842642d819309e14

View File

@@ -2,6 +2,8 @@
Status: rejected — the separate persistence interface package is the intended modular capability seam for durable backends. Folding it into `dsh-session` would reduce package count at the cost of a cleaner backend boundary.
English | [中文](2026-06-20-fold-session-persistence-interface.zh.md)
## Problem
`dsh-session-persistence` is an interface package whose main concepts are already owned by `dsh-session`: `SessionHeader`, `SessionEvent`, `SessionId`, `session/event`, and `session/flush`. The package adds the abstract `SessionPersistence` service, the shared write coordinator, and contract helpers. Backend packages depend on it, and `agent-loop` has to optionally find a sibling service for resume.

View File

@@ -0,0 +1,31 @@
# Agent Note: 将持久化接口合并进 dsh-session
Status: rejected — 独立的持久化接口包是为持久后端设计的模块化能力 seam。将其折叠进 `dsh-session` 虽能减少包数量,却会牺牲更清晰的后端边界。
[English](2026-06-20-fold-session-persistence-interface.md) | 中文
## 问题
`dsh-session-persistence` 是一个接口包package其核心概念已经由 `dsh-session` 拥有:`SessionHeader``SessionEvent``SessionId``session/event``session/flush`。该包额外添加了抽象的 `SessionPersistence` 服务、共享写入协调器和契约辅助工具。后端包依赖它,`agent-loop`(智能体循环)也需要可选地查找一个同级服务来实现恢复。
当持久化还是一个全新的可替换后端设计时,能力 seam 的拆分是合理的。但在可变摘要被移除之后,这个接口包基本上只是包装了会话日志自身的存储关切。继续保持独立可能带来的仪式感多于清晰度。
## 提案
将抽象的 `SessionPersistence` 服务、协调器和持久化契约辅助工具移入 `dsh-session`。JSONL 和 SQLite 仍作为独立的后端包,注册由会话包拥有的服务。这样既保留了后端可替换性,又删除了一个支撑包和一条跨包 seam。
实施 PRPull Request应更新[能力 seam](../../implemented/architecture/2026-06-13-capability-seams.md) 指南,补充此例外:持久化不同于 bash 或 LLM大语言模型因为它的词汇和生命周期事件本就属于会话包的核心领域。
## 验收标准
- `@deepseek-ai/dsh-session-persistence` 作为包被移除。
- `dsh-session` 导出持久化服务类型、协调器和契约辅助工具。
- JSONL 和 SQLite 后端包直接依赖 `dsh-session`
- `agent-loop` 的恢复功能使用会话包拥有的服务键。
- [会话持久化](../../implemented/architecture/2026-06-14-session-persistence.md)、[共享持久化写入协调器](../../implemented/architecture/2026-06-18-shared-persistence-write-coordinator.md)与[包文档](../../../../packages/session-persistence/session-persistence/README.md)说明后端实现为何仍保持独立。
## 放弃了什么
`dsh-session` 变得更重:它同时拥有内存日志和持久化接口。这就是代价。如果第三方持久化后端已经形成公开生态,独立的接口包会是更清晰的 SDK 边界;但在预发布阶段,在尚无外部消费方时,多出的包看起来更像是过早的抽象。
<!-- agent-note-format: alternatives-not-recorded (pre-format Agent Note) -->

View File

@@ -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
2026-06-20-generic-tool-rendering.md: 6fc610546da04e7d1e16fc17ada87483a142aa3c
2026-06-20-generic-tool-rendering.zh.md: 11386b87d845129950a8473eb1cf4ea6ce697ac8

View File

@@ -2,6 +2,8 @@
Status: rejected — tool-owned presentation should wait for more real tools before being generalized or deleted. Bash and ACP currently need the existing richer presentation path.
English | [中文](2026-06-20-generic-tool-rendering.zh.md)
## Problem
Tools can define `presentCall()` and `presentResult()` callbacks that return `ToolCallPresentation`, `ToolResultPresentation`, and optional `ToolTerminal` fields. The code itself flags the design as muddy: title, kind, raw input, content, terminal cwd, terminal output, exit code, and signal grew incrementally into a bag of optional fields. ACP then maintains pending call state to pair a result with the original args, creates replay-only presenters on `session/load`, and maps terminal subfields into Zed-specific `_meta`. `dsh-tool-bash` even parses exit status back out of rendered text because the pure replay-safe presenter no longer has the structured `BashRunResult`.

View File

@@ -0,0 +1,35 @@
# Agent Note: 收拢工具自有的 UI 展示逻辑
Status: rejected — 工具拥有的呈现机制应等到出现更多真实工具后再进行泛化或删除。Bash 与 ACPAgent Client Protocol目前仍需要现有的丰富呈现路径。
[English](2026-06-20-generic-tool-rendering.md) | 中文
## 问题
工具可以定义 `presentCall()``presentResult()` 回调,返回 `ToolCallPresentation``ToolResultPresentation` 以及可选的 `ToolTerminal` 字段。代码本身就标记了这个设计的混乱title、kind、raw input、content、terminal cwd、terminal output、exit code 和 signal 逐步增长为一堆可选字段。ACP 随后维护 pending call 状态以将 result 与原始 args 配对,在 `session/load` 时创建仅用于回放的 presenter并将 terminal 子字段映射为 Zed 特有的 `_meta``dsh-tool-bash` 甚至从渲染后的文本中反向解析退出状态,因为纯回放安全的 presenter 已经拿不到结构化的 `BashRunResult`
真正的第一方用途是为 ACP 提供 bash 展示。这不足以作为冻结一个跨包packageUI 展示 API 的依据。
## 提案
暂时移除工具自有的 UI 展示回调。规范的工具事件已经携带工具名、原始参数字符串、结果内容和错误状态。UI 从这些字段渲染一个通用的工具卡片。工具特有的富展示可以在至少有两个真实工具和两个真实消费方来验证词汇之后,以带标签的 render-intent union 形式回归。
## 曾考虑的替代方案
作为更小的替代方案,可以在一个 PRPull Request中将当前的可选字段集合替换为一个显式 union但如果目标是简化更彻底的做法是删除回调、保留通用路径。
## 验收标准
- `ToolDefinition` 移除 `presentCall``presentResult`
- `ToolCallPresentation``ToolResultPresentation``ToolTerminal``ToolCallKind` 消失,除非一个最小的通用 UI 类型仍需要其中之一。
- ACP 不再维护 presenter pending 状态,也不再在实时流式输出/加载回放期间调用工具回调。
- `dsh-tool-bash` 不再解析渲染文本来恢复退出状态以供 UI pill 使用。
- 快照预期输出展示通用工具卡片和文本结果。
## 放弃了什么
Bash 失去其自定义的终端风格卡片和模型生成描述的放置位置。回退方案仍然合理:命令作为工具输入展示,输出作为文本展示。富展示应当在产品拥有足够的 UI/工具多样性、足以支撑一份稳定的展示契约时再行设计。
## 相关
这是[移除 ACP terminal 元数据](2026-06-20-drop-acp-terminal-meta.md)的宽泛版本。如果本 Agent Noteagent 决策记录)被接受,那个更窄的 Agent Note 就不再必要。

View File

@@ -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
2026-06-20-retire-mid-turn-steering.md: a8812b3222739244d77f4d4dab60cf7c0cd6907d
2026-06-20-retire-mid-turn-steering.zh.md: 81a211a167daeb8c57b98f2a1c1451dbc54d09e4

View File

@@ -2,6 +2,8 @@
Status: rejected — mid-turn steering is an intentional agent capability for between-step user/plugin input and future goal/loop workflows. It is complexity with a product direction, not an accidental duplicate of `send()`.
English | [中文](2026-06-20-retire-mid-turn-steering.zh.md)
## Problem
The agent exposes two user-message paths that look close but have different lifecycle semantics: `send()` queues a normal user turn, while `steer()` injects a message between steps of the currently running turn and falls back to `send()` when idle. That distinction leaks through the whole stack: `Agent.steer()` is public API, the session log has a durable `steering/message` event, the agent event taxonomy has `agent/steering`, the loop maintains a steering FIFO beside the queued-message FIFO, cancellation clears both queues, and `deriveMessages()` has to render steering as a tagged synthetic user message rather than a normal prompt.

View File

@@ -0,0 +1,37 @@
# Agent Note: 移除轮次中途引导
Status: rejected — 轮次中途 steering中途引导是一项有意设计的 agent智能体能力用于接收步骤之间的用户/插件输入以及未来的 goal/loop 工作流。它是面向产品方向的复杂度,而非 `send()` 的意外重复。
[English](2026-06-20-retire-mid-turn-steering.md) | 中文
## 问题
agent 暴露了两条用户消息路径,外观相近但生命周期语义不同:`send()` 将一条普通用户轮次排入队列,而 `steer()` 在当前运行轮次的步骤之间注入一条消息,空闲时则回退为 `send()`。这一区分贯穿整个栈:`Agent.steer()` 是公开 API会话日志有持久化的 `steering/message` 事件agent 事件分类体系有 `agent/steering`agent loop智能体循环在排队消息 FIFO 之外还维护一个 steering FIFO取消操作需要清空两个队列`deriveMessages()` 必须将 steering 渲染为带标签的合成用户消息,而非普通提示词。
续行 seam 进一步放大了成本。`agent/turn-continuation` 默认条件为 `hadToolCalls || steeringInjected`,因此同一轮次内的 steering 消息即使模型未请求工具调用,也会强制循环再次调用模型。注释中提到了未来 `/goal``/loop` 和预算守卫的用途,但当前仓库没有生产级监听器;只有测试注册了该 waterfall瀑布式事件。另外唯一调用 `steer()` 的生产 UI 是 stdio 演示。ACPAgent Client Protocol在轮次运行期间已经通过普通队列发送提示词。
## 提案
暂时删除轮次中途的用户 steering。`Agent.send()` 成为提交用户内容的唯一公开方式;当 agent 正在运行时,内容等待下一个轮次。循环仅因工具调用而在轮次内继续,不因用户在某个步骤运行期间输入内容而继续。调用方若要中断当前轮次,使用 `cancel()` 后再 `send()`
移除 `Agent.steer()`、steering FIFO、`steering/message``agent/steering`、由 steering 驱动的续行逻辑,以及取消操作中区分排队消息与 steering 消息的逻辑。除非实现 PRPull Request发现了生产级监听器否则在同一变更中一并移除 `agent/turn-continuation`;没有 steering 后,当前仓库不再有具体的续行消费方。如果将来真正的预算或目标插件需要强制续行,应以该插件为具体消费方重新引入一个更窄的 seam。
## 验收标准
- `Agent` 暴露唯一的用户消息入口 `send()`
- 持久化会话事件词汇不再包含 `steering/message`
- `deriveMessages()` 渲染普通用户消息和上下文注入,不存在 steering 标签路径。
- 循环只有一个排队消息 FIFO没有同轮次用户消息续行路径。
- `agent/turn-continuation` 被移除,或收窄到有具名的生产级消费方。
- stdio UI 和文档将运行期间的输入描述为「排入下一轮次的输入」。
- 会话格式版本和已录制的 fixture测试前置数据已刷新非当前版本的存储日志按预发布格式策略被拒绝。
## 放弃了什么
用户无法在模型处于工具步骤之间时添加同轮次 steering 内容。这种行为在理论上对「你已经在工作了,也考虑一下 X」的场景有用但它不是 ACP 当前暴露的行为,且使轮次边界更难推理。更简单的行为是合理的:用户输入成为下一条提示词,取消操作仍是替换进行中工作的显式手段。
## 相关
本提案与[移除持久化步骤边界](2026-06-20-drop-durable-step-boundaries.md)天然配对,因为移除同轮次 steering 和 `agent/turn-continuation` 后,工具调用成为一个轮次包含多个模型步骤的唯一原因。
<!-- agent-note-format: alternatives-not-recorded (pre-format Agent Note) -->

View File

@@ -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
2026-06-20-single-session-acp-bridge.md: e99de76854390a0979d1b66866d1d48aacbc0036
2026-06-20-single-session-acp-bridge.zh.md: 660e4ccf6f2fba8672315bfed30872870f401554

View File

@@ -2,6 +2,8 @@
Status: rejected — Zed is the current target ACP client and its ACP implementation is explicitly multi-session: it stores live sessions in a `HashMap<SessionId, AcpSession>`, tracks `pending_sessions`, joins concurrent loads for the same id, and tests close-during-load behavior.
English | [中文](2026-06-20-single-session-acp-bridge.zh.md)
## Problem
The ACP bridge now supports multiple live sessions on one JSON-RPC connection. That capability brings multi-entry session maps, reverse session/agent lookups, per-session prompt state, loading ids, demux for every event, cross-session teardown, and isolation concerns for future permission prompts and background tasks. The older [multi-session ACP proposal](../../implemented/feature/2026-06-14-acp-multi-session.md) still tracks the unfinished permission-ownership piece; this Agent Note is the competing simplification path.

View File

@@ -0,0 +1,31 @@
# Agent Note: 将 ACPAgent Client Protocol桥接恢复为每连接一个活跃会话
Status: rejected — Zed 是当前目标 ACP 客户端,其 ACP 实现明确支持多会话:它把活跃会话存入 `HashMap<SessionId, AcpSession>`,跟踪 `pending_sessions`,合并同一 id 的并发加载,并测试加载期间关闭的行为。
[English](2026-06-20-single-session-acp-bridge.md) | 中文
## 问题
ACP 桥接现在支持在一条 JSON-RPC 连接上承载多个活跃会话。这一能力带来了多条目会话映射、反向会话/agent智能体查找、逐会话的提示词状态、加载中 id、每条事件的解复用、跨会话拆除以及未来权限提示与后台任务的隔离问题。较早的[多会话 ACP 提案](../../implemented/feature/2026-06-14-acp-multi-session.md)仍在追踪未完成的权限归属部分;本 Agent Noteagent 决策记录)是与之竞争的简化路径。
产品目标已经证明它需要在一个 harness 进程上承载并发的编辑器对话Zed 的 ACP 连接拥有多个会话和加载状态。快照回放层仍然避免并发模型流,因为其回放条目是位置相关的;这是测试 fixture测试前置数据的局限而非移除桥接多路复用的理由。
## 提案
将 ACP 的范围收回到每连接一个活跃会话。`session/new``session/load` 创建唯一的会话记录;在现有会话被 dispose资源释放或连接关闭之前第二个活跃会话请求将被拒绝。如果编辑器需要多个聊天标签页可以启动多个 agent 子进程,直到桥接具备具体的多会话 UX 和权限模型。
移除多会话映射和解复用逻辑,改用单一的 `SessionRecord | undefined` 即可。桥接仍可保留使 dispose 正确的 agent/会话生命周期 seam简化仅针对在同一传输层上多路复用多个活跃会话这一点。
## 验收标准
- ACP 每连接只有一条活跃会话记录。
- 当该记录存在时,`session/new``session/load` 拒绝请求。
- 事件处理器不再在 `Map<sessionId, record>` 上做解复用。
- 多会话测试被移除,或移至继续支持多路复用的提案下。
- 既有的[多会话 ACP 提案](../../implemented/feature/2026-06-14-acp-multi-session.md)更新为链接本 Agent Note并继续作为当前方向。
## 放弃了什么
ACP 客户端无法在一个服务器进程上承载多个并发对话。这是一项有实质意义的能力削减。对于一个尚未发布的 harness 而言,更简单的模型仍然合理:一个编辑器对话对应一个 agent 进程,跨会话的权限/后台任务隔离不再是活跃的正确性负担。
<!-- agent-note-format: alternatives-not-recorded (pre-format Agent Note) -->

View File

@@ -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
2026-06-20-truncate-interrupted-turns.md: af18618ad4c41af125e37c51b9fd971dd8eae64e
2026-06-20-truncate-interrupted-turns.zh.md: a20d0169f7735aa7a9437c10c958580c00704171

View File

@@ -2,6 +2,8 @@
Status: rejected — a single turn can contain substantial real work, including many steps and large tool output. Preserving interrupted turns is preferable to silently dropping that tail on load.
English | [中文](2026-06-20-truncate-interrupted-turns.zh.md)
## Problem
The current persistence contract preserves a final turn that was durably written but never closed. On load, `interruptedTurnClosers()` scans the tail, synthesizes error `tool/result` events for unanswered tool calls, appends a `step/end` when a step is open, appends `turn/end { kind: 'interrupted' }`, and asks the backend to durably commit that repair. The coordinator, JSONL backend, SQLite backend, session event vocabulary, invariants, docs, and tests all model this synthetic close path.

View File

@@ -0,0 +1,36 @@
# Agent Note: 加载时截断被中断的最终轮次
Status: rejected — 单个轮次可以包含大量真实工作,包括多个步骤和大量工具输出。保留被中断的轮次,优于在加载时静默丢弃这段尾部。
[English](2026-06-20-truncate-interrupted-turns.md) | 中文
## 问题
当前的持久化契约会保留已持久写入但从未关闭的最终轮次。加载时,`interruptedTurnClosers()` 扫描尾部,为未应答的工具调用合成 error `tool/result` 事件,在步骤处于打开状态时追加 `step/end`,追加 `turn/end { kind: 'interrupted' }`并要求后端持久提交这次修复。协调器、JSONL 后端、SQLite 后端、会话事件词汇、不变式、文档和测试都对这条合成关闭路径进行了建模。
这是一套庞大的机制,只为保留上次崩溃轮次中的部分工作。它还会凭空创造从未发生过的事件。合成的工具结果虽然有用(因为它使提供方历史保持合法),但也意味着恢复后的日志中包含了模型可见、却并非任何工具产出的文本。当前设计在尚无已发布产品、也没有真实恢复 UX 来证明部分轮次恢复确有价值的情况下,就优化了最大化尾部保留。
## 提案
加载时只保留最后一个已完成的轮次。后端仍然容忍并截断撕裂的最终记录,但如果解析出的持久前缀止于一个打开的 `turn/start` 之后,规范的修复方式是丢弃上一个 `turn/end` 之后的所有事件。不合成 `tool/result`,不合成 `step/end`,不追加 `turn/end { interrupted }`,也不引入 `interrupted` 轮次结束原因。
这使持久化的轮次边界变得简单:一个已完成的 `turn/end` 就是检查点。最后一个检查点之后的内容都是崩溃尾部。下一次提示词从最后一个已知合法的提供方 transcript文本记录恢复而不是从部分重建的最终轮次恢复。
## 验收标准
- `TurnEndReasonMap` 移除 `interrupted` 变体。
- `interruptedTurnClosers()` 及其测试删除。
- 持久化协调器的修复钩子截断后端特有的撕裂/打开尾部状态,不追加关闭事件。
- [会话持久化文档](../../../../packages/session-persistence/session-persistence/README.md)说明加载返回最后一个已完成的轮次,不包含部分最终轮次。
- 快照与契约测试随其所固定的行为一同更新。
- 会话格式版本与记录的 fixture测试前置数据刷新按预发布格式策略非当前版本的存储日志被拒绝不提供迁移路径。
## 放弃的内容
崩溃可能丢失最终轮次中的真实工作:上一个 `turn/end` 之后追加的助手文本、工具调用和工具输出。这是有意为之的简化。产品尚未发布,最终轮次恢复的语义未经用户验证,而一个干净的「已完成轮次即检查点」模型在解释、测试和实现上都容易得多。未来若需「恢复部分崩溃工作」功能,应设计为面向用户的显式恢复视图,而非静默插入规范 transcript 的合成事件。
## 相关
本提案是对[会话持久化](../../implemented/architecture/2026-06-14-session-persistence.md)与[轮次封闭不变式](../../implemented/architecture/2026-06-15-turn-enclosure-invariant.md)的直接简化。它还移除了持久化步骤边界事件的大部分动机,使[移除持久化步骤边界事件](2026-06-20-drop-durable-step-boundaries.md)的改动更小。
<!-- agent-note-format: alternatives-not-recorded (pre-format Agent Note) -->

View File

@@ -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
2026-07-04-prune-unimplemented-subagent-vocabulary.md: 890aca31f09f97ab6d9bf7c00f738d894695d9ad
2026-07-04-prune-unimplemented-subagent-vocabulary.zh.md: 7837759604a30ee8f58d922bb5f55f6730d1ddcb

View File

@@ -2,6 +2,8 @@
Status: rejected — the deferred capability vocabulary (`outputSchema`/`structured`, `toolFilter`, `sendMessage`/`resume`) is intentionally reserved surface: the seam advertises the full intended contract ahead of its implementations by design, so providers and consumers grow into a stable shape rather than re-negotiating it per capability. The consumer-evidence analysis below records the decision-time state.
English | [中文](2026-07-04-prune-unimplemented-subagent-vocabulary.zh.md)
## Problem
The [subagent seam](../../implemented/feature/2026-06-21-subagent-capability-seam.md) shipped a two-tier capability design: start-time capability flags checked by the service, and optional runtime methods on `SubagentRun`. Three start-time features and both optional runtime methods have zero implementations and zero callers:

View File

@@ -0,0 +1,39 @@
# Agent Note: 裁剪未实现的 subagent seam 词汇
Status: rejected — 延后的能力词汇(`outputSchema`/`structured``toolFilter``sendMessage`/`resume`)是有意保留的接口面:该 seam 按设计先于实现声明完整的预期契约,使提供方与消费方沿稳定形状演进,而非针对每项能力重新协商。下方的消费方证据分析记录了决策时的状态。
[English](2026-07-04-prune-unimplemented-subagent-vocabulary.md) | 中文
## 问题
[subagent seam](../../implemented/feature/2026-06-21-subagent-capability-seam.md) 交付了一套两层能力设计:启动时由服务检查的能力 flag以及 `SubagentRun` 上的可选运行时方法。三个启动时功能和两个可选运行时方法的实现数与调用数均为零:
- **`outputSchema`/`structured``toolFilter`**`SubagentCapabilities``SubagentStartRequest``SubagentResult`,位于 `packages/subagent/subagent/src/types.ts`):在作出决策时,每个真实提供方都声明 `outputSchema: false, toolFilter: false``packages/subagent/subagent-spawn/src/index.ts``packages/subagent/subagent-fork/src/index.ts``packages/subagent/subagent-acp/src/index.ts`);唯一的生产环境 `ctx.subagents.start` 调用方(`packages/subagent/tool-subagent/src/index.ts`)构造 `{ prompt, parent, signal?, agentOptions? }`,结构上无法设置这两个字段;`structured` 仅出现在脚本化测试 fixture测试前置数据中。服务的能力检查包含两行 assert其唯一执行者是拒绝测试。
- **`SubagentRun.sendMessage` / `SubagentRun.resume`**(同一文件):没有任何提供方实现——包括 mock 也没有spawn spec 断言的正是它们的*缺失*。
在作出决策时,`dsh-subagent` 依赖 `dsh-tools` 的唯一原因是 `outputSchema` 的 schema 类型(现为 `ObjectJsonSchema`)。三个后续 subagent 工作流按会话快照回放、fork seed 边界、ACPAgent Client Protocol后端都围绕这块接口面落地却没有增长出哪怕一个消费方。
## 提案
从 seam 中移除 `outputSchema`/`structured``toolFilter``sendMessage``resume`;将 `SubagentCapabilities` 缩减为 `{ depthLimit }`;删除两行能力 assert、三个提供方上的 all-false flag、脚本化 fixture 的 structured 分支和能力旋钮,以及为固定被移除接口面而存在的测试。`dsh-tools` 的 peer/dev 依赖应从 `packages/subagent/subagent/package.json` 中删除。更新 [subagent.md](../../../../docs/core-data-structures/subagent.md) 中的粘贴内容与 type-equiv manifest元数据清单以及受影响的提供方 README。实现 PRPull Request按照 [implemented/AGENTS.md](../../implemented/AGENTS.md) 修订 seam Agent Noteagent 决策记录)的能力目录。
**保留** `depthLimit`/`maxDepth` 与能力检查。进程内后端已强制执行该限制,尽管当前发布的工具尚未设置它。递归是已知的 seam 风险,因此恰当的后续工作是提供一个工具默认值,而非删除正在工作的强制逻辑。
审视过但有意不动的相邻接口面:`SubagentService.getProvider()`/`list()` 仅有测试 harness 消费方,但 [prune-dead-seam-methods 实现说明](../../implemented/simplification/2026-06-20-prune-dead-seam-methods.md)恰好记录了这种形态从 bash 执行器中被移除后又被回退的经过——对于一个基于已跟踪 map 的单行访问器而言,测试 harness 就是消费方。`SubagentRunEndInfo.lastAssistantMessage` 是一个已记录的保留项([subagent 观测/丰富化 Agent Note](../../implemented/feature/2026-06-30-subagent-observe-enrich.md)的评审删除了 `agentType` 但有意保留了它,因为它是进程外子 agent智能体唯一的最终消息通道它当前未接通的桥接转发是一个待补的缺口或待记录的消费方不是本 Agent Note 要裁剪的接口面。
这是[从持久化 seam 裁剪死方法](../../implemented/simplification/2026-06-20-prune-dead-seam-methods.md)在 seam 词汇层面的回响:每个实现都必须为无人声明的成员,甚至更弱,因为这里连一个实现都没有。
## 曾考虑的替代方案
### 为什么不保留?
两类能力的设计是 seam Agent Note 的核心亮点,日后重新添加 `outputSchema` 会涉及多个文件。但该设计以 `depthLimit` 作为活跃示例、以 Agent Note 作为记录仍然成立;而且 seam Agent Note 本身承认已交付的 `toolFilter` 形态是错误的(真正的强制需要在子 agent 上下文中实施 `tools/pre-execute` deny而非 schema 过滤)——该 deny 原语已存在于拦截 seam 上,因此基于真实实现提供方重新添加时,将固定出一份比当前推测性契约更好的契约。
## 验收标准
- 被移除的拼写仅出现在本 Agent Note 和修订后的 seam Agent Note 中;`SubagentCapabilities``{ depthLimit: boolean }``dsh-tools` 依赖边已消除(`hygiene` 绿色)。
- 深度强制测试不变且绿色。
## 风险
subagent 生命周期事件在结束载荷上携带 `lastAssistantMessage`——该增强位于服务模块中,不在本 Agent Note 缩减的 seam 词汇范围内observe-enrich Agent Note 记录了因缺少消费方而删除 `agentType` 兄弟字段的判断,本 Agent Note 延续了这一判断。CC 钩子桥接是这些生命周期事件的第一个外部消费方它只读取事件载荷不涉及本文移除的任何接口面observe-enrich Agent Note 推迟的控制流重设计将实现 `resume` 列为自身的未来工作——恰好是本 Agent Note 模式所预期的重新添加触发点。

View File

@@ -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
2026-07-12-collapse-workflow-to-foreground-core.md: 629e2140523c3ae7caf533de99821206d05f1b8e
2026-07-12-collapse-workflow-to-foreground-core.zh.md: 3ae5e026a0b123a6b695b339010bf14a99515912

View File

@@ -2,6 +2,8 @@
Status: rejected — Workflow progress is an intentional observation surface; make it useful through a consumer instead of deleting it.
English | [中文](2026-07-12-collapse-workflow-to-foreground-core.zh.md)
## Problem
The workflow capability executes foreground JavaScript that composes subagents, but it also carries an unconsumed progress-observation system. No production listener subscribes to any of the six `workflow/*` events; listeners exist only in workflow tests. Nevertheless the seam defines run/phase/agent outcome payloads, the worker sends phase/log/agent lifecycle protocol messages, the host forwards them through a `liveAgents` pairing ledger, and the engine maintains run ids solely to correlate those notifications.

View File

@@ -0,0 +1,39 @@
# Agent Note: 将工作流收缩至已使用的前台核心
Status: rejected — 工作流进度是有意设计的观测接口面;应通过消费方使其发挥作用,而非删除它。
[English](2026-07-12-collapse-workflow-to-foreground-core.md) | 中文
## 问题
工作流能力执行前台 JavaScript 来编排 subagent但它同时携带了一套无人消费的进度观测系统。没有任何生产环境的监听器订阅六个 `workflow/*` 事件中的任何一个监听器仅存在于工作流测试中。尽管如此seam 定义了 run/phase/agent智能体 outcome 载荷worker 发送 phase/log/agent 生命周期协议消息host 通过一个 `liveAgents` 配对账本转发它们,引擎维护 run id 仅仅是为了关联这些通知。
这套进度词汇不仅仅是未被使用;它在不经重新设计的情况下也无法服务于其唯一已命名的未来消费方。`WorkflowRunInfo` 包含 `{id, meta}` 但没有父 agent、会话或工具调用标识而面向模型的工具也从不暴露 run id。一个全局 ACPAgent Client Protocol监听器无法将事件路由到正确的客户端会话。`meta.phases` 从未被查询,`phase(title)` 不对其做校验phase 的 `detail`/`model` 和 agent 的 `label`/`phase` 仅供事件消费,`whenToUse` 被校验和复制但从未被渲染或用于选择。`phase()``log()` 仍然跨越 worker 边界,尽管没有接收方。
live handle 在观测者消失后仍重复事件时代的数据。`WorkflowRun.id` 没有非事件消费方,而工具读取 `run.meta.name` 只是为了渲染一个它已经以 `args.meta.name` 形式持有的值;两者都不属于执行/取消 handle。
取消机制也为一个同步启动提供了两条公开通道。`WorkflowStartRequest.signal` 被传递给 worker host而唯一的生产调用方另外将同一个 signal 桥接到 `WorkflowRun.cancel()`。因为 `start()` 在控制权让出之前就返回了 run不存在需要请求时取消的就绪窗口重复的 signal 增加了 host 的 listener/disarm 状态却没有封堵任何竞态。
`WorkflowError.fatal` 是同一种推测性分支的微缩版:所有生产环境的构造都是 fatal 的,`fatal: false` 仅存在于测试中,组合子已经通过 `instanceof` 区分工作流失败。
## 提案
保留已使用的核心:`agent(prompt, { schema, model })``parallel``pipeline``args`、并发/agent 上限、取消、有界 dispose资源释放、结构化结果、worker 隔离与前台工具收集。移除所有 `workflow/*` 事件及其仅供事件使用的 info/outcome 类型;移除 `phase()``log()`、agent 的 `label`/`phase`、phase 声明、`whenToUse` 及其 worker 消息/host 观测者;将工作流元数据收缩为工具实际使用的 name移除仅供事件使用的 run id/meta 快照与合成的 agent-end 账本。将 `WorkflowRun` 收缩为 `result``cancel()``dispose()`;工具渲染请求方持有的 name。移除 `WorkflowStartRequest.signal` 及 worker host 的 input-signal listener/disarm 状态,保留调用方从其 abort signal 到 `run.cancel()` 的桥接。将 `WorkflowError` 变为单一的 fatal 错误类,不再有布尔模式或 `isFatalWorkflowError()` 辅助函数。
修订已实施的动态工作流 Agent Noteagent 决策记录),并更新 seam/工具/worker README、工具 schema、生成的 catalog 与包package依赖图、worker type-equiv 记录、单元测试以及工作流快照/header fixture测试前置数据。如果进度 UI 工作被立项,应从一份命名了父 agent/会话/工具调用的关联契约出发,而非原样复活这套协议。
## 曾考虑的替代方案
**为未来 UI 保留预建的观测词汇。** 当前形态类似 Claude Code 的动态工作流元数据host 有意地将每个转发的 agent start 与 worker 的 end 或一个合成的终止 end 配对。移除它意味着放弃形态兼容性,使进度 UI 成为一项全新的设计任务;但现有载荷仍缺少可路由的归属信息,因此仅靠平衡的生命周期也无法在不重新设计的情况下让已命名的 ACP 消费方可行。
## 验收标准
- 工作流公开 seam 仅包含有生产消费方的执行、取消、结果与 dispose 契约。
- 不再保留任何工作流事件、phase/log 协议消息、run-id 生成器、仅供进度使用的元数据、host 配对账本或 fatal 模式分支。
- run handle 不再有 id/meta 回显,取消在同步 `start()` 返回后只有一条持有者拥有的通道。
- parallel/pipeline 行为、上限、取消后的完全停稳、worker 隔离、结构化输出与面向模型的工作流场景保持测试覆盖。
- 类型检查、覆盖率、快照、doc-sync文档同步门禁、module-graph 校验、构建与 hygiene 全部通过。
## 风险
这是对工作流 DSL、事件分类体系、handle 与 start request 的编译可见收缩。现有提供描述性元数据的工作流调用,以及使用 `phase``log` 或 label 的脚本,都必须相应精简;程序化调用方需自行将 abort source 桥接到返回的 handle未来的观测者必须添加一个关联性更好的 seam。使工作流有用的执行语义不变。

View File

@@ -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
2026-07-12-prune-unused-skill-registry-surface.md: 5a13effa04a6cd9954741a0a33ebc6fc3512fab8
2026-07-12-prune-unused-skill-registry-surface.zh.md: 46d49a02c294c492abdd6e7e611a5c92eb317c12

View File

@@ -2,6 +2,8 @@
Status: rejected — Direct runtime skill registration is an intentional extension path for third-party plugins.
English | [中文](2026-07-12-prune-unused-skill-registry-surface.zh.md)
## Problem
The skill service's embedded-runtime subsystem has zero production caller of `ctx.skills.register()`. It adds a reserved `runtime` provider name, a runtime map/rank/source, duplicate policy, a second revision in cache keys, normalization, disposers, and tests alongside the provider seam every shipped skill already uses. `SkillSummary.whenToUse` and candidate/definition `path` are parsed and copied but never read by a production consumer: the model catalog renders name/description, resource loading uses `resourceBase`, and providers own their locator. The deliberately open `metadata` extension point stays.

View File

@@ -0,0 +1,29 @@
# Agent Note: 裁剪 skill技能注册表中未使用的接口
Status: rejected — 直接在运行时注册 skill 是为第三方插件保留的有意扩展路径。
[English](2026-07-12-prune-unused-skill-registry-surface.md) | 中文
## 问题
skill 服务的嵌入式运行时子系统中,`ctx.skills.register()` 没有任何生产调用方。它引入了一个保留的 `runtime` 提供方名称、一套运行时 map/rank/source、重复策略、缓存键中的第二个 revision、规范化逻辑、dispose资源释放器以及相应测试——而所有已交付的 skill 都只使用提供方 seam。`SkillSummary.whenToUse` 和 candidate/definition 的 `path` 被解析和复制,但没有任何生产消费方读取它们:模型目录只渲染 name/description资源加载使用 `resourceBase`,提供方自行管理其定位器。有意开放的 `metadata` 扩展点保留不动。
## 提案
移除 `SkillService.register()``SkillRegistration`、运行时伪提供方及保留名称规则、运行时 revision/缓存分支,以及仅用于运行时的 source/rank 规范化逻辑。需要嵌入式 skill 的测试改为注册一个小型真实提供方。保留 `providerRevision` 作为进行中的发现 epoch但已完成的目录缓存仅以 cwd 为键每次提供方变更同步清除缓存await 之后的 revision 比较已能阻止插入陈旧结果。从 skill 契约和本地提供方副本中移除 `whenToUse``SkillCandidate.path``SkillDefinition.path`,同时保留提供方的 locator/root 路径;保留 `metadata``disableModelInvocation``source``provider``locator``resourceBase`,因为它们要么是有意开放的扩展词汇,要么是生产消费的字段。
同步修订 skill 系统 Agent Noteagent 决策记录、README、JSDoc、目录文件与测试。agent智能体作用域的系统提示词段、工具提供方和变量明确不在本提案范围内[agent 作用域贡献者契约](../../implemented/architecture/2026-07-08-agent-scope-contexts.md)有意允许在 `setup(agentCtx)` 期间通过 agent 拥有的上下文注册这三者,因此仓库内没有固定的作用域注册并不能证明它们未被使用。
## 曾考虑的替代方案
**保留面向嵌入方的运行时 skill 注册。** 这是已实现的 skill Agent Note 中有意提供的同步直接定义便利接口。一个小型提供方包装层可以在 effect 拥有的生命周期下暴露相同的嵌入数据,但它必须实现异步 `list()`/`get()`、携带提供方身份,并接受提供方的重复语义。本提案选择只保留一条统一的提供方路径,而非维护第二套排序、校验、缓存失效与查找路径。
## 验收标准
- skill 收集只有一条提供方驱动的路径,已完成缓存仅以 cwd 为键revision epoch 仅用于进行中的失效检测;保留的 skill 字段要么有生产读取方,要么有记录在案的有意扩展契约。
- agent 作用域的提示词段、变量、工具提供方、工具守卫,以及原生模式和 Code Mode 下的 structured-output 提交行为保持不变。
- 类型检查、覆盖率、快照、doc-sync文档同步门禁、module-graph 校验、构建与 hygiene 全部通过。
## 风险
这是对预发布 skill 注册表的编译可见收缩。外部编程式 `list()`/`get()` 消费方将失去 `whenToUse` 路由提示和 candidate/definition 的 `path`;已交付的模型目录从未渲染它们,资源解析保留了显式的 `resourceBase` 加上提供方自有的不透明 locator但这些字段并非观测等价。skill 本地 frontmatter 解析必须继续保留并校验所支持的 metadata schema外部提供方仍可提供嵌入式、文件系统、远程或其他 skill 来源。