fix(agent): commit each deck page before starting the next
**PR:**fix(agent): commit each deck page before starting the next (#4591)
source_automation: “voyager-merged-pr” run_date: “2026-07-11” anchor_pr_number: 4591 pr_number: 4591 pr_title: “fix(agent): commit each deck page before starting the next” pr_url: “https://github.com/adastralab-ai/voyager/pull/4591 ↗” author: “Horcrux / magicismight” merged_at: “2026-07-10T15:43:14Z” modules: [“agent-eval/cases/design”,“agent-eval/provider.ts”,“backend/workers/agent/src/skills/design-html”,“backend/workers/agent/src/skills/generate-slide”] files_changed: 7 learning_tags: [“agent-runtime”,“deck-generation”,“prompt-contract”,“tool-trajectory-eval”,“user-visible-progress”,“long-turn-timeout”] business_line: null related_prs: [4389,4516,4580] line_stage: null open_questions: [] feishu_doc_url: “https://my.feishu.cn/docx/HbPQdf4r0oRQzkxApD9c9of8nfh ↗”#
正文来源:飞书学习文档 ↗。以下为通过个人 Feishu API 获取并转换后的完整 Markdown 正文。
Voyager Merged PR 学习 - 2026-07-11 - PR #4591#
今日选择#
**PR:**fix(agent): commit each deck page before starting the next (#4591)
**作者:**magicismight
**Merge 时间:**2026-07-10T15:43:14Z(2026-07-11 01:43:14 AEST)
链接:https://github.com/adastralab-ai/voyager/pull/4591 ↗
**模块:**agent-eval/cases/design, agent-eval/provider.ts, backend/workers/agent/src/skills/design-html, backend/workers/agent/src/skills/generate-slide
**学习标签:**agent-runtime, deck-generation, prompt-contract, tool-trajectory-eval, user-visible-progress, long-turn-timeout
为什么值得学#
- 它把用户可感知的运行时反馈顺序写回技能契约:多页 deck 不是先生成完所有 HTML 再集中提交,而是每页从资产到 HTML 到 commit 闭环完成后再进入下一页。
- 它没有把问题下沉成复杂工具改造,而是承认工具本来就是单页粒度提交,修复点放在 agent 的技能约束和轨迹回归测试上。
- 它新增的 eval 检查的是工具调用序列,而不是最终文件数量;这更接近 agent 运行时 bug 的真实形态。
- 它顺手处理了 eval harness 的 300s 默认超时,让多页 deck 这种长 turn 可以被纳入回归层,而不是因为基础设施限制被排除。
关键代码#
1. 共享 design-html commit policy 把多页生成定义为用户可见的增量提交。
- **One design/page**: write the HTML, run one `inspect-html` preview/validation pass, fix material issues, then commit.
- **Multiple designs/pages**: do not load or run `inspect-html`. Build one page at a time: generate only that page's assets, write a unique working HTML file, self-check the hard rules, and commit it before starting any work on the next page (its image generation included).plaintext设计点:这里把“commit”从后处理步骤提升为用户反馈协议。多页任务每一页的 commit 是画布出现内容的边界,因此 agent 不应该为了内部吞吐把可见反馈批处理掉。
2. slide skill 在更具体的 deck 语境里重复同一顺序约束。
## Multi-slide decks
For decks, build slide N end-to-end before touching slide N+1: generate only slide N's assets, write a unique `/workspace/slide-N.html`, self-check, and commit it — only then start slide N+1.plaintext设计点:同一规则同时放在通用 HTML contract 和 slide-specific skill,减少模型在组合技能时把约束压缩丢失的概率。它不是泛泛说“commit directly”,而是给出 slide N 到 slide N+1 的严格时序。
3. 新 eval 用 pending uncommitted 标记捕捉“先写下一页”的轨迹。
const seq = context.providerResponse?.metadata?.toolSequence ?? [];
const seen = new Set();
let uncommitted = null;
for (const step of seq) {
if (step.name === "update_design" || step.name === "insert_page") { uncommitted = null; continue; }
const path = step.name === "write_file" ? String(step.input?.path ?? "") : "";
if (!path.endsWith(".html") || seen.has(path)) continue;
if (uncommitted) return { pass: false, score: 0, reason: `started ${path} before committing ${uncommitted}` };
seen.add(path);
uncommitted = path;
}plaintext设计点:测试不是断言某个 prompt 文案存在,而是断言 tool trajectory 的业务不变量:一个新 HTML 文件出现后,必须先有 update_design/insert_page 清掉 pending 状态,才能开始下一页。
4. eval provider 为长 agent turn 设置有限但更现实的 undici 超时。
// The eval route answers only when the whole agent turn finishes; multi-page
// deck cases run past undici's default 300s headersTimeout.
const TURN_TIMEOUT_MS = 20 * 60_000;
setGlobalDispatcher(
new Agent({ headersTimeout: TURN_TIMEOUT_MS, bodyTimeout: TURN_TIMEOUT_MS }),
);plaintext设计点:多页生成是单个 agent turn,eval route 只在整个 turn 完成后返回。这里不是无限放宽,而是把超时上限改成能覆盖真实长任务、同时仍能让卡死 worker 失败的有限边界。
和最近学习记录的关系#
它和最近几天的 agent/image 学习链路有直接关系,但关注点从“工具结果/费用/模型选择”转到“多步骤生成的用户可见进度”。#4516 和 #4580 都是在约束模型不要误重试、不要绕过用户确认;#4591 则约束模型不要把多页工作内部批处理成一个最终爆发。共同点是:把隐含产品语义写成 agent 协议和 eval,而不是只依赖 UI 层兜底。
我会怎么吸收#
- 凡是用户能实时感知的多步骤任务,都要定义“可见提交点”,并把它作为 agent/tool contract 的一部分。
- prompt/skill 修复要配 trajectory eval;对 agent 类系统,最终状态正确不代表过程正确。
- 长 turn 的测试基础设施要显式建模超时:默认 HTTP timeout 经常不是产品不变量,只是库默认值。
边界/风险#
看到一个有意接受的 eval 边界:review 曾指出仅把 update_design/insert_page 视为清 pending,未精确校验 htmlPath 可能被无关提交掩盖;作者解释最终选择非脆弱优先,避免绝对/相对路径变体带来的误报。这个取舍合理,但意味着 eval 保证的是“提交节奏”,不是“提交路径与刚写路径严格一致”。如果以后出现错误 htmlPath 的真实 bug,需要补更精确但归一化良好的路径断言。
候选说明#
今天(2026-07-11 Australia/Melbourne)窗口内看到 7 个已 merge 到 main 的候选:#4648、#4636、#4629、#4628、#4623、#4594、#4591。没有因为去重跳过今天候选;昨天已学习 #4580,所以未重复选择。最终选 #4591,是因为它横跨 agent 技能契约、运行时用户反馈和 eval harness,比价格调整、单文件分页大小、worktree DX 等 PR 更有学习价值;#4594 也有价值,但更偏 UI loading 连续性,工程边界不如 #4591 清晰。