17 Lean Research Closure¶
目标¶
用一个 Trellis 任务完成适度拆解、状态记录、缺口修复和关闭检查,避免计划过宽或部分完成后提前结束。
一项任务如何拆¶
新任务默认使用 lean(轻量)模式。一般先保留一个 task,在 task 内安排 1–4 个 work packages(工作包)。工作包描述可观察结果,不描述命令步骤。
例如,“生成可安装包并通过安装验证”可以是一个工作包;“读取配置、修改文件、运行构建、查看输出”不能拆成四个工作包。
只有下面五项中至少满足两项,才适合单独建立工作包:
- 产生独立产物;
- 有独立验证标准;
- 依赖前一结果;
- 可以独立失败或阻塞;
- 需要不同代理、环境或权限。
出现 5 个以上工作包时,工具只提示考虑拆成多个 task,不会自动拆分。真正的 subtask(子任务)用于独立交付、独立审查或并行工作;work package 仍属于同一任务并共享范围。
最短流程¶
python3 ./.trellis/scripts/task.py create "验证本地分析脚本" --slug verify-analysis
TASK="$(find .trellis/tasks -maxdepth 1 -type d -name '*-verify-analysis' -printf '%f\n' | tail -n 1)"
python3 ./.trellis/scripts/closure.py plan --task "$TASK" \
--intent "得到可重复运行且经过验证的分析结果" \
--in-scope "本地固定样例" \
--out-of-scope "正式论文结论" \
--done-when "分析脚本在固定样例上运行成功"
python3 ./.trellis/scripts/closure.py validate --task "$TASK"
export TRELLIS_CONTEXT_ID=manual-closure-example
python3 ./.trellis/scripts/task.py start "$TASK"
python3 ./.trellis/scripts/closure.py capsule --task "$TASK"
完成当前工作包后:
python3 ./.trellis/scripts/closure.py package-check --task "$TASK"
python3 ./.trellis/scripts/closure.py package-done --task "$TASK" \
--evidence "tests/test_analysis.py: passed"
python3 ./.trellis/scripts/closure.py audit --task "$TASK"
python3 ./.trellis/scripts/closure.py close --task "$TASK"
python3 ./.trellis/scripts/task.py archive "$TASK" --no-commit
task.json(任务状态)是当前状态的唯一事实源。plan_revision(计划修订号)只在范围、完成条件、工作包或研究契约等计划内容实际变化时递增;state_revision(状态修订号)在 Closure 语义写入时递增。兼容字段 task_revision(任务修订号)对应计划修订,hermes_revision(Hermes 修订号)对应状态修订。阶段和工作包状态只能通过命令变更;对话里说“已经完成”不会把任务改成 completed(已完成)。
默认生命周期协调¶
内置任务生命周期协调默认启用。任务创建、启动、Closure 命令、每轮任务续接、子代理返回、会话结束检查和归档都会读取同一份 task.json,并只修复能够从现有状态确定的偏差,例如:
- 原版任务状态与 Hermes 阶段映射不一致;
- 当前工作包引用不存在,或遗漏了唯一处于运行、审核、阻塞状态的工作包;
- 派发失败已阻塞工作包,但任务阶段尚未同步;
- 下一动作为空,或因结构修复需要重新计算;
- 关闭标记只写入了一半。
协调器重复运行不会重复写事件或递增修订号。发生实际修复时,才写入 lifecycle_reconciled(生命周期已校正)事件。归档成功后写入 task_archived(任务已归档)事件。
生命周期协调不会接受证据、处置工作包、批准主张或关闭任务。runner(运行代理)成功仍只代表运行结束;工作包必须经过 package-check(工作包检查)和 package-done(工作包处置),任务必须经过 audit(审计)和 close(关闭)。这样可以修复“模型忘记同步状态”,但不会把不完整结果误判为完成。
需要诊断时可以在 .trellis/config.yaml 中设置 task_lifecycle.enabled: false,或临时设置 TRELLIS_TASK_LIFECYCLE=0(关闭内置任务生命周期协调)。自定义 Shell 生命周期钩子仍默认留空。
计划锚点与方案漂移¶
每次 validate(校验)成功都会在 task.json(任务状态)生成 plan_anchor(计划锚点)。它固定当时的 intent(目标)、范围、完成定义、工作包结果与验收、证据要求、研究路线、关键约束,以及 prd.md(需求文档)、design.md(设计方案)、implement.md(实施计划)中方案契约部分和当前决策记录的哈希。Notes(说明)、Progress(进度)、Experiment Log(实验记录)等专门章节用于追加执行记录,不会改变锚点;其他方案正文仍受保护。完整锚点还随 plan_validated(计划已校验)事件追加保存,因此重新校验不会抹掉旧方案。它不是第二份当前状态;当前状态仍以 task.json 为准,锚点只是“哪一版方案得到批准”的基线。
已有的 Hermes 任务若已在 ready、running、review 或 blocked 阶段但没有锚点,首次生命周期续接会生成一次 legacy_migration(旧任务迁移)锚点并记录事件;原版非 Hermes 任务不受影响。
在 ready、running 或 review 阶段,如果这些内容被直接改动,生命周期协调会写入 plan_drift_detected(计划漂移已发现)事件并进入 blocked(阻塞)。package-check(工作包检查)、package-done(工作包处置)、正式 agent 派发、audit(审计)、close(关闭)都会拒绝继续。这样“当前报错所以换一个方案”的判断不会悄悄替换原计划。
遇到困难时先在原计划内复现和定位;有限 repair(修复)仍只处理审计缺口。需要改变目标、完成定义、工作包 outcome(结果)、done_when(完成条件)、证据要求、范围、研究协议或方案正文时,使用 amend(计划变更)。方案文件先修改,再用 amend --field plan_documents --value current(接受当前方案文件)确认这一版。已经校验的验收、研究协议和方案文件变化必须同时提供人工批准与 decision_ref(决策记录引用);记录必须有 Decision(决定)、Rationale(理由)、Evidence(证据)、Original Commitment(原承诺)、Failure Evidence(失败证据)、Failed Attempts(已尝试路径)、Alternatives(备选方案)和 Failure Conditions(失效条件)。完成变更后任务回到 planning,再次 validate 才会生成新锚点。
模型架构、新假设、数据、切分、预处理、指标、基线或主张范围变化属于探索性研究;其中模型架构变化必须创建独立探索任务,不会覆盖旧任务结果。旧任务应明确保留为完成、延期、阻塞或失败,而不是把新路线写成原方案已经完成。
状态可见性与回放¶
status --json(状态 JSON)会从最新未应用的 plan_amended(计划变更)事件显示待处理事项:变更字段、当前 plan_revision(计划修订号)、仍缺少的人工批准或决策记录,以及恢复条件。它不会把聊天中的“已同意”当作批准。
python3 ./.trellis/scripts/closure.py status --task "$TASK" --json
python3 ./.trellis/scripts/closure.py timeline --task "$TASK"
timeline(时间线)只汇总 task-events.jsonl(任务事件记录)和 dispatch_audit.jsonl(派发审计记录)末尾的最近 12 条短摘要。它不运行生命周期校正、不修改 task.json(任务状态)或事件记录;用于快速回看当前任务如何进入此状态,不读取原始终端日志、完整差异、搜索过程或聊天内容。
Task Capsule¶
capsule(紧凑上下文)默认控制在约 500–1000 个字符,包含任务目标、范围、模式、阶段、当前工作包、完成条件、下一动作、阻塞项和最多 3 个相关引用。
每轮自动注入优先使用 capsule,不自动读取完整 prd.md(需求文档)、全部报告、全部事件、全部 ledger(账本)、历史任务和无关规范。这些文件不会删除,仍可按需读取。
普通任务恢复仍可使用 capsule(紧凑上下文)。正式 Hermes(科研工作流)角色改为读取 validated dispatch(已验证派发):派发绑定当前修订号、角色、模式、工作包、目标和最多 3 个引用,正文不超过 2000 字符。
Claude Code、Codex 和 OpenCode 使用同一 capsule 语义。其他具有共享每轮 hook 的平台也会收到 capsule;只有会话开始注入或没有主会话 hook 的平台,应在恢复任务时显式运行 closure.py capsule。
Agent Context Firewall¶
正式防火墙只支持 Claude Code(Claude 代码工具)和 Codex(代码代理平台)。派发文件位于 .trellis/tasks/<task>/hermes/dispatches/<job>.dispatch.json(派发文件),净化结果位于同目录的 <job>.result.json(结果文件)。
python3 ./.trellis/scripts/hermes/dispatch.py create --task "$TASK" \
--role reviewer --profile closure --objective "检查当前关闭条件"
python3 ./.trellis/scripts/hermes/dispatch.py list --task "$TASK"
执行前会比较当前计划修订号,只有计划或计划锚点变化才返回 stale_dispatch(过期派发);兄弟派发完成产生的状态变化不会使其过期。同一结果可安全重试,不同结果不能覆盖已登记结果。结果必须包含 uncertainties(不确定项),结论最多 1200 字符;长日志、完整差异、搜索过程、敏感信息和绝对用户路径不会进入主上下文。两次非法返回只阻塞该 job(工作编号)和当前工作包,不会把科研任务标成完成。
角色与阶段¶
工作包仍是任务内部的结果分组,不因为使用不同角色自动变成子任务。常见顺序如下:
planner:task_planning(规划代理的任务规划模式)提出 1–4 个工作包候选;状态变更仍由 closure 命令应用。coder(编码代理)完成需要修改代码、测试或配置的当前工作包。runner(运行代理)登记测试、构建、实验或验证结果。reviewer(复核代理)进行质量、证据或关闭复核;不同模式不能互相替代门禁。researcher(检索代理)只在规划或实现明确缺少代码库、文献或官方文档信息时加入。
planner(规划代理)不能直接把工作包标记为完成,coder(编码代理)不能批准主张,runner(运行代理)不能把命令成功当作证据批准,reviewer(复核代理)也不能伪造人工批准。
三种模式¶
| 模式 | 适合场景 | 关闭前增加的检查 |
|---|---|---|
lean(轻量) |
日常代码、探索、文档、小规模试验 | 完成定义、工作包处置、基础验证、无阻塞、关闭报告 |
standard(标准) |
需要可重复运行记录的正式项目阶段 | 成功运行清单、产物 hash、指标、证据、主张限制 |
publication(发表) |
正式论文证据和可公开主张 | 统计比较、主张处置、证据引用、STATE.md、CLAIMS.md 和人工批准 |
run finished(运行结束)、package done(工作包完成)、task closed(任务关闭)和 claim approved(主张批准)是不同状态。运行成功只生成运行记录,不能直接成为已接受证据;任务关闭也不能代替论文主张批准。
模式都会检查钩子心跳;缺少新鲜钩子时给出明确警告,并继续使用派发、结果、记录和审计协议。standard(标准)与 publication(发表)的额外关闭条件来自运行清单、证据、统计、主张和人工审批,不来自沙箱或已取消的 Codex 严格执行器。
Audit 与有限修复¶
审计只输出紧凑缺口和下一动作。例如:
repair(有限修复)只重新打开审计指出的未完成工作包,不修改已完成工作包,也不会自动运行实验或扩大范围。lean 默认 1 轮,standard 和 publication 默认 2 轮;再次超过上限时任务进入 blocked(阻塞)并生成 HANDOFF.md(交接文件)。
人工审阅后确需增加一次修复机会时,显式批准上限变更:
python3 ./.trellis/scripts/closure.py amend --task "$TASK" \
--field max_repair_count --value 2 \
--reason "人工审阅后允许一次额外修复" \
--approved-by 'human/root'
python3 ./.trellis/scripts/closure.py validate --task "$TASK"
数据集、研究假设、数据切分、指标定义、基线、主张范围、任务范围、closure mode 和修复上限变化不能由 repair 自动处理。
计划变更¶
尚未 validate(校验)的 planning(规划)任务可以记录低风险变更;已经校验的验收变化必须使用人工批准和决策记录:
python3 ./.trellis/scripts/closure.py amend --task "$TASK" \
--field work_packages.WP2.done_when \
--value '["固定测试通过"]' \
--reason "验收条件需要可执行" \
--approved-by 'human/root' \
--decision-ref design.md
高风险研究契约变更必须显式记录人工批准:
python3 ./.trellis/scripts/closure.py amend --task "$TASK" \
--field dataset --value 'dataset-v2' \
--reason "数据来源修订" --approved-by 'human/root'
变更后任务回到 planning,需重新运行 closure.py validate。工具不会重写已经完成的工作包。
Handoff¶
handoff(交接)通常下发给 coder:configuration(配置修改)子代理生成当前任务的 HANDOFF.md(交接摘要)。它也可由 closure 命令直接生成紧凑状态摘要。
HANDOFF.md 只在代理切换、压缩或清理上下文前、任务阻塞、显式调用和关闭时需要。它记录当前目标、阶段、工作包、已完成结果、改动文件、证据、失败尝试、阻塞和下一动作,但不会修改任务、证据或主张状态。
有活动 closure 任务时,主代理的每次用户请求都会收到一条紧凑续接提示:当前阶段、当前工作包、下一动作和 task.json(任务状态)路径。新生成的交接同时记录计划修订号和状态修订号;恢复提示按状态修订号判断交接是否仍新鲜。旧格式或过期交接只显示警告,任务状态仍以 task.json 为准。交接文件全文不会自动注入,也不会默认传给子代理;task.py finish(结束会话)只清除会话指针,不会隐式生成交接。
上下文采用渐进披露:首次进入任务或任务修订变化时,才注入不超过约 1000 字符的 Task Capsule(任务胶囊);后续请求只保留短续接提示。项目背景、研究方案、约束、任务详情和历史记录只提供文件路径,由主代理按当前请求读取直接相关的一个文件,不默认预读全部内容。
在 compact(压缩)或 clear(清空)后,共享 hook 会再次注入当前 Task Capsule 和短续接提示。交接摘要只在修订号匹配时给出文件路径;其正文、完整需求文档和历史聊天不会自动重新注入,因此恢复时先以当前 task.json(任务状态)为准。
常见失败¶
validate提示缺少完成定义:用plan --done-when补充可观察验收条件。package-done提示缺少证据:先运行实际验证,再通过--evidence登记已有仓库文件或evidence_ledger.jsonl(证据账本)中的证据编号;任意文字不会被接受为证据。close提示工作包未处置:完成、defer 或 waive 对应工作包;不要直接改 JSON 状态。close提示派发未确认:先校验或处置对应结果;满足关闭条件后仍要显式运行audit(审计)和close(关闭)。stale_dispatch(过期派发):当前计划或计划锚点已变化,按新计划修订号重新创建派发;普通状态更新不会触发此错误。repair达到上限:查看HANDOFF.md和阻塞原因,由人工决定停止任务,或批准提高max_repair_count后重新校验。archive被拒绝:先运行closure.py audit和closure.py close。旧任务没有 closure 字段时仍走原版兼容归档。
示例¶
examples/lean-closure/(单工作包轻量示例);examples/standard-ai4chem/(固定数据和指标契约的标准 AI4Chem 示例)。
已知限制¶
- 自动规划只根据 intent 和完成定义生成候选工作包,研究者仍需审阅拆解质量。
- JSONL 事件便于 Git 审阅,但不是防篡改数据库。
- repair 只调整安全的任务状态,不会自动补跑实验、伪造证据或批准主张。
- publication 的人工批准真实性依赖外部流程,本项目只校验记录字段。
验证记录¶
- 日期:2026-07-15。
- 版本:
0.7.1-beta.3(测试版)。 - 命令:closure CLI 集成测试、共享 hook 测试、核心 task schema 测试和场景 smoke test(冒烟测试)。
- 结果:适度拆解、修订号、派发过期、结果净化、模式心跳、有限 repair、关闭和归档兼容均有自动化覆盖。
- 未验证项:自动候选工作包的科研语义仍需任务负责人审阅;人工审批身份真实性由外部流程保证。