过去半年,技术圈最火热的概念莫过于“Vibe Coding”——让AI写代码,人类负责“感知 vibe”(氛围、感觉)。你只需要用自然语言描述需求,Cursor、Copilot、Claude 就能生成一坨代码,复制粘贴,跑起来,收工。这种开发方式在个人项目、黑客松、Demo阶段确实爽快,效率是传统编码的5-10倍。
但爽完之后,问题来了。
当你想把那个“vibe 出来的东西”推上生产环境、面对真实用户流量时,你发现:没有单元测试、没有类型约束、没有错误处理、没有日志规范、没有部署流水线、没有人知道这个系统到底是怎么工作的——包括你自己。代码能跑,但没人敢动。改一行,炸三处。
这就是Vibe Coding的“技术债务悬崖”——它让你跑得飞快,但每跑一步都在往悬崖边靠近。
我从Vibe Coding起步,经历了三次生产事故的惨痛教训后,逐步摸索出一套将“AI的自由生成”与“工程化的规范约束”相结合的实战方案。核心就是两样东西:Harness(交付平台) 和 SDD(规范驱动开发)。这篇文章记录的就是这条进化之路的全过程。
第一坑:代码一致性崩溃
某次我用Vibe Coding生成了一套REST API,前后端加起来大概15个接口。两周后需求变更,需要给所有接口增加一个x-request-id的响应头。我让AI改了,但它只改了其中10个接口,剩下5个漏掉了——因为它在生成时没有“全局上下文”的概念,每次对话都是独立的。我在生产环境排查问题时才发现有的接口有、有的没有,整个系统的行为完全不一致。
第二坑:部署全靠“手搓”
没有流水线,每次上线都是手动操作:本地build、scp上传、ssh登录、重启服务。有一次我忘了scp新的环境变量文件,导致生产环境读取的是旧配置,整个支付功能挂了2小时。而且由于没有任何回滚机制,我只能回退到三天前的手动备份,中间丢失了两批数据。
第三坑:AI生成的代码无人敢维护
团队里后来加入了一个新同事,他看到某个AI生成的模块,问了我三个问题:这个函数的边界条件是什么?异常情况怎么处理的?为什么这里用了一个我从来没见过的第三方库?我一个都答不上来。因为当初生成的时候,我只说了一句“帮我实现用户认证”,AI自由发挥了一套方案,但没有任何设计文档、没有架构说明、没有测试用例。
这三个坑的本质是同一个问题:AI的自由度没有被工程化的约束所管理。
我需要的不是限制AI的能力,而是给它一套明确的“游戏规则”——就像给一辆跑车铺上赛道,而不是让它在一片荒野里狂飙。
赛道由两样东西构成:
规范不是一纸空文,而是可执行、可验证的代码。在我们的实践中,SDD分为三个层次:
层次一:数据契约(Data Contract)
定义系统所有输入输出的形状。这里的关键是用类型系统把规范“锁死”。
typescript
// 数据契约:用户模块
import { t } from 'elysia';
// 请求规范
export const CreateUserSchema = t.Object({
email: t.String({ format: 'email' }),
password: t.String({ minLength: 8, maxLength: 64 }),
name: t.String({ minLength: 1, maxLength: 50 }),
role: t.Enum(['admin', 'user', 'guest'])
});
// 响应规范
export const UserResponseSchema = t.Object({
id: t.String({ format: 'uuid' }),
email: t.String(),
name: t.String(),
role: t.String(),
createdAt: t.Date(),
// 敏感字段不返回
});
// 错误规范(统一错误码)
export const ErrorSchema = t.Union([
t.Object({ code: t.Literal('VALIDATION_ERROR'), message: t.String() }),
t.Object({ code: t.Literal('DUPLICATE_EMAIL'), message: t.String() }),
t.Object({ code: t.Literal('INTERNAL_ERROR'), message: t.String() })
]);层次二:行为契约(Behavior Contract)
定义系统“怎么做”的规则,包括业务流程、状态流转、事务边界。这部分规范会作为System Prompt的一部分注入AI的上下文。
# behavior_contract.yaml
module: UserRegistration
flows:
- name: 注册流程
steps:
- 验证邮箱格式和唯一性
- 密码加密(bcrypt, cost=10)
- 创建用户记录(状态: PENDING_VERIFICATION)
- 发送验证邮件(异步,不阻塞响应)
- 返回用户信息(不包含密码字段)
business_rules:
- 同一邮箱24小时内最多注册3次(防刷)
- 密码不能与最近3次历史密码相同
- 注册成功后自动分配默认角色'user'
error_handling:
- 邮箱已存在 → 返回 409 DUPLICATE_EMAIL
- 邮箱格式错误 → 返回 400 VALIDATION_ERROR
- 邮件服务失败 → 记录日志,但不影响用户注册成功(最终一致性)层次三:质量契约(Quality Contract)
定义“什么是好的代码/系统”,包括性能指标、测试覆盖率、代码风格等。
quality_gates:
performance:
- api_p95_latency: < 200ms
- db_query_time: < 50ms
- memory_usage: < 512MB
test:
- unit_test_coverage: > 80%
- integration_test_pass_rate: 100%
- e2e_critical_paths: 全部覆盖
code_style:
- typescript_strict: true
- no_any: true # 禁止使用any类型
- max_function_lines: 50
- max_complexity: 10有了这套三层规范,AI的编码过程从“写一段代码给我”变成了“按照这份施工图完成建造”。
具体操作流程:
/specs目录typescript
// 规范驱动的AI Prompt模板
const sddPrompt = `
你是一个严格遵守规范的全栈工程师。
【数据契约】
${JSON.stringify(dataContract, null, 2)}
【行为契约】
${behaviorContract}
【质量契约】
${qualityContract}
【任务】
根据以上规范,实现 ${taskDescription}
要求:
1. 所有输入输出必须严格遵循数据契约的类型定义
2. 业务逻辑必须覆盖行为契约中的所有步骤和业务规则
3. 代码必须通过质量契约中的检查项
4. 生成的代码需要包含对应的单元测试
请开始实现。
`;这种“先定义规范,再让AI填充实现”的模式,将AI生成代码的通过率从最初的62%提升到了91%。
有了规范,接下来要解决的是:如何让每次代码变更都自动经历一遍“规范校验 → 构建 → 部署 → 验证”的全过程?
答案就是Harness——一个将CI/CD、Feature Flags、验证门禁整合在一起的交付平台。
我们的Harness流水线是这样设计的:
[开发提交PR]
│
▼
┌──────────────────────────────────────────────────────┐
│ Stage 1: 规范静态检查 (SDD Static Validation) │
│ - 校验 specs/ 目录下的所有YAML/TS文件格式 │
│ - 运行 spec-validator 检查契约完整性 │
│ - 检查是否有破坏性变更(API breaking change检测) │
└────────────────┬─────────────────────────────────────┘
│ 通过
▼
┌──────────────────────────────────────────────────────┐
│ Stage 2: 单元测试 + 覆盖率门禁 │
│ - 运行所有单元测试(含AI生成的测试) │
│ - 覆盖率 < 80% → 流水线失败 │
│ - 运行类型检查 (tsc --noEmit) │
└────────────────┬─────────────────────────────────────┘
│ 通过
▼
┌──────────────────────────────────────────────────────┐
│ Stage 3: 构建镜像 │
│ - 前端: npm run build (Next.js) │
│ - 后端: bun build (Elysia) │
│ - 多阶段构建优化镜像大小 │
└────────────────┬─────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────┐
│ Stage 4: 部署到开发环境 (自动) │
│ - 部署策略: 滚动更新 │
│ - 部署后自动运行烟雾测试(smoke test) │
│ - 烟雾测试失败 → 自动回滚 │
└────────────────┬─────────────────────────────────────┘
│ 通过
▼
┌──────────────────────────────────────────────────────┐
│ Stage 5: 部署到预发环境 (需人工审批) │
│ - 部署策略: 金丝雀发布 (10% 流量) │
│ - 运行30分钟金丝雀验证 │
│ - 对比业务指标(错误率、延迟、吞吐) │
│ - 指标异常 → 自动回滚 │
└────────────────┬─────────────────────────────────────┘
│ 通过
▼
┌──────────────────────────────────────────────────────┐
│ Stage 6: 部署到生产环境 (需二次审批) │
│ - 部署策略: 蓝绿部署 │
│ - 全量运行契约测试套件 │
│ - 自动更新API文档 (OpenAPI生成) │
└──────────────────────────────────────────────────────┘这是Harness区别于普通CI/CD工具的核心能力——它不只是“部署”,而是“部署+验证”。
在AI全栈场景中,我们配置了三类验证门禁:
类型一:数据契约验证门禁
部署后,Harness会自动向新部署的服务发送一组“契约测试请求”,验证响应格式是否严格符合OpenAPI/Schema定义。
# harness/verification_gates.yaml
- name: contract_validation
type: HTTP_TEST
spec:
requests:
- method: POST
url: /api/users
body: '{"email":"test@example.com","password":"Test1234","name":"Test"}'
expected:
status: 201
schema: $ref: specs/user_schema.json#/UserResponse
- method: GET
url: /api/users/test@example.com
expected:
status: 200
schema: $ref: specs/user_schema.json#/UserResponse
# 验证敏感字段不存在
absent_fields: ["password", "passwordHash"]
failure_condition: "任何请求失败或schema不匹配"类型二:性能基线门禁
部署后,Harness会向服务发送模拟流量(基于录制的生产流量回放),持续5分钟,监控P95延迟和错误率。
- name: performance_baseline
type: LOAD_TEST
spec:
duration: 5m
requests_per_second: 100
recording_source: "harness_recordings/production_traffic_2026_06.har"
thresholds:
p95_latency: 200ms # 超过200ms则失败
error_rate: 0.1% # 超过0.1%则失败类型三:AI质量门禁(AI-specific)
对于AI Agent模块,还需要验证“生成的代码质量”本身。
yaml
- name: ai_quality_gate
type: CUSTOM_SCRIPT
spec:
script: |
# 运行AI自检套件
bun run agent:self-check --threshold=0.85
# 检查是否有已知的安全漏洞(通过Trivy扫描)
trivy image myapp:latest --severity HIGH,CRITICAL
failure_condition: "ai_quality_score < 0.85 或 存在高危漏洞"在AI全栈场景中,很多变更不需要“部署新代码”,而是“调整配置”——比如换一个Prompt模板、调整模型温度参数、切换Embedding模型版本。
Harness的Feature Flags让我们能够在不重新部署的情况下,动态控制这些配置:
// 在代码中使用Feature Flag
import { getFlag } from '@harness/feature-flags';
const generateResponse = async (userInput: string) => {
const useNewPrompt = await getFlag('use_enhanced_prompt', {
target: { identifier: user.id }
});
const temperature = await getFlag('model_temperature', {
defaultValue: 0.7,
target: { identifier: user.id }
});
const prompt = useNewPrompt ? ENHANCED_PROMPT : BASE_PROMPT;
return await llm.generate(prompt, { temperature });
};这样我可以:
整个操作在Harness UI上点击即可完成,不需要写代码、不需要走CI/CD流水线。
一个用Vibe Coding在3天内拼出来的AI客服系统:
Day 1:补齐规范
/specs目录Day 2:接入Harness
harness/pipeline.yaml)Day 3:修复 + 验证
指标 | 迁移前(Vibe Coding) | 迁移后(SDD+Harness) |
|---|---|---|
每次上线平均耗时 | 45分钟(手动操作) | 12分钟(全自动) |
部署失败率 | 30%(经常忘记某步骤) | <2% |
回滚时间 | 20-60分钟(手动找备份) | <1分钟(一键回滚) |
测试覆盖率 | 0% | 82% |
生产事故(月均) | 2.3次 | 0.3次 |
新成员上手时间 | 2周(看不懂代码) | 3天(看规范就懂了) |
从Vibe Coding到Harness × SDD,本质上是一次从“个人开发者”到“工程化团队”的蜕变——即使你仍然只有一个人。
Vibe Coding让你“能写代码”,但SDD让你“能写对的代码”,Harness让你“能持续把对的代码交付到生产”。
这套组合拳的意义不在于“阻止AI犯错”,而在于当AI犯错时,你能在几秒钟内发现、在几分钟内回滚、在几小时内修复。
这才是AI时代全栈开发者的核心竞争力:不是写代码的速度,而是构建可维护、可演进、可信任的系统的能力。
关于作者:全栈架构师,AI工程化实践者。曾在多家互联网公司负责DevOps平台建设,目前专注探索AI辅助下的高效开发范式。欢迎在思否评论区交流讨论。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。