AI 写代码越快,为什么我反而越没有掌控感?——一份仍在演进的人机协作实践记录

9 阅读17分钟

30 秒判断:AI 编码代理可以把系统实现得很快,但“能运行”不等于“负责人能预测、解释、干预和恢复”。本文不是一套已经验证完成的人机协作方法论,而是记录我在一个 Agent 项目中怎样从“相信设计文档和测试”,逐步发现掌控感缺口,再尝试用垂直切片、决策账本和人工确认补洞的过程。当前方案仍然只是过渡方案。

适合谁读:正在用 Codex、Claude Code 等工具开发真实项目的人;发现代码增长速度快于自己理解速度的人;需要为 AI 生成的系统承担最终责任,却不想逐行阅读全部代码的人。

系列位置:本文是《学习问答助手Agent实践》实现复盘系列的开篇。后两篇增量发布故障复盘和 HTML 解析故障复盘展示具体故障;本篇解释这些故障为什么会动摇人的掌控感。

代码库:ai-study-helper-v2

结构速览:§0 系统跑起来之后;§1 掌控感的四个维度;§2 最初的三个错误假设;§3 第一轮修补:垂直切片;§4 第二轮修补:决策账本;§5 真实故障暴露了什么;§6 当前方案的边界、外部实践与协作模式;§7 下一轮实验:控制契约;§8 尚未回答的问题;§9 一页速查。

证据标记:✅ 项目实测=在本项目中真实发生;🧪 可回归=已有测试或质量门;🤔 当前判断=根据现有实践形成的暂定结论,后续可能被推翻。


0. 系统跑起来之后

这个项目最初的目标很单纯:做一个面向普通用户的本地文档学习问答 Agent,把需求定义、架构、实现和评测完整走一遍。

AI 加入后,代码和文档的推进速度明显加快:

  • Tauri 桌面壳能启动;
  • Python sidecar 能被打包和重启;
  • HTML 能解析、切块和预览;
  • 文档身份、版本和 artifacts 能保存;
  • embedding 和双索引能构建;
  • collection 能发布;
  • 后台入库、当前知识库、操作历史和详情页逐步出现。

从功能列表看,进展很快。

但有一个感受越来越明显:

这个系统确实是我要做的,但我不再能轻松说明它在各种情况下会怎样。

不是完全看不懂,也不是不会操作,而是无法稳定回答一些本应由负责人随时回答的问题:

  • 连续导入两批文件后,库里到底有几篇?
  • 界面显示“保存成功”时,哪几层状态真的完成了?
  • 修改解析器后,旧快照还能不能继续增量更新?
  • 自动测试全绿,为什么用户还是不知道自己拥有什么?
  • 哪个决定来自设计,哪个决定是 AI 在实现时替我做的?

我开始意识到,问题不只是心理上的“不熟悉代码”,而是系统复杂度和人的控制能力之间出现了缺口。

🤔 当前判断:AI 提升的是实现吞吐量;如果控制手段不同步升级,负责人承担责任的面积会大于实际理解的范围。


1. 掌控感的四个维度

最初我把“掌控”理解成“知道代码怎么写”。后来发现,即使逐行读代码,也未必真的能控制一个持续演化的系统。

我现在更愿意把掌控感拆成四个维度:

维度要回答的问题缺失时的表现
可预测动手前,我知道系统准备怎样变化功能看起来完成了,却惊讶于真实行为
可解释当前代码和状态为什么是这样能运行,但说不清为什么这样设计
可干预方向错误时,我能在成本可承受时改选只能等交付后审核,容易被沉没成本绑定
可恢复出错后能定位、回滚并重新验证知道坏了,但不知道从哪一层恢复

这四件事都不要求人亲自写每一行代码。

传统软件团队也是通过模块边界、代码评审、测试、监控、事故复盘和回滚机制建立控制,而不是由负责人读完所有实现。

所以问题不是“AI 写了代码,所以我不放心”,而是:

AI 已经进入执行层,但项目还没有建立与它匹配的控制层。


2. 最初的三个错误假设

回看早期实践,我至少有三种过于乐观的假设。

假设一:设计足够详细,AI 就会一致地实现

设计文档确实非常重要。它保存了产品边界、目标用户、质量属性、阶段划分和不可妥协的约束。

但设计里的原则不自动等于实现中的算法。

例如:

设计原则:单知识库、增量更新
实现算法:本批结果构建新快照

这两句话并不矛盾。开发时完全可能把“本批结果构建新快照”理解为实现增量更新。缺少的是一条更具体的契约:

新集合 =
  旧活动集合中未被本批替代的文档
  + 本批成功文档

再用测试把它固定为:

导入 3 篇后再导入 4 篇,必须得到 7 篇

只有原则、算法和测试连成一条链,设计才真正约束实现。

假设二:自动测试全绿,系统就可靠

测试当然不可缺少。本项目有类型检查、单元测试、集成测试、迁移恢复、失败注入、构建和 CI。

但测试证明的是被写出来的断言。

如果没人写“连续两批入库后的总状态”,单批测试可以一直绿色。

如果没人写“点击保存后必须进入活动知识库”,接口测试也可以通过。

🧪 可回归:后来补上的连续批次、版本替换、partial、回滚和单篇完整入库测试,才把这些产品语义变成系统必须满足的约束。

假设三:最后集中确认所有决策,人仍然保有控制

为了避免 AI 擅自决定,我要求实现中的自行决策集中记录,完成后由我二次确认。

这比把决定留在聊天里好得多,但实践后暴露出新问题:

  • 决策发生在代码写完之后,改选成本已经变高;
  • 十多个决策集中出现,容易变成审批疲劳;
  • “确认”不等于真正理解;
  • 有些解释自洽,但没有独立行为证据;
  • 人看到的是 AI 对实现的总结,而不是系统实际运行的完整现场。

所以二次确认是高价值机制,但它不是完整控制。


3. 第一轮修补:垂直切片

最早采用的办法是把系统拆成垂直切片,每个切片必须有:

输入
  ↓
核心行为
  ↓
输出
  ↓
失败语义
  ↓
可运行验证

它避免了一个常见问题:AI 很快铺开很多页面、接口和模块,但没有任何一条路径真正闭环。

例如入库工作台不是只画一个上传页面,而是要把:

  • 来源队列;
  • 后台任务;
  • 阶段进度;
  • 暂停、恢复和取消;
  • 失败来源;
  • 自动发布;
  • 当前知识库更新;

连成可以实际运行的一条链路。

这一步有效提高了交付质量。

但它主要解决“有没有闭环”,没有完全解决“这个闭环是否符合负责人脑中的产品语义”。

切片可以让每个局部都有验收,却不能自动发现:

  • 两个切片组合后的行为冲突;
  • 旧切片留下的文案和接口已经过期;
  • 一条设计原则没有被任何测试表达;
  • 用户虽然能操作,却看不懂当前状态。

4. 第二轮修补:决策账本

接下来增加了切片内决策记录:

字段回答的问题
决策 ID以后怎样稳定引用
问题设计没有明确什么
选择实际采用了什么
设计依据为什么它不和设计冲突
候选与取舍其他方案为什么不用
影响改动波及哪些边界
验证用什么证明它工作
状态待确认、已确认或已否决

它带来的第一个好处是可追溯:

代码为什么长成现在这样,不再依赖某次聊天记录。

第二个好处是暴露模糊点:

如果一项实现找不到对应的设计依据,它可能不是普通细节,而是新的设计问题。

第三个好处是形成人的最终决定权:

AI 可以分析候选,但不能把所有产品级取舍都当作自己的技术选择。

但“决策账本”也不是银弹。

它记录了选择,却没有保证:

  • 人在合适的时间看到决定;
  • 人具备判断该决定所需的上下文;
  • 选择对应的系统不变量真的被执行;
  • 说明与实际代码保持一致;
  • 决定之间没有组合冲突。

🤔 当前判断:决策账本解决的是可审计性,不自动解决可理解性和可干预性。


5. 真实故障暴露了什么

真正让我重新审视流程的,不是代码编译失败,而是几个“自动测试和局部分析都没有提前发现”的问题。

5.1 每批都正确,合起来错误

先导入 3 篇,再导入 4 篇,活动知识库只剩 4 篇。

单批快照完整、索引完整、任务成功;问题出在连续操作后的集合语义。

这让我看到:

  • 设计原则必须变成操作序列测试;
  • “任务成功”只是事件,“当前集合”才是状态;
  • 局部验收无法替代系统不变量。

详见增量发布故障复盘。

5.2 旧切片完成过,不代表现在仍正确

早期预览流程只保存文档版本。后续加入 embedding、索引和发布后,旧的“保存到知识库”文案仍然存在。

每个阶段单独看都完成了,组合后的用户承诺却失真。

这让我看到:

  • 新切片必须重新审查它改变了哪些旧入口;
  • 按钮文案和数据流也是跨切片契约;
  • 自动化测试需要覆盖完整用户任务,而不只覆盖模块边界。

5.3 一个小修复可能改变全链路版本

一个合法 HTML 注释触发解析异常。修复后不仅遍历逻辑变了,正文边界和 extraction hash 也可能变化,因此解析器版本必须提升,旧 collection 还不能静默混入新版本。

这让我看到:

  • 小 bug 可能改变数据语义;
  • “修好了”必须继续追问兼容性和回归;
  • 版本号属于可复现契约,不是发布装饰。

详见HTML 解析故障复盘。

5.4 能力边界改变,评测现场也必须改变

原计划的一篇评测材料只有 PDF,而当前产品明确不支持 PDF。

如果偷偷转换成 HTML,系统可以继续“演示”,但原始来源和评测基线会被破坏。

最终改为使用当前 15 篇 HTML 组成新的冻结快照,并记录 ADR。

这让我看到:

  • 评测语料不是越接近理想越好,必须与产品真实能力一致;
  • 能力边界变化要进入版本和基线;
  • 诚实保留缺口,比制造完整假象更有价值。

6. 当前方案解决了什么,没解决什么

当前采用的是:

设计基线
  + 垂直切片
  + 决策账本
  + 自动测试
  + 人工二次确认
  + Git 历史

它已经解决:

  • 不再依赖聊天保存关键决定;
  • 每个切片有输入、输出和失败语义;
  • 产品原则可以逐步转成测试;
  • 高风险决定能明确交给人;
  • 代码变化有对应文档和历史。

它仍未完全解决:

  • 人在什么时候最应该介入;
  • 如何避免最后集中审批造成判断失真;
  • 如何让负责人快速形成新的系统心智模型;
  • 如何证明人真的理解关键行为,而不只是点了确认;
  • 如何识别“局部都正确、组合后错误”的跨切片问题。

所以我不把它看成最终方法,而是一个已经开始有效的中间状态。

6.1 外部实践只能提供假设

知识库里正好有 OpenAI 的《Harness engineering: leveraging Codex in an agent-first world》。它提出“人掌舵、Agent 执行”、仓库知识作为事实源、让环境对 Agent 可读可执行、通过反馈回路迭代等观点。这些观点很有启发。

但它不是可以逐条照搬的操作手册。

那篇实践来自 OpenAI 的工程团队、成熟代码库、内部产品和特定工具链。它没有替我回答:

  • 一个人与 AI 协作时,什么时候必须亲自介入;
  • 怎样避免十几项待确认决策造成审批疲劳;
  • 什么证据足以让我重新相信系统;
  • 本地桌面应用的数据恢复和不可逆操作应由谁把关;
  • 处在学习、开源和产品化三重目标下,流程成本应该如何取舍。

所以我把外部经验按三层处理:

类别例子采用方式
硬约束数据不可静默丢失、凭证不落盘、失败不能伪装成功本地验证后直接采用
工作假设中途检查、决策分级、证据包、反向解释在自己的切片中试行
个人偏好一次审多少决定、先看界面还是测试、文档写多细根据实际认知效果持续调整

外部案例证明“某种做法在某个上下文里有效”,不能证明“它在你这里也有效”。

6.2 不必寻找唯一的协作模式

我一开始想找一套适用于所有任务的方法。后来发现更现实的目标是建立一组按任务切换的模式:

任务更合适的协作方式
产品定义、边界与非目标人主导,AI 做反方和结构化整理
架构探索人机共同讨论,AI 提供候选和失败预演
已定契约的实现AI 主导,人检查关键不变量
复杂故障定位结对调试,AI 管证据,人确认根因
文档与文章AI 起草,人决定价值、取舍与叙事
删除、迁移、发布人明确批准,AI 提供恢复路径

真正需要学习的不是“哪套流程最好”,而是:

当前任务应该进入哪种人机分工模式?

6.3 流程规则也必须能够退役

每次遇到问题就新增一条规则,很容易产生流程债务:

  • 规则都有过合理原因;
  • 组合起来却越来越重;
  • 人开始为了满足流程而工作,而不是为了得到可靠结果。

因此每条试行规则都应回答:

  • 它要防住什么具体失败;
  • 适用于哪种风险和任务;
  • 使用成本是什么;
  • 有什么本地证据;
  • 什么时候复核;
  • 下次继续、调整还是删除。

协作方法需要像代码一样演进,但它不应只增不减。


7. 下一轮实验:控制契约

下一阶段准备把控制点继续前移,在切片开始前增加一页“控制契约”。

这套调整已经记录为仓库中的 ADR 0007,并新增了切片控制契约与证据包模板。它是一种待验证的实验,不是因为写进 ADR 就自动有效。

7.1 开始前先定义

  • 用户可观察到的完成目标;
  • 最多 3~5 条核心不变量;
  • 明确禁止的行为;
  • 主要失败语义;
  • 预计需要人工判断的风险点;
  • 本切片打算在哪个时点做中途演示。

它不替代详细设计,只负责回答:

这个切片完成后,负责人必须能够相信什么?

7.2 决策分级

不再把普通实现细节和产品风险放进同一张审批表。

A 级:AI 可自主决定

  • 不改变公开接口、数据语义和用户行为;
  • 有明确设计依据;
  • 可自动验证。

B 级:完成后集中确认

  • 设计给了方向但缺具体算法;
  • 可回退;
  • 有影响,但局限在当前切片。

C 级:执行前必须停下来

  • 数据删除、安全边界、不可逆变化;
  • 突破产品硬约束;
  • 新增高风险依赖;
  • 无法可靠回退。

项目的学习目标仍然保留一个更严格的要求:所有实质性的自行决策都要留下记录。但记录、确认和执行前阻断不是同一强度。

7.3 中途可运行检查点

对于涉及数据流、任务状态、存储或用户主流程的切片,不等全部完成才展示。

在第一条主路径能运行时,先检查:

  • 数据实际走到哪;
  • 用户会看到什么;
  • 失败会留下什么状态;
  • 当前实现是否偏离控制契约。

7.4 完成证据包

交付时不仅给“已完成”,还要给:

证据回答的问题
可运行入口我怎样亲自操作
自动化命令哪些行为被机器验证
失败探针失败路径是否真的触发过
不变量映射每条核心原则由哪个测试保证
已知风险哪些问题仍然存在
人工验收动作我只需检查哪几个关键流程

7.5 反向解释

最后一个控制点不是“你确认吗”,而是让负责人独立回答几个行为问题。

例如:

  • 连续导入两批文件,数量应该怎样变化?
  • 单篇失败会不会删掉以前成功的文档?
  • 回滚后继续导入,基线是什么?
  • 清空知识库会删什么、保留什么?

如果负责人答不出来,说明系统还没有真正变成可掌控的合作成果。


8. 尚未回答的问题

这套新流程还没有经过完整验证,以下问题仍然开放:

  1. 一个切片最多能承载多少个需要人判断的 B 级决策,才不会造成审批疲劳?
  2. 中途检查点应该在哪一层出现:第一条用户路径、第一次真实发布,还是第一个失败样本?
  3. 自动测试能否表达大部分产品不变量,哪些必须依赖人?
  4. 负责人应该检查代码、数据流、运行界面,还是三者按风险组合?
  5. 当 AI 的解释与实现不一致时,怎样快速发现?
  6. 如何衡量“掌控感”真的提高,而不是流程看起来更完整?
  7. 新加入的开发者或另一个 Agent,能否只靠仓库恢复同样的系统模型?

我暂不声称这些问题已经有答案。

本文记录的价值,正是它们还没有答案。


9. 一页速查

最初的问题:

系统快速实现
但负责人无法稳定预测、解释、干预和恢复

这不是单纯心理不适:

责任范围 > 当前理解范围

已经尝试:

  • 设计基线;
  • 垂直切片;
  • 决策账本;
  • 自动测试;
  • 人工二次确认;
  • Git 和 ADR。

它们解决:

  • 可追溯;
  • 局部闭环;
  • 高风险决定有人负责;
  • 历史可恢复。

还没有完全解决:

  • 决策出现得太晚;
  • 人工确认不等于理解;
  • 跨切片组合仍然可能错误;
  • 负责人难以持续更新系统心智模型。

下一步实验:

控制契约
  + 风险分级
  + 中途可运行检查点
  + 完成证据包
  + 负责人反向解释

对方法本身的要求:

  • 外部实践是案例,不是标准答案;
  • 当前任务决定协作模式;
  • 每条规则都要记录成本、证据和复核时点;
  • 方法必须允许调整、降级和退役。

当前最重要的一句话:

人-AI 协同的目标不是让 AI 多写代码、人少做事,而是让责任、理解、决定和验证始终对得上。