CC端到端开发skill:心跳、阻塞与续跑机制

前言:这篇文章介绍 fully-coding 的运行时可靠性设计。它通过 heartbeat、任务状态机、blockLog 和 auto-resume,让一次长时间 Claude Code 开发任务在中断后仍能安全恢复。

本博文对应的代码仓库见:(Github)[https://github.com/seedily/claude-coding-skills]

背景

Claude Code 执行复杂任务时,常见风险不是“不会写代码”,而是任务运行时间变长后状态失控。

例如:

  • 任务跑到一半,终端关闭了。
  • 电脑重启,执行状态丢失。
  • 流程遇到需要用户确认的风险,但没有明确记录。
  • 用户重新启动任务,却不知道该从 Step 4 继续,还是从 Step 5 继续。
  • 多个恢复进程同时尝试接管同一个任务,导致重复执行。

fully-coding 用一套心跳与续跑规则处理这些问题。核心文件是 heartbeat-resume-rules.md,核心状态记录在 {ts}-codingLog.md 的 frontmatter 中。

这套机制能成立,前提是每一步都已经按 SDD(Specification-Driven Development,规范驱动开发)的方式落盘。也就是说,规范是第一性产物:当前状态、当前步骤、阻塞原因、恢复入口都不是依赖临时对话记忆,而是写在可读取的文档字段里。

心跳字段

每个任务的 codingLog.md frontmatter 都会维护一组状态字段:

---
type: coding-log-template
status: running
last-heartbeat: 20250615-120530
current-step: 5
current-role: developer
pid: 12345
batch-subtask: false
---

这些字段分别表示:

字段 作用
status 当前任务状态
last-heartbeat 上次心跳时间
current-step 当前执行到第几步
current-role 当前主导角色
pid 当前 Orchestrator 进程标识
batch-subtask 是否为 batch 子任务

其中最关键的是 statuslast-heartbeat。前者说明任务处于什么阶段,后者说明原执行进程是否可能失联。

任务状态机

fully-coding 定义了 7 种任务状态:

状态 含义
running 正在执行
resuming 某个恢复进程正在尝试接管
blocked 遇到阻塞,等待用户确认
stalled 心跳超时,原进程无响应
failed 任务失败且无法继续
planned --plan-only 已完成 Step 1-4,等待用户决定是否继续实现
completed 已完成

状态流转可以用下面的图表示:

stateDiagram-v2 [*] --> running : 新任务启动 / 续跑接管成功 running --> blocked : 遇到阻塞,等待用户确认 running --> stalled : 心跳超时 running --> planned : --plan-only Step 4 完成 running --> completed : Step 9 完成 / --quick-dev Step 7 完成 running --> failed : 任务失败且无法继续 planned --> running : 用户使用 --start-step 5 继续实现 blocked --> running : 用户确认后继续 blocked --> stalled : 阻塞长期未处理 stalled --> resuming : 自动续跑尝试接管 resuming --> running : 原子过渡成功 resuming --> stalled : 原子过渡失败 failed --> resuming : 用户手动重跑 completed --> [*]

这套状态机的重点是避免“误恢复”和“重复恢复”。

为什么需要 resuming 状态

假设某个任务已经 stalled,同时有两个恢复动作被触发:

  • 用户手动执行 /fully-coding --auto-resume
  • 定时任务也执行了 /fully-coding --auto-resume

如果没有 resuming 这个过渡状态,两个进程可能同时认为自己可以接管,然后重复执行同一个步骤。

fully-coding 的做法是:

  1. 恢复前先把状态写成 resuming
  2. 写入当前进程的 pid 和最新 last-heartbeat
  3. 再次读取 frontmatter 确认状态仍属于自己。
  4. 确认成功后,才改为 running 并继续执行。

这相当于一个轻量的原子接管协议。

auto-resume 的判断顺序

续跑不是直接继续,而是按顺序检查。

flowchart TD A[收到 auto-resume / task-id] --> B[确认 codingLog.md 存在] B --> C{status 是 completed?} C -->|是| C1[禁止续跑] C -->|否| D{status 是 planned?} D -->|是| D1[仅允许显式 --start-step 5] D -->|否| E{存在未确认 blockLog?} E -->|是| E1[暂停,等待用户确认] E -->|否| F[检查 pid 和心跳] F --> G{心跳是否超时?} G -->|否| G1[认为原任务仍在运行] G -->|是| H[标记 stalled] H --> I[进入 resuming] I --> J[确认接管成功] J --> K[恢复到 current-step]

这个顺序能避免三类错误:

  • 已完成任务被重复执行。
  • --plan-only 产物未经用户确认就自动进入开发。
  • 阻塞事件未处理就继续往下跑。

planned 状态的特殊性

planned--plan-only 的完成状态。它表示 Step 1-4 已经完成,任务已经生成需求、范围和方案,但还没有修改业务代码。

普通 --auto-resume 不会自动接管 planned 任务。

如果用户确认要继续实现,需要显式执行:

/fully-coding --start-step 5 --task-id {ts}

这个设计很关键。因为 --plan-only 的语义是“先审方案”,不能让自动续跑在用户未确认的情况下进入代码实现。

blockLog 的作用

blockLog.md 不是普通日志,它只在流程必须暂停等待用户确认时创建。

典型情况包括:

  • 3 次自动修复后仍无法解决的 block 级问题。
  • 3 次测试修复后仍失败且无法继续。
  • 破坏性或不可逆操作需要用户决策。
  • 当前角色无法自行修复的步骤失败。

blockLog 的价值是把“为什么停下来”写清楚:

字段 作用
阻塞步骤 哪一步停了
阻塞类型 评审阻塞、测试失败、编译错误、外部依赖缺失等
阻塞原因 为什么不能自动继续
修复建议 用户可以怎么处理
用户确认状态 待确认 / 已确认
用户处理方案 用户最终如何决策

它不是日志堆积,而是一份交接文档。无论是用户接手判断,还是后续自动恢复继续执行,都能先读到明确可见的暂停原因和恢复条件。

什么时候不登记 blockLog

fully-coding 特别强调:不是一有问题就登记 blockLog。

以下情况不登记:

  • Step 6 评审发现问题,但仍在 3 次自动修复循环内。
  • Step 7 测试失败,但仍在 3 次自动修复循环内。
  • Step 6 有条件通过,流程可以继续。

这个规则避免了 blockLog 被普通修复噪音污染。只有真正需要用户确认的中断,才进入 blockLog。

batch 子任务如何隔离

fully-coding-batch 会把一个大需求拆成多个子任务,每个子任务复用 fully-coding 的 Step 3-9。

为了避免独立任务和 batch 子任务互相抢占,codingLog.md 会包含:

batch-subtask: true

独立任务的 --auto-resume 会跳过 batch 子任务。batch 子任务由 fully-coding-batch --auto-resume 统一调度。

这保证了两类任务的恢复边界清晰。

这套机制适合什么场景

心跳和续跑机制特别适合:

  • 长时间执行的企业功能开发。
  • 需要跨多轮自动修复的任务。
  • 会产生多个文档和代码变更的复杂任务。
  • 需要定时自动接管 stalled 任务的场景。
  • batch 串行开发多个子任务的场景。

它尤其适合超长周期编程。因为任务周期越长,越不能只依赖“模型还记得什么”,而要依赖规范化文档把状态、决策和阻塞点固定下来。

它不一定适合很小的一次性任务。对于只改一行配置的小任务,完整状态机可能显得重。

总结

fully-coding 的心跳与续跑机制解决的是“长任务如何不中断、不重复、不失控”的问题。

它的关键设计包括:

  1. 用 frontmatter 保存运行状态。
  2. 用 heartbeat 判断原进程是否失联。
  3. resuming 做原子接管。
  4. planned 保护方案模式不自动进入开发。
  5. blockLog.md 记录真正需要用户确认的阻塞。
  6. batch-subtask 隔离独立任务和批次子任务。

这些机制让 fully-coding 更像一个可恢复的开发状态机,而不是一次性代码生成命令。

posted @ 2026-06-23 19:31  鱼007  阅读(14)  评论(0)    收藏  举报