初始化 agent_ops 文档治理体系

This commit is contained in:
2026-08-07 16:56:51 +08:00
commit 10840909ab
75 changed files with 15750 additions and 0 deletions
@@ -0,0 +1,202 @@
# 04.runtime_workspace 技术实施规范评审(二)
**评审编号:** 02
**日期:** 2026-08-06
**评审对象:** [04.runtime_workspace.md](04.runtime_workspace.md)(产品/验收权威)、[05.technical_implementation_spec.md](05.technical_implementation_spec.md)、[06.technical_implementation_spec_review.md](06.technical_implementation_spec_review.md),以及 [运行时与智能体工具.md](../../设计/02.正式方案/运行时与智能体工具.md)、[LineUp Runtime 与 App SDK 架构方案](../../设计/02.正式方案/lineup-runtime-sdk-architecture.md)、[LineUp App 最终设计方案](../../设计/02.正式方案/app_final_design.md)。
**评审方法:** 由独立子代理只读复核当前文件,不沿用上一轮“已解决”结论;重点检查统一 activation、Agent Tool 路由、SDK session data、Runtime 原子提交,以及 Web / Tauri 是否能按同一契约实现。
**总体结论:** Pomodoro 前台语义、`activation_not_required`、通用 session data 和“先持久化、后对账”已经对齐。本轮进一步确认:Runtime 只按已验证的 App、方法、参数和当前 ready App session 做路由,不理解 MiniApp 的业务参数或直接写其数据;前台只是个别 Tool 的额外业务前提。MiniApp 通过 SDK 声明 Agent Tool 与 handler,构建时自动生成 Manifest 的不可执行 Tool 描述,开发者无需维护第二份手写 Manifest。长期 Tool 已分开协议回执 / 进度与最终业务结果;activation ready 也成为 Runtime 持久化、向 Agent 可见的进度事实,同时不把提前到达的合法调用丢给 Agent 处理。session data 已冻结 revision 0、订阅首帧、严格递增和重连对齐语义。因此 TIS2-01TIS2-05 已解决;TIS2-06 是有明确触发条件的 P4 延续项。**本轮没有剩余 P0~P3,第 04 次技术规范可以进入实现阶段。**
## 问题清单(Outline
状态标记:🔴 未解决,必须处理;🟡 已提出修复方向,尚未确认或未回填实施规范;✅ 已确认通过;⚪ 可延期但必须保留记录。P0~P3 必须在当前迭代处理;P4~P5 可以延期,但须记录原因与重新评估条件。
| 状态 | 优先级 | 编号 | 问题 | 证据与当前结论 / 下一步 |
|---|---:|---|---|---|
| ✅ | P1 | TIS2-01 | Runtime 如何在页面未前台显示时调用 MiniApp 的方法。 | **已确认并回填:** Runtime 只验证并路由 `app_scope + method + 参数`,解析或建立当前 App session 并等待 MiniApp active / ready;随后将调用投递给 MiniApp。MiniApp 自己理解方法和参数、修改 session data、返回结果。`app_ready` 不要求前台;`foreground_required` 在其上额外要求前台;`activation_not_required` 不启动 App。具体无界面执行容器是后续实现选择,不改变这条 Runtime / MiniApp 契约。 |
| ✅ | P1 | TIS2-02 | MiniApp 如何声明面向 Agent 的方法,并让 Runtime 路由到正确的处理逻辑。 | **已确认并回填:** MiniApp 在 SDK 中用 `defineAgentTools(...)` 声明公开 method、schema、activation requirement 和 handler;构建自动生成 Manifest 的不可执行 Tool 描述,开发者不写第二份 Manifest。Runtime 只按已验证 Tool 路由到 ready App session 的统一 SDK 接收入口;SDK 在 Bundle 内按 method 分发本地 handler。Registry 不保存私有函数 target。 |
| ✅ | P1 | TIS2-03 | 长期 `pomodoro.start``starting` / `focusing` 时的 Agent 回执与冻结 result schema 不一致。 | **已确认并回填:** `accepted / starting``started` 是持久化、可重放的协议回执 / 进度;只有 `completed``interrupted``not_started` 是符合 output schema 的唯一最终业务结果。Agent 只能在 `started` 后说“已开始计时”。同一 call_id 返回最新已持久化回执,终态后返回最终结果,不追加 outbox。 |
| ✅ | P1 | TIS2-05 | Agent 如何得知 MiniApp 已启动就绪,以及是否必须等待该通知后才能发送后续调用。 | **已确认并回填:** Runtime 将 activation 的 `starting / ready / failed / cancelled` 作为与触发 call_id 关联的受控协议进度通知 Agent;Agent 收到 `activation_ready` 后再编排依赖调用是推荐方式,但不是硬门槛。Runtime 持久化并排队提前到达的 `app_ready` / `foreground_required` 调用,ready 后按顺序投递;失败 / 取消则受控拒绝。`activation_not_required` 仍立即执行。Pomodoro 的 `started` 包含 ready,不重复发 `activation_ready`。 |
| ✅ | P2 | TIS2-04 | `sessionData.get()``subscribe()` 之间可能丢失一次更新,首帧与 revision 语义未冻结。 | **已确认并回填:** 空数据固定 revision 0;订阅在同一 App 子会话的串行顺序中注册并先收到当前完整快照,后续 revision 严格递增;因此读与订阅之间的 replace 要么成为首帧、要么紧随其后。重复 / 旧 revision 忽略,跳跃 / Bridge 重连重新 get 并订阅;Web / Tauri 共享 fixture。revision CAS 不做业务自动合并,TIS2-06 延续。 |
| ⚪ | P4 | TIS2-06 | 多入口同时修改 session data 时,是否建立 Runtime 通用 mutation queue。 | **延续项,不属于第 04 次实现:** 当前 Pomodoro 没有修改型 UI Action,保持 `get / replace / subscribe + revision CAS` 即可。首次实现“Agent Tool 与 UI Action 都可修改同一 App 子会话”的 MiniApp(例如可手动修改的 To-do 或 Whiteboard)前,必须先冻结统一 mutation queue、操作顺序、幂等恢复与业务冲突边界;离线多端协同 / CRDT 另行设计。 |
| ✅ | — | TIS2-C1 | Pomodoro 的前台即专注语义 | 前台确认后才创建 operation;仅挂载 / 预载不等于开始,失败 / 取消不产生 operation 或 IM 静态记录。 |
| ✅ | — | TIS2-C2 | `pomodoro.interrupt` 不唤醒 App | `activation_not_required` 可取消已有 starting 或中断已有 focusing,但不会因停止指令新开 App。 |
| ✅ | — | TIS2-C3 | session data、operation 与 IM 记录的职责边界 | session data 按 `app_scope + app_session_id` 隔离并由 MiniApp 自解释;operation / outbox 是 Runtime 事实;IM 是不可变静态结果。 |
| ✅ | — | TIS2-C4 | 原子提交和三条入口 | Runtime 先持久化 operation、activation、session data、workspace、receipt / outbox,再让 Lifecycle / Host / Surface 对账;Agent Tool、UI Action、Host 生命周期意图不混同。 |
## 本轮已通过的边界
### TIS2-C1Pomodoro 只有进入前台才真正开始
`pomodoro.start` 被接受后,Runtime 可以创建 instance、App 子会话和 `starting` activation;但 Host 必须明确确认该 instance 已成为用户当前看到的前台 App,Runtime 才创建 `focusing` operation 与 `ends_at`。iframe 创建、资源加载或后台预载都不是这个确认。最终激活失败、启动中取消或用户在启动中离开,都表示“本次计时未开始”,不产生 `operation_id`、deadline、专注中断记录或专注 IM 静态记录。
### TIS2-C2:停止指令不会反而打开 Pomodoro
`pomodoro.interrupt` 只查询调用所在 conversation 已有的 `starting``focusing` Pomodoro:前者取消启动,后者中断 operation;两者都不会为这条停止指令创建 instance、Surface 或前台焦点。
### TIS2-C3:通用 session data 不泄露 Runtime 业务事实
SDK 从不可伪造的 context 推导 `app_scope + app_session_id`,MiniApp 只能读取和替换自己的 JSON 数据字典。Pomodoro 可自行组织活动、显示信息、current 或 historyRuntime 不识别这些字段,也不直接向字典写 Pomodoro 私有业务数据。deadline、终态竞争、Tool receipt、outbox 和恢复继续属于 Runtime operation;一次完成后写入 Interact / IM 的记录是独立的不可变静态副本。
### TIS2-C4:持久化仍先于 Host 副作用
`RuntimeOperationCommitCoordinator` 的职责没有被 activation 新模型削弱:持久化失败时 activation、operation、session data、workspace、receipt、outbox、Lifecycle 和 Surface 均保持旧状态;持久化成功后 Host / Surface 对账失败时,Runtime 从已保存事实恢复或重试,不能倒写或伪造终态。
## TIS2-01Runtime 如何调用未前台显示的 MiniApp 方法
**已解决(2026-08-06,收敛决议)。**
此前问题错误地把重点放在“后台执行容器究竟是 Worker、iframe 还是别的实现”。用户已明确 Runtime 的架构职责:
它接收 Agent Tool 后只根据 schema 验证调用结构,找到 `app_scope` 下的 method 与参数,确认目标 MiniApp 当前
session 是否 active / ready,然后把调用路由给 MiniApp。Runtime 不理解参数字段和数值的业务意义,也不直接写
MiniApp 的数据;MiniApp 才知道 `todo.add` 表示新增待办,并自行通过 session data 完成业务修改。
```text
Agent Tool Call
→ Runtime:验证 Tool、schema、scope、幂等
→ Runtime:解析或建立目标 App session,等待 MiniApp ready
→ Runtime:投递 method + 已验证参数
→ MiniApp:理解业务、修改自己的 session data、返回结果
→ Runtime:验证、持久化 receipt / result,并回传 Agent
```
三个 activation requirement 的意义随之明确:
```text
app_ready
= MiniApp 已 active / readyRuntime 可路由方法调用;不要求前台
= 未来 todo.add
foreground_required
= app_ready,且 Host 已确认 MiniApp 成为当前前台
= pomodoro.start;前台是“开始专注”的业务前提
activation_not_required
= 不为这次调用启动或唤醒 MiniApp,只操作已有 Runtime 事实
= pomodoro.interrupt
```
运行中但不在前台的 MiniApp 如何落到具体 Host 容器,是后续实现层的选择;它不得改变上述统一的 Runtime 路由、
MiniApp 业务处理与 SDK 回传契约。本轮不再把“Runtime 是否直接写 To-do 数据”或“是否前台”误当作这个问题。
Runtime 同时会把 activation 的受控状态回传给触发启动的 Agent:`accepted / starting``activation_ready`,或
`activation_failed / activation_cancelled`。这条通知帮助 Agent 在需要时顺序编排后续调用,但 Runtime 不把正确性
交给 Agent:如果合法的 `app_ready` / `foreground_required` 调用在 ready 前已经到达,它会被持久化到同一 activation
等待队列,ready 后按顺序投递;`activation_not_required` 则保持立即执行。
## TIS2-02SDK 声明 Agent Tool,构建自动生成 Manifest
**已解决(2026-08-06,收敛决议)。**
MiniApp Manifest 的 Tool 区块仍是 Runtime 安装、Registry、Inventory 和 Agent 调用所依赖的能力说明书;但它不应是
开发者手写和维护的第二份图纸。每个 MiniApp 在自身代码中通过 SDK 的 `defineAgentTools(...)` 声明公开 Tool、
输入 / 输出 schema、activation requirement 和 `miniapp_sdk` Tool 的本地 handler。构建阶段从该声明自动生成
Manifest 的不可执行 Tool 投影,并与 Bundle 一同校验、签名和安装。
```text
MiniApp 源码中的 SDK Tool 声明
├── 供 TypeScript 校验 handler、输入和输出
├── 供 Bundle 内 SDK 建立 method → handler 本地映射
└── 构建自动生成 Manifest tools 描述
→ Runtime 安装时验证并投影 Registry
→ Runtime 发布 Agent Inventory
```
运行时对普通 MiniApp Tool 的路径固定为:
```text
Agent 调用 app_scope + method + params
→ Runtime 按生成 Manifest 校验、定位 ready App session
→ Runtime 投递到该 session 的统一 SDK Tool 接收入口
→ SDK 按 method 调用 Bundle 内已声明 handler
→ MiniApp 处理业务、写 session data、返回受控结果
```
Runtime 不保存、更不调用 MiniApp 私有函数 targetManifest 不包含函数、URL、回调或其他可执行内容。`delivery =
miniapp_sdk` 表示上述固定入口;`delivery = runtime` 才使用 Runtime 内部 handler key,例如第 04 次 Pomodoro
的 deadline / interrupt 可靠性操作。构建必须拒绝重复 method、非法 schema、miniapp_sdk Tool 缺少 handler 或
handler 与 schema 不匹配;runtime Tool 则必须匹配 Runtime 内置的受控 execution。
## TIS2-03:长期 Tool 的协议 receipt 与业务 result 分层
**已解决(2026-08-06,收敛决议)。**
`pomodoro.start` 的业务 result schema 只允许最终业务结果:已完成、已中断或未开始。同一个 call_id 在 `starting`
`focusing` 时不能伪造终态,也不能把 activation / operation 对象塞进业务 result。因此这条调用固定分成两层:
```text
Tool protocol receipt / progress
= accepted / startingRuntime 已收到请求,正在把 Pomodoro 打开到前台
= startedHost 已确认前台,Runtime 已创建 operation,计时真实开始
= 对 Agent 只包含 call_id、app_scope、受控状态,以及 started 后必要的时间事实
= 不属于 Tool 的业务 result_schema;每个阶段各自只写一次可重试 outbox
Tool business result
= 已完成、已中断、未开始等业务终态
= 必须符合 Manifest result_schema
= 每次 Tool Call 只持久化并回传一次
```
首次 start 与开始成功的原子提交分别写 `accepted / starting``started` 协议消息。相同 call_id 在 `starting` / `focusing`
时返回已持久化的最新协议回执;仅在进入 completed、interrupted 或 not_started 后返回已持久化的业务 result。`accepted`
只表示 Runtime 接到请求,不代表 Agent 可以对用户说“已开始计时”;真正开始仍以 Host 前台确认和 operation 创建为准。
## TIS2-05activation ready 如何通知 Agent、提前调用由谁负责
**已解决(2026-08-06,收敛决议)。**
所有 MiniApp 都有 `starting → ready | failed | cancelled` activation。Runtime 在持久化状态变化后,通过与原启动
call_id 关联的 protocol receipt / progress 向 Agent 发出 `accepted / starting``activation_ready`
`activation_failed / activation_cancelled`MiniApp、Surface 与 Host 都不得直接通知 Agent。通知只携带 call_id、
app_scope、状态和受控失败原因,不能把 instance / App 子会话变成 Agent 可指定的控制目标。
Agent 在收到 `activation_ready` 后再发送依赖该 App 的后续指令,是推荐的编排方式,但不是请求能否接收的硬门槛。
Runtime 自己持久化并排队在 ready 前到达的合法 `app_ready` / `foreground_required` Tool,ready 后按到达顺序投递;
若启动失败或取消,Runtime 不执行业务 handler,而为每个等待调用回传稳定错误。`activation_not_required` 保持立即处理,
因而启动中的 `pomodoro.interrupt` 可以直接取消当前启动。Pomodoro 的 `started` 同时表达 activation ready、前台确认与
operation 已开始,故不额外向 Agent 发送重复的 `activation_ready`
## TIS2-06:通用 mutation queue 与多入口协作写入
**优先级:P4(延续项,不在第 04 次迭代实现)。**
To-do 若只展示数据、所有修改都经 Agent Tool 进入,实际上天然只有一个业务写入来源;画板若同时允许 Agent Tool
和用户 UI Action 修改同一份 session data,则需要 Runtime 为同一个 `app_scope + app_session_id` 建立统一、持久化、
幂等的 mutation queue,避免两个来源各自基于旧 JSON 快照整体覆盖。该机制应让 Agent Tool、UI Action 与受控
Runtime 动作都以“业务操作”而非完整 JSON 快照进入同一顺序,再由 MiniApp 在最新数据上实现自己的业务效果。
这个方向是通用 Runtime 能力,不应要求开发者预先选择“单点 / 协作”模式;实际有哪些写入入口,是 MiniApp 已经
声明的 Tool / UI Action 自然决定的。但实现它会同时引入写入 handler 上下文、队列持久化与重启恢复、UI Action 写入
协议、顺序 / 幂等规则,以及未来离线多人协作与 CRDT / OT 的清晰边界。第 04 次只验证没有修改型 UI Action 的
Pomodoro,不能为此提前扩大范围。
本迭代继续使用通用 `sdk.sessionData.get / replace / subscribe` 与 revision CASCAS 只防止旧版本覆盖,不承诺
自动合并业务冲突。**重新评估触发条件:** 在开始任何一个“Agent Tool 与 UI Action 都能修改同一 App 子会话”的
功能之前,例如手动编辑 To-do 或 Whiteboard 的首个交互式绘制流程,必须先将本项提升为该迭代的 P1 并完成设计。
## TIS2-04session data 首帧与 revision 同步窗口
**已解决(2026-08-06,收敛决议)。**
本项只处理 Surface 读取自身 session data 时的版本同步,不处理 Agent 与 UI 同时修改数据的业务合并;后者已作为
TIS2-06 的 P4 延续项。若 Surface 先 `get()`、再 `subscribe()`,两次调用之间发生的 replace 不能被遗漏。第 04 次
冻结以下最小且跨 Host 一致的规则:
```text
不存在 session data
→ get() 返回 { data: null, revision: 0 }
subscribe(listener)
→ 在同一 app_scope + app_session_id 串行顺序中注册
→ 注册后先投递当前完整 { data, revision }
→ 之后投递 revision 严格递增的 session_data.changed
```
因此,若 replace 在注册前提交,首帧就是新 revision;若注册先完成,则新 revision 作为后续事件抵达。SDK 收到重复或
旧 revision 时忽略;若发现 revision 跳跃或 Bridge 重连,取消旧订阅、重新 `get()` 并建立新的订阅。Web / Tauri 共享
golden fixture,且必须测试“get(revision 3) 与 subscribe 之间发生 replace(revision 4)”以及反向注册顺序的场景。
`expected_revision` 冲突只返回稳定错误 `session_data_revision_conflict`,第 04 次不自动合并 JSON。
## 本轮关闭条件
1. TIS2-01TIS2-05 已回填主迭代定义、实施规范与正式方案;TIS2-06 是已记录的 P4 延续项,在其重新评估触发条件出现前不阻塞第 04 次验收。
2. 第 04 次进入实现后,必须以本文件和实施规范的 Web / Tauri fixture、单元测试、构建与代表性 Host 流程验证这些决议;实现完成后进行下一轮独立验收评审。