技术方案:Game Agent Runtime 交互边界重构 #168

Closed
suzmii wants to merge 6 commits from codex/game-agent-runtime-interaction-design into master
Member

关联 #167

变更内容

本 PR 重构 Game Agent Runtime 交互边界技术方案,并将原先集中在单篇长文档中的内容拆分为四份职责明确的文档:

  1. 总览与分阶段实施计划;
  2. 唯一规范性 Interaction Contract V1;
  3. 交互边界迁移矩阵;
  4. 证据与决策附录。

方案的目标是将 GUI、CLI 和自动化测试统一为同一协议的 Consumer:

  • Consumer 只读取公开状态并提交用户意图;
  • Supervisor Shell 统一负责交互决策、命令受理、幂等和结果读回;
  • Runtime 继续作为执行事实源;
  • Public / Developer read model 分离;
  • 不新增第二套 Runtime authority 或第二份 Conversation 正文;
  • 通过 P0–P6 分阶段迁移现有入口。

本 PR 不包含

  • 生产 Rust、TypeScript、Tauri 或 Runner 实现;
  • Runtime main loop、task queue 或 Agent 执行状态机重构;
  • Provider、LLM 或提示词调整;
  • Runner 开机自启或无人值守常驻;
  • Session rotation、handoff、ActiveSessionIndex 或 session control lease;
  • 全局 owner generation / lease;
  • 资源上传、Preview Registry 或 Session 管理面的重新设计。

文档权威关系

  • 总览:解释目标、边界和实施阶段;
  • Interaction Contract:唯一规范性协议,所有 IC-* 规则以此为准;
  • 迁移矩阵:将协议映射到当前代码和迁移动作;
  • 证据附录:记录代码事实、设计决策和验收门禁。

迁移矩阵和证据附录不得覆盖或改写 Interaction Contract。

验证

已完成:

  • npm run check:encoding
  • git diff --check
  • IC-* 定义与引用检查
  • Markdown fenced code block 配对检查
  • 本地 Markdown 链接检查

本 PR 只包含技术方案文档,不包含生产实现,也不代表 P0–P6 的实施验收已经完成。

关联 #167 ## 变更内容 本 PR 重构 Game Agent Runtime 交互边界技术方案,并将原先集中在单篇长文档中的内容拆分为四份职责明确的文档: 1. 总览与分阶段实施计划; 2. 唯一规范性 Interaction Contract V1; 3. 交互边界迁移矩阵; 4. 证据与决策附录。 方案的目标是将 GUI、CLI 和自动化测试统一为同一协议的 Consumer: - Consumer 只读取公开状态并提交用户意图; - Supervisor Shell 统一负责交互决策、命令受理、幂等和结果读回; - Runtime 继续作为执行事实源; - Public / Developer read model 分离; - 不新增第二套 Runtime authority 或第二份 Conversation 正文; - 通过 P0–P6 分阶段迁移现有入口。 ## 本 PR 不包含 - 生产 Rust、TypeScript、Tauri 或 Runner 实现; - Runtime main loop、task queue 或 Agent 执行状态机重构; - Provider、LLM 或提示词调整; - Runner 开机自启或无人值守常驻; - Session rotation、handoff、ActiveSessionIndex 或 session control lease; - 全局 owner generation / lease; - 资源上传、Preview Registry 或 Session 管理面的重新设计。 ## 文档权威关系 - 总览:解释目标、边界和实施阶段; - Interaction Contract:唯一规范性协议,所有 `IC-*` 规则以此为准; - 迁移矩阵:将协议映射到当前代码和迁移动作; - 证据附录:记录代码事实、设计决策和验收门禁。 迁移矩阵和证据附录不得覆盖或改写 Interaction Contract。 ## 验证 已完成: - `npm run check:encoding` - `git diff --check` - `IC-*` 定义与引用检查 - Markdown fenced code block 配对检查 - 本地 Markdown 链接检查 本 PR 只包含技术方案文档,不包含生产实现,也不代表 P0–P6 的实施验收已经完成。
suzmii added 2 commits 2026-08-13 15:28:26 +08:00
梳理Consumer与Supervisor Shell的现状边界
规划统一命令、状态投影、Runner自驱和分阶段迁移
明确旧公开接口的渐进下线与验收门禁
根据Review意见完善Game Agent Runtime交互协议
Project CI / Frontend tests (pull_request) Successful in 2m43s
Project CI / Native shell tests (pull_request) Successful in 13m45s
Project CI / Backend tests (pull_request) Failing after 8s
Project CI / Repository checks (pull_request) Failing after 8s
784facbdb3
补齐公开协议版本、事件身份、有序性、cursor与Snapshot revision规则

统一五个公开写命令的request ledger、请求指纹、幂等冲突、结果读回与崩溃恢复

补充Interaction identity、response去重、项目级PolicyApproval与锁内策略复核

拆分Public/Developer Snapshot,冻结公开字段白名单、稳定枚举与结构化错误

明确project/Runner/GUI owner、projection journal、恢复矩阵与自动调度门禁

调整分阶段实施边界、旧公开面检查范围并补充技术文档索引
suzmii added 1 commit 2026-08-13 15:43:46 +08:00
Merge branch 'master' into codex/game-agent-runtime-interaction-design
Project CI / Repository checks (pull_request) Successful in 1m28s
Project CI / Frontend tests (pull_request) Successful in 3m4s
Project CI / Backend tests (pull_request) Successful in 4m6s
Project CI / Native shell tests (pull_request) Failing after 10m14s
bc959b2a85
Owner

先说结论:方向认同,身份/ledger/投影三层的收敛做得很扎实。下面只针对 V1 公开写协议的表达能力提两点,其余部分不评。

两点的共同性质是:它们不是实现细节,而是 §8「协议冻结输出」一旦生效后无法靠 Consumer fallback 或新增字段绕过的缺口(§1.3.2 已经明确禁止「忽略未知字段」式兼容)。所以放在冻结前提。


1. submit_intent 没有承载「入口意图」的通道

§1.3.2 冻结的请求体是 { meta, sessionId, message, runProfile },配合 §1.3 的「source 由受信任 transport 固定映射,Consumer 不得自报任意 source」。

问题在于 transport 是「Tauri GUI / CLI / 测试夹具」这一层,不是「用户点了哪个按钮」这一层。同一个 GUI 里的多个入口映射到同一个 source,于是:

入口 A → submit_intent(session, "做个像空洞骑士的游戏", standard)
入口 B → submit_intent(session, "做个像空洞骑士的游戏", standard)

两个请求逐字节相同。requestFingerprint 都相同——§1.3.1 第 2 步规定指纹覆盖「完整业务 payload」但「transport 字段不进指纹」。后端没有任何确定性依据区分这两次调用。

两个看起来可行的替代都不成立:

  • 塞进 runProfile:它是执行档(standard / autonomous-game-build),表示「怎么执行」;入口意图表示「要做什么」。两者正交,合并会让同一字段承担两种语义,且 §1.3.2 限定 runProfile 只允许已注册的公开 profile 名称和版本。
  • message 推断:信息源本来是一次确定的按钮点击,从自由文本反推等于把确定信息降级成启发式。凡是需要「同一时刻最多一条某类 run」这种并发唯一性判定的场景,后端必须确定性地知道本次是不是该类启动,猜不出来。

建议

SubmitIntentCommand 增加一个业务字段(形态由本方案决定,intentKind 只是举例):

struct SubmitIntentCommand {
    meta: AgentRuntimeCommandMeta,
    session_id: String,
    message: String,
    run_profile: AgentRuntimeRunProfile,
    intent_kind: AgentRuntimeIntentKind,   // 稳定公开枚举
}

关键是「Consumer 可请求、后端可否决」,这样不破坏本方案原有的信任模型:

  • Consumer 只陈述点了哪个入口,不是权限主张;
  • Shell 在锁内按项目状态和策略校验,可拒(typed error)可无视;
  • Consumer 永远不能自报 source。后端查表只是从 transport → source 变成 (transport, intentKind) → source,映射权和否决权都还在后端。

顺带一个正效果:intentKind 作为业务字段进入 requestFingerprint,同 requestId 换 intent 会正确命中 IDEMPOTENCY_KEY_REUSED,而不是静默走错分支。

这不是个例

任何新增的用户入口都会撞同一堵墙——「从模板新建」「续做上一次的方案」「导入既有设计直接开建」。五命令冻结后若没有 intent 通道,以后每加一个入口,要么申请第六个命令,要么从自由文本里夹带。前者违反 §8 的冻结,后者违反 §1.1 的「Consumer 不得反向推导 Runtime 状态」的同一精神。


2. ApproveCommand 的二值 decision 表达不了「带意见退回重做」

§1.3.2 冻结 ApproveCommand { meta, interaction, decision }ApprovalDecision = Approve | Reject,且 §1.3.2 明确「未列出的字段不属于 V1……未知字段、重复字段和错误字段类型统一返回 INVALID_REQUEST,不得通过忽略未知字段实现兼容」。

这意味着审批类交互在 V1 里只有二值。但「用户看到产物 → 提出具体修改意见 → 退回重做 → 再次审批」是审批场景的常见第三态,它和 Reject(终止)在业务语义上完全不同:前者继续同一条工作链,后者收束它。二值方案下只能:

  • Reject 兼作退回 —— 语义丢失,后端无法区分「不要了」和「改一下」;
  • 让用户先 Reject 再重新 submit_intent —— 变成两次独立操作,中间状态无法保证原子,且丢掉了「这次修改针对的是哪一版产物」的绑定;
  • answer —— 但 §1.4 明确「answer 仅接受 UserInput,approve 仅接受 ToolApproval/PolicyApproval;命令与 kind 不匹配返回 INVALID_REQUEST」。

建议

二选一即可,不需要两个都做:

  1. ApprovalDecision 扩成稳定三值枚举(approve | reject | requestChanges 或等价命名),并允许 requestChanges 携带一个有界、可脱敏的意见正文字段;
  2. 或保持 decision 二值,但在 AgentRuntimePublicInteractionPresentation::PolicyApprovalallowed_decisions 中允许声明第三值,由 presentation 侧驱动。

无论哪种,正文字段都应纳入 §1.4 的 response fingerprint(「不能只散列自由文本」那条约束正好适用),并沿用 §1.4 已有的公开内容安全过滤。


以上两点都不是迁移工作量,而是协议表达能力:按 §1.3.2「不得通过忽略未知字段实现兼容」和 §8「任何实现若无法满足上述合同,必须先修改本技术方案并重新评审」,一旦冻结,补这两个缺口的门槛就从「改一版草案」变成「重新评审」。所以放在现在提。

先说结论:方向认同,身份/ledger/投影三层的收敛做得很扎实。下面只针对 **V1 公开写协议的表达能力**提两点,其余部分不评。 两点的共同性质是:它们不是实现细节,而是 §8「协议冻结输出」一旦生效后**无法靠 Consumer fallback 或新增字段绕过**的缺口(§1.3.2 已经明确禁止「忽略未知字段」式兼容)。所以放在冻结前提。 --- ## 1. `submit_intent` 没有承载「入口意图」的通道 §1.3.2 冻结的请求体是 `{ meta, sessionId, message, runProfile }`,配合 §1.3 的「`source` 由受信任 transport 固定映射,Consumer 不得自报任意 source」。 问题在于 **transport 是「Tauri GUI / CLI / 测试夹具」这一层,不是「用户点了哪个按钮」这一层**。同一个 GUI 里的多个入口映射到同一个 source,于是: ``` 入口 A → submit_intent(session, "做个像空洞骑士的游戏", standard) 入口 B → submit_intent(session, "做个像空洞骑士的游戏", standard) ``` 两个请求逐字节相同。**连 `requestFingerprint` 都相同**——§1.3.1 第 2 步规定指纹覆盖「完整业务 payload」但「transport 字段不进指纹」。后端没有任何确定性依据区分这两次调用。 两个看起来可行的替代都不成立: - **塞进 `runProfile`**:它是执行档(`standard` / `autonomous-game-build`),表示「怎么执行」;入口意图表示「要做什么」。两者正交,合并会让同一字段承担两种语义,且 §1.3.2 限定 `runProfile` 只允许已注册的公开 profile 名称和版本。 - **从 `message` 推断**:信息源本来是一次确定的按钮点击,从自由文本反推等于把确定信息降级成启发式。凡是需要「同一时刻最多一条某类 run」这种并发唯一性判定的场景,后端必须确定性地知道本次是不是该类启动,猜不出来。 ### 建议 给 `SubmitIntentCommand` 增加一个业务字段(形态由本方案决定,`intentKind` 只是举例): ```rust struct SubmitIntentCommand { meta: AgentRuntimeCommandMeta, session_id: String, message: String, run_profile: AgentRuntimeRunProfile, intent_kind: AgentRuntimeIntentKind, // 稳定公开枚举 } ``` **关键是「Consumer 可请求、后端可否决」,这样不破坏本方案原有的信任模型:** - Consumer 只**陈述**点了哪个入口,不是权限主张; - Shell 在锁内按项目状态和策略校验,可拒(typed error)可无视; - Consumer 永远不能自报 `source`。后端查表只是从 `transport → source` 变成 `(transport, intentKind) → source`,映射权和否决权都还在后端。 顺带一个正效果:`intentKind` 作为业务字段进入 `requestFingerprint`,同 `requestId` 换 intent 会正确命中 `IDEMPOTENCY_KEY_REUSED`,而不是静默走错分支。 ### 这不是个例 任何新增的用户入口都会撞同一堵墙——「从模板新建」「续做上一次的方案」「导入既有设计直接开建」。五命令冻结后若没有 intent 通道,以后每加一个入口,要么申请第六个命令,要么从自由文本里夹带。前者违反 §8 的冻结,后者违反 §1.1 的「Consumer 不得反向推导 Runtime 状态」的同一精神。 --- ## 2. `ApproveCommand` 的二值 decision 表达不了「带意见退回重做」 §1.3.2 冻结 `ApproveCommand { meta, interaction, decision }`,`ApprovalDecision = Approve | Reject`,且 §1.3.2 明确「未列出的字段不属于 V1……未知字段、重复字段和错误字段类型统一返回 `INVALID_REQUEST`,不得通过忽略未知字段实现兼容」。 这意味着**审批类交互在 V1 里只有二值**。但「用户看到产物 → 提出具体修改意见 → 退回重做 → 再次审批」是审批场景的常见第三态,它和 `Reject`(终止)在业务语义上完全不同:前者继续同一条工作链,后者收束它。二值方案下只能: - 用 `Reject` 兼作退回 —— 语义丢失,后端无法区分「不要了」和「改一下」; - 让用户先 `Reject` 再重新 `submit_intent` —— 变成两次独立操作,中间状态无法保证原子,且丢掉了「这次修改针对的是哪一版产物」的绑定; - 走 `answer` —— 但 §1.4 明确「`answer` 仅接受 UserInput,`approve` 仅接受 ToolApproval/PolicyApproval;命令与 kind 不匹配返回 `INVALID_REQUEST`」。 ### 建议 二选一即可,不需要两个都做: 1. `ApprovalDecision` 扩成稳定三值枚举(`approve | reject | requestChanges` 或等价命名),并允许 `requestChanges` 携带一个**有界、可脱敏**的意见正文字段; 2. 或保持 decision 二值,但在 `AgentRuntimePublicInteractionPresentation::PolicyApproval` 的 `allowed_decisions` 中允许声明第三值,由 presentation 侧驱动。 无论哪种,正文字段都应纳入 §1.4 的 response fingerprint(「不能只散列自由文本」那条约束正好适用),并沿用 §1.4 已有的公开内容安全过滤。 --- 以上两点都不是迁移工作量,而是协议表达能力:按 §1.3.2「不得通过忽略未知字段实现兼容」和 §8「任何实现若无法满足上述合同,必须先修改本技术方案并重新评审」,一旦冻结,补这两个缺口的门槛就从「改一版草案」变成「重新评审」。所以放在现在提。
suzmii marked the pull request as work in progress 2026-08-14 17:18:47 +08:00
suzmii added 1 commit 2026-08-16 12:10:03 +08:00
完善 Agent Runtime 交互边界重构协议
Project CI / Frontend tests (pull_request) Successful in 2m38s
Project CI / Repository checks (pull_request) Failing after 13s
Project CI / Backend tests (pull_request) Failing after 13s
Project CI / Native shell tests (pull_request) Failing after 9m56s
17684223ab
冻结 Public Snapshot、五命令和 Runtime 事件的权威边界
统一 Public wire schema、字段限制和 Rust 到 TypeScript 生成合同
补齐请求幂等、Interaction、审批、取消、恢复和 retry lineage 状态机
明确 submit、same-run steer、Goal Contract 与 slash management 路由
引入 durable record envelope、owner fencing 和跨平台恢复门禁
完善 Session rotation、handoff target 与 continuation set 恢复合同
拆分 direct reply、Runtime final reply、status 和 public event 交付
新增 Public conversation message、分页、去重和历史完整性合同
调整分阶段实施计划、兼容策略和编码前证据验收门禁
Author
Member

方案重构与重新请求评审

已吸收此前评审提出的两项 V1 协议表达能力问题:

  • submit_intent 现在显式携带 intentKind,由 Consumer 陈述入口意图、Shell 在策略和权限边界内复核;
  • approve 现在支持 requestChanges,并绑定有界 feedback、不可变目标和唯一 rework operation。

同时,为避免单篇长文档同时承担说明、规范、迁移和证据四种职责,候选方案已整理为四份互相引用的文档:

  1. 总览与实施计划:解释目标、边界和 P0–P6 的实施顺序;
  2. Interaction Contract V1:唯一规范性协议,定义 IC-* 规则;
  3. 迁移矩阵:将 Contract 映射到当前入口、迁移动作和阶段;
  4. 证据与决策附录:记录代码事实、设计选择和 EG-* 验收门禁。

本轮还补齐了此前 P2 审查发现的协议闭环:

  • Snapshot 订阅、路由、sequence、revision、hash 与重连语义;
  • source 的正常缺失、预期缺失、损坏和冲突处理;
  • fail-closed Snapshot 与 stale display 的区别;
  • Public / Developer 事件流隔离;
  • collaborator 的 durable collaborationId、retry lineage 和 fallback replacement;
  • Public DTO 不泄露动态 child identity;
  • answer / approve 对应的正式 interaction capability。

当前 PR 仍然只包含设计文档,不包含生产实现。
P0 可以在方案评审后开始建立现状基线和 fixture;P1–P6 仍需按各阶段的 EG-* 门禁实施和验收。

请重新评审时重点确认:

  1. 四份文档之间的职责和引用关系是否清楚;
  2. Contract 是否还存在会让不同实现者产生不同协议行为的缺口;
  3. P0–P6 的阶段顺序、边界和验收门禁是否足以指导后续实现。
## 方案重构与重新请求评审 已吸收此前评审提出的两项 V1 协议表达能力问题: - `submit_intent` 现在显式携带 `intentKind`,由 Consumer 陈述入口意图、Shell 在策略和权限边界内复核; - `approve` 现在支持 `requestChanges`,并绑定有界 feedback、不可变目标和唯一 rework operation。 同时,为避免单篇长文档同时承担说明、规范、迁移和证据四种职责,候选方案已整理为四份互相引用的文档: 1. **总览与实施计划**:解释目标、边界和 P0–P6 的实施顺序; 2. **Interaction Contract V1**:唯一规范性协议,定义 `IC-*` 规则; 3. **迁移矩阵**:将 Contract 映射到当前入口、迁移动作和阶段; 4. **证据与决策附录**:记录代码事实、设计选择和 `EG-*` 验收门禁。 本轮还补齐了此前 P2 审查发现的协议闭环: - Snapshot 订阅、路由、sequence、revision、hash 与重连语义; - source 的正常缺失、预期缺失、损坏和冲突处理; - fail-closed Snapshot 与 stale display 的区别; - Public / Developer 事件流隔离; - collaborator 的 durable `collaborationId`、retry lineage 和 fallback replacement; - Public DTO 不泄露动态 child identity; - answer / approve 对应的正式 interaction capability。 当前 PR 仍然只包含设计文档,不包含生产实现。 P0 可以在方案评审后开始建立现状基线和 fixture;P1–P6 仍需按各阶段的 `EG-*` 门禁实施和验收。 请重新评审时重点确认: 1. 四份文档之间的职责和引用关系是否清楚; 2. Contract 是否还存在会让不同实现者产生不同协议行为的缺口; 3. P0–P6 的阶段顺序、边界和验收门禁是否足以指导后续实现。
suzmii added 1 commit 2026-08-17 22:00:58 +08:00
重构 Game Agent Runtime 交互边界设计文档
Project CI / Backend tests (pull_request) Failing after 14s
Project CI / Repository checks (pull_request) Failing after 15s
Project CI / Frontend tests (pull_request) Successful in 2m41s
Project CI / Native shell tests (pull_request) Failing after 10m32s
ec565b8d5d
将原交互边界长文档拆分为总览、Contract、迁移矩阵和证据附录
冻结 Snapshot、事件、Capability、Interaction、Conversation 和错误合同
明确 P0–P6 阶段边界、Writer Cutover 与分阶段证据门禁
更新文档索引和四份设计文档的权威阅读顺序
suzmii added 1 commit 2026-08-17 22:10:19 +08:00
Merge branch 'master' into codex/game-agent-runtime-interaction-design
Project CI / Repository checks (pull_request) Successful in 1m12s
Project CI / Frontend tests (pull_request) Successful in 3m2s
Project CI / Backend tests (pull_request) Successful in 3m42s
Project CI / Native shell tests (pull_request) Successful in 13m49s
c675c08f2e
suzmii marked the pull request as ready for review 2026-08-17 22:15:42 +08:00
suzmii marked the pull request as work in progress 2026-08-17 22:15:49 +08:00
suzmii requested review from kdletters 2026-08-17 22:15:53 +08:00
suzmii marked the pull request as ready for review 2026-08-17 22:49:39 +08:00
suzmii closed this pull request 2026-08-20 23:04:09 +08:00
Some checks are pending
Project CI / Repository checks (pull_request) Successful in 1m12s
Project CI / Frontend tests (pull_request) Successful in 3m2s
Project CI / Backend tests (pull_request) Successful in 3m42s
Project CI / Native shell tests (pull_request) Successful in 13m49s

Pull request closed

Sign in to join this conversation.