文档:对齐 M1 开工前的四处口径,并把 PR 结构冻结进方案
Project CI / Repository checks (pull_request) Successful in 1m32s
Project CI / Frontend tests (pull_request) Successful in 2m59s
Project CI / Native shell tests (pull_request) Failing after 3m22s
Project CI / Backend tests (pull_request) Successful in 3m46s

第 19 节第 2 条改写:原文要求回归钉死「执行层拒绝」与「广告层仍放行」
两半,与第 4.3 节「allowlist 的作用是让它在广告层就消失」直接冲突,
且两节互相引用却结论相反。更正为:那段描述的是 M1 之前的现状不是目标态;
目标态两层都拒,回归第二半从「仍放行」翻为「不再出现」,纵深防御纪律保留。

第 23.8 节新增 M1 的 PR 结构与合入门禁:11 个 PR、依赖顺序与各自门禁。
PR 划分属工程流程契约,须团队可见——PR 描述不得引用个人工作稿,
原第 23.6 步骤五只有一句「未开始」,并行开工时无可引用的 DAG。
其中 M1C-0 与 M1C-1 拆开,因两者风险类别不同:前者改 master 已发布的
静态委派机制,后者是新增功能;合并会让「做游戏返工额度未被误放宽」
这条关键回归淹没在审批闭环 diff 里。M1C-2 拆 a/b,因失败模式无关。

第 23.6 步骤三订正:身份登记的代码已于 2026-08-13 合入,
原文仍写「代码落地属 M1」,进度过期。

第 23.1 订正:steer 资格判据在 goal_contract_root_steer_task_at
(steering.rs:747,判据 763 行),原文误记为同文件 714 行的
goal_contract_root_steer_replacement_run_id——行号对但函数名错。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-13 12:38:58 +00:00
parent 10af1fc377
commit 9605f31440
@@ -1602,7 +1602,7 @@ receipt 永远压过 stale pending:一旦该版本存在有效 receiptpendi
## 19. 安全不变量与构建验证边界
1. 不放松 `autonomous-game-build``user.input_request` 的现行禁等待防线;多轮策划只发生在 top-level standard plan run。
2. **2026-08-13 按 D11 二次拆写,取代 2026-08-12 按 D9 的拆写)** 做方案链路的工具边界分两层:**Supervisor 根 run** 以新可信 source `project-supervisor-plan` 承载入口,工具面按现役 `standard` deny-list 模型,其 Provider 不直接向用户提问,而是在认领策划子 Agent 的 `AGC_NEEDS_USER_INPUT_V1` 终态信封后,在自己的 runtime/session 上创建 `waiting-for-user-input` pending(复用 PR #165 中转链路,见第 1.1 节「D11 新拓扑」,不是 D9/D10 设想的「Runtime 直投」);**策划子 Agent**`agentId=project-planning`,由 Project Supervisor 通过 `agent.delegate` 静态委派,不再由 ready-task 调度器启动)的 action 工具广告与执行双门都必须是 exact allowlistMCP 为空。**`user.input_request` 在此拓扑下由执行层 Runtime 兜底拒绝,不是产品自律要求**——委派子 Agent 天然带 `parent_agent_id`/`parent_run_id``validate_user_input_action_owner``apps/ai-game-creator-shell/src-tauri/src/user_input.rs:367-394`)在落盘 pending 之前直接判定失败并拒绝。但**广告层仍可见**:`build_agent_runtime_native_function_tools``apps/ai-game-creator-shell/src-tauri/src/agent_native_tools.rs:279`)没有 `agent_id` 参数、无法按身份裁剪;`standard` profile 下 `tool_policy_snapshot.rs:144-147``apps/ai-game-creator-shell/src-tauri/src/agent/runtime_actions/tool_policy_snapshot.rs`)仍无条件把 `user.input_request` 列入 `auto_tools`,模型看得见、会去调用,只是调用必然失败并转成一次失败的 tool observation。回归用例须同时钉死「执行层拒绝」与「广告层仍放行」这两半,不能只测其中一半就当作已覆盖。原 D10「排除是产品约束的自律要求而非 Runtime 兜底」的表述在新拓扑下已失效,见第 2 节 D10 作废条目。
2. **2026-08-13 按 D11 二次拆写,取代 2026-08-12 按 D9 的拆写)** 做方案链路的工具边界分两层:**Supervisor 根 run** 以新可信 source `project-supervisor-plan` 承载入口,工具面按现役 `standard` deny-list 模型,其 Provider 不直接向用户提问,而是在认领策划子 Agent 的 `AGC_NEEDS_USER_INPUT_V1` 终态信封后,在自己的 runtime/session 上创建 `waiting-for-user-input` pending(复用 PR #165 中转链路,见第 1.1 节「D11 新拓扑」,不是 D9/D10 设想的「Runtime 直投」);**策划子 Agent**`agentId=project-planning`,由 Project Supervisor 通过 `agent.delegate` 静态委派,不再由 ready-task 调度器启动)的 action 工具广告与执行双门都必须是 exact allowlistMCP 为空。**`user.input_request` 在此拓扑下由执行层 Runtime 兜底拒绝,不是产品自律要求**——委派子 Agent 天然带 `parent_agent_id`/`parent_run_id``validate_user_input_action_owner``apps/ai-game-creator-shell/src-tauri/src/user_input.rs:367-394`)在落盘 pending 之前直接判定失败并拒绝。但**广告层仍可见**:`build_agent_runtime_native_function_tools``apps/ai-game-creator-shell/src-tauri/src/agent_native_tools.rs:279`)没有 `agent_id` 参数、无法按身份裁剪;`standard` profile 下 `tool_policy_snapshot.rs:144-147``apps/ai-game-creator-shell/src-tauri/src/agent/runtime_actions/tool_policy_snapshot.rs`)仍无条件把 `user.input_request` 列入 `auto_tools`,模型看得见、会去调用,只是调用必然失败并转成一次失败的 tool observation。**以上描述的是 M1 之前的现状,不是目标态**(2026-08-13 更正:原文把「广告层仍放行」写成了回归须钉死的一半,与第 4.3 节「allowlist 的作用是让它在广告层就消失」直接冲突,两节互相引用却结论相反)。**目标态是两层都拒**M1 的 exact allowlist 让 `user.input_request` 不再出现在策划子 Agent 的函数目录,执行层兜底继续保留。回归用例仍须同时钉死两半,只是第二半从「广告层仍放行」翻为**「广告层不再出现」**:① 策划子 Agent 的函数目录中不含 `user.input_request`;② 即便绕过广告层伪造一次调用,仍被 `validate_user_input_action_owner` 拒绝。不能只测其中一半就当作已覆盖——两层是纵深防御,将来若有重构把广告层泄漏带回来,执行层兜底必须仍然成立。原 D10「排除是产品约束的自律要求而非 Runtime 兜底」的表述在新拓扑下已失效,见第 2 节 D10 作废条目。
3. `.agent/planning/**``game/fast_gdd.md` 唯一写者是 Runtime;任何 Agent 通用写工具都不能触达。
4. GDD、receipt 追加不可变;index、session、Markdown 和 UI 只作有限投影,不能反写权威事实。
5. approve receipt 是构建信任根;Agent 文本、“已批准”状态缓存、Markdown 徽标或 UI 内存都无批准权。
@@ -1803,7 +1803,7 @@ D9 之后,root 是未变的 Project Supervisor,它在 `standard` 下天然
*裁决理由*:steer 替换会终止旧根、另起 replacement root run,而 D11 把策划的轮次预算挂在了委派链上——`clarification_round` 沿 `repair_of_delegation_id` 上溯推断,且每一跳都强制 `parent_run_id` 等于当前根 run(见第 4.1 节与第 23.5 节)。换根之后 `parent_run_id` 变了,旧链的 continuation 会被跨 run 隔离判据直接拒绝,**这条策划链路剩余的问询轮次全部作废**,用户已经回答过的内容也无法续接。这不是"交互未验证",是确定性的能力损失。
*实现要求(重要,不能靠副作用实现)*`goal_contract_root_steer_replacement_run_id``apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/steering.rs:763`)现在的资格判据`agent_runtime_supervisor_source_is_trusted(&task.source)`——**与 Goal Contract 创建权限、根控制面工具授权是同一个 matcher**。因此**不得**用「不把 `project-supervisor-plan` 加进该 matcher」来实现本裁决:那会连带否掉 Goal Contract,正好撞上本节尚未裁决的「plan source 与 Goal Contract 协议的关系」。本裁决必须实现为一条**独立于可信 source 判定的显式否决**:steer 入口识别出 plan 根 run 后直接拒绝并返回 typed 错误,无论该 source 是否在可信 matcher 内。回归用例须同时覆盖「plan source 在 matcher 内」与「不在 matcher 内」两种情形下 steer 均被拒。
*实现要求(重要,不能靠副作用实现)*steer 资格判据所在函数是 `goal_contract_root_steer_task_at``apps/ai-game-creator-shell/src-tauri/src/agent/runtime_protocol/steering.rs:747`,判据在 763 行;**2026-08-13 订正:原文误记为同文件 714 行的 `goal_contract_root_steer_replacement_run_id`,行号对但函数名错**),它现在用的`agent_runtime_supervisor_source_is_trusted(&task.source)`——**与 Goal Contract 创建权限、根控制面工具授权是同一个 matcher**。因此**不得**用「不把 `project-supervisor-plan` 加进该 matcher」来实现本裁决:那会连带否掉 Goal Contract,正好撞上本节尚未裁决的「plan source 与 Goal Contract 协议的关系」。本裁决必须实现为一条**独立于可信 source 判定的显式否决**:steer 入口识别出 plan 根 run 后直接拒绝并返回 typed 错误,无论该 source 是否在可信 matcher 内。回归用例须同时覆盖「plan source 在 matcher 内」与「不在 matcher 内」两种情形下 steer 均被拒。
*产品侧替代路径*:用户中途要改方向,走既有的两条——本轮问询里回答/自由填写来纠偏;或在 GDD 审批卡上 `revise` / `reject`。都不行时放弃本轮、重开一条 plan lineage(第 4.1 节的 `PLAN_ACTIVE_RUN_EXISTS` 约束保证同一时刻只有一条非终态 lineage)。
@@ -1875,7 +1875,7 @@ M0 完成不表示任何策划功能已上线。M1 的功能实现仍未开始
| --- | --- | --- |
| 一 | `M0A-3` 批一:D9 二次作废 / D10 作废 / D11 入表、第 1.1 节新拓扑段、第 19 节第 2 条与第 24 节第 8 条改写、decision-log 补记 | **已完成**(见第 1.1 节批一执行状态) |
| 二 | `WP1` + `WP2`:澄清轮次与返工深度拆分及其回归 | **已完成**(见第 23.5 节) |
| 三 | `project-planning` 的 agentCatalog 登记机制定稿 | **已完成**(机制冻结见第 3.1 节;代码落地属 M1 |
| 三 | `project-planning` 的 agentCatalog 登记 | **已完成**(机制冻结见第 3.1 节;**代码亦已落地**2026-08-13manifest、prompt bundle、runtime adapter、`prompt.rs` 角色合成分支及四处 needs_change 全部合入 |
| 四 | `M0A-3` 批二:拓扑与工具面部分 | **已完成**2026-08-13),拆解见下 |
| 四之余 | schema 与 golden vector 收口 | **已完成**2026-08-13),拆解见下 |
| 五 | M1 本体:策划闭环功能实现 | 未开始;合入门见下 |
@@ -1948,6 +1948,30 @@ M0 完成不表示任何策划功能已上线。M1 的功能实现仍未开始
- 本裁决改的是 master 已发布的静态委派机制,须在 `decision-log.md` 补 dated 记录,写明 `WP1` 的 depth≤1 结论未被推翻。
- 回归必须覆盖:用户修订跳不增 `depth` 也不重置 `round`;连续多次修订均可通过;做游戏链路的返工仍在 `depth=1` 被拒;无该变体的历史记录分类行为不变;32 跳边界仍 fail closed。
### 23.8 M1 的 PR 结构与合入门禁(2026-08-13
第 23.6 节步骤五原本只有一句「未开始」。M1 一旦并行开工,PR 划分与依赖顺序就是**工程流程契约**——它决定谁能先合、谁阻塞谁、每个 PR 的回滚边界在哪,属于必须团队可见的内容,不能只存在于个人工作稿里(PR 描述也不允许引用工作稿)。故在此冻结结构;每个 PR 的逐项做什么与逐点复核清单不在本节范围。
| PR | 主题 | 依赖 | 合入门禁 |
| --- | --- | --- | --- |
| `M1A-1` | source 常量 `project-supervisor-plan` + 进可信 matcher + steer 独立否决 | — | 全部可信 source 消费点逐点复核结论进 PR 描述;steer 在「plan source 在 matcher 内」与「不在」两种构造下均被拒 |
| `M1A-2` | 两层工具面 + `project-planning` 角色 brief | `M1A-1` | 两层工具面快照;`user.input_request` 在广告层不出现且执行层仍拒(第 19 节第 2 条两半) |
| `M1B-1` | `.agent/planning/` 存储层、strict schema、typed 指纹、版本链;含 `.agent/planning/**` 只挡写判据 | `M1A-2` | **第 9.1 节 golden vector 逐字节相等且指纹相等**(先于其它测试);create-only 与等前缀不可变 |
| `M1B-2` | `plan.submit_gdd` 原生工具与提交点 | `M1B-1` | 全部拒绝分支;提交点前后强杀恢复;同 submissionId replay 不产生 vN+1 |
| `M1C-0` | 新增 `StaticDelegateContractStatus::UserRevisionRequested` 与分类分支 | `M1A-1` | **本 PR 无写入方、是惰性路径,行为零变化**;做游戏链路返工仍在 `depth=1` 被拒;无该变体的历史记录分类不变 |
| `M1C-1` | `gdd-approval` pending、审批命令、receiptreceipt 写入上述 status | `M1B-2``M1C-0` | 第 13.0 节审批前置门:取证未通过时不出现审批卡;连续多次修订均可通过且 `repair_depth` 不变 |
| `M1C-2a` | Goal Contract 接线:turn 1 冻结、固定验收图、审批前置门取证 | `M1C-1` | turn 1 只能是一个 `agent.goal_contract``acceptanceNodes` 不接受自定义 |
| `M1C-2b` | 澄清中转接线、轮次派生、预算注入 | `M1C-2a` | 3 轮上限;continuation 重放幂等不增加轮次;答案绑定冲突被拒 |
| `M1D-1` | 前端 hydrate 与 GDD 审批卡 | `M1C-2b` | 前端只经 `hydrate_game_creator_plan_gdd_state` 读权威状态,不在页面侧合成批准事实 |
| `M1D-2` | 入口分流与阶段进度 | `M1D-1` | 「直接开建」跳过路径与现状零差异 |
| `M1E` | 端到端与故障注入收口 | `M1D-2` | 第 21 节测试矩阵中跨层场景 |
**拆包纪律**
- `M1C-0``M1C-1` 拆开的理由是**风险类别不同**:前者改的是 master 已发布的静态委派机制,后者是 M1 新增功能。合并成一个 PR 会让「做游戏链路返工额度未被误放宽」这条最关键的回归淹没在审批闭环的 diff 里。拆开后 `M1C-0` 全程不产生半状态——它没有写入方,`UserRevisionRequested` 要到 `M1C-1` 才被写出。
- `M1C-2` 拆成 a/b 的理由是两者失败模式无关:Goal Contract 是协议时序问题,澄清中转是身份派生与幂等问题。
- 顺序是依赖顺序不是优先级。`M1C-0` 只依赖 `M1A-1`,可与 `M1B-*` 并行。
## 24. 最终不变量摘要
- 策划与构建是两个不同 profile/source 的 run,由用户动作连接,不由 Agent 自行升级。