算法可视化与交互学习平台
Planning & Execution:从下一步行动到完整任务Planning Agent: Decompose, Execute and Replan
No.17 用 state → action → observation 解决局部的‘下一步做什么’,No.18 把同一控制能力提升为完整任务闭环:先把模糊请求写成带验收证据的 Goal Contract,再拆成具有稳定 Step ID、输入输出契约和依赖关系的 DAG,经 Plan Validation 后调度串行与并行步骤,持续记录状态、预算和取消传播;遇到结构性失败时保留有效产物、替换失败子图并重新验收。核心浏览器实验在同一复杂任务、同一失败注入和同一预算下真实比较 ReAct only、Plan → Execute 与 Plan → Execute → Replan,并从 execution trace 计算七项指标。
No.17 决定下一步,No.18 对整个任务负责
No.17 的 ReAct 循环每次只回答一个局部问题:在当前 state 和 Observation 下,下一步应该调用哪个工具。复杂任务却还有另一组无法靠单步贪心自然解决的问题:哪些结果必须先拿到、哪些步骤可以同时进行、什么时候算真正完成、失败后哪些产物仍然有效,以及剩余预算是否足够继续。
No.18 的对象不是更长的聊天记录,而是一份可执行、可验证、可修改的任务计划。Planner 把 Goal 变成 DAG;Executor 只运行 ready steps;Runtime 维护状态、预算、取消和证据;Replanner 只在当前计划结构已不再可行时替换未完成子图。
| 层级 | 核心问题 | 可见产物 |
|---|---|---|
| No.17 · local control | 下一步 Action 是什么? | Action、Observation、局部 state transition |
| No.18 · global completion | 怎样以可验收方式完成整个任务? | Goal Contract、Plan DAG、Execution Ledger、Plan Diff、Acceptance Report |
Goal 不是一句愿望:目标、交付物、验收、约束和边界必须同时出现
一个可执行 Goal Contract 同时包含 objective、deliverables、acceptance criteria、constraints、budget 与 out-of-scope。只有 能把‘看起来完成’变成可验证完成。
Acceptance Criterion 先声明证据要求
Goal Contract 只定义需要哪类 evidence 以及怎样判定通过;此时 Plan 尚未生成,不应提前引用任何 Step ID。随后由 Plan.acceptance_coverage 把 AC 映射到具体 step、output 与 predicate。
约束参与规划,而不是写在备注里
如果用户要求不进入多 Agent,那么任何 delegation step 都应在 Plan Validation 阶段被拒绝,而不是执行后再解释。
实验一:把模糊请求改写成 Executor 能验收的 Goal Contract
从熟悉的“待办清单导出 CSV”开始:用六个问题补全 Goal,运行普通列表、空列表与特殊字符验收样例,再展开查看完整 goal-contract.yaml。Goal 先声明 evidence requirement,Plan 才负责把 AC 映射到具体 step.output。
“给待办清单加一个导出功能,保持现有页面风格。”
“导出什么、什么格式、空列表怎么办、怎样证明原功能没坏”都没有答案,因此 Executor 现在还不能安全开始改代码。
让用户把当前筛选后的待办任务下载为 CSV;正常列表、空列表和特殊字符都能正确处理,并且现有功能与构建保持通过。
用户最终能够做什么?
从当前待办清单下载一个 CSV 文件。
为什么要写:描述任务完成后发生的状态变化,而不是先规定按钮写在哪个组件里。
普通列表
type 与 predicate,但此时还没有 S1、S2 等步骤,所以不应提前引用 step.output。acceptance_coverage: AC1: S7.test_report → csv_normal_export == passed AC2: S7.test_report → csv_special_characters == passed AC3: S7.test_report → csv_empty_list == passed AC4: S7.test_report → regression_tests && build == passed
Task decomposition 的最小单位不是动词,而是可验收的状态变化
“研究一下”“处理代码”“看看是否正常”看似是步骤,实际没有清晰的输入边界和结束条件。一个可调度步骤至少要回答四件事:消费什么、产生什么、由什么证据证明成功、失败会影响哪些后继。下面继续使用 G-TODO-CSV,不再切换任务。
| 模糊分解 | 可执行分解 | 为什么更好 |
|---|---|---|
| 理解需求 | 不再新建 Step;已完成的 goal_contract 作为 initial_artifact | Plan 消费 Goal,而不是在 S1 里重新解释或改写 Goal |
| 检查项目 | S1“检查项目结构与待办数据”:输入 goal_contract + existing_project,输出 project_map + todo_data_contract | 把现有项目和待办数据边界变成可消费事实 |
| 查规则、看风格 | S2 输出 csv_rules;S3 输出 style_contract | 二者只依赖 S1,可以并行并在 S4 汇合 |
| 设计并修改多个文件 | S4 输出 csv_export_contract + change_design;S5 输出 csv_exporter;S6 输出 export_ui | S5/S6 可并行,也能在契约漂移后单独修复 |
| 跑一下测试 | S7 输出 test_report;S8 消费它并输出 acceptance_report | 测试证据与最终验收分开,失败时能取消失效的 S8 |
分解粒度也不能无限变小。把每一行代码拆成 step 会让规划、状态更新和验证开销超过执行收益。经验规则是:当产物能被独立验证、依赖、重试、取消或并行时,才值得成为单独步骤。
Plan Schema 把任务叙述变成 Runtime 可以拒绝、调度和追踪的数据
继续使用实验一的“待办清单导出 CSV”:阅读与后续 Runtime 共用的完整 P1 / S1–S8 plan.json,按七个语义组逐行理解计划身份、预算、Step ID、依赖与输入、输出契约、失败策略和 AC1–AC4 验收覆盖;同时解释 P / v / G / S / AC / ID / DAG 以及 JSON 符号。
左侧是可以保存为 plan.json 的完整文件。选择右侧七个语义组,文件中的对应行会同步高亮;先理解“这一组行回答什么问题”,再看字段名。
Runtime 正在执行哪份计划?它服务于哪个 Goal?
- plan_id 必须唯一且非空
- version 必须为正整数,并在 Replan 时递增
- goal_ref 必须能解析到真实存在的 Goal Contract
depends_on: ["S5", "S6"]检查步骤状态S5、S6 是否都已经成功?它决定 S7 在 DAG 上能否进入 ready。consumes: ["csv_exporter", "export_ui"]检查产物是否存在两个可用 artifact 是否真的已登记?它决定 S7 拿到的数据是否完整。两者不能互相替代:前置步骤可能显示 succeeded,却没有产出约定 artifact;也可能 artifact 来自初始输入,并不要求先执行某个步骤。
P1Plan 1第 1 份计划的 ID
v1Version 1计划的第 1 个版本
GGoal目标契约前缀
SStep步骤 ID 前缀
ACAcceptance Criterion验收条件前缀
IDIdentifier稳定且唯一的标识符
DAGDirected Acyclic Graph有向无环依赖图
Step ID 与输出契约是跨执行、重试和 Replan 的引用坐标
S7 不只是显示序号。完整引用坐标是 plan_id / version / step_id / attempt,例如 P1 / v1 / S2 / #1。Trace、日志、预算、依赖边、验收条件和取消事件都通过它指向同一次逻辑执行;Step ID 在一个 plan version 内必须唯一,并且一旦产生可消费输出就不能被静默复用。
| 情形 | 正确处理 | 禁止行为 |
|---|---|---|
| S2 CSV 检索瞬时超时 | 记录 S2#1 failed、S2#2 succeeded;逻辑 ID 仍映射 S2 | 假装第一次调用没有发生 |
| S7 暴露输入契约漂移 | 保留 S1–S6 的历史与仍有效产物,新增 R1/R2/R3,并把 S8@v1 标记 cancelled | 直接覆盖 S7 的失败记录 |
| 成功产物仍有效 | 以 immutable artifact reference 复用;R2 只添加增量 contract_fix | Replan 时重跑所有已成功步骤 |
| 旧后继失效 | 显式 cancelled / superseded,并传播到尚未分派的后代 | 让旧步骤和新步骤同时提交结果 |
输出契约还应说明结构、版本、来源和完整性。例如 test_report@v2 不只是“测试通过”四个字,而是包含 suite、exit code、AC1–AC4 predicate 结果、artifact hash 与生成它的 plan version。
实验二:向 Plan 注入环、缺失依赖和断裂输出,观察 Validator 在执行前拒绝
先把 Validator 理解为“开工前检查图纸”:对照正确的 P1 / S1–S8 基线,再分别注入循环等待、不存在的 S99,以及 S7 输入与 AC4 证据断裂。每次都沿着“改了什么 → 为什么无法开始 → 错误码的白话含义 → 最小修复”追踪因果,并区分依赖步骤与输入产物。
G-TODO-CSV→P1 · v1 · S1–S8它不会生成 CSV、修改文件或运行测试,只读取 Plan,判断“有没有可能按这张图开始并走到验收”。如果结果是 INVALID,Runtime 会在派发第一个 Step 之前拒绝计划,因此执行步数与执行预算消耗都为 0。
depends_on前置步骤必须真实存在并成功结束
consumes所需 artifact 必须来自初始材料或祖先输出
acceptance_coverage每条 AC 必须能定位到真实证据
→ 表示右侧必须等待左侧;∥ 表示依赖满足后可以并行。artifact 是能被 Runtime 登记并交给下游读取的有名产物,例如 S7.test_report。
- 1S1 可以直接使用 goal_contract 与 existing_project 开始工作。
- 2每个 depends_on 都指向真实步骤,而且依赖关系中没有环。
- 3每个 consumes 都能在初始材料或祖先步骤的 produces 中找到。
- 4AC1–AC4 都能追溯到 S7.test_report。
VALID共 60 项
结构检查通过,可以派发 Step;运行时仍可能遇到 timeout 或测试失败。
它证明依赖可以排开,不代表所有步骤必须串行;S2/S3 与 S5/S6 的并行排程会在下一实验展开。
depends_on要等待哪些步骤成功
consumes开始时必须拿到哪些产物
{
"id": "S1",
"depends_on": [],
"consumes": [
"goal_contract",
"existing_project"
],
"produces": [
"project_map",
"todo_data_contract"
],
"estimate": {
"duration_ticks": 2,
"cost_units": 3
},
"policy": {
"cancellable": false,
"on_failure": "stop"
}
}Plan Validity 是多项硬约束的合取,不是 Planner 的自评分
只有所有硬约束同时成立,Plan 才能进入执行。估算接近上限可以是 warning;超过扣除 Replan reserve 后的可执行预算,以及环、缺失依赖、输入输出断裂或不可达验收证据,必须是 error。
Dependency Satisfaction 在运行时再次检查
静态 Validity 只证明计划结构可能执行;真正分派某步前仍要确认所有依赖已 succeeded 且所需 artifact 可读。
Validator 必须独立于 Planner
让产生 Plan 的同一自由文本输出自行宣布 valid,会把遗漏的依赖误当成不存在的约束。Runtime 应依据 schema 与独立 oracle contract 检查。
DAG 只表达先后必要性:没有依赖边,不等于一定要并行
在有向无环图中,边 S2 → S4 表示 S4 必须等待 S2 的 csv_rules;它不表示二者属于不同 Agent,也不表示 Runtime 一定拥有足够资源。并行首先由依赖允许,然后还要通过资源锁、预算预留、并发上限和副作用冲突检查。
S1 检查项目结构与待办数据
├─ S2 检索 CSV 规则 ─────┐
└─ S3 检查交互与页面风格 ─┴→ S4 设计 CSV 导出契约
├─ S5 实现 CSV 逻辑 ─┐
└─ S6 接入导出按钮 ──┴→ S7 测试 → S8 验收| 概念 | Runtime 判断 | 本实验例子 |
|---|---|---|
| Ready Set | 依赖成功、输入齐备、预算已预留 | S1 完成后 S2 与 S3 同时 ready |
| Serial barrier | 必须汇合多个分支 | S4 等待 S2 + S3;S7 等待 S5 + S6 |
| Resource conflict | 即使无依赖也不能安全并发 | S5/S6 若同时修改同一组件,需要文件锁或重新分解 |
| Cancellation propagation | 失败依赖让后继 blocked;结构替换让旧后继 cancelled | S7 failed 后 S8@v1 不可继续 |
实验三:在同一 DAG 上切换全串行与依赖并行,并高亮 Critical Path
在同一个 Todo CSV P1 上点击任意节点检查 consumes / produces,切换调度模式观察 makespan 从 26 降到 18 ticks;紫色节点构成决定最短完工时间的 Critical Path。
P1 · G-TODO-CSVS1–S8 · 串行工作量 26 tickscsv_export_contract + change_designcsv_exporterCritical Path 给出无限资源下的时间下界,优化非关键步骤不一定更快
拓扑顺序中逐步计算 earliest start 与 earliest finish,最终最大值就是关键路径长度。串行总工作量是 ,当前 DAG 的 。
本实验的关键路径
S2 比 S3 慢 1 tick,S5 与 S6 等长,因此有两条同长关键分支。界面选择其中一条作为可解释的 backpointer path。
Critical Path 会随 Replan 改变
插入 R1/R2/R3 后必须重算,而不能沿用 Plan v1 的时间下界;否则 Parallel Efficiency 会被错误夸大。
Plan-and-Execute 不是生成列表后照单全做,而是一个持续验证的调度循环
- Plan:从 Goal Contract 生成 versioned DAG 与每步输出契约。
- Validate:检查 ID、依赖、环、契约、验收覆盖和预算可行性;INVALID 时禁止执行。
- Schedule:从 Ready Set 中选择不冲突的步骤,先预留预算,再并行 dispatch。
- Observe:只接受真实工具或代码运行产生的 output artifact;写入 append-only Ledger。
- Update:把 succeeded / failed / cancelled 传播到后继,重新计算 ready、blocked 和剩余预算。
- Accept:没有 ready steps 不等于成功;还必须逐条验证 Goal Acceptance。
No.17 的行动循环可以嵌入第 3–4 步,用于完成某个复杂 step;No.18 的 Scheduler 不替代工具选择,而是为每次局部行动提供全局依赖、预算和完成语境。
Execution Ledger 让每一步从 pending 到终态都可追踪,blocked 只是依赖派生状态
pending → ready → running → succeeded
├→ failed
└→ cancelled
blocked = pending AND any(dependency ∈ {failed, cancelled})blocked 不应覆盖成一个不可逆的主状态:Replan 可能替换失败依赖,使原本 blocked 的目标重新可达。真正的 Ledger 需要记录事件序列,而不是只保存每步最后一个字符串。
| 事件字段 | 用途 | 不能省略的原因 |
|---|---|---|
| plan_version + step_id + attempt | 唯一定位一次执行 | 区分 S2#1 超时与 S2#2 成功 |
| started_at / ended_at / lane | 计算 makespan 与并行效率 | 只看顺序号无法证明并发 |
| input_refs / output_refs | 验证 Dependency Satisfaction | 不能依赖 Planner 自报 |
| reserved_cost / actual_cost | 预算 guard 与退款 | 取消步骤可能释放未消费预算 |
| reason / error_class | 选择 retry、replan 或 stop | 所有失败都重试会形成循环 |
对有副作用的步骤还需要幂等键、提交边界和补偿策略。取消一个“尚未分派”的步骤很安全;取消一个已经写入外部系统的步骤,可能只能停止后续工作并执行补偿,而不能假装它从未发生。
失败后先分类:Retry 修复一次执行,Replan 修复任务结构
| 失败类型 | Plan 仍可行? | 首选动作 | Todo CSV 例子 |
|---|---|---|---|
| 瞬时工具失败 | 是 | 在 retry policy 内重试同一逻辑步骤 | S2 检索 CSV 规则 timeout,输入和输出契约未变 |
| 参数或格式错误 | 通常是 | 修复参数后重试;保留错误 Observation | CSV 检查器收到错误的 delimiter 参数类型 |
| 结构性契约漂移 | 否 | Replan 未完成子图 | S6 的 export_ui 传 filtered_tasks,而 S5 的 csv_exporter 仍读取 all_tasks |
| 目标或约束改变 | 否 | 生成新 Goal/Plan version 并重新验收 | 用户把“浏览器本地导出”改成“云端定时导出” |
| 不可恢复或预算不足 | 否 | 取消后继并受控停止 | 剩余预算不足以重新测试并生成 acceptance_report |
Replan 不是“再想一次”的同义词。如果新计划没有可见 diff,没有说明哪些成功产物被保留、哪些旧后继被淘汰、预算怎样重新分配,那么它只是一次不可审计的重试。
Replanning 的输入必须包含失败证据、不可变成功产物和剩余预算
Replanner 依据同一个 Goal、当前 Plan、Execution Ledger、失败 Observation、仍有效的成功 artifacts 与剩余预算,生成只替换未完成子图的新版本。
最小改图原则
先求失败节点的受影响后继闭包,只替换其中尚未成功且输出已失效的部分。
新版本仍必须验证
Replanner 不是 Validator 的例外。Plan v2 仍要通过无环、输入输出、验收覆盖和预算检查后才能继续。
正确 Replan 的第一步常常是取消旧后继,而不是立刻增加新步骤
默认契约漂移场景中,S7 发现 export_ui 与 csv_exporter 的输入契约不一致,因而没有产生可信 test_report;S8@v1 已经失去可用输入。Runtime 先把它标记为 cancelled,随后 Plan v2 插入 R1 定位边界、R2 生成增量 contract_fix、R3 只重跑受影响测试,最后创建 S8@v2。
Plan v1: S5 csv_exporter + S6 export_ui → S7 failed → S8 blocked
│
└─ cancel S8@v1
Plan v2: preserve S1…S6 → R1 diagnose → R2 repair → R3 test → S8@v2| 保留 | 取消 / 替换 | 为什么 |
|---|---|---|
| G-TODO-CSV、S1 project_map + todo_data_contract、S2 csv_rules、S3 style_contract | 不重跑 | 失败没有使这些输入和知识失效 |
| S5 csv_exporter 与 S6 export_ui | 保留原 artifact,R2 生成增量 contract_fix | 便于审计接口 diff,避免覆盖历史 |
| S7 failed event | 不删除,R3 生成新 test_report | Recovery 指标需要失败证据 |
| 旧 S8 | cancelled,不能复活同一 attempt | 它引用的是缺失的 test_report |
预算要在分派前预留,并为诊断与 Replan 留出恢复空间
预算不仅覆盖成功路径。Runtime 在步骤开始前预留 estimate;若剩余预算不足,就取消尚未分派的步骤并返回 budget_exceeded,而不是先超支再统计。
为什么默认预算是 40
Plan v1 的正常成功路径成本为 31。契约漂移时,S1–S7 的已用成本为 30;R1/R2/R3 与 S8@v2 再用 9,总计 39,仍有 1 unit 余量。ReAct only 因提前接入按钮和重复检查需要 41,恰好在最终验收前被 guard 停止。
Budget Exceeded Rate 的含义
硬 guard 不允许真实花费超过上限;指标统计的是因预算不足而终止的 trials / 总 trials,而不是超限了多少资源。
核心实验先冻结公平性:三种策略只能改变控制方式,不能改变任务真值
三种策略继续共享实验一的同一个 G-TODO-CSV:检查项目与待办数据,并行获得 CSV 规则和页面风格,设计导出契约,并行实现 csv_exporter 与 export_ui,运行测试,最后按 AC1–AC4 验收。从 Goal 到核心实验始终只有这一项任务。
| 固定项 | 三种策略完全相同 |
|---|---|
| Goal 与验收 | 同一个 G-TODO-CSV、AC1–AC4 与独立 oracle |
| 步骤真值 | 同一 S1–S8 拓扑、artifact contract、耗时和成本;不让某策略得到更便宜的工具 |
| Failure injection | 无故障、S2 一次 CSV 规则检索 timeout、或 S7 发现 export_ui / csv_exporter contract drift |
| 预算 | 30 / 40 / 48 units,分派前使用同一 guard |
| 指标 | 全部从同一 PlanningEvent trace 计算;N/A 不冒充 0 |
唯一自变量是控制策略:ReAct only 逐步选择局部动作且没有显式全局 Plan;Plan → Execute 先生成并验证固定 DAG;Plan → Execute → Replan 允许在结构性失败后取消旧分支并提交有效 Plan v2。
核心实验:同一复杂任务比较 ReAct only、Plan → Execute 与 Plan → Execute → Replan
在同一个 G-TODO-CSV / P1 / S1–S8 上选择失败注入与总预算,运行 deterministic Planning Runtime;对照总体状态、Plan 版本、成本、makespan、七项指标和逐事件 execution trace。
S7 发现 export_ui 与 csv_exporter 对筛选任务的输入契约不一致,需要替换失败子图。
| Strategy | Plan Validity | Dependency Satisfaction | Plan Completion | Replan Recovery | Redundant Steps | Parallel Efficiency | Budget Exceeded Rate |
|---|---|---|---|---|---|---|---|
| ReAct only | — | — | — | — | — | — | — |
| Plan → Execute | — | — | — | — | — | — | — |
| Plan → Execute → Replan | — | — | — | — | — | — | — |
逐项读默认 trace:三个失败结果来自三种不同机制
1. ReAct only:能局部恢复,但全局冗余吞掉最终验收预算
A3 在 csv_rules 与 csv_export_contract 尚未齐备时提前接入按钮,形成一次 blocked 冗余步骤;S7 发现 export_ui / csv_exporter 契约漂移后,它又重新检查已经看过的项目与数据。它最终修复并重跑测试,却已经花完 40 units;分派需要 1 unit 的 S8 时触发预算 guard。失败原因不是模型完全不会修,而是没有全局依赖和恢复预算。
2. Plan → Execute:调度高效,但固定 DAG 不能消化结构性新事实
S2/S3 与 S5/S6 两组并行,使执行贴近 Critical Path;S7 failed 后 S8 因缺少 test_report 正确 blocked。它没有越权改图或伪造成功,因此 Plan Completion 为 75%。这是一种正确失败:系统知道 P1 v1 已经不够,却没有 Replanner 能力。
3. Plan → Execute → Replan:先取消旧下游,再最小替换失败子图
Runtime 保留 S1–S6,取消 S8@v1,插入 R1/R2/R3,并用 S8@v2 重新验收。总成本 39 小于预算 40;没有重新检索 CSV 规则或重复检查页面风格。Replan Recovery 为 100%,但只有在 contract drift 场景才有定义。
| 切换场景后应观察什么 | 合理结果 |
|---|---|
| S2 工具超时 | 固定 Plan 内 retry 成功;Replanner 不产生 v2 |
| 无故障 | 两种 Plan 策略结果相同;ReAct 仍因串行和提前尝试略慢 |
| 30 units | 不同策略在不同分派点触发取消;真实 cost 永不超过 30 |
| 48 units + contract drift | ReAct 可最终完成,但冗余和 makespan 仍高于最小 Replan |
七项指标分别检查结构、执行、恢复、浪费、并行与预算,不能压成一个总分
Planning 质量必须从计划版本、真实执行 trace 与独立验收共同计算。ReAct 没有显式 Plan,因此 Plan Validity、Plan Completion 与 Replan Recovery 显示 N/A,而不是 0。
Plan Completion 不等于 Goal Acceptance
计划内步骤可能全部 succeeded,但验收证据仍不满足用户 Goal;二者必须分别计算,最终 completed 以 Acceptance 为准。
Redundant Steps 需要数据流判断
失败尝试不自动等于冗余;如果它提供了错误证据并支持正确恢复,就可能是必要诊断。真正冗余是输出未被后继或验收消费。
单次实验中的 Budget Exceeded Rate
每次选定场景相当于一个 trial,所以显示 0% 或 100%;批量 benchmark 时再对多个 trials 取均值。
浏览器实验的忠实缩略控制器:验证、调度、记录、取消、Replan 与验收
typescript本卡展示核心实验同构的控制边界。上方四个实验直接运行项目内的 TypeScript Planning Runtime;这里不使用伪 Python 执行器,以免把静态示例误当成真实 DAG 结果。
按执行顺序理解与检查
type Terminal = 'succeeded' | 'failed' | 'cancelled'
async function planAndExecute(goal: GoalContract, budget: Budget) {
let plan = await planner.create(goal, budget)
let validation = validatePlan(plan)
if (!validation.valid) return stop('invalid_plan', validation.issues)
const ledger = new ExecutionLedger(plan.version)
const artifacts = new ArtifactStore()
while (!goal.acceptance.every(ac => ac.verify(artifacts))) {
const ready = readySteps(plan, ledger, artifacts)
.filter(step => !resourceLocks.conflicts(step))
if (ready.length === 0) {
const failure = classifyBlockedPlan(plan, ledger, artifacts)
if (!failure.recoverable) return stop(failure.code, ledger)
const diff = await replanner.createDiff({
goal,
currentPlan: plan,
ledger,
failureObservation: failure.observation,
immutableArtifacts: artifacts.stillValid(),
remainingBudget: budget.remaining()
})
cancelSupersededDescendants(diff, ledger, budget)
const candidate = applyPlanDiff(plan, diff)
validation = validatePlan(candidate)
if (!validation.valid) return stop('invalid_replan', validation.issues)
plan = candidate
continue
}
const batch = reserveWithinBudget(ready, budget)
if (batch.length === 0) {
cancelPending(plan, ledger, 'budget_guard')
return stop('budget_exceeded', ledger)
}
const observations = await Promise.allSettled(
batch.map(step => executor.run(step, artifacts))
)
for (const [index, observation] of observations.entries()) {
const step = batch[index]
ledger.append(toExecutionEvent(step, observation, plan.version))
if (observation.status === 'fulfilled') {
artifacts.commit(step.outputs, observation.value, plan.version)
budget.settle(step.id, observation.value.actualCost)
} else {
budget.settleFailure(step.id, observation.reason.actualCost)
if (isRetryable(observation.reason, step.policy)) {
ledger.enqueueRetry(step.id, observation.reason)
}
}
}
}
return complete({
planVersion: plan.version,
acceptanceReport: goal.acceptance.map(ac => ac.evidence(artifacts)),
metrics: computePlanningMetrics(plan, ledger, budget)
})
}No.18 的完成标准:不是拥有 Plan,而是能用证据完成、失败、改图或取消
| 能力 | 本模块已经闭环的判断 |
|---|---|
| Goal | 模糊请求被改写为 deliverables、AC、constraints、budget 与 out-of-scope |
| Decomposition | 步骤以可验证输出为边界,粒度足以依赖、并行、重试和取消 |
| Plan | Step ID、input/output、DAG、估算、failure policy 与验收引用可解析 |
| Validation | 执行前拒绝重复 ID、缺失依赖、环、断裂契约和不可达验收 |
| Execution | 只分派 ready steps,记录 append-only Ledger,严格区分 succeeded / failed / cancelled |
| Replan | 以失败证据和剩余预算为输入,保留有效产物,最小替换未完成子图并再次验证 |
| Evaluation | 三策略同任务同预算,从 trace 计算七项指标,N/A 与 0 保持不同语义 |
当前实现是一个确定性、单进程、单 Agent 的教学 Runtime。它没有持久化跨会话记忆,不会把工作委派给其他 Agent,也不模拟分布式队列、租约、跨机器补偿事务或生产级权限系统。这些都不是缺失的“隐藏功能”,而是明确的 scope boundary。
正在检查登录状态与模型配置…