18 KiB
04.runtime_workspace 技术实施规范评审(二)
评审编号: 02
日期: 2026-08-06
评审对象: 04.runtime_workspace.md(产品/验收权威)、05.technical_implementation_spec.md、06.technical_implementation_spec_review.md,以及 运行时与智能体工具.md、LineUp Runtime 与 App SDK 架构方案、LineUp App 最终设计方案。
评审方法: 由独立子代理只读复核当前文件,不沿用上一轮“已解决”结论;重点检查统一 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-01~TIS2-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-C1:Pomodoro 只有进入前台才真正开始
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 或 history;Runtime 不识别这些字段,也不直接向字典写 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-01:Runtime 如何调用未前台显示的 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 完成业务修改。
Agent Tool Call
→ Runtime:验证 Tool、schema、scope、幂等
→ Runtime:解析或建立目标 App session,等待 MiniApp ready
→ Runtime:投递 method + 已验证参数
→ MiniApp:理解业务、修改自己的 session data、返回结果
→ Runtime:验证、持久化 receipt / result,并回传 Agent
三个 activation requirement 的意义随之明确:
app_ready
= MiniApp 已 active / ready,Runtime 可路由方法调用;不要求前台
= 未来 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-02:SDK 声明 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 一同校验、签名和安装。
MiniApp 源码中的 SDK Tool 声明
├── 供 TypeScript 校验 handler、输入和输出
├── 供 Bundle 内 SDK 建立 method → handler 本地映射
└── 构建自动生成 Manifest tools 描述
→ Runtime 安装时验证并投影 Registry
→ Runtime 发布 Agent Inventory
运行时对普通 MiniApp Tool 的路径固定为:
Agent 调用 app_scope + method + params
→ Runtime 按生成 Manifest 校验、定位 ready App session
→ Runtime 投递到该 session 的统一 SDK Tool 接收入口
→ SDK 按 method 调用 Bundle 内已声明 handler
→ MiniApp 处理业务、写 session data、返回受控结果
Runtime 不保存、更不调用 MiniApp 私有函数 target;Manifest 不包含函数、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。因此这条调用固定分成两层:
Tool protocol receipt / progress
= accepted / starting:Runtime 已收到请求,正在把 Pomodoro 打开到前台
= started:Host 已确认前台,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-05:activation 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 CAS;CAS 只防止旧版本覆盖,不承诺
自动合并业务冲突。重新评估触发条件: 在开始任何一个“Agent Tool 与 UI Action 都能修改同一 App 子会话”的
功能之前,例如手动编辑 To-do 或 Whiteboard 的首个交互式绘制流程,必须先将本项提升为该迭代的 P1 并完成设计。
TIS2-04:session data 首帧与 revision 同步窗口
已解决(2026-08-06,收敛决议)。
本项只处理 Surface 读取自身 session data 时的版本同步,不处理 Agent 与 UI 同时修改数据的业务合并;后者已作为
TIS2-06 的 P4 延续项。若 Surface 先 get()、再 subscribe(),两次调用之间发生的 replace 不能被遗漏。第 04 次
冻结以下最小且跨 Host 一致的规则:
不存在 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。
本轮关闭条件
- TIS2-01~TIS2-05 已回填主迭代定义、实施规范与正式方案;TIS2-06 是已记录的 P4 延续项,在其重新评估触发条件出现前不阻塞第 04 次验收。
- 第 04 次进入实现后,必须以本文件和实施规范的 Web / Tauri fixture、单元测试、构建与代表性 Host 流程验证这些决议;实现完成后进行下一轮独立验收评审。