
Image: AI generated
一个问题
打开你项目中最长的文件,看看里面有多少个函数。
让 AI 代理修改那个文件中的某一个函数。代理会读取整个文件。它打开文件是因为需要一个函数,结果却带来了 19 个不必要的函数。
问题就从这里开始。
人类阅读的代码 vs 代理操作的代码
一直以来,代码是给人类阅读的。给变量取好名字、写注释、写文档——一切都是为了减轻人类的认知负担。
在代理时代,问题变了。人类容易阅读的代码和代理容易操作的代码是一样的吗?
不一样。
| 人类 | AI 代理 | |
|---|---|---|
| 导航方式 | 用眼睛浏览目录树 | 用 grep 搜索 |
| 打开文件 | 在 IDE 中滚动 | read file — 全部加载 |
| 上下文判断 | 直觉 + 经验 | 只知道上下文中有的内容 |
| 不必要的代码 | 忽略 | 消耗上下文预算 |
| 2,000 行文件 | 只看需要的部分 | 全部处理 |
人类滚动 2,000 行文件时,“这部分别碰"的直觉会自动启动。代理没有这种直觉。读了 2,000 行,其中 1,950 行都是上下文污染。
研究证实了这一点。混入不相关信息时,AI 性能下降 30~85%。即使不必要的 token 是空白字符,性能也会下降。上下文越短越好,这不是直觉,而是实验结果。
别把机器人放进人类的办公室。要建造机器人能工作的工厂。
代理需要的三样东西
代理要在代码库中稳定工作,需要具备三个条件。
1. 必须可读——没有噪音
一个文件一个概念。文件名就是概念名。
before: read utils.go → 20 个函数,19 个不必要
after: read check_one_file_one_func.go → 1 个函数,正好是需要的
filefunc 解决了这个问题。它用 22 条结构规则将代码按语义单元分离。在 Hono 框架(star 23k+)上,把 186 个文件拆成了 626 个。4,419 个测试全部通过。文件增加了 3.4 倍,但逻辑一行都没变。
“文件不会太多吗?"——代理不会浏览目录,它搜索。不管是 500 个还是 1,000 个文件,一次 grep 就够了。比起挑出需要的 5 个文件,不打开不必要的 295 个更重要。
2. 必须可验证——机械地
修改没有测试的函数,没人知道会坏什么。代理也不知道。陷入 doom loop。
before: 0 个测试,修改后不知道会坏什么
after: 527 个函数有测试,行为变更立即检测
tsma 解决了这个问题。它索引项目中的每个函数,检测是否有测试,衡量覆盖率,并以行号反馈未覆盖的分支。
不给反馈让 LLM 写测试,覆盖率在 60~70% 就停了。告诉它"第 41、44、70 行未覆盖”,它就能达到 100%。同一个模型。差别只在反馈的分辨率。
在 527 个函数的项目上的实验结果:TODO 完成到 0。自主代理在 40 个时宣布"全部完成”。应用棘轮后:527 个全部完成。
3. 规范必须可交叉验证
API 模式、数据库模式、安全策略、状态转换是否彼此一致,必须能够机械地确认。改了一个地方,编译之前就必须知道是否和其他地方矛盾。
before: 200 个端点,人工检查规范一致性
after: 一个 operationId 链接所有层,机器检测漂移
yongol 解决了这个问题。它通过一个 operationId 链接 10 个 SSOT(OpenAPI、DDL、sqlc、SSaC、Rego、Hurl 等),用约 287 条规则进行交叉验证。OpenAPI 中 user_id 是 string,DDL 中却是 BIGINT——这类跨层矛盾,现有工具抓不到。
贯穿三个工具的同一结构
filefunc、tsma 和 yongol 是独立工具,但有共同的结构。
filefunc: 22 条结构规则 → validate → 修复 → 重复
tsma: 测量覆盖率 → 反馈未覆盖分支 → 修复 → 重复
yongol: 交叉验证 → 检测漂移 → 修复 → 重复
全是同一个循环。
LLM 生成 → 确定性工具判定 → 结果反馈给 LLM → 重复
Symbolic Feedback Loop。确定性工具校正 LLM 概率性生成的循环结构。不是 AI 验证 AI,而是机器验证 AI。
给它意见,它就奉承。给它事实,它就修改。问"代码没问题吧?“它回答"嗯,很好”。告诉它"第 41 行:字段名不匹配",它立即修复。没有奉承对象的反馈——因为数字和位置不是情感。
从遗留系统到 agent-operable
不需要一次性改变现有代码库。这不是打地基,而是抗震加固。在不关店的情况下加固建筑。
第 1 步——使之可读
从最长的文件开始拆分。运行 filefunc validate,把违规降到零。所有现有测试必须通过。
第 2 步——使之可验证
反复运行 tsma next。为没有测试的函数添加测试,填补未覆盖的分支。即使代理中途挂了,进度也会保留。新代理运行 tsma next 就能接着干。
第 3 步——交叉验证
引入 SSOT,运行 yongol validate。机器捕捉跨层矛盾。
每一步都是独立的。不做第 1 步也可以做第 2 步,不做第 2 步也可以做第 1 步。但三者结合起来,代理自主工作的范围会急剧扩大。
改变操作系统
agent-operable codebase 不仅仅是 lint 或工具层面的事。这是改变代码库的操作系统。
| human-readable | agent-operable | |
|---|---|---|
| 文件大小 | 人类可滚动的范围 | 一个概念 |
| 测试 | 有最好,没有靠直觉 | 每个函数必须有 |
| 规范 | 文档、wiki、口头传达 | 声明式、可交叉验证、机器可读 |
| 反馈 | PR 审查(小时级) | 验证器运行(秒级) |
| 完成判断 | 人类说"差不多了" | 机器说"还剩 487 个" |
很多人在让火车跑得更快。更大的模型、更聪明的代理、更好的提示词。
火车越快,轨道越重要。铺轨道的人几乎还没出现。
相关文章
- filefunc — 一个文件一个概念 — 用 22 条结构规则消除 LLM 上下文污染的代码结构规范
- tsma — 遗留代码的回归防线 — 基于棘轮的测试自动化,将 527 个函数完成到 TODO 0
- 编码代理为什么能用又为什么会崩 — Symbolic Feedback Loop 的结构性分析
- 反馈拓扑比模型智商更重要 — 同一个模型为什么在 40 停下或完成 527
- whyso — git blame 看不到的东西 — 文件级变更历史自动提取
参考资料
- Stanford, “Lost in the Middle: How Language Models Use Long Contexts” (2024) — 相关信息埋在上下文中间时性能下降 30%+
- Amazon, “Context Length Alone Hurts LLM Performance” (2025) — 即使不必要 token 是空白字符,性能也下降 13.9~85%
- Hono 框架实证 — 186 个文件 → 626 个文件,4,419 个测试全部通过
- tsma 527 个函数实证 — PASS 246 个(46.7%)、DONE 281 个(53.3%)、TODO 0 个
- Ratchet Pattern 实验 — 自主代理 40/527(7.6%) vs 棘轮 CLI 527/527(100%)