Clipping 微信公众号

爆肝长文:SDD 实战下篇,从渐进式 SDD 到 Lattice Harness:AI Coding 的团队级闭环

by Dolphin7 原文 ↗
Created: 2026-07-02

公众号名称:dolphin07

作者名称:Dolphin7

发布时间:2026-07-02 19:45

渐进式 Spec Coding 解决“别跑散”,Harness 把执行和裁判分开,Loop 解决“别从零开始”。

如果说上篇讲的是“怎么让 AI Coding 不要从一句话需求直接跳到随机代码”,那这篇要继续回答另一个更难的问题:

当团队已经有了 Spec,谁来证明这次交付真的做对了?

上篇讲的是我们在团队里落地 Spec Coding 的第一阶段:先试工具,再从工具里抽方法。我们试过 OpenSpec + Superpowers 这种完整流程,也用过 Plan Mode 这种轻量控制点,最后收敛成两条更现实的渐进式 SDD 路线:

需求类型上篇方案目的
低风险 / 小改动Superpowers + Plan Mode先让 AI 出计划,人确认后再改
中等复杂 / 多人协作Plan Mode + 轻量 Spec 摘要锁边界、关键路径和验收标准
高风险 / 回归风险PrismSpec / plan 模式保留 spec.mdplan.mdreview.mdverify.md
高不确定 / 关键链路PrismSpec / tdd 模式先写失败测试,再实现,再验证

这套方案是有效的。它至少解决了三个问题:

  1. 1. AI 不再直接从一句话需求跳到代码;
  2. 2. 中高风险需求有了 spec.mdplan.mdreview.mdverify.md 这些可交接工件;
  3. 3. 团队开始按风险选择控制强度,而不是所有需求都走同一条重流程。

但真实跑下来,提效没有想象中那么完整。

个人编码会更快,方案收敛会更清楚,review 也更有依据。但团队级交付仍然会卡在几个老问题上:业务规则靠人临场补、验收证据不稳定、测试和验收标准脱节、失败经验没有回流。

也就是说,Spec 让 AI 少跑散,但还没有让团队稳定地判断“这次真的做对了”。

这就是我说的:Spec 只能解决 0 到 80。

剩下 20 分,不该继续靠更厚的 Spec 补,而是五个工程缺口:

缺口问题需要补什么
上下文缺口关键业务规则没进来,Spec 方向仍然会错可审计的项目上下文
裁判缺口谁判断做对了,不能让生成者自证独立 Verification
追踪缺口验收标准、测试、代码、证据没有链路验收覆盖与过程证据
漂移缺口API、schema、错误码会和 Spec 腐化drift check
学习缺口失败停在终端,下次继续从零猜loop state 与 learn draft

更关键的是,到了团队级交付,不能再默认“同一个 Agent 写完、自己解释、自己宣布通过”。执行者可以修复问题,但最终裁判必须来自独立证据:测试、静态检查、验收覆盖、漂移检查、只读 reviewer 或人工确认。

所以这篇是在上篇渐进式 SDD 的基础上,继续补第二层工程能力:

PrismSpec / 渐进式 SDD
  -> Context
  -> Orchestrator
  -> Verification
  -> Evidence / Eval
  -> Loop / Learn
  -> Lattice Harness

上篇解决的是“流程怎么不变重”,这篇解决的是“交付怎么可证明、可复盘、可复用”,以及“谁有资格宣布通过”。

Lattice 是我在 PrismSpec 之上继续补出来的 repo-local AI Coding control plane / harness:不做 IDE、不做云平台、不接管 Agent,只把团队交付需要的控制点变成仓库内可版本化的 contracts。


一、SDD 落地之后,为什么还差一层 Harness

上篇的自研 PrismSpec 解决的是 Spec Coding 的最小流程:

brainstorm -> plan -> implement(plan|tdd) -> verify -> finish

它关心的是:

  • • 需求如何变成 spec.md
  • • Spec 如何拆成 plan.md
  • • 什么时候走 plan
  • • 什么时候必须走 tdd
  • • 实现结果如何先经过 review.md
  • • 验证结果如何落到 verify.md

但 PrismSpec 本身不应该膨胀成完整平台。否则它会重新变成一套重流程。

Lattice 接在 PrismSpec 后面,核心不是再加一层流程,而是把团队 AI Coding 的关键控制点落成 repo-local contracts:

控制点没有 Harness 时的问题Lattice 放在哪里
Spec需求、假设和边界留在聊天里spec.mdplan.mdreview.mdverify.md
Context上下文靠人临场补,下一次不可恢复lattice/context/README.mdknowledge/Context Basis
OrchestratorAgent 靠对话记忆推进任务guide.shspec-status.shtask-next.shtask-complete.sh
Verification完成靠自然语言总结pipeline.shgates/、fresh command output
Evidence测试、review、失败记录散在各处eval-runs/*.json、summary、history、dashboard
Learning失败经验直接丢失或污染知识库loop state、escalation、learn draft、promotion

所以 PrismSpec 的边界很清楚:它负责把需求变成可执行 Spec;Lattice 负责把上下文、验证、证据和学习变成仓库内契约。

这里的 Orchestrator 很关键。它不替 Agent 做语义判断,而是把“下一步该做什么”从聊天记忆变成文件状态和命令协议:guide.sh 根据当前产物路由阶段,spec-status.sh 推进状态,task-next.sh 找下一项任务,task-complete.sh 要求 evidence 后才能完成任务。这样下一位 Agent、下一次会话、CI 或 reviewer 都能从仓库恢复上下文,而不是依赖上一轮对话。

这张图是我对下半场的整体理解:

Lattice 的价值不是多一套文档,而是把团队交付的控制点固化成可恢复、可验证、可审计的 repo-local contracts。


二、Context:不要把知识库做成 Prompt 杂货铺

很多团队一听 Context,就会走向两个极端:

  • • 要么什么都不放,靠人每次在 prompt 里解释。
  • • 要么什么都塞进去,把 README、会议纪要、事故复盘、代码片段全塞进上下文。

这两个都不对。

Lattice 里 Context 的定位很克制:

Context 不是代码真相源,而是帮助 Agent 少看错、少漏看,并把采用依据写进 Spec。代码、测试和 schema 仍是真相源。

1. Context 只放 AI 推不出来的约束

代码能告诉模型“现在怎么写”,但不一定能告诉它“为什么必须这么写”。

适合进入知识库的内容,是高稳定、高复用、跨需求会反复影响判断的规则:业务不变量、历史事故、架构决策、团队约定、接口契约。临时讨论、大段源码、泛 prompt 技巧都不适合直接进长期知识。

关键标准很简单:

这条信息如果不提前告诉 AI,它会不会做出“能跑但不对”的实现?

会,就值得沉淀。不会,就别污染知识库。

2. Context 要 map-first,再按需检索

Lattice 当前的主入口不是一个“大 prompt”,也不是让 Agent 上来就跑 loader,而是一张给 Agent 读的上下文地图:

lattice/context/
├── README.md              # Agent 必读的项目上下文地图
├── external.md            # 外部文档、中心知识、第三方协议入口
├── knowledge/
│   ├── architecture.md
│   ├── rules.md
│   ├── pitfalls.md
│   ├── glossary.md
│   └── decisions/
└── drafts/                # 待确认的经验沉淀

这里有三层,不要混在一起:

作用产物
Context Map告诉 Agent 去哪里找、冲突时信谁lattice/context/README.md
Project Knowledge存长期稳定、可复用、可审计的项目知识lattice/context/knowledge/
Context Basis记录本次任务实际采用了哪些依据spec.md#Context Basis

一次需求进来,正确顺序是:

  1. 1. 先读用户本次需求和当前代码、测试、schema;
  2. 2. 再读 lattice/context/README.md,知道相关知识在哪;
  3. 3. 只选择会影响 Scope、验收标准、Risk、Interface、Compatibility 或 Verification 的事实;
  4. 4. 把采用的事实写进 spec.md 的 Context Basis。

知识条目建议保持短、硬、可审计:

# 支付幂等规则

**关键词**:payment, idempotency, fund
**核心规则**:所有支付类 mutation 都必须带幂等键。
**来源**:2026-06-26 事故复盘
**适用上下文**:支付、扣款、退款、核销等会改变资金或权益状态的写操作。

3. Context 必须进入 Spec,而不是停在聊天里

只把知识读给 Agent 没用。它必须落到 spec.md 里,变成后续 review、plan、test 能引用的约束。

推荐写成这样:

## Context Basis

| 类型 | 来源 | 事实 / 约束 | 决策影响 |
|------|------|-------------|----------|
| knowledge | `rules.md#payment-idempotency` | 支付类 mutation 必须带幂等键 | 验收标准需要覆盖重复提交 |
| decision | `decisions/ADR-12` | 订单状态只能单向流转 | 影响失败恢复和重放语义 |

这样 Context 才从“背景材料”变成“交付契约的一部分”。

4. 项目知识库和中心知识库要分工

团队知识库不能只做一个大仓库。真实落地更适合两层:

层级放什么不放什么作用
项目知识库当前项目的业务规则、接口边界、历史坑、局部决策跨团队通用但未经验证的经验服务当前 repo 的 Spec 和 Plan
中心知识库多项目反复验证过的通用规则、平台约定、安全红线、工程模板单项目特例、临时讨论、未确认结论给多个项目提供共享基线

项目知识库更接近真实业务,中心知识库更接近组织资产。两者不能混成一个池子,否则会出现两个问题:

  1. 1. 中心规则太重,压死项目差异;
  2. 2. 项目特例上升太快,污染公共知识。

更稳的方式是:中心知识库默认 read-only,下游项目本地 override。只有经过多个项目验证、来源清楚、owner 明确的规则,才上升为中心知识。

5. 知识要自下而上蒸馏,不要自上而下编目录

很多知识库失败,是因为一开始就按组织架构设计目录:业务域、系统、模块、流程、规范,看起来很完整,但真正写 Spec 时搜不到、用不上、没人维护。

AI Coding 里的知识应该从真实交付里蒸馏出来。

推荐流程是:

这条链路有三个好处:

  • • 知识来自真实失败和真实决策,不是凭空写规范;
  • • 每条知识都有来源和适用范围,后续可审计;
  • • 中心知识库只沉淀 verified 共性,不压制项目差异。

所以 Context 工程不是“建一个知识库”,而是建立一条从交付现场到项目知识、再到中心知识的蒸馏链路。关键不是让 Agent 看更多,而是让它少看错、少漏看,并把采用依据留在 spec.md

Context 不是越多越好,而是越准越好。真正有价值的是能改变 Scope、验收标准、Risk 和 Policy 的知识。


三、Verification / Evidence:不要让 AI 自己证明自己正确

先把两个词拆开。

概念回答的问题典型产物
Verification这次交付当下能不能过?pipeline.sh、gates、fresh command output、verify.md
Evidence / Eval为什么算过?历史上过得怎么样?失败能不能复盘?eval-runs/*.json、summary、history、dashboard、outcome

团队级 AI Coding 最危险的不是没有测试,而是没有独立裁判;最难沉淀的也不是测试结果,而是可比较、可查询、可复盘的 evidence。

在团队级 AI Coding 里,Evidence / Eval 至少要回答三个问题:

  1. 1. 这次交付是否满足 Spec?
  2. 2. 这次 Agent 的工作过程是否可靠?
  3. 3. 这个团队的 AI Coding 能力是否在变好?

当前最该先做的是前两个。第三个可以后面再数据化。

这里有一条底线:执行者不能做最终裁判。

同一个 Agent 可以写代码、修失败、补测试,但它不能只凭自己的解释宣布“已经通过”。否则 Verification 会退化成自证:同一套上下文、同一套盲点、同一套合理化能力,既负责生成,也负责证明。

所以核心不是“再让 AI 看一遍”,而是把最终裁决交给独立证据:测试、静态检查、验收覆盖、drift check、只读 reviewer、人工确认。Agent 可以参与修复,但通过与否必须由外部信号决定。

在 Lattice 里,我把证据分成六层:

先做 L1-L4,因为它们确定性强、误报低、能直接进入本地和 CI。L5-L6 先记录、汇总和暴露风险线索,不要过早自动判死刑。

1. Verification 先做确定性卡口

不要一上来就让另一个 LLM 做语义评审。更稳的是先把确定性卡口做扎实。

Lattice 的交付流水线是 manifest-driven:

Gate解决的问题
bootstrap环境是否具备基本执行条件
spec-lintSpec 结构是否完整,验收标准编号是否连续
build项目是否能构建
lint / type-check静态质量是否过线
unit-test基础行为是否通过
ac-coverage每条验收标准是否有测试追踪
drift-checkSpec 和代码是否开始漂移
compliance是否有知识引用、澄清记录等过程证据

这套卡口的价值不是“高级”,而是“外部”。它不依赖 Agent 自己说自己完成。

随后,pipeline.sh --json-out 会把 gate output、review summary、TDD evidence 和 loop state 汇总成 lattice/state/eval-runs/*.json。这份 JSON 是 Evidence / Eval 的机器事实源,Markdown summary、history、dashboard 和 PR comment 都从它派生。

2. 验收覆盖:把验收标准连到测试

很多团队写了验收标准,但最后测试和验收标准没有关系。结果就是:Spec 写得很好,测试也很多,但没人知道测试到底覆盖了哪个验收点。

Lattice 用一个很土但很有效的方式解决:测试命名追踪验收编号,也就是让每条测试明确对应哪条验收标准。下面示例里的 AC-1AC-2 只是 Lattice 默认采用的编号格式,你也可以理解为“验收标准 1”“验收标准 2”。

Go:

func TestAC1_RedeemValidCoupon(t *testing.T) {}
func TestAC2_RedeemExpiredCoupon(t *testing.T) {}

Node / TS:

describe("AC-1: 核销有效优惠券", () => {})
it("AC-2: 拒绝已过期优惠券", () => {})

Python:

def test_ac1_redeem_valid_coupon(): ...

然后 ac-coverage.sh 输出矩阵:

| 验收编号 | 验收描述 | 测试函数 | 状态 |
|----|----------|----------|------|
| AC-1 | 创建商品 | TestAC1_CreateItem | 已覆盖 |
| AC-2 | 查询商品 | TestAC2_GetItem | 已覆盖 |
| AC-3 | 商品不存在 | — | 未覆盖 |

这就是最小可用的 Verification evidence:不是看测试总数,而是看验收标准有没有可执行证据。

3. Drift Check 解决“文档和代码谁变了”的问题

Spec 最容易腐化的地方,是接口、数据结构、错误码这些强契约。

Lattice 的 drift-check.sh 先把强契约漂移做成 gate 协议,当前 Go / Gin / GORM 示例已经能演示 route、schema、error code、seed SQL 等检查方向:

漂移类型检查什么
DDL driftSpec 里的 CREATE TABLE 和 ORM model 是否一致
Route driftSpec API 表和代码路由注册是否一致
Error code driftSpec 错误码和代码常量是否一致
Seed SQL driftSpec seed SQL 和 fixture 是否一致
Plugin drift用户自定义 OpenAPI / Protobuf / 架构检查

这里的关键不是内置支持多少框架,而是协议:任何 drift plugin 只要遵守退出码即可。

drift:
  plugins:
    - name: proto-check
      run: "bash scripts/proto-drift.sh ${SPEC_FILE} ${PROJECT_ROOT}"

退出码约定:

Exit Code含义
0通过
1失败,可由 Agent 修复后重跑
2需要人工介入

这比“请 AI review 一下有没有漂移”靠谱得多。AI 可以解释和修复漂移,但是否通过必须由 gate 的退出码和诊断输出决定;Evidence / Eval 再把这些结果沉淀成可复盘、可比较的质量事实。


四、Loop / Learn:让失败进入闭环

有了 Context、Verification 和 Evidence / Eval,还差最后一块:失败怎么回流。

很多 AI Coding 的失败不是“模型不会写”,而是失败信息没有被结构化利用。编译失败、测试失败、漂移失败都只是终端里的一段输出,下一轮 Agent 又重新猜。

Lattice 的最小 Loop 是:

verify -> fail -> fix -> rerun -> pass
                 └-> retry exhausted -> escalation

当前 pipeline.sh 已经支持最小可用的 Loop:

  • • 任一步失败立即停止;
  • • 失败后 Agent 可以修复并重跑;
  • • 默认最多 3 次重试;
  • • 重试耗尽后 exit 2,触发 escalation;
  • • 在 lattice/state/loops/.json 记录 failed step、retry、failure category 和 next action;
  • • retry 耗尽时生成 lattice/context/drafts/escalation-.md
  • • eval run 中嵌入 loop state,后续 summary、history、dashboard 都能汇总。

这看起来简单,但它让 AI Coding 从“自然语言完成声明”变成了“可控循环”。

但这里要守住一个边界:Loop 不是让同一个 Agent 无限自修复、无限自我裁判。更合理的职责拆分是:

环节负责什么不能做什么
Coding Agent实现、修复、补测试、重跑命令不能凭自然语言宣布最终通过
Independent Gatesbuild、lint、test、验收覆盖、drift check不解释业务意图,只给证据
Read-only Reviewer / Human审 cannot-verify、残余风险、知识沉淀不直接替执行 Agent 偷改代码
Learn Step生成 draft、等待确认后入库不把每次失败自动写成 verified knowledge

这套分工的目标,是避免“自己写、自己判、自己复盘”的闭环幻觉。

失败要分类,不然没法复盘

建议把失败至少分成这些类别:

类别例子默认动作
environment缺 yq、docker 未启动修环境或提示用户
spec_structure缺章节、验收编号跳号修 Spec
implementationbuild/lint/test 失败修代码
ac_gap验收标准没有测试补测试或调整 Spec
driftAPI/DDL/error code 不一致修代码或更新 Spec
compliance未引用知识、无澄清记录补记录或人工确认
unknown无法判断escalation

失败分类不需要一开始就很复杂。先用 gate name + regex 就够了。Lattice 里可以用 lattice/config/failure-categories.yaml 覆盖默认分类,并用 failure-category-lint.sh 做配置检查。

Escalation 后不要直接污染知识库

很多团队的知识库会越来越脏,是因为每次失败都直接写成“经验”。

更好的方式是先生成 learn draft:

# Draft:创建商品 API 的路由漂移

**失败分类**:drift
**失败步骤**:drift-check
**关联 Spec**:lattice/specs/create-item-api/spec.md
**证据**:Spec 声明了 `POST /items`,但代码里没有注册对应路由。
**建议沉淀**:新增 Gin API 时,需要同时更新 `internal/handler/router.go` 的路由注册,并补充对应的验收编号测试覆盖。
**状态**:draft

人或只读 reviewer 确认后,再通过 knowledge-review.shlearn-draft.sh promote 进入 lattice/context/knowledge/。这样经验会回流,但不会污染 verified knowledge。Loop 的边界也就清楚了:不是无限自修复,而是让失败被分类、被裁判、被升级、被沉淀。


五、展望:Loop 会把一次性提效变成团队复利

前面讲的 Context、Verification、Evidence / Eval,还是围绕单次需求交付。再往后,真正有价值的是 Loop。

没有 Loop,AI Coding 只是一次性加速:这次更快写完,下次仍然从零开始。团队真正需要的是让每次失败、每次 review、每次线上反馈,都能回到研发系统里。

Loop 应该回写四个位置:

反馈来源回写到哪里例子
Spec 漏约束Spec 模板 / 验收标准写法每个幂等需求必须写重复请求语义
Context 缺失项目知识库 / 中心知识库支付 mutation 必须带幂等键
Verification 漏卡口Gate / Test / Drift plugin新增 error code drift check
执行失败Plan 拆分 / Retry 策略某类任务必须拆出独立 RED test

我理想中的 Loop 不是“Agent 无限自动修”,而是一个有边界、有裁判、有升级机制的状态机:

这里多出来的 Judging 很重要。它代表裁判环节必须独立存在:可以是确定性 gate,可以是只读 reviewer,也可以是人工确认,但不能只是执行 Agent 自己的一段解释。

短期,Loop 的最小心智只需要落三个字段:

failed_step
retry_count
failure_category

中期,要让 pipeline 输出结构化 eval run。Lattice 当前已经在往这个方向走:pipeline.sh --json-out 会产出 lattice/state/eval-runs/*.json,其中包含 pipeline status、metrics、process evidence 和 loop state。形态大概是:

{
  "run_id": "2026-06-26T12-34-56Z",
  "spec_file": "lattice/specs/create-item.md",
  "git_sha": "abc1234",
  "pipeline": {
    "status": "fail",
    "retry_count": 1
  },
  "metrics": {
    "ac_total": 5,
    "ac_covered": 4,
    "drift_count": 1
  }
}

长期,团队才真正能回答这些问题:

  • • 哪类需求最容易失败?
  • • 哪个 gate 最常拦住问题?
  • • 哪些知识条目真的减少了返工?
  • • 哪个 Agent / prompt / kernel 版本 first-pass pass rate 更高?
  • • 哪些 review 问题应该升级成新的 Eval gate?

这一步才是从“工具提效”走向“团队能力复利”。


六、当前边界

这套东西我现在不会把它包装成生产级平台。它更像一个已经跑通最小闭环的 preview:适合试点、改造和验证团队流程,但还有几个边界要讲清楚。

边界当前状态
语言和框架覆盖Go / Gin / GORM 示例较完整,Node / Python drift parser 仍待扩展
Dashboard已有静态 dashboard,交互过滤、时间序列趋势和跨项目归因还在演进
知识治理learn draft 有 review / promote / discard 审计,但语义冲突仍需要 reviewer 判断
自动裁判优先依赖确定性命令和 gate,不把 LLM 主观打分当最终通过条件
中心化平台当前先稳定 repo-local 文件协议,不急着做服务端平台

这也是我更愿意把它叫 Harness,而不是平台的原因:先把控制点、证据和边界跑通,再谈规模化和中心化。


七、把这几句话带走

如果只记住几句话,我希望是这三句:

Spec 解决路径收敛,Harness 解决独立裁判。

Context 要进入 Spec,完成声明要指向外部命令和证据。

Loop 不是无限自修复,而是失败分类、升级和沉淀。

这就是我理解的 AI Coding 下半场:从个人提效,走向团队级正确性工程;从一次性生成,走向可验证、可复盘、可复利的交付闭环。


最后:源码和模板

后面我会继续写 AI Coding、Spec Coding、Context、Verification、Evidence / Eval、Loop 和 Agent 工程化。

如果你想看具体实现,我整理了 Lattice repo-local harness 的源码和模板。私信关键词 lattice,可以拿到:

  1. 1. 自研 Lattice 源码;
  2. 2. Context map 和项目知识示例;
  3. 3. 验收覆盖检查样例;
  4. 4. drift-check 模板;
  5. 5. eval run JSON 和 learn draft 示例。

如果这篇文章对你有启发,欢迎关注、收藏,也欢迎在评论区说说你们团队现在最卡的是哪一段:Spec 太重、Context 太散、Verification 太弱、Evidence 不成体系,还是失败经验无法回流。

如果你还没看上篇,可以先私信关键词 prismspec,领取 PrismSpec 渐进式 SDD skills、需求分级卡片和轻量 Spec 模板,再回来看这篇里的 Harness 和 Loop。


内容效果不满意?点此反馈

输入关键词开始搜索