AI 做需求覆盖审计时 grep 抽样的致命误报
让 AI 对着一份 H5 原型或代码库,做「需求文档覆盖率 gap 分析」,看起来是个标准任务。AI 扫一遍页面列表,grep 几个关键词,输出一张"缺失功能清单"——快,干净,自信。
然而这张清单很可能有一半是假的。当你把它发给熟悉产品的同事,他们会在 30 秒内指出:「这几个功能明明都有,你确定认真看过了吗?」
现象
AI 领到任务:「对比需求文档和现有原型,列出未实现的功能点。」输出了 8 条 gap,其中 7 条其实已经实现——只是藏在 section 内部,而不在页面标题或 navbar 文字里。
用户反馈:
"你确定你认真去调研过了吗?你去看线上的 HTML 来核实一下。"
AI 回去 grep 了 6 个关键词,发现:筛选条件、报名费字段、协议历史版本、物流查询入口、颜色配置面板、授权说明——全部存在,只是命名和 AI 猜测的关键词不一致。
8 条 gap,7 条误报。
根因
原型和代码库里的 UI 特性是「声明式」的:一个颜色选择器可能是 6 个 <button class="sw"> 组成的 swatch 行,grep 颜色 或 swatch 未必命中;一个草稿保存功能可能写作「暂存」;物流查询可能在订单详情页的第三个 tab 里。
关键词存在 ≠ 特性存在;关键词不存在 ≠ 特性缺失。
AI 的捷径是:列出所有 section/page 的标题,对每个需求点 grep 关键词,命中就标 ✅,未命中就标 ❌。这本质上是用「命名检索」代替「内容阅读」,而 UI 实现的特性几乎不会直接把需求文档关键词写进组件名。
grep '关键词' mockup.html 返回零行,不是「功能不存在」的证据。
它只能说明这个关键词没有字面出现。实现可能用了同义词、子组件嵌套、条件渲染、或完全不同的 copy 文案。发给用户之前没有 Read 完整 section,等于把「没找到」说成了「没有」。
正解
硬规则:在声明某个功能缺失之前,必须完整读完最可能承载该功能的 section——不是 grep,是 Read。
具体做法:
- 先做需求→section 映射:每条需求点对应哪几个 section(按语义主题,不按关键词)。
- 逐 section 全文读取:用 Read 工具带
offset+limit覆盖整个 section 体,不要只读标题行。 - 三态标注,不是两态:
- ✅ 已确认存在 — 在 section X 第 N 行看到具体实现
- ❌ 已确认缺失 — 读完全部候选 section,无实现(附行号区间为证)
- ⚠️ 部分实现 — 功能存在但与需求描述有出入
- 缺失结论必须附行号佐证:「我读了 section X(第 A–B 行),未发现字段 Y。」没有行号的 ❌ 不可发出。
# 正确路径示例
读 section [订单详情](offset=4200, limit=120)
→ 发现第 4265 行:<li class="logistic-btn">查看物流</li>
→ 标注 ✅ 物流查询,附 line 4265
读 section [赛事报名](offset=4680, limit=80)
→ 发现第 4706 行:<label>报名费(可选)</label>
→ 标注 ✅ 报名费字段,附 line 4706
每一条「功能缺失」的结论背后,必须有一次完整的 Read(覆盖完整 section body)作为支撑。
Read 一个 section 的代价:1 次工具调用,约 3 秒。
一条误报的代价:用户信任损失 + 多轮纠错 + 本次会话所有判断的可信度归零。
成本不对称极端倾斜,默认全读,不要抽样。
一句话外卖
对 UI 做特性存在性审计时,「grep 未命中」是无效证据;只有「读完 section 全文,未见实现」才是可发出的缺失结论。