Skip to content

feat(runtime):增加plan/build模式 #511

@phantom5099

Description

@phantom5099

Summary

在现有主链路基础上,引入 会话级 plan / build 双模式,并把“当前计划”提升为 session 持久化的一等对象。plan 模式负责调研、分析、提问、收敛方案;build 模式负责基于当前执行计划完成实现。两种模式共用同一套 runtime 主循环,工具能力统一经过 internal/tools 管理,verify 只属于执行阶段。

本方案的最终决策:

  • plan / buildruntime/session 的正式模式
  • PlanSpec 是唯一真相源
  • PlanArtifact 保存计划元信息、PlanSpec 与派生 SummaryView
  • 模型在生成计划时同步产出 plan_spec + summary_candidate
  • runtime 对 summary_candidate 做轻量结构校验,失败时回退为本地生成的 SummaryView
  • plan / build 默认都只注入 SummaryView
  • 计划状态、审批状态、执行状态集中在 runtime/session

Key Changes

1. Session 与计划模型

internal/session 中新增模式与计划状态,并进行 schema 升级。

新增字段建议:

  • AgentMode string
    注释:当前会话的工作模式,决定 runtime 采用规划还是执行语义,并直接影响工具可见性与收尾逻辑。
    值:plan | build

  • CurrentPlan *PlanArtifact
    注释:当前会话唯一有效的计划对象;执行阶段只围绕它推进,规划阶段生成或重写它。
    为空表示当前还没有正式计划,需要在 plan 结束或 build_bootstrap 阶段补齐。

PlanArtifact 建议结构:

  • ID string
    注释:当前计划的稳定标识,用于区分一次正式计划产出与后续重写结果。

  • Revision int
    注释:当前计划的修订版本号;只有发生正式计划重写时递增,普通追问或讨论不递增。

  • Status string
    注释:当前计划的生命周期状态,用于约束是否允许进入执行阶段,以及是否需要重新对齐。
    值:draft | approved | implicit | executing | completed | superseded

  • Spec PlanSpec
    注释:当前计划的唯一真相源;所有正文视图、摘要视图、执行注入内容都从这里派生,不从正文反向提取。

  • Summary SummaryView
    注释:由 Spec 派生出的默认上下文摘要,适用于 planbuild 两种模式;它是结构化投影,不是独立真相源。
    约束:仅在计划首次保存、正式重写、关键 Todo 变化时刷新,不随每轮对话重新生成。

  • CreatedAt
    注释:该计划首次成稿时间,用于计划审阅、调试和状态追踪。

  • UpdatedAt
    注释:该计划最近一次正式变更时间,用于判断是否发生过重写、审批后是否又被修改。

PlanSpec 作为唯一真相源,建议结构:

  • Goal string
    注释:当前任务的目标定义;用于约束执行边界,并作为摘要与正文的核心起点。

  • Steps []string
    注释:执行路线的关键步骤列表;用于表达实施顺序与主要落点。

  • Constraints []string
    注释:实现过程中必须遵守的边界、限制和不变量;执行偏离时优先受此约束。

  • Verify []string
    注释:执行完成后的验证要求或验收标准;用于生成执行摘要并驱动 verify 阶段关注点。

  • Todos []Todo
    注释:结构化待办项;用于把计划中的步骤映射为更细粒度的执行动作和进度状态。
    约束:每个 todo 必须有稳定 ID,供 SummaryView.ActiveTodoIDs 引用。

  • OpenQuestions []string
    注释:当前尚未解决的问题列表;若存在阻塞写操作的关键问题,则不能结束 bootstrap 或进入正式执行。

SummaryView 建议结构:

  • Goal string
    注释:当前计划目标的压缩表达,供 plan/build 常规上下文使用。

  • KeySteps []string
    注释:当前最关键的步骤摘要,不要求覆盖全部 Steps,但要覆盖当前主线。

  • Constraints []string
    注释:当前执行必须牢记的关键约束摘要。

  • Verify []string
    注释:当前计划的核心验收要求摘要。

  • ActiveTodoIDs []string
    注释:当前摘要引用的 todo ID 集合,必须来自 PlanSpec.Todos

约束:

  • 只维护单个当前计划
  • PlanSpec 是唯一正式计划数据
  • 不以正文作为完整计划真相源
  • 不从正文反向提取字段
  • SummaryView 是从 PlanSpec 派生出的默认上下文摘要,不是第二真相源
  • TaskState 继续保留,但执行阶段的计划锚点是 CurrentPlan.Spec

迁移策略:

  • 提升 SQLite schema version
  • sessions 表新增 agent_modecurrent_plan_json
  • 如选择持久化摘要缓存,则同时新增 current_plan_summary_json
  • agent_mode 默认值为 build
  • current_plan_json 默认值为空字符串,读取时解释为 nil
  • current_plan_summary_json 默认值为空字符串,读取时可按需重建

兼容规则:

  • 旧会话加载后默认处于 build
  • 旧会话没有 CurrentPlan 是合法状态
  • 第一次直接执行时由 runtime 进入 bootstrap 阶段补齐最小计划

2. Tool 边界与模式隔离

采用 Manager 动态过滤 + 执行期硬阻断。

internal/tools/manager.go

  • 扩展 SpecListInput,增加 Mode string
  • ListAvailableSpecs(...) 根据 mode 过滤工具 spec
  • Registry 保持全量注册,不拆多套 registry

planbuild_bootstrap 默认仅开放明确只读工具,例如:

  • 文件读取 / 搜索类
  • 只读记忆查询类
  • 必要的只读网页抓取类

默认禁用:

  • 文件写入 / 编辑工具
  • bash
  • 会修改任务状态的工具
  • 记忆写入 / 删除
  • 全部 MCP 工具,除非未来有明确只读标注机制

执行期保护要求:

  • 当当前阶段不允许写操作且命中写类工具时,直接返回结构化拒绝错误
  • 不能只依赖 spec 不可见,必须防止伪造 tool call 绕过
  • 任何辅助执行能力都必须通过 runtime -> tools 的统一边界,不能直接写 session 计划状态

3. Runtime 主循环与模式行为

保留统一主循环,不拆第二套 runtime。运行时按行为阶段处理:

  • plan
  • build_bootstrap
  • build_execute

plan 阶段行为:

  • 允许读工具调用
  • 允许澄清问题、方案对比、补充调研
  • 不允许任何写操作
  • 不以“无 tool call”作为完成判定
  • 只有当模型输出形成有效计划结果时,才执行计划收尾:
    • 解析输出为 PlanSpec
    • 读取同轮返回的 summary_candidate
    • summary_candidate 做轻量结构校验
    • 校验通过则采用该摘要,否则由 runtime 基于 PlanSpec 生成规范化 SummaryView
    • 写回 CurrentPlan
    • Status = draft

build 阶段行为:

  • 正式执行开始后,状态切到 executing
  • 成功完成后,状态切到 completed
  • 执行阶段继续沿用现有 verify / acceptance 流程

最小 PlanSpec 校验要求:

  • Goal 非空
  • Steps 至少 1 条
  • Verify 至少 1 条
  • Todos 至少包含首批执行动作
  • OpenQuestions 中不存在阻塞写操作的关键未决问题

4. 计划视图、摘要生成与上下文控制

完整计划是结构化持久化对象,不是每轮上下文负担。

渲染策略:

  • RenderPlanContent(spec):渲染完整正文视图,给用户阅读
  • BuildSummaryView(spec):根据 PlanSpec 生成规范化 SummaryView
  • 模型在输出 PlanSpec 时可同时返回 summary_candidate

SummaryView 生成规则:

  • 优先由模型在生成 PlanSpec 的同时输出结构化 summary_candidate
  • runtime 对 summary_candidate 只做轻量结构校验
  • 若候选摘要缺失或校验失败,则回退为 BuildSummaryView(spec) 的规范化结果
  • 最终持久化与注入的 SummaryView 基于 PlanSpec
  • 不额外为了生成摘要再发起一次模型调用

summary_candidate 输出形状要求:

  • goal string
  • key_steps []string
  • constraints []string
  • verify []string
  • active_todo_ids []string

约束:

  • active_todo_ids 必须引用当前 PlanSpec.Todos 中的稳定 todo ID
  • key_stepsconstraintsverify 使用规范化短句列表
  • 当前阶段不引入 step_refs / constraint_refs 这类重型 ID 系统

轻量结构校验规则:

  • 缺少必填字段,失败
  • goalkey_stepsverify 为空,失败
  • active_todo_ids 中存在不存在的 todo ID,失败
  • 其他字段不做复杂语义裁判
  • 一旦失败,不重试模型,直接回退为 BuildSummaryView(spec)

校验边界:

  • runtime 只负责结构完整性和 todo 引用合法性
  • 不承诺第一版覆盖复杂自然语言一致性问题
  • 不额外调用第二个大模型做摘要裁判

SummaryView 至少包含:

  • 当前目标
  • 当前关键步骤 / 待办
  • 关键约束
  • 验证要求
  • 当前活跃 todo 引用

注入策略:

  • plan 模式下:

    • 若当前无 CurrentPlan,不注入计划上下文
    • 若当前已有计划且只是继续讨论、补充分析、回答局部问题,默认注入 SummaryView
    • 若当前任务是重写计划、审阅完整计划或 SummaryView 不足以支持当前推理,则注入完整正文视图
  • build 模式下:

    • 常规执行请求默认只注入 SummaryView
    • 只有在以下情况才注入完整正文视图:
      • 新计划刚生成
      • 计划刚重写
      • 会话恢复后首次对齐
      • 用户要求查看完整计划
      • runtime 判断 SummaryView 不足以支撑当前任务

刷新策略:

  • 计划首次保存时生成 SummaryView
  • 正式重写计划时重新生成 SummaryView
  • 关键 Todo 状态变化时可刷新一次 SummaryView
  • 普通追问、普通澄清时不刷新 SummaryView

5. 计划稿更新规则

CurrentPlan 是正式计划对象,不是对话逐轮镜像。

更新规则:

  • 普通澄清、追问、利弊讨论,只进入消息历史,不改写 CurrentPlan
  • 只有出现实质性决策变化时,才重写 CurrentPlan
  • 用户明确要求“更新计划 / 重写计划 / 按新方向调整”时,重写 CurrentPlan
  • 每次正式重写计划时递增 Revision
  • 每次正式重写计划时同步刷新 SummaryView

实质性决策变化包括:

  • 目标变化
  • 方案路线变化
  • 关键边界或约束变化
  • 执行步骤结构变化
  • 验证标准变化

6. 审批与状态流转

审批语义进入正式状态机,而不是依赖口头约定。

状态流转规则:

  • 显式规划生成后:draft
  • 用户批准后:approved
  • 开始执行后:executing
  • 执行完成后:completed

执行约束:

  • approved 计划可直接进入执行
  • draft 计划不得自动进入正常执行
  • 执行过程中如果计划被重写,当前执行应中止并要求重新对齐

7. Prompt 组织方式

模式差异通过 overlay 管理,不维护两份独立大 prompt。

采用:

  • 一份共享基础系统提示
  • 一份 plan overlay
  • 一份 build overlay

共享基础提示负责:

  • 项目规则
  • 架构边界
  • 工具纪律
  • 通用行为约束

plan overlay 强调:

  • 只能分析、读取、调研、提问、输出结构化计划
  • 不允许执行改动
  • 结果要收敛为有效 PlanSpec
  • 可同时输出结构化 summary_candidate

build overlay 强调:

  • 必须基于当前执行计划推进
  • 若当前无计划,先通过只读 bootstrap 生成最小计划
  • 默认基于 SummaryView 执行,仅在必要时回看完整正文
  • 允许必要的小幅偏离,但必须说明原因
  • 需要维护执行进度并进入 verify

8. 模块边界约束

该特性的边界明确如下:

  • session 持有模式、计划、审批、版本等真相状态
  • runtime 决定当前处于规划、bootstrap、执行还是验证阶段
  • tools 是所有模型可调用能力的唯一入口,负责可见性和执行期保护
  • 任何辅助能力只能提供调研结果、候选结论或执行结果,不能直接改写 CurrentPlan、计划状态或跳过工具边界
  • verify 只属于执行阶段,规划阶段不承担代码验收职责
  • 对外展示的正文和摘要都属于 PlanSpec 的投影视图,不应反过来驱动计划真相状态

Test Plan

  • session schema 迁移后,旧会话可正常加载,新字段默认值正确
  • 旧会话默认 agent_mode=build,且 CurrentPlan=nil 合法
  • 若持久化 current_plan_summary_json,旧会话缺失该列时迁移能正确补齐默认值
  • plan 模式下 ListAvailableSpecs(...) 仅返回只读工具
  • plan 模式下伪造写工具调用会被执行期硬阻断
  • plan 模式输出无法形成有效 PlanSpec 时会被识别并返回错误
  • 模型可在输出 PlanSpec 时同时输出结构化 summary_candidate
  • summary_candidate 结构完整且 todo 引用合法时会被采用
  • summary_candidate 缺少必填字段、必填字段为空或 todo ID 非法时会回退为 runtime 规范化摘要
  • plan 在已有计划时默认注入 SummaryView,而不是完整正文
  • plan 在重写计划或 SummaryView 不足时会注入完整正文
  • 普通追问不会改写 CurrentPlan
  • 实质性计划变更会重写 CurrentPlan 并递增 Revision
  • BuildSummaryViewRenderPlanContent 都基于同一份 PlanSpec
  • 常规执行默认只注入 SummaryView,不会每轮注入完整正文
  • 满足特定条件时会重新注入完整正文
  • SummaryView 会在首次成稿、正式重写、关键 Todo 变化时刷新
  • draft 计划不能直接进入正常执行
  • 执行过程中计划被重写时会中止当前执行并要求重新对齐
  • 执行完成后会进入 verify,并最终标记为 completed
  • MCP 在 plan 模式默认不可见、不可执行

Assumptions

  • plan 模式默认不支持 MCP
  • 默认不把完整正文当作真相源持久化;正文与摘要都可从 PlanSpec 重建
  • SummaryView 是派生字段,可持久化为缓存,也可按需重建,但不作为第二真相源
  • 默认不落地 plan 文件
  • 默认不做计划历史版本列表
  • 默认不做 transcript 级记忆清洗

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions