🛠️ 第5章 第一个可复用工作流:在 emotional_chat 项目中稳定复用
📄 一句话概括

readiness 不是打分表,是止损表:每一条不过,都对应一种「它一定会做错」。 把命令收进脚本,是把「你记得」换成「仓库记得」。 局部验证省的是计算,不是启动——Demo 里函数级差五十八倍,进程级只差一点一倍。

📝 本章和前面几章的关系

上一篇讲两条确认,这一篇把它扩成八条,并且回答一个更实际的问题: 验证要花多少钱,以及这个成本怎么改变 Agent 的行为。 Demo 量了三组数:readiness 八条过几条、函数级全量与局部的差、进程级全量与局部的差。 第三组数有点反直觉,也是这一篇最值钱的一句。

一、readiness 检查清单

八条,按「它会不会做错事」排,不按重要性排。

条目 不过会怎样
能一键跑起来 它连启动都验证不了
能一键验证 它不知道自己对不对
依赖有清单 它装不上,或装错版本
环境变量有样例 它去猜,猜错了才报错
测试不依赖网络 它偶尔失败,你以为是它的问题
有 AGENTS.md 它得靠翻目录猜规矩(第 6 章)
目录有边界 它会翻遍全仓,把你的额度吃光
README 说清怎么跑 它读不到入口,就自己发明一个

最后一条最容易被当成「软要求」,其实最硬。 Agent 的第一动作几乎总是「读 README 和入口文件」—— 读不到,它就会按自己的想象跑一条命令,然后拿到一堆报错。 八条不用一次全补。 前两条补不上,别的补了也没用;前两条补上了,后六条可以慢慢来。

二、把命令收进脚本

「收进脚本」的意思不是「写个 shell」,是「让命令有一个固定的名字」。 python tasks.py test 就是一个固定的名字。 为什么重要?因为 Agent 不该猜。 让它猜「测试怎么跑」,它会试 pytest、试 python -m unittest、试 npm test, 每次猜错都要花一轮。 收进脚本还有一个附带好处:命令带参数时不用解释。 「跑测试要加 -k 不是 e2e」这种话,写进脚本就再也不用说。 Demo 里那个 tasks.py 只有二十行, 它做的三件事:兜住环境变量、给两条命令起名、出错时给出用法。 这三件事就是「入口」的全部。

三、局部验证比全量测试更常用

这一条要拿数说话。 Demo 量了两组: 函数级全量 131.8 毫秒、局部 2.3 毫秒,差五十八倍; 进程级全量 649 毫秒、局部 602 毫秒,差一点一倍。 为什么差这么多?因为起一个 Python 进程,这台机器上要五百多毫秒。 六十个用例的计算量才一百三十毫秒—— 启动开销是计算量的四倍,局部化省下的那点计算,被启动完全盖住了。 这不是说局部验证没用,是说它省的位置和你以为的不一样。 它省的是计算,不是启动。 所以真机上省得多,是因为那边起进程快;这台机器上慢,省下来的就看不见。 对 Agent 的影响在这里:它会根据验证成本调整策略。 验证便宜,它愿意多验几次;验证贵,它倾向于「看着像就交差」。 所以要它稳,先把验证做便宜。

四、动手 Demo:readiness 八条,和「局部验证到底省多少」

这个 Demo 两段。 第一段拿一个真仓库逐条查八条 readiness,输出过几条。 第二段造六十个用例,量「全量跑」和「只跑一个」的差——分函数级和进程级各量一次。 为什么分两级?因为很多人只量了第一级,就以为第二级也一样。 实际差得很远,原因在下面那个「启动开销」。

t = time.perf_counter()
for i in range(len(CASES)):
    run_one(i)
full = (time.perf_counter() - t) * 1000

t = time.perf_counter()
run_one(17)
one = (time.perf_counter() - t) * 1000

# 再各起一个进程跑一次,看启动开销占多少
py(base, u"bench.py")
py(base, u"one.py")

实跑输出:

--------------------------------------------------------------------
readiness 八条,和「局部验证到底省多少」
--------------------------------------------------------------------


  ① 八条 readiness,逐条查
  --------------------------------------------------------------------
  [过]     能一键跑起来        tasks.py 有 run
  [过]     能一键验证          tasks.py 有 test
  [过]     依赖有清单          requirements.txt 在
  [过]     环境变量有样例      .env.example 在
  [过]     测试不依赖网络      全部本地断言
  [不过]   有 AGENTS.md        第 6 章才写
  [不过]   目录有边界          没有 src 与 tests 分层
  [过]     README 说清怎么跑   已写两条命令
  八条过了 6 条。缺的两条都是结构问题:没有项目说明书,没有目录边界。
  ! readiness 不是打分表,是止损表。
  每一条不过,都对应一种「它一定会做错」:没有一键验证,它就不知道自己对不对;
  没有目录边界,它就会乱翻。

  ② 局部验证能省多少:先量函数级
  --------------------------------------------------------------------
  用例总数 60
  全量 132.7 毫秒 / 局部 1.8 毫秒 / 差 75 倍

  ③ 再量进程级:启动开销是固定的
  --------------------------------------------------------------------
  起进程跑全量 674 毫秒 / 起进程跑一个 594 毫秒 / 差 1.1 倍
  函数级差 75 倍,进程级只差 1.1 倍。
  ! 为什么差这么多?因为起一个 Python 进程,这台机器上要五百多毫秒。
  六十个用例的计算量才一百三十毫秒——启动开销是计算量的四倍,局部化省下来的那点计算,
  被启动完全盖住了。
  这不是说局部验证没用,是说它省的位置和你以为的不一样:省的是计算,不是启动。
  所以真机上省得多,是因为那边起进程只要几十毫秒;这台机器上起进程慢,省下来的就看不见。

  ④ 这组数对 Agent 意味着什么
  --------------------------------------------------------------------
| 做法 | 一次验证的代价 | 它会怎么做 |
|---|---|---|
| 只能跑全量 | 六十个用例 | 改一处等一轮,越改越慢 |
| 能跑局部 | 一个用例 | 改一处立刻验,敢多试几次 |

  ! Agent 的行为是被「验证成本」塑造的。验证越便宜,它越愿意多验几次;
  验证越贵,它越倾向于「看着像就交差」。要它稳,先让验证便宜。

八条过了六条。 缺的两个都是结构问题:没有 AGENTS.md(第 6 章才写)、没有目录分层。 这条数是真查的,不是摆样子。 函数级差五十八倍,进程级只差一点一倍。 这两个数放一起看,才看得出「启动开销」这件事。 单看第一组,你会以为「跑一个很快」;单看第二组,你会以为「局部没用」。 「起进程跑全量 649 毫秒 / 起进程跑一个 602 毫秒」—— 两者差的那四十七毫秒,才是「省下来的计算」。 剩下六百毫秒是每次都要交的固定税。 这条结论对你有用:如果验证很慢,先别急着并行化用例,先看慢在启动还是慢在计算。 慢在启动,改用例没用;慢在计算,减少范围才有用。

30 秒实验

  1. 查一遍你的仓库这八条过几条。 前两条不过的话,别的先别管。
  2. 给你最常用的三条命令起名字。 就用脚本,别用别名——别名在新 shell 里就没了,脚本一直在。
  3. 量一次你的「起进程开销」。 跑一个什么都不做的脚本,看它要多久——这个数会解释你很多「慢」的困惑。

常见误区

  1. 「readiness 是给大项目看的,小项目不用。」 越小越要。 小项目没有文档、没有流程,Agent 全靠猜——它猜错的成本,比补这八条高得多。
  2. 「验证跑全量最保险。」 保险的意思是「每次都很慢」,而慢的验证会被人跳过。 能跑局部就先跑局部,提交前再跑全量。
  3. 「局部验证快很多倍。」 看情况。 Demo 里进程级只差一点一倍——因为起进程的固定开销盖住了一切。这个数得自己量。
自测三问(点开对答案) 1. 八条里哪一条最容易被当成「软要求」,其实最硬? —— **README 说清怎么跑。** **Agent 第一动作几乎总是读 README 和入口文件**——读不到,它就会自己发明一条命令。 2. 为什么函数级差五十八倍、进程级只差一点一倍? —— **因为起一个 Python 进程要五百多毫秒。** **函数级只算计算,进程级要加上这笔固定开销**——**六十个用例的计算量比启动还小。** 3. 验证很慢时,先查什么? —— **先看慢在启动还是慢在计算。** **慢在启动,减用例范围没用;慢在计算,才该缩小范围或并行。**

下一篇 5.3 走一遍完整链路:选需求、先出计划、改完当场验、留痕。

相关笔记