一个「AI 优先」的框架是怎么炼成的:五轮 AI 实测全记录
我们让完全不了解框架的 AI Agent 独立完成开发任务,前后五轮, 累计发现并修复 20 个真实缺陷,一次成功率从 0.5 提升到连续三轮 1.0。 这是完整、未经修饰的数据。
一个反直觉的结论:五轮下来,每一轮 AI 都能发现 3~5 个我们没想到的问题。 所以我们把"让 AI 实测"变成了框架开发的固定环节,而不是一次性验证。
为什么做这个测试
市面上的后台框架都在说"对 AI 友好",但没人给出可验证的证据。
我们决定用一个笨办法:找个 AI,给它文档,让它干活,看它会不会出错。
测试方法固定,五轮一致:
| 项 | 设定 |
|---|---|
| 被测对象 | 一个完全不了解本框架的 AI Agent |
| 提供材料 | 框架文档 + MCP 工具 + 自省接口(第三轮起加文档站) |
| 禁止事项 | 不许读框架源码(第三轮起明确禁止) |
| 人工干预 | 零。不给提示、不纠正、不补充说明 |
| 评分标准 | 一次生成即可运行 = 1.0;需 1 次修正 = 0.5;需 ≥2 次或人工介入 = 0 |
| 复核方式 | 父 Agent 独立复现 AI 的每一项结论,不轻信自述 |
第五轮的特殊设计:任务描述改用业务语言,故意不提 API 名 —— 测的不再是"能否照抄 API",而是"能否自己发现框架有这个能力":
| 任务给的说法 | 期望 AI 自己找到 |
|---|---|
| "部门有上下级关系,要能直观看到层级结构" | tree() 方法 |
| "列表要能导出成表格文件" | $grid->export() |
| "表单内容较多,希望分成几个步骤填写" | $form->step() |
五轮结果
| 第一轮 | 第二轮 | 第三轮 | 第四轮 | 第五轮 | |
|---|---|---|---|---|---|
| 一次成功率 | 0.5 | 0.5 | 1.0 | 1.0 | 1.0 |
| 框架纠错贡献 | 0% | 50% | 100% | 100% | 100% |
| 是否读源码 | 读了 | 读了 | 没读 | 没读 | 没读 |
| 任务要求满足度 | 部分 | 7/7 | 7/7 | 9/9 | 8/8 |
第五轮最有价值的验证:三项新加的框架能力(树形结构 / 数据导出 / 分步表单) 全部被 AI 自主发现并使用,且它在代码里逐条标注了需求对应关系 —— 证明是"理解需求后主动检索能力",而非碰运气。
发现路径是 MCP search-docs(不是文档站):
search-docs {"query":"树形结构"} → tree()->parentColumn() / titleColumn() / draggable()
search-docs {"query":"导出"} → export() 开启 CSV 导出,未开启时导出接口返回 403
search-docs {"query":"分步表单"} → step() 声明分步表单的步骤,后续字段归属该步骤"框架纠错贡献"是什么:AI 出错后,是框架的错误信息帮它改对的, 还是它自己读源码/靠经验猜出来的。这个指标比成功率更重要—— 它衡量的是框架本身是否具备纠错能力。
第一轮的真相:AI 最终交付的代码是正确的,但它是先读了框架源码才写对的。 这否定了「AI 优先」的核心假设 —— 所以记为 0.5,而不是看起来更漂亮的 1.0。
值得一提的是,这个判断是被测 AI 自己提出来的。它在报告里写: 「我一次写对了最终代码,但那是因为我在写之前先读了框架源码, 而不是因为框架帮我纠错。」
20 个真实缺陷
四轮测试累计发现并修复的缺陷。按严重程度排序:
致命级
| # | 缺陷 | 后果 |
|---|---|---|
| 1 | 验证器只查语法、不查需求达标度 | 脚手架漏 3 条需求仍报「✅ 通过」,AI 会把绿灯当交付标准,交出残次品 |
| 2 | 验证器假阳性:只读声明不验证运行时 | 报「每页 30 条 ✅ 已设置」,但 API 实际返回 20 —— 声明写了却没生效 |
这两个是同一类失效的两种表现:只验证声明,不验证真实行为。
高危级
| # | 缺陷 | 后果 |
|---|---|---|
| 3 | MCP query-data 搜索静默失效 | 传关键词返回全表。静默失败比报错更危险 —— AI 会以为数据本来就这样 |
| 4 | did_you_mean 实际返回 null | 文档承诺的字段不存在,AI 拿不到修正建议 |
| 5 | did_you_mean 在真实路径被丢弃 | 异常本身带建议,但 Verifier 捕获后只取 message,AI 只看到笼统的"编译失败" |
| 6 | 未知 query 参数静默忽略 | 用 order=desc 代替 direction=desc → 不报错、返回未排序结果,而校验器仍报「可排序 ✅」 |
| 7 | search-docs 数据分叉 | 与 capabilities.json 不同源,缺了新展示器 —— 恰好是任务要用的两个 |
中低级
| # | 缺陷 | 后果 |
|---|---|---|
| 8 | 文档示例用实例属性 + 非静态方法 | 照抄示例跑不起来(真实基类三方法全 static) |
| 9 | $show->field()->dateTime() 必然致命错误 | Field 基类缺该方法 |
| 10 | perPage() 无任何文档 | AI 唯一查不到、只能抄参考实现的语法 |
| 11 | scaffold-resource 引用不存在的 Model 却零提示 | 生成 use App\Models\Course,但该类不存在 |
| 12 | 幽灵列静默通过 | 拼错列名不报错,该列在结果中凭空消失 |
| 13 | 未注册的 Resource 也能「全绿」 | 注释掉 Provider 注册后,两项校验仍报成功 |
| 14 | map() 整数键被序列化成数组 | PHP 会把 "0"/"1" 转回整数,前端 map[key] 取值失败 |
| 15 | 文档声称检查「路由/权限/迁移」,实际只做语法校验 | 过度承诺 |
第五轮新增(验证 M5 新能力时发现)
| # | 缺陷 | 后果 |
|---|---|---|
| 16 | 需求校验器对未知键静默通过 | 喂 {"tree":"zzz","bogus_key":"x"} 返回「✅ 全部需求已满足」(空核对块)—— AI 以为已验证,实际什么都没查 |
| 17 | draggable() 是幽灵能力 | 编译产物有 draggable:true,但前端零拖拽实现。比缺功能更糟 —— 它给出虚假承诺 |
| 18 | /__ai/schema/{uri} 丢失新元数据 | grid 返回扁平数组,丢掉 perPage/exportable/tree;form 丢掉 stepped/steps。AI 唯一的自查接口看不到新能力 |
| 19 | 文档站内容陈旧 | M5 改完后忘了重新生成,站点缺导出/树形/分步三节 |
| 20 | 重复唯一值返回 500 而非 422 | 用户看到"服务器错误",不知道是编码重复 |
三条写进代码的教训
教训 1:校验器只读元数据 = 假阳性工厂
任何"已设置"的断言,都必须有对应的运行时验证。
- $actual = $node->meta['perPage']; // 只读声明 → 假阳性
+ $actual = $this->runtimePerPage($node); // 真跑一次分页 → 可信修复后的输出:✅ 每页 30 条 — 已生效(运行时实测 30 条)
教训 2:同一份信息有多个来源 = 迟早分叉
缺陷 7 的根因:新增展示器时只改了 Capabilities, SearchDocs 里还有一份硬编码的旧列表。
解法不是"记得同步更新两处",而是让它们同源 —— 现在 SearchDocs 从 Capabilities 动态取数,并加了回归测试:
// Capabilities 里有的,search-docs 必须也有
foreach (array_keys((new Capabilities)->columnOptions()) as $option) {
$this->assertStringContainsString($option.'()', $text);
}教训 3:异常携带的上下文不能在捕获时丢弃
// 修复前:AI 只看到笼统的"编译失败"
catch (\Throwable $e) {
$issues[] = ['message' => '编译失败: '.$e->getMessage()];
}
// 修复后:保留完整可自愈信息
catch (\Throwable $e) {
if ($e instanceof AiReadableException) {
$issue['did_you_mean'] = $ctx['did_you_mean']; // 是否想用 teacher_email
$issue['available_columns'] = $ctx['available_columns'];
$issue['example'] = $ctx['example']; // 可粘贴的修正代码
}
}教训 4:校验器的"沉默"比"报错"更危险
第五轮 AI 做了个探针实验,把不认识的需求键喂进校验器:
// 输入
{"tree": "zzz", "export": "zzz", "step": "zzz", "bogus_key": "x"}
// 输出
## 需求核对
(空)
✅ 全部需求已满足它不报错,也不核对 —— 直接给了绿灯。
这跟第四轮的"假阳性"是同一类问题的不同表现:
校验器一旦沉默,AI 就失去了判断依据。
修复后:
❌ 未知需求键: bogus_key — 校验器不认识这个键,它不会被核对
修正: 受支持的键: searchable, sortable, required, columns,
fields, per_page, tree, export, step原则:「校验器不认识这个键」和「这个键校验通过」必须是两件事。
AI 自发做对了什么
测试中最有价值的观察:AI 会主动怀疑框架的"绿灯"。
第三轮 AI 自己设计了反向对照实验:
| 验证项 | 方法 | 为什么这么做 |
|---|---|---|
| perPage 是否真生效 | 插入 30 行自有数据 | 当时表里只有 3 行,断言不可证伪 |
| searchable 是否真过滤 | 用只存在于非搜索列的关键词搜,必须返回 0 行 | 证明关键词没泄漏到非搜索列 |
| required 是否只是 UI 星号 | 直接 POST 缺字段 | 确认后端真拦截 |
| sortable 是否真改变顺序 | 对比 asc/desc 的实际返回序列 | 不只看 HTTP 200 |
它还专门做了负向测试:故意改坏 4 条需求,验证校验器能否全部报出 —— 4 条全中,它才敢相信校验器的全绿。
第五轮它又升级了手法 —— 当怀疑 draggable() 只是写进 JSON 没实现时, 它没有读源码,而是:
dump 真实 HTTP 响应的 HTML,统计
dragstart/drop/pointerdown事件 handler 的出现次数 → 结果为 0 → 确认前端没有拖拽实现
用运行结果证伪声明,而不是靠读源码或猜测。
这给框架设计提了个要求:校验器必须可被证伪。 如果 AI 无法独立验证"绿灯是否可信",它就只能盲信 —— 而盲信会致命。
AI 说框架哪里最难用
原话摘录(未经修饰):
$grid->perPage(15)的写法在文档站完全不存在。 我 grep 了全部页面…最终是从已有参考实现OrderResource.php抄来的。
这是最危险的一类 bug:错误参数不报错,静默返回未排序结果。 而校验器说「可排序: priority ✅ 已满足」—— 它只验了声明,没验运行时。 如果我只信校验器就会交付一个"排序实际靠猜参数"的接口。
scaffold-resource 生成残缺代码却零告警。 如果我直接交付 scaffold 输出,8 条标准会挂 3 条。
复现方式
测试完全可复现。任何人都可以:
# 1. 准备环境
composer create-project laravel/laravel:^12.0 demo
cd demo && composer require aimanong/framework
php artisan aimanong:install
# 2. 建一张表
php artisan make:migration create_products_table
# 3. 启动 MCP Server,让你的 AI 客户端连上
php artisan mcp:start aimanong
# 4. 给 AI 的任务(示例)
# "为 products 表创建管理后台 Resource,
# title 和 sku 可搜索,price 可排序,
# 每页 20 条,price 用金额格式展示"关键:验证时要求 AI 传 requirements 参数,否则校验器只查语法、不查需求达标度。
我们仍在改进的地方
诚实记录已知不足:
| 问题 | 现状 |
|---|---|
方法名拼错($form->texte())无建议 | PHP 在调用前就抛 Error,走不到模糊匹配。修需 __call 兜底,与"零魔法"约定冲突,权衡中 |
/__ai/schema/{uri} 与 schema.json 结构不一致 | 前者 grid 是扁平数组,后者是 {perPage, columns} |
scaffold-resource 不知道用户需求 | 脚手架能读表结构,但"要哪些列可搜索"是任务信息。正确解法是 AI 主动传 requirements |
结语
一个「AI 优先」框架的好坏,不该由它的宣传语判断,而该由AI 实际用它的表现判断。
我们把这个过程完整公开,包括每一轮失败的数据和每一个被 AI 发现的自己的 bug。
如果你发现我们漏了什么,欢迎提 Issue。
测试环境:PHP 8.2.29 / Laravel 12.69.3 / 四轮分别针对 users、orders、tickets、courses 四张表完整原始记录见仓库 internal-docs/AI实测记录.md
