diff --git a/docs/README.md b/docs/README.md index 471c17e62..53b06587e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -34,6 +34,16 @@ - [浏览器内 AI Web 工程沙箱预览](./technical/【技术方案】浏览器内AIWeb工程沙箱预览方案-2026-06-13.md) - [AI Web 工程 Runner 安全模型](./technical/【安全模型】AIWeb工程Runner与预览隔离威胁模型-2026-06-13.md) +### AI 游戏创作 Runtime + +1. [AI 游戏创作 Agent Runtime 交互边界重构总览与实施计划](./technical/【技术方案】AI游戏创作Agent%20Runtime交互边界重构实施计划-2026-08-12.md) +2. [AI 游戏创作 Agent Runtime 交互合同 V1(唯一规范性协议)](./technical/【技术协议】AI游戏创作Agent%20Runtime交互合同V1-2026-08-17.md) +3. [AI 游戏创作 Agent Runtime 交互边界迁移矩阵](./technical/【迁移方案】AI游戏创作Agent%20Runtime交互边界迁移矩阵-2026-08-17.md) +4. [AI 游戏创作 Agent Runtime 交互边界证据与决策附录](./technical/【设计依据】AI游戏创作Agent%20Runtime交互边界证据与决策附录-2026-08-17.md) +5. [AI 游戏创作 Agent Runtime V1.1](./technical/【技术方案】AI游戏创作Agent%20Runtime%20V1.1-2026-07-12.md) + +上述四份交互边界文档按“总览 → Contract → 迁移矩阵 → 证据附录”阅读;字段、状态机和错误语义只以 Contract 中的 `IC-*` 为准。 + ### 后端与公开数据 - [外部生成 Worker 化方案](./technical/【后端架构】外部生成Worker化方案-2026-06-03.md) diff --git a/docs/technical/【技术协议】AI游戏创作Agent Runtime交互合同V1-2026-08-17.md b/docs/technical/【技术协议】AI游戏创作Agent Runtime交互合同V1-2026-08-17.md new file mode 100644 index 000000000..383d38739 --- /dev/null +++ b/docs/technical/【技术协议】AI游戏创作Agent Runtime交互合同V1-2026-08-17.md @@ -0,0 +1,1393 @@ +# AI 游戏创作 Agent Runtime 交互合同 V1 + +> 文档角色:唯一规范性协议 +> schemaVersion:`game-creator-agent-interaction.v1` +> 状态:评审中;规则已采用默认失败关闭,完成冻结评审前不得进入生产实现 +> 配套总览:[`【技术方案】AI游戏创作Agent Runtime交互边界重构实施计划-2026-08-12.md`](./【技术方案】AI游戏创作Agent%20Runtime交互边界重构实施计划-2026-08-12.md) +> 实现映射:[`【迁移方案】AI游戏创作Agent Runtime交互边界迁移矩阵-2026-08-17.md`](./【迁移方案】AI游戏创作Agent%20Runtime交互边界迁移矩阵-2026-08-17.md) +> 设计证据:[`【设计依据】AI游戏创作Agent Runtime交互边界证据与决策附录-2026-08-17.md`](./【设计依据】AI游戏创作Agent%20Runtime交互边界证据与决策附录-2026-08-17.md) + +## 0. 规范解释 + +本文中的 `MUST`、`MUST NOT`、`SHOULD`、`MAY` 为规范词: + +- `MUST`:实现和测试必须满足; +- `MUST NOT`:实现禁止出现; +- `SHOULD`:除非有重新评审通过的明确理由,否则必须满足; +- `MAY`:允许但不要求。 + +所有正式实现、schema、fixture、迁移矩阵和评审 finding 必须引用稳定 `IC-*` 编号。总览、迁移矩阵和证据附录不得重新定义本文规则。 + +--- + +## 1. 参与者与权威边界 + +### IC-ARC-001:唯一公开控制边界 + +GUI、普通 CLI 和面向公开协议的测试 MUST 作为平等 Consumer,只通过本文 read model 和五个写命令操作 Project Supervisor Runtime。transport 可以是 Tauri、Runner RPC 或进程内测试,但 MUST 复用同一语义和 handler。 + +### IC-ARC-002:Consumer 职责 + +Consumer MUST 只执行: + +```text +render(snapshot) +dispatch(command) +read(conversation) +``` + +Consumer MUST NOT: + +- 根据 Runtime phase、自然语言文案或私有字段选择 start/steer/retry/resume; +- 直接推进 pending、timer、lane、ready task 或 finalization; +- 从 event 或 conversation 推导 Runtime 成功; +- 把 Runtime output 再 append 成第二条正式聊天消息; +- 自报 Developer、Runner internal 或其它受信任 capability。 + +### IC-ARC-003:Supervisor Shell 职责 + +Supervisor Shell MUST: + +- 完成 schema、身份、权限、目标、capability 和幂等校验; +- 将 `submit_intent` 统一路由为 direct reply、start、steer、reject 或 interaction required; +- 通过 Adapter 绑定现有 Runtime identity; +- 生成 Public/Developer projection; +- 提供可重试的 request result read-back。 + +Shell MUST NOT 把 request/projection record 当成 Runtime task、provider、steer、finalization 或 conversation 的第二事实源。 + +### IC-ARC-004:Runtime 事实源 + +现有 Runtime durable state、task、pending/action、provider retry、steer、finalization、conversation 和 event records MUST 继续决定执行事实。新 record MAY 保存协调状态、source binding、projection metadata 和 request read-back,但 MUST NOT 覆盖、重写或重新解释 Runtime 事实。 + +### IC-ARC-005:Public 与 Developer 分离 + +Public DTO 和 Developer DTO MUST 为不同类型和调用面。Developer capability MAY 扩大 read,但 MUST NOT 允许正式 Project Supervisor 写操作绕过五命令或 owner 门禁。专业/child Agent 的直接调试控制只能留在明确的受信任管理面,不得伪装成 Public Supervisor 协议。 + +--- + +## 2. Wire、身份、权限与 owner + +### IC-WIRE-001:版本与序列化 + +所有 Public Snapshot、event envelope、command、command response、command error 和 conversation DTO MUST 携带或协商: + +```text +schemaVersion = game-creator-agent-interaction.v1 +``` + +Rust 字段 MUST 序列化为 camelCase;业务枚举 MUST 使用 lowerCamelCase;结构化错误码 MUST 使用 SCREAMING_SNAKE_CASE。 + +带数据 union MUST 使用扁平内部 tag: + +```json +{ "kind": "conversation", "sessionId": "..." } +``` + +未知、缺失或重复 `kind`,未知字段、重复字段、错误类型和超限字段 MUST 在任何项目副作用前返回 `INVALID_REQUEST`。V1 MUST NOT 通过忽略未知字段兼容未来版本。本文的 Rust 片段是规范性 DTO:除明确标记 `Option`、`Vec` 或“可省略”的字段外,字段均为必填;Public Snapshot 及其嵌套对象不得添加未在 Contract 定义的字段。所有本文引用但非原始标量的 Public 类型必须由本节或后续 `IC-*` 条款冻结其 wire shape/枚举,不得由 Consumer 自行补充。 + +### IC-WIRE-002:统一边界常量 + +Rust MUST 作为边界常量、schema 和 fingerprint 规范的单一来源,并生成或校验 TypeScript schema 与 golden fixture。至少冻结: + +| 对象 | V1 限制 | +|---|---| +| 通用 Public ID/cursor | `1–128` UTF-8 bytes;无控制字符、路径分隔符和首尾空白 | +| 单 command JSON | 最大 `64 KiB` UTF-8 | +| Conversation message | 非空;最大 `4,000` Unicode scalar 且最大 `16 KiB` UTF-8 | +| requestChanges feedback | 非空;最大 `2,000` Unicode scalar,并通过公开内容安全过滤 | +| 单 Public Snapshot | 最大 `256 KiB` UTF-8;collaborators/interactions 各最多 `128`,latestChecks 最多 `32`;超限不得截断或发布 partial DTO | +| Public 摘要/标题/问题/选项/error message 字段 | 最大 `1,000` Unicode scalar 且最大 `4 KiB` UTF-8;Conversation 与 requestChanges 使用各自更严格/专用上限 | +| 单 Developer Snapshot | 最大 `512 KiB` UTF-8;runs/interactions 各最多 `128`,diagnostics 最多 `256` | +| Developer summary | 最大 `1,000` Unicode scalar 且最大 `4 KiB` UTF-8;diagnostic code 最大 `128` UTF-8 bytes | +| UserInput questions | `1–3` | +| 每题 options | `2–3`;freeform 始终可用 | +| digest | V1 仅 `sha256`;64 位小写十六进制 | + +历史 Runtime response stream 的 `32,000` Unicode scalar 兼容限制 MUST NOT 被本文悄悄改成新的 byte cap;若修改必须提升 schema/version 并单独迁移。 + +### IC-ID-001:项目身份 + +`projectId` MUST 来自现有项目 manifest 且在项目生命周期内不可变。`projectPath`、绝对路径、locator handle、导出路径和本地配置目录 MUST NOT 进入 Public DTO、Public conversation 或 Runtime prompt。 + +Shell 的内部入参 MUST 是受信任宿主已解析的 `TrustedProjectContext { projectId, canonicalRoot }`,而不是 Consumer 提交的 root。Tauri/Runner transport 可以使用其宿主保存的 locator 或本地 root;它 MUST 在任何 ledger、owner 或 Runtime 操作前 canonicalize root、读取 manifest,并复核其 `projectId` 与 command `projectId` 一致。找不到或不一致时分别失败为 `PROJECT_NOT_FOUND` / `PROJECT_ID_MISMATCH`,不得把 Public `projectId` 当作文件系统路径或让 Consumer 补传路径。 + +### IC-ID-002:Session 身份 + +`sessionId` MUST 来自现有按 Agent 持久化的 Session catalog。`sessionCatalogVersion` 是对 **Project Supervisor Agent 完整 catalog** 计算的 opaque digest/stale guard: + +- MUST 是字符串,不得由 Consumer 构造; +- MUST NOT 写回 catalog; +- MUST NOT 成为第二 session revision 或 active-session authority; +- MUST NOT 代表 collaborator/child Agent 的 Session catalog。 + +V1 MUST NOT 新增 live Session rotation、handoff manifest、ActiveSessionIndex 或 session control lease。 + +### IC-ID-003:Run 与历史归属 + +每个 command、interaction 和 delivery MUST 显式携带或通过 private binding 保存 `agentId + sessionId + runId`。历史记录 MUST 按已落盘 identity 回读,MUST NOT 根据当前 active Session、文件位置、时间或 GUI 窗口重新归属。 + +对公开的协作组摘要和 `PublicInteractionContext::Collaborator`,Shell MUST 在首次确认同一 parent Supervisor run 下的一项协作执行时,分配并在 Shell ledger 持久化不透明 `collaborationId`。其 private binding 至少固定 `projectId + parentSupervisorAgentId + parentRunId + collaborationId`,并关联 group、original/current Agent 与 run identity、source 和 predecessor/successor lineage。一个 parent run 中同一 group 可以有 `0..N` 个协作 binding;Public 以 `collaborationId` 区分,不得仅以 group 或动态 child `agentId` 去重。retry/successor MUST 保留原 `collaborationId` 并更新 current identity/lineage;isolated 执行是该 binding 的执行方式,不另造公开身份。`manifestFallback` 只可为尚无 Runtime binding 的静态 group 占位;Runtime binding 出现后 MUST 替换该占位,二者不得并列表示同一协作实体。Shell 只可经 private binding 将 Collaborator interaction 解析到真实目标,Public DTO 不得暴露 dynamic child identity。 + +现有 catalog 的“有 live task 时拒绝 create/fork/archive/set-active”语义 MUST 保持不变。 + +### IC-ID-004:Request 身份 + +每个写命令 MUST 包含: + +```rust +struct CommandMeta { + schema_version: String, + project_id: String, + request_id: String, +} +``` + +`requestId` 标识一次 Public command,不等于 runId、steerId、interactionId、messageId 或 finalizationId。 + +### IC-ID-005:Opaque identity + +所有 Public ID 和 cursor MUST 视为不透明值。Consumer MUST NOT 从 ID 前缀、路径、时间、进程号或字符串结构推导对象类型、顺序或权限。 + +### IC-AUTH-001:调用来源 + +transport MUST 从受信任宿主上下文传递 principal/capability;Consumer payload MUST NOT 自报来源权限。权限拒绝 MUST 在创建项目 command ledger 或执行副作用前完成。 + +### IC-OWNER-001:执行权威 + +现有 `.agent/runtime/execution-owner.lock` 的 OS 排他锁 MUST 是项目执行写入权威。`execution-owner.json` 和 Runner `bootId` 只用于诊断关联,MUST NOT 用于 lease 接管或判断旧 owner 已死亡。 + +启用 External Runner 时,正式五命令和投影修复 MUST 在持有 owner lock 的 Runner 内 Shell handler 执行。GUI/CLI MUST 只是 transport adapter。未启用 Runner 的进程内模式和测试 MUST 使用同一 Shell handler,并在创建 Shell record、修复 projection 或调用 Runtime primitive **之前**取得同一 OS owner-lock 实现;per-Agent task/run/action lock 不能替代 project execution owner。 + +失去 owner lock、Runner draining 或无法证明 owner 状态时 MUST 停止新写入并返回 `OWNER_UNAVAILABLE`、`TRANSIENT_UNAVAILABLE` 或进入 reconciliation;MUST NOT 根据诊断 JSON、mtime 或本地时钟接管。 + +### IC-OWNER-002:锁顺序 + +正式写路径 MUST 按以下顺序取得锁: + +```text +project execution owner +→ supervisor project lock +→ command / interaction / projection 子记录锁 +→ 现有 Runtime 自身 run/action 锁 +``` + +这里的 `supervisor project lock` 只在已持有 execution owner 的进程内串行 Shell handler;它不是第二个跨进程 owner、不得自行 stale reclaim,也不得用 PID、mtime、诊断 JSON 或本地时钟接管。现有 `.agent/project.lock` 的 create-new/PID/超时回收语义不是这个锁,MUST NOT 直接复用为 Shell protocol lock。P1 可以用 owner-guard 内的进程内 mutex 或不带回收语义的专用子锁实现它;子记录锁只保护具体 command、interaction 或 projection record,不能提升为执行权威。 + +MUST NOT 持有文件锁等待 Consumer;MUST NOT 绕过现有 Runtime 锁顺序。 + +--- + +## 3. Durable record 与幂等结果 + +### IC-DUR-001:Record envelope + +新增 project durable record MUST 至少包含: + +```rust +struct DurableEnvelope { + schema_version: String, + record_id: String, + record_revision: u64, + ledger_version: u64, + project_id: String, + checksum: String, + owner_boot_id: String, + created_at: u64, + updated_at: u64, +} +``` + +- `recordRevision` 从 1 开始并随同一 record 状态变化递增; +- `ledgerVersion` 只表示追加顺序,不能代替 record revision; +- `checksum` MUST 覆盖除 checksum 字段外的完整 canonical record; +- envelope 与 body 重复出现的 `projectId` 不一致时 MUST 按损坏隔离; +- `ownerBootId` MUST NOT 替代 OS owner lock。 + +本文的 `canonical` 固定为 **RFC 8785 JSON Canonicalization Scheme** 的 UTF-8 bytes;`checksum`、request fingerprint 与 `snapshotHash` 必须各自对其规定的完整值使用同一实现和 sha256。实现 MUST 用 RFC 8785 test vectors 覆盖 Unicode、数字、object key ordering、嵌套对象与 checksum 字段剔除;MUST NOT 用 `serde_json::to_string`、pretty JSON、结构体声明顺序或各模块自定义排序代替 canonicalization。 + +P1 Shell record MUST 存在专用私有 namespace `.agent/runtime/supervisor-shell/`;其 command、interaction/rework mapping 与 projection journal 各有明确 record kind 和 bounded retention/read-back 规则。它 MUST NOT 混入 `.agent/agent.db` 或现有 Runtime task/finalization journal,因为它们的 authority、scan/retention 和损坏隔离边界不同。 + +### IC-DUR-002:原子持久化 + +P1 实现 MUST 使用当前平台可证明的原子写、写后回读和目录/文件持久化语义。无法证明 prepared record 已 durable 时 MUST NOT 进入真实副作用。torn/corrupt record MUST 被隔离并阻止自动重放。现有 JSON sidecar helper 只有在保持临时文件写入、文件同步、原子 replace、父目录同步、回读和 symlink/size 检查的前提下才 MAY 复用;它本身不定义 command ledger 的 record 生命周期。 + +### IC-DUR-003:Shell ledger 的唯一顺序与重建 + +`.agent/runtime/supervisor-shell/ledger.jsonl` MUST 是 Shell coordination record 的唯一追加顺序 authority。每个 durable record transition MUST 作为一条完整、带 `DurableEnvelope` 的 canonical JSON line 追加;`ledgerVersion` 从 1 开始,按该文件最后一条有效 line 的物理追加顺序严格递增。command、interaction/rework mapping、source binding 和 projection transition 共享同一序列,但仍用各自 record kind 和 `recordId` 区分。 + +追加必须在 `IC-OWNER-002` 的 owner/supervisor lock 内完成,并在任何真实副作用前同步、回读并核验 checksum。仅最后一条未完成/torn tail MAY 在同一锁内截除;中间行格式、checksum、projectId、recordRevision 或 ledgerVersion 不连续/冲突时,整个 Shell ledger MUST 隔离为 corrupt,不得跳过坏行继续追加或自动重放。 + +为了避免把 JSONL 扫描上限误当协议语义,read-back index、per-record materialization 和 projection checkpoint MAY 作为派生缓存;它们与 ledger 不一致时 MUST 从有效 ledger 重建或失败关闭,MUST NOT 覆盖 ledger。若未来需要 compact,必须先 durable 写入可验证 checkpoint,并永久保留每个已受理 request 的 `requestId + fingerprint + result/read-back binding`;P3 在此之前不得以删除 terminal record 的方式缩短幂等窗口。 + +### IC-IDEMP-001:Request fingerprint + +request fingerprint MUST 覆盖: + +```text +schemaVersion + commandKind + projectId + 完整规范化业务 payload +``` + +MUST NOT 覆盖 transport source、locator、时间戳、重试次数、日志或响应展示文案。 + +### IC-IDEMP-002:同键重放 + +- 同 `requestId` + 同 fingerprint:MUST 返回原结果或当前 in-progress/unknown 状态,不重复真实副作用; +- 同 `requestId` + 不同 fingerprint:MUST 返回 `IDEMPOTENCY_KEY_REUSED`,零副作用; +- Consumer transport 超时:MUST 使用相同 requestId 重试或 read-back,MUST NOT 换 requestId fallback 到旧命令。 + +### IC-IDEMP-003:结果状态 + +command record MUST 能区分: + +```text +prepared +executing +succeeded +rejected +outcome-unknown +corrupt +``` + +`succeeded/rejected` 只表示该 request 已映射到可读回的 durable source evidence;MUST NOT 由 Shell 自己的协调状态伪造 Runtime 成功或失败。 + +### IC-IDEMP-004:未知结果 + +若真实 Runtime/Provider/工具副作用可能已经发生,但无法唯一证明结果,command MUST 进入 `outcome-unknown` 或 Runtime `needs-reconciliation`。任何 Consumer、Runner recovery 或 retry MUST NOT 自动重放该真实副作用。 + +### IC-IDEMP-005:Result read-back + +Shell MUST 提供按 `projectId + requestId` 的结果读回。身份、权限或结构校验失败且请求从未进入 project ledger 时 MAY 返回 `REQUEST_NOT_FOUND`;已进入 ledger 的业务拒绝 MUST durable `rejected` 并可重放。 + +--- + +## 4. Read model 与出向事件 + +### IC-READ-001:Public Snapshot 是完整 Public 状态 + +Public Snapshot MUST 是正式 Consumer 唯一完整 Runtime 状态视图。它是现有 facts 的可重建投影,不是执行事实源。 + +V1 Public Snapshot 的 wire shape 固定为以下字段;实现不得增加未在本文定义的 Public 字段: + +```rust +struct PublicSnapshot { + schema_version: String, + project_id: String, + supervisor_agent_id: String, + session_context: SessionContext, + session_id: Option, + session_catalog_version: Option, + snapshot_revision: u64, + snapshot_hash: String, + status: PublicStatus, + stage: PublicStage, + waiting_on: PublicWaitingOn, + next_step: PublicNextStep, + outcome: Option, + progress: Option, + collaborators: Vec, + interactions: Vec, + command_capabilities: CommandCapabilities, + error: Option, +} +``` + +Public 投影在规范排序和内容安全过滤后若任一数量、字符串或总 wire size 超出 `IC-WIRE-002`,MUST 返回 `PUBLIC_SNAPSHOT_LIMIT_EXCEEDED` read error;不得截断 collaborator、interaction、capability 或发布 partial/failClosed DTO。 + +每个已发布 Snapshot 都是一个确定 observation outcome:`valid` 或 `failClosed`。只要完整 Public 白名单值发生变化,两个 outcome 都 MUST 推进该 view scope 的 `snapshotRevision`;初次发布从 1 开始。无法确定任何安全 outcome 时,read/transport MUST 返回错误,MUST NOT 伪造或复用 Snapshot。 + +`snapshotHash` MUST 等于 `sha256(RFC8785_CanonicalJSON(SnapshotWithoutSnapshotHashAndSnapshotRevision))`。除 `snapshotHash`、`snapshotRevision` 外,Snapshot 的所有字段都属于 hash 输入;`eventId`、event `sequence`、connection/subscription identifier、delivery timestamp、projection record revision/ledgerVersion 不是 Snapshot 字段,不得进入 hash。所有数组 MUST 按下列稳定 key 排序后再 canonicalize:`activeGroups` 按 group wire value、`latestChecks` 按其公开 id、`collaborators` 按 `collaborationId`、`interactions` 按 `interactionId`、capability 内各数组按其完整 canonical JSON 字节序。`updatedAt` 是由 source record 提供的公开状态更新时间,属于 hash 输入;不得在每次 projection read 时用当前 wall clock 重写。相同规范 Snapshot MUST 得到相同 hash;hash 未变化时 MUST NOT 推进 revision 或发出事件。 + +进度与专业组的最小 Public DTO 冻结为: + +```rust +struct SupervisorProgressView { + supervisor_run_id: String, + loop_iteration: u32, + task_progress: ProgressCount, + plan_progress: ProgressCount, + active_groups: Vec, + latest_checks: Vec, + latest_rework_summary: Option, + updated_at: u64, +} + +struct CollaboratorSummary { + collaboration_id: String, + group: CollaboratorGroup, + source: CollaboratorProjectionSource, // runtime | manifestFallback + status: CollaboratorPublicStatus, + stage: Option, + completed_step_count: Option, + total_step_count: Option, + current_task_summary: Option, + outcome: Option, + error: Option, + updated_at: u64, +} + +struct ProgressCount { completed: u32, total: u32 } +struct PublicCheckSummary { id: String, status: PublicCheckStatus, summary: String } +struct SnapshotError { code: SnapshotErrorCode, message: String } + +enum CollaboratorProjectionSource { Runtime, ManifestFallback } +enum CollaboratorPublicStatus { Pending, Running, Waiting, Completed, Failed, Cancelled, Unknown } +enum CollaboratorPublicStage { Preparing, Executing, Coordinating, WaitingForUserInput, WaitingForUserApproval, Finalizing } +enum PublicCheckStatus { Pending, Passed, Failed, Skipped } +enum CollaboratorGroup { Design, Art, Code, Balance, Audio, Publishing } +enum SessionContext { Ready, NeedsBootstrap, NeedsReconciliation } +enum PublicStatus { Idle, Preparing, Queued, Running, Waiting, Paused, Cancelling, Completed, Failed, Cancelled, TerminalPending, NeedsReconciliation } +enum PublicStage { Idle, Preparing, PublicStatusPending, Planning, Executing, Coordinating, WaitingForUserInput, WaitingForUserApproval, WaitingForPolicyApproval, WaitingForDeveloperApproval, WaitingForTimer, WaitingForRunner, PausedByUser, Cancelling, Finalizing, Reconciling, Completed, Failed, Cancelled, TerminalPending } +enum PublicWaitingOn { None, PublicStatusMessage, UserInput, UserApproval, PolicyApproval, DeveloperApproval, Timer, Runner, Reconciliation } +enum PublicNextStep { None, WaitForPublicStatus, SubmitIntent, AnswerInteraction, ApproveInteraction, CancelRun, ResumeRun, RetryTerminalRun, WaitForRunner, Reconcile } +enum PublicOutcome { Success, Failure, Cancelled, Unknown } +``` + +`CollaboratorGroup` 固定为 `design/art/code/balance/audio/publishing`。`sessionContext=needsBootstrap` 且 `sessionId=None` 时,`collaborators` MUST 为空,不得创建 `manifestFallback`;Session ready 后才按已验证 session identity 建立 fallback,避免 bootstrap/ready 之间重分配或重复公开实体。`manifestFallback` 只表示当前 manifest 静态组信息:它 MUST 使用 `status=pending`,`stage/completedStepCount/totalStepCount/currentTaskSummary/outcome/error` 均为 None,且不得生成 interaction、recovery 或 command capability。它的 `collaborationId` MUST 是 Shell 为 `(projectId, supervisorAgentId, sessionId, manifestDigest, group)` 占位持久化的 ID,并受 `IC-ID-003` 的 Runtime binding 替换规则约束;若已有 parent run,则 binding 还必须记录该 parent run。Runtime source 缺失而按依赖矩阵本应存在时,不得降级为 `manifestFallback`,必须 fail-closed。Runtime binding 出现时应复用该 fallback 的 `collaborationId` 并原子替换其 source/binding;只有 fallback 与 Runtime identity 已冲突时才分配新 ID并从 Public 同时移除旧占位。`RepairApprovalPending` 只能引用同一 Public PolicyApproval interaction,不能自己生成第二写命令。 + +V1 稳定枚举值冻结如下: + +| 字段 | lowerCamelCase wire value | +|---|---| +| `sessionContext` | `ready`、`needsBootstrap`、`needsReconciliation` | +| `status` | `idle`、`preparing`、`queued`、`running`、`waiting`、`paused`、`cancelling`、`completed`、`failed`、`cancelled`、`terminalPending`、`needsReconciliation` | +| `stage` | `idle`、`preparing`、`publicStatusPending`、`planning`、`executing`、`coordinating`、`waitingForUserInput`、`waitingForUserApproval`、`waitingForPolicyApproval`、`waitingForDeveloperApproval`、`waitingForTimer`、`waitingForRunner`、`pausedByUser`、`cancelling`、`finalizing`、`reconciling`、`completed`、`failed`、`cancelled`、`terminalPending` | +| `waitingOn` | `none`、`publicStatusMessage`、`userInput`、`userApproval`、`policyApproval`、`developerApproval`、`timer`、`runner`、`reconciliation` | +| `nextStep` | `none`、`waitForPublicStatus`、`submitIntent`、`answerInteraction`、`approveInteraction`、`cancelRun`、`resumeRun`、`retryTerminalRun`、`waitForRunner`、`reconcile` | +| `outcome` | `success`、`failure`、`cancelled`、`unknown`;无终局时字段为 None,不使用字符串 `none` | + +未知稳定枚举值 MUST 按不支持的协议版本失败关闭,Consumer 不得显示原始值并继续构造命令。 + +### IC-READ-002:Public 白名单 + +Public Snapshot MAY 暴露: + +- 项目和当前 Project Supervisor 的不透明身份; +- 紧凑 status/stage/waitingOn/nextStep/outcome; +- 有界 progress 和公开检查摘要; +- 六个静态专业组的有界状态; +- User audience 的 Open/Resolving interaction; +- 服务端生成的 command/recovery capability; +- 脱敏 Snapshot error。 + +Public Snapshot MUST NOT 暴露: + +- 绝对路径、locator、Provider/model/prompt; +- 完整 task/action/plan/observation/tool 参数; +- 动态 child 身份; +- private interaction fingerprint; +- finalization、commit marker、pending/provider/recovery sidecar; +- 可用于绕过正式命令的内部 operation identity。 + +### IC-READ-003:Developer Snapshot + +Developer Snapshot MUST 使用独立 endpoint、DTO 和受信任 capability。Public 与 Developer 类型 MUST NOT 使用 union 混合返回。V1 Developer wire shape 冻结为: + +```rust +struct DeveloperSnapshot { + schema_version: String, + project_id: String, + snapshot_revision: u64, + snapshot_hash: String, + public_snapshot_revision: Option, + runs: Vec, + interactions: Vec, + diagnostics: Vec, + command_capabilities: DeveloperCommandCapabilities, +} + +struct DeveloperRunSummary { + agent_id: String, + session_id: String, + run_id: String, + status: PublicStatus, + stage: PublicStage, + summary: Option, + updated_at: u64, +} + +struct DeveloperInteractionSummary { + interaction_id: String, + kind: InteractionKind, + scope: InteractionScope, + status: InteractionPublicStatus, + audience: InteractionAudience, + summary: String, +} + +struct DeveloperDiagnosticSummary { + code: String, + severity: DeveloperDiagnosticSeverity, + summary: String, +} + +struct DeveloperCommandCapabilities { + reconcile: Vec, +} + +enum InteractionAudience { User, Developer } +enum DeveloperDiagnosticSeverity { Info, Warning, Error } +``` + +Developer Snapshot 的 `interactions` 只包含当前 Open/Resolving 的脱敏摘要;历史 interaction 走独立 Developer/local history。Developer Snapshot 可以暴露以上选定内部 identity 和脱敏摘要,但 MUST 应用 `IC-WIRE-002` 的数量、长度、总 wire size 和内容安全限制。所有条目先验证并规范化,再按完整 RFC 8785 canonical JSON bytes 排序;完全重复项保留,因字节相同而不影响 hash。任一上限超出时必须返回 `DEVELOPER_SNAPSHOT_LIMIT_EXCEEDED` read error,不得截断或发布 partial Snapshot。 + +Developer view 拥有独立于 Public view 的 revision/hash/event scope;hash 使用 `IC-READ-001` 的 RFC 8785 规则。`IC-READ-004` 的 failClosed 向量只适用于 Public view;Developer 任一 required source 无法闭合、identity/digest 冲突或 projection continuity 无法恢复时,统一返回 read error,不得复用旧 Developer Snapshot、发布 partial DTO 或将 diagnostics 当作 failClosed。Developer capability 只扩大受信任 read 与五命令内的显式 reconcile,不允许正式 Project Supervisor 写操作绕过 owner、幂等或 Shell handler。 + +### IC-READ-004:Projection 一致性 + +project projection journal MAY 缓存 Snapshot、revision、event cursor 和恢复 metadata,但只维护自身一致性。它 MUST NOT 参与 Runtime 事务或将“投影已闭合”解释为 command/Runtime 完成。 + +P2 MUST 经专用 projection reader 建立一次有界 source observation:在 owner/supervisor lock 边界内读取所需 Runtime source、记录每份 source 的稳定 identity/revision/digest,并在发布前复核这些 witness;观察期间发生变化时 MUST 有界重试。现有跨 `runtime.json`、task JSONL、event JSONL、response stream 与 sidecar 的聚合 read result 没有该 witness,MUST NOT 直接包装为 Public Snapshot。 + +投影依赖按以下最小矩阵解释;“缺失”只在列出的正常情形可接受,任何存在但无法解析、digest/identity 不可验证或与其它 witness 冲突的 source 都不是空值: + +| 投影类别 | source | 正常缺失 / 空 | 存在但损坏或预期缺失 | +|---|---|---|---| +| project/view identity | trusted project context + project manifest | 不允许缺失 | 不能证明 projectId 与 Project Supervisor identity 时返回 read/transport error,不得发布 Snapshot | +| Session identity | Project Supervisor Session catalog | bootstrap 时可无 active Session,映射 `needsBootstrap` | catalog 损坏、digest 不可复现或与 Runtime identity 冲突时 fail-closed | +| 基础 Supervisor state | runtime state | bootstrap/尚无 Runtime 时可缺失,映射 `needsBootstrap` | 非 bootstrap 时 fail-closed | +| task/progress | task journal | 无 active run 时可为空或缺失 | active run 应有却缺失,或损坏时 fail-closed | +| response stream | stream sidecar | optional,不能单独决定 completed | 损坏不得公开 stream 文本;若完成/交付证明依赖它则 fail-closed | +| event journal | event JSONL | 空可接受;V1 默认不作为 Public Conversation source | 已登记 Public event 所需 source 损坏/截断时 fail-closed;不得由 recent reader 跳过后继续公开 | +| collaboration | manifest + durable collaboration binding | 无协作时为空;无 Runtime binding 时仅允许规范 `manifestFallback` | binding、parent lineage、fallback replacement 或 source identity 冲突时 fail-closed | +| interaction | pending/action sidecar + Shell interaction binding | 没有 open interaction 时两者都可缺失 | 任一方声称 interaction 存在而另一 required source 缺失/损坏时 fail-closed | +| capability | session/run/interaction revision witness + policy result | 没有合法操作时为空 | Snapshot 状态要求某操作但 target/revision/policy witness 不闭合时 fail-closed,不得只保留展示状态 | +| projection continuity | Shell ledger + derived projection journal | 首次投影可无 journal,并从 revision 1、event sequence 0 建立 | derived journal 可从完整 ledger 重建;ledger 损坏或无法恢复唯一 revision/event chain 时返回 read error | + +当完整 witness 证明 source 可组合时,reader 发布 `valid` Snapshot。只有 trusted project context 与 manifest 已证明 `projectId + supervisorAgentId + view`,但其它 required source 缺失、损坏、冲突或有界重试后不能闭合时,reader 才能发布内容安全的 `failClosed` Snapshot。V1 failClosed 的完整字段向量固定为: + +```text +schemaVersion = 当前 V1 +projectId / supervisorAgentId = 已验证 manifest identity +sessionContext = needsReconciliation +sessionId = None +sessionCatalogVersion = None +status = needsReconciliation +stage = reconciling +waitingOn = reconciliation +nextStep = reconcile +outcome = None +progress / collaborators / interactions = empty +commandCapabilities = 全空 +error.code = PUBLIC_STATE_INVALID +error.message = "Public state could not be verified." +``` + +`RECONCILIATION_REQUIRED` 只用于 source observation 本身有效、且 Runtime facts 明确处于 reconciliation 的 valid Snapshot,不用于 projection 损坏。无法证明 project、Supervisor 或 view identity 时 MUST 返回 read/transport error。failClosed 不得复制未证明 Runtime 事实;它按 `IC-READ-001` 计算确定的 hash/revision,并在非首次 publication 时产生事件,不得让 Consumer 停在旧 valid Snapshot。 + +### IC-EVT-001:SnapshotChanged 语义 + +出向事件 MUST 只表示 Snapshot 可能变化: + +```rust +enum SnapshotEventKind { SnapshotChanged } + +struct OutboundEnvelope { + schema_version: String, + event_id: String, + sequence: u64, + from_revision: u64, + to_revision: u64, + event: SnapshotEventKind, +} +``` + +每个 `(projectId, view)` scope 的首次 Snapshot 直接以 revision 1 建立,MUST NOT 为它生成 event;此时 `currentSequence=0`。从第二次规范 Snapshot 变化开始,每个 event 的 `fromRevision` MUST 等于此前已发布 revision,`toRevision` MUST 等于发布后可重读的 revision 且大于前者,首个 event sequence 为 1。一次 publication 可以合并多个 source 变化,但 source 变化而规范 Snapshot 不变时不得发 event。`sequence` 是该 scope 的独立单调事件序列,不要求与 revision 一一对应;projection journal 重建后必须从 durable projection/event record 恢复。事件 MUST NOT 携带完整 Runtime 状态或成为最终事实。Consumer 遇到重复、乱序、缺口、重连或 Snapshot revision 低于 `toRevision` 时 MUST 重新读取完整 Snapshot;重读后仍不能得到 `toRevision` 或更高 revision 时,必须显示 stale/read failure,不得用 event 自行合并状态。 + +### IC-EVT-002:事件保留 + +`SnapshotChanged` event log MAY 有界保留,但 V1 subscription 不承诺历史 event 补读;断线重连总是重新取得完整 Snapshot 和新的 `currentSequence` watermark。该语义 MUST NOT 套用于 Public Conversation 的 session-lifetime cursor。 + +### IC-EVT-003:订阅路由与建立 + +Public 与 Developer MUST 使用独立 read endpoint、权限能力和事件流;任何 event stream 的 scope 固定为 `(projectId, view)`,其中 `view` 是 `public` 或 `developer`。`SnapshotSubscribeRequest` 的 endpoint 已隐含 `view`,不得由 Consumer 在 Public endpoint 中切换为 Developer。订阅建立请求必须经 trusted project context 与该 view capability 核验,不得接受 Consumer 传入路径或以 eventId 推导 scope: + +```rust +enum SnapshotView { Public, Developer } + +struct SnapshotSubscribeRequest { + schema_version: String, + project_id: String, +} + +struct PublicSnapshotSubscriptionStarted { + schema_version: String, + project_id: String, + current_snapshot: PublicSnapshot, + current_sequence: u64, +} + +struct DeveloperSnapshotSubscriptionStarted { + schema_version: String, + project_id: String, + current_snapshot: DeveloperSnapshot, + current_sequence: u64, +} +``` + +建立订阅 MUST 原子地返回一个已验证的完整当前 Snapshot 和其 `currentSequence` watermark,然后仅投递该 scope 中 `sequence > currentSequence` 的实时 event;跨 scope event MUST NOT 投递。V1 不接受 `afterSequence`,不在握手前后发送 backlog;断线、缺口、权限变化或重连均重新建立订阅并读取完整 Snapshot。Public stream 与 Developer stream 的 watermark 不得混用。 + +### IC-CAP-001:Capability 是唯一写入口来源 + +Consumer MUST 只提交当前可信 Snapshot 中服务端生成的 capability 允许的 command/target/option。Consumer MUST NOT 从 `waitingOn`、`nextStep`、status 或错误文案自行构造命令。 + +Shell MUST 在写锁内重读 facts 并复核 capability target;capability 过期返回 `TARGET_STALE` 或 `TARGET_BUSY`,不能因为 Consumer 曾看到能力就继续执行。 + +### IC-CAP-002:Stale display + +Public read 暂时失败且尚未收到新的 Snapshot 时,Consumer MAY 显示上一份已验证 Snapshot 并明确标记 stale。stale 不是新的 Snapshot,也不等于 `failClosed` Snapshot。收到 `failClosed` Snapshot 后,Consumer MUST 用它替换旧视图并禁用全部写入口;不得保留旧 interaction 或 capability。仅在仍展示上一份 valid Snapshot 的短暂 stale 状态,上一份精确 cancel capability MAY 被提交;Shell 仍必须在 owner/project lock 内重新授权和复核,且若期间已发布 `failClosed` 或 target 漂移则零副作用拒绝。 + +### IC-CAP-003:Capability DTO + +```rust +struct CommandCapabilities { + submit_intent: Option, + interaction_responses: Vec, + cancel: Option, + resume: Vec, +} + +struct InteractionResponseCapability { + interaction_id: String, + interaction_revision: u64, + session_id: String, + expected_session_catalog_version: String, + action: InteractionAction, // answer | approve + allowed_decisions: Vec, // answer 时为空 +} + +enum InteractionAction { Answer, Approve } + +struct SubmitIntentCapability { + session_id: String, + expected_session_catalog_version: String, + conversation_options: Vec, + builtin_command: Option, +} + +struct SubmitIntentOption { + intent_kind: IntentKind, + entry_binding_kind: Option, + run_profile: RunProfile, + input_policy: InputPolicy, + allowed_attachment_media_kinds: Vec, +} + +struct BuiltinCommandCapability { + expected_parser_version: String, + allowed_command_names: Vec, +} + +struct CancelCapability { + session_id: String, + expected_session_catalog_version: String, + run_id: String, + expected_run_revision: u64, +} + +enum PublicResumeCapability { + ContinueRun { + session_id: String, + expected_session_catalog_version: String, + run_id: String, + expected_run_revision: u64, + }, + RetryTerminalRun { + session_id: String, + expected_session_catalog_version: String, + target: RetryTarget, + }, +} + +struct DeveloperReconcileCapability { + session_id: Option, + run_id: String, + expected_run_revision: u64, + reconciliation_id: String, +} +``` + +Capability 必须按下表签发;“必须签发”表示全部 required witness 闭合且 policy 至少产生一个合法选项时,投影不得任意省略;任一禁止条件成立时必须撤销: + +| capability | 必须签发条件 | 必须不签发 / 失效条件 | audience | +|---|---|---|---| +| `submitIntent` | valid Snapshot、`sessionContext=ready`、Session catalog witness 有效,且 policy matrix 至少产生一个 conversation/builtin option | bootstrap、failClosed/reconciliation、Session/catalog 漂移、无合法 option | Public | +| `builtinCommand` | `submitIntent` 已签发、parser version 可验证且至少一个公开 command name 合法 | parser/version 未知、命令集合为空或只剩 Local/Developer management | Public | +| `interactionResponses` | User audience Open interaction、private binding/revision/target witness 闭合;每个 allowed action 有精确 capability | Resolving/非 User、binding 漂移、target/policy 不闭合、failClosed | Public | +| `cancel` | valid Snapshot 中存在同 Session 的可取消 live Project Supervisor run,run identity 与 catalog witness 闭合 | 无 live run、已 terminal/cancelling、identity/revision 漂移、failClosed | Public | +| `ContinueRun` | valid Snapshot 的同一 Project Supervisor run 明确为 `pausedByUser`,run/catalog revision 闭合 | 非 pausedByUser、target 漂移、failClosed | Public | +| `RetryTerminalRun` | valid Snapshot 明确给出 `nextStep=retryTerminalRun`,predecessor terminal 与 retry policy witness 闭合 | 非允许终态、已有 successor、lineage/terminal revision 漂移、failClosed | Public | +| `reconcile` | trusted Developer endpoint,存在 durable reconciliation binding,run/reconciliation revision 闭合 | Public view、binding 不完整、结果可能被当作自动副作用重放 | Developer/Runner | + +所有 capability 在其引用的 Session catalog、Run、interaction、policy 或 reconciliation witness 变化时立即失效。Developer `reconcile` 仍通过 `resume` command、同一 Shell handler、owner 与幂等门禁执行,不是第六个命令。 + +`conversationOptions` MUST 按合法组合输出,Consumer MUST NOT 从多个独立白名单字段做笛卡尔积。每个 Open Public interaction 的 `allowedActions` 必须与 `interactionResponses` 中同 interactionId/revision 的一个或多个 capability 精确一致;Resolving interaction 与 `failClosed` Snapshot 的该数组必须为空。Consumer 只能由该 capability 构造 `InteractionResponseMeta` 与答案/decision,`allowedActions` 本身只是展示字段。对 Collaborator interaction,capability 的 `sessionId` 始终是 Project Supervisor Session 的 stale/auth guard,不得解释为 child Session;实际 child target 只能由 interaction 的 private durable binding 在 owner 锁内恢复和复核。Resume capability MUST 使用与 `ResumeIntent` 同构的 tagged target,并携带所需 revision/correlation;Consumer 只能原样提交 capability 中的 target。 + +--- + +## 5. 五个公开写命令 + +### IC-CMD-001:命令集合 + +V1 正式写命令仅为: + +```text +submit_intent +answer +approve +cancel +resume +``` + +start、steer、confirm、reject、retry、schedule、wake、compact、goal management、session management 和 local path management MUST NOT 作为新的平行 Public Runtime 命令。 + +### IC-CMD-002:统一响应 + +成功响应 MUST 包含: + +```rust +struct CommandResponse { + schema_version: String, + request_id: String, + request_fingerprint: String, + replayed: bool, + observed_snapshot_revision: u64, + result: T, +} +``` + +`accepted` 只表示请求已可靠受理或映射,不表示 Runtime 已终结。 + +V1 ack union 冻结为: + +```rust +enum IntentDisposition { DirectReply, Start, Steer, SteerDeferred, Reject, InteractionRequired } +enum ResumeMode { ContinueRun, RetryTerminalRun, ReconcileRun } + +enum CommandAck { + IntentAccepted { + disposition: IntentDisposition, + accepted_run_id: Option, + steer_id: Option, + response_message_id: Option, + runtime_status_message_id: Option, + }, + InteractionAccepted { + interaction_id: String, + decision: Option, + follow_up_interaction_id: Option, + }, + CancelAccepted { + run_id: String, + cancel_operation_id: String, + }, + ResumeAccepted { + mode: ResumeMode, + predecessor_run_id: String, + accepted_run_id: Option, + affected_run_count: u32, + }, + InteractionRequired { + interaction_id: String, + interaction_revision: u64, + }, +} +``` + +只有 DirectReply MAY 在 ack 中返回 `responseMessageId`;Start/Steer 的最终 assistant 属于 RuntimeFinalReply,MUST NOT 在受理 ack 中伪造。`CancelAccepted` 不代表 Run 已 terminal;RetryTerminalRun 才在 ResumeAccepted 中返回新的 `acceptedRunId`。 + +### IC-CMD-003:SubmitIntent 请求 + +```rust +struct SubmitIntentCommand { + meta: CommandMeta, + payload: SubmitIntentPayload, +} + +enum SubmitIntentPayload { + Conversation { + session_id: String, + expected_session_catalog_version: String, + message: String, + attachments: Vec, + intent_kind: IntentKind, + entry_binding: Option, + run_profile: RunProfile, + }, + BuiltinCommand { + session_id: String, + expected_session_catalog_version: String, + command_line: String, + expected_parser_version: String, + }, +} + +enum IntentKind { + CreateFromPrompt, + ContinueProject, + CreateFromTemplate, + ImportExistingDesign, +} + +struct AttachmentBinding { + attachment_namespace: String, + attachment_id: String, + attachment_revision: u64, + digest_algorithm: String, + content_digest: String, + media_kind: PublicMediaKind, +} + +enum EntryBinding { + Template { + template_id: String, + template_revision: u64, + digest_algorithm: String, + content_digest: String, + }, + ExistingDesign { + design_id: String, + design_revision: u64, + digest_algorithm: String, + content_digest: String, + }, +} + +struct RunProfile { + name: String, + version: String, +} + +enum InputPolicy { TextOnly, TextWithOptionalAttachments } +enum EntryBindingKind { Template, ExistingDesign } +enum PublicMediaKind { Image, Audio, Video, Document, Code, ProjectVersion, Other } +``` + +Conversation message MUST 非空,attachment-only MUST 在 ledger 前 `INVALID_REQUEST`。`intentKind` MUST 由 Consumer 明确表达入口意图,但不是权限主张;Shell MUST 按 capability 和 policy matrix 复核。MUST NOT 从 message 推断 intent,也不得把 intent 塞入 runProfile。 + +`entryBinding` 仅与对应 intentKind 组合;附件和 entry 必须来自现有资源/模板 lineage,包含 immutable revision 和 sha256 digest,不接收文件字节、绝对路径、`file://`、临时 URL 或上传 token。 + +BuiltinCommand MUST 通过同一版本 Shell parser。slash route MUST NOT 携带附件、entry binding 或 Runtime profile;项目路径、导入、配置等 Local Management MUST 走独立受信任管理面。 + +### IC-CMD-004:SubmitIntent 路由 + +Shell MUST 在 project lock 内按冻结 option/policy matrix 将 Conversation 判为: + +```text +directReply +start +steer +steerDeferred +reject +interactionRequired +``` + +active root Run 已绑定冻结 Goal Contract 时,普通 execute intent MUST NOT 被偷偷转换为 replacement steer;必须返回 `TARGET_BUSY`,或要求显式 Goal management operation。Consumer MUST NOT选择 disposition。 + +### IC-CMD-005:Input envelope + +Conversation 在执行 Runtime/Provider 前 MUST 先建立同 requestId 绑定的 input envelope,并按以下顺序: + +```text +reserve stable conversationUserMessageId +→ 幂等写入并回读 user conversation message +→ 标记 input committed +→ 调用 Runtime start/steer 或生成 direct reply +``` + +无法证明 user message commit 时 MUST 进入 outcome-unknown/reconciliation;MUST NOT 用新 messageId 补写第二条用户消息。 + +### IC-CMD-006:Answer 请求 + +```rust +struct AnswerCommand { + meta: CommandMeta, + interaction: InteractionResponseMeta, + answers: Vec, +} +``` + +```rust +enum Answer { + Option { question_id: String, option_id: String }, + Freeform { question_id: String, text: String }, +} +``` + +Answer 仅适用于 UserInput。答案 MUST 恰好覆盖当前全部 questionId,每题只能选择当前 optionId 或提交 freeform;缺失、重复、越界或旧 revision MUST 零副作用失败。 + +### IC-CMD-007:Approve 请求 + +```rust +struct ApproveCommand { + meta: CommandMeta, + interaction: InteractionResponseMeta, + decision: ApprovalDecision, + feedback: Option, +} + +enum ApprovalDecision { Approve, Reject, RequestChanges } +``` + +- ToolApproval:仅 approve/reject; +- Project scope PolicyApproval:仅 approve/reject,并绑定冻结 target set; +- `requestChanges`:只允许 Run/Action scope、User audience、单一 immutable targetArtifact 的 PolicyApproval;必须携带 feedback; +- approve/reject MUST 省略 feedback。 + +`requestChanges` MUST 在 interaction resolving 时预分配唯一 `reworkOperationId`,并在 durable rework prepared/enqueued 后才把旧 interaction 标记 Resolved。unknown result MUST NOT 创建第二返工。 + +### IC-CMD-008:Cancel 请求 + +```rust +struct CancelCommand { + meta: CommandMeta, + session_id: String, + expected_session_catalog_version: String, + run_id: String, + expected_run_revision: u64, +} +``` + +Cancel MUST 精确绑定当前 Project Supervisor Session/Run/revision;`expectedRunRevision` 不匹配时零副作用 `TARGET_STALE`。它只接受取消 operation,不得伪造 Runtime terminal。重复 cancel MUST 复用同一 cancel operation。目标终结、Session 变化或归属冲突 MUST 返回 durable `TARGET_STALE`/业务拒绝。 + +### IC-CMD-009:Resume 请求 + +```rust +enum ResumeIntent { + ContinueRun { + session_id: String, + expected_session_catalog_version: String, + run_id: String, + expected_run_revision: u64, + }, + RetryTerminalRun { + session_id: String, + expected_session_catalog_version: String, + target: RetryTarget, + }, + ReconcileRun { + session_id: Option, + run_id: String, + expected_run_revision: u64, + reconciliation_id: String, + }, +} + +enum RetryTarget { + Supervisor { + run_id: String, + expected_terminal_revision: u64, + expected_retry_policy_digest: String, + }, + Collaborator { + collaboration_id: String, + expected_terminal_revision: u64, + expected_retry_policy_digest: String, + }, +} +``` + +- ContinueRun 只继续 capability 明确声明的 pausedByUser 同一 durable Run; +- RetryTerminalRun MUST 为失败终态预分配唯一 successor runId,保存 predecessor/successor lineage,MUST NOT 复用旧 runId;`expectedRetryPolicyDigest` 是 V1 sha256 canonical policy digest,policy 变化时旧 capability 必须 stale; +- ReconcileRun 只允许受信任 Developer/Runner capability,MUST NOT 自动重放未知副作用; +- timer、lane、ownerRecovered、interactionResolved 和 schedule-ready 是内部 recovery intent,不进入 Public Resume; +- 自然语言“继续”MUST NOT 静默路由成 Resume。 + +### IC-CMD-010:旧入口并存 + +P3–P5 期间,任何能操作同一 Supervisor Run 的旧 Tauri/CLI/`swarm_cli`/helper MUST 满足其一: + +1. 启用 External Runner 时转发同一 Runner Shell endpoint; +2. 未启用 Runner 时调用同一 Shell handler 并持等价 owner; +3. 只读或明确的内部/Developer-local 能力; +4. 在新协议启用时显式禁用。 + +“调用一个 Adapter 函数”不足以证明收口;必须证明真实写入发生在 owner 进程。既有 Runner `runtime.resume/steer/cancel/pause/compact` RPC 只能作为 Shell 内部实现或委托 Shell,MUST NOT 保留为并行公开控制协议。 + +--- + +## 6. InteractionRequired + +### IC-INT-001:Interaction identity + +Interaction MUST 使用独立 identity: + +```rust +struct InteractionResponseMeta { + interaction_id: String, + response_id: String, + expected_interaction_revision: u64, + session_id: String, // 始终是 Project Supervisor Session + expected_session_catalog_version: String, +} +``` + +若 interaction context 是 Collaborator,创建时 MUST durable 保存该 interactionId 到完整 collaboration binding、target identity、policy 与 source witness 的 private binding;manifestFallback 不得承载 Public interaction。处理 response 时,Shell MUST 在 owner lock 内重读 binding 和 target lineage;retry/successor、parent lineage、source 或 group 发生漂移时旧 interaction MUST `INTERACTION_STALE`,不得路由到 successor 或同组其它 child。缺失/冲突 binding 必须进入 reconciliation 或从 Public 列表移除。 + +`interactionRevision` 从 1 开始,只在该 interaction 可回答内容、约束、binding 或状态变化时递增。无关 Snapshot 更新 MUST NOT 使 interaction stale。 + +同 `responseId` + 同 fingerprint MUST 重放;同 responseId 不同内容 MUST `IDEMPOTENCY_KEY_REUSED`。 + +### IC-INT-002:Interaction 类型与状态 + +```text +kind: UserInput | ToolApproval | PolicyApproval +scope: Project | Run | Action +audience: User | Developer +status: Open | Resolving | Resolved | Superseded | Cancelled +``` + +Public DTO 冻结为: + +```rust +struct PublicQuestion { + id: String, + header: String, + question: String, + options: Vec, +} + +struct PublicQuestionOption { + id: String, + label: String, + description: String, +} + +struct PublicInteractionView { + interaction_id: String, + interaction_revision: u64, + kind: InteractionKind, + scope: InteractionScope, + actionable: bool, + allowed_actions: Vec, // answer | approve + status: InteractionPublicStatus, // open | resolving + context: PublicInteractionContext, + presentation: PublicInteractionPresentation, +} + +enum PublicInteractionContext { + Supervisor, + Collaborator { + collaboration_id: String, + group: CollaboratorGroup, + }, +} + +enum PublicInteractionPresentation { + UserInput { + questions: Vec, + allow_freeform: bool, + }, + PolicyApproval { + title: String, + summary: String, + allowed_decisions: Vec, + }, + ToolApproval { + title: String, + summary: String, + risk_level: PublicRiskLevel, + allowed_decisions: Vec, + }, +} + +enum InteractionKind { UserInput, ToolApproval, PolicyApproval } +enum InteractionScope { Project, Run, Action } +enum InteractionPublicStatus { Open, Resolving } +enum PublicRiskLevel { Low, Medium, High } +``` + +Public Snapshot 只投影 User audience 的 Open/Resolving。Open 可回答;Resolving 只显示处理中并禁用再次提交;其它状态从公开列表移除。`kind` 与 presentation variant MUST 严格一致;不匹配按 `PUBLIC_STATE_INVALID` 失败关闭。`actionable/allowedActions` 只是展示能力,Shell 仍必须锁内授权。 + +### IC-INT-003:Bound fingerprint + +每个 interaction MUST 保存 private request fingerprint 和 `boundStateFingerprint`,精确绑定其 durable target、policy 和父子身份。Shell MUST 在解决前锁内重读并复核。目标漂移返回 `INTERACTION_STALE`,零副作用。 + +### IC-INT-004:Artifact binding + +产物审批 MUST 绑定: + +```rust +struct ArtifactBinding { + artifact_namespace: String, + artifact_id: String, + artifact_revision: u64, + digest_algorithm: String, + content_digest: String, +} +``` + +只有现有 lineage 可按 immutable revision 重读并计算 sha256 时才能开放 requestChanges;否则返回 `ARTIFACT_BINDING_UNAVAILABLE`。MUST NOT 新建平行 artifact identity。 + +### IC-INT-005:UserInput presentation + +UserInput MUST 有 1–3 个问题;questionId 为稳定唯一 snake_case;每题 2–3 个 option;optionId MUST 在 interaction 创建时按规范 questionId 和 ordinal 生成,不得从 label 推导。freeform 始终允许。label/description/顺序变化必须递增 revision。 + +私有问题原文必须经过内容安全过滤。不能安全公开时 MUST 转为 Developer interaction 或 needs-reconciliation,不得泄漏到 Public。 + +### IC-INT-006:Approval target set + +Project scope PolicyApproval MUST 固化精确 `agentId + parentRunId + runId + actionId + actionFingerprint` target set;MUST NOT 把“当前所有 Run”作为隐含目标。target set 变化必须创建新 interaction。 + +### IC-INT-007:解决顺序 + +Answer/Approve MUST: + +```text +request ledger replay check +→ owner/project/interaction lock +→ 重读 interaction 与 target +→ 校验 revision、status、binding、principal 和 policy +→ CAS Open → Resolving +→ 执行或准备唯一 operation +→ durable evidence 后 Resolved +``` + +崩溃恢复 MUST 复用 interaction/response/rework identity;外部结果未知时保持 Resolving 或进入 reconciliation,MUST NOT 伪造 Resolved。 + +--- + +## 7. Public Conversation 与交付 + +### IC-CONV-001:独立展示通道 + +Conversation/response stream 与 Runtime Snapshot 是独立通道。Conversation message MUST NOT 改变 Runtime 生命周期结论;Runtime completed MUST NOT 反向伪造 assistant message。 + +### IC-CONV-002:不复制正文 + +Public Conversation MUST 是既有 source record 之上的只读索引/分页层。index 只保存: + +```text +sourceKind +deliveryKind +messageId +sourceRecordRef +sourceDigest +sequence +cursor +previousCursor +``` + +MUST NOT 保存第二份正文。读取时必须按 sourceKind 回读原 source 并验证 digest。 + +### IC-CONV-003:Delivery kinds + +```rust +enum DeliveryKind { + User, + DirectReply, + RuntimeFinalReply, + RuntimeStatus, + PublicEvent, +} + +enum ConversationRole { User, Assistant, System } + +struct ConversationProvenance { + run_id: Option, + source_agent_id: Option, + source_run_id: Option, +} + +struct PublicConversationMessage { + schema_version: String, + project_id: String, + session_id: String, + delivery_kind: DeliveryKind, + message_id: String, + sequence: u64, + cursor: String, + role: ConversationRole, + public_text: String, + event_id: Option, + provenance: Option, +} +``` + +`eventId` 只有 PublicEvent 为 Some,且 MUST 逐字节等于 messageId;其它 delivery MUST 为 None。provenance 只允许公开 run/source lineage,MUST NOT 包含 finalizationId、Provider、locator、path、tool/action 或 private ledger identity。 + +Public 去重键固定为: + +```text +(projectId, sessionId, deliveryKind, messageId) +``` + +### IC-CONV-004:User 与 DirectReply + +User 和 DirectReply MUST 从对应 Session conversation message 回读。DirectReply 在 command prepared 时 MUST 预分配稳定 user/assistant messageId,先提交并回读 user message,再写 assistant response,最后关闭 command result。 + +未知 slash command 的直接回复也走该顺序;路径或 Local Management 结果不得伪装成 assistant conversation。 + +### IC-CONV-005:RuntimeFinalReply + +RuntimeFinalReply MUST 复用现有 finalization/conversation identity,不生成第二身份: + +- `messageId` 标识 Agent/Session/Run conversation assistant; +- `finalizationId` 还绑定 response fingerprint/revision/request slot/steer cursor/plan/Goal; +- response stream 由 requestSlot/responseRevision/appliedSteerCursor 标识。 + +三者 MUST 分开保存和核验,不能称为同一 identity。成功后 finalization/recovery sidecar 可能清理,因此长期正文 source 是带稳定 messageId 的 conversation assistant。response stream 单独不足以证明 final reply committed。 + +### IC-CONV-006:RuntimeStatus 准入 + +RuntimeStatus MUST 按具体类型准入,不得假设每个 Run 都有同构 source: + +- 根 Project Supervisor accepted start/terminal:可能来自 project conversation; +- 专业 Agent terminal:可能来自其 Agent Session conversation; +- 带 parent 的 Supervisor receipt/isolated join:当前没有 Session status message,默认不进入 Public Conversation。 + +只有具体 status 同时具有稳定 messageId、明确 conversation scope、task/run correlation 和可回读 source 时才可进入 committed chain。project conversation source MUST 通过 correlation 显式绑定 Session,不能从文件位置猜测。 + +### IC-CONV-007:PublicEvent 默认拒绝 + +现有普通 Runtime event 默认 MUST NOT 进入永久 Public Conversation。只有显式登记的 event type 同时满足以下条件才 MAY 进入: + +1. 写入时已有可恢复、可幂等复用的规范 eventId; +2. `messageId == eventId`; +3. role 固定为 system; +4. 正文仅为 allowlisted `publicText`; +5. 存在可按 eventId 定位、报告损坏/截断并校验 publicText digest 的 source reader; +6. source agent/session/run scope 已证明; +7. 重放复用同一 eventId/sequence/cursor。 + +现有 pid/时间/进程内计数 eventId 和只返回最近 20 条、跳过损坏行的 recent-events reader 不满足条件。GUI MUST NOT 事后生成 `game-chat-runtime-event:*` identity。child event 被旧 GUI 写入 project transcript 时,在 source scope 未证明前必须历史隔离。 + +### IC-CONV-008:Sequence 与 cursor + +每个 `(projectId, sessionId)` MUST 使用 conversation-global sequence。sequence 预留失败 MAY 形成永久空洞;空洞不触发无限重读。response-stream sequence 与 conversation sequence 无关。 + +committed cursor chain 只连接已能从原 source 回读的消息。Public read 请求: + +```rust +struct ConversationReadRequest { + schema_version: String, + project_id: String, + session_id: String, + after_cursor: Option, + limit: u32, +} +``` + +响应 DTO 冻结为: + +```rust +enum ConversationHistoryState { + Complete, + LegacyEntriesIsolated, +} + +struct PublicConversationReadPage { + schema_version: String, + project_id: String, + session_id: String, + messages: Vec, + next_cursor: Option, + has_more: bool, + history_state: ConversationHistoryState, +} +``` + +`afterCursor=None` 表示从该 Session Public origin 分页。cursor 在 Session 生命周期内 MUST 持续有效;Public Conversation read MUST NOT 返回 `CURSOR_EXPIRED`。`legacyEntriesIsolated` 只表示 V1 committed chain 完整、但存在无法证明 identity 的 pre-V1 私有隔离项;不得把截断的 V1 history 标成该状态。 + +### IC-CONV-009:历史失败关闭 + +以下任一情况 MUST 返回无 partial page 的 `CONVERSATION_HISTORY_INCOMPLETE`: + +- committed index 损坏; +- source 缺失、不可定位或 digest 漂移; +- sourceKind/scope/correlation 不匹配; +- 同一 source 对应多个 identity; +- cutover 后出现未登记 writer、双写或无稳定 messageId; +- committed cursor chain 无法从 origin 补读。 + +非法 cursor 返回 `CURSOR_INVALID`,不得夹带 partial page。Consumer MUST 停止合并并显示恢复状态,不能用私有 path、ledger 或 recent window 掩盖截断。 + +### IC-CONV-010:Writer cutover + +P3 启用 Public Conversation read adapter 前,迁移矩阵 MUST 列出所有正式 writer,包括: + +- project conversation; +- Agent Session conversation; +- Runtime finalization/status/event; +- CLI/`swarm_cli` direct reply; +- GUI ordinary Agent chat; +- Developer Agent panel; +- project pending-message autosave; +- GUI response-stream/final-reply 和 Runtime-event 派生 autosave; +- 所有 `append_local_conversation_message` 调用方。 + +每个 writer MUST 明确三选一: + +1. 由 Shell source binding 接管; +2. 保留为 Developer/local history 且永不进入 Public; +3. 在启用 Public Conversation read adapter 前禁用。 + +P5 只删除已经停止写入后的 Consumer 展示/调用分支,不承担正式 writer cutover。cutover watermark 后 Public scope MUST 不存在缺少稳定 messageId 的正式 append;同一 source identity 在同一时刻只能有一个 writer。 + +--- + +## 8. Error contract + +### IC-ERR-001:Command、Snapshot 与 read error 分离 + +Snapshot error、Snapshot read error 和 Command error MUST 使用不同 DTO,不能把 requestId、request fingerprint、replayed 或 command result 嵌入 Snapshot/read error。无法安全发布完整 Snapshot 时返回: + +```rust +enum SnapshotReadErrorCode { + ProjectIdentityUnavailable, + ProjectionContinuityUnavailable, + DeveloperStateInvalid, + DeveloperSnapshotLimitExceeded, + PublicSnapshotLimitExceeded, + PermissionDenied, + TransientUnavailable, +} + +struct SnapshotReadError { + schema_version: String, + code: SnapshotReadErrorCode, + retryable: bool, + message: String, +} +``` + +`ProjectIdentityUnavailable`、`ProjectionContinuityUnavailable`、`DeveloperStateInvalid`、`DeveloperSnapshotLimitExceeded` 和 `PublicSnapshotLimitExceeded` 默认不可重试;`TransientUnavailable` 可用同一 read/subscribe request 重试。read error message 必须为稳定脱敏文案,不能包含 path、source 原文或内部 identity。 + +### IC-ERR-002:稳定 Command error code + +Command error DTO 冻结为: + +```rust +enum CommandErrorCode { + InvalidRequest, + ProtocolVersionUnsupported, + PermissionDenied, + ProjectNotFound, + ProjectIdMismatch, + RequestNotFound, + IdempotencyKeyReused, + CommandInProgress, + CommandResultUnknown, + NeedsReconciliation, + TargetStale, + TargetBusy, + CancelAlreadyTerminal, + InteractionStale, + InteractionAlreadyResolved, + ArtifactBindingUnavailable, + OwnerUnavailable, + TransientUnavailable, + Internal, +} + +struct CommandError { + schema_version: String, + code: CommandErrorCode, + retryable: bool, + message: String, + request_id: Option, + request_fingerprint: Option, + replayed: bool, + observed_snapshot_revision: Option, + interaction_required: bool, +} +``` + +V1 `CommandErrorCode` 冻结为下表中的 code;Rust 枚举名按 `IC-WIRE-001` 序列化为 SCREAMING_SNAKE_CASE。`retryable` 必须等于表中默认值,只有 `TARGET_BUSY` 可以由签发 capability 明确覆盖: + +| Code | 语义 | 默认 retryable | +|---|---|---| +| `INVALID_REQUEST` | schema/字段/类型/上限错误 | false | +| `PROTOCOL_VERSION_UNSUPPORTED` | major/version 不支持 | false | +| `PERMISSION_DENIED` | 调用来源或项目权限拒绝 | false | +| `PROJECT_NOT_FOUND` | locator 无法解析项目 | false | +| `PROJECT_ID_MISMATCH` | locator 与 projectId 不一致 | false | +| `REQUEST_NOT_FOUND` | 从未进入 ledger 或无权读取 | false | +| `IDEMPOTENCY_KEY_REUSED` | 同 requestId 不同 fingerprint | false | +| `COMMAND_IN_PROGRESS` | 同 request 正在处理 | true | +| `COMMAND_RESULT_UNKNOWN` | 结果无法安全证明 | false | +| `NEEDS_RECONCILIATION` | durable facts 冲突或未知结果需修复 | false | +| `TARGET_STALE` | Session/Run/revision 已变化 | false | +| `TARGET_BUSY` | 当前状态禁止该操作 | true/按 capability | +| `CANCEL_ALREADY_TERMINAL` | cancel 目标已终结 | false | +| `INTERACTION_STALE` | interaction revision/binding 已变化 | false | +| `INTERACTION_ALREADY_RESOLVED` | 已由其它 response 解决 | false | +| `ARTIFACT_BINDING_UNAVAILABLE` | 目标不可按 immutable revision/digest 绑定 | false | +| `OWNER_UNAVAILABLE` | 无有效 execution owner | true | +| `TRANSIENT_UNAVAILABLE` | transport/Runner 暂不可用 | true | +| `INTERNAL` | 已脱敏内部错误 | false | + +`retryable=true` 只允许使用同 requestId 重试 transport/读回,MUST NOT 表示可换 requestId 重做真实副作用。 + +Snapshot error code 冻结为: + +```rust +enum SnapshotErrorCode { + ConfigurationRequired, + AuthenticationFailed, + RateLimited, + TransportFailed, + ProviderFailed, + VerificationFailed, + BudgetExhausted, + SandboxDenied, + ArtifactUnavailable, + ReconciliationRequired, + PublicStateInvalid, + Internal, +} +``` + +上述枚举按 `IC-WIRE-001` 序列化为 SCREAMING_SNAKE_CASE。 + +Snapshot error 只描述当前可公开状态,不包含 requestId、requestFingerprint、replayed 或 command result。`interactionRequired` 只能与同 revision 的 Public interaction/capability 互相校验,不能单独驱动按钮。 + +### IC-ERR-003:Public content safety + +Public message、interaction、status、event 和 error 文案 MUST 经过长度、路径、Provider、密钥、Token、工具参数和 observation 过滤。过滤失败 MUST 拒绝公开或进入 Developer/reconciliation,MUST NOT 原样降级输出。 + +--- + +## 9. Migration 与兼容 + +### IC-MIG-001:Shadow 只读 + +Shadow mode 仅可比较 Public projection、schema 和脱敏结果,MUST NOT 调用真实 Runtime/Provider/工具或写 conversation。 + +### IC-MIG-002:Fallback 边界 + +迁移 fallback 只允许 transport 明确返回“unknown command”,且能证明新 handler 未执行。新 handler 已收到请求后的 structured error、timeout、disconnect 或 unknown outcome MUST NOT fallback 到旧写入口。 + +### IC-MIG-003:旧公开面删除 + +P6 MUST 通过调用图证明正式 transport、Consumer 和 Public DTO 已无旧控制协议。Runtime 内部 primitive、恢复测试和明确的管理面 MAY 保留;MUST NOT 使用“全仓旧名称为零”误删内部能力。 + +### IC-MIG-004:产品决策隔离 + +`--swarm-chat` 的普通 Public CLI / 受信任 Developer CLI 定位由 `FD-001` 决定。该决策只能选择 read capability 和命令入口呈现,MUST NOT 改变五命令、owner、source authority 或单 writer 规则。它只阻塞 P5 的 CLI 产品绑定与呈现验收,不阻塞 Interaction Contract 核心冻结,也不阻塞 P0–P4 的 shared Shell、owner、record、Snapshot 或 write ingress 实施。 + +### IC-MIG-005:P3 写入口收口与 P5 Consumer 迁移 + +P3 的完成条件是:任何仍能操作同一 Project Supervisor Run 的 legacy Tauri command、普通 CLI、`swarm_cli` 或 helper 都已成为同一 Shell handler 的纯 transport(External Runner 时在 owner Runner 内执行;进程内时先持等价 owner),或者在新协议启用时明确禁用。它不得先在 Consumer 进程调用 Runtime primitive 再通知 Runner。 + +P5 只负责把 GUI/CLI 的读取、渲染、capability 驱动交互和旧 UX 分支迁为 Public/Developer Consumer;P5 不得被用来延后 P3 的真实 writer 收口。 + +### IC-MIG-006:P4 Runner 重启发现 + +P4 若承诺已受理 operation 不依赖 GUI/CLI 请求推进,Runner MUST 有跨重启的、受信任宿主拥有的 project discovery registry。registry 只保存已验证 manifest 的 private locator / project binding,且只提供候选项目发现;它不是 Public DTO、Runtime fact、owner lease 或接管依据。Runner 对每个候选项目仍 MUST 重新解析 manifest、取得 execution owner,并依 durable command/source evidence 决定 wake、reconciliation 或不动作。 + +--- + +## 10. 冻结条件 + +本文转为正式冻结前 MUST 满足: + +1. 所有 `IC-*` 有唯一含义,无重复或相互冲突定义; +2. 迁移矩阵为每个正式 ingress/read/writer 建立 `MX-* → IC-*` 映射; +3. 冻结前 `EG-*` 明确证明或隔离现有行为; +4. `FD-001` 已被标记为 P5 专属的 read/呈现决策;它必须在 P5 开始前决定,但不阻塞 P0–P4; +5. Rust/TypeScript schema fixture 的规范、golden/negative 向量和预期结果已经定义;P1 负责实现并运行生成链路; +6. request、interaction、conversation 和 owner 的 crash/read-back 语义可以形成可执行 fixture; +7. P1 的 trusted project resolver、owner-guard 内 Shell lock、RFC 8785 canonicalization 与专用 Shell record namespace 已有单一实现边界; +8. P2 的 projection observation/witness 可以形成可执行 fixture; +9. PR #168 重新评审本文,而不是继续依赖旧评论或旧大文档段落。 diff --git a/docs/technical/【技术方案】AI游戏创作Agent Runtime交互边界重构实施计划-2026-08-12.md b/docs/technical/【技术方案】AI游戏创作Agent Runtime交互边界重构实施计划-2026-08-12.md new file mode 100644 index 000000000..6f17bb5b6 --- /dev/null +++ b/docs/technical/【技术方案】AI游戏创作Agent Runtime交互边界重构实施计划-2026-08-12.md @@ -0,0 +1,345 @@ +# AI 游戏创作 Agent Runtime 交互边界重构 + +> 文档角色:总览与分阶段实施计划 +> 状态:评审中;尚未允许进入 P1–P6 生产实现 +> 更新日期:`2026-08-17` + +## 0. 阅读入口与权威顺序 + +本文只解释重构目的、系统边界和 P0–P6 实施顺序,不定义协议字段与状态机。四份配套文档的职责和权威顺序如下: + +1. 本文:第一次理解方案和实施阶段的入口。 +2. [`【技术协议】AI游戏创作Agent Runtime交互合同V1-2026-08-17.md`](./【技术协议】AI游戏创作Agent%20Runtime交互合同V1-2026-08-17.md):唯一规范性协议;所有 `IC-*` 要求以它为准。 +3. [`【迁移方案】AI游戏创作Agent Runtime交互边界迁移矩阵-2026-08-17.md`](./【迁移方案】AI游戏创作Agent%20Runtime交互边界迁移矩阵-2026-08-17.md):把 `IC-*` 映射到当前代码、入口、阶段和验收证据。 +4. [`【设计依据】AI游戏创作Agent Runtime交互边界证据与决策附录-2026-08-17.md`](./【设计依据】AI游戏创作Agent%20Runtime交互边界证据与决策附录-2026-08-17.md):保存 `EV-*` 代码事实、`DR-*` 设计决策和 `EG-*` 证据门禁。 + +如四份文档发生冲突: + +- 当前代码和仓库最新架构文档决定“系统现在是什么”; +- Interaction Contract 决定“本次重构必须实现什么”; +- 迁移矩阵和证据附录不得改变 Contract,只能暴露当前差距; +- 实现发现 Contract 不可行时,先修改 Contract 并重新评审,不得在 Consumer 或 Adapter 中自行发明兼容语义。 + +--- + +## 1. 为什么要重构 + +当前 GUI、CLI、`swarm_cli`、Tauri wrapper 和测试路径分别承担了一部分 Runtime 生命周期判断: + +- 是否启动新 Run; +- 是否 steer 当前 Run; +- 是否直接回复; +- 如何处理用户输入、批准、拒绝、重试、恢复和取消; +- 如何合并 Runtime state、event、response stream 和 conversation; +- 如何把 Runtime 输出再次保存为聊天消息。 + +这导致同一个用户操作可能因 Consumer 不同而走不同控制流,也使前端刷新、CLI 无头运行、Runner 恢复和测试夹具难以共享同一行为边界。 + +本重构解决的不是“代码散落”本身,而是控制权归属不清: + +> Consumer 现在既展示状态,又在部分路径中决定下一步并写入 Runtime;重构后 Consumer 只展示后端状态并表达用户意图,Supervisor Shell 统一作出交互决策。 + +--- + +## 2. 目标边界 + +### 2.1 核心目标 + +1. GUI、CLI 和公开协议测试成为同一协议的平等 Consumer。 +2. Consumer 只执行 `render(snapshot)` 与 `dispatch(command)`,不推进 Runtime 状态机。 +3. Supervisor Shell 统一处理正式用户交互决策、命令校验、幂等受理和结果读回。 +4. 现有 Runtime task、state、pending、provider、steer、finalization、conversation 和 event records 继续作为执行事实源。 +5. External Runner 存在时,由持有现有 OS project execution-owner lock 的 Runner 执行正式写入。 +6. Public 与 Developer read model 分离,正式用户协议不泄漏路径、Provider、工具参数、内部 action 或 recovery 细节。 +7. 通过 Adapter 和明确 writer cutover 分阶段迁移,不制造第二套 Runtime authority 或第二份 conversation 正文。 + +### 2.2 不在本轮 + +- Runtime `main_loop`、task queue、Provider retry、delegation/all-join 或 Agent 执行状态机内部重构; +- LLM、Provider、提示词或工具体系调整; +- Runner 开机自启或无人值守常驻; +- 新增 live Session rotation、Session handoff、第二 active-session index 或 session control lease; +- 新增全局 owner generation/lease CAS; +- 重新设计资源上传、项目资源 lineage、Preview Registry 或 Session 管理面; +- 把管理命令、路径操作或 Developer 调试能力伪装成五个 Public Runtime 命令。 + +--- + +## 3. 新系统的一句话结构 + +```text +GUI / CLI / Tests + 读取 Public Snapshot 与 Public Conversation + 提交五个公开写命令 + ↓ +Supervisor Shell + 校验身份、权限、版本、目标和幂等性 + 决定 direct reply / start / steer / reject / interaction required + 通过 Adapter 调用现有 Runtime 能力 + ↓ +Existing Runtime + 继续维护 task / state / action / provider / finalization / conversation / event 事实 +``` + +四个角色的责任如下: + +| 角色 | 负责 | 禁止 | +|---|---|---| +| Consumer | 显示 Snapshot、提交 command、读取 Conversation | 根据 phase/文案自行选择 start、steer、retry、resume;直接解释私有 Runtime records | +| Supervisor Shell | 统一交互判断、命令受理、幂等、能力投影和错误映射 | 复制 Runtime 生命周期真相;把投影完成当成执行成功 | +| Runtime | 实际执行、恢复、finalization 和事实持久化 | 依赖 GUI 轮询推进状态 | +| Runner | 持 owner lock 时执行正式 Shell 写入、wake 和恢复 | 失去 owner 后继续写;依赖诊断 JSON 或本地时间接管 | + +--- + +## 4. 一次用户输入如何流动 + +1. Consumer 读取 `PublicSnapshot`。 +2. Snapshot 返回当前状态以及服务端生成的 command capability。 +3. 用户提交消息时,Consumer 调用 `submit_intent`,不调用 start/steer primitive。 +4. Shell 校验 schema、项目、Session、权限、requestId 和 capability target。 +5. Shell 持久化可读回的 request acceptance record。 +6. Shell 根据冻结 policy matrix 决定: + - DirectReply; + - Start; + - Steer; + - Reject; + - InteractionRequired。 +7. 需要 Runtime 执行时,Shell 通过 Adapter 绑定现有 run/steer/action/finalization identity;不复制这些对象的生命周期。 +8. Runtime 更新 durable facts。 +9. Public projector 从 facts 重建 Snapshot;`SnapshotChanged` 只提示 Consumer 重新读取 Snapshot。 +10. 文本交付通过 Public Conversation Adapter 按 source 回读;Snapshot 和 conversation 都不能互相推导对方的权威结论。 + +### 4.1 五个 Public 写命令 + +| 命令 | 用户含义 | Shell 负责决定的内部动作 | +|---|---|---| +| `submit_intent` | 提交消息或受支持的内置命令 | direct reply / start / steer / reject / interaction required | +| `answer` | 回答 UserInput | 校验 interaction revision、答案约束和 durable target | +| `approve` | 批准、拒绝或带意见返工 | 校验 audience、policy、artifact binding 和 rework identity | +| `cancel` | 取消精确 Supervisor Run | 校验 Session、Run 和取消矩阵;不伪造终态 | +| `resume` | 继续、重试或受信任 reconcile | 明确区分 ContinueRun、RetryTerminalRun、ReconcileRun | + +### 4.2 两个 read model + +- Public Snapshot:普通 GUI、普通 CLI 和公开测试的唯一完整 Runtime 视图。 +- Developer Snapshot:受信任开发入口的独立 DTO;扩大 read,不扩大正式 Supervisor 写权限。 + +### 4.3 Conversation 是独立展示通道 + +Public Conversation 不保存第二份正文,只建立 source-to-Public 索引并从原 source 回读。V1 区分: + +- User; +- DirectReply; +- RuntimeFinalReply; +- 满足准入条件的 RuntimeStatus; +- 满足准入条件的 PublicEvent。 + +不能稳定定位、校验或归属的 source 默认隔离,不因 GUI 当前能展示就进入永久 Public history。 + +--- + +## 5. 关键不变量 + +1. **单一执行事实源**:Runtime durable records 决定执行事实;Shell ledger 只记录 request 协调和 source binding。 +2. **单一正式 writer**:同一真实副作用和同一 conversation source identity 在任一时刻只有一个正式 writer。 +3. **服务端能力驱动**:没有 capability 就不能构造命令;有 capability 仍需 Shell 在锁内重读事实并复核。 +4. **结果未知不重放**:无法证明真实副作用是否发生时进入 outcome-unknown/reconciliation,不换 requestId 重做。 +5. **Session 不重归属**:历史 command、interaction 和 delivery 依赖已落盘 `agentId + sessionId + runId`,不依赖当前 active Session 猜测。 +6. **事件不是状态**:事件只提示重新读取 Snapshot;事件丢失、重复或乱序不能改变最终状态。 +7. **Conversation 不复制正文**:Public index 不成为正文 authority;source 不可回读时失败关闭。 +8. **Public 与 Developer 隔离**:Developer read capability 不能成为绕过同一 Shell write ingress 的通道。 + +完整规范见 Contract 中的 `IC-*` 要求。 + +--- + +## 6. 分阶段实施计划 + +### P0:行为基线与协议验证框架 + +**人话目标**:在改变系统前,建立可以重复观察当前行为、发现重构破坏的测试入口;不是决定协议,也不实现生产协议。 + +允许: + +- 只读 fixture、golden trace、negative fixture; +- crash-point harness; +- 调用图和 writer inventory; +- 对当前 identity、Session、owner、conversation 和 event 行为的代码/运行证据记录。 + +禁止: + +- 新生产 handler; +- Consumer fallback; +- 改变 Runtime 生产行为; +- 用空 DTO、stub 或 ignored test 假装协议已实现。 + +完成条件: + +- 迁移矩阵中的 P0 inventory 均有证据; +- 每条 `EG-*` 能区分“现状满足”“现状必须隔离”“待后续阶段实现”; +- 当前 master 行为基线可重复通过。 + +### P1:最小持久协议底座 + +**人话目标**:实现 Shell 以后需要的请求受理、结果读回和 source binding 基础,但不开放五个 Public 写命令。 + +实现: + +- 统一 Contract/schema 单一来源; +- 以专用 append-only Shell ledger 为 authority 的 command acceptance/read-back、interaction/rework mapping 与 source-binding record; +- 可从 ledger 重建的 projection journal/index; +- RFC 8785 canonical fingerprint/checksum、连续 ledgerVersion、内容安全过滤和损坏隔离; +- 专用 `.agent/runtime/supervisor-shell/` record namespace(不混入 `agent.db` 或 Runtime journal); +- `TrustedProjectContext` resolver、execution-owner guard 内的 Shell lock 与调用来源基础设施。 + +P1 的实现边界:Public DTO 始终无路径,但 Shell 只能接收宿主已解析、已核验 manifest 的 trusted project context;现有 `.agent/project.lock` 具有 PID/时间回收语义,不能作为 Shell protocol lock。`.agent/runtime/supervisor-shell/ledger.jsonl` 是唯一追加顺序 authority,sidecar/index 只是可重建缓存。P1 交付的是持久协调底座和 read-back,不把当前 Runner 内存 request cache 当作幂等证据,也不开放 Public 写入口。 + +不实现: + +- 新 Public 写入口; +- Consumer 迁移; +- 第二份 task/finalization/provider/steer 生命周期。 + +### P2:Public / Developer Snapshot 与事件流 + +**人话目标**:先让 Consumer 能通过一个稳定接口看懂系统,而不改变旧写行为。 + +实现: + +- Public Snapshot; +- Developer Snapshot; +- Snapshot revision/hash; +- Public/Developer 隔离的 `(projectId, view)` Snapshot 订阅、`SnapshotChanged` 有界事件和重连; +- read-only/shadow projection; +- User/Developer interaction view 的只读物化; +- 带 source identity/revision/digest witness 与正常缺失/损坏矩阵的有界 projection observation:能确定 project/view scope 而观察无法闭合时,发布无 capability、无未证实 Runtime 事实的 fail-closed invalid/reconciliation Snapshot;完全不能确定安全 outcome 时返回 read error,而不挑一份跨文件旧读结果继续。 +- 为每项协作执行持久化 opaque `collaborationId` binding;同组多 child、retry successor 与 manifest fallback replacement 不依赖动态 child identity;无 parent run 的静态 fallback 绑定 project/session/manifest digest/group,不能承载可操作 interaction。 + +旧 GUI/CLI 仍保留写路径;shadow 只能比较投影,不能执行真实副作用。P2 不能把当前跨 `runtime.json`、JSONL、stream 和 sidecar 的聚合读取结果直接序列化为 Public Snapshot。 + +### P3:五命令与统一 Interaction Loop + +**人话目标**:让后端具备完整、真实可用的统一写协议,并将新旧正式入口收进同一 Shell ingress。 + +实现: + +- 五个 Public 命令及 strict schema; +- requestId 幂等、业务拒绝读回、unknown outcome; +- submit intent policy matrix; +- answer/approve/cancel/resume 状态机; +- Public Conversation read adapter; +- legacy ingress 的单 writer 收口。 + +P3 不提前迁移 GUI/CLI 的读模型和界面体验,但必须先收口真实 writer:任何仍能操作同一 Supervisor Run 的旧 Tauri/CLI/`swarm_cli` wrapper 都要转发同一 Shell handler(或在新协议启用时明确禁用),不得先在 Consumer 进程写 Runtime 再通知 Runner。P5 只迁移 Consumer 的读与交互体验。 + +### P4:Runner 自驱与安全恢复 + +**人话目标**:已受理操作不依赖 GUI 轮询推进;Runner 在现有 owner/lifecycle 门禁内完成 wake、恢复和 reconciliation。 + +实现: + +- 已接受 operation 的 durable wake/discovery; +- dirty projection 修复; +- Runner 重启后的安全恢复与跨重启 project discovery registry; +- drain、owner 冲突和 GUI-owner/CLI 启动路径的区分; +- outcome-unknown 零自动真实副作用重放; +- watchdog 强退视为 crash 边界,而非已完成的 drain。 + +本阶段不新增 headless lease,也不承诺无人值守常驻。 + +### P5:迁移 CLI、Tests、GUI + +**人话目标**:只切换 Consumer,不新增协议语义。 + +顺序: + +1. 普通 Supervisor CLI; +2. 面向 Public Contract 的测试; +3. GUI; +4. Developer UI/CLI 的独立 read 边界。 + +迁移后: + +- Consumer 只读 Snapshot/Conversation,只提交五命令; +- GUI 不再解释 Runtime phase、合成启动决策或 autosave Runtime output; +- CLI 不再直接调用 start/steer/resume primitive; +- 内部 Runtime 单测和恢复测试仍可直接测试内部能力。 + +P5 前产品决策 `FD-001`:`--swarm-chat` 必须明确选择为只读 Public view 的普通 Supervisor CLI,或显式受信任的 Developer CLI;无论选择哪种,其正式写操作均不得绕过 Shell。 + +### P6:删除旧公开面并最终收口 + +**人话目标**:删除已经没有正式 Consumer 的旧公开控制协议,同时保留 Runtime 内部能力和必要回归测试。 + +删除: + +- 正式 transport 的旧 start/steer/confirm/reject/answer/cancel/retry/resume/schedule/read 注册; +- Consumer 旧调用点和生命周期分支; +- GUI Runtime output 派生 autosave; +- migration fallback; +- Public scope 内缺少稳定 messageId 的 conversation append。 + +保留: + +- Runtime 内部 start/steer/resume/recovery primitive; +- 验证内部能力的单元和恢复测试; +- 独立管理面 goal/compact/session/config; +- 明确隔离的 Developer/local history。 + +--- + +## 7. 里程碑 + +| 里程碑 | 对应阶段 | 产出 | 允许进入下一阶段的条件 | +|---|---|---|---| +| M0 | P0 | 基线、调用图、证据门禁 | 现状与隔离边界可证明 | +| M1 | P1 | 最小持久底座 | 原子性、损坏、幂等基础测试通过 | +| M2 | P2 | 双 Snapshot 与事件 | source 缺失/损坏、fail-closed 发布、协作 lineage、订阅重连/缺口、权限和字段隔离通过 | +| M3 | P3 | 五命令、Interaction、Conversation read | crash/read-back、单 writer、跨 transport fixture 通过 | +| M4 | P4 | Runner wake/recovery | owner、drain、重启、unknown outcome 通过 | +| M5 | P5 | CLI/Tests/GUI 迁移 | 三类 Consumer 行为等价且无私有字段依赖 | +| M6 | P6 | 旧公开面删除 | 静态调用图和最终协议验收通过 | + +阶段完成条件必须引用 Contract `IC-*`、迁移矩阵 `MX-*` 和证据门禁 `EG-*`;本文不重复字段级验收。 + +--- + +## 8. 冻结与开发准入 + +当前允许: + +- 继续评审和收束四份文档; +- 编写不改变生产行为的 P0 基线与 fixture 骨架; +- 解决 `FD-001` 产品决策。 + +当前不允许: + +- 开始 P1–P6 生产实现; +- 因实现方便而修改 Contract 语义; +- 根据旧评论恢复 owner generation、Session rotation、handoff 或 Consumer fallback; +- 把 P0 证据任务解释为“以后再决定协议规则”。 + +允许进入 P1 的前提: + +1. P0/M0 已完成:当前 master 行为基线可重复通过,正式 ingress/read/writer inventory 已形成,且每条后续 `EG-*` 已标记现状、隔离边界和责任阶段; +2. Contract 中没有未标注的候选字段、重复定义或互相冲突的 `IC-*`; +3. 迁移矩阵覆盖所有正式 ingress、read、conversation writer 和删除面; +4. 附录中的冻结前 `EG-*` 有明确预期结果; +5. P1 的 trusted project resolver、owner-guard Shell lock、RFC 8785 canonicalization、专用 Shell record namespace 已明确为单一实现边界; +6. `FD-001` 可在 P5 开始前决定,不阻塞 Contract 核心冻结或 P0–P4; +7. PR #168 完成针对四份文档职责和 Contract 可施工性的重新评审。 + +--- + +## 9. 最小心智模型 + +```text +Consumer 只表达意图、读取状态; +Shell 统一交互决策和正式写入口; +Runtime 继续保存和推进执行事实; +Runner 只在持有现有 owner 时写; +Snapshot 是状态视图,事件是刷新提示; +Conversation 从原 source 回读,不复制正文; +不知道副作用结果时停止并 reconciliation,不重复执行。 +``` diff --git a/docs/technical/【设计依据】AI游戏创作Agent Runtime交互边界证据与决策附录-2026-08-17.md b/docs/technical/【设计依据】AI游戏创作Agent Runtime交互边界证据与决策附录-2026-08-17.md new file mode 100644 index 000000000..77bd5f92a --- /dev/null +++ b/docs/technical/【设计依据】AI游戏创作Agent Runtime交互边界证据与决策附录-2026-08-17.md @@ -0,0 +1,432 @@ +# AI 游戏创作 Agent Runtime 交互边界证据与决策附录 + +> 文档角色:代码事实、设计决策、反例与证据门禁 +> 状态:持续维护;不能覆盖 Interaction Contract +> 规范来源:[`【技术协议】AI游戏创作Agent Runtime交互合同V1-2026-08-17.md`](./【技术协议】AI游戏创作Agent%20Runtime交互合同V1-2026-08-17.md) +> 迁移入口:[`【迁移方案】AI游戏创作Agent Runtime交互边界迁移矩阵-2026-08-17.md`](./【迁移方案】AI游戏创作Agent%20Runtime交互边界迁移矩阵-2026-08-17.md) + +## 0. 使用边界 + +本附录只保存三类内容: + +- `EV-*`:当前代码已经能直接证明的事实; +- `DR-*`:明确采用或拒绝的设计决策及其理由; +- `EG-*`:证明实现满足 `IC-*` 的测试/调用图门禁。 + +代码变化可能使 `EV-*` 过期;此时必须更新 evidence 和迁移矩阵。不得为了适应过期代码事实而静默放宽 Contract。 + +--- + +## 1. 当前代码事实 + +### 1.1 Session 与 conversation + +#### EV-SESSION-001:Session catalog 按 Agent 持久化 + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/project/conversation.rs` +- 关键对象/函数:Agent Session catalog、`read_game_creator_agent_session_catalog_at` 一类 catalog 读写函数。 +- 事实:catalog 保存 `schemaVersion + agentId + activeSessionId + sessions`;不是项目级全 Agent catalog。 +- 事实:当前没有独立 `sessionRevision`;不能把候选 digest 写回或解释为第二 revision。 +- 约束:支持 `IC-ID-002`、`IC-ID-003`;对应 `MX-ID-002`、`MX-ID-003`。 + +#### EV-SESSION-002:Live task 阻止 Session mutation + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/project/conversation.rs` +- 关键函数:`ensure_agent_session_has_no_live_tasks`、create/fork/set-active/archive Session 路径。 +- 事实:Agent 有未终结 Runtime task 时,create/fork/archive/set-active 会被拒绝。 +- 约束:V1 不能用新协议绕过该语义,也不能默认具备 live handoff。 + +#### EV-CONV-001:Conversation 支持有 identity 和无 identity append + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/commands.rs` +- 关键函数:Tauri command `append_local_conversation_message`。 +- 事实:`messageId: Option`;有值走 idempotent append,无值走普通 append。 +- 风险:Public cutover 后无 identity append 会破坏去重、source mapping 和完整性证明。 +- 约束:支持 `IC-CONV-010`;对应 `MX-CONV-012`~`MX-CONV-014`。 + +#### EV-CONV-002:Conversation 正文已有持久 source + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/project/conversation.rs` +- 关键函数:`append_local_conversation_message_for_session_at`、`append_local_conversation_message_for_session_idempotent_at`、带 finalization 的幂等 append。 +- 事实:已有 project conversation 与 Agent Session conversation;Public adapter 无需复制正文。 +- 约束:支持 `IC-CONV-002`。 + +### 1.2 Project owner、Runner 与 CLI + +#### EV-OWNER-001:OS lock 是当前 project execution owner + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/runner/project_owner.rs` +- 事实:`.agent/runtime/execution-owner.lock` 通过平台 OS 文件锁实现排他;Windows/Unix 分别有安全打开与文件类型校验。 +- 约束:支持 `IC-OWNER-001`;拒绝新增平行 owner authority。 + +#### EV-OWNER-002:Owner JSON 和 bootId 是诊断信息 + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/runner/project_owner.rs`、`runner/state.rs`、`runner/protocol.rs`。 +- 事实:诊断 record 描述 owner/boot,但真正写入排他来自 lock handle。 +- 风险:按 JSON、mtime、本地时钟或 bootId generation 接管会形成第二 authority。 + +#### EV-OWNER-003:现有 project 写锁不是 execution owner + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/project/filesystem.rs`。 +- 事实:`.agent/project.lock` 用 create-new 文件和 PID/时间/mtime stale reclaim;它服务现役项目写操作,不由 Runner execution owner guard 定义。 +- 约束:不能把它直接解释为 `IC-OWNER-002` 的 supervisor project lock;Shell 必须在真实 owner 下另行串行。 + +#### EV-OWNER-004:进程内 Runtime 当前只持局部锁 + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_driver/recovery_scan.rs`、`runner/state.rs`。 +- 事实:production execution owner 的获取在 Runner state;未启用 Runner 的恢复主要依赖 Agent task/run lock。 +- 约束:P1/P3 进程内 Shell 必须在任何 record/projection/Runtime 写之前补同一 OS owner-lock 获取,不能把局部锁当等价 owner。 + +#### EV-RUNNER-001:Runner 已有内部 Runtime RPC + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/runner/dispatch.rs` +- 当前方法包括:`runtime.resume`、`runtime.continue_action`、`runtime.steer`、`runtime.interrupt_for_steer_decision`、`runtime.pause`、`runtime.cancel`、`runtime.compact`、`runtime.wake_pending`。 +- 事实:这些是现有 Runner 内部控制能力,不能因新 Shell 再作为平行 Public 协议保留。 +- 约束:支持 `IC-CMD-001`、`IC-CMD-010`;对应 `MX-ING-006`。 + +#### EV-CLI-001:CLI 可无 GUI 启动/连接受限 Runner + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/cli.rs` 与 Runner client/server 路径。 +- 事实:Runtime 写入要求显式项目外 `--config-dir` 并可启动 External Runner;普通 CLI Runner 路径不要求 GUI-owner。 +- 约束:V1 保留该终端会话能力,不新增 headless lease,也不承诺无人值守常驻。 + +#### EV-CLI-002:CLI/`swarm_cli` 当前仍直接调用内部能力 + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/cli.rs`、`src-tauri/src/swarm_cli/turn_dispatch.rs`。 +- 事实:`AgentSteer` 路径调用 `steer_game_creator_agent_runtime_task_at`;`swarm_cli` 可 dispatch Runtime turn 并直接 append user/assistant conversation。 +- 约束:支持 `MX-ING-004`、`MX-ING-005`、`MX-CONV-002`。 + +#### EV-RUNNER-002:request 去重与已知项目均是进程内状态 + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/runner/state.rs`、`runner/protocol.rs`、`runner/dispatch.rs`。 +- 事实:`write_request_cache` 和 `known_roots` 都在 Runner 内存;重启后 cache 无法提供 request result read-back,Runner 也不能仅凭自身发现此前项目。 +- 约束:P1 durable command record 不能复用该 cache;P4 的自驱恢复必须增加受信任的跨重启候选项目发现,且每个候选仍重取 owner、重读 durable evidence。 + +### 1.3 Runtime final reply 与 response stream + +#### EV-FINAL-001:messageId 与 finalizationId 不是同一 identity + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/finalization.rs` +- 事实:final reply `messageId` 由 Agent/Session/Run 派生;`finalizationId` 还绑定 response fingerprint、revision、request slot、steer cursor、plan 和 Goal fingerprint。 +- 约束:支持 `IC-CONV-005`;Public 去重 key 不能反推 finalization。 + +#### EV-FINAL-002:Response stream 有独立 tuple + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/response_stream.rs` +- 事实:stream 使用 taskId/sessionId/runId/requestSlot/responseRevision/appliedSteerCursor;`streaming → ready → committed` 会合法改变 status/sequence。 +- 约束:status/sequence 不能被放入“不可变 source identity digest”。 + +#### EV-FINAL-003:Response stream 不能独自证明 committed + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_actions/response_stream.rs` +- 事实:部分 streaming sidecar 写错误被忽略;publisher 可在 char 上限处截断;dirty 状态不能替代写后回读。 +- 约束:支持 `IC-IDEMP-004`、`IC-CONV-005`;必须交叉验证 finalization 和 conversation lifecycle。 + +#### EV-FINAL-004:成功后 recovery sidecar 会删除 + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_state.rs` 与 `runtime_protocol/finalization.rs`。 +- 事实:成功路径完成 conversation assistant、Runtime completed、response committed 后会清理 finalization/provider/tool-plan handoff recovery sidecar。 +- 约束:历史正文必须从 conversation messageId 回读,不能假定 sidecar 永久存在。 + +#### EV-PROJECTION-001:现有 Runtime 聚合读取不是原子观察点 + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_driver/entrypoints.rs`、`agent/runtime_state.rs`。 +- 事实:读取会依次组合 runtime state、task/event JSONL、response stream 和 sidecar;写入跨文件,state rename 与 journal append 各有独立锁/时刻。 +- 约束:P2 不能直接把该聚合结果包装为 Public Snapshot;必须建立带 identity/revision/digest witness 的 observation,无法闭合即 fail closed。 + +### 1.4 RuntimeStatus + +#### EV-STATUS-001:根 Supervisor status 落在 project conversation + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_state.rs` +- 关键函数:`append_game_creator_agent_runtime_public_status_message_at`。 +- 事实:messageId 由 agentId/sessionId/runId/status correlation 派生,但 append 时 `agent_id=None`、`session_id=None`。 +- 约束:进入 `(projectId, sessionId)` Public history 前必须显式保存 correlation mapping,不能从文件 scope 猜 Session。 + +#### EV-STATUS-002:专业 Agent terminal status 落在其 Session conversation + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_state.rs` +- 关键函数:`append_game_creator_agent_runtime_terminal_public_message_at`。 +- 事实:非根 Supervisor 的 terminal status 使用其 `agentId/sessionId` 幂等 append。 +- 约束:历史消息保持原 agent/session/run,不重归属到 Supervisor 当前 Session。 + +#### EV-STATUS-003:部分 Supervisor continuation 不写 Session status + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_state.rs`。 +- 事实:有 parent agent/run 的 Supervisor receipt 或 isolated-join continuation 为避免重复 formal project chat,terminal path直接返回,不写第二 Session message。 +- 约束:这类 status 默认不进入 Public Conversation;不能假设每个 Run 有同构 status source。 + +#### EV-STATUS-004:Accepted start status 只覆盖特定根 Supervisor + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_driver/task_start.rs`。 +- 事实:`requires_public_start_status` 只对无 parent 的根 Project Supervisor 且非 receipt/join source 生效。 +- 约束:P0 必须按类型而非泛化 “RuntimeStatus” 建 fixture。 + +### 1.5 Runtime event + +#### EV-EVENT-001:普通 eventId 不可恢复 + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_state.rs` +- 关键函数:`new_game_creator_agent_runtime_event_id`。 +- 事实:无 actionId 时使用 `pid + unixMillis + process-local sequence + eventType`;重启/重试没有稳定规范 key。 +- 约束:支持 `IC-CONV-007` 默认拒绝。 + +#### EV-EVENT-002:带 actionId 的 event 只覆盖部分路径 + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_state.rs` +- 关键函数:`append_game_creator_agent_runtime_event_with_action`。 +- 事实:有 actionId 时可按 run/eventType/phase/actionId 形成较稳定 identity 和重复检查;普通 append 仍生成新 eventId。 +- 约束:即使 action event 较稳定,也必须同时满足 reader、digest、scope 和重放条件才能显式登记 Public。 + +#### EV-EVENT-003:现有 reader 吞坏行并截断最近 20 条 + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_state.rs`、`src-tauri/src/main.rs`。 +- 关键函数/常量:`read_recent_game_creator_agent_runtime_events_for_session`、`AGENT_RUNTIME_RECENT_EVENT_LIMIT = 20`。 +- 事实:JSON 解析失败直接跳过;成功记录只返回最后 20 条。 +- 约束:该 reader 只能支持当前 GUI recent display,不能作为 `IC-CONV-007` 的 Public source reader。 + +#### EV-EVENT-004:Event record 自带公开正文 + +- 代码:`apps/ai-game-creator-shell/src-tauri/src/agent/runtime_state.rs`。 +- 事实:allowlist event 写入 `publicText`;正文不一定存在于 conversation message。 +- 约束:若未来接入,PublicEvent 是 source-record projection 例外,不能复制成普通 assistant conversation。 + +### 1.6 GUI writer 与跨 scope 落盘 + +#### EV-GUI-001:GUI 为 Runtime event 生成第二 identity + +- 代码:`apps/ai-game-creator-shell/src/features/project-workspace/SupervisorChatOnlyView.tsx`。 +- 事实:GUI 以 `game-chat-runtime-event:${eventId}` 构造聊天 message,并同时聚合 Supervisor 和直接 child events。 +- 约束:该 identity 不能进入规范 Public history。 + +#### EV-GUI-002:GUI 为 final reply 生成派生 identity + +- 代码:`apps/ai-game-creator-shell/src/features/project-workspace/SupervisorChatOnlyView.tsx`。 +- 事实:GUI 使用 `game-chat-final-reply:*` 构造 final 聊天 message。 +- 约束:应归一到现有 finalization conversation `messageId`。 + +#### EV-GUI-003:派生消息会 autosave 到 project conversation + +- 代码:`apps/ai-game-creator-shell/src/App.tsx`。 +- 事实:全局 messages autosave 可用 `agentId=null` 调用 `append_local_conversation_message`;child event 的 source Session 与实际 project transcript scope 不同。 +- 约束:支持 `MX-CONV-010`、`MX-CONV-011`;历史跨 scope 项默认隔离。 + +#### EV-GUI-004:普通 Agent chat 直接 append + +- 代码:`apps/ai-game-creator-shell/src/App.tsx`、`features/app-shell/useDeveloperAgentPanel.ts`。 +- 事实:普通 Agent user/assistant、错误回复和 Developer panel user message 存在直接 append 调用。 +- 约束:writer cutover 必须覆盖全部调用方,而不是只覆盖 Runtime output 双写。 + +--- + +## 2. 设计决策 + +### DR-001:采用统一 Supervisor Shell + +- 决定:正式 Consumer 只读状态、表达意图;Shell 统一交互决策。 +- 原因:GUI/CLI/测试当前存在重复且不一致的生命周期判断。 +- Contract:`IC-ARC-001`~`IC-ARC-004`。 + +### DR-002:拒绝平行 Runtime authority + +- 拒绝:让 request ledger、projection ledger 或 Public Snapshot 自己决定 task/finalization/provider 成功。 +- 原因:现有 Runtime facts 跨多个 record,当前没有可复用的全局事务;平行状态会漂移。 +- Contract:`IC-ARC-004`、`IC-IDEMP-003`、`IC-READ-004`。 + +### DR-003:拒绝 Session rotation 与 handoff + +- 拒绝:ActiveSessionIndex、live Session rotation、handoff manifest、continuation set、rotation fence、session control lease。 +- 原因:现有 catalog 明确禁止 live task 时切换;新增能力需要跨 task/conversation/finalization/interaction 的迁移和 rollback authority,超出本轮交互边界重构。 +- Contract:`IC-ID-002`、`IC-ID-003`。 + +### DR-004:拒绝全局 owner generation/lease + +- 拒绝:用 boot generation、诊断 JSON、lease expiry 或本地时间替代 OS lock。 +- 原因:会建立第二 owner authority,并在 pause/时钟漂移/文件残留时产生双 writer。 +- Contract:`IC-OWNER-001`。 + +### DR-005:采用 Snapshot + 有范围的事件提示 + +- 决定:Snapshot 是完整 Public read;event 只提示重新读取。Public 与 Developer 事件流按 `(projectId, view)` 隔离,订阅原子取得完整初始 Snapshot。 +- 原因:Consumer 本地合并不能可靠处理缺口、重连和跨 source 更新;全局或按路径过滤的 event 会泄露/混淆多项目状态。 +- Contract:`IC-READ-001`、`IC-READ-004`、`IC-EVT-001`~`IC-EVT-003`。 + +### DR-005A:fail-closed 也是可发布状态 + +- 决定:source observation 无法闭合但仍能确定 project/view scope 时,发布无 capability、无未证实 Runtime 事实的 `failClosed` Snapshot;完全不能确定安全 outcome 时返回 read error。 +- 原因:若 invalid 状态不推进 revision/hash/event,Consumer 会永久保留一份已失效的 valid Snapshot;保留旧 capability 会绕过失败关闭。 +- Contract:`IC-READ-001`、`IC-READ-004`、`IC-CAP-002`。 + +### DR-005B:协作实体有独立持久 identity + +- 决定:Public collaborator 使用 durable `collaborationId` binding,不从 group 或动态 child Agent identity 临时拼接;retry/successor 延续该 ID,manifest fallback 被 Runtime binding 替换。 +- 原因:同组多 child、重试与 isolated 执行都不能由单一 group/agentId 稳定代表,且 Public 不得泄露真实 child identity。 +- Contract:`IC-ID-003`、`IC-READ-001`、`IC-INT-002`。 + +### DR-006:采用五命令,不公开内部 primitive + +- 决定:`submit_intent/answer/approve/cancel/resume` 是唯一 Public 写集合。 +- 原因:Consumer 表达用户意图,不选择 Runtime primitive。 +- Contract:`IC-CMD-001`~`IC-CMD-010`。 + +### DR-007:Conversation 不复制正文 + +- 决定:Public 只建无正文 source index,从既有 conversation/event source 回读。 +- 原因:复制会建立第二正文 authority,并放大 GUI/CLI 双写。 +- Contract:`IC-CONV-002`。 + +### DR-008:PublicEvent 默认拒绝 + +- 决定:普通现有 event 不进入永久 Public history;只有显式登记且满足全部 identity/reader/digest/scope 条件的类型才可接入。 +- 原因:现有普通 eventId 不可恢复,reader 截断且吞坏行,GUI 还会再造 identity。 +- Contract:`IC-CONV-007`。 + +### DR-009:RuntimeStatus 按具体 source 准入 + +- 决定:不把 RuntimeStatus 泛化为所有 Run 的同构 conversation source。 +- 原因:根 Supervisor、专业 Agent 和 receipt/join 的实际落盘行为不同。 +- Contract:`IC-CONV-006`。 + +### DR-010:结果未知时停止而非重放 + +- 决定:Provider/工具/Runtime 副作用可能发生但不可证明时进入 outcome-unknown/reconciliation。 +- 原因:换 requestId 或 fallback 会产生重复真实副作用。 +- Contract:`IC-IDEMP-004`、`IC-MIG-002`。 + +### DR-011:保留 CLI 无 GUI 的受限 Runner 能力 + +- 决定:不以 GUI-owner 门禁删除现有 CLI 会话期间启动/连接 Runner 的能力。 +- 原因:普通 CLI 是协议平等 Consumer,headless 能力是前端逻辑是否泄漏的重要验收。 +- Contract:`IC-OWNER-001`。 + +### DR-012:`--swarm-chat` 产品定位仍需显式决定 + +- 决策 ID:`FD-001`。 +- 可选:普通 Public Supervisor CLI;或显式受信任 Developer CLI。 +- 不可选:无 capability 时静默读取私有字段;Developer write 绕过 Shell。 +- Contract 不变量:`IC-MIG-004`。 + +--- + +## 3. 冻结前证据门禁 + +同一个 `EG-*` 跨多个阶段时,状态按 `EG-ID@P阶段` 独立记录:某阶段 PR 只需关闭属于该阶段的子门禁,后续阶段的未实现证据不阻塞前一阶段完成;最终门禁只有在全部子门禁关闭后才整体完成。后续实现若推翻已关闭证据,必须重新打开对应子门禁。下文“阶段”按顺序对应各阶段必须提供的证据,不得以一个阶段的局部通过冒充整项关闭。 + +### EG-BASE-001:当前行为基线 + +- 对应:全部 P0。 +- 要求:确定性 Provider/进程内 Runtime 记录 submit、等待、批准、取消、恢复、终态与副作用计数;归一化随机 ID/时间。 +- 失败处理:阻塞迁移比较,不改变 Contract。 + +### EG-SCHEMA-001:Strict wire fixture + +- 对应:`IC-WIRE-001`、`IC-WIRE-002`。 +- 要求:`@P0` 定义全部 DTO 的 schema/golden/negative 向量和预期结果;`@P1` 实现 Rust→TypeScript 生成/校验,覆盖未知/重复/错误字段、tagged union、大小、Unicode scalar/UTF-8 byte、Public 零路径/私有字段。 +- 阶段:P0(规范向量)/P1(实现与通过);`@P1` 阻塞 P2/P3。 + +### EG-ID-001:身份与 Session + +- 对应:`IC-ID-001~005`。 +- 要求:projectId/path mismatch;opaque catalog digest;live-task create/fork/archive/set-active 拒绝;Supervisor 与 collaborator 交叉 Session mutation;历史 delivery 不重归属。 +- 阶段:P0/P2/P3。 + +### EG-OWNER-001:Owner 与执行位置 + +- 对应:`IC-OWNER-001~002`、`IC-CMD-010`。 +- 要求:External Runner 下所有正式 writer 实际在 owner Runner;进程内测试持等价 owner;双 Runner、drain、失锁、GUI-owner 丢失、CLI 启动回归。 +- 阶段:P0/P3/P4/P5。 + +### EG-STORE-001:Shell durable 底座 + +- 对应:`IC-ID-001`、`IC-OWNER-001~002`、`IC-DUR-001~003`、`IC-IDEMP-001~005`。 +- 要求:trusted project resolver 的缺失/manifest mismatch;进程内与 Runner 对同一 project owner 互斥;`.agent/project.lock` stale reclaim 不参与 Shell 互斥;RFC 8785 向量;专用 Shell ledger 的连续 ledgerVersion、tail repair/中间损坏隔离、atomic write、回读、checksum、派生 index 重建与 Runner crash 后 read-back。 +- 阶段:P1;阻塞 P2/P3。 + +### EG-PROJECTION-001:Projection observation + +- 对应:`IC-READ-001~004`、`IC-EVT-001~003`、`IC-CAP-001~003`。 +- 要求:读 manifest/catalog/state/task/event/stream/Shell binding/projection journal 期间并发变化;source witness 变化的有界 retry;验证 normal/required absence、损坏和 conflict;验证 failClosed 完整固定向量及 manifest identity 不可证明时 read error;逐类 capability issuance/撤销;首次 revision1/sequence0。 +- 阶段:P2;阻塞 P2 完成与 P3 capability 依赖。 + +### EG-CMD-001:Request 幂等与崩溃读回 + +- 对应:`IC-IDEMP-001~005`、`IC-CMD-001~010`。 +- 要求:同 request 同/异 fingerprint、并发重复、业务拒绝重放、prepared/executing/succeeded 各 crash point、Runner 强杀、unknown outcome 零重复副作用。 +- 阶段:P1/P3/P4。 + +### EG-INT-001:Interaction 状态机 + +- 对应:`IC-INT-001~007`。 +- 要求:identity/revision/response replay;Public interaction capability 与 allowedActions 精确一致;User/Developer audience;question/option/freeform;target set;artifact digest;requestChanges 唯一 rework;Resolving crash recovery;collaboration binding 的 restart 重建、retry successor/parent lineage/source/group 漂移旧 interaction stale、manifestFallback 不可操作。 +- 阶段:P2/P3。 + +### EG-READ-001:Snapshot 与事件 + +- 对应:`IC-READ-001~004`、`IC-EVT-001~003`、`IC-CAP-001~003`。 +- 要求:Public/Developer `(projectId, view)` 路由隔离、原子 initial Snapshot、snapshot-first/no-backlog、duplicate/out-of-order/gap/reconnect;Public failClosed 固定向量、Developer source failure 统一 read error;revision/hash/排序/size canonical vectors,Public/Developer 超限均返回固定 read error 且无 partial DTO;全部 capability 正反签发与 cancel run revision/builtin Session/retry policy guards;bootstrap collaborators 为空、parentRun multi-child、retry lineage、fallback replacement、stale cancel 复核。 +- 阶段:P2。 + +### EG-CONV-001:Final reply source + +- 对应:`IC-CONV-005`。 +- 要求:messageId/finalizationId/stream tuple 唯一性;streaming→ready→committed;publisher 写失败/截断;sidecar 清理后 conversation 回读;Provider 调用计数。 +- 阶段:P0/P3/P4。 + +### EG-CONV-002:Status source + +- 对应:`IC-CONV-006`。 +- 要求:根 Supervisor start/terminal、专业 Agent terminal、receipt/isolated join 无 source 三类分别验证;project status correlation 缺失/冲突失败关闭。 +- 阶段:P0/P3。 + +### EG-CONV-003:Event 默认隔离与准入 + +- 对应:`IC-CONV-007`。 +- 要求:枚举规范 action identity 与普通 pid/time identity call site;普通 event 未进入 Public chain;如接入某类型,必须通过 eventId 定位、坏行/截断报告、digest、scope 和重放 fixture。 +- 阶段:P0/P1/P3;不通过只阻塞该 event type 接入,不阻塞默认隔离方案。 + +### EG-CONV-004:Writer cutover + +- 对应:`IC-CONV-010`。 +- 要求:全部 `append_local_conversation_message` 调用方三选一;GUI final/event autosave 停止;同 source 单 writer;Public scope 无缺少 messageId append。 +- 阶段:P0/P3/P5/P6。 + +### EG-CONV-005:Cursor 与历史完整性 + +- 对应:`IC-CONV-008`、`IC-CONV-009`。 +- 要求:origin/tail、分页、永久 sequence 空洞、duplicate、非法 cursor、index/source/digest/correlation 损坏、无 partial page、session-lifetime cursor。 +- 阶段:P3/P5/P6。 + +### EG-MIG-001:跨 Consumer golden replay + +- 对应:`IC-ARC-001`、`IC-MIG-001~004`。 +- 要求:GUI、普通 CLI、进程内测试和 Runner transport 对同一输入产生等价 request/result/Snapshot/conversation 语义和副作用计数。 +- 阶段:P3/P5/P6。 + + +### EG-INGRESS-001:P3 正式写入口与 writer cutover + +- 对应:`IC-CMD-010`、`IC-CONV-010`、`IC-MIG-005`。 +- 要求:legacy Tauri/CLI/`swarm_cli`/helper 的正式写入口全部转发同一 Shell handler 或禁用;Public Conversation adapter 启用前所有 writer 已接管、隔离或停止;cutover watermark 后零旧正式 writer、零派生双写。 +- 阶段:P3;阻塞 P3 完成与 P5 Consumer 迁移。 + +### EG-RUNNER-001:P4 跨重启发现与安全恢复 + +- 对应:`IC-OWNER-001~002`、`IC-IDEMP-004`、`IC-MIG-006`。 +- 要求:trusted discovery registry 的注册/删除/损坏/权限 fixture;Runner 重启后重新解析 manifest、重取 owner、按 durable evidence wake/reconcile/no-op;未知真实副作用零自动重放。 +- 阶段:P4;阻塞 P4 完成。 + +### EG-DEL-001:旧公开面删除 + +- 对应:`IC-MIG-003`。 +- 要求:正式 invoke handler、transport、Consumer、Public DTO 不再引用旧协议;内部 primitive 与回归测试仍存在;Preview/resource/session 管理面未误删。 +- 阶段:P6。 + +--- + +## 4. 证据更新规则 + +1. `EV-*` 只能由代码读取、定向测试或运行证据支持;README/旧设计声明不能单独成为事实。 +2. 代码与 `EV-*` 冲突时先更新 evidence 和迁移矩阵;若冲突使 `IC-*` 不可实现,再提交 Contract 变更评审。 +3. `EG-*` 失败的默认处理是隔离、阻塞阶段或进入 reconciliation,不是增加 Consumer fallback。 +4. 每个 P0–P6 PR 必须列出所实现的 `IC-*`、受影响 `MX-*` 和关闭的 `EG-ID@P阶段`;不得把跨阶段门禁标记为提前整体完成。 +5. 本附录不保存密钥、Token、绝对本地私密路径、Provider 原文、会话记录或构建产物。 diff --git a/docs/technical/【迁移方案】AI游戏创作Agent Runtime交互边界迁移矩阵-2026-08-17.md b/docs/technical/【迁移方案】AI游戏创作Agent Runtime交互边界迁移矩阵-2026-08-17.md new file mode 100644 index 000000000..e2d97c94a --- /dev/null +++ b/docs/technical/【迁移方案】AI游戏创作Agent Runtime交互边界迁移矩阵-2026-08-17.md @@ -0,0 +1,161 @@ +# AI 游戏创作 Agent Runtime 交互边界迁移矩阵 + +> 文档角色:把 Interaction Contract 映射到当前代码、阶段和验收证据 +> 状态:P0 inventory;矩阵不得修改 `IC-*` 语义 +> 总览入口:[`【技术方案】AI游戏创作Agent Runtime交互边界重构实施计划-2026-08-12.md`](./【技术方案】AI游戏创作Agent%20Runtime交互边界重构实施计划-2026-08-12.md) +> 规范来源:[`【技术协议】AI游戏创作Agent Runtime交互合同V1-2026-08-17.md`](./【技术协议】AI游戏创作Agent%20Runtime交互合同V1-2026-08-17.md) +> 证据来源:[`【设计依据】AI游戏创作Agent Runtime交互边界证据与决策附录-2026-08-17.md`](./【设计依据】AI游戏创作Agent%20Runtime交互边界证据与决策附录-2026-08-17.md) + +## 0. 使用规则 + +每一行包含: + +```text +当前 source/入口 +→ 适用 IC 规则 +→ 当前差距 +→ 唯一迁移动作 +→ 阶段 +→ 完成证据 +``` + +状态值: + +- `baseline`:现状能力,尚未迁移; +- `isolate`:不满足 Public Contract,默认隔离; +- `adapt`:复用现有事实并通过 Shell Adapter 接入; +- `replace-consumer`:后端能力就绪后替换 Consumer; +- `remove-public`:P6 删除公开注册/调用; +- `decision`:需要显式产品决定,但不得改变 Contract。 + +--- + +## 1. 正式 ingress 与执行位置 + +| MX ID | 当前入口/source | 当前事实 | Contract | 目标动作 | 阶段 | 状态/证据 | +|---|---|---|---|---|---|---| +| MX-ING-001 | GUI Supervisor chat,`apps/ai-game-creator-shell/src/App.tsx` 与 `SupervisorChatOnlyView.tsx` | GUI 仍参与 start/steer、状态合并和输出同步 | `IC-ARC-002`、`IC-CMD-003`、`IC-CMD-004` | GUI 只提交 capability 中的 `submit_intent`,不选择 disposition | P5 | `replace-consumer`;GUI 调用图无 Runtime primitive | +| MX-ING-002 | 普通 Agent chat,`apps/ai-game-creator-shell/src/App.tsx` | user/assistant 直接 append,并调用内部 Agent 能力 | `IC-CMD-010`、`IC-CONV-010`、`IC-MIG-005` | P0 归类;正式路径在 P3 接 Shell、开发路径在 P3 隔离;P5 只清理旧 Consumer 分支 | P0/P3/P5 | 全调用图、ingress cutover 与 UI 清理 | +| MX-ING-003 | Tauri commands,`apps/ai-game-creator-shell/src-tauri/src/commands.rs` | 暴露旧 Runtime 和 conversation write wrapper | `IC-OWNER-001`、`IC-CMD-010`、`IC-MIG-005` | P3 先转发同一 Shell endpoint;旧注册 P6 删除 | P3/P6 | transport fixture + invoke handler 静态检查 | +| MX-ING-004 | CLI commands,`apps/ai-game-creator-shell/src-tauri/src/cli.rs` | `AgentSteer` 等路径直接调用 Runtime primitive;CLI 可启动受限 Runner | `IC-CMD-001`、`IC-CMD-010`、`IC-MIG-005` | P3 先收口为 Shell transport;P5 再迁 Public CLI read/UX;保留无 GUI 启动 Runner 能力 | P3/P5 | CLI golden replay;无直接 start/steer/resume | +| MX-ING-005 | `--swarm-chat`,`cli.rs` 与 `swarm_cli/turn_dispatch.rs` | 读取专业 Agent 状态并直接 dispatch/append | `IC-ARC-005`、`IC-CMD-010`、`IC-MIG-004`、`IC-MIG-005` | P3 先让正式写走 Shell 或禁用;P5 按 `FD-001` 选择 Public/Developer read 呈现 | P3/P5 | Shell writer fixture;`decision`;Public/Developer DTO 零交叉 | +| MX-ING-006 | Runner `runtime.*` RPC,`src-tauri/src/runner/dispatch.rs` | 已有 resume/steer/cancel/pause/compact 等内部 RPC,request cache 仅内存 | `IC-CMD-001`、`IC-CMD-010`、`IC-IDEMP-001~005` | 仅作为 Shell 内部实现/委托 Shell;不得把 cache 当 durable read-back | P1/P3/P6 | crash 后同 requestId read-back + dispatch 调用图 | +| MX-ING-007 | 进程内测试 transport | 可绕过 External Runner 直接调用实现 | `IC-OWNER-001`、`IC-CMD-010` | 复用同一 Shell handler,并在任何 Shell/Runtime 写前取得同一 OS owner lock;per-Agent lock 不等价 | P1/P3 | 同 fixture 跨 Runner/进程内 replay | +| MX-ING-008 | Runtime 内部 wake/recovery | timer/lane/schedule/owner recovery 不属于用户意图;Runner known roots 当前仅在内存 | `IC-CMD-009`、`IC-ARC-004`、`IC-MIG-006` | 保持内部 recovery intent,不导出为 Public resume;P4 建跨重启候选项目发现 | P4/P6 | 静态 Public DTO 检查、重启 discovery 与恢复测试 | + +--- + +## 2. Read model 与 Consumer 决策 + +| MX ID | 当前 read/source | 当前事实 | Contract | 目标动作 | 阶段 | 状态/证据 | +|---|---|---|---|---|---|---| +| MX-READ-001 | manifest/Session catalog/Runtime state/task/Shell binding 读取 | GUI/CLI 分别解释 status/phase;缺少完整 project/session/binding witness | `IC-READ-001`、`IC-READ-004`、`IC-ARC-002` | Shell 按完整 source dependency matrix 形成 valid/failClosed/read-error,稳定投影 status/stage/waitingOn/nextStep | P1/P2/P5 | manifest/catalog/binding/journal、bootstrap、active-task 缺失、损坏、跨 Consumer Snapshot fixture | +| MX-READ-002 | pending action、user-input、tool confirmation sidecar | 当前由不同 UI/CLI 分流;无 open interaction 可缺失 | `IC-READ-004`、`IC-CAP-003`、`IC-INT-001`~`IC-INT-007` | P2 只读物化稳定 Interaction,并生成与 interactionId/revision 一致的 response capability;required sidecar 缺失/损坏则 fail-closed,P3 接管 answer/approve | P2/P3 | identity/revision/audience/capability/required-source fixture | +| MX-READ-003 | response stream | 是 optional Runtime final-reply 实时/恢复辅助,写错误可能被忽略 | `IC-READ-004`、`IC-CONV-005`、`IC-IDEMP-004` | 只作为短期 source evidence;不能单独证明 committed;完成证明依赖它时损坏/缺失 fail-closed | P0/P2/P3 | optional、写失败、截断、ready→committed fixture | +| MX-READ-004 | GUI Runtime state/event merge | Consumer 自行拼接多个 source | `IC-READ-001`、`IC-EVT-001` | P5 删除 normalize/merge 决策,只渲染 Snapshot | P5 | 前端类型/调用图检查 | +| MX-READ-005 | Tauri best-effort update event | 不提供按 project/view scope 可靠补读历史 | `IC-EVT-001`~`IC-EVT-003` | 替换为按 `(projectId, view)` 路由的 snapshot-first subscription;V1 不补历史 event,缺口/重连均重读完整 Snapshot | P2 | 首次 revision1/sequence0、Public/Developer 隔离、重复/乱序/缺口/重连 fixture | +| MX-READ-006 | Developer Agent panel | 可读私有 Agent 状态并直接操作 | `IC-ARC-005`、`IC-READ-003`、`IC-MIG-005` | P2 建独立 Developer DTO;正式 Supervisor 写在 P3 走五命令,Developer-local 写在 P3 隔离;P5 只清理旧 UI 分支 | P2/P3/P5 | 未授权拒绝、ingress cutover、Public 字段零泄漏 | +| MX-READ-007 | Preview/resource/session 管理面 | 独立现役合同 | `IC-ARC-002`、`IC-MIG-003` | 保持 sibling contract,不从 Snapshot nextStep 重造 | P5/P6 | 调用图证明未误删 | +| MX-READ-008 | command capability 投影 | 当前 Consumer 由 status/phase 自行判断按钮 | `IC-CAP-001~003`、`IC-READ-004` | 按 Contract issuance matrix 从完整 witness 必签/撤销 submit、interaction、cancel、resume 与 Developer reconcile capability | P2/P3 | 每类 capability 正反状态、witness 漂移、Public/Developer audience fixture | + +--- + +## 3. 身份、Session 与 owner + +| MX ID | 当前 source | 当前事实 | Contract | 目标动作 | 阶段 | 状态/证据 | +|---|---|---|---|---|---|---| +| MX-ID-001 | 项目 manifest/路径 | manifest 有 project identity;transport 大量使用绝对路径定位,尚无 projectId 反向 root registry | `IC-ID-001` | Public 只传 projectId;宿主 resolver 产出并复核 `TrustedProjectContext`,locator 留在受信任边界 | P1/P2/P3 | path-free schema + resolver/subscription mismatch fixture | +| MX-ID-002 | Session catalog,`project/conversation.rs` | 每 Agent 一份 catalog;无独立 revision;live task 禁止变更 | `IC-ID-002`、`IC-ID-003` | 对 Project Supervisor catalog 计算 opaque digest;不写回、不扩权 | P0/P2/P3 | live-task 与跨 Agent Session fixture | +| MX-ID-003 | collaborator/child history | 各自具有 agentId/sessionId/runId,但无稳定公开协作实体 | `IC-ID-003` | 首次 binding durable 分配 collaborationId;retry/successor 保持 ID,fallback 被 Runtime binding 替换;无 parent run 的 fallback 绑定 project/session/manifest digest/group;不使用 Supervisor 当前 Session 重新归属 | P2/P3 | parentRun multi-child、retry lineage、fallback replacement、交叉 mutation fixture | +| MX-OWNER-001 | `.agent/runtime/execution-owner.lock` | OS 排他锁是真正 owner;现仅 Runner production path 获取 | `IC-OWNER-001`、`IC-OWNER-002` | 直接复用;进程内 Shell 也必须在写前取得同一实现,不新增 generation/lease | P0/P1/P4 | 双 Runner、进程内冲突、drain、失锁测试 | +| MX-OWNER-002 | `.agent/project.lock` | create-new 文件锁按 PID/时间/mtime reclaim,不是 owner | `IC-OWNER-002` | 不可作为 Shell protocol lock;保留其现役业务用途 | P1 | stale reclaim 与 Shell lock 分离 fixture | +| MX-OWNER-003 | `execution-owner.json` 与 bootId | 仅诊断/实例关联 | `IC-OWNER-001` | 保持私有诊断,不用于接管/CAS | P0/P4 | 时间/mtime/诊断冲突 negative fixture | +| MX-OWNER-004 | GUI-owner watchdog | GUI 启动 Runner 时的生命周期门禁 | `IC-OWNER-001` | 保留 GUI-owner 路径;不扩张为 CLI control lease | P4 | GUI-owner 丢失与 drain fixture | +| MX-OWNER-005 | CLI `--config-dir` Runner | 当前可无 GUI 启动/连接受限 Runner | `IC-OWNER-001` | 保留现有终端会话能力;不承诺常驻 | P4/P5 | CLI Runner 回归 | + +--- + +## 4. Command 与现有 Runtime identity + +| MX ID | Public command | 现有内部能力/source | Contract | Adapter 要求 | 阶段 | 证据 | +|---|---|---|---|---|---|---| +| MX-CMD-001 | `submit_intent` DirectReply | CLI Reply/Execute kernel、conversation append | `IC-CMD-003`~`IC-CMD-005`、`IC-CONV-004` | 预分配 user/assistant messageId,先 user commit 再 reply | P3 | crash-point + same request replay | +| MX-CMD-002 | `submit_intent` Start | Runtime start/pending/task/status | `IC-CMD-004`、`IC-CMD-005` | 绑定 input envelope、现有 task/run/status identity | P3 | user→status→queued crash fixture | +| MX-CMD-003 | `submit_intent` Steer | 现有 V1.13 steer ledger | `IC-CMD-004`、`IC-CMD-005` | prepared 时绑定 steerId/cursor;不复制 steer 生命周期 | P3 | same-run、重复和 deferred fixture | +| MX-CMD-004 | `answer` | user-input sidecar/answer primitive | `IC-CMD-006`、`IC-INT-001~007` | 物化稳定 interaction,按 response/revision 解决 | P2/P3 | option/freeform/stale/replay fixture | +| MX-CMD-005 | `approve` | tool/policy confirm 与 reject primitive | `IC-CMD-007`、`IC-INT-001~007` | audience/policy/target set/artifact binding 锁内复核 | P2/P3 | approve/reject/requestChanges matrix | +| MX-CMD-006 | `cancel` | Runtime cancel primitive | `IC-CMD-008` | 精确 Session/Run/revision;唯一 cancel operation;不伪造终态 | P3 | cancel revision/state matrix | +| MX-CMD-007 | `resume` ContinueRun | paused Run resume | `IC-CMD-009` | 同 Run + expected revision | P3 | paused/running/waiting/finalizing negative fixture | +| MX-CMD-008 | `resume` RetryTerminalRun | terminal retry/successor lineage | `IC-CMD-009` | 唯一 successor runId;保存 predecessor/source identity;绑定 terminal revision 与 retry policy digest | P3 | policy drift、concurrent retry + crash fixture | +| MX-CMD-009 | `resume` ReconcileRun | 受信任 reconciliation | `IC-CMD-009`、`IC-IDEMP-004` | 只读/修复已知事实,不重放未知副作用 | P3/P4 | Developer capability + provider/tool count | +| MX-CMD-010 | Goal replacement | 现有 replacement primitive | `IC-CMD-004` | 仅显式 Goal management operation;不由普通 execute intent 触发 | P3 | frozen Goal Contract negative fixture | + +--- + +## 5. Conversation source 与 writer cutover + +| MX ID | Source/writer | 当前事实 | Contract | 目标动作 | 阶段 | 状态/证据 | +|---|---|---|---|---|---|---| +| MX-CONV-001 | Session user message | 现有 conversation 正文 source | `IC-CONV-002`、`IC-CONV-004` | 复用正文;Public index 只保存 source metadata | P3 | source digest/read-back fixture | +| MX-CONV-002 | DirectReply | `swarm_cli`/GUI 可直接 append user+assistant | `IC-CONV-004`、`IC-CONV-010` | Shell 接管稳定 identity 和写入顺序 | P3/P5 | 零重复 user/assistant | +| MX-CONV-003 | RuntimeFinalReply | finalization + response stream + conversation | `IC-CONV-005` | 保存三层 identity binding;长期正文从 conversation 回读 | P3 | sidecar 清理后历史回读 | +| MX-CONV-004 | 根 Supervisor start/terminal status | 稳定 messageId 但正文写 project conversation | `IC-CONV-006` | 以 task/run correlation 显式绑定 Supervisor Session | P0/P3 | correlation 缺失/冲突 fixture | +| MX-CONV-005 | 专业 Agent terminal status | 写其 Agent Session conversation | `IC-CONV-006` | 按该 agent/session/run 回读,不重归属 | P0/P3 | session scope fixture | +| MX-CONV-006 | receipt/isolated join status | 当前不写 Session status message | `IC-CONV-006` | 默认不进入 Public Conversation | P0 | `isolate` negative fixture | +| MX-CONV-007 | 普通 Runtime event | eventId 依赖 pid/时间/进程计数 | `IC-CONV-007` | V1 默认隔离 | P0 | `isolate`;call site inventory | +| MX-CONV-008 | action-identity event | 部分 event 可按 action identity 幂等 | `IC-CONV-007` | 仅在规范 reader/digest/scope 全闭合后显式登记 | P0/P1/P3 | 默认 `isolate`;event replay fixture | +| MX-CONV-009 | recent-events reader | 静默跳过坏行,只返回最近 20 条 | `IC-CONV-007`、`IC-CONV-009` | 不作为 Public source reader;若接 event 必须补新 reader | P0/P1 | 损坏/截断/定位 fixture | +| MX-CONV-010 | GUI final autosave | `response-stream → game-chat-final-reply:* → autosave` | `IC-CONV-005`、`IC-CONV-010` | P3 adapter 启用前停止正式写入;P5 只删除旧消费/展示分支 | P3/P5 | cutover watermark 后零派生 writer;GUI 调用图清理 | +| MX-CONV-011 | GUI event autosave | `Runtime event → game-chat-runtime-event:* → project conversation` | `IC-CONV-007`、`IC-CONV-010` | P3 adapter 启用前停止正式写入并隔离历史跨 scope 项;P5 清理旧 UI 分支 | P0/P3/P5 | source scope inventory + cutover 后零派生 writer | +| MX-CONV-012 | 普通 Agent chat append | `App.tsx` user/assistant 可无 messageId append | `IC-CONV-010` | P3 前将正式 Supervisor 接 Shell、Developer/local 显式隔离;P5 只清理旧 Consumer 分支 | P0/P3/P5 | writer 三选一清单 + cutover fixture | +| MX-CONV-013 | Developer panel append | Developer user history 直接写 | `IC-ARC-005`、`IC-CONV-010` | P3 前标记 Developer-local 且永不进入 Public,或接正式 Shell;P5 清理旧调用面 | P0/P3/P5 | DTO/调用面隔离 + cutover fixture | +| MX-CONV-014 | project pending-message autosave | 项目级 conversation writer | `IC-CONV-010` | P3 adapter 启用前接 stable source binding 或停止;P5 只删除旧 Consumer 分支 | P0/P3/P5 | writer cutover fixture | +| MX-CONV-015 | Public Conversation cursor | 当前无统一永久 source index | `IC-CONV-002`、`IC-CONV-008`、`IC-CONV-009` | P3 建无正文 index、origin/tail/cursor chain | P3 | 分页、空洞、损坏、全量补读 | + +--- + +## 6. Public / Developer 字段边界 + +| MX ID | 数据 | 当前风险 | Contract | 动作 | 阶段 | 证据 | +|---|---|---|---|---|---|---| +| MX-DATA-001 | project path / LocalConversationResult.path | GUI/CLI 可读本地路径 | `IC-ID-001`、`IC-READ-002` | Public DTO 零 path;local transport 单独返回 | P2/P5/P6 | schema/static check | +| MX-DATA-002 | Provider、tool、observation | Developer/runtime records 含私有原文 | `IC-READ-002`、`IC-ERR-003` | Public 严格白名单;Developer 仍脱敏有界 | P2 | sensitive fixture | +| MX-DATA-003 | dynamic child identity | GUI 可聚合专业/child Runtime | `IC-ID-003`、`IC-READ-002` | Public Snapshot/event/error/capability 只显示 durable collaborationId/组摘要;真实 child agent/session/parentRun/run/delegation identity 只留 private binding | P2/P5 | parentRun multi-child、retry、fallback replacement、Public zero-leak、权限 fixture | +| MX-DATA-004 | interaction private prompt/policy | sidecar 可能含原始模型内容 | `IC-INT-005`、`IC-ERR-003` | 生成独立 Public presentation;不安全则 Developer/reconciliation | P2 | redaction fixture | +| MX-DATA-005 | finalization/provider identity | 恢复和调试需要,正式 UI 不需要 | `IC-CONV-005`、`IC-READ-002` | 保留 private binding,Public message 仅 provenance allowlist | P3 | Public schema zero-leak | + +--- + +## 7. P6 删除清单 + +| MX ID | 删除范围 | 保留范围 | Contract | 完成证据 | +|---|---|---|---|---| +| MX-DEL-001 | 正式 transport 旧 start/steer/confirm/reject/answer/cancel/retry/resume/schedule/read 注册 | Runtime 内部 primitive | `IC-MIG-003` | handler/route 静态检查 | +| MX-DEL-002 | GUI/CLI 旧生命周期判断和 fallback | Public Consumer + Developer read | `IC-ARC-002`、`IC-MIG-002` | Consumer 调用图 | +| MX-DEL-003 | GUI Runtime output 派生 autosave | 原 conversation/finalization/event source | `IC-CONV-010` | writer cutover + 零 duplicate | +| MX-DEL-004 | Public DTO 的 path/finalization/provider/private fields | 受信任本地/Developer DTO | `IC-READ-002`、`IC-READ-003` | schema diff | +| MX-DEL-005 | Public scope 无稳定 messageId append | 明确 Developer/local history | `IC-CONV-010` | 所有 append caller 已分类 | +| MX-DEL-006 | migration unknown-command fallback | 内部回归测试 | `IC-MIG-002`、`IC-MIG-003` | transport fixture | + +--- + +## 8. 当前冻结前缺口 + +| ID | 缺口 | 性质 | 阻塞阶段 | +|---|---|---|---| +| FD-001 | `--swarm-chat` 是普通 Public Supervisor CLI 还是显式 Developer CLI | 产品兼容决策 | P5 产品绑定/呈现;不阻塞 Contract 核心冻结 | +| GAP-001 | 全部 legacy Runtime ingress 的实际写入进程调用图尚未形成正式 artifact | P0 evidence | P3 | +| GAP-002 | 全部 conversation append writer 的接管/隔离/禁用归类尚未闭合 | P0 evidence | P3/P5 | +| GAP-003 | event type/call site identity inventory 尚未形成正式 artifact | P0 evidence | PublicEvent 接入;默认隔离不受阻 | +| GAP-004 | 按 eventId 定位、报告坏行/截断、校验 digest 的 reader 尚不存在 | implementation gap | PublicEvent 接入;默认隔离不受阻 | +| GAP-005 | Rust→TypeScript strict schema/golden fixture 尚未实现;冻结前只定义规范与向量 | P1 implementation | P2/P3 | +| GAP-006 | `projectId → TrustedProjectContext` 的受信任宿主 resolver 尚未实现 | P1 implementation | P2/P3;Public DTO 始终保持无路径 | +| GAP-007 | 现有 `.agent/project.lock` 具有 stale reclaim,不能当 Shell protocol lock | P1 implementation boundary | P1;须与 execution owner 下串行分离 | +| GAP-008 | RFC 8785 canonicalization 尚无单一复用实现 | P1 implementation | P1;checksum/fingerprint/hash 不可各自序列化 | +| GAP-009 | Shell record 尚无唯一 append order authority;不能由多份 sidecar 自行分配 ledgerVersion | P1 implementation | P1;建立专用 ledger,sidecar/index 只能派生 | +| GAP-010 | Projection reader 尚无 witness、一致 observation、source absence/corruption matrix、fail-closed publication | P2 implementation | P2;不能直接公开现有聚合 read | +| GAP-011 | Runner 的 known roots 与 request dedupe 都是内存态 | P3/P4 implementation | P3 durable read-back;P4 restart discovery | +| GAP-012 | Snapshot subscription 尚无按 `(projectId, view)` 路由、durable sequence 与原子 initial Snapshot | P2 implementation | P2;V1 使用 snapshot-first/no-backlog,不能复用全局 best-effort event | +| GAP-013 | collaborator/child 到 durable collaborationId 的 binding/lineage 尚不存在 | P2 implementation | P2;Public 不得临时以 agentId/组名拼接 identity | + +这些缺口不得被解释为 Contract 规则未决定:除 `FD-001` 外,现状不满足即按 Contract 默认隔离或失败关闭。