Harness 是一个长时间运行智能体框架(Long-Running Agent Framework),提供可执行协议,使任意智能体任务能够跨多个会话持续运行,并具备自动进度恢复、任务依赖解析、失败回滚和标准化错误处理能力。
用途 Harness 适用于需要多会话自主智能体工作的场景,尤其是需要进度检查点、失败恢复和任务依赖管理的任务。它通过结构化协议让智能体在上下文窗口重置后仍能恢复工作。
设计原则
- 为智能体而非人类设计:测试输出、文档和任务结构是智能体的主要接口。
- 进度文件即上下文:当上下文窗口重置时,进度文件加 git 历史等于完整恢复。
- 过早完成是头号失败模式:带明确完成标准的结构化任务列表可防止过早宣告胜利。
- 一切标准化且可 grep:ERROR 在同一行、结构化时间戳、一致前缀。
- 快速反馈循环:预计算统计,在完整验证前运行冒烟测试。
- 一切幂等:初始化脚本、任务执行、环境设置都必须可安全重跑。
- 失败安全而非静默失败:每个失败都必须有明确的恢复策略。
命令 /harness init <project-path> # 在项目中初始化 harness 文件 /harness run # 启动/恢复无限循环 /harness status # 显示当前进度和统计 /harness add "task description" # 向列表添加任务
激活标记 仅当 harness 根目录(与 harness-tasks.json 同目录)存在 .harness-active 标记文件时,钩子才生效。/harness init 和 /harness run 必须创建该标记:touch <project-path>/.harness-active。当所有任务完成(无 pending/in_progress/retryable 剩余)时移除它:rm <project-path>/.harness-active。没有该标记时,所有钩子均为空操作,立即退出 0。
进度持久化(双文件系统) 在项目工作目录维护两个文件:
- harness-progress.txt(仅追加日志):跨会话记录所有智能体动作的自由文本日志,永不截断。示例条目包含时间戳、SESSION 编号、INIT、LOCK、Starting、CHECKPOINT、Completed、ERROR、ROLLBACK、STATS 等类型。
- harness-tasks.json(结构化状态):包含 version、created、session_config(concurrency_mode、max_tasks_per_session、max_sessions)、tasks 数组(每个任务含 id、title、status、priority、depends_on、attempts、max_attempts、started_at_commit、validation、on_failure、error_log、checkpoints、completed_at)、session_count、last_session。 任务状态:pending → in_progress(瞬态,仅在活跃执行期间设置)→ completed 或 failed。会话开始时发现 in_progress 任务意味着上一会话被中断,需通过上下文窗口恢复协议处理。并发模式下任务还可能带有 claim 元数据:claimed_by 和 lease_expires_at。 会话边界:会话从智能体开始执行会话启动协议时开始,到满足停止条件或上下文窗口重置时结束。每个会话获得唯一 SESSION-N 标识符。
并发控制 在修改 harness-tasks.json 前,使用可移植的 mkdir 获取独占锁(在所有 POSIX 系统上原子,macOS 和 Linux 均可用)。锁键必须稳定,即使从子目录调用。脚本会向上搜索包含 harness-tasks.json 的根目录,计算路径哈希,在 /tmp 下创建锁目录,检查锁持有者是否存活,并处理陈旧锁。记录锁获取与释放日志。 模式:
- 独占(默认):整个会话持有锁,第二个会话快速失败。
- 并发(通过 session_config.concurrency_mode: "concurrent" 选择加入):仅作为状态事务锁,在读取/修改/写入 harness-tasks.json 及追加 harness-progress.txt 时持有,实际工作前立即释放。 并发模式不变量:所有 worker 必须指向同一状态根;任务选择是建议性的,真正关卡是锁下的原子认领;绝不在同一 git 工作目录运行两个 worker,应使用独立 worktree/clone。
无限循环协议 会话启动(每次执行):读取状态(harness-progress.txt 最后 200 行 + 完整 harness-tasks.json)、读取 git(git log --oneline -20 和 git diff --stat)、获取锁、恢复中断任务、健康检查(运行 harness-init.sh)、跟踪会话(递增 session_count,检查 max_sessions)、选择下一个任务。
任务选择算法 选择前运行依赖验证:循环检测(传递遍历 depends_on,发现循环则标记失败)、阻塞传播(依赖失败且永不重试的任务标记为失败)。然后按优先级选择:pending 且所有依赖完成的任务(按 P0>P1>P2 再按 id);failed 且 attempts < max_attempts 且所有依赖完成的任务(按优先级再按最早失败)。若无合格任务则记录最终 STATS 并停止。
任务执行循环 每个任务执行精确序列:认领(原子,锁下,记录 started_at_commit,设置 in_progress、claimed_by、lease_expires_at)、带检查点执行(记录 CHECKPOINT 并追加到 checkpoints 数组)、验证(运行 validation.command,带超时包装;若为空则记录 ERROR 并停止)、记录结果(成功则 completed 并 git commit;失败则递增 attempts、回滚 git reset --hard 和 git clean -fd、执行 cleanup、记录 ERROR、设置 failed)、跟踪(递增每会话任务计数器)、继续(立即选择下一任务)。
停止条件 所有任务完成;所有剩余任务在 max_attempts 失败或被失败依赖阻塞;达到 max_tasks_per_session;达到 max_sessions;用户中断。
上下文窗口恢复协议 新会话发现 status: "in_progress" 任务时:独占模式视为中断会话并运行恢复协议;并发模式仅在 claimed_by 匹配本 worker 或 lease_expires_at 已过期时恢复。检查 git 状态(git diff --stat、git log --oneline -5、git stash list)、检查检查点,然后按决策矩阵行动(无未提交/无近期任务提交/无检查点 → 标记失败;无/无/有 → 验证文件状态;无/有/任意 → 运行验证;有/无/任意 → 带未提交更改运行验证;有/有/任意 → 提交未提交更改并运行验证)。记录恢复日志。
错误处理与恢复策略 每个错误类别有默认恢复策略:ENV_SETUP(重跑 init,仍失败则停止)、CONFIG(停止,需人工修复)、TASK_EXEC(回滚并重试)、TEST_FAIL(回滚并重试)、TIMEOUT(终止进程、执行清理、重试)、DEPENDENCY(跳过任务、标记阻塞)、SESSION_TIMEOUT(使用上下文窗口恢复协议)。JSON 损坏:检查 harness-tasks.json.bak,有效则恢复,否则记录 ERROR 并停止。备份协议:每次写入前复制当前文件到 .bak,原子写入(写 .tmp 再 mv)。
环境初始化 若项目根存在 harness-init.sh,每次会话启动时运行,脚本必须幂等。示例脚本包含 npm install 或 pip install、数据库可达性检查、冒烟测试。
标准化日志格式 所有日志条目使用单行、可 grep 格式:[ISO-timestamp] [SESSION-N] <TYPE> [task-id]? ...