Source Reading 011 · The Governor源码精读 011 · 调速器

HUMANIZE

A Claude Code plugin that wraps an AI agent in a shell-hook control loop and hands the brakes to an independent reviewer. Read line by line against the real source.一个 Claude Code 插件: 用 shell 钩子把 AI agent 关进一个控制回路, 再把刹车交给一个独立的审查者。 对着真实源码逐行读。

Repository仓库
What it is是什么
iterative-dev plugin迭代开发插件
Language语言
Bash · jq · Python
Reviewed by审查者
codex CLI · gpt-5.5
Enforced by靠什么强制
7 lifecycle hooks7 个生命周期钩子
Commit提交
0ec921a · v1.16.0
§ 00 — Prologue§ 00 — 序章

A plugin that won't let you stop一个不让你停下来的插件

Almost every coding-agent tool is built to help the model do more. Humanize is built to stop the model from quitting too early. That inversion is the whole idea, and it is worth understanding because it is the same problem we face when we point agents at long-horizon kernel optimization.几乎所有 coding agent 工具的设计目标都是让模型多干点。 Humanize 反过来: 它的目标是不让模型太早收工。 这个反转就是它的全部立意—— 也正是我们让 agent 去做长周期 kernel 优化时撞上的同一个问题, 所以值得读懂。

The pitch in the README is plain: Claude implements a plan, an independent codex process reviews the work, and issues feed back into implementation until the work is genuinely done. The authors call the loop RLCR — “Ralph-Loop with Codex Review,” which they note also reads as “Reinforcement Learning with Code Review.” What the README does not advertise is the mechanism: there is no daemon, no orchestrator process, no agent framework. The entire loop is implemented as Claude Code lifecycle hooks — shell scripts the harness runs at fixed moments — and a pile of state files in a timestamped directory.README 的卖点很直白: Claude 实现一份计划, 一个独立的 codex 进程审查产出, 发现的问题再喂回实现阶段, 直到活儿真正干完。 作者把这个循环叫 RLCR—— “Ralph-Loop with Codex Review”, 他们还说这也能读成 “Reinforcement Learning with Code Review”。 README 没怎么宣传的是它的机制: 没有常驻进程、 没有编排器、 没有 agent 框架。 整个循环是用 Claude Code 的生命周期钩子实现的—— 也就是 harness 在固定时刻执行的 shell 脚本—— 外加一堆放在带时间戳目录里的状态文件。

That makes it an unusually good source-reading subject. The cleverness is not in any single algorithm; it is in how a handful of `exit 2`s and atomic `mv`s combine into something that behaves like a controller with a setpoint and a circuit breaker. I read the loaded files at commit 0ec921a: the 2,221-line Stop hook, the 1,578-line shared library, the 1,541-line setup script, the validators, the command prompts, and the agent definitions. Everything below cites the real lines.这让它成了一个特别好的源码精读对象。 它的妙处不在某一个算法, 而在于一把 `exit 2` 和原子 `mv` 怎么拼成了一个行为上带设定点和断路器的控制器。 我读的是提交 0ec921a 的核心文件: 2221 行的 Stop 钩子、 1578 行的共享库、 1541 行的安装脚本、 那些校验器、 命令提示词、 还有 agent 定义。 下面每一处都引用真实行号。

How to read this怎么读这篇

Filenames are clickable and point at the pinned commit on GitHub with line fragments. If a claim has a number in it (“2,221 lines,” “blocks at 3 consecutive stalls”), it came from the file, not from memory. The toggle in the top-right switches the whole page between English and Chinese.文件名都可点, 指向 GitHub 上钉死的那个提交, 带行号片段。 凡是带数字的论断(“2221 行”、“连续停滞 3 次就熔断”)都来自文件本身, 不是凭记忆。 右上角的开关把整页在中英文之间切换。

§ 01 — Architecture§ 01 — 架构

One agent, seven hooks, zero daemons一个 agent, 七个钩子, 零个常驻进程

Start from the question that decides the whole design: how do you make a stateless agent run a multi-round loop without a process to hold the loop? Claude Code runs one turn at a time. When the model decides it is finished, the turn ends. There is no “while” anywhere for a plugin to hook into.先从决定整个设计的那个问题出发: 在没有进程托管循环的情况下, 你怎么让一个无状态的 agent 跑一个多轮循环? Claude Code 一次只跑一个回合。 模型觉得自己干完了, 回合就结束。 哪里都没有一个 “while” 让插件去挂。

Humanize's answer is to hijack the one moment the harness gives back control: the Stop hook, which fires when the model tries to end its turn. The Stop hook runs Codex, decides whether the work is acceptable, and if not, returns a JSON verdict that blocks the stop and injects the next instruction. The model never gets to leave. The “loop” is just the same Stop hook firing again and again, each time reading a state file to know where it is.Humanize 的答案是劫持 harness 唯一交还控制权的那一刻: Stop 钩子—— 模型试图结束回合时触发的钩子。 Stop 钩子跑一遍 Codex, 判断产出能不能接受, 不能的话就返回一个 JSON 裁决, 挡住这次停止并注入下一条指令。 模型根本走不掉。 所谓 “循环”, 不过是同一个 Stop 钩子一次又一次地触发, 每次读一个状态文件来知道自己走到哪了。

Plate Ithe hook-governed loop被钩子治理的循环
PLATE I · THE MACHINE USER CLAUDE implements the plan, one turn at a time STOP HOOK loop-codex-stop-hook.sh 2,221 lines · the engine stops? exit 2 — block & feed the review back in CODEX codex exec · codex review the independent eye spawn PRE / POST / PROMPT HOOKS validators gate every tool call Write · Edit · Read · Bash WORKING TREE + GIT only allowed calls pass through .humanize/rlcr/<timestamp>/ state.md · finalize-state.md · complete-state.md (the phase, encoded as a filename) round-N-prompt.md · round-N-summary.md · round-N-review-result.md · goal-tracker.md · plan.md read · atomic mv setup writes
The model sits inside a membrane of hooks. Tool calls are filtered on the way out; the exit is intercepted and turned into a Codex review; the verdict either lets the turn end or blocks it and re-prompts. The only durable state is a directory of markdown files named by timestamp.模型坐在一层钩子膜里面。 工具调用在出门时被过滤; 退出被拦截、 变成一次 Codex 审查; 裁决要么放回合走、 要么挡住它并重新下指令。 唯一持久的状态, 是一个按时间戳命名的 markdown 文件目录。

The hook surface is declared once, in hooks/hooks.json. Seven hooks across four lifecycle events. Note the Stop hook's timeout: 7200 — two hours — because a single review round can legitimately run a full Codex pass at high reasoning effort.钩子面只声明一次, 在 hooks/hooks.json 里。 四个生命周期事件上挂了七个钩子。 注意 Stop 钩子的 timeout: 7200—— 两小时—— 因为单独一轮审查在高推理强度下跑完一整趟 Codex 是合理的。

Event事件 Matcher匹配 Script脚本 Job职责
UserPromptSubmitloop-plan-file-validator.shblock prompts that switch branch or dirty the plan挡住切分支或弄脏计划的提示
PreToolUseWrite/Edit/Readloop-{write,edit,read}-validator.shprotect state files, enforce round + phase rules保护状态文件, 强制轮次 + 阶段规则
PreToolUseBashloop-bash-validator.shthe heavyweight: deny dangerous commands, block forged exits最重的一个: 拦危险命令、 挡伪造的退出
PostToolUseBashloop-post-bash-hook.shone-shot: record the Claude session_id into state一次性: 把 Claude 的 session_id 记进状态
Stoploop-codex-stop-hook.shthe engine: review, decide, advance or terminate引擎: 审查、 决断、 推进或终止
Why this is the right shape为什么这个形状是对的

A daemon would have to track the session, survive crashes, and reconcile with the harness. By putting the whole controller in the Stop hook and the whole state on disk, Humanize gets crash-safety for free: if anything dies, the next Stop just re-reads the files and continues. This is the same reason robust kernel-search harnesses checkpoint every variant to disk instead of holding the search in a long-lived process — the loop should be reconstructable from durable state, not from a process's memory.常驻进程得跟踪会话、 扛住崩溃、 还要和 harness 对账。 Humanize 把整个控制器塞进 Stop 钩子、 把整个状态放到磁盘上, 于是白捡了崩溃安全性: 任何东西挂了, 下一次 Stop 重新读文件接着跑就行。 这跟稳健的 kernel 搜索 harness 把每个变体都 checkpoint 到磁盘、 而不是把搜索攥在一个长生命周期进程里, 是同一个道理—— 循环应该能从持久状态重建, 而不是从某个进程的内存里。

§ 02 — Protocol§ 02 — 协议

How a shell script talks back to the model一个 shell 脚本怎么回话给模型

A hook is a program. The harness pipes it a JSON blob on stdin describing the event, and reads two channels back: the process exit code, and anything the process prints. Humanize uses two different reply protocols depending on the event, and the difference matters.钩子就是个程序。 Harness 从 stdin 把一段描述事件的 JSON 喂给它, 再从两个通道读回结果: 进程退出码, 以及进程打印的任何东西。 Humanize 根据事件用了两种不同的回话协议, 而这个区别很关键。

The PreToolUse validators speak in exit codes: exit 0 allows the tool call, exit 2 blocks it and feeds whatever they printed to stderr back to the model as the block reason, and exit 1 is a hard error. The Stop and UserPromptSubmit hooks speak in a richer JSON-on-stdout protocol, because they need to inject a multi-paragraph instruction, not just a one-line reason:PreToolUse 校验器用退出码说话: exit 0 放行工具调用, exit 2 拦下它、 并把它打到 stderr 的内容当作拦截理由喂回模型, exit 1 是硬错误。 Stop 和 UserPromptSubmit 钩子则用一种更丰富的 stdout-JSON 协议, 因为它们要注入的是一整段多段落指令, 而不只是一行理由:

loop-codex-stop-hook.sh · the block verdictL2212–2221 ↗
# block the stop, hand the model its next round of work
jq -n \
    --arg reason "$(cat "$NEXT_PROMPT_FILE")" \
    --arg msg "$SYSTEM_MSG" \
    '{
        "decision": "block",
        "reason": $reason,
        "systemMessage": $msg
    }'
exit 0

Two details repay attention. First, the hook exit 0s even while blocking — the “block” lives in the JSON decision field, not in the exit code, which is the Stop-hook spec. Second, the entire next-round prompt is loaded from a file with $(cat ...) and passed through jq --arg, so newlines and quotes are escaped correctly. A surprising amount of this codebase is careful JSON escaping, because the “reason” field is the only wire back to the model and a botched escape would corrupt the instruction.两个细节值得留意。 第一, 钩子在拦截时仍然 exit 0—— “拦截” 写在 JSON 的 decision 字段里、 而不在退出码里, 这是 Stop 钩子的规范。 第二, 整段下一轮提示是用 $(cat ...) 从文件读进来、 再经 jq --arg 传递的, 于是换行和引号都被正确转义。 这个代码库里有出奇多的精心 JSON 转义, 因为 “reason” 字段是回到模型的唯一一根线, 一个搞砸的转义就会把指令弄坏。

“Am I even in a loop?”“我到底在不在循环里?”

Every hook fires on every session, loop or not. So the first thing each one does is ask whether an RLCR loop is active for this session, and bail out silently if not. There is no boolean flag for “in a loop” — the presence of an active state file in a session-matched directory is the flag.每个钩子在每一个会话上都会触发, 不管在不在循环里。 所以每个钩子做的第一件事, 就是问一句: 这个会话现在有没有一个活跃的 RLCR 循环; 没有就悄悄退出。 没有什么 “在循环中” 的布尔标志—— 在一个会话匹配的目录里存在一个活跃状态文件, 本身就是那个标志。

loop-codex-stop-hook.sh · fail-open when there is no loopL62–69 ↗
HOOK_SESSION_ID=$(extract_session_id "$HOOK_INPUT")
LOOP_DIR=$(find_active_loop "$LOOP_BASE_DIR" "$HOOK_SESSION_ID" true)

# If no active loop (or session_id mismatch), allow exit
if [[ -z "$LOOP_DIR" ]]; then
    exit 0
fi
Fail-open vs fail-closed, chosen on purpose故意区分的 fail-open 与 fail-closed

The split is deliberate and consistent. No active loop → fail open (exit 0), so the plugin is completely invisible during normal work. But a malformed state file, a git timeout, an unresolved symlink, or the post-signoff “methodology” phase → fail closed (block). The rule of thumb: when you are not sure you are governing anything, get out of the way; when you know you are governing and something is wrong, stop everything.这个区分是刻意且一致的。 没有活跃循环 → fail openexit 0), 于是插件在日常工作里完全隐形。 但状态文件损坏、 git 超时、 符号链接解析不了、 或者签收后的 “方法论” 阶段 → fail closed(拦截)。 经验法则: 不确定自己在治理什么时, 让开; 确定在治理、 又发现不对劲时, 全停。

§ 03 — State machine§ 03 — 状态机

The phase is the filename阶段就是文件名

Here is the idea I keep coming back to. The loop has phases — implementation, code review, finalize, a post-mortem “methodology” pass, and several terminal states. You would expect a phase: field somewhere. There isn't one. The phase is encoded in which state file exists, and every phase transition is a single mv.这就是我反复回味的那个点。 循环有好几个阶段—— 实现、 代码审查、 收尾、 一个事后 “方法论” 复盘、 还有几个终态。 你会以为某处有个 phase: 字段。 没有。 阶段被编码进哪个状态文件存在, 而每一次阶段转换都是一次 mv

loop-common.sh · resolve_active_state_file (the phase decoder)L268–280 ↗
# precedence: most-specific phase wins
if   [[ -f "$loop_dir/methodology-analysis-state.md" ]]; then echo "…/methodology-analysis-state.md"
elif [[ -f "$loop_dir/finalize-state.md" ]];            then echo "…/finalize-state.md"
elif [[ -f "$loop_dir/state.md" ]];                     then echo "…/state.md"
else echo ""; fi

Implementation and code review share the same file, state.md; the difference between them is a single boolean field, review_started, flipped in place. Everything coarser — finalize, methodology, and the terminal states complete- / cancel- / maxiter- / stop- / unexpected-state.md — is a rename. The constants are declared once as readonly in loop-common.sh:24–76.实现阶段和代码审查阶段共用同一个文件 state.md; 它们的区别只是一个布尔字段 review_started, 就地翻转。 所有更粗粒度的东西—— 收尾、 方法论、 以及终态 complete- / cancel- / maxiter- / stop- / unexpected-state.md—— 都是一次重命名。 这些常量在 loop-common.sh:24–76 里作为 readonly 声明一次。

Plate IIstate transitions = atomic renames状态转换 = 原子重命名
PLATE II · THE FILENAME IS THE PHASE setup-rlcr-loop.sh writes round 0 state.md IMPLEMENTATION review_started = false issues → current_round++ (sed in place) state.md CODE REVIEW review_started = true · same file Codex ⊢ COMPLETE · field flip [P0-9]→ round++ finalize-state.md simplify · commit · sign off mv · clean methodology-analysis -state.md · optional post-mortem retrospective if enabled complete-state.md ✓ terminal · preserved for forensics mv · done TERMINAL (mv) cancel-state.md maxiter-state.md stop-state.md unexpected-state.md circuit breaker / cancel / corrupt
Every edge labeled mv is a single atomic rename; the only in-place edits are the review_started flip and the sed that bumps the round counter. Because a phase change is one rename, it is crash-safe: there is no window where two phase booleans disagree, and a killed process leaves the directory in a valid state.每一条标着 mv 的边都是一次原子重命名; 唯二的就地修改是 review_started 的翻转、 和把轮次计数器加一的那次 sed。 因为一次阶段变化就是一次重命名, 它是崩溃安全的: 不存在两个阶段布尔量互相矛盾的时间窗, 进程被杀也只会让目录停在一个合法状态上。

The atomic-rename discipline shows up everywhere state changes. In-place field updates never write the file directly; they write a PID-suffixed temp and mv over the original, so a concurrent reader can never see a half-written file:这种原子重命名的纪律出现在每一处状态变化里。 就地更新字段从不直接写文件; 它们写一个带 PID 后缀的临时文件、 再 mv 盖回原文件, 于是并发的读者永远看不到一个写了一半的文件:

loop-codex-stop-hook.sh · bump the round counter, atomicallyL1502–1505 ↗
local temp_file="${STATE_FILE}.tmp.$$"
sed "s/^current_round: .*/current_round: $round/" "$STATE_FILE" > "$temp_file"
mv "$temp_file" "$STATE_FILE"
State file状态文件 Meaning含义 Created by由谁创建
state.mdactive loop; review_started picks impl vs review活跃循环; review_started 决定实现还是审查setup-rlcr-loop.sh:880
finalize-state.mdreview passed; simplify + sign off审查通过; 简化 + 签收stop-hook:1325
methodology-…-state.mdoptional post-mortem; near-total lockdown可选事后复盘; 近乎全锁methodology lib方法论库
complete-state.mdsuccess, preserved (renamed, not deleted)成功, 保留(重命名而非删除)stop-hook:988
cancel / maxiter / stop / unexpectedterminal exits; the loop simply vanishes next Stop终止退出; 下一次 Stop 时循环直接消失end_loop()
§ 04 — The gauntlet§ 04 — 关卡

A dozen cheap gates before one expensive review一打廉价关卡, 挡在一次昂贵审查前面

When the model tries to stop, the hook does not call Codex right away. Codex is slow and costs money, so the hook first runs a long ladder of cheap, local checks. Each one can block the stop on its own, and each block carries a specific templated instruction telling the model exactly what to fix. Only if all of them pass does the hook spend a Codex call.模型试图停下时, 钩子不会立刻叫 Codex。 Codex 又慢又花钱, 所以钩子先跑一长串廉价的本地检查。 每一个都能自己挡下这次停止, 而且每次拦截都带着一条具体的模板化指令, 明确告诉模型该修什么。 只有全部通过, 钩子才会花一次 Codex 调用。

Plate IIIthe pre-review funnel审查前的漏斗
PLATE III · THE STOP-HOOK GAUNTLET 01 · session active & schema current 02 · branch == start_branch 03 · plan file unchanged vs backup 04 · all todos / tasks complete 05 · git status readable (else fail-closed) 06 · no source file > 2000 lines 07 · working tree clean (& pushed) 08 · round summary written 09 · round contract written (anti-drift) 10 · BitLesson Delta present 11 · goal tracker filled (round 0) 12 · under max iterations IF ANY GATE FAILS → exit 0 with { "decision": "block", "reason": … } the model receives ONE specific, templated fix instruction (rendered from prompt-template/), then the turn restarts — no Codex call is spent. Cheap, deterministic checks catch the easy mistakes so the expensive reviewer only sees committed, summarized work. ALL PASS → RUN CODEX
The order is roughly cheapest-and-most-fundamental first. Notice gate 06: any tracked or new source file over 2,000 lines blocks the loop until it is split. The plugin has opinions, and it enforces them before it ever asks the reviewer.顺序大致是越便宜越根本的越靠前。 注意第 06 关: 任何被跟踪或新建的源文件超过 2000 行, 都会卡住循环直到它被拆分。 这个插件是有主见的, 而且它在开口问审查者之前就把这些主见强制了。

The large-file gate is a good window into the house style — opinionated, but careful. It walks the cached git status, resolves each path against the project root (the hook may run from a different working directory), skips deleted files, classifies by extension, and only then counts lines:大文件这道关是观察其代码风格的好窗口—— 有主见, 但很小心。 它遍历缓存下来的 git status, 把每个路径对着项目根解析(钩子可能从别的工作目录运行), 跳过已删除的文件, 按扩展名分类, 然后才数行数:

loop-codex-stop-hook.sh · the “split your files” gateL524–603 ↗
MAX_LINES=2000
# … per file in `git status --porcelain`:
line_count=$(wc -l < "$filename" 2>/dev/null | tr -d ' ') || continue
[[ "$line_count" =~ ^[0-9]+$ ]] || continue          # numeric guard
if [ "$line_count" -gt "$MAX_LINES" ]; then
    LARGE_FILES="...- \`${filename}\`: ${line_count} lines"
fi
# … block: "Split these into smaller modules before continuing."
The block is the curriculum拦截本身就是课程

Each gate's block message is a small lesson: commit your work, split that file, write your summary, fill the goal tracker. The loop never just says “no.” It says no and hands over the next correct action. For a kernel-optimization agent this is the template I want — a failed compile or a slow benchmark should not end the turn, it should re-enter with the exact next experiment to try.每道关的拦截消息都是一节小课: 提交你的工作、 拆掉那个文件、 写你的总结、 填好目标追踪表。 这个循环从不只说 “不行”。 它说不行、 并且把下一个正确动作递过来。 对一个 kernel 优化 agent, 这正是我想要的模板—— 一次编译失败或一个慢 benchmark 不该结束回合, 而该带着确切的下一个实验重新进来。

§ 05 — The reviewer§ 05 — 审查者

Codex, the outside eyeCodex, 外部之眼

The whole premise is that an agent reviewing its own work has blind spots, so the reviewer is a different model in a different process: the codex CLI, defaulting to gpt-5.5 at high reasoning effort. It runs in two distinct modes depending on phase.整个前提是: 一个 agent 审查自己的产出会有盲区, 所以审查者是另一个进程里的另一个模型codex CLI, 默认 gpt-5.5、 高推理强度。 它按阶段分两种模式运行。

In implementation phase, codex exec reads Claude's prose summary of the round and decides whether the work is plausibly complete. In review phase, codex review --base <commit> reads the actual diff and grades it, tagging findings with severity markers [P0][P9]. The loop only finalizes when a review comes back with no [P0-9] markers at all.实现阶段codex exec 读 Claude 这一轮的散文总结, 判断活儿是不是大概率干完了。 在审查阶段codex review --base <commit> 读真正的diff 并打分, 给发现标上严重度标记 [P0][P9]。 只有当一次审查回来完全没有 [P0-9] 标记时, 循环才收尾。

Markers on their own line必须独占一行的标记

Codex signals “done” by ending its review with the bare word COMPLETE, or asks to halt with STOP. The parsing is strict on purpose: it takes the last non-empty line, trims it, and requires an exact match — so a sentence like “I cannot mark this COMPLETE” never trips the completion path.Codex 用以单独一个词 COMPLETE 结尾来表示 “完成”, 或用 STOP 请求中止。 解析故意很严: 取最后一个非空行、 trim、 要求精确相等—— 于是像 “我不能把它标成 COMPLETE” 这样的句子永远不会触发完成路径。

loop-codex-stop-hook.sh · strict marker matchL1811–1815 ↗
# The word must be on its own line to avoid false positives like "CANNOT COMPLETE"
LAST_LINE=$(echo "$REVIEW_CONTENT" | grep -v '^[[:space:]]*$' | tail -1)
LAST_LINE_TRIMMED=$(echo "$LAST_LINE" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')

A subtle asymmetry: in review phase, a Codex COMPLETE is ignored. Only the absence of [P0-9] issues moves the loop to finalize (stop-hook:1866). The reviewer is allowed to say “looks done” about a summary, but it is not allowed to talk its way out of a clean diff — the diff has to actually be clean.一个微妙的不对称: 在审查阶段, Codex 说 COMPLETE 会被忽略。 只有 [P0-9] 问题的消失才把循环推进到收尾(stop-hook:1866)。 审查者可以对一份总结说 “看着像完成了”, 但它不能靠嘴皮子绕过一个干净的 diff—— diff 必须真的干净。

Two small but load-bearing tricks两个不起眼却关键的把戏

Pin the base commit, not the branch. Code review diffs against BASE_COMMIT — a SHA captured at loop start — rather than BASE_BRANCH. If you are working directly on main, the branch ref advances with every commit you make, so diffing against the live branch would show nothing. Freezing the SHA freezes the review baseline.钉住基线提交, 而不是分支。 代码审查是对着 BASE_COMMIT 做 diff—— 一个在循环开始时抓下来的 SHA—— 而不是 BASE_BRANCH。 如果你直接在 main 上干活, 分支 ref 会随你每次提交往前走, 于是对着活分支做 diff 会什么都看不到。 把 SHA 冻住, 就把审查基线冻住了。

loop-codex-stop-hook.sh · why a fixed SHAL1214–1221 ↗
# Using the fixed commit SHA prevents comparing a branch to itself when
# working on main, as the branch ref advances with each commit but the
# captured SHA stays fixed
local review_base="${BASE_COMMIT:-$BASE_BRANCH}"

Disable the reviewer's own hooks. Codex is itself a hooked CLI. If a Codex review triggered Codex's own Stop hook, you could get recursion. Humanize passes --disable codex_hooks — but only after probing codex --help to confirm the flag exists, caching the answer so older Codex builds don't choke on an unknown argument.关掉审查者自己的钩子。 Codex 本身也是个带钩子的 CLI。 如果一次 Codex 审查触发了 Codex 自己的 Stop 钩子, 就可能递归。 Humanize 传 --disable codex_hooks—— 但只在探测过 codex --help 确认这个 flag 存在之后才传, 并把结果缓存起来, 免得老版本 Codex 被一个未知参数噎住。

loop-codex-stop-hook.sh · capability probe, cached per loopL1172–1181 ↗
CODEX_DISABLE_HOOKS_ARGS=()
_CODEX_FEATURE_CACHE="$CACHE_DIR/.codex-disable-hooks-supported"
if [[ -f "$_CODEX_FEATURE_CACHE" ]]; then
    [[ "$(cat "$_CODEX_FEATURE_CACHE")" == "yes" ]] && CODEX_DISABLE_HOOKS_ARGS=(--disable codex_hooks)
elif codex --help 2>&1 | grep -q -- '--disable'; then
    CODEX_DISABLE_HOOKS_ARGS=(--disable codex_hooks)
    echo "yes" > "$_CODEX_FEATURE_CACHE" 2>/dev/null
else
    echo "no" > "$_CODEX_FEATURE_CACHE" 2>/dev/null
fi

One more policy worth flagging: a Codex review that fails (non-zero exit, empty output, missing result file) is treated as a blocking error, not a reason to skip ahead. The review phase cannot be skipped — the loop must keep retrying until a review actually completes and comes back clean (block_review_failure). The reviewer is not a suggestion; it is a required gate.还有一条策略值得点出: 一次失败的 Codex 审查(非零退出、 空输出、 结果文件缺失)被当成阻塞性错误, 而不是跳过的理由。 审查阶段不能被跳过—— 循环必须一直重试, 直到一次审查真正跑完并干净返回(block_review_failure)。 审查者不是个建议; 它是个必过的关。

§ 06 — The control loop§ 06 — 控制回路

It is a controller, and it has a circuit breaker它是个控制器, 而且带断路器

Read the comments and the control-systems metaphor is not mine, it is theirs. Line 1035 labels accumulated commit history the “Integral component.” The usage doc calls the loop “an amplifier.” There is a function named stop_for_mainline_drift and log lines that print CIRCUIT BREAKER TRIGGERED. Once you see it, the whole engine reads like a feedback controller.读读注释, 这个控制系统的比喻不是我安的, 是他们自己的。 1035 行把累积的提交历史标成 “Integral component”。 使用文档把这个循环叫 “放大器”。 有个函数叫 stop_for_mainline_drift, 还有日志会打 CIRCUIT BREAKER TRIGGERED。 一旦看出来, 整个引擎读起来就是个反馈控制器。

Plate IVthe RLCR loop as a feedback controller把 RLCR 循环看成反馈控制器
PLATE IV · THE LOOP IS A CONTROLLER SETPOINT all ACs met · zero [P0-9] CONTROLLER · STOP HOOK P · present — this round's [P0-9] I · past — commit history fed back D · trend — ADVANCED/STALLED/REGRESSED error PLANT · CLAUDE implements the change actuate OUTPUT · diff the working tree SENSOR · CODEX measures error: [P0-9] − measured error (remaining [P0-9]) CIRCUIT BREAKERS stall ≥ 2 rounds → replan_required (re-anchor) stall ≥ 3 rounds → STOP the loop Codex emits STOP (alignment) → STOP round > max_iterations → STOP → terminal mv, the loop opens trend → drift every Nth round: Full Alignment Check (deep recalibration)
Setpoint: all acceptance criteria met with zero severity markers. The controller actuates by handing Claude the next prompt; Codex is the sensor measuring how far off we still are; the feedback is negative (remaining issues subtract from “done”). The three terms are present error, accumulated history, and the trend of progress — and when the trend flattens, breakers open the loop instead of grinding forever.设定点: 所有验收标准达成、 零严重度标记。 控制器通过把下一条提示交给 Claude 来 “施动”; Codex 是传感器, 量我们还差多远; 反馈是负的(剩余问题从 “完成” 里扣)。 三个分量分别是当前误差、 累积历史、 和进展的趋势—— 趋势一旦走平, 断路器就打开回路, 而不是无休止地磨。

The integral term积分项

Every review prompt carries the accumulated commit history since the base commit, plus the last few rounds' summaries and review results. The code calls this the integral component by name. It is what keeps the reviewer from forgetting the trajectory and re-litigating settled decisions each round.每条审查提示都带上自基线提交以来累积的提交历史, 外加最近几轮的总结和审查结果。 代码里就直接管它叫积分分量。 正是它让审查者不会忘记整条轨迹、 不会每一轮都把已经定下来的决定重新翻一遍。

loop-codex-stop-hook.sh · the integral contextL1035–1043 ↗
# Integral component: accumulated commit history and recent round references
if [[ -n "$BASE_COMMIT" ]] && git -C "$PROJECT_ROOT" merge-base --is-ancestor "$BASE_COMMIT" HEAD 2>/dev/null; then
    COMMIT_HISTORY=$(git log --oneline --no-decorate --reverse "$BASE_COMMIT"..HEAD | tail -80)
else
    COMMIT_HISTORY=$(git log --oneline --no-decorate --reverse -30)
    [[ -n "$COMMIT_HISTORY" ]] && COMMIT_HISTORY="(base commit unavailable, showing recent branch commits)
${COMMIT_HISTORY}"
fi

The derivative term, and the breaker微分项, 和那个断路器

In implementation phase, every Codex review must end with a line: Mainline Progress Verdict: ADVANCED / STALLED / REGRESSED. That verdict is the derivative — it measures whether the main objective moved this round, independent of how many side-issues got cleaned up. If it stalls twice, the loop injects a drift-recovery prompt that forces re-anchoring on the plan. If it stalls a third time, the circuit breaker fires and the loop stops itself.在实现阶段, 每次 Codex 审查都必须以一行结尾: Mainline Progress Verdict: ADVANCED / STALLED / REGRESSED。 这个裁决就是微分项—— 它衡量这一轮主线目标有没有动, 跟顺手清掉了多少枝节问题无关。 停滞两次, 循环就注入一个漂移恢复提示, 强制重新锚回计划。 停滞第三次, 断路器跳闸, 循环把自己停掉。

loop-codex-stop-hook.sh · stall → replan → stopL1837–1848 ↗
"$MAINLINE_VERDICT_STALLED"|"$MAINLINE_VERDICT_REGRESSED")
    NEXT_MAINLINE_STALL_COUNT=$((MAINLINE_STALL_COUNT + 1))
    if [[ "$NEXT_MAINLINE_STALL_COUNT" -ge 2 ]]; then
        NEXT_DRIFT_STATUS="$DRIFT_STATUS_REPLAN_REQUIRED"
        DRIFT_REPLAN_REQUIRED=true          # inject a re-anchor prompt
    fi
    if [[ "$NEXT_MAINLINE_STALL_COUNT" -ge 3 ]]; then
        MAINLINE_DRIFT_STOP=true             # trip the breaker
    fi
    ;;

There is also a periodic recalibration. Every Nth round (default 5) the regular review is upgraded to a Full Alignment Check against the whole plan and goal tracker, and only during those rounds is Codex permitted to emit STOP to halt a stagnating loop. The arithmetic lands the checks at rounds 4, 9, 14, … :还有一个周期性的重新校准。 每第 N 轮(默认 5)常规审查会升级成一次完整对齐检查, 对着整份计划和目标追踪表来核, 而且只有在这些轮里 Codex 才被允许发 STOP 来中止一个停滞的循环。 算术把这些检查落在第 4、 9、 14… 轮:

loop-codex-stop-hook.sh · Full Alignment cadenceL1022–1024 ↗
FULL_ALIGNMENT_CHECK=false
if [[ $((CURRENT_ROUND % FULL_REVIEW_ROUND)) -eq $((FULL_REVIEW_ROUND - 1)) ]]; then
    FULL_ALIGNMENT_CHECK=true
fi
Why the derivative term matters most for us为什么微分项对我们最要紧

A naive loop measures “are there issues left?” and happily clears fifty trivial side-issues while the real objective never moves. The mainline verdict separates motion from progress. That is exactly the failure mode of a kernel-optimization agent: it will gladly shave a microsecond off a warm-up path for twenty rounds while the actual GEMM stays 3× off roofline. A separate “did the mainline number move?” signal — wired to a breaker — is the difference between a search that converges and one that fidgets.一个朴素的循环只量 “还有没有问题?”, 然后乐呵呵地清掉五十个琐碎枝节, 而真正的目标一动不动。 主线裁决把 “在动” 和 “在进步” 分开。 这恰好是 kernel 优化 agent 的失效模式: 它会高高兴兴地花二十轮给热身路径省下一微秒, 而真正的 GEMM 还差 roofline 三倍。 一个单独的 “主线数字动了没?” 信号—— 接到断路器上—— 就是一个会收敛的搜索和一个只会原地抖动的搜索之间的区别。

§ 07 — The pre-flight§ 07 — 起飞前检查

Begin with the end in mind以终为始

Before the loop runs a single round, it tries to verify that you understand the plan. The reasoning in the docs is sharp enough to quote: “An RLCR loop is an amplifier: it will faithfully execute whatever plan you give it. If the plan is wrong, the loop makes it wrong faster and at scale.” They have a name for the failure they are guarding against — wishful coding: tossing a generated plan into the machine and hoping.在循环跑哪怕一轮之前, 它会试着确认真的看懂了计划。 文档里的论证够锋利, 值得照引: “一个 RLCR 循环是个放大器: 你给它什么计划, 它就忠实地执行什么。 计划要是错的, 循环只会让它错得更快、 更成规模。” 他们给要防的这个失效起了名字—— 许愿式编码: 把一份生成的计划丢进机器, 然后干等。

The mechanism is a two-question multiple-choice quiz, generated by a dedicated opus agent that reads the plan. Question one tests the core mechanism — what changes and how. Question two tests the architecture — how the pieces connect. Opus is the most expensive model in the plugin, used here, because the hard part is writing plausible wrong answers that a skimmer would fall for but a careful reader would not.机制是一道两题的选择题小测, 由一个专门的 opus agent 读完计划后出题。 第一题考核心机制—— 改什么、 怎么改。 第二题考架构—— 各部分怎么连起来。 Opus 是这个插件里最贵的模型, 偏偏用在这里, 因为难点是写出看着像真的错误选项—— 让略读者上钩、 让细读者一眼识破。

agents/plan-understanding-quiz.md · the discriminator ruleL40–42 ↗
# the entire quality bar, in three lines:
- A user who has carefully read and understood the plan should pick the correct answer
- A user who just skimmed the title or blindly accepted a generated plan would likely pick wrong
- Wrong options should be plausible (not obviously absurd) but clearly incorrect to someone who read the plan

The output is a fixed 13-field contract (two questions, four options each, two answers, plus a plan summary), and one of the enforcement notes is a small anti-bias trick: randomize the position of the correct answer; do not always put it in A or D. The quiz is advisory, not a gate — miss both questions and you are shown what the plan actually does, then offered the choice to proceed anyway or stop and read. The friction is the point, not the blocking.输出是一个固定的 13 字段契约(两题、 每题四个选项、 两个答案、 外加一段计划摘要), 而其中一条执行须知是个小小的反偏置技巧: 随机化正确答案的位置; 别老把它放在 A 或 D。 这个测验是建议性的, 不是关卡—— 两题都答错, 它会给你看计划到底在做什么, 然后让你选: 仍然继续, 还是停下来读。 重点是那点摩擦, 不是拦你。

The model-tier ladder is itself a design模型档位阶梯本身就是设计

Across the plugin, model choice tracks cognitive difficulty: haiku for the cheap relevance gates, sonnet for the branch-switch compliance check, opus for distractor generation. Cost is spent where the reasoning is genuinely hard. That is a habit worth stealing for any multi-agent system on a budget.在整个插件里, 模型选择跟着认知难度走: haiku 做廉价的相关性关卡, sonnet 做切分支的合规检查, opus 做干扰项生成。 钱花在推理真正难的地方。 这是任何有预算的多 agent 系统都值得偷的习惯。

§ 08 — Before the loop§ 08 — 循环之前

The planning pipeline计划流水线

The loop is only half the product. The other half is a three-command pipeline that turns a loose thought into a plan good enough to amplify. Each command is pure prompt engineering — markdown with frontmatter — and each forces the model into a parseable, auditable contract.循环只是产品的一半。 另一半是一条三命令的流水线, 把一个松散的念头变成一份好到值得放大的计划。 每个命令都是纯提示工程—— 带 frontmatter 的 markdown—— 而且每个都把模型逼进一个可解析、 可审计的契约。

Plate Videa → plan → refined plan → loop念头 → 计划 → 精修计划 → 循环
PLATE V · THE PLANNING PIPELINE gen-idea fan out N=6 Explore agents, orthogonal → draft.md gen-plan Codex-first critique, converge ≤ 3 rounds → plan.md refine-plan classify comments, write QA ledger → refined plan start-rlcr quiz gate, then hand to the loop → § 01–06 ACCEPTANCE CRITERION SCHEMA - AC-1: <criterion> - Positive Tests (expected to PASS): - <case that succeeds when met> - Negative Tests (expected to FAIL): - <case that is rejected> - AC-1.1: <sub-criterion> TDD baked into the schema — every AC is falsifiable TASK TABLE — EVERYTHING ROUTED | task | Target AC | Tag | Depends On | | task1 | AC-1 | coding | - | | task2 | AC-2 | analyze | task1 | coding → Claude executes analyze → delegate to Codex every task maps to an AC — nothing forgotten
The pipeline's whole job is to produce a plan the loop can verify mechanically: acceptance criteria with positive and negative tests, and a task table where every task maps to an AC and carries a routing tag. The amplifier only works if the thing being amplified is falsifiable.这条流水线的全部职责, 是产出一份循环能机械验证的计划: 带正反测试的验收标准, 以及一张每个任务都映射到某条 AC、 还带路由标签的任务表。 放大器只有在被放大的东西可证伪时才管用。

gen-plan puts the reviewer firstgen-plan 把审查者放在最前面

The non-obvious move in gen-plan.md is that Codex critiques the raw draft before Claude writes a plan, returning a fixed six-field contract (CORE_RISKS, MISSING_REQUIREMENTS, TECHNICAL_GAPS, …). The reviewer sees the problem before the implementer commits to a solution, so the plan is not anchored on Claude's first framing. A second Codex pass then challenges the candidate plan across up to three convergence rounds, tracked in a matrix with explicit resolved / needs_user_decision / deferred statuses.gen-plan.md 里不显眼的一手是: Codex 在 Claude 动笔写计划之前就先批评原始草稿, 返回一个固定六字段契约(CORE_RISKSMISSING_REQUIREMENTSTECHNICAL_GAPS…)。 审查者在实现者锚定某个方案之前就看到了问题, 于是计划不会被 Claude 的第一框架带偏。 然后第二趟 Codex 挑战候选计划, 最多三轮收敛, 记录在一张带明确 resolved / needs_user_decision / deferred 状态的矩阵里。

refine-plan is an auditable comment compilerrefine-plan 是一个可审计的批注编译器

When reviewers annotate a plan with inline comments (three accepted syntaxes: CMT:…ENDCMT, <cmt>, <comment>), refine-plan.md classifies each into exactly one of question / change_request / research_request, with a precedence ladder research > change > question for mixed-intent blocks (you must investigate before you can correctly change or answer). It then strips the comments and emits a QA ledger with one row per comment — a provable 1:1 audit, with dispositions answered / applied / researched / deferred / resolved. The instruction is explicit that the parser must be a stateful scanner, not a regex, because comment markers inside fenced code blocks have to be ignored.当审查者用内联批注标记一份计划(接受三种语法: CMT:…ENDCMT<cmt><comment>), refine-plan.md 把每条恰好归为 question / change_request / research_request 之一, 混合意图的块按优先级阶梯 research > change > question 处理(你得先调查, 才能正确地改或答)。 然后它剥掉批注、 产出一份每条批注一行的 QA 账本—— 一个可证的 1:1 审计, 处置值为 answered / applied / researched / deferred / resolved。 指令明确要求解析器必须是个有状态扫描器、 而不是正则, 因为围栏代码块里的批注标记必须被忽略。

§ 09 — Memory§ 09 — 记忆

The bitter-lesson notebook苦涩教训笔记本

Each project keeps a knowledge base at .humanize/bitlesson.md — a structured log of lessons learned across rounds, named for Rich Sutton's “Bitter Lesson.” Entries follow a strict template: a dated ID BL-YYYYMMDD-short-name, plus scope, problem description, root cause, solution, constraints, validation evidence, and the source rounds where the problem appeared and was solved.每个项目在 .humanize/bitlesson.md 维护一个知识库—— 一份跨轮次的经验日志, 名字取自 Rich Sutton 的 “苦涩教训”。 条目遵循严格模板: 一个带日期的 ID BL-YYYYMMDD-short-name, 外加范围、 问题描述、 根因、 解法、 约束、 验证证据、 以及问题出现并被解决的那些来源轮次。

Two pieces make it work. A haiku selector agent runs before each task and picks which lessons apply, with a hard instruction to prefer precision over recall — return NONE rather than dilute the implementer's context with weakly-related lessons. And every round summary must carry a ## BitLesson Delta section, which the stop gate validates strictly:两块东西让它跑起来。 一个 haiku 选择器 agent 在每个任务前运行、 挑出哪些教训适用, 带一条硬指令: 宁要精确不要召回—— 宁可返回 NONE, 也不用弱相关的教训稀释实现者的上下文。 而每一轮总结都必须带一个 ## BitLesson Delta 段, 由 stop gate 严格校验:

the BitLesson Delta contract · validated every rounddocs/bitlesson.md ↗
## BitLesson Delta
- Action: none|add|update
- Lesson ID(s): <IDs or NONE>
- Notes: <what changed and why>

# strict rules:
#  Action: none   → Lesson ID(s) must be NONE / empty
#  add / update   → must reference a real BL-… ID that exists in the file

Provider routing for the selector is automatic and worth noting: model names matching gpt-* or o[N]-* route to Codex, while claude-*/haiku/sonnet/opus route to Claude. The same agent definition drives either backend. If the configured provider's binary is missing, it falls back to Codex so the loop still proceeds.选择器的 provider 路由是自动的, 值得一提: 模型名匹配 gpt-*o[N]-* 的走 Codex, 而 claude-*/haiku/sonnet/opus 走 Claude。 同一份 agent 定义驱动任一后端。 配置的 provider 二进制缺失时, 它回退到 Codex, 循环照样往前走。

This is the part I would build first这是我会最先搭的部分

A per-project, append-only ledger of “here is a failure mode and the fix that worked, with the evidence” is exactly the performance database a kernel-optimization agent needs. Swap “lesson” for “a tiling/vectorization choice that moved the GEMM toward roofline, with the profiler trace,” and the BitLesson schema becomes the training substrate for later RL. The strict, machine-checkable delta contract is what makes it trustworthy enough to learn from.一个按项目、 只追加的账本, 记着 “这是一个失效模式和管用的修法, 附证据”—— 这正是 kernel 优化 agent 需要的性能数据库。 把 “教训” 换成 “一个把 GEMM 推向 roofline 的 tiling/向量化选择, 附 profiler trace”, BitLesson 的 schema 就成了日后 RL 的训练底料。 那个严格、 机器可校验的 delta 契约, 正是让它可信到能从中学习的东西。

§ 10 — Threat model§ 10 — 威胁模型

Why the agent can't cheat its way out为什么 agent 没法靠作弊脱身

A loop that re-prompts a model until it succeeds has an obvious attack: the model could just forge an exit — edit the state file, fake a COMPLETE, or run the cancel command itself. Humanize assumes the agent will try, and defends in depth. No single layer is trusted; each one independently makes the cheat harder.一个不停重提示模型直到它成功的循环, 有个显而易见的攻击: 模型可以干脆伪造一个退出—— 改状态文件、 假装 COMPLETE、 或者自己去跑取消命令。 Humanize 假定 agent 会去试, 然后做纵深防御。 没有任何单层是被信任的; 每一层都独立地把作弊变得更难。

Plate VIdefense in depth against a forged exit对伪造退出的纵深防御
PLATE VI · DEFENSE IN DEPTH LAYER 4 — .review-phase-started marker + per-call state re-validation LAYER 3 — is_cancel_authorized: the sanctioned exit needs a .cancel-requested signal LAYER 2 — PreToolUse validators block the writes mv state.md · git push · immutable goal-tracker · plan.md LAYER 1 — the round prompt forbids it “you MUST NOT exit by lying or edit the loop state” ATTEMPT edit state · fake cancel · forge COMPLETE an exit is real only if it survives all four layers prompt (soft) → validators (hard) → signed cancel → marker + re-check terminal states are renamed, never deleted — every attempt is preserved for forensics
The prompt is the only soft layer; everything outside it is enforced by shell. The cancel command isn't blocked outright — instead the one sanctioned mv state.md → cancel-state.md is gated behind a .cancel-requested signal file that only the real cancel command drops, with an injection-hardened parser so the escape hatch can't be turned into an arbitrary move.提示是唯一的软层; 它外面的一切都由 shell 强制。 取消命令并没有被一刀切地禁掉—— 而是那唯一被认可的 mv state.md → cancel-state.md 被一个 .cancel-requested 信号文件把着关, 只有真正的取消命令才会丢下它, 还配了一个抗注入的解析器, 免得这个逃生口被改造成任意的 move。

Layer 4 is my favorite because it closes a specific hole. The implementation-vs-review distinction is just a boolean in state.md. A model could edit that boolean to true to skip straight to review. So entering review phase also writes a .review-phase-started marker file, and the hook refuses to honor review_started=true unless that marker exists — a hand-edited toggle is detected and rejected as an inconsistency.第 4 层是我最喜欢的, 因为它堵了一个具体的洞。 实现-还是-审查的区别只是 state.md 里的一个布尔量。 模型可以把它改成 true 直接跳到审查。 所以进入审查阶段时还会写一个 .review-phase-started 标记文件, 钩子拒绝认可 review_started=true, 除非那个标记存在—— 一个手改的开关会被当成不一致检测出来并拒绝。

loop-codex-stop-hook.sh · the anti-toggle checkL1922–1938 ↗
# This prevents manual toggle attacks where someone edits state.md directly
if [[ ! -f "$LOOP_DIR/.review-phase-started" ]]; then
    REASON="Review phase state inconsistency detected. …"
    jq -n --arg reason "$REASON" --arg msg "…" \
        '{"decision": "block", "reason": $reason, …}'
    exit 0
fi
§ 11 — Small cleverness§ 11 — 小巧思

A drawer of small cleverness一抽屉小巧思

The reason this codebase rewards a close read is the density of small, correct decisions in plain shell. Here is a drawer of the ones I would not have thought to write until I saw them break without them.这个代码库值得细读的原因, 是它在朴素 shell 里那一把又一把又小又对的决定。 下面这一抽屉, 都是我没亲眼见过 “没有它就会出事” 之前不会想到要写的。

The session-id handshakesession-id 握手

The setup script writes state.md with session_id: deliberately blank, because it runs inside Claude's Bash tool and cannot see its own session id. It drops a one-shot .pending-session-id signal carrying the setup script's own path as a command signature; the PostToolUse Bash hook fires after the command, confirms the just-run command actually starts with that signature, extracts the session id from the hook's JSON, and atomically patches it in. The comment cites a real bug (issue #67): a trailing slash on CLAUDE_PLUGIN_ROOT produced a // mismatch, so both sides are normalized with tr -s '/' first.安装脚本写 state.md 时故意把 session_id: 留空, 因为它跑在 Claude 的 Bash 工具里面、 看不到自己的 session id。 它丢下一个一次性的 .pending-session-id 信号, 里头带着安装脚本自己的路径作为命令签名; PostToolUse Bash 钩子在命令之后触发、 确认刚跑的命令确实以那个签名开头、 从钩子的 JSON 里抽出 session id、 再原子地补进去。 注释引用了一个真实 bug(issue #67): CLAUDE_PLUGIN_ROOT 尾部一个斜杠产生了 // 不匹配, 所以两边先用 tr -s '/' 归一化。

Why bother? Because the session id must be recorded before any Agent Team members spawn, so that only the team leader's session is governed by the hooks. The whole dance exists to make the hooks session-aware in a system that never told the setup script which session it was.何必费这劲? 因为 session id 必须在任何 Agent Team 成员生成之前记下来, 这样才只有队长的会话被钩子治理。 这整套舞步的存在, 就是为了在一个从没告诉安装脚本 “你是哪个会话” 的系统里, 让钩子变得会话感知。

A flicker-free TUI from two escape codes两个转义码搭出的无闪烁 TUI

The monitor dashboard is a live terminal UI with a frozen status bar on top and a scrolling log below — built without any TUI library. It carves the screen with one VT100 sequence (DECSTBM, “set top and bottom margins”) so output only scrolls below the reserved rows, and redraws the bar in place using erase-to-end-of-line instead of a full clear, so it never flickers.监控面板是一个实时终端 UI: 顶上冻一条状态栏、 下面滚动日志—— 没用任何 TUI 库搭出来。 它用一个 VT100 序列(DECSTBM, “设置上下边距”)把屏幕切开, 让输出只在保留行下方滚动; 再用 “清到行尾” 而不是整屏清除来就地重绘状态栏, 于是从不闪烁。

scripts/humanize.sh · split-screen via scroll regionL652–659 ↗
_setup_terminal() {
    clear
    # reserve top rows for the status bar; scroll only below
    printf "\033[${status_bar_height};%dr" $(tput lines)   # DECSTBM
    tput cup $status_bar_height 0
}
Trick巧思 Where位置 Why it's there为何如此
Control-char placeholders控制符占位loop-bash-validator.sh:321\x01/\x02/\x03 stand in for &> >& &>> so splitting a command on & doesn't shred redirections\x01/\x02/\x03 替身 &> >& &>>, 这样按 & 切命令时不会撕碎重定向
awk, not sed用 awk 不用 sedloop-post-bash-hook.sh:127session ids contain / and &, which are sed-hostile replacement charssession id 含 /&, 都是 sed 替换里的雷
Refuse pwd拒用 pwdlib/project-root.shresolve root via CLAUDE_PROJECT_DIR → git toplevel; pwd drifts as Claude cds mid-sessionCLAUDE_PROJECT_DIR → git 顶层解析根; pwd 会随 Claude 中途 cd 漂移
Zombie-loop guard僵尸循环防护loop-common.sh:344only the newest timestamped dir is inspected, so a stale state.md can never be revived只看最新的时间戳目录, 旧的 state.md 永远复活不了
Incremental tail增量 tailscripts/humanize.sh:1079tail -c +N reads only new bytes each frame; a shrinking file signals rotationtail -c +N 每帧只读新字节; 文件变小就是轮转信号
Portable timeout可移植 timeoutscripts/portable-timeout.shmacOS has no timeout; probe gtimeouttimeout→python, and exit 124 to match GNUmacOS 没有 timeout; 探测 gtimeouttimeout→python, 并以 124 退出对齐 GNU
Signal sets a flag only信号只置标志scripts/humanize.sh:780the SIGWINCH handler does no I/O — that would race the redraw and corrupt arithmeticSIGWINCH 处理器不做 I/O—— 否则会和重绘竞争、 把算术弄乱
Late PIPE trap迟设 PIPE trapsetup-rlcr-loop.sh:1447trap 'exit 0' PIPE set just before the final stdout dump, so an early reader-close exits cleantrap 'exit 0' PIPE 只在最后 stdout 输出前设, 读者提前关管道也能干净退出
jq empty-collapse guardjq 空塌缩防护rlcr-stop-gate.shexplicit ternaries instead of select(length>0), so an empty session_id doesn't wipe the whole object用显式三元而非 select(length>0), 免得空 session_id 抹掉整个对象
Dual-purpose PENDING双用 PENDINGcommands/gen-plan.mdDEC-N · PENDING is both the human to-do list and the machine gate that blocks auto-startDEC-N · PENDING 既是给人的待办、 也是挡住自动启动的机器关卡
§ 12 — Transfer§ 12 — 迁移

What transfers to a kernel agent什么能迁到 kernel agent 上

I read this with one project in mind: a multi-agent system that writes high-performance AMD kernels by running long-horizon, parallel optimization loops. Humanize is not about kernels, but its control structure is almost exactly the loop I want, and reading it sharpened a few decisions.我读它时脑子里装着一个项目: 一个多 agent 系统, 靠跑长周期、 并行的优化循环来写高性能 AMD kernel。 Humanize 跟 kernel 无关, 但它的控制结构几乎正是我想要的循环, 读它让我把几个决定想清楚了。

HumanizeHumanize Kernel agent equivalentKernel agent 的对应
Codex review (the sensor)Codex 审查(传感器)rocprof / omniperf counters + a correctness check — an external, non-negotiable measurement, not the agent's own opinionrocprof / omniperf 计数器 + 正确性检查—— 一个外部的、 不容商量的测量, 不是 agent 自己的看法
[P0-9] severity markers[P0-9] 严重度标记distance from roofline + correctness failures, graded by how much performance is left on the table距 roofline 的差距 + 正确性失败, 按还有多少性能没榨出来分级
Mainline Progress Verdict主线进展裁决“did the real GEMM latency move toward roofline?” — separate from incidental micro-wins“真正的 GEMM 延迟有没有朝 roofline 动?”—— 与顺手的微优化区分开
Drift circuit breaker漂移断路器stop a search that fidgets on warm-up paths while the binding kernel stays 3× off peak停掉那种在热身路径上原地抖、 而关键 kernel 还差峰值三倍的搜索
Cheap gates before CodexCodex 前的廉价关卡does it compile? does it pass the reference check? — gate before spending a full profiling run编得过吗? 过参考检查吗?—— 在花一次完整 profiling 之前先过关
BitLesson ledgerBitLesson 账本the performance database: every variant's code + params + profiler trace, the substrate for later RL性能数据库: 每个变体的代码 + 参数 + profiler trace, 日后 RL 的底料
State as files in a timestamped dir状态 = 时间戳目录里的文件crash-safe, reconstructable parallel search — checkpoint every variant, never hold the search in a process崩溃安全、 可重建的并行搜索—— 每个变体都 checkpoint, 绝不把搜索攥在进程里

The single most useful idea is the separation the mainline verdict makes: motion is not progress. A loop that only asks “are there issues left?” will clear easy issues forever. A loop that asks “did the one number that matters move?” — and trips a breaker when it doesn't — converges instead of fidgeting. For kernel search, the one number is the gap to roofline, and wiring it to a breaker is what keeps a 500-variants-per-day agent from spending its budget polishing things that don't bind.最有用的一个想法, 是主线裁决做出的那个区分: 在动不等于在进步。 一个只问 “还有没有问题?” 的循环会永远清简单问题。 一个问 “那个唯一要紧的数字动了没?”、 不动就跳闸的循环, 会收敛而不是抖动。 对 kernel 搜索, 那个唯一的数字就是距 roofline 的差距, 把它接到断路器上, 正是让一个每天试 500 个变体的 agent 不至于把预算花在打磨不构成瓶颈的东西上。

The second idea is the funnel: never spend the expensive measurement until the cheap checks pass. Compiling and a correctness check are seconds; a full omniperf pass is minutes. Humanize's ordering — local deterministic gates first, the costly external reviewer last — is the right shape for any agent whose feedback signal is expensive to obtain.第二个想法是漏斗: 廉价检查没过之前, 绝不花那次昂贵的测量。 编译加一次正确性检查是秒级; 一整趟 omniperf 是分钟级。 Humanize 的排序—— 本地确定性关卡在前、 昂贵的外部审查者在后—— 对任何 “反馈信号获取代价高” 的 agent 都是对的形状。

§ 13 — Epilogue§ 13 — 尾声

The brake is the feature刹车才是功能

Most agent tooling adds capability — more tools, more context, more autonomy. Humanize adds a brake, and the brake is the whole value. It takes an eager model that wants to declare victory and wraps it in durable state, an external sensor, and a circuit breaker, until the eagerness becomes something you can actually steer.大多数 agent 工具加的是能力—— 更多工具、 更多上下文、 更多自主权。 Humanize 加的是一个刹车, 而这个刹车就是它的全部价值。 它拿一个急着宣布胜利的模型, 用持久状态、 一个外部传感器、 和一个断路器把它裹起来, 直到那份急切变成你真能驾驭的东西。

None of it requires a framework. Seven shell hooks, a directory of markdown, an independent reviewer, and a controller that knows the difference between motion and progress. That the most interesting agent-orchestration code I read this month is written in Bash is itself the lesson: the hard part was never the runtime, it was knowing where to put the gates.这些都不需要框架。 七个 shell 钩子、 一个 markdown 目录、 一个独立审查者、 还有一个分得清 “在动” 和 “在进步” 的控制器。 我这个月读到的最有意思的 agent 编排代码竟是用 Bash 写的, 这本身就是教训: 难的从来不是运行时, 而是知道把关卡放在哪。

Read next接着读

If the agent-orchestration angle is what hooked you, the companion reading is Codex's goal-tracking source and Kernel-Design Agents on the paper shelf. Everything is indexed at the library.如果是 agent 编排这个角度勾住了你, 配套阅读是 Codex 的目标追踪源码, 以及论文架上的 Kernel-Design Agents。 一切都索引在 文库 里。

Source来源
PolyArch/humanize · v1.16.0 · MIT · read at commit 0ec921a读于提交 0ec921a
Typography字体
Oswald · Chivo · B612 Mono · Noto Sans SC
Palette配色
cyanotype blueprint + redline review pencil蓝晒图纸 + 红线审稿铅笔
Compiled for写给
jinnpan.com · the libraryjinnpan.com · 文库