立项策划:落地 M1A-4,plan 根 run 只能委派策划子 Agent
Project CI / Repository checks (pull_request) Successful in 1m17s
Project CI / Frontend tests (pull_request) Successful in 2m52s
Project CI / Backend tests (pull_request) Successful in 3m53s
Project CI / Native shell tests (pull_request) Failing after 10m38s

补 M1A-2 的反方向。原先只做了「目标是 project-planning 时要求父是
plan 根」,反过来「父是 plan 根时目标必须是 project-planning」没做,
也没记为 deferred。后果是 plan 根 run 可以委派任意专业 Agent,而被
委派者拿常规 standard 工具面(能写文件、跑命令),第 24 节「策划全程
零构建」当时只由 Prompt 兜底。

执行层:observe_agent_runtime_agent_delegate 补对称分支;
observe_agent_runtime_agent_spawn_isolated 对 plan 根 run 一律拒——它是
第二条造子 Agent 的通道,只堵 delegate 等于留后门。两条共用 typed
kind=plan-root-child-target-unsupported。

强弱判据分工与 M1A-3 一致:弱判据从 task journal 读 source 决定是否
管辖,强判据 validate_project_supervisor_plan_root_binding_at 决定是否
合法,其 Err 永远落进拒绝分支。不可写成 is_ok() 当作「不是 plan 根」,
那会在 binding 损坏时放行任意子 Agent 创建。

上下文层:plan source 下不拼 supervisorIntro 与 $visualContract。不改
.md 内容,不新增 composition key。

三条有意保留的取舍已冻结进 decision-log,非待办:
$isolatedAgentTemplates 仍列出专业角色名(被执行层硬拒后的死文本,
上下文层收窄边界到此为止);task journal 读取失败对所有 source
fail closed(改成放行是新的 fail-open);plan 根 prompt 断言偏弱
(执行层是该场景唯一保障)。

同步方案 §22 证据表、§23.8 PR 表、§24 不变量,并订正 M1A-2 决策条里
含糊的「Supervisor 根 run 继续使用现役工具面」。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-14 05:02:46 +00:00
parent 09c7d7af8d
commit c22b929080
9 changed files with 562 additions and 27 deletions
@@ -1,8 +1,22 @@
# 决策记录
## 2026-08-14 M1A-4:plan 根 run 的子 Agent 创建面收窄,并冻结三条已知残留
- **补的是 `M1A-2` 的反方向。** `M1A-2` 只做了「目标是 `project-planning` → 要求父是 plan 根」这一半;反过来「父是 plan 根 → 目标必须是 `project-planning`」当时没做,也没记为 deferred。后果是 plan 根 run 可以委派任意专业 Agent,而被委派者拿的是常规 `standard` 工具面(能写文件、跑命令),第 24 节「策划全程零构建」当时只由 Prompt 兜底、不是机制保证。
- 落地:`observe_agent_runtime_agent_delegate` 补对称分支;`observe_agent_runtime_agent_spawn_isolated` 对 plan 根 run 一律拒绝(**它是第二条造子 Agent 的通道,只堵 delegate 等于留后门**)。两条通道共用 typed `kind=plan-root-child-target-unsupported`。Supervisor 根 run 的 prompt 在 plan source 下不拼 `supervisorIntro` 与 `$visualContract` 两段;不改 `.md` 内容、不新增 composition key(第 4.2 节)。
- **强弱判据分工与 `M1A-3` 一致,不得合并**:弱判据(`task.source` 自称是 plan,经 task journal 读取而非 binding)决定「本约束是否管辖这条 run」;强判据 `validate_project_supervisor_plan_root_binding_at` 决定「它是否合法」。强判据 `Err` **永远落进拒绝分支**,绝不可写成 `else if validate(..).is_ok() { 拒 }`——那会把「binding 损坏」误归为「不是 plan 根」,恰好在 durable 状态损坏时放行任意子 Agent 创建。
- 回归:`plan_root_delegate_rejects_non_planning_targets_but_keeps_planning_path`(含 `project-planning` 正向路径仍通过,避免把功能整个焊死)、`plan_root_delegate_and_spawn_isolated_fail_closed_when_binding_missing_or_corrupted`、`gui_root_delegate_and_spawn_isolated_are_unaffected_by_plan_root_symmetry`、`plan_root_supervisor_prompt_drops_intro_and_visual_contract_sections`、`non_plan_supervisor_prompt_stays_byte_identical_to_the_original_composition`。
**以下三条是经复核后有意保留的取舍,不是待办。后续 PR 不得在未重新裁决的情况下「顺手修掉」。**
1. **`$isolatedAgentTemplates` 仍会向 plan 根 run 列出全部专业角色名。** `art-director` / `design-foundation` / `art-asset-plan` / `code-prototype` 等名字来自 `$base`(`RUNTIME_PROMPT_RUNTIME_COMPOSITION` 的 `$isolatedAgentTemplates` 段,由 `GAME_CREATOR_AGENT_GROUP_DEFINITIONS` 运行时渲染),用途是广告 `agent.spawn_isolated` 的合法模板 id,**不在本次裁掉的两段之内**。裁掉它要动 `$base` 与隔离模板目录,波及全部 Agent。保留的依据是:`A2` 已对 plan 根 run 硬拒 `spawn_isolated`,该目录对 plan 根 run 是**死文本**,不构成可利用面。**结论:上下文层的收窄边界到此为止;「plan 根 run 的上下文里不出现其它 Agent 名」这一目标 M1 不成立,不要据此写验收句。**
2. **plan 之外的 source 多了一个失败面。** 两个 observe 函数新增的 task journal 读取,其 `Err` 分支位于弱判据之前,对 `project-supervisor-gui/cli/game-chat` 同样生效。正常状态不触发(仅 journal I/O 损坏等异常)。保留的依据是:读不到 task 就无法判断这条 run 是不是 plan 根,此时 fail closed 是正确取向;改成「读失败就放行」会引入一个新的 fail-open。**这是对第 19 节「做游戏链路逐字不变」的一处有意例外,仅限异常路径。**
3. **上下文层回归是弱断言。** `plan_root_supervisor_prompt_drops_intro_and_visual_contract_sections` 用「不含某几条独有短句」断言,不是对照组那种字节级 `assert_eq`。已实测非永真。已知漏报场景:若将来 `$visualContract` / `supervisorIntro` 被替换成措辞不同但仍暗示专业组扇出的新文本,这条不会报警。**执行层的 `A1`/`A2` 是该场景的唯一保障**——这也是本包把硬门排在裁段之前的原因。
- 关联文档:`docs/technical/【技术方案】立项策划Agent(Fast GDD)-2026-08-10.md` 第 4.3、22、23.8、24 节。
## 2026-08-13 M1A-2:planning 子 Agent 两层工具面与角色 brief 注入
- 落地范围:在 `M1A-1` 的 `project-supervisor-plan` source 基础上,收口两层工具面。Supervisor 根 run 继续使用 `standard` 的现役工具面;`project-planning` 只接受 `source=agent-delegate`、`profile=standard`、父 Agent 为 `project-supervisor` 的静态委派身份。
- 落地范围:在 `M1A-1` 的 `project-supervisor-plan` source 基础上,收口两层工具面。Supervisor 根 run 继续使用 `standard` 的现役工具面;`project-planning` 只接受 `source=agent-delegate`、`profile=standard`、父 Agent 为 `project-supervisor` 的静态委派身份。**(2026-08-14 订正:「Supervisor 根 run 继续使用现役工具面」这句读起来像决定,实际是要求丢失——本包工作项原本还要求「按 source 收窄 Supervisor 侧委派面:做方案链路只应产生一条指向 `project-planning` 的委派」,该半未实现也未记为 deferred。已由 `M1A-4` 补齐,见本文件同名条。)**
- planning 子 Agent 的当前 native action exact allowlist 只有 `file.read`、`file.list`;`update_agent_plan` / `respond_to_user` 是协议控制函数,不计入 action capability。MCP catalog 强制为空,`webSearchEnabled=false`,`collaborationPolicy=null`。`plan.submit_gdd` 刻意未注册、未广告、未执行,留给后续 `M1B-2`,因此本条不代表 GDD 提交、版本存储或审批闭环已完成。
- Prompt:Prompt Bundle 新增并登记 `project-planning` role brief,standard planning child 的初始请求与 repair/rebuild 请求均注入同一 brief;Supervisor 和其它 Agent 不注入该 section。brief 只描述 Fast GDD 澄清、终态 `AGC_NEEDS_USER_INPUT_V1`、三轮边界、平台事实与低幻觉约束,不授予任何写入、命令、MCP、预览、生成或审批能力。
- 纵深拒绝:广告层不再向 planning child 暴露 `user.input_request`;Provider parser、action batch/pending、并行只读、执行层和状态恢复均按原始 tool identity 再校验。伪造写入/命令/MCP、`project.search` 等映射为 `file.read` 的 alias、`user.input_request` 都 fail-closed;恢复旧快照不得把 planning 工具面扩回全量目录。委派子 Agent 原有 `validate_user_input_action_owner` 执行层拒绝继续保留。