芥末
发布于 2026-03-23 / 0 阅读
0
0

用 Claude Code 和 OpenSpec 构建可落地的 AI 编码工作流

AI Coding(AI 辅助编码)已经从“让模型补几行代码”进入到“让 AI 参与完整研发流程”的阶段。问题也随之变化:早期大家关心模型够不够聪明,现在更关键的是,AI 是否真的理解当前项目、当前任务、业务边界和历史决策。

很多失败的 AI 编码案例,并不是模型不会写代码,而是它拿到的上下文不完整、不干净,或者人给出的意图太模糊。模型在一个小函数里表现很好,一旦进入大型工程,就容易改错文件、破坏隐含规则、遗漏测试、陷入反复修复同一个错误的循环。

Claude Code 和 OpenSpec 可以组合成一套更工程化的 AI 编码方式:

  • Claude Code 负责执行:读代码、改文件、跑命令、验证结果。
  • OpenSpec 负责约束:把需求、设计、任务拆解和业务规则沉淀成规格。
  • 两者结合后,AI 不再只是在聊天窗口里“猜需求”,而是围绕明确规格进行受控执行。
flowchart LR
    A[业务意图] --> B[OpenSpec 规格]
    B --> C[Claude Code 执行]
    C --> D[代码修改]
    D --> E[测试与验证]
    E --> F[规格归档]
    F --> B

这套模式的核心不是把开发者替换掉,而是把开发者从“逐行告诉 AI 怎么写”转向“定义规格、审查边界、验证结果”。

AI 编码的瓶颈:上下文比模型更容易失控

大语言模型(LLM,Large Language Model)在短上下文任务中表现很强,例如生成一个工具函数、解释一段 SQL、补全单元测试。但真实项目里,代码只是上下文的一部分,更多关键信息散落在多个地方:

  • 代码仓库里的模块边界;
  • README、设计文档、接口文档;
  • 历史 Pull Request(PR,代码合并请求)里的讨论;
  • 业务规则和异常分支;
  • 团队约定的代码风格;
  • 测试命令、构建方式、发布约束;
  • 开发者脑子里的隐性知识。

当 AI 没有拿到这些信息时,它生成的代码可能语法正确、局部逻辑也看似合理,但会违背系统原有设计。

生产力悖论:写得快不等于交付快

AI 编码常见的体验是:一开始速度很快,模型几秒钟就能生成大段代码。但随着任务变复杂,开发者需要花大量时间做这些事:

  • 检查 AI 是否误解需求;
  • 回滚错误修改;
  • 给 AI 补充遗漏背景;
  • 修复生成代码引入的新 bug;
  • 反复要求 AI 跑测试、改测试、再跑测试。

这就形成了一个悖论:局部代码生成速度变快,但完整任务交付时间不一定下降。尤其在复杂业务里,如果 AI 一开始理解错了方向,后面的修复成本会越来越高。

上下文窗口不是万能解法

扩大上下文窗口只能让模型“装下更多内容”,不能保证模型“使用正确内容”。如果把大量无关文件、历史对话、临时调试信息都塞进去,反而会出现两个问题:

问题表现后果
上下文污染旧需求、废弃方案、无关代码混在一起AI 依据过时信息做决策
注意力漂移关键规则被大量低价值 Token 淹没AI 忽略真正重要的约束

上下文工程(Context Engineering)要解决的不是“怎么写一句更漂亮的提示词”,而是“怎么为当前任务准备最小、准确、可验证的上下文”。

把上下文当作一等系统来设计

成熟的 AI 编码工作流不能依赖临时复制粘贴。上下文应该像代码、配置、测试一样被管理,具备明确的来源、作用域和生命周期。

一个可控的上下文系统通常包含三层:

flowchart TD
    A[长期知识] --> D[当前工作上下文]
    B[项目规则] --> D
    C[任务规格] --> D
    D --> E[模型调用]
    E --> F[代码修改]
    F --> G[验证结果]
    G --> H[更新规格或记忆]
层级内容典型载体
长期知识项目架构、业务规则、团队约定规格文件、CLAUDE.md、内部知识库
当前任务上下文本次需求、变更范围、验收条件OpenSpec change 目录
工作上下文当前模型调用真正需要看的文件和命令输出Claude Code 动态读取

这种拆分能减少两个风险:

  1. 少给无关信息:不要让 AI 一次性读完整个仓库。
  2. 多给关键约束:业务边界、测试方式、禁止事项必须显式写出来。

Claude Code:终端里的 AI 编码代理

Claude Code 是 Anthropic 推出的终端原生 AI 编码工具。它不是传统 IDE(Integrated Development Environment,集成开发环境)里的补全插件,而是一个可以在项目目录中执行任务的代理(Agent)。

它能做的事情包括:

  • 搜索和阅读项目文件;
  • 理解 Git 状态;
  • 修改多个文件;
  • 执行测试、构建、格式化命令;
  • 根据命令输出继续修复;
  • 读取项目级说明文件;
  • 通过 MCP 访问外部工具和数据源。

代理循环:收集、行动、验证

Claude Code 的优势在于它不是只生成一次代码,而是可以围绕任务形成闭环。

flowchart LR
    A[收集上下文] --> B[制定修改计划]
    B --> C[编辑代码]
    C --> D[运行测试或命令]
    D --> E{是否通过}
    E -- 否 --> F[分析错误]
    F --> C
    E -- 是 --> G[输出结果]

这个循环对应真实工程师的工作方式:

阶段Claude Code 会做什么价值
收集上下文搜索文件、查看调用链、读取说明文档减少盲改
执行动作修改代码、调整配置、补测试完成实际变更
验证结果跑测试、看报错、继续修复避免停留在“看起来正确”

AI 编码要想进入真实项目,验证环节非常关键。没有测试和命令输出,模型只能根据概率判断代码是否可用;有了验证反馈,模型才能基于事实修正。

终端原生为什么重要

终端是软件工程里最稳定的自动化接口。构建、测试、代码生成、数据库迁移、Git 操作、CI/CD(Continuous Integration / Continuous Delivery,持续集成与持续交付)脚本,大多都可以通过命令行完成。

Claude Code 放在终端里,有几个直接收益:

  • 可以和现有脚本复用,不需要重建一套流程;
  • 可以放进自动化任务,例如代码审查、批量重构、依赖升级;
  • 可以在服务端、容器、远程开发机中使用;
  • 可以把“执行命令后的反馈”纳入下一轮推理。

例如,一个常见任务可以这样交给 Claude Code:

claude "为订单结算模块补充优惠券叠加规则的单元测试,运行相关测试并修复失败用例"

在理想状态下,Claude Code 不只是生成测试文件,还会找到测试命令并执行:

./mvnw test -Dtest=CouponSettlementServiceTest

如果测试失败,它会根据失败栈继续修改,而不是让开发者手动把报错复制回聊天框。

MCP:让 AI 按需访问外部上下文

MCP(Model Context Protocol,模型上下文协议)是一套让 AI 代理访问外部工具和数据源的开放协议。它解决的问题是:AI 不应该只依赖当前对话和本地文件,还需要安全地查询数据库、文档系统、监控平台、Issue 系统等外部信息。

但外部工具也会带来新的上下文压力。假设一个内部系统有几千个 API,如果一次性把所有 API 描述都塞进上下文,Token 会被工具说明消耗掉,模型反而更难完成任务。

更合理的方式是按需访问:

sequenceDiagram
    participant U as 开发者
    participant C as Claude Code
    participant M as MCP Server
    participant D as 外部数据源

    U->>C: 分析优惠券结算异常
    C->>M: 查询可用工具
    M-->>C: 返回工具摘要
    C->>M: 调用订单日志查询
    M->>D: 执行定向查询
    D-->>M: 返回结果
    M-->>C: 返回精简上下文
    C-->>U: 给出原因和修复建议

这种模式的重点是“查询结果进入上下文”,而不是“全量数据进入上下文”。对于大型代码库、数据库和日志系统,这一点尤其重要。

CLAUDE.md:把项目规则写成 AI 能读的操作手册

Claude Code 支持通过 CLAUDE.md 维护项目级说明。它通常放在仓库根目录,用来告诉 AI:

  • 项目怎么启动;
  • 测试怎么运行;
  • 代码风格是什么;
  • 哪些目录不能随意改;
  • 常见架构约束;
  • 生成代码时必须遵守的规则。

一个后端项目的 CLAUDE.md 可以这样写:

# Project Guide for Claude

## Build and Test

- Run all tests: `./mvnw test`
- Run coupon tests: `./mvnw test -Dtest=CouponSettlementServiceTest`
- Format check: `./mvnw spotless:check`

## Architecture Rules

- Controller 层只能做参数校验和 DTO 转换。
- 业务逻辑必须放在 Service 层。
- Repository 只能访问数据库,不允许调用外部 RPC。
- 订单结算链路禁止引入同步远程调用。

## Coding Rules

- 新增业务分支必须补充单元测试。
- 金额计算统一使用 BigDecimal,禁止使用 double。
- 分布式锁必须设置过期时间,并保证 finally 中释放。

这样的文件比临时提示词更可靠。因为它跟着仓库走,新会话、新成员、新机器都能读到同一份约束。

OpenSpec:让 AI 先对齐规格,再开始写代码

Claude Code 解决的是“执行能力”问题,但执行之前还需要明确任务边界。OpenSpec 的作用就是把需求变成可评审、可执行、可归档的规格。

SDD(Spec-Driven Development,规格驱动开发)的核心思想是:在写代码之前,先把业务意图、变更范围、验收场景和执行任务写清楚。

这对 AI 编码尤其重要。因为人类开发者可以根据经验补全隐含需求,AI 如果没有显式上下文,很容易用“看似合理”的方式填空。

OpenSpec 的目录结构

OpenSpec 通常会在项目中维护一个 openspec 目录,用来存放当前变更和长期规格。

openspec/
  project.md
  specs/
    coupon-settlement.md
    order-payment.md
  changes/
    refactor-coupon-logic/
      proposal.md
      design.md
      tasks.md
      specs/
        coupon-settlement.md
  archive/
    2026-06-07-refactor-coupon-logic/

每个变更单独放在 changes/ 下,避免不同任务的上下文互相污染。

四类核心工件

工件说明面向的问题
proposal.md描述为什么要改、改什么、不改什么防止需求范围失控
design.md描述技术方案、数据结构、接口变化防止实现方向跑偏
specs/描述业务场景和验收规则防止业务语义模糊
tasks.md拆成可执行的小任务让 AI 按步骤推进

其中 specs/ 最关键。它不应该只写一句“支持优惠券叠加”,而要写成具体场景。

## Requirement: 多张优惠券叠加结算

用户在满足规则时,可以同时使用多张可叠加优惠券。

### Scenario: 满减券和店铺券可叠加

Given 用户订单金额为 300 元
And 用户拥有一张满 200 减 30 的平台券
And 用户拥有一张满 100 减 10 的店铺券
When 用户提交结算
Then 应抵扣 40 元
And 应付金额为 260 元

### Scenario: 优惠券过期临界点

Given 优惠券过期时间为 2026-06-07 10:00:00
And 当前服务端时间为 2026-06-07 10:00:01
When 用户提交结算
Then 该优惠券不可使用
And 返回明确的过期原因

这种写法减少了“支持”“优化”“合理处理”这类模糊词,让 AI 能围绕输入、动作、输出生成代码和测试。

OpenSpec 的生命周期:提案、应用、归档

OpenSpec 的价值不只是写文档,而是给变更建立生命周期。

flowchart LR
    A[Propose 提案] --> B[Review 评审规格]
    B --> C[Apply 执行变更]
    C --> D[Verify 测试验证]
    D --> E[Archive 归档]
    E --> F[更新长期规格]

Propose:隔离当前变更上下文

提案阶段只关心当前变更,不把所有历史讨论都混进来。AI 可以先分析现有代码,再生成变更骨架。

/opsx:propose "重构优惠券结算逻辑,引入 Redis 分布式锁并支持多券叠加"

生成后的目录可能类似:

openspec/changes/refactor-coupon-logic/
  proposal.md
  design.md
  tasks.md
  specs/
    coupon-settlement.md

开发者需要审查这些文件,尤其是业务场景是否完整。AI 常常能发现常规路径,但边界条件仍然需要人补充,例如:

  • 优惠券过期临界点;
  • 同一张券重复提交;
  • Redis 锁获取失败;
  • 部分优惠券可叠加、部分不可叠加;
  • 订单金额发生变化后的重新计算;
  • 退款时优惠分摊规则。

Apply:让 AI 按任务清单受控执行

规格通过后,再让 Claude Code 执行任务。

/opsx:apply refactor-coupon-logic

tasks.md 可以拆成这样:

# Tasks

- [ ] 梳理 CouponSettlementService 当前结算流程
- [ ] 增加优惠券叠加规则模型
- [ ] 引入 Redis 分布式锁,防止同一用户重复结算
- [ ] 使用 Lua 脚本保证券状态校验和占用的原子性
- [ ] 补充优惠券过期、重复提交、叠加规则冲突测试
- [ ] 运行 CouponSettlementServiceTest
- [ ] 更新 coupon-settlement 规格

这样做有两个好处:

  1. AI 不需要猜下一步做什么;
  2. 每完成一个任务都能验证,不容易积累大量未检查修改。

Archive:把一次性对话变成长期知识

任务完成后,需要把临时变更归档,并把稳定规则合并到长期规格中。

/opsx:archive refactor-coupon-logic

归档后的收益很明显:下一次再修改优惠券模块,AI 不需要从零理解业务,也不需要依赖上一次聊天记录。长期规格会成为团队记忆的一部分。

Claude Code + OpenSpec 的实际工作流

把两者合在一起,可以形成一套适合复杂业务变更的流程。

sequenceDiagram
    participant Dev as 开发者
    participant OS as OpenSpec
    participant CC as Claude Code
    participant Repo as 代码仓库
    participant Test as 测试命令

    Dev->>OS: 创建变更提案
    OS-->>Dev: 生成 proposal/design/spec/tasks
    Dev->>OS: 审查并补充业务边界
    Dev->>CC: 按 OpenSpec 执行 apply
    CC->>Repo: 搜索代码并修改文件
    CC->>Test: 运行单元测试/构建命令
    Test-->>CC: 返回结果
    CC->>Repo: 根据失败结果修复
    Dev->>OS: 归档变更并更新长期规格

可以把职责分得更清楚:

环节人负责什么AI 负责什么
需求定义判断业务目标和边界协助整理规格草稿
技术设计审查架构影响和风险根据代码库提出方案
编码实现审查关键路径按任务修改代码
测试验证判断覆盖是否足够编写并运行测试
知识沉淀决定哪些规则进入长期规格更新文档和归档记录

这不是“让 AI 自由发挥”,而是“把 AI 放进工程流程”。

示例:重构优惠券结算逻辑

假设电商系统要重构优惠券结算模块,目标包括:

  • 支持多张优惠券叠加;
  • 引入 Redis 分布式锁,避免重复提交;
  • 使用 Lua 脚本保证券状态校验和占用的原子性;
  • 保留现有满减、店铺券、平台券规则;
  • 补齐并发和过期场景测试。

如果直接对 AI 说“帮我重构优惠券逻辑”,风险很高。它可能只改 CouponService,却忽略订单结算入口;也可能只考虑正常路径,没有处理锁释放和异常回滚。

更稳妥的方式是先建立规格。

1. 创建提案

/opsx:propose "重构优惠券结算逻辑,支持多券叠加,并用 Redis 锁防止重复结算"

proposal.md 可以明确范围:

# Proposal: Refactor Coupon Settlement Logic

## Why

当前优惠券结算逻辑分散在多个分支中,并发提交时存在重复占用风险。
新结算逻辑需要支持多券叠加,并保证券状态校验和占用过程具备原子性。

## What

- 增加多券叠加规则。
- 引入用户维度 Redis 分布式锁。
- 使用 Lua 脚本完成券状态校验和占用。
- 补充并发、过期、重复提交测试。

## Non-goals

- 不调整退款分摊逻辑。
- 不修改优惠券发放规则。
- 不变更订单主流程接口协议。

Non-goals 很重要,它能告诉 AI 哪些地方不要动。

2. 补充业务场景

规格文件里写清楚输入输出:

## Requirement: 重复提交保护

同一用户在短时间内重复提交同一订单结算请求时,只允许一个请求成功占用优惠券。

### Scenario: 并发重复提交

Given 用户 A 拥有一张可用优惠券 C1
And 用户 A 对订单 O1 发起两次并发结算请求
When 两个请求同时进入优惠券占用逻辑
Then 只有一个请求可以成功占用 C1
And 另一个请求应返回重复提交或稍后重试提示
And 优惠券 C1 最终只能绑定到一个结算单

这类场景会直接影响实现方式。没有这个规格,AI 可能只加一个普通锁;有了这个规格,AI 才有理由引入 Redis 锁和 Lua 原子操作。

3. 拆解任务

# Tasks

- [ ] 阅读 CouponSettlementService、CouponRepository、OrderCheckoutService
- [ ] 建立优惠券叠加规则计算器
- [ ] 增加 Redis 锁封装,锁 key 使用 userId + orderId
- [ ] 增加 Lua 脚本,原子校验券状态并占用
- [ ] 补充 CouponSettlementServiceTest
- [ ] 补充并发重复提交测试
- [ ] 运行相关测试并修复失败用例

Claude Code 执行时就可以一项一项完成,而不是在仓库里漫无目的地搜索。

4. 执行与验证

/opsx:apply refactor-coupon-logic

执行过程中,Claude Code 应该持续运行相关测试:

./mvnw test -Dtest=CouponSettlementServiceTest
./mvnw test -Dtest=CouponConcurrentSubmitTest

如果测试失败,错误输出会成为下一轮上下文。这样 AI 的修复有事实依据,而不是继续凭猜测改代码。

5. 归档规格

/opsx:archive refactor-coupon-logic

归档后,稳定下来的业务规则进入:

openspec/specs/coupon-settlement.md

以后不管是人还是 AI,只要要改优惠券结算,都应该先读这份规格。

OpenSpec 和常见 AI 编码工具的关系

OpenSpec 不是 Claude Code 的替代品,它更像规格管理层。Claude Code、Cursor、Aider 等工具都可以读取 Markdown 文件,因此都能接入这种模式。

工具主要定位适合做什么与 OpenSpec 的关系
Claude Code终端 AI 代理跨文件修改、运行命令、验证结果按规格执行任务
CursorAI 编辑器IDE 内联修改、代码阅读、局部重构读取规格辅助编码
Aider命令行结对编程Git 驱动的小步修改根据任务清单提交变更
OpenSpec规格驱动层管理需求、设计、任务、归档为各种编码代理提供稳定上下文

选择工具时可以按场景判断:

场景更适合的组合
大范围重构,需要跑测试和改多个文件Claude Code + OpenSpec
日常开发,需要频繁在 IDE 中查看和编辑Cursor + OpenSpec
小步提交、命令行习惯强Aider + OpenSpec
团队希望沉淀业务规则和变更记录OpenSpec 作为统一规格层

团队落地:把 AI 编码能力沉淀成组织资产

个人用 AI 写代码,收益容易停留在个人习惯里。团队要想持续获得收益,需要把高质量上下文沉淀下来。

用 Skill 固化团队规则

Claude Code 可以通过 Skill 机制封装特定能力,例如:

.claude/
  skills/
    java-code-review/
      SKILL.md
    security-checklist/
      SKILL.md
    middleware-usage/
      SKILL.md

一个安全审计 Skill 可以写成:

# Security Checklist

在修改接口、鉴权、订单、支付、优惠券相关代码时,必须检查:

- 是否存在越权访问;
- 是否校验用户身份和资源归属;
- 是否避免把内部错误堆栈返回给前端;
- 金额、库存、优惠券状态修改是否具备幂等保护;
- 外部输入是否经过白名单或格式校验。

这样团队成员不需要每次手写同样提示,AI 也能稳定遵守同一套规则。

用 MCP 连接内部知识

团队内部通常有很多有价值的信息:

  • 历史代码库;
  • 线上事故复盘;
  • 接口文档;
  • 数据库表结构;
  • 监控指标;
  • 日志查询平台;
  • 内部组件使用规范。

可以通过 MCP Server 暴露成 AI 可调用工具。关键不是让 AI 拿到所有数据,而是让它能按任务查询精确结果。

flowchart LR
    A[Claude Code] --> B[MCP Server]
    B --> C[代码搜索]
    B --> D[接口文档]
    B --> E[日志平台]
    B --> F[监控系统]
    B --> G[知识库]

建立 AI 编码效能飞轮

团队级 AI 编码应该形成持续循环:

flowchart TD
    A[完成一次需求] --> B[更新 OpenSpec 规格]
    B --> C[沉淀 CLAUDE.md 规则]
    C --> D[补充 Skill 或 MCP 工具]
    D --> E[下一次 AI 执行更准确]
    E --> A

每次项目交付后,可以问三个问题:

  1. AI 哪些地方理解错了?
  2. 哪些规则应该写进 CLAUDE.md
  3. 哪些业务场景应该进入 OpenSpec 长期规格?

如果 AI 反复犯同一种错,不要只在聊天里纠正一次,而要把它变成规则。例如:

## Prohibited Rules

- 禁止在订单结算链路中直接调用远程营销接口。
- 禁止用 double 处理金额。
- 禁止在未补充测试的情况下修改优惠券叠加规则。
- 禁止吞掉分布式锁释放异常。

这类负向约束非常有用,因为它能直接减少重复沟通成本。

工程师角色会发生什么变化

当 AI 能完成越来越多编码动作时,工程师的核心价值会更偏向这些能力:

  • 把模糊需求拆成明确规格;
  • 识别业务边界和异常场景;
  • 判断技术方案是否符合系统约束;
  • 设计可验证的测试路径;
  • 把一次性经验沉淀成团队规则。

代码仍然重要,但代码会越来越像规格和约束的执行结果。对于复杂业务系统来说,真正稀缺的是高质量意图表达,而不是简单的语法实现。

Claude Code 让 AI 更像能执行任务的工程助手,OpenSpec 让任务有了清晰边界和长期记忆。两者结合后,AI 编码不再只是“生成代码片段”,而是进入“规格定义、受控执行、自动验证、知识沉淀”的工程闭环。

参考资料:

  1. https://thenewstack.io/context-is-ai-codings-real-bottleneck-in-2026/
  2. https://github.blog/ai-and-ml/generative-ai/spec-driven-development-with-ai-get-started-with-a-new-open-source-toolkit/
  3. https://solguruz.com/blog/spec-driven-development-guide/
  4. https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents
  5. https://code.claude.com/docs/en/how-claude-code-works
  6. https://www.anthropic.com/engineering/code-execution-with-mcp
  7. https://code.claude.com/docs/en/best-practices

评论