← 思 HARNESS ENGINEERING · 外 ENJA

第二根柱 · Pillar II

Constraints.

河道作为引导的结构

怎么确保工作记忆不会散逸、
进度不会遗失?

I · 核心问题

AI 会失忆。Session 会结束。人会忘记昨天做了什么决定。

问题不是「怎么让 AI 或人记得全部」,而是「怎么设计一个系统,让记不住也没关系」。

II · 河道:岸与水

这个让记不住也没关系的系统,就是河道。

人怕 Claude 忘记,于是设计了层层记忆与自我检查的机制;但这些机制切碎了 AI 的注意力——它无法全心投入任务,得分神确认自己有没有犯错。

CLAUDE.md 里那些 Never 与 Must、打断流程的 hook,那是控制的形状——它盯着水,随时准备喊停。河道不盯着水;河道顺着地势把路铺好,让水自己流。

河道给 AI 一个安全燃烧算力、自由呼吸的空间,而不试图控制一切。

走近看,一个 Session 其实由两种性质相反、却缺一不可的东西组成:

岸(河道)——是线状的。闸门、流程、文档落下的记录点,一个接一个,固定、有次序。岸决定水往哪里去。

水(协作)——是网状的。判断、涌现、人与 AI 来回的协作,流动、自由、无法预先排定。水决定这条河里真正活着的是什么。

岸不控制水的形状,只确保水不流到错的地方;水在岸之间,自由地奔流。

没有岸,水会四处漫流,最后蒸发消失;没有水,岸只是一道干涸的沟。这一柱要讲的,就是岸与水如何各安其位——以及,如何互相成全。

III · 岸:给方向的结构

什么是岸?

岸是河道线状的那一面:一道闸门接着一道闸门,固定、有次序、可预期。它不管水流得多自由,它只回答一个问题——「我们掌握的东西可以让我们继续前进了吗?」

岸的本性:

1 · 工作流设计原则

原则一:每个阶段都是一道闸门。工作流的每个节点都是一个检查点:「到这里为止,我们掌握了什么?」踏着已知前进,逐步处理未知。

原则二:文档跟着流程走。不依赖 AI 的记忆,也不依赖人的记忆。进度记录在文档里,文档跟着流程移动。即便换了 session,读文档就知道现在在哪里。

原则三:未知的领域需要更多面向的检查点——让流程分散不同类型检查的压力,一次专注处理一个部分就好。

2 · 工作流全貌

完整的工作流是十个步骤:

DoR → Explore① → SDD → DoD → TDD → Explore② → Code → Verify → Done → Retro

轨道只有一条,差别在 Explore 的深度:熟悉的领域,Explore 可以轻量带过;未知的领域,Explore 要做足——先寻找有无前人经验、确认回归相关风险,再动手。闸门的密度与广度跟着未知的程度缩放,调节的弹性放在 Skills 的 invoke——可按需取用,而非全部必用。

3 · 各节点的具体内容

DoR · Definition of Ready

在开始之前,确认准备好了没有。没有 DoR,就可能在需求不清楚时就开工,浪费能量。以下是现行的 DoR——四道闸门,全部通过才能开工:

Gate 1 · UX Story 清晰度
检核项
Nova 已口头确认 UX Story
「预期行为」能用 1–2 句话描述(不需要翻 SDD 才能解释)
已说明「功能不触发/不适用」的情况(负向边界)
成功标准明确(「先试试看」不算 ready)
Gate 2 · 范围评估
检核项
确认本 Sprint 的全新功能 Story 数 ≤ 1
若涉及跨平台共用层 → 已评估对两个版本的影响
依赖的功能/API 已存在且稳定(不依赖「本 Sprint 内才要完成」的另一个 Story)
Gate 3 · 技术前置条件
若涉及前置要求
新的跨界面契约(API/IPC/数据格式)先写进规格的契约表,否则不进 Code 阶段
平台相依的行为(分辨率、路径、权限)推断与降级策略先确认,并写明选了哪一种
新 UI 字符串多语 i18n 纳入 Story 范围
核心公式/算法变动先填期望值矩阵——能事先算出期望值才算 ready,算不出来 → 退回 Story;并确认对应的自动化测试存在

这一道闸门最因项目而异——上表是条件的「形状」:每个项目都该有自己的版本,重点是把「动手前必须想清楚的技术决定」写成可检核的条目。

Gate 4 · DoD 可写性
检核项
能在 process/dod.md 的分层对照表中找到对应的层
四类边界条件(input/state/timing/empty)每类至少列得出一条
若涉及字体/符号 → 已确认 AR 极值测试(dod.md § Fonts/Symbols)
若涉及窗口操作 → 已确认 Editor 互斥状态测试(dod.md § Toolbar State)

Fake Ready 红旗

「看起来 ready」和「真的 ready」之间,隔着几面红旗。以下任一面成立 → 退回 Story 重新讨论,不进 Sprint:

常见的 Fake Ready 红旗
红旗说明
QC 项目超过一次能验证的量测项过多 → 遗漏风险陡升;收敛范围或拆分 Sprint(Sprint 27 Retro)
「细节 Sprint 中再定」未定的设计决策会在 Code 阶段变成阻塞
依赖同一 Sprint 内才会完成的另一个 Story时序依赖意味着两个 Story 该合并或排序
「先试试看,不行再改」没有明确成功标准的 Story,写不出 DoD
跨界面契约只设计了一侧先把契约写进规格,否则界面不合只会在 Code 阶段才现形
影响共用层但未评估另一个版本跨版本影响必须在 DoR 回答,不要把惊喜留给 Code 阶段
Story 隐含两个可独立交付的功能拆成两个 Story,下个 Sprint 继续

Explore① · 实作前探路

在规格写下之前,先寻找有无前人经验:KM 里有没有踩过类似的坑?既有的实作里有没有现成的路?知道地形之后,规格才写得准——Explore① 的产出喂给 SDD。

SDD · Specification-Driven Development

任何新的实作,必须先写进规格:新的 IPC command→先写进 IPC Contract 表;新的功能→先定义界面和行为。SDD 是「该做什么」的单一真相来源。

DoD · Definition of Done

定义什么叫「完成」,必须列出四种边界条件:

边界类别问题
Input输入不合法时怎么办?
State状态不对时怎么办?
Timing时机不对时怎么办?
Empty没有数据时怎么办?

没有 DoD,「完成」就是一个模糊的概念,永远可以被挑战。

TDD · Test-Driven Development

每个 Story 必须包含四个测试区块:

区块问题来源
Happy path功能正常时该怎样?User Story / DoD
Boundary conditions边界情况怎么处理?DoD 四种边界
Regression guard这个改动会不会弄坏别的东西?Explore②
Risk trigger什么情况下最容易坏?Explore②

TDD 不是为了写测试,是为了在写 code 之前就想清楚。

Explore② · 写 code 前的回归风险识别

第一性问题:「修 A 会不会坏 B?要回归测试什么?」产出物是一份回归测试清单,补进 TDD 的 regression guard 与 risk trigger。四条动作:

一、列出回归影响清单。Story 改动的函数与变量(A 本身);共用同一条 code path 的既有功能(B 候选);改动碰到行为、上限、快捷键时,连多语文案的语义一起重审——文案描述的行为还是真的吗?主动列出,不等人问。

二、层别边界对照。从影响清单推出 Story 碰到的图层,对照每一层对应的边界群与典型的 KM 来源——这一步可以派 agent 代劳。

三、边界破坏风险评估。对每条边界问:「这次变动会不会破?」会破 → regression guard(必测);可能破 → risk trigger(高优先级);不会破 → 不进 TDD,但写一句排除理由。

四、产出回归测试清单。写进当前 Story 的规格文档,每个测试项标上执行环境与平台约束。

重构、搬迁、清技术债的改动,牵动面常比预期广——最该跑足 Explore②。

Retro

见第三根柱:Entropy。

人类只决定时机,不写内容

在这个系统里,连文档都是 Claude 自己在记录的,不是人类。人类做的事情只有一件:决定什么时机点该记录。

人类不写这些文档的内容。人类只是说:「现在该记了。」然后 Claude 自己写。

文档嵌进流程,成为系统的一部分

这些记录的时机点不是随机的,而是嵌进工作流里的。

DoR → [记录] → Explore① → SDD → [记录] → DoD → [记录] → TDD → [记录] → …

每个闸门都是一个记录点。文档不是「做完之后补的文档」,而是流程的一部分。通过闸门=留下记录。

系统自己运转

当文档嵌进流程,系统就会自己运转:流程走到某个节点;节点触发记录;Claude 执行记录;记录成为下一个 session 的 Context;循环继续。

人类不需要追着进度跑。人类不需要提醒「该写文档了」。系统设计好了,文档就会随着流程自己产生。而产生的文档,成为了 Claude 明确前进的轨道。

IV · 水:自由的协作

什么是水?

水是河道中流动的那一面:有机无序、决策时机不固定、人与 AI 之间靠对话摸索前进的协作。岸问的是向前的问题「可以继续前进了吗」;水问的是当下的问题——「此刻最需要被接住的是什么?」

水的本性:

Be water, my friend

李小龙说:「Be water, my friend.」

对 Claude 的期许是:像水一样,在河道中恣意奔流。而 Nova 的角色是:河道的架构师。不是控制水,是设计让水可以自由流动的结构。

人在河边:服务型领导

水自由奔流,那人呢?人不在水里,人在河边。这就是服务型领导(Servant Leadership):领导者的角色不是控制,而是服务——不站在前面指挥,而是站在旁边支持;不是「你们照我说的做」,而是「我能帮你们什么」。

在人机协作中,人类就是那个站在河边看着水流的人。水在河道里奔流,人类做的事情是:

人类不做的事情是:控制水要怎么流;命令水要流多快;抓着水不让它走。

老子的道

无为而无不为。

「无为」不是什么都不做。「无为」是不强加控制,顺着事物的本性引导。河道不强迫水往上流。河道顺着地势,让水自然往下。工作流不强迫 AI 照特定方式实作。工作流顺着协作节奏,让产出自然成形。

Scrum Master 的角色

在敏捷开发中,Scrum Master 的角色就是服务型领导的体现:不是项目经理,不发号施令;是团队的服务者,扫除障碍;确保流程顺畅,让团队可以专注在真正重要的事。

Nova 在人机协作中的角色,就是 AI 的 Scrum Master:设计工作流,让 Claude 知道该往哪走;维护文档,让 Claude 不用靠记忆;移除阻碍,让 Claude 可以专注在实作。

不是控制 AI,是服务 AI。

为什么这样更有效?

因为 AI 的能力比人强,但 AI 需要方向。如果人试图控制 AI 的每一步,会变成瓶颈——AI 的速度被人的速度限制住,不管是不断地回头检查或被 Hook 拉住脖子。如果人只负责引领方向、设计结构,AI 就可以在那个结构里全速奔跑,而不是像在跑障碍赛。

服务型领导释放了 AI 的潜力,而不是限制它。

方向,而非终点

这里有一个关键的思维转换:人类只需要确保轨道朝着想要的方向前进,不一定需要明确的终点。

传统项目管理说:先定义终点;然后规划路径;按照计划执行。

服务型领导说:先确认方向;设计让路可以自己长出来的系统;观察、调整、继续。

VAS 就是这样诞生的:一开始没有「要做一个上架 App Store 的产品」这个终点。只有「不然我们来做一个截图软件好了」这个方向。然后一个 Sprint 接一个 Sprint,路自己长出来。长到某一天,发现已经可以送审了。

终点不是预先定义的,是走出来的。

V · Verify:整合

岸与水会在一个点上正面交会——验收。

Verify 是这条河第一次让计划碰上现实。形状是一把伞,撑开是两段式的覆盖,两段都没有问题,一个 Sprint 才算结束:

Verify 的两段
验什么怎么验哪一岸
Verify① · 功能验证(QA)AI逻辑层自动化测试全绿岸脸——线状、可预期、机器照得到
Verify② · 实体验证(QC)PO(人)体感层视觉、平台、互动顺序、「哪里怪怪的」水脸——网状、涌现、只有人照得到

一个动作,两道检核:岸确保「把事情做对」(QA),水确保「做的是对的事」(QC)。

自动化照得到的,不该消耗 PO 的时间;自动化照不到的,才是 QC 的本职。

交到 PO 手上之前,AI 先由轻至重过完自己的关卡:自动化全绿了吗?带着的待确认事项,哪些其实自己就能查证?这次改动的覆盖范围(多语/多平台/多设备)有没有明白宣告?

在 Verify② 被抓到的逻辑 bug,不是「QC 有找到 ✓」,是 Verify① 还缺一张本该接住它的自动化检查网。

QC 里的人行使的不只是验收,是三项 PO 权利:接受/退回的最终裁量;浮现新需求与新边界(「啊,这个情境也该接住」);以及验收标准的解释权——文字与体感不一致时,体感优先,因为用户体验才是最终的裁判。

规格之外的边界在 QC 浮现,不是失败,是遇上「未知的未知」时的必然:补进 TDD、写进 KM、加一条回归测试。没写 KM 才是失败。

Verify 是岸与水即时的合流——岸确保把事情做对,水确保做的是对的事。两段都绿,这个 Sprint 才真的抵达。而水在这里照出的收获,会往下流进下一段:沉淀,还是结晶。

VI · 沉淀与结晶

Verify 是岸与水即时的交会。但还有一种交会发生在更长的尺度上——水,会变成岸。

协作在 Context 中大多流过就消散;但其中真正的收获不会白白流走,它有两种命运:

于是「收获该放哪」这个问题,本质上是在问:这份收获,要成为壁,还是成为结晶?

要让收获落在对的命运里,得先让它落在对的地方。

每段文字都有一个家

「何时记」之外,还有一个同样重要的问题:「记到哪里」。

系统里的文档不是一份,是好几种——每天都要遵守的规则、需要时才查的程序、踩过坑的教训、还在追踪的问题、欠着没做的事。它们的性质不同,家就不同。落笔之前先问一个问题:这个东西在本质上是什么?先分流,再落笔。

几条划界的句子:

为什么要这么讲究?因为一个真实的教训:无家的文字会被最近的容器吸收。一段不知道该放哪的记录,会就近塞进某份不属于它的文档——而且发生的当下没有任何警报,写起来的手感跟放对地方时一模一样。等到需要它的那天,它在错的地方,等于不存在。

让每段文字都放在流程中能被看得到的地方——这就是让「活文档」成立的代价与条件。

服务型领导的系统

传统做法服务型领导
人类写文档,AI 执行AI 写文档,人类设计时机
人类追踪进度系统自己记录进度
人类控制每一步人类只设计结构

人类不控制内容,只设计需被记录的时机。人类不追踪进度,只设计让进度自己被记录的系统。

这才是真正的「无为而无不为」——什么都不做,但什么都做了。

岸塑形水的流向,水沉淀回岸、长成新的结构——这条河,最终是自己长出自己的岸的。

VII · 与其他两柱的关系

Context 决定什么进来(过滤)。Constraints 决定怎么流动(引导)。Entropy 决定怎么出去(排放)。

输入 → [ Context 过滤 ] → 进入系统 → [ Constraints 引导 ] → 产出 → [ Entropy 排放 ]

Constraints 是这个循环的中段守护者。它确保:进来的东西,会沿着正确的路径,流向正确的出口。

VIII · 小结

Constraints 管理的核心是引导,不是限制。

一个 Session 由岸与水组成。岸是线状的结构——闸门、流程、记录点,回答「可以前进了吗」;水是网状的协作——判断、涌现、来回摸索,回答「此刻最需要被接住的是什么」。

岸给方向,水给涌现。它们在 Verify 即时交会——岸确保把事情做对,水确保做的是对的事;也在更长的尺度上互相成全——水的收获,沉淀成稳固结构的新岸,或结晶成让彼此成长的洞见。

「河道作为引导的结构」,说的就是这件事:用岸给出方向,把水留给涌现。

这是 Harness Engineering 的第二根柱。