关于 long-run
Long Run Harness 通过里程碑流水线编排复杂的多日任务。它将执行状态和检查点持久化以支持恢复,为每个里程碑执行计划、运行、审查流程,并在审查失败时阻止依赖任务。
主要功能
- 01按里程碑流水线执行工作
- 02在状态转换前保存状态
- 03从已保存的检查点恢复
- 04落实计划、运行、审查流程
- 05失败时阻止依赖任务
- 06并行执行符合条件的里程碑
适用场景
- 01中断后继续多日任务
- 02执行预先规划的里程碑
- 03协调相互独立的里程碑工作
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ tmdgusya/ engineering-discipline --skill long-run安装后在 Claude Code 中输入/long-run确认已加载。
详细介绍
长程运行调度器
通过里程碑流水线协调复杂任务的多日执行。每个里程碑都会依次经历 plan-crafting → run-plan → review-work,里程碑之间设有检查点,以便在中断后恢复。
核心原则
长时间运行的执行必须可恢复、可审计且故障安全。每次状态转换都会在下一项操作开始前持久化到磁盘。如果执行因任何原因停止——速率限制、崩溃、用户暂停、上下文丢失——都可以从上一个检查点恢复,而不必重复已完成的工作。
硬性门槛
- 执行前必须先有里程碑。 里程碑必须来自
milestone-planningskill 或由用户提供。执行期间绝不内联生成里程碑。 - 每个里程碑执行前后都必须更新状态文件。 不得只在内存中保存状态。如果没有写入磁盘,就等于没有发生。
- 每个里程碑都必须完成完整流水线。 plan-crafting → run-plan → review-work。不得走捷径。不得因为“看起来没问题”就跳过 review-work。
- 失败的里程碑会阻塞其依赖项。 如果 M2 依赖 M1,而 M1 未通过 review,M2 就不会启动。没有例外。
- 默认自主执行——里程碑之间不设审批门槛。 用户只在 milestone-planning 锁定里程碑计划时审批一次。从那时起,里程碑会按 plan → run → review → checkpoint 的顺序推进,无需暂停等待确认。仅在以下情况停止并询问:某个里程碑耗尽重试次数(
failed)、Mid-Execution Correction 需要确定范围、触发集成升级,或加载的状态不一致。每个阶段转换时发布简短的状态报告,让用户随时可以中断——状态文件可确保每次暂停后都能恢复。 - 绝不修改已完成的里程碑。 里程碑通过 review-work 后,其文件即被锁定。如果后续里程碑需要修改前序工作,应将其作为一个新里程碑。
- 每个里程碑完成后都要创建检查点。 继续执行前,写入检查点文件,记录已完成的工作、测试结果和审核结论。
适用场景
milestone-planning已生成里程碑 DAG 后- 用户说“long run”“start long run”“execute milestones”或“run all milestones”时
- 恢复之前暂停的长程运行会话时
不适用场景
- 里程碑尚不存在时(先使用
milestone-planning) - 只有一个里程碑时(直接使用 plan-crafting + run-plan)
- 对于不需要多阶段执行的快速任务
输入
- 调度器状态目录路径 — 例如:
docs/engineering-discipline/harness/<session-slug>/ - 该目录必须包含
state.md和milestones/*.md文件
如果状态目录不存在,询问用户是否要先运行 milestone-planning。
流程
阶段 1:加载并验证状态
- 从调度器目录读取
state.md - 从
milestones/读取所有里程碑文件 - 验证:
state.md中引用的所有里程碑都有对应文件- 依赖 DAG 有效(无循环,且可以进行拓扑排序)
- 没有里程碑处于无效状态(例如,处于“executing”状态但没有计划文件)
- 确定当前位置:
- 哪些里程碑已完成?
- 哪些里程碑已准备好启动(所有依赖项都已满足)?
- 这是全新开始还是恢复执行?
- 向用户展示状态:
## Long Run Status: [Session Name]
**Progress:** N/M milestones completed
**Current phase:** [planning M3 | executing M3 | reviewing M3 | ready to start M3]
**Next up:** [M3, M4 (parallel)]
Completed: M1 ✓, M2 ✓
In progress: M3 (executing)
Pending: M4, M5
- 如果加载的状态一致,立即继续——状态展示是报告,不是门槛。只有当第 3 步的验证发现不一致,或
failed里程碑阻塞后续进度时,才询问用户。
阶段 2:里程碑执行循环
按拓扑顺序处理每个里程碑:
┌─────────────────────────────────────┐
│ Milestone Pipeline │
│ │
│ ┌──────────┐ ┌─────────┐ │
│ │ Plan │───→│ Run │ │
│ │ Crafting │ │ Plan │ │
│ └──────────┘ └────┬────┘ │
│ │ │
│ ┌────▼────┐ │
│ │ Review │ │
│ │ Work │ │
│ └────┬────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ PASS? │ │
│ │ Yes → checkpoint│ │
│ │ No → retry │ │
│ └─────────────────┘ │
└─────────────────────────────────────┘
步骤 2-1:门槛检查
启动里程碑前:
- 确认所有依赖里程碑的状态均为
completed - 确认没有文件与正在并行执行的里程碑冲突
- 更新 state.md:将里程碑状态设为
planning - 使用时间戳更新执行日志
第 2-2 步:制定计划阶段
- 根据里程碑定义编写上下文摘要:
- 目标 → 来自里程碑文件
- 范围 → 里程碑文件中受影响的文件
- 成功标准 → 来自里程碑文件
- 约束 → 从父级问题 + 已完成里程碑的上下文继承
- 已完成里程碑上下文约定: 对于每个已完成的前置里程碑,仅包含:
- 创建/修改的文件(来自检查点的“Files Changed”列表)
- 已确立的接口约定(函数签名、API 形状、类型定义)
- 已验证达成的成功标准
- 不要包含:执行日志、审查文档、执行者/验证者的输出,或完整检查点内容
- 注意: 根据里程碑定义编写的上下文摘要不包含复杂度评估部分,因为路由已在里程碑规划阶段确定。摘要直接进入计划制定阶段,不再重新路由。
- 按照
plan-crafting技能模式执行:- 在
docs/engineering-discipline/plans/YYYY-MM-DD-<milestone-name>.md创建计划文档 - 计划必须满足所有里程碑成功标准
- 计划不得修改里程碑范围以外的文件
- 在
- 更新 state.md:记录此里程碑的计划文件路径
- 报告,但不等待批准: 发布简短的计划摘要(目标、任务数、涉及的文件)作为进度报告,并直接继续执行。
第 2-3 步:执行计划阶段
- 更新 state.md:将里程碑状态设为
executing,并将Attempts计数器加 1 - 按照
run-plan技能模式执行计划:- 每项任务都进行执行者-验证者循环
- 对独立任务进行并行执行
- 验证者的信息相互隔离
- 如果
run-plan在某项任务重试 3 次后仍报告失败:- 更新 state.md:将里程碑状态设为
failed - 在执行日志中记录失败详情
- 停止并向用户报告。 不要继续处理依赖此里程碑的后续里程碑。
- 更新 state.md:将里程碑状态设为
- 如果所有任务均已完成:进入审查阶段
第 2-4 步:审查工作阶段
- 更新 state.md:将里程碑状态设为
validating - 按照
review-work技能模式执行:- 根据计划文档进行信息隔离审查
- 给出二元的 PASS/FAIL 判定
- 如果 PASS:
- 更新 state.md:将里程碑状态设为
completed - 写入检查点文件(参见下文的检查点格式)
- 更新执行日志
- 继续下一个里程碑
- 更新 state.md:将里程碑状态设为
- 如果 FAIL:
- 在执行日志中记录审查发现
- 重试决策(根据 state.md 中跨崩溃保留的
Attempts计数器):- 如果 Attempts == 1:返回第 2-3 步,并附上审查反馈(重新执行同一计划)
- 如果 Attempts == 2:返回第 2-2 步(将审查反馈作为约束重新制定计划)
- 如果 Attempts >= 3:将状态设为
failed,停止并向用户报告
步骤 2-5:跨里程碑集成检查
里程碑通过 review-work 后,但在写入检查点之前,请验证该里程碑的输出是否与之前完成的所有里程碑正确集成:
- 运行项目最高级别的验证(使用 state.md 中的 Verification Strategy,或按照 plan-crafting 的 Verification Discovery 顺序重新发现)
- 检查跨里程碑接口: 如果已完成的里程碑定义或使用了前置里程碑的接口,请验证它们是否兼容(函数签名匹配、API 契约有效、类型一致)
如果集成检查通过: 继续写入检查点。
如果集成检查失败 — 跨里程碑失败响应:
该里程碑已通过自身的 review-work(内部正确性),但破坏了与其他里程碑的集成。这是一个边界问题。
-
诊断(尝试 1):
- 阅读失败输出
- 确定哪个接口边界或交互出现问题
- 判断修复属于当前里程碑,还是需要新增纠正里程碑
- 如果可在当前里程碑范围内修复:派发定向修复工作者 → 重新运行 review-work → 重新运行集成检查
- 如果修复超出当前里程碑范围:升级处理
-
诊断(尝试 2):
- 如果第一次修复未解决问题,重新分析
- 应用第二次定向修复
- 重新运行集成检查
-
升级给用户(2 次尝试均失败后):
- 报告:涉及哪些里程碑、哪个集成边界失败、尝试过哪些修复
- 选项:添加纠正里程碑、回滚到检查点、接受并继续(用户确认存在集成缺口)
- 将用户的决定记录在 state.md 执行日志中
步骤 2-6:检查点
里程碑通过 review 后:
写入 checkpoints/M<N>-checkpoint.md:
# Checkpoint: M<N> — [Milestone Name]
**Completed:** YYYY-MM-DD HH:MM
**Duration:** [time from planning start to review pass]
**Attempts:** [number of plan-execute-review cycles]
## Plan File
`docs/engineering-discipline/plans/YYYY-MM-DD-<name>.md`
## Review File
`docs/engineering-discipline/reviews/YYYY-MM-DD-<name>-review.md`
## Test Results
[Full test suite status at checkpoint time]
## Files Changed
[List of files created/modified in this milestone]
## State After Milestone
[Brief description of system state — what works now that didn't before]
阶段 3:并行执行里程碑
当多个里程碑的所有依赖均已满足且不存在文件冲突时:
- 确定可并行的里程碑组
- 先为所有并行里程碑运行 plan-crafting(依次执行——计划很轻量)
- 将所有计划摘要作为一份进度报告发布(无需等待批准),然后并发派发每个里程碑的流水线:
- 每个里程碑运行 run-plan → review-work
- 每个里程碑都在工作树中运行(
isolation: "worktree"),以防止文件冲突 - 两者完成并通过 review 后,将工作树合并回来
- 如果其中一个失败:分别处理(如果不存在依赖,另一个可以继续)
工作树合并协议:
- 两个里程碑分别在各自的工作树中通过 review
- 检查工作树更改之间是否存在文件冲突
- 如果没有冲突:依次合并(先合并 M_lower,再合并 M_higher)
- 如果检测到冲突:停止,报告给用户,并请求手动解决
- 合并后:对合并结果运行完整测试套件
- 如果测试失败:停止并报告给用户
阶段 4:完成
所有里程碑完成后(包括 milestone-planning 中的 Integration Verification Milestone):
- 更新 state.md:将整体状态设为
completing - 最终 E2E 门禁: 对完全集成的代码库最后一次运行项目最高级别的验证
- 运行完整测试套件以检查回归
- 如果最终 E2E 门禁失败:
- 诊断:确定哪个里程碑的输出可能导致问题
- 通过 Mid-Execution Correction 流程创建纠正里程碑
- 通过完整流水线执行纠正里程碑(plan-crafting → run-plan → review-work)
- 修正后重新运行 E2E 门禁
- 如果 2 次纠正尝试均失败:向用户升级处理并提供完整诊断
- 如果最终 E2E 门禁通过: 更新 state.md:将整体状态设为
completed - 生成完成摘要:
# Long Run Complete: [Session Name]
**Started:** YYYY-MM-DD
**Completed:** YYYY-MM-DD
**Total milestones:** N
**Total attempts:** [sum of all milestone attempts]
## Milestone Summary
| Milestone | Status | Attempts | Duration |
|-----------|--------|----------|----------|
| M1: [name] | ✓ completed | 1 | 2h |
| M2: [name] | ✓ completed | 2 | 4h |
| ...
## Final Test Suite
[PASS/FAIL — N passed, M failed]
## Files Changed (Total)
[Aggregated list across all milestones]
- 呈现给用户,并建议使用
simplify进行最后一次代码质量检查
恢复协议
恢复已暂停或中断的会话时:
- 阅读 state.md,确定最后已知状态
- 针对每个里程碑,确定恢复操作:
| 上次状态 | 恢复操作 |
|---|---|
pending | 正常开始 |
planning | 重新开始制定计划(计划文件可能不完整) |
executing | 检查运行计划的进度;继续执行或重新开始 |
validating | 重新开始 review-work(审查可能不完整) |
completed | 跳过(已完成检查点) |
failed | 向用户说明失败情况;询问是重试还是跳过(见下方“跳过规则”) |
skipped | 跳过(用户之前选择跳过此里程碑) |
- 对于处于
executing状态的里程碑:检查计划中的任务是否已勾选。从第一个未勾选的任务继续。 - 从 state.md 中读取
Attempts计数器,确定剩余重试次数。恢复时不要重置计数器——它会在崩溃后保留,以防止无限重试。 - 将恢复计划作为状态报告发布,然后继续。只有当
failed里程碑阻塞执行路径或状态不一致时,才询问用户。
执行中纠正
如果执行过程中发现已完成里程碑的输出有误,或需要新增里程碑:
- 暂停执行——不要继续执行依赖该里程碑的后续里程碑
- 记录发现,在 state.md 的执行日志中说明发现的问题以及触发发现的里程碑
- 需要用户决策: 向用户说明情况和选项:
- 添加纠正里程碑: 创建新的里程碑定义(由用户编写目标和成功标准,或仅针对新范围重新运行 milestone-planning)。将其按适当依赖关系插入 DAG。然后从新里程碑恢复执行。
- 从检查点重新规划: 回退到某个已完成里程碑的检查点,将后续里程碑标记为
pending,并将其Attempts重置为 0,然后从该位置重新开始。 - 中止: 将整体状态设为
failed并停止。
- 新里程碑遵循相同的流程——plan-crafting → run-plan → review-work。即使是“快速修复”,也不能走捷径。
- 绝不修改已完成的里程碑(硬性门槛 #6 仍然适用)。纠正里程碑会通过完整的计划周期生成新文件或覆盖现有文件。
跳过规则
用户选择跳过失败的里程碑时:
- 在 state.md 中将里程碑状态设为
skipped - 在执行日志中记录跳过事件及用户给出的原因
- 默认情况下,被跳过里程碑的依赖项也会被阻塞——与
failed相同。DAG 的约定是:只有前置条件为completed时,依赖项才能运行。 - 用户可以通过确认缺少前置条件,明确解除对依赖项的阻塞:“尽管 M2 已跳过,仍继续执行 M4。”在执行日志中记录此例外。
- 如果用户解除对依赖项的阻塞,在 plan-crafting 期间向该里程碑的 Context Brief 添加备注:“前置条件 M2 已跳过。以下输出缺失:[根据 M2 的成功标准列出]。”
**已跳过的里程碑无法取消跳过。**如果用户希望之后尝试该里程碑,请创建一个目标相同的新里程碑。
时长限制
如果单个里程碑的总活跃时间(从规划开始到审查完成)过长:
- 软限制: 如果里程碑处于
planning或executing状态的时间,明显占整体工作的比例过大,则暂停并向用户报告:“里程碑 M3 已进行较长时间。继续、缩小范围还是中止?” - 尝试次数硬限制: 3 次尝试上限(F1)限制了重试循环。但如果单次尝试的 plan-crafting 生成了 15 个以上的任务,则暂停并报告:“此里程碑的计划包含 N 个任务——对于单个里程碑来说可能过大。请考虑拆分。”
- 目的: 防止单个失控的里程碑耗尽整个执行预算,或因测试不稳定而无限期运行。
上下文窗口管理
长时间运行的会话会达到上下文窗口限制。Claude Code 会自动压缩较早的消息(上下文折叠)。必须设计好执行框架以应对这种情况:
- 绝不要依赖对话记忆来保存状态。 所有状态都保存在磁盘上的
state.md和里程碑文件中。如果上下文被压缩,执行框架会重新读取状态文件,不会丢失任何信息。 - 每个里程碑都是一个全新的上下文边界。 开始为新里程碑制定计划时,工作子 Agent 会从干净的上下文开始。它只会收到里程碑定义和已完成前置里程碑的上下文(见 F8 约定),而不会收到完整的对话历史。
- 检查点文件是唯一可信来源。 如果在里程碑执行期间上下文丢失,恢复时应读取检查点文件,而不是经过压缩的对话摘要。
- 避免累积大量内联状态。 不要在对话中不断汇总所有里程碑。应通过路径引用
state.md和检查点文件。
速率限制处理
长时间运行的会话会遇到速率限制。Claude Code 内置了带指数退避的重试机制(最多重试 10 次,最长退避 5 分钟)。执行框架应配合此机制,而不是与之对抗:
- 让 claude-code 处理临时速率限制。 短暂的 429/529 错误会自动进行退避重试。不要每次遇到 API 错误就提前保存状态。
- 遇到持续的速率限制时保存状态。 如果速率限制持续时间超过自动重试窗口(你会看到反复出现的“rate limit”消息),请立即将当前状态记录到磁盘。
- 在执行日志中记录速率限制事件及其时间戳。
- 向用户报告:“遇到速率限制。状态已保存。准备好后使用
long-run恢复。” - 不要在 claude-code 的内置重试机制之上添加手动重试循环,这会导致重试放大。
- 后台 Agent 中止: Claude Code 的后台 Agent(例如 critic 子 Agent)遇到 529 过载错误时会立即中止,而不是重试。因此,milestone-planning 中的 critic 失败处理(重新分派一次,使用最低可行评审小组)才有必要——critic 失败往往由临时速率限制导致,而不是永久性错误。
反模式
| 反模式 | 失败原因 |
|---|---|
| 不使用 milestone-planning,而是在内联内容中生成里程碑 | 里程碑缺少对抗性评审;分解效果不佳 |
| 因为里程碑“很简单”而跳过 review-work | 未发现的缺陷会在多个里程碑中累积 |
| 里程碑失败后仍继续执行 | 依赖它的里程碑会建立在有问题的基础之上 |
| 阶段之间不更新 state.md | 崩溃会导致进度丢失,无法恢复 |
| 修改已完成的里程碑文件 | 破坏检查点不变性,使评审结果失效 |
| 不使用 worktree 隔离并行运行里程碑 | 文件冲突会破坏两个里程碑 |
| 遇到速率限制时自动重试 | 浪费配额;用户可能更愿意等待 |
| 在里程碑之间暂停以请求批准 | 违背自主执行的初衷——用户在锁定里程碑时已选择完整运行。仅在失败和范围变更时升级处理 |
| 未检查冲突便合并 worktree | 文件重叠时会造成无声的数据丢失 |
| 跳过跨里程碑集成检查 | 里程碑各自通过,但在边界处彼此破坏 |
| 未经用户升级处理便无限重试 E2E 失败 | 设置 2 次尝试上限,是为了避免在误诊问题上浪费预算 |
最小检查清单
- 状态目录存在,且包含有效的 state.md 和里程碑文件
- 已验证依赖 DAG(无环)
- 已确定当前位置(全新开始或恢复进度)
- 在会话开始时和每次阶段转换时发布状态报告
- 每个里程碑都经过 plan-crafting → run-plan → review-work
- 每次阶段转换前后都更新 State.md
- 每个里程碑成功完成后都编写检查点
- 失败的里程碑会阻止其依赖项
- 并行里程碑使用 worktree 隔离
- 每个里程碑完成后都通过跨里程碑集成检查
- 最终 E2E Gate 在完成时通过
- 完成时通过完整测试套件
转换
长期运行完成后:
- 最终代码质量检查 →
simplify技能 - 如果在完成测试中发现问题 →
systematic-debugging技能 - 如果用户想添加更多里程碑 →
milestone-planning技能
此技能本身不会调用下一个技能。它会报告完成情况,并由用户决定下一步。