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 动态读取 |
这种拆分能减少两个风险:
- 少给无关信息:不要让 AI 一次性读完整个仓库。
- 多给关键约束:业务边界、测试方式、禁止事项必须显式写出来。
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 规格
这样做有两个好处:
- AI 不需要猜下一步做什么;
- 每完成一个任务都能验证,不容易积累大量未检查修改。
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 代理 | 跨文件修改、运行命令、验证结果 | 按规格执行任务 |
| Cursor | AI 编辑器 | 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
每次项目交付后,可以问三个问题:
- AI 哪些地方理解错了?
- 哪些规则应该写进
CLAUDE.md? - 哪些业务场景应该进入 OpenSpec 长期规格?
如果 AI 反复犯同一种错,不要只在聊天里纠正一次,而要把它变成规则。例如:
## Prohibited Rules
- 禁止在订单结算链路中直接调用远程营销接口。
- 禁止用 double 处理金额。
- 禁止在未补充测试的情况下修改优惠券叠加规则。
- 禁止吞掉分布式锁释放异常。
这类负向约束非常有用,因为它能直接减少重复沟通成本。
工程师角色会发生什么变化
当 AI 能完成越来越多编码动作时,工程师的核心价值会更偏向这些能力:
- 把模糊需求拆成明确规格;
- 识别业务边界和异常场景;
- 判断技术方案是否符合系统约束;
- 设计可验证的测试路径;
- 把一次性经验沉淀成团队规则。
代码仍然重要,但代码会越来越像规格和约束的执行结果。对于复杂业务系统来说,真正稀缺的是高质量意图表达,而不是简单的语法实现。
Claude Code 让 AI 更像能执行任务的工程助手,OpenSpec 让任务有了清晰边界和长期记忆。两者结合后,AI 编码不再只是“生成代码片段”,而是进入“规格定义、受控执行、自动验证、知识沉淀”的工程闭环。
参考资料:
- https://thenewstack.io/context-is-ai-codings-real-bottleneck-in-2026/
- https://github.blog/ai-and-ml/generative-ai/spec-driven-development-with-ai-get-started-with-a-new-open-source-toolkit/
- https://solguruz.com/blog/spec-driven-development-guide/
- https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents
- https://code.claude.com/docs/en/how-claude-code-works
- https://www.anthropic.com/engineering/code-execution-with-mcp
- https://code.claude.com/docs/en/best-practices