# Agent Note（agent 决策记录）：为待处理队列项提供编辑与移除操作

Status: implemented

[English](2026-07-29-addressable-queue-operations.md) | 中文

## 问题

Web 队列能够渲染待处理消息，但无法编辑或删除其中某一行。`MessageId` 不足以充当寻址标识，因为调用方可以多次将同一条不可变消息加入队列。浏览器还会根据轮次和状态事件推断队列项已退役，因此当行操作与驱动器认领发生竞态时，系统无法给出权威结果。

## 决策

**每次获准进入 FIFO 的项都有独立标识。** AgentLoop 会铸造不透明的 `InboxItemId`，并发布一个 `InboxItem`，其中包含该 id、已有标识的 `UserMessage`，以及接受时确定的 `queued | steering` 放置方式。复用同一个 `MessageId` 会创建不同的 inbox 标识。注入绕过 FIFO，因此不会获得 inbox 标识。

**变更边界止于驱动器认领。** `Agent.updateInbox(id, action)` 会同步搜索待处理的 queued FIFO。编辑会替换已冻结的内容，同时保留 `InboxItemId`、`MessageId`、来源、唤醒策略和位置。移除会发出该次入队项的终态 discard。严格 steering（中途引导）会把消息作为新的 steering 单次入队项转移到开放的 next-step 窗口；窗口关闭时返回 `steer-unavailable`，且不改变 queued 项。待处理 steering 和已被驱动器认领的项会返回 `not-found`，因此后续变更绝不会改写活动轮次输入或持久历史。

**实时账本是权威状态。** `agent/inbox/enqueue`、`update`、`dequeue` 和 `discard` 共同维护 queued 入队项的 Host 镜像。同步可重入的 update 或终态事件可能先于外层 enqueue 监听器到达镜像；镜像会在当前分发期间保留这一尚不可见的结果，并在处理 enqueue 时把它合并进去，因此监听器注册顺序不会导致系统发布陈旧内容或不存在的行。协议发送完整的 `session/queue` 快照，而非增量猜测。重连会发送当前基线，每次 queued 变更或终态事件都会整体替换它。客户端不会进行乐观编辑，也绝不根据持久轮次事件或状态变化退役队列行。

**Queue 寻址要求普通会话的 Agent 存活。** `session.updateQueue` 只查询已挂载的 Agent 注册表，绝不恢复冷会话：`InboxItemId` 属于进程本地标识，无法在重启或资源释放后继续指向工作。由会话支撑的 subagent 会在访问 inbox 前返回 `agent-busy`，并保留其继续执行 owner；对于普通会话，Agent 缺失和单次入队项已被驱动器认领这两种情况都返回 `queue-item-not-found`。

**Web 操作只面向 Queue。** 带 placement 的 `session/queue` 会同时携带 queued 和待处理 steering；QueueDock 只选择 queued 项，ChatView 则投影 steering，并在消费后沿用既有的持久 transcript（文本记录）路径。QueueDock 在队列为空时隐藏，只有一个待处理项时直接渲染该行，存在两个或更多待处理项时则默认收起为可展开或收起完整列表的 `"<n> 条排队消息"` 表头。表头暴露 `aria-expanded` 和 `aria-controls`；展开后的列表以 180px 为高度上限，并可滚动。存在进行中的编辑或变更时，列表行会保持可见；队列清空后，下一次出现队列时会恢复默认收起状态。可见行暴露编辑、删除以及仅在运行期间可用的严格 steering 操作。UI 从运行时 `SessionFace` 契约派生队列行与变更类型，而不是导入连接插件，因此插件仍通过服务和快照协作。仅当所有内容块都是文本时才提供编辑功能；编辑器不能静默丢弃非文本块。编辑中的行只展示保存和取消操作，对应的键盘操作分别是 Enter 和 Escape。删除会移除对应的精确入队项；严格 steering 会保留每个内容块，并且只通过权威快照退役该行。Web 停止操作会保留待处理 Queue 工作；只有在被中断轮次达到完全停稳后，AgentLoop 才认领下一个可唤醒入队项，其出队事件会退役该行，无需浏览器重发。[Web Queue steering 操作](2026-07-30-web-queue-steer-action.md)负责定义严格转移与待处理投影契约。

## 考虑过的替代方案

**通过 `MessageId` 寻址行。** 不予采纳，因为同一条不可变消息可以重复发送；按消息标识编辑或删除会无法确定应操作哪一次入队。

**在浏览器中进行乐观变更。** 不予采纳，因为驱动器认领或另一个客户端可能先于 Host 操作完成。等待权威快照可以显式呈现所有权边界，并让 `queue-item-not-found` 报告真实竞态。

**允许编辑或移除待处理 steering。** 不予采纳，因为 QueueDock 只寻址独立的 queued 轮次。严格 steering 一旦成功，新的 steering 单次入队项就属于活动轮次，并且不再位于此变更接口内。

**暴露仅协议层的前移操作。** 不予采纳，因为当前没有产品交互会重新排序 Queue。公开一个没有当前消费方的操作，会为了推测性用途引入排序语义和测试。

**为队列操作恢复冷 Agent。** 不予采纳，因为持久会话标识不会保留进程本地的 inbox 寻址凭据。恢复只能在创建无关的实时状态后得到 `not-found`。

## 验证

AgentLoop 契约测试会在编辑、移除和严格 steering 精确 queued 入队项时保持提示词接纳窗口打开，拒绝对 steering 入队项的变更，并验证所得独立轮次及终态生命周期事件。Host schema 与代理测试覆盖仅含 queued 项的权威快照、同步可重入变更顺序、重连、拒绝冷 Agent、类型化竞态错误和 RPC 传输。客户端运行时和 QueueDock 测试覆盖非乐观投影、单行呈现、多行默认收起、交互期间强制保持可见、清空后重置、展开、仅文本编辑、保存与取消入口、移除、严格 steering、退役竞态，以及禁用混合内容编辑。无密钥浏览器场景会通过构建后的 Web 组合和真实 HTTP／SSE 协议执行公开的全部三项操作，随后连续停止活动轮次，证明保留的 FIFO 会继续推进且不清空队尾。

## 后果

queued 工作获得精确的行操作，但不会因此成为持久会话历史。单次入队标识是进程本地的实时寻址凭据，会在认领、严格转移、广义取消、dispose 或重启时消失；Web 停止操作会将 queued 入队项保留到后续认领，而重连只能恢复仍由活跃 Agent 持有的 queued 项。编辑会排除混合内容，直至编辑器能够保留每个块；待处理 steering 则不属于此投影和操作接口。

现在，协议会在每次变更时携带完整队列快照。队列预期保持较短，因此系统优先选择确定性恢复和多客户端收敛，而非增量变更协议。
