Handbooks
核心概念

哪些内容可以信任

手册中哪些部分是解析得到的事实,哪些是模型输出,哪些数据会离开你的机器,以及这个工具拒绝做哪些事。

简短版本

断言来源会出错吗?
这个文件存在于这个路径解析器不会
这个函数位于第 88–104 行解析器不会
这个签名是 send(self, url, data)解析器不会
这个函数调用了那个函数解析器完整层级不会;通用层级为尽力而为
这些调用无法被解析解析器不会 —— 它们被如实列出,而非猜测
这些文件无法被读取或解析解析器不会 —— 它们被如实列出,而非算作已覆盖
这个文件属于这个阶段LLM,经机械化校验判断上可能出错;结构上不会
这个文件的用途是“…”LLM —— 这是描述性文字
这个子系统的工作方式是“…”LLM —— 这是描述性文字
这份状态流经这几个阶段LLM,基于真实阶段 id,不过阶段 id 是真实的

**整个设计遵循的规则是:**智能体依据表格的上半部分进行路由,并在行动之前阅读真实源码。SKILL 包在第一行就写明了这一点,其路由协议以这样一句话收尾:“在提出或做出任何修改之前,对每个被引用的路径执行 read_file,阅读实际源码。”

哪些数据会离开你的机器

**Phase 1 —— 什么都不会。**静态分析完全在本地进行,不发起任何网络调用。

Phase 2 和 Phase 3 会把源文件内容发送到配置的端点。它可以是运行在你自己机器上的模型(vLLM、Ollama、LiteLLM)。Handbooks 没有遥测、没有统计分析,除 OpenAI 之外也没有其他默认端点——而 OpenAI 的密钥必须由你自己提供。

--max-chars-per-file <n> 限定任何单个文件最多会被发送多少内容。

渲染、打包和校验从不接触网络,applyrollback 也一样。

规划器在本地读取你的源码,并把读到内容的节选发送到端点,与生成阶段相同。

哪些事被刻意拒绝

拒绝正是这个工具的承重结构。按优先级排列:

补丁器(patcher)

  • 锚点匹配到次 → 拒绝。代码已经变了。
  • 锚点匹配到两次或以上 → 拒绝。它有歧义。
  • 绝不“取第一个匹配”。补丁就是这样落进错误函数的。
  • 只要有一处失败,就在写入任何一个字节之前中止整个补丁应用。
  • 逃出源码根目录的路径会被拒绝——包括当文件尚不存在时、经由符号链接的父目录逃逸的情况。
  • 回滚会拒绝处理任何在打补丁之后又被改动过的文件,除非你传入 --force

规划器(planner)

  • 不存在写入工具。不是被禁用了——是根本没有实现
  • 凭空捏造 ## Tool result 小节的回复会被直接整体拒绝,连同其末尾附带的任何计划——因为那个计划是从虚构中推导出来的。
  • 已经放弃的运行会以非零码退出,而不是把一段道歉写进 plan.md
  • 灾难性正则((a+)+(.*)*)会在拖垮运行之前就被拒绝。

流水线

  • 分析器无法解析的调用会进入 dropped-calls.json,绝不靠猜。
  • 分析器读不了或解析不了的文件会带着原因进入 scan-coverage.json,并被挡在 scannedFiles 之外,绝不会被当成一个空文件来描述。只解析出一部分的文件会留下,但同样会被列出来——它的事实是真的,只是不完整,而你应该知道哪些页面是建立在这些事实之上的。
  • 卡片生成失败的文件会得到一个描述,绝不会得到编造的描述,并被列入 _coverage.json
  • doctor 循环提出的结构性修改,若引用了不存在的阶段、或会让文件成为孤儿,就会在触及骨架之前被拒绝。
  • 评审者的回复解析失败时,按 REJECT 计。

配置

  • 密钥从来不是命令行标志,出现在配置文件里则会被拒绝——因为配置文件是要提交进版本库的。有两个设置属于密钥:llmApiKey / OPENAI_API_KEY,以及 llmExtraBody / OPENAI_EXTRA_BODY——后者内容完全自由,会被合并进每一个请求体,而网关确实接受写在那里的鉴权信息,所以没有任何办法分辨其中哪个是调参字段、哪个是凭据。
  • llmBaseUrl 则刻意被一概当作密钥:团队让所有本地检出都指向同一个共享网关,是有正当理由把它提交进去的。只有内嵌了凭据的 URL(https://user:pass@host/v1)会在配置文件里被拒绝。
  • 提供了但无效的值绝不会悄悄落回默认值。写错就是错误。
  • 空值按未设置处理,因此 HANDBOOK_TITLE= 不可能产出一本没有标题的手册。

检测漂移

SKILL 包中的 coverage.json 携带打包时捕获的每个文件的内容哈希

handbook validate --skill skills/myrepo --source ~/code/myrepo

会对当前源码重新计算哈希,并报告自那以后内容发生变化的每一个文件。智能体正是这样在依据过期断言行动之前得知*“这一页可能已落后于代码”*的——这也是给 handbook skill 传入 --work--source 值得的原因。

纠错通道

当手册中的断言与真实源码相矛盾时,使用手册的智能体会向技能根目录下的 corrections.jsonl 追加一行 JSON:

{
  "file": "src/engine.py",
  "page": "references/stages/stage-2.md",
  "claim": "spin() is defined in src/main.py",
  "actual": "spin() is defined in src/engine.py"
}

随后 handbook resync --corrections <file>恰好刷新其中点名的那些文件——即使它们的字节从未变过,因为一条被源码推翻的断言,本身就足以成为重新描述该文件的理由。

这个文件位于技能根目录,绝不放在 references/ 之下,因为规划器会以只读方式挂载那棵目录树。重建时,尚未处理的纠错记录会在清理过程中被保留下来。

Studio 的安全态势

Studio 是一个本地工具,也不假装自己不是。

  • 默认绑定 127.0.0.1
  • CSRF 防护检查的是 Host 请求头而不是套接字,因此只有回环主机名能通过。
  • POST 要求 application/json,从而挡住经典的跨源表单攻击。
  • 源码与手册文件的伺服被沙箱限制在已注册的根目录之内。

在容器中它必须绑定 0.0.0.0,否则发布出去的端口根本无法访问;但这并不会放宽谁能与它对话:请求里写局域网 IP 或容器主机名的仍然会得到 403。远程访问是一项刻意未实现的独立特性——它需要一份显式的允许列表。

Handbook 不声称知道的事

调用图无法告诉你一个决定为什么这样做、产品是拿来干什么的,或者你们团队的约定是什么。Handbooks 不去推断这些,也不假装能推断。它记录结构与行为;意图仍然要由你自己写下来。

本页目录