Vibe Coding 分享:用 SDD 与 TDD 把 AI 编码流程跑通
1. 为什么 Vibe Coding 跑着跑着就乱了Vibe Coding 这个词从 2025 年被 Collins 选为年度词汇之后几乎成了 AI 编码的代名词。它的核心画面很美好你用自然语言描述需求AI 把代码吐出来你从代码农民工变成代码工头。但真正在项目里跑过几周的人都知道事情没那么简单。我见过太多这样的场景一个需求丢给 AI它三下五除二生成两百行代码跑起来看着没问题你合并了。第二天改另一个功能AI 又生成一堆代码和昨天的逻辑悄悄打架。到第三周你想改一个按钮的防抖AI 直接在请求前加锁、请求后解锁局部需求满足了但整个项目的按钮组件体系开始腐化。这就是典型的局部最优和全局最优冲突——AI 的注意力只聚焦在当下任务它不知道你的项目里已经有一个防抖按钮组件。更麻烦的是上下文爆炸。项目一大代码量指数级增长有限的 Context Window 里塞满实现细节真正的工程信息被稀释。噪音一多模型开始幻觉正确率下降注意力被稀释到无法做正确判断。然后是 debug 灾难AI 写的代码变量命名规范、注释详细有些还是瞎编的、结构工整但逻辑深处藏着一个边缘情况迭代着迭代着就鬼打墙AI 反复修改都修不好越修越乱最后没人看得懂。问题的根子在于Vibe Coding 把推理过程外包了工程师最多 review 一下而人脑记忆短暂对项目的掌控力直线下降。古法编程下代码是推理理解制作的结果Vibe Coding 下你只剩一个 review 动作审查标准还可能是错的。所以真正要解决的不是怎么让 AI 写得更快而是怎么让 AI 写的东西可验证、可约束、可回滚。这就是 SDDSpec-Driven Development规格驱动开发和 TDDTest-Driven Development测试驱动开发要出场的地方。SDD 把编码意图结构化TDD 把意图可执行化两者合起来才是 Vibe Coding 在真实项目里跑通的工程化底座。这篇文章我会把整条链路拆开从需求描述到 Spec 文档从 Spec 派生测试从测试驱动 AI 做最小改动再到用 MCP 工具补齐外部知识。每一步都给可复制的提示词模板、测试骨架和配置片段最后演示一次从自然语言需求到测试通过的完整验证动作。适合已经在用 Claude Code、Codex CLI 或者 Cursor 这类工具但被越聊越乱折磨过的开发者。2. TaoToken 前置把模型接入和 Key 管理理顺在讲 SDD 和 TDD 的具体流程之前得先把模型接入这件事理顺。因为后面所有的提示词、测试生成、代码审查都依赖一个稳定的模型调用入口。如果你还在为每个工具单独配 Key、单独切模型、单独处理 401 报错那工程化流程根本跑不起来。TaoToken 在这里扮演的角色是统一的模型接入层。它提供兼容 OpenAI 风格的 API 端点你可以把它理解成一个模型网关Claude Code、Codex CLI、Cline、Cursor 这些工具都可以通过同一个 Base URL 和 Key 去调用不同的模型。官网在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 端点是 https://taotoken.net/api 注意 API 地址不带 UTM 参数。为什么 SDDTDD 流程特别需要这一层因为这套流程里模型的分工是明确的技术设计和架构推理用最强的模型工程实现用执行速度快的模型代码检查再用一个模型交叉验证。如果每个工具都单独配 Key你会在切模型这件事上浪费大量时间而且很难保证同一个 Spec 在不同工具里看到的是同一份上下文。先拿 Key。打开 https://taotoken.net/api-keys 创建一个 API Key复制出来。这个 Key 后面会用在三个地方Claude Code 的 settings、Codex 的 auth.json、以及 Cline 的 MCP 配置。建议给 Key 起一个能看出用途的名字比如sdd-tdd-flow方便后面排查问题时定位。拿到 Key 之后先别急着配工具用最朴素的方式验证一下通路。打开终端用 curl 发一个最小请求curl https://taotoken.net/api/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -d { model: claude-sonnet-4-20250514, messages: [ {role: user, content: 只回复两个字通了} ], max_tokens: 16 }如果返回的 JSON 里choices[0].message.content是通了说明 Key 和网络都没问题。这一步很重要因为后面 Claude Code 报 401 的时候你得先能区分是 Key 的问题还是工具配置的问题。模型选择上结合我自己的使用经验给个分工建议。Claude 系列像高工执行具体编码任务快但发散性偏高容易过度设计代码完成度有时不够设计好技术文档后往往要跑两三遍才达标。GPT 系列像架构师适合分析问题、规划任务执行慢但考虑问题发散性低以用户提出的执行标准为准代码完成度高对 UI 还原度也好——注意这里说的是 GPT 而不是 gpt-codexgpt-codex 更适合简单重复性工作。Gemini 编码质量和架构规划都不及前两者但前端 UI 编写很好偶尔能 debug 出 Claude 和 GPT 都解不出的问题只是水平不稳定。国内模型里GLM 4.7 适合零散小需求上强度后即使几轮自检仍有较多漏洞GLM5 表现快追上 Claude Opus 4.6 了但算力严重不足非常慢MiniMax 和 Kimi 与 GLM 4.7 相近实际生产中更多作为补充、打下手的角色。所以在这套流程里我的分工是技术设计推理用 GPT 或 Claude 的强模型工程实现用 Claude代码检查用另一个模型交叉验证。TaoToken 的好处是这些模型可以通过同一个入口切换不用为每个模型单独维护一套配置。如果你打算长期跑这套流程尤其是涉及多 Agent 协作、subAgent 并行写测试这种场景建议直接上 Coding Plan地址是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite 。按量付费在频繁调用下成本不好控Coding Plan 更适合这种持续性的编码工作流。3. 可复制配置Claude Code、Codex 与 MCP 三件套配置这一步是整套流程能不能跑起来的关键。我见过太多人卡在这里Base URL 填错、Key 没生效、Model ID 写了个不存在的名字然后工具报一堆看不懂的错。下面把 Claude Code、Codex CLI 和 MCP 三件套的配置都写全你直接复制改 Key 就行。先说 Claude Code。它的配置文件在~/.claude/settings.json如果你用的是项目级配置就放在项目根目录的.claude/settings.json。核心是三个字段Base URL、API Key、Model ID。配置片段如下{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: sk-你的TaoToken密钥, ANTHROPIC_MODEL: claude-sonnet-4-20250514, ANTHROPIC_SMALL_FAST_MODEL: claude-haiku-4-20250514 }, permissions: { allow: [ Read, Write, Bash(git diff:*), Bash(npm test:*), Bash(pytest:*) ] } }这里ANTHROPIC_BASE_URL填https://taotoken.net/api不要带 UTM 参数也不要多加/v1Claude Code 会自己拼路径。ANTHROPIC_AUTH_TOKEN就是你在 API Keys 页面拿到的 Key。ANTHROPIC_MODEL是主模型ANTHROPIC_SMALL_FAST_MODEL是处理轻量任务比如生成 commit message时用的快模型配一个便宜的能省不少成本。permissions.allow这块我特意只放开了读、写和几个安全的 Bash 命令。注意这里没有放开git commit和git push——这是刻意的。git 是 AI 编码的最后一道防线只要没提交所有的过错甚至误删都能通过 git 恢复。让 AI 执行 git 操作等于把这道防线拆了。后面第 5 节会专门讲这个坑。再说 Codex CLI。它的认证文件在~/.codex/auth.json配置在~/.codex/config.toml。auth.json 负责认证{ OPENAI_API_KEY: sk-你的TaoToken密钥 }config.toml 负责模型和端点model gpt-5 model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api/v1 env_key OPENAI_API_KEY wire_api chat注意 Codex 的base_url要带/v1这跟 Claude Code 不一样是两套工具的历史差异配错了会直接 404。wire_api填chat表示走 Chat Completions 协议。最后是 MCP 配置。MCPModel Context Protocol是一个用于 AI 工具集成的开源标准允许 AI Agent 通过标准协议接入文件、数据库、网页、内部系统等资源极大扩展 AI 的能力边界。MCP 服务器提供一些可调用的工具AI 可以像内置工具一样调用。但要注意MCP 并不是越多越好它本身会侵占上下文工具调用过程中的查询和结果也会带来上下文需要控制数量按需添加和开启。在 SDDTDD 流程里我建议至少配两个 MCP一个是文档查询类的比如 context7用来查 GitHub 上三方库的最新信息防止 AI 用过时 API 做错误决策一个是测试运行类的。以 Claude Code 为例MCP 配置在~/.claude.json或项目级.mcp.json{ mcpServers: { context7: { command: npx, args: [-y, upstash/context7-mcp], env: { DEFAULT_MINIMUM_TOKENS: 5000 } }, test-runner: { command: npx, args: [-y, modelcontextprotocol/server-filesystem, ./tests] } } }context7 用来抓取三方库最新文档test-runner 这里用 filesystem server 举例实际项目中你可以换成更贴合自己测试框架的 MCP。配好之后重启 Claude Code用/mcp命令能看到已加载的 server 列表。三件套配完建议做一次连通性检查。在 Claude Code 里输入/status确认 Base URL 和 Model 显示正确在 Codex CLI 里跑一次codex print hello看能不能正常返回。如果这一步就报错先别往下走回到第 5 节对照报错排查。4. SDD TDD 实操从需求到测试通过配置通了现在进入正题。这一节我会用一个具体需求走完整条链路给一个已有的登录页面加登录按钮防抖功能。这个需求足够小能在一篇文章里演示完又足够典型能暴露 Vibe Coding 的局部最优问题——如果直接让 AI 改它很可能在请求前加锁而不是抽一个防抖组件。4.1 先写 Spec别急着让 AI 写代码SDD 的核心理念是先写一份详细的技术文档明确输入、输出、逻辑边界和 UI 约束然后让 AI 根据这份图纸生成代码。在仓库里维护SPEC.md或docs/spec/*.md内容至少包含五块目标/范围/非目标、模块边界与依赖方向、接口/数据契约、非功能要求、验收标准。验收标准这块最关键因为它会直接派生成测试。我用的提示词模板是这样的你是一个技术文档工程师。我要给登录页面加登录按钮防抖功能。 请基于以下信息生成一份 SPEC.md不要写实现代码。 背景登录按钮当前无防抖快速点击会发送多次请求。 目标点击后 500ms 内重复点击不触发新请求。 非目标不改动登录接口本身不改动表单校验逻辑。 模块边界只允许修改 src/components/LoginButton 和 src/hooks/useDebounce。 接口契约LoginButton 的 props 不变useDebounce 返回一个包裹后的函数。 非功能要求防抖延迟可配置默认 500ms不引入新的第三方依赖。 验收标准请写成 Given-When-Then 格式至少覆盖正常点击、快速连点、防抖期间组件卸载三种情况。把这段丢给 GPT 或 Claude 的强模型它会输出一份结构化的 SPEC.md。你要做的是审查这份文档确认模块边界和验收标准符合预期。这一步不能省——AI 写的文档和代码都需要审查确认之后才可以接受。审查通过后把 SPEC.md 提交到仓库。这份文档是宝贵资产AI 可以通过阅读文档了解模块核心情况新加入的开发者也能快速了解工程。4.2 从 Spec 派生测试先跑一次 RedSpec 里的验收标准要拆成三类测试按性价比排序契约测试/接口测试锁住 API 和 schema 行为最防跑偏领域单元测试锁住不变量和边界条件信息密度最高UI 测试基本不需要只测功能逻辑部分。用这个提示词让 AI 从 Spec 生成测试骨架阅读 docs/spec/login-button-debounce.md 的验收标准部分。 为每条 Given-When-Then 生成一个测试用例骨架使用 Vitest React Testing Library。 要求 1. 只生成测试文件不要生成实现代码。 2. 每个测试的断言先写成 expect(true).toBe(false)确保测试能失败。 3. 测试文件放在 src/components/LoginButton/__tests__/ 下。 4. 不要 mock useDebounce要测真实行为。生成的测试骨架大概长这样import { render, screen, fireEvent } from testing-library/react; import { LoginButton } from ../LoginButton; describe(LoginButton 防抖, () { it(正常点击应触发一次登录请求, () { const onSubmit vi.fn(); render(LoginButton onSubmit{onSubmit} /); fireEvent.click(screen.getByRole(button)); expect(onSubmit).toHaveBeenCalledTimes(1); expect(true).toBe(false); // 故意失败确认测试有效 }); it(500ms 内快速连点应只触发一次请求, () { const onSubmit vi.fn(); render(LoginButton onSubmit{onSubmit} /); const btn screen.getByRole(button); fireEvent.click(btn); fireEvent.click(btn); fireEvent.click(btn); expect(onSubmit).toHaveBeenCalledTimes(1); expect(true).toBe(false); }); it(防抖期间组件卸载不应报错, () { const onSubmit vi.fn(); const { unmount } render(LoginButton onSubmit{onSubmit} /); fireEvent.click(screen.getByRole(button)); unmount(); expect(true).toBe(false); }); });跑一次npm test确认所有测试都是 Red。这一步很多人会跳过但它极其重要如果测试一开始就是绿的说明它根本没测到东西后面 AI 把代码改绿了也是假绿。4.3 让 AI 做最小改动把测试跑绿现在进入 TDD 的核心循环。提示词的重点不是写代码而是只改这些模块、必须满足 Spec 的这些条款、目标是让以下 failing tests 通过、输出 git diff 和验证命令。模板如下阅读 docs/spec/login-button-debounce.md 和 src/components/LoginButton/__tests__/ 下的测试。 目标让所有 failing tests 通过。 约束 1. 只允许修改 src/components/LoginButton 和 src/hooks/useDebounce。 2. 必须满足 SPEC 的模块边界和接口契约。 3. 不引入新的第三方依赖。 4. 不要修改测试文件。 输出git diff 格式的改动 验证命令。AI 会生成useDebouncehook 和改造后的LoginButton。跑npm test如果全绿进入下一步如果还有红的把失败信息贴回去让它继续改但每次都要强调只改允许的模块。绿了之后才是重构。允许 AI 重构但以测试全绿为护栏。如果实现过程中有取舍或行为更改先改 Spec再改测试和实现否则会出现 spec 漂移——文档和代码对不上下次 AI 读文档就会被误导。4.4 用 subAgent 并行处理独立任务当项目里同时有多个独立任务时可以用 subAgent 提效。subAgent 是专门处理某一类任务的 AI 助手有自己独立的上下文窗口执行结果回到主会话汇总。它适合做专注、可并行、只要结果的任务比如查 API、找 bug 根因、写测试方案。在 Claude Code 里你可以这样描述任务用 subAgent 并行处理以下三个任务每个任务独立汇报结果 1. 为 useDebounce 补充边界条件测试延迟为 0、负数、超大值。 2. 检查 LoginButton 是否有内存泄漏风险。 3. 查 context7 上 React 19 的 useTransition 是否能替代当前防抖实现。subAgent 的 token 成本较低因为结果摘要才回到主上下文。但要注意subAgent 之间不能互相通信所以涉及多模块协商的任务比如跨模块重构不适合用 subAgent得用 Agent Teams。Agent Teams 是真正的多会话并行每个成员是完整的 AI 对话共享任务列表成员之间可以直接通信但成本更高慎用。5. 常见报错排查401、proxy failed 与 OAuth配置和流程跑起来之后最容易卡住的就是各种报错。这一节把我在实际使用中踩过的坑列出来对照着排查。401 Unauthorized。这是最常见的。先确认三件事Key 是否复制完整有没有漏掉前缀或多余空格、Base URL 是否写对Claude Code 用https://taotoken.net/apiCodex 用https://taotoken.net/api/v1、Key 是否已激活。如果三件套都对还报 401用第 2 节的 curl 命令单独测一次能通说明是工具配置问题不通说明是 Key 问题。另外注意Claude Code 读的是ANTHROPIC_AUTH_TOKEN而不是ANTHROPIC_API_KEY这两个字段名不一样写错了会静默失败。local proxy failed / connection refused。这个报错通常出现在你之前配过本地代理工具还在往旧地址发请求。检查~/.claude/settings.json里有没有残留的HTTP_PROXY或HTTPS_PROXY环境变量有就删掉。Codex 的话检查~/.codex/config.toml里的base_url是不是还指向 localhost。还有一种情况是 MCP server 启动失败导致的 proxy failed用/mcp看哪个 server 是红的单独跑一下它的启动命令看报什么错。Error reading choices / choices 字段为空。这个报错说明请求发出去了但返回的 JSON 结构不符合预期。常见原因是 Model ID 写错了比如写了个不存在的模型名服务端返回了错误结构。检查ANTHROPIC_MODEL或model字段确认模型名拼写正确。另一个原因是wire_api配错了Codex 里如果填了responses但服务端只支持chat就会解析失败改成chat即可。OAuth 相关报错。如果你用的是 Claude Code 的官方登录流程它可能会尝试走 OAuth 而不是 API Key。报错信息里出现oauth或login字样时检查是不是同时配了 OAuth token 和 API Key两者冲突。解决办法是清掉 OAuth 相关的缓存通常在~/.claude/下的 credentials 文件只保留ANTHROPIC_AUTH_TOKEN。MCP server 加载了但工具调不到。先确认 MCP server 进程真的起来了用ps aux | grep mcp看一眼。然后确认工具名有没有冲突两个 MCP 提供同名工具时后加载的会覆盖前面的。最后检查上下文占用MCP 工具本身会侵占上下文如果同时开了五六个 MCP模型可能没足够空间做推理表现就是工具明明在但 AI 就是不用。按需开启用完就关。测试跑绿了但功能还是坏的。这是 TDD 里最隐蔽的坑测试写得太弱AI 用取巧的方式让它变绿。比如断言只检查了函数被调用没检查调用参数或者 mock 掉了真实逻辑。排查方法是看测试的断言强度如果一条测试只有expect(fn).toHaveBeenCalled()而没有参数和次数断言基本就是弱测试。回到第 4.2 节把断言写强。git 历史被 AI 搞乱。如果你不小心放开了 git 权限AI 可能执行了git commit --amend或git reset把历史改得面目全非。这就是为什么第 3 节的 permissions 里我刻意没放开 git 写操作。补救办法是用git reflog找到操作前的 commit hash然后git reset --hard hash恢复。记住git 是最后一道防线别让 AI 碰。6. 把流程固化下来从工具到习惯走到这里你已经有了完整的链路TaoToken 统一接入模型Claude Code 和 Codex 配好三件套Spec 驱动设计测试驱动实现MCP 补齐外部知识报错有对照表。但工具配好只是开始真正让这套流程产生价值的是把它固化成习惯。第一件事是把 Spec 和测试纳入 code review。以前 review 只看代码现在 review 先看 Spec 有没有更新、测试有没有覆盖新的验收标准。如果一次改动没有对应的 Spec 变更和测试变更这次改动就不该合并。这条规则听起来严但它能挡住 80% 的AI 悄悄改行为问题。第二件事是善用 Skills。Skills 是可复用的作业指导书SOP 触发条件 交付格式可以用命令触发也可以在合适场景自动触发。一个 Skill 的目录结构是SKILL.md必需scripts/、references/、assets/可选。它解决的问题是固化流程、减少重复工作、把脆弱的多轮编排改成更确定的程序化执行同时节省上下文。凡是重复了两次以上的类似 prompt都应该封装成命令或 Skill。比如从 Spec 生成测试骨架这个动作你每周都要做就该写成一个 Skill。第三件事是控制 MCP 数量。MCP 扩展了 AI 的能力边界但它侵占上下文工具调用过程中的查询和结果也带来上下文。我的做法是分场景配置日常编码只开 context7 和测试相关的 MCP做 iOS 开发时临时开 apple-docs MCP 抓官方 API 知识做完就关。不要图省事全开着上下文被稀释后模型准确率会明显下降。第四件事是模型分工要稳定。Codex 做架构处理Claude 做工程实现再用 Codex 做检查处理——这个分工我在多个项目里验证过比单一模型从头跑到尾效果好。原因是不同模型的偏见不同交叉检查能暴露单一模型看不到的问题。TaoToken 的价值在这里体现得最明显同一个 Key 切换不同模型不用维护多套配置。最后说一个心态上的事。AI 时代代码生成会越来越便宜但判断需求、约束设计、系统取舍、线上风险、质量体系这些不会消失甚至会更重要因为 AI 把产能放大了你需要更强的质量与方向盘。对新手来说最大的问题不是写不出来而是不知道什么是对的、不知道怎么验证、不知道为什么这样设计。所以如果你带新人别让他全程靠 AI 自动驾驶让他用 AI 解释代码、带着他读项目强制他写测试、跑验证命令把为什么这么做写进文档和规则里形成团队知识库。这套流程不是让你少写代码而是让你把精力从敲键盘转移到定义问题和验证结果上。SDD 把意图结构化TDD 把意图可执行化两者合起来Vibe Coding 才真正从看起来很快变成跑得通、守得住、可回滚。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →