CONFIDENTIAL

Harness Engineering

CATEGORY [TECH]
CREATED 2026.03.21
UPDATED 2026.04.01
READ_TIME 15 MIN
TAGS

前言

harness engineering整体翻译过来则是驾驭工程师,这是一个3月份才出现的新词(也有可能是我火星了),该词的大致意思是ai就像野马,桀骜不驯一往直前,世界上有一群最好的骑手,他们用马鞍(codex/cc)与缰绳(spec)或者胡萝卜(鼓励性提示词工程)之类的乱七八糟的让ai按照规划跑满一个全程的项目。我很喜欢这个词,让我在vibecoding的时候有一种骑马的感觉,仿佛马儿在放开奔驰,景色飞速的倒退,狂风呜咽地刮过脸颊,而我依然在马背上稳稳的握着我的缰绳。

spec的实践与思考

人的天性是更倾向可掌控的事物,在早期的copilot时代,ai还是副驾驶,他的每一次变更我都会进行cr后再进行同意。这不能赖我过于保守,想想那个年代的ai吧,gpt4o或者deepseek。直到Claude模型,以及cursor/augment的出现改变了我,我开始将更多的自由度交给ai,比如在实习公司的各种代码。然后是到了今年2月,我正式的接触了cc/codex这种cli的编程工具。如果比作马的话,以前大概用的是观赏性马匹,这次骑上了的卢或者赤兔,不仅跑的快,脾气也大。他的脾气揭露了一个恐怖的事实 ——当你面前的只有命令行,实时的cr几乎变得不可能。当马跑的过快的时候,你要让他停下来等你观察每一步都走到了跑道上吗?

面对这种无论是外观还是使用上都和黑盒别无二致的东西,你所能做的只有祈祷他会吐出正确的代码。尤其是在将cli部署到了无图形化桌面的linux之后,你只能望着黑漆漆的终端,看着ai无情的吐出一段又一段,你不知道哪个是真正能用的,哪个是垃圾。你坐到了马背上却没拿缰绳,于是你只能祈祷ai会把你带到目的地。

spec似乎是个解法。SDD(Specification-Driven Development)这东西像是ai时代下传统软件工程瀑布流和敏捷开发的私生子。以规格文档为第一要素,代码视为规格文档的实现。让ai永远被spec驱动着。这乍一听似乎很好,你列下一条条代码军规,prd,系统架构规范或者其他什么东西,似乎ai就真的会遵守规则去写出你脑子里幻想的”整洁代码”? spec作为ai时代的软件工程,也演变了不同的路子

  1. 轻spec派:openspec 要求写代码前先写文档
  2. tdd+轻spec派:superPower 要求写完文档后还要先写测试,测试也作为spec的一部分
  3. 标准spec派:speckit , Trellis 要求完全按照需求分析 -> 计划拆解 -> 任务执行”的流水线执行,如trellis甚至靠hooks将spec的文档每轮都强制注入到ai上下文里

三种流派在我写毕设的短短一周内都接触了一遍。Trellis那繁琐的框架让我烦不胜烦,过于多的hook,每轮都要严格执行的流程在燃烧我的token,尤其是如果规范写的过于繁琐反而会影响模型的发挥,superPower的头脑风暴是很好用,可是在写一个最简单的crud代码之前都要补测试。轻spec+tdd是我正在用的,我还为此专门按生命周期给文档划分了不同的层次,让ai进行渐进式的阅读。 image.png

缺憾

好吧好吧我在欺骗谁,在这些文档的背后,我终于明白了spec本质是提示词工程,他有提示词工程或者说符号的缺点:人们总会词不达意。如果你有符号学的功底,那么借用知乎一名老哥的话就是需求是实在界的洞。你想穷尽语言,穷尽提示词去将需求描述清楚这是不可能的一件事,一旦你描述清楚了,那么说明你在写代码。sdd的本质是你在试图让真实需求与提示词之间的朦胧由一个上下文窗口指数增长的概率模型来填补,尽管ai可能已经做的足够好了,尽管他可能以后会更好,但是只要是人类的提示词还是符号,那么你就永远不可能一次把你想要的结果做出来。这不是ai的问题,这是人类的问题。

回到目前重获新生的tdd,tdd实际上在ai时代火起来是因为他可以被视为一种特殊的文档,当ai在偏离内容时会主动报错。test可以作为一种比提示词更精准的规格语言来规范ai,尽管这种语言对于过于明白的需求十分繁琐,但是对于那些跨域多条链路需要闭合的需求再合适不过了。tdd的优点在ai时代可贵起来,尽管他依旧只是在打象征界和实在界的补丁。

软件工程

让我们从拉康变回一个和ai对线的harness engineer,我们虽然不能从符号学的陷阱里逃脱出来,但是我们还有软件工程,想想我们引以为傲的软件工程!在ai时代下你就是项目经理,ai就是你的员工,你要有一套大企业的工程化的思想来领导你的ai员工,让我们从sdd的father——瀑布流开始。 作为一个从1970年Royce提出时就背负骂名的软件工程,royce在黑板上画了一个线性图他画了那个经典的“需求 → 设计 → 实现 → 测试 → 运维”流程,然后开始批评道

这种线性流程在实际项目中是有风险的,应该引入反馈和迭代

很明显,大家都没听进去,因为在2026年的今天他换了个样子复活了。 有人将所有的提示词写在agent.md里,或者干脆将所有的spec一口气全写好。一个没有经过多轮迭代的文档,一个僵死的文档,稍有差错,就好在ai这台汗血宝马的加持下立马和需求背离了十万八千里。这不能怪sdd,这只能怪那个人的软件工程没学好,如果你一开始就明确的知道需求是什么,如何设计,那么ai可以迅速的把你载到终点。可你不知道,你走到半路可能才发现路走错了,地图标识的不清楚打了电话才发现这是个拐弯处不是减速带。

于是螺旋模型又出现了,确认需求后按阶段拆功能点,控制好文档的生命周期,哪些文档该频繁被维护,哪些文档只是临时的,哪些文档过期了需要被清理。在一个阶段做完后迅速的测试,反馈,迭代,将spec文档进行更新后再进行下一阶段。这就像是赛马到达一个路口后看看地图,修复一下当前偏离的路径,再前往下一个地点。

而对于一些频繁变更需求的模型,则可以上敏捷开发,只按功能点做最小实现,借助ai做最小mvp实现。我们这次连地图都没有了,但是我们知道怎么走是错的,我们可以极快试错逼近答案

Ai以后

4年前我在方舱医院里注册了ChatGPT,我从未想过他可以取代程序员写代码的工作。2年前我让ai作为copilot辅助编程时,我没想到他可以坐上主驾驶位。几个月前我在使用cli之前,从未想到过一个拥有了shell的ai可以做到一个程序员能做到的一切。未来呢?

人月神话里面提出来了两种复杂度的概念,本质复杂度与附带复杂度。

  1. 本质复杂度是这是问题本身带来的复杂度,你无论怎么做都绕不开。你必须理解是什么复杂,去尝试理解业务本身,才能解决这个问题。
  2. 实现过程中人为引入的复杂度,比如这个编程语言的熟练度,混乱代码结构,糟糕的团队协作。 附带复杂度是可以被减少到最小的。想象一个秃头的有5年工作经验的程序员,他熟悉任何编程语言并1s中之内看出编译为什么报错,他设计出来了精妙绝伦的代码结构,他有着完美的团队精神。很明显,这些ai也能做到,随着ai的发展当1s中能写10w行代码的时候,代码结构美不美就不重要了。

软件开发的难点主要在本质复杂度,而不是附带复杂度。

这句话被很多人当成反驳vibecoding的圣经,因为目前一个经验老道的程序员比ai强的是更能迅速的正确的理解问题,理解问题比解决问题要重要100倍。ai这个概率模型哪天抽风了没有理解问题(这当然经常发生),而你也完全不理解系统的复杂度,于是在ai自我博弈左右互搏的时候整个系统的维护性就崩塌了。这声明了当前编程的一个事实,哪怕再让ai给出设计,去写代码,人总是需要去理解这个系统的,去宏观的理解这个系统的复杂度,这是为什么对于资深程序员,ai对他们解决难题的时候帮助没那么大,因为他们需要尝试理解问题。

让我们做个思维实验,此刻是2077年,人类唯一的cr就是看代码跑出来的成功符不符合预期,不cr设计,只提需求,他成功的设计了系统,在完全不理解系统的前提下。如果ai能强到没人理解复杂度,但系统长期稳定运行,那么问题来了。

“如果没人理解复杂度,但系统长期稳定运行,那‘人的理解’还重要吗?”

实际上在这个幻想里复杂度的理解主体从人变成了ai,ai代替了人思考,代替了人理解。倘若在未来AI不仅设计系统还能持续监控,自动修复问题,自己理解并演化系统。那么程序员这份职业确实该消亡了。(我为什么感觉是有可能的),想要做到这点需要

  1. ai需要解决弥补符号与实在的朦胧问题——当然也可以去尝试多重试几遍,个人认为是最大的难点
  2. ai需要解决上下文问题——也许不需要解决,人都会遗忘,在一个差不多够的上下文系统里面尝试让ai去遗忘一些不重要的东西比记住更多更有用
  3. ai要会背锅——这并不可能