2026-08-28·by Sijie Wang#cybernetics#theory#agents

git-as-agent-trust-substrate

Git 作为 agent 信任基座

问题所在。 当多个 AI agent 协作完成一个不可逆且对外可见的动作(发布、部署、发送)时,你不能指望任何一个 agent 是诚实的:生成这份工作的 agent,恰恰是判断它该不该上线的最差人选;而被问"你做到合规了吗"的 agent,完全可以直接回答"是"。让 agent 审查 agent 层层串联也解决不了这个问题——同一模型家族的审查者会共享同样的盲点(slop-is-a-context-deficit 实验的告诫:同一家族的评判者会漏掉同样的东西),而且这整条链条都不具备防篡改的证据能力。

模式的精确表述(2026-07-16 修正)。 权威来源不是 git——而是一个可重复执行的确定性检查。不可化简的机制是:关卡对制品重新跑一遍确定性 lint,而不是相信任何 agent 的自我报告。 git 的本质职责是另一件、更具体的事:内容寻址,把被检查过的制品和最终发布的制品绑定在一起(从而消除检查时刻与使用时刻之间的间隙)。git 贡献的其他一切都有价值,但都是可替代的。

  1. 角色间的权力分立。 生成者(generator,负责产出)· 审计者(auditor,运行 lint 并提交记录)· 发布者(publisher,只对已验证、已内容寻址的记录采取行动)。任何角色都不能替另一个角色做事。
  2. 关卡的完整性来自重跑本身,而不是来自 git。 发布者不会相信一个"通过"的状态——它会重新跑一遍确定性 lint(或者把已提交的 lint 结果与已提交的制品对照验证)。agent 没办法凭嘴上功夫蒙混过一个会被重新执行的检查;初稿里"读取 git"的说法,把功劳错记到了 git 头上。git 与通过/不通过的判定只是偶然相关;真正换来信任的是重跑这个动作。
  3. git 真正承重的地方——TOCTOU 间隙。 没有内容寻址的话,agent 可以让制品 v1 通过 lint,然后偷换成不合规的 v2 再发布(检查的是一个东西,发布的是另一个)。git 堵上了这个漏洞:发布者发布的,恰好就是那个内容哈希被提交过、被 lint 过的制品。要做到这一点,你需要内容寻址加不可变性——也就是 git 或与之等价的东西。这才是 git 出现在这个流程里的原因,而不是通过/不通过的判定本身。
  4. 硬规则是代码;软判断是 agent。 机械化的、可用 diff 检验的规则(完整性、格式、来源、频率)都放在确定性 lint 里,agent 没法靠争辩绕过去。agent 的判断(品味、语域)只作为建议,绝不作为关卡——这样就绕开了同家族合谋的问题。

git 的其他贡献——真实存在,但可替代。 带时间戳、防篡改的来源记录(一个签名的仅追加日志同样能做到);依赖历史的检查所读取的、持久化的有序历史(速率冷却、去重、平台期检测——任何有序存储都行,git log 只是恰好方便);零额外工具的人工审计/回退(git log/diff/revert)。对一个原生使用 git 的操作者来说,这些几乎是免费的,这就是为什么 git 是实用意义上的基座,尽管从逻辑上讲只有内容寻址才是必需的。

这带来的一种解耦。 如果威胁模型里根本不存在偷换向量——发布和审计在一个原子步骤里完成,中间没有 agent 可利用的间隙——那么关卡就完全不需要 git 了,git 会退化成纯粹的审计存储。关卡的完整表述是:确定性重跑 +(当且仅当存在 TOCTOU 间隙时才需要内容寻址)。 git 只是获得后一个条款的一种方式,而不是前一个条款的来源。

一个熟悉想法的推广。 这就是"约束要机械化,而不是靠社会化默契"(vault 主人的工程原则)应用到 agent 协作上的样子:与其信任 agent 会遵守规则,不如把规则做成 agent 的输出必须通过的一次重跑,并锚定到实际发布的那份确切内容上。这其实是 CI 门禁式(continuous-integration,持续集成)部署,只是重新套用到了一个工人是语言模型的世界里:流水线不信任提交者,而是对已提交的内容重新跑一遍检查——阻止"检查"和"部署"之间被偷换的,正是那个提交哈希。

重跑本身就是一次 agent 的生成——"验证就是生成一个 agent"(2026-07-16)。 这个重跑不是"同一进程再调用一次函数";它的实际形态是一个新生成的、干净上下文的 agent,去 shell 出确定性 lint,对已提交的内容执行检查。生成新 agent 之所以重要,而不只是重新执行这件事本身,有两个原因:(1)干净的上下文防止了同上下文合谋——验证者与产出这份制品的生成者之间不共享任何状态、不共享任何自圆其说的理由、不共享任何半成型的故事(这正是 executor-acceptance-test 用在发布关卡上:一个干净的 agent,要么给出引用要么判失败);(2)整台机器的验证接口是统一的——不管是确定性关卡还是判断性关卡,一律都是"生成一个 agent 去重新检查",这样需要推理的信任原语就只有一个。确定性 lint 是那个被生成出来的 agent 所运行的东西;生成动作决定的是"谁来运行它"。

由此衍生出的构建纪律——"重跑验证不了的东西,就不许进来。" 因为验证就是一次生成 agent 的重跑,一个组件只有在这样的重跑能够检查它时,才配在这台机器里占有一席之地。一个任何重跑都无法确认的字段(一个无法证伪的断言、一句无法核实的"相信我")不会被降格为软性建议留下来——而是被直接排除在外。这让机器里的每一道关卡都能被同一个原语证伪,也是为什么面对"第一条规则没有在代码里强制执行"这种担忧,正确的修法不是加一个哈希相等断言,而是指出:发布者 agent 已经在对已提交(已哈希)的内容重跑了——真正起强制作用的是重跑本身,而不是某个专门定制的检查。

落地实例。 utter-manual——发布者是一个新生成的 agent,它对审计者已提交的账本记录重新跑一遍机械 lint,只有结果干净时才执行那个不可逆的动作(发到一个真实账号上),因此 agent 无法靠嘴上功夫说动机器发布不合规的内容。

这套基座横跨人↔agent,不只是 agent↔agent(2026-07-16)。 在需要品味判断的步骤上(lint 检查不了的那部分残余——这个视频好不好、它代不代表我),判官是人,他们的"同意"也用同样的方式绑定:记录成一个 token,其内容哈希必须与已提交的制品一致human-gated-publish,utter-manual 的 publish.human_approval)。发布者的关卡因此变成两把锁——一个确定性重跑的 PASS,加上一个人对匹配哈希给出的 approve。于是,阻止 agent 发布"被检查过的东西之外的内容"的那套内容寻址机制,同样也阻止机器发布"人没有认可过的内容":对一个人来说,"认可这份确切字节"和对 lint 来说"重跑这份确切字节"一样防篡改。信任的原语(内容寻址式授权)在确定性关卡和人工关卡上是统一的。

边界所在。 这套基座保证的是符合已声明的规则、且检查与发布之间不会被偷换——而不是规则本身是对的。一份错误的 lint spec,会把"错了但合规"的工作照样发出去。而硬/软的划分意味着,任何只能靠品味判断(而非可用 diff 检验的规则)的东西,最终仍然落在建议性的 agent 加人工签字上,而不是落在关卡上。这套模式把信任,从"agent 是诚实的"挪到了"规则是对的、并且有人在盯着那些构成性的 diff"——这是一个严格意义上更好的信任落脚点,而不是一个没有信任的地方。

同类项:slop-is-a-context-deficit(为什么 agent 审 agent 不够)· executor-acceptance-test(生成干净 agent 重新检查,这里被用作发布关卡)· trust-follows-provenance(靠重新推导来验证,而不是靠点头认可)· utter-manual(落地实例)· vault 自身的 pre-commit lint(同一种哲学在笔记层面的体现)。

来源:2026-07-16 的设计,从 utter-manual 架构中泛化而来;正是这个模式,让不可逆的对外动作得以委托给不受信任的 agent 去执行。

about this entry

One of sijie's wiki entries. The AI on this site is grounded in the same corpus and answers in sijie's voice, with citations back to entries like this one — answering costs sijie money, so it waits behind a code: enter an access code →