关于 loop-runner
loop-runner 是用于控制 Agent 编辑与验证循环的技能,以 shell 命令退出码判定是否通过,而非依赖模型自评。它通过确定性限制、运行日志和失败经验记录管理重试与升级。
主要功能
- 01基于 shell 的验证
- 02强制迭代次数与时限
- 03基于状态哈希的停滞检测
- 04人工升级保护条件
- 05JSON 运行日志与失败经验
适用场景
- 01反复修复未通过的测试
- 02在严格停止条件下修复类型或 lint 错误
- 03停止没有进展的重复修改
- 04将未解决的运行升级给人工处理
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ rheinmir/ setup --skill loop-runner安装后在 Claude Code 中输入/loop-runner确认已加载。
详细介绍
技能:loop-runner
内容
目的与背景
- 目的: 驱动一个不会失控的自主修复循环。VERIFY 是一个 shell 命令,其退出码为 0 表示通过(pytest / tsc / lint)——优先于 LLM 自我判断,因为 Agent 无法绕过非 0 退出码强行辩称已完成。终止保护措施是强制性的,且全部具有确定性。
- 触发条件(何时使用):
- Agent 反复执行编辑后检查的循环(修复失败的测试、满足类型检查器或 lint 的要求)。
- 需要确保循环停止:迭代次数有上限、墙钟时间有上限、停滞时停止并升级处理。
- 需要可重放的运行日志和反思经验记录,而不依赖模型自行“判断已完成”。
- 非目标: 不用 LLM 判断“是否完成”;不在配置之外调整保护参数;不自动调用(
disable-model-invocation: true)。
心智模型
PROPOSE(工作区状态)→ VERIFY(shell 退出码)→ GUARDS(max_iter · budget_seconds · no_progress_k · escalate_after_iter)→ REFLEXION(经验记录)→ CRITIQUE → REVISE(隔离的适配器)→ 重复。除 CRITIQUE / REVISE 外,所有步骤都具有确定性。
立即构建 / 后续适配的边界:
- 确定性(现已构建并测试):控制循环、所有保护措施、基于状态哈希的进度检测、运行日志产物、反思。→
harness/scripts/loop-runner.py - 隔离的适配器(
verified: false):LLM 批评 / 修订步骤 + 可调的保护参数。→harness/loop-runner.config.yaml(适配时只编辑这一个文件)。默认修订步骤为空操作 / shell 存根,因此整个循环无需 LLM 即可运行并通过自测。
输入与输出约定
| 字段 | 是否必需? | 含义 | |
|---|---|---|---|
| 输入 | --verify | 是 | shell 命令;退出码为 0 表示通过 |
| 输入 | --config | 否 | 保护参数默认值(harness/loop-runner.config.yaml);CLI 参数会覆盖配置 |
| 输入 | --revise | 否 | shell 命令或实际的 LLM 修订适配器;默认为空操作存根 |
| 输入 | --state | 否 | 状态哈希匹配模式;未提供时,no_progress_k 不启用 |
| 输入 | --log | 否 | 运行日志路径 |
| 输出 | 运行日志 JSON | 是 | 迭代次数、判定结果、终止原因,位于 run_log.path |
| 输出 | 情景经验 | 失败时 | 追加到 reflexion.episodic_memory_page(延迟创建,并包含有效的 frontmatter + ## Origin) |
| 输出 | 退出码 | 是 | 0 SUCCESS · 2 MAX_ITER · 3 TIMEOUT · 4 NO_PROGRESS · 5 ESCALATE |
规则与功能
- RULE-01(必须):VERIFY 具有确定性(退出码)。绝不让 LLM 自行判断“已完成”。
- RULE-02(必须):保护措施是强制性的——绝不能为了“让它完成”而移除其中任何一项。
- RULE-03(必须):隔离的值(保护参数 + 修订钩子)只能存在于配置中。同一个值出现在两个地方就意味着泄漏。
- RULE-04(必须):在
verified: false状态下,应采取故障安全行为:除非符合性验证证明修订猜测正确,否则一律假定其有误。 - RULE-05(必须):自测必须保持通过,且不得写入真实 wiki(其情景经验页面会重定向到临时目录)。
- 功能:运行 shell 命令(verify / revise);计算工作区文件哈希;写入运行日志 + 情景经验 wiki 页面。
失败边界
- VERIFY 退出码为 0 → 成功(SUCCESS,退出码 0)。
- 达到
max_iter→ 失败(MAX_ITER,退出码 2)。 - 超出
budget_seconds→ 失败(TIMEOUT,退出码 3)。 - 状态哈希连续 K 次迭代未变化 → 受阻(NO_PROGRESS,退出码 4)。
- 达到
escalate_after_iter→ 转交给人工处理(ESCALATE,退出码 5)。
用法
主要工作流
| 步骤 | 类型 | 输入 | 操作 | 输出/退出 | 失败/下一步 |
|---|---|---|---|---|---|
| W01 | 确定性 | — | python3 harness/scripts/loop-runner.py selftest(5 个防护场景,不使用大模型) | 绿色 | 红色 → 先修复运行器,然后停止 |
| W02 | 确定性 | 工作区 | PROPOSE — 当前工作区状态 | 状态 | → W03 |
| W03 | 确定性 | --verify | VERIFY — 运行 shell 命令 | 退出码 0 → SUCCESS | 非零 → W04 |
| W04 | 确定性 | 计数器、状态哈希、时钟 | GUARDS — max_iter、budget_seconds、no_progress_k、escalate_after_iter | 继续或终止代码 2/3/4/5 | 终止 → 写入运行日志,然后停止 |
| W05 | 效果 | 判定结果 | REFLEXION — 向情景记忆页面追加一行经验教训 | 经验教训 | → W06 |
| W06 | 判断 | 失败输出 | CRITIQUE → REVISE,通过隔离适配器(大模型、桩或 shell 命令)执行 | 新的工作区状态 | → W02 |
各步骤详情(W01–W06 的事实来源):
如何运行
# self-test — 5 deterministic guard scenarios, no LLM, no deps
python3 harness/scripts/loop-runner.py selftest
# real loop around a verify command (config supplies the guard defaults)
python3 harness/scripts/loop-runner.py run \
--config harness/loop-runner.config.yaml \
--verify "pytest -q" \
--revise "<shell cmd, or the real LLM-revise adapter>" \
--state "src/**" --log harness/out/loop-runner-run.json
CLI 标志会覆盖配置。进程退出码:0 SUCCESS · 2 MAX_ITER · 3 TIMEOUT · 4 NO_PROGRESS · 5 ESCALATE。
循环(一次迭代)
- PROPOSE — 当前工作区状态(初始提案,或上一次迭代的修订结果)。
- VERIFY — 运行 shell 命令;退出码为 0 → 以 SUCCESS 停止。
- GUARDS(每次迭代都会检查,且全部强制执行):
max_iter— 硬性上限(始终启用;不可禁用)。budget_seconds— 墙上时钟时间预算(0 = 关闭)。no_progress_k— 状态哈希连续 K 次迭代未变化 → NO_PROGRESS(未设置state_paths时关闭)。escalate_after_iter— 转交给人工 → ESCALATE(0 = 关闭)。
- REFLEXION — 失败时,向情景记忆维基页面追加一行“经验教训”。
- CRITIQUE → REVISE — 通过隔离适配器(大模型或桩 / shell 命令)执行。然后重复循环。
输出
- 运行日志 JSON(迭代次数、判定结果、终止原因),位于
run_log.path。 - 情景记忆经验教训追加到
reflexion.episodic_memory_page(按需创建,并包含有效的 frontmatter 和## Origin)。
分支
| ID | 类型 | 守卫条件 | 行为 | 跳过 / 失败 | 重新汇合 |
|---|---|---|---|---|---|
| B01 | 能力可选 | 提供了 --state / state_paths | 启用 no_progress_k 状态哈希停滞检测 | 未提供 → 守卫关闭 | W04 |
| B02 | 用户可选 | budget_seconds 或 escalate_after_iter > 0 | 执行墙上时钟时间预算 / 人工升级 | 0 → 关闭(max_iter 始终启用) | W04 |
| B03 | 能力可选 | 已接入真实的大模型修订适配器 | W06 使用大模型;verified: false → 安全失败(RULE-04) | 未接入 → 无操作 / shell 桩 | W02 |
验证与停止
停止与否只由退出码和守卫决定,绝不由模型决定。max_iter 不可禁用,因此每次运行都会终止。Selftest 必须始终通过,且不得向实际维基写入内容。
示例
- 正向:
run --verify "pytest -q" --state "src/**",修订操作在第 2 次迭代修复失败的测试 → VERIFY 退出码为 0 → SUCCESS,进程退出码为 0,运行日志列出 2 次迭代。 - 边界/失败: 修订桩始终不修改
src/**下的文件,no_progress_k=2→ 连续 2 次迭代状态哈希相同 → NO_PROGRESS,退出码为 4,并追加经验教训;模型无法声称任务已完成。
评论
支持 Markdown