Files
app/迭代/03.sdk_and_coreapp/03.design_review.md
T

14 KiB
Raw Blame History

03.sdk_and_coreapp 第 3 次设计评审记录

评审编号:03 评审日期:2026-08-05 评审对象:03.sdk_and_coreapp.md 参考资料:APP架构设计.md01.design_review.md02.design_review.md 评审方式:基于当前主定义的独立只读复核;重点检查已确认的边界在契约、实施步骤与验收目标之间是否能够由同一套实现兑现。 结论:产品层级、标准交互归属和受限 MiniApp 信任模型已稳定;未发现 P0 架构冲突。经本轮统一收敛,3 项 P1 与 2 项 P3 均已确认并回填主定义文档;后续不再进行纯设计评审,直接进入实现,并在实现完成后做一次关闭式复核。

问题清单(Outline

状态标记: 已确认并回填设计; 🟡 待产品/架构决策; 🔵 待在契约中细化; 文档或实施编排建议; — 不适用或无此问题。

本清单是本次评审的当前有效视图。后文说明问题为何会造成实现分歧,并给出需要冻结的最小决策;在问题确认前,建议不是实施依据。确认后应先更新本清单,再回填 03.sdk_and_coreapp.md 的契约、实施步骤和验收项。

状态 编号 问题 当前结论 / 下一步
P0 阻塞级架构冲突 未发现。Runtime 为唯一通信与裁决方、标准交互属于 Interact、bundled MiniApp 受限运行的主线一致。
P1-1 用户关闭 App 时,尚未结束的普通 MiniApp Tool 怎样收敛 已确认并回填:一旦 Runtime 接受关闭,未终态的普通 Tool 原子转为 cancelled(app_closed);已提交结果只继续 outbox;随后关闭 Surface、停止 instance、结束子会话并恢复焦点。标准交互不自动取消。
P1-2 Agent dismiss 等待中的标准交互,缺少可执行的控制契约 已确认并回填:Runtime 私有 interaction.dismisscontrol_id + call_id 请求;Runtime 从受认证 Envelope 推导 Agent/会话,幂等处理并只写唯一 cancelled outbox。App 已关闭事件带出仍 pending 的交互 call_id。
P1-3 interactive Tool 如何确定 App 子会话关联,和通用 ToolDescriptor.target 怎样一致 已确认并回填:无 app_session_context 一律归主 IM;有上下文时 Runtime 验证同 Agent、同父会话的 App 子会话,已关闭会话可仅作历史关联。interactive 不使用普通 Tool target。
P3-1 标准交互请求类型不能直接作为 fixture 或代码依据 已确认并回填:去除重复字段,定义请求联合类型;可回答交互使用 Runtime 计算的 expires_in_ms,默认 15 分钟、范围 1 分钟至 24 小时;notice 不接受期限。
P3-2 Whiteboard 的完成后关闭表述与统一生命周期规则冲突 已确认并回填:所有 bundled App 的普通 Tool 完成只结束 Tool;关闭 Surface/instance/子会话只能由显式 Lifecycle 关闭处理。重复目录条目已删除。

通过项

  • Interact 是唯一 kind = system MiniAppTask Dashboard 与 Whiteboard 均是 kind = bundled,没有可信 Host DOM、Tauri、Transport、Store、Agent 或任意网络特权。
  • notice / choice / confirm / input 始终是人与 Agent 的会话交互,不进入任何 MiniApp SDK Inbox 或 sdk.tools.subscribe;前台 bundled App 上的视觉覆盖不成为 owner 或提交权限。
  • Runtime 保存交互归属并以原子状态写入决定唯一结果;用户首次有效回答、Agent dismiss、到期和 Runtime 失败不会产生多条 Agent outbox。
  • App 子会话只保存人与 Agent 围绕 App 的交互,不记录 Dashboard 表单、画板编辑等 App 内部业务动作;关闭 App 不自动取消仍 pending 的 Interact 交互。
  • 普通 input 按现有 IM 内容与日志基线处理;秘密输入已正确作为未来独立的 password-input P4 遗留事项保留在 02.design_review.md

P0:阻塞问题

无。

P1:开始相关编码前必须确认(均已解决)

P1-1:用户关闭 App 时,尚未结束的普通 MiniApp Tool 怎样收敛

用人话说: 用户把 Task Dashboard 或 Whiteboard 关掉时,Runtime 不能让刚才交给那个 App 的工作 悬在半空。Agent 要么收到“这项工作已取消/失败”的唯一结果,要么 Runtime 明确保留一个可恢复、仍有执行者 的工作;不能只关闭画面而不说明 Tool 的命运。

当前文档同时出现了三种没有被统一的说法:

Task Dashboard Tool 完成
→ 不自动关闭 Dashboard 或 App 子会话

Whiteboard App 完成或失败
→ Runtime 关闭 Surface、恢复 Interact

MiniApp requestClose()
→ Runtime 检查 pending Tool、Surface、operation 和 Policy
→ 允许关闭或返回拒绝码

最后一条没有说明“检查之后”的规则。若用户关闭正在执行 Tool 的 App,Tool 是被拒绝关闭、由 Runtime 先取消 Tool、由 App 收到取消后再关闭,还是允许 Surface 消失但实例在后台恢复执行?这些选择对 outbox、恢复和用户 看到的状态都不同。Whiteboard 的“完成后关闭”也与 Task Dashboard 的“完成不关闭”相互冲突。

已确认(2026-08-05): 一旦 Runtime 接受用户、MiniApp 或 Policy 的关闭请求,关闭的意思就是释放该 App instance,不是把它偷偷留在后台。Runtime 不再向该 instance 投递新 Tool;对绑定该 instance 且仍为 received / routing / waiting_for_app / running 的普通 Tool,以 app_closed 原因原子转为 cancelled,并且 每条 Tool 只写一条 cancelled outbox。已处于 submitted 的 Tool 结果不可改写,Runtime 继续将已固定的结果 可靠发出。之后 Runtime 关闭 Surface、停止 instance、结束 App 子会话并恢复前一有效前台 App。

同一时刻 Tool 完成与关闭竞争时,第一个原子终态写入获胜;重复关闭、重启恢复和迟到上报不得产生第二条 outbox。用户若只想暂时离开 App,应进入后台而不是关闭。此规则只处理普通 MiniApp Tool;仍 pending 的 人与 Agent 标准交互不自动取消,Runtime 仅通知 Agent,由 Agent 选择是否 dismiss。

以下原“需要冻结”的项目均由上述决议覆盖:

  1. 对每种 Tool 状态(waiting_for_apprunningsubmitted 等),规定用户/Policy 请求关闭时的行为;
  2. 规定普通 Tool 的最终结果由谁写入、是否必须先让 Tool 进入 completed / failed / cancelled / expired 才能完成关闭;
  3. 明确“关闭 App instance”“关闭该 App 的 Surface”“Tool 成功/失败”三者不是同一个事件,并定义允许的先后顺序;
  4. 将 Task Dashboard 与 Whiteboard 的完成、关闭和焦点恢复规则统一到同一条生命周期原则;
  5. 增加关闭进行中 Tool、重启恢复和重复关闭只产生一个最终 Tool outbox 的验收 fixture。

P1-2Agent dismiss 等待中的标准交互,缺少可执行的控制契约

用人话说: 文档已经允许 Agent 看到“画板已关闭”后,决定把之前的问题收起来。这很好;但还没有写清 Agent 发来的“收起这题”消息长什么样,Runtime 怎么确认它收的是正确那一道题,以及网络重发时如何不重复 通知 Agent。实现者因此可能各自发明一个临时控制消息。

当前仅有行为描述:

Agent remote dismiss
→ Runtime 将 pending / presented interaction 终结为 cancelled
→ 写入唯一 cancelled outbox

但缺少下面的契约:

  • Agent 发起 dismiss 使用 interaction_id、原始 call_id,还是二者都使用;
  • Runtime 如何从已保存记录校验 agent_idconversation_id 与当前状态,而不是信任客户端字段;
  • 目标已回答、已到期或同一条 dismiss 重放时,应得到何种稳定回执,是否绝不新增 outbox;
  • Runtime 发出的 App 已关闭事件如何关联原 Tool/interaction,使 Agent 能准确选择要 dismiss 的问题;
  • dismiss 控制请求本身如何去重、审计并在 Runtime 重启后恢复处理。

已确认(2026-08-05): 定义 Runtime 私有的 Agent → Runtime interaction.dismiss 控制契约。Agent 使用 自己发起原 interactive Tool 时持有的 call_id 定位目标,并为每次控制请求提供唯一 control_id。Runtime 从 受认证 Envelope 取得 agent_idconversation_id,不信任请求额外携带的归属字段;它以这两个值和 call_id 查找交互,原子地将仍 pending / presented 的记录转为 cancelled 并写入唯一 outbox。已终态或重放 请求只返回稳定幂等回执,不覆盖结果、不再写 outbox。

App 已关闭事件会携带仍 pending 的 pending_interaction_call_ids,让 Agent 能按业务需要精确 dismiss;该控制 契约不属于 MiniApp SDK,也不能投递给 Interact 或 bundled MiniApp。

P1-3interactive Tool 如何确定 App 子会话关联,和通用 ToolDescriptor.target 怎样一致

用人话说: 视觉上哪个 App 在前台,不等于 Agent 的问题就属于哪个 App。例如用户正看 Whiteboard Agent 仍可能问一条普通 IM 问题;反过来,画板已经关了,Agent 仍可能针对刚才的画板提问。因此 Runtime 不能用“当前前台 App”猜测问题应该放进哪个子会话。

当前记录有可选 app_session_id,且要求与 App 有关的问题写进子会话;但没有说明 Agent Tool 请求如何 表达这层上下文、Runtime 如何验证它。与此同时,所有 ToolDescriptor 都要求 target.app_scope,而 interactive 明确不创建/复用任何业务 MiniApp,也不投递给 Interact 的 SDK Tool Inbox。这会造成至少两种 不兼容实现:有人将交互强行 target 到 chat,有人直接跳过 target,也有人按当前前台 App 自动归档。

已确认(2026-08-05): 不带 app_session_context 的 interactive Tool 一律记录在主 IM,不创建或猜测 App 子会话。Agent 若要关联某段 App 工作,可在 interactive Tool 的运行时上下文中提供 app_session_context.app_session_idRuntime 必须验证其属于同一 agent_id、父 conversation 和真实 App 子会话。已经关闭的子会话仍可作为历史上下文关联,但不会复活 instance 或旧问题。验证失败则拒绝该 Tool, 不创建交互。

handling = interactive 不使用普通 MiniApp Tool 的 target,也不因此变为 Interact MiniApp Tool。Runtime 在创建 App 子会话时向当前 Agent 可靠发送其稳定 ID,供后续 Agent 交互引用。

以下原“需要冻结”的项目均由上述决议覆盖:

  1. 不带经验证 App 上下文的 interactive Tool 一律写入主 IM,不创建 App 子会话;
  2. 若 Agent 需要关联某段 App 工作,定义它可引用的稳定 App 子会话标识,以及 Runtime 必须验证的 agent_id、父 conversation、App session 状态和权限边界;已关闭 App 关联的问题是否仍允许保留,需要明确;
  3. handling = interactive 定义与普通 ToolDescriptor.target 不同的明确规则:例如 target 对它不适用, 或只允许一个受限的“会话上下文”字段;不能让它暗中变成 Interact MiniApp Tool
  4. 在 fixture 中覆盖“Whiteboard 前台但问题属于主 IM”“App 已关闭但问题仍关联旧子会话”“非法/跨会话 app_session_id 被拒绝并不产生交互”三种情况。

P2:本迭代验收前必须处理(本次无未决项)

本次未发现独立 P2 问题。P1 项处理后,应把其中的关闭、dismiss、上下文绑定 fixture 纳入本迭代验收。

P3:本迭代结束前必须处理(均已解决)

P3-1:标准交互请求类型不能直接作为 fixture 或代码依据

ChoiceRequest 代码块中 prompt 出现两次。它不是不同字段,直接照抄会造成 TypeScript 重复属性定义。 此外,记录使用了尚未声明的 StandardInteractionRequest,文字规定 Agent 可给出 1 分钟至 24 小时的期限, 但四种最低请求类型都没有统一的期限字段。

已确认(2026-08-05): 删除重复 promptStandardInteractionRequest 由四种请求组成。可回答交互 在请求中使用 expires_in_ms,Runtime 根据自身当前时间计算并持久化 expires_at;未提供时默认 15 分钟, 仅接受 1 分钟至 24 小时。notice 不等待回答,也不接受期限。fixture 覆盖默认、越界和 notice 错带期限。

P3-2Whiteboard 的完成后关闭表述与统一生命周期规则冲突

Task Dashboard 已清楚规定 Tool 完成不会关闭 App;Whiteboard 的最小体验却写成“App 完成或失败,Runtime 关闭 Surface、恢复 Interact”。这会让两个同为 kind = bundled 的参考 App 获得不同且没有声明依据的 生命周期语义,也和“只有 AppLifecycleManager.close(instance_id) 才停止实例/结束子会话”不一致。

已确认(2026-08-05): Whiteboard 与 Task Dashboard 使用相同规则:Tool complete / fail 只结束 Tool Surface、instance、焦点和 App 子会话仅由前后台或显式 AppLifecycleManager.close 处理。SDK v1 不为 Whiteboard 预设“提交后自动关闭”的例外;将来若需要,必须作为显式 Lifecycle Policy 并遵循 P1-1 的关闭收敛。

实现模块目录树中的 conversation-store.ts 也重复出现一次,应一并删除重复行,避免错误引导目录改动。

P4P5:遗留问题

本次没有新增 P4/P5。第 2 次评审已登记的 P4-1(历史提案可读性)和 P4-2(未来 password-input 秘密输入原语)继续作为不阻塞当前迭代的遗留问题,其延期原因与重新评估条件以 02.design_review.md 为准。