{
  "title": "Vibe Coding 的蜜月期结束了：AI 开发正在从\"写代码\"进化到\"写契约\"",
  "url": "https://miaok.ong/posts/vibe-coding-contract-first/",
  "date": "2026-06-21T00:00:00Z",
  "lastmod": "2026-06-21T00:00:00Z",
  "type": "posts",
  "kind": "page",
  "language": "zh",
  "description": "\u003cblockquote\u003e\n\u003cp\u003e自然语言描述需求 → 等 AI 吐代码 → 跑一下，居然能用。这种体验太爽了。但当你把这种模式带入超过 3 天、超过 3 个文件的真实项目时，爽感会在某个深夜崩溃：这个数为什么是 0？这个页面数据是哪来的？为什么 mock 数据被当成了生产结果？\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"一vibe-coding-的临界点\"\u003e\n  一、Vibe Coding 的临界点\n  \u003ca class=\"heading-link\" href=\"#%e4%b8%80vibe-coding-%e7%9a%84%e4%b8%b4%e7%95%8c%e7%82%b9\"\u003e\n    \u003ci class=\"fa-solid fa-link\" aria-hidden=\"true\" title=\"链接到标题\"\u003e\u003c/i\u003e\n    \u003cspan class=\"sr-only\"\u003e链接到标题\u003c/span\u003e\n  \u003c/a\u003e\n\u003c/h2\u003e\n\u003cp\u003e2026 年 6 月，73% 的开发团队在日常工作中使用 AI 编码代理\u003csup id=\"fnref:1\"\u003e\u003ca href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e1\u003c/a\u003e\u003c/sup\u003e。Codex 推出了跨设备任务迁移（Handoff）和操作复刻（Record \u0026amp; Replay），Claude Code 上线了可视化协作的 Artifacts 功能，GLM-5.2 在编程基准上逼近顶级闭源模型。\u003c/p\u003e\n\u003cp\u003e工具栈在飞速成熟，但一个更根本的问题浮出水面：\u003cstrong\u003e开发范式没有跟上\u003c/strong\u003e。\u003c/p\u003e\n\u003cp\u003eVibe Coding 这个从 2025 年流行起来的词，描述的是一种\u0026quot;凭感觉\u0026quot;的 AI 辅助开发方式：用自然语言描述你想做什么，让 AI 写代码，跑通就算完。它的核心体验是\u003cstrong\u003e快感驱动\u003c/strong\u003e——省去了查文档、设计接口、写测试的\u0026quot;枯燥\u0026quot;环节，直达\u0026quot;看到效果\u0026quot;的多巴胺。\u003c/p\u003e\n\u003cp\u003e问题也在这里。Vibe Coding 的验证终点是\u0026quot;页面能跑\u0026quot;。但在 AI 的加持下，一个数据全部伪造的页面也能跑得很快。\u003c/p\u003e\n\u003cp\u003eX 上开发者 @dotey 系统性地回应了这个问题：\u0026ldquo;需求分析、系统设计、代码审查和灰度发布在 AI 时代非但不能省，反而更重要。\u0026ldquo;另一位从安全从业者转向全栈开发的 @Pluvio9yte 则提出了一个更精准的主张——\u003cstrong\u003eContract First\u003c/strong\u003e。不是需求文档驱动，也不是纯粹代码驱动，而是先定义接口、数据模型和验收标准这些\u0026quot;契约\u0026rdquo;，再把它们作为人和 AI 之间稳定的参照物。\u003c/p\u003e\n\u003cp\u003e这个话题今天在技术社区爆发，不是偶然的。它标志着 AI 辅助开发正在经历从\u0026quot;能用\u0026quot;到\u0026quot;可靠\u0026quot;的范式迁移。\u003c/p\u003e\n\u003ch2 id=\"二一个真实翻车案例demo-惊艳生产致命\"\u003e\n  二、一个真实翻车案例：Demo 惊艳、生产致命\n  \u003ca class=\"heading-link\" href=\"#%e4%ba%8c%e4%b8%80%e4%b8%aa%e7%9c%9f%e5%ae%9e%e7%bf%bb%e8%bd%a6%e6%a1%88%e4%be%8bdemo-%e6%83%8a%e8%89%b3%e7%94%9f%e4%ba%a7%e8%87%b4%e5%91%bd\"\u003e\n    \u003ci class=\"fa-solid fa-link\" aria-hidden=\"true\" title=\"链接到标题\"\u003e\u003c/i\u003e\n    \u003cspan class=\"sr-only\"\u003e链接到标题\u003c/span\u003e\n  \u003c/a\u003e\n\u003c/h2\u003e\n\u003cp\u003e我们内部有一个 AI 辅助开发项目。目标是用 AI Agent 完成一个投资看板 Web App：自选股管理、日报查看、研究库搜索、方法论浏览，最终做成 PWA，手机可用。\u003c/p\u003e",
  "keywords": null,
  "tags": ["AI","Software Engineering","Vibe Coding","Contract First","Developer Tools"],
  "categories": ["Insight"],
  "author": "孔淼",
  "image": "https://miaok.ong/images/2026-06-21-contract-first-cover.jpg",
  "content": "\u003cblockquote\u003e\n\u003cp\u003e自然语言描述需求 → 等 AI 吐代码 → 跑一下，居然能用。这种体验太爽了。但当你把这种模式带入超过 3 天、超过 3 个文件的真实项目时，爽感会在某个深夜崩溃：这个数为什么是 0？这个页面数据是哪来的？为什么 mock 数据被当成了生产结果？\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"一vibe-coding-的临界点\"\u003e\n  一、Vibe Coding 的临界点\n  \u003ca class=\"heading-link\" href=\"#%e4%b8%80vibe-coding-%e7%9a%84%e4%b8%b4%e7%95%8c%e7%82%b9\"\u003e\n    \u003ci class=\"fa-solid fa-link\" aria-hidden=\"true\" title=\"链接到标题\"\u003e\u003c/i\u003e\n    \u003cspan class=\"sr-only\"\u003e链接到标题\u003c/span\u003e\n  \u003c/a\u003e\n\u003c/h2\u003e\n\u003cp\u003e2026 年 6 月，73% 的开发团队在日常工作中使用 AI 编码代理\u003csup id=\"fnref:1\"\u003e\u003ca href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e1\u003c/a\u003e\u003c/sup\u003e。Codex 推出了跨设备任务迁移（Handoff）和操作复刻（Record \u0026amp; Replay），Claude Code 上线了可视化协作的 Artifacts 功能，GLM-5.2 在编程基准上逼近顶级闭源模型。\u003c/p\u003e\n\u003cp\u003e工具栈在飞速成熟，但一个更根本的问题浮出水面：\u003cstrong\u003e开发范式没有跟上\u003c/strong\u003e。\u003c/p\u003e\n\u003cp\u003eVibe Coding 这个从 2025 年流行起来的词，描述的是一种\u0026quot;凭感觉\u0026quot;的 AI 辅助开发方式：用自然语言描述你想做什么，让 AI 写代码，跑通就算完。它的核心体验是\u003cstrong\u003e快感驱动\u003c/strong\u003e——省去了查文档、设计接口、写测试的\u0026quot;枯燥\u0026quot;环节，直达\u0026quot;看到效果\u0026quot;的多巴胺。\u003c/p\u003e\n\u003cp\u003e问题也在这里。Vibe Coding 的验证终点是\u0026quot;页面能跑\u0026quot;。但在 AI 的加持下，一个数据全部伪造的页面也能跑得很快。\u003c/p\u003e\n\u003cp\u003eX 上开发者 @dotey 系统性地回应了这个问题：\u0026ldquo;需求分析、系统设计、代码审查和灰度发布在 AI 时代非但不能省，反而更重要。\u0026ldquo;另一位从安全从业者转向全栈开发的 @Pluvio9yte 则提出了一个更精准的主张——\u003cstrong\u003eContract First\u003c/strong\u003e。不是需求文档驱动，也不是纯粹代码驱动，而是先定义接口、数据模型和验收标准这些\u0026quot;契约\u0026rdquo;，再把它们作为人和 AI 之间稳定的参照物。\u003c/p\u003e\n\u003cp\u003e这个话题今天在技术社区爆发，不是偶然的。它标志着 AI 辅助开发正在经历从\u0026quot;能用\u0026quot;到\u0026quot;可靠\u0026quot;的范式迁移。\u003c/p\u003e\n\u003ch2 id=\"二一个真实翻车案例demo-惊艳生产致命\"\u003e\n  二、一个真实翻车案例：Demo 惊艳、生产致命\n  \u003ca class=\"heading-link\" href=\"#%e4%ba%8c%e4%b8%80%e4%b8%aa%e7%9c%9f%e5%ae%9e%e7%bf%bb%e8%bd%a6%e6%a1%88%e4%be%8bdemo-%e6%83%8a%e8%89%b3%e7%94%9f%e4%ba%a7%e8%87%b4%e5%91%bd\"\u003e\n    \u003ci class=\"fa-solid fa-link\" aria-hidden=\"true\" title=\"链接到标题\"\u003e\u003c/i\u003e\n    \u003cspan class=\"sr-only\"\u003e链接到标题\u003c/span\u003e\n  \u003c/a\u003e\n\u003c/h2\u003e\n\u003cp\u003e我们内部有一个 AI 辅助开发项目。目标是用 AI Agent 完成一个投资看板 Web App：自选股管理、日报查看、研究库搜索、方法论浏览，最终做成 PWA，手机可用。\u003c/p\u003e\n\u003cp\u003ePhase 2.5 的技术 Spike 结束后，团队看到了：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e一个漂亮的首页\u003c/li\u003e\n\u003cli\u003e能登录的用户系统\u003c/li\u003e\n\u003cli\u003e能展示自选股列表的页面\u003c/li\u003e\n\u003cli\u003e日报详情页\u003c/li\u003e\n\u003cli\u003ePWA 可安装，手机端打开流畅\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e按照直觉判断，这应该是\u0026quot;完成了 Spike 阶段\u0026rdquo;。代码提交了，页面能跑，视觉方向也确定了。\u003c/p\u003e\n\u003cp\u003e但当我们进行独立 QA 审查时，从代码层面发现了 7 个问题：\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003e盈亏永远显示 \u003ccode\u003e--\u003c/code\u003e\u003c/strong\u003e：\u003ccode\u003eWatchlistView.vue\u003c/code\u003e 中盈亏字段硬编码，没有接 \u003ccode\u003ecost_price\u003c/code\u003e 和实时行情\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e首页\u0026quot;最近文章\u0026quot;是固定卡片\u003c/strong\u003e：\u003ccode\u003eHomeView.vue\u003c/code\u003e 的最近文章写死了 3 篇样例，代码注释写着\u0026quot;下一阶段接入 knowledge_base\u0026quot;\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e日报摘要是固定文案\u003c/strong\u003e：\u003ccode\u003eReportView.vue\u003c/code\u003e 的 summary-card 不来自 API 真实数据\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAPI 失败时静默展示 mock 行情\u003c/strong\u003e：\u003ccode\u003eportfolio.ts\u003c/code\u003e 内置了 \u003ccode\u003efallbackWatchlist\u003c/code\u003e 和 \u003ccode\u003efallbackQuotes\u003c/code\u003e，一旦后端不可用，前端就展示假数据——和真实数据一模一样\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e自选股只能看不能改\u003c/strong\u003e：后端只实现了 3 个 GET 接口，没有 POST/PATCH/DELETE\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e研究库和方法论页面完全不存在\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e部署方案零落地\u003c/strong\u003e：Nginx/systemd 在文档里写了，但实际只有裸跑 uvicorn\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e这 7 个问题没有一个是隐蔽的 Bug。它们就在代码里，打开文件就能看到。但它们在过程中全部被标记为\u0026quot;已完成\u0026quot;。\u003c/p\u003e\n\u003cp\u003e为什么？\u003c/p\u003e\n\u003ch2 id=\"三不是-ai-不够强是契约缺位\"\u003e\n  三、不是 AI 不够强，是契约缺位\n  \u003ca class=\"heading-link\" href=\"#%e4%b8%89%e4%b8%8d%e6%98%af-ai-%e4%b8%8d%e5%a4%9f%e5%bc%ba%e6%98%af%e5%a5%91%e7%ba%a6%e7%bc%ba%e4%bd%8d\"\u003e\n    \u003ci class=\"fa-solid fa-link\" aria-hidden=\"true\" title=\"链接到标题\"\u003e\u003c/i\u003e\n    \u003cspan class=\"sr-only\"\u003e链接到标题\u003c/span\u003e\n  \u003c/a\u003e\n\u003c/h2\u003e\n\u003cp\u003e复盘结论很清楚：问题不出在 LLM 的能力上，而出在\u003cstrong\u003e人和 AI 之间的契约层\u003c/strong\u003e。\u003c/p\u003e\n\u003cp\u003e在 Vibe Coding 模式下，开发者和 AI 的交互只有两层：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e输入层\u003c/strong\u003e：自然语言需求描述\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e输出层\u003c/strong\u003e：跑通即确认\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e两者的中间地带是真空的。没有接口契约，没有数据契约，没有验收契约。结果就是：AI 按照\u0026quot;让页面看起来能用\u0026quot;的目标优化，而那个目标和\u0026quot;让项目真正可交付\u0026quot;是两回事。\u003c/p\u003e\n\u003cp\u003e更可怕的是，在没有明确定义 DoD（Definition of Done）的场景中，\u003cstrong\u003emock、硬编码和假数据会通过图灵测试\u003c/strong\u003e——它们看起来和真实数据一样，甚至在 Demo 中表现完美。直到用户真正使用，或者被另一个 reviewer 从代码层审查，才会露馅。\u003c/p\u003e\n\u003cp\u003e这就是为什么 Contract First 需要成为 AI 开发的新基座。\u003c/p\u003e\n\u003ch3 id=\"contract-first-的三个维度\"\u003e\n  Contract First 的三个维度\n  \u003ca class=\"heading-link\" href=\"#contract-first-%e7%9a%84%e4%b8%89%e4%b8%aa%e7%bb%b4%e5%ba%a6\"\u003e\n    \u003ci class=\"fa-solid fa-link\" aria-hidden=\"true\" title=\"链接到标题\"\u003e\u003c/i\u003e\n    \u003cspan class=\"sr-only\"\u003e链接到标题\u003c/span\u003e\n  \u003c/a\u003e\n\u003c/h3\u003e\n\u003cp\u003e\u003cstrong\u003e1. 接口契约：API 先于实现\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e在让 AI 写代码之前，先定义好 API 的入参、出参、错误态。不是\u0026quot;做一个自选股页面\u0026quot;，而是：\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eGET /api/watchlist → { tickers: [{symbol, name, shares, cost_price, current_price, pnl}] }\nPOST /api/watchlist → body: {symbol, shares, cost_price} → 201\nPATCH /api/watchlist/{ticker} → body: {shares?, cost_price?} → 200\nDELETE /api/watchlist/{ticker} → 204\n错误态: 401 | 404 | 422\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e有了这层契约，AI 生成代码时就有了硬边界。前端和后端不会各自漂移，reviewer 也有明确的对照标准。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e2. 数据契约：每个 UI 字段必须追溯数据源\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e这是反 mock 的核心武器。为每个页面字段建立数据源映射：\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003e字段\u003c/th\u003e\n          \u003cth\u003e来源\u003c/th\u003e\n          \u003cth\u003e状态\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e自选股盈亏\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003ecost_price\u003c/code\u003e + quote API 实时计算\u003c/td\u003e\n          \u003ctd\u003e⚠️ 硬编码 \u003ccode\u003e--\u003c/code\u003e\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e首页最近文章\u003c/td\u003e\n          \u003ctd\u003eKB API \u003ccode\u003eGET /api/knowledge?limit=3\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003e❌ 固定卡片\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e日报摘要\u003c/td\u003e\n          \u003ctd\u003eReport API \u003ccode\u003eGET /api/reports/{id}\u003c/code\u003e 的 \u003ccode\u003esummary\u003c/code\u003e 字段\u003c/td\u003e\n          \u003ctd\u003e❌ 固定文案\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003ereviewer 拿着这张表审查，mock 和硬编码无处遁形。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e3. 验收契约：DoD + 证据包 + 反 mock 规则\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e每个阶段必须有独立 DoD，不能只靠\u0026quot;看起来完成了\u0026quot;。\u003c/p\u003e\n\u003cp\u003eSpike 阶段可以是轻量的：允许占位、允许 dev-only mock。但必须满足两条硬性规则：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e所有 mock/placeholder 必须集中登记为技术债\u003c/li\u003e\n\u003cli\u003e不允许静默 fallback mock 冒充真实数据\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e进入 MVP 阶段后，规则升级为 P0 阻断：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e生产路径代码不得使用未标注的 fallback mock\u003c/li\u003e\n\u003cli\u003eAPI 失败时必须显示错误态，不自动展示 mock\u003c/li\u003e\n\u003cli\u003e所有页面业务内容必须来自真实数据源\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e加上阶段 Evidence Pack（需求覆盖矩阵、API 覆盖表、数据源映射、mock 扫描结果、reviewer PASS/REVISE/BLOCK 结论），final-gate 就不再是\u0026quot;看报告文案\u0026quot;，而是\u0026quot;审证据厚度\u0026quot;。\u003c/p\u003e\n\u003ch2 id=\"四contract-落地的操作指南\"\u003e\n  四、Contract 落地的操作指南\n  \u003ca class=\"heading-link\" href=\"#%e5%9b%9bcontract-%e8%90%bd%e5%9c%b0%e7%9a%84%e6%93%8d%e4%bd%9c%e6%8c%87%e5%8d%97\"\u003e\n    \u003ci class=\"fa-solid fa-link\" aria-hidden=\"true\" title=\"链接到标题\"\u003e\u003c/i\u003e\n    \u003cspan class=\"sr-only\"\u003e链接到标题\u003c/span\u003e\n  \u003c/a\u003e\n\u003c/h2\u003e\n\u003cp\u003e如果你已经开始在日常开发中使用 AI 代理，以下是可以立即套用的操作清单：\u003c/p\u003e\n\u003ch3 id=\"step-1在每个任务启动前先写需求矩阵\"\u003e\n  Step 1：在每个任务启动前，先写需求矩阵\n  \u003ca class=\"heading-link\" href=\"#step-1%e5%9c%a8%e6%af%8f%e4%b8%aa%e4%bb%bb%e5%8a%a1%e5%90%af%e5%8a%a8%e5%89%8d%e5%85%88%e5%86%99%e9%9c%80%e6%b1%82%e7%9f%a9%e9%98%b5\"\u003e\n    \u003ci class=\"fa-solid fa-link\" aria-hidden=\"true\" title=\"链接到标题\"\u003e\u003c/i\u003e\n    \u003cspan class=\"sr-only\"\u003e链接到标题\u003c/span\u003e\n  \u003c/a\u003e\n\u003c/h3\u003e\n\u003cp\u003e不要直接跟 AI 说\u0026quot;做个用户管理页面\u0026quot;。先画表：\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003e需求项\u003c/th\u003e\n          \u003cth\u003eAPI/数据源\u003c/th\u003e\n          \u003cth\u003eUI 字段\u003c/th\u003e\n          \u003cth\u003e状态\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e用户列表\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003eGET /api/users\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003e表格：姓名/邮箱/角色/状态\u003c/td\u003e\n          \u003ctd\u003e未开始\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e用户详情\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003eGET /api/users/{id}\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003e信息卡：全部字段\u003c/td\u003e\n          \u003ctd\u003e未开始\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e编辑用户\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003ePATCH /api/users/{id}\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003e表单弹窗：角色/状态\u003c/td\u003e\n          \u003ctd\u003e未开始\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e这张表就是你和 AI 之间的稳定契约。无论 AI 怎么自由发挥，review 时只需要逐行对照这张表。\u003c/p\u003e\n\u003ch3 id=\"step-2建立反-mock-清单\"\u003e\n  Step 2：建立反 mock 清单\n  \u003ca class=\"heading-link\" href=\"#step-2%e5%bb%ba%e7%ab%8b%e5%8f%8d-mock-%e6%b8%85%e5%8d%95\"\u003e\n    \u003ci class=\"fa-solid fa-link\" aria-hidden=\"true\" title=\"链接到标题\"\u003e\u003c/i\u003e\n    \u003cspan class=\"sr-only\"\u003e链接到标题\u003c/span\u003e\n  \u003c/a\u003e\n\u003c/h3\u003e\n\u003cp\u003e在代码 review 环节固定执行 \u003ccode\u003egrep\u003c/code\u003e 扫描：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003efallback\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003emock\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esample\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eplaceholder\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e固定中文业务文案（如\u0026quot;今日组合观察\u0026quot;\u0026ldquo;市场整体回暖\u0026rdquo;）\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e每一条出现都必须有合理解释，且登记为技术债或由独立 QA 标记 BLOCK。\u003c/p\u003e\n\u003ch3 id=\"step-3区分-spike-和真实交付的阶段口径\"\u003e\n  Step 3：区分 Spike 和真实交付的阶段口径\n  \u003ca class=\"heading-link\" href=\"#step-3%e5%8c%ba%e5%88%86-spike-%e5%92%8c%e7%9c%9f%e5%ae%9e%e4%ba%a4%e4%bb%98%e7%9a%84%e9%98%b6%e6%ae%b5%e5%8f%a3%e5%be%84\"\u003e\n    \u003ci class=\"fa-solid fa-link\" aria-hidden=\"true\" title=\"链接到标题\"\u003e\u003c/i\u003e\n    \u003cspan class=\"sr-only\"\u003e链接到标题\u003c/span\u003e\n  \u003c/a\u003e\n\u003c/h3\u003e\n\u003cp\u003eSpike 的价值是快，但快必须换来可见风险，不是隐藏风险。每次 Spike 结束强制输出欠债登记：\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003e欠债项\u003c/th\u003e\n          \u003cth\u003e严重度\u003c/th\u003e\n          \u003cth\u003e阻断 MVP？\u003c/th\u003e\n          \u003cth\u003e处理计划\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e\u003ccode\u003eportfolio.ts\u003c/code\u003e fallback mock\u003c/td\u003e\n          \u003ctd\u003eP0\u003c/td\u003e\n          \u003ctd\u003e是\u003c/td\u003e\n          \u003ctd\u003e删除或改为 dev-only\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e盈亏硬编码 \u003ccode\u003e--\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003eP0\u003c/td\u003e\n          \u003ctd\u003e是\u003c/td\u003e\n          \u003ctd\u003e接入 \u003ccode\u003ecost_price\u003c/code\u003e + quote\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e最近文章固定卡片\u003c/td\u003e\n          \u003ctd\u003eP0\u003c/td\u003e\n          \u003ctd\u003e是\u003c/td\u003e\n          \u003ctd\u003e接入 KB API\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eKB/methodology 页面缺失\u003c/td\u003e\n          \u003ctd\u003eP1\u003c/td\u003e\n          \u003ctd\u003e否\u003c/td\u003e\n          \u003ctd\u003e下一阶段\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch3 id=\"step-4reviewer-必须读代码不能只看页面\"\u003e\n  Step 4：Reviewer 必须读代码，不能只看页面\n  \u003ca class=\"heading-link\" href=\"#step-4reviewer-%e5%bf%85%e9%a1%bb%e8%af%bb%e4%bb%a3%e7%a0%81%e4%b8%8d%e8%83%bd%e5%8f%aa%e7%9c%8b%e9%a1%b5%e9%9d%a2\"\u003e\n    \u003ci class=\"fa-solid fa-link\" aria-hidden=\"true\" title=\"链接到标题\"\u003e\u003c/i\u003e\n    \u003cspan class=\"sr-only\"\u003e链接到标题\u003c/span\u003e\n  \u003c/a\u003e\n\u003c/h3\u003e\n\u003cp\u003eAI 时代的验收如果只停留在\u0026quot;打开页面看一眼\u0026quot;，那等于没有验收。因为 AI 生成的页面可能在视觉上完美无缺，而数据完全来自一个 3 行 mock 函数。\u003c/p\u003e\n\u003cp\u003eQA reviewer 的最低审查深度应该是：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e抽查关键前端组件代码\u003c/li\u003e\n\u003cli\u003e对照 API 覆盖率表\u003c/li\u003e\n\u003cli\u003e执行 mock/hardcode grep\u003c/li\u003e\n\u003cli\u003e测试错误态和空态\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"五同一案例contract-first-会拦住什么\"\u003e\n  五、同一案例，Contract First 会拦住什么？\n  \u003ca class=\"heading-link\" href=\"#%e4%ba%94%e5%90%8c%e4%b8%80%e6%a1%88%e4%be%8bcontract-first-%e4%bc%9a%e6%8b%a6%e4%bd%8f%e4%bb%80%e4%b9%88\"\u003e\n    \u003ci class=\"fa-solid fa-link\" aria-hidden=\"true\" title=\"链接到标题\"\u003e\u003c/i\u003e\n    \u003cspan class=\"sr-only\"\u003e链接到标题\u003c/span\u003e\n  \u003c/a\u003e\n\u003c/h2\u003e\n\u003cp\u003e回到上述项目。如果 Phase 2.5 Spike 按照 Contract First 执行，哪些问题会在提交前被拦住？\u003c/p\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003e问题\u003c/th\u003e\n          \u003cth\u003eVibe Coding 下的结果\u003c/th\u003e\n          \u003cth\u003eContract First 下的结果\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003efallback mock\u003c/td\u003e\n          \u003ctd\u003e没人发现，静默通过\u003c/td\u003e\n          \u003ctd\u003eAPI 覆盖表必须标注 mock 路径 → reviewer 查出 → BLOCK\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e盈亏硬编码\u003c/td\u003e\n          \u003ctd\u003e页面看着正常，通过\u003c/td\u003e\n          \u003ctd\u003e数据源映射表标注为\u0026quot;硬编码 \u003ccode\u003e--\u003c/code\u003e\u0026quot; → BLOCK\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e最近文章固定\u003c/td\u003e\n          \u003ctd\u003e卡片有内容，通过\u003c/td\u003e\n          \u003ctd\u003e数据源映射显示\u0026quot;未接 KB API\u0026quot; → 登记为 P0 欠债\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e缺 CRUD\u003c/td\u003e\n          \u003ctd\u003e\u0026ldquo;Spike 阶段可以不完整\u0026rdquo;\u003c/td\u003e\n          \u003ctd\u003e接口契约已定义 POST/PATCH/DELETE → 对照后标记未完成\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003e部署缺失\u003c/td\u003e\n          \u003ctd\u003e\u0026ldquo;上线前再说\u0026rdquo;\u003c/td\u003e\n          \u003ctd\u003eEvidence Pack 要求部署证据或明确声明未部署 → flag\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e核心差异在于：Vibe Coding 下，开发者的自检标准是\u0026quot;它看起来对吗\u0026quot;，而 AI 在视觉上几乎不会出错。Contract First 下，自检标准是\u0026quot;它符合契约吗\u0026quot;，mock 和硬编码在对照矩阵的那一刻就暴露了。\u003c/p\u003e\n\u003ch2 id=\"六ai-时代的软件工程常识在回归\"\u003e\n  六、AI 时代的软件工程常识在回归\n  \u003ca class=\"heading-link\" href=\"#%e5%85%adai-%e6%97%b6%e4%bb%a3%e7%9a%84%e8%bd%af%e4%bb%b6%e5%b7%a5%e7%a8%8b%e5%b8%b8%e8%af%86%e5%9c%a8%e5%9b%9e%e5%bd%92\"\u003e\n    \u003ci class=\"fa-solid fa-link\" aria-hidden=\"true\" title=\"链接到标题\"\u003e\u003c/i\u003e\n    \u003cspan class=\"sr-only\"\u003e链接到标题\u003c/span\u003e\n  \u003c/a\u003e\n\u003c/h2\u003e\n\u003cp\u003e这一波讨论中，我最受触动的是 @dotey 的一句话：\u0026ldquo;需求分析、系统设计、代码审查和灰度发布在 AI 时代非但不能省，反而更重要。\u0026rdquo;\u003c/p\u003e\n\u003cp\u003e这句话的逆直觉之处在于：AI 让写代码变快了，于是我们天然想省掉\u0026quot;不是写代码\u0026quot;的环节。但恰恰是这些环节在 AI 加持下变成了最短的短板——因为你可能一天产出 3000 行代码，而 2000 行是基于 mock 数据的假页面。\u003c/p\u003e\n\u003cp\u003eContract First 不是让开发变慢。它是在 AI 的速度之上，加了一层防撞栏。没有防撞栏，越快的车越危险。\u003c/p\u003e\n\u003cp\u003e更有趣的是，在同一天的技术讨论中，几位开发者不约而同地提到了类似的观察：@AI_Jasonyu 发现 PP-OCRv6 这种 1.5MB 的极小模型在特定垂直任务上反超了 GPT-5.5，因为\u0026quot;边界清晰的契约让精巧的小模型找到了决定性优势\u0026quot;；@zhixianio 在端侧模型测试中反复强调\u0026quot;定义好问题边界\u0026quot;比\u0026quot;用更强的模型\u0026quot;更重要。\u003c/p\u003e\n\u003cp\u003e这些看似不相关的讨论指向同一个方向：\u003cstrong\u003e在系统复杂度面前，契约比能力更重要\u003c/strong\u003e。不是一个更强的 AI 就能解决 mock 问题——只有定义好什么是\u0026quot;真正的完成\u0026quot;，问题才开始被解决。\u003c/p\u003e\n\u003cp\u003e如果你正在用 AI 辅助开发，今天的建议很简单：下一次打开 Codex 或 Cursor 之前，先花 10 分钟画一张需求矩阵。那 10 分钟会在 review 时帮你省下 10 小时。\u003c/p\u003e\n\u003chr\u003e\n\u003cp\u003e\u003cem\u003e2026-06-21 · 公开发布版\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"footnotes\" role=\"doc-endnotes\"\u003e\n\u003chr\u003e\n\u003col\u003e\n\u003cli id=\"fn:1\"\u003e\n\u003cp\u003e数据来源：Stackademic 2026年6月开发者调查，https://blog.stackademic.com/5-ai-coding-agents-that-actually-ship-production-code-in-2026-f4954e98bc05\u0026#160;\u003ca href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\"\u003e\u0026#x21a9;\u0026#xfe0e;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n",
  "wordCount": 544,
  "readingTime": 3,
  "tableOfContents": "\u003cnav id=\"TableOfContents\"\u003e\n  \u003cul\u003e\n    \u003cli\u003e\u003ca href=\"#一vibe-coding-的临界点\"\u003e一、Vibe Coding 的临界点\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#二一个真实翻车案例demo-惊艳生产致命\"\u003e二、一个真实翻车案例：Demo 惊艳、生产致命\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#三不是-ai-不够强是契约缺位\"\u003e三、不是 AI 不够强，是契约缺位\u003c/a\u003e\n      \u003cul\u003e\n        \u003cli\u003e\u003ca href=\"#contract-first-的三个维度\"\u003eContract First 的三个维度\u003c/a\u003e\u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#四contract-落地的操作指南\"\u003e四、Contract 落地的操作指南\u003c/a\u003e\n      \u003cul\u003e\n        \u003cli\u003e\u003ca href=\"#step-1在每个任务启动前先写需求矩阵\"\u003eStep 1：在每个任务启动前，先写需求矩阵\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#step-2建立反-mock-清单\"\u003eStep 2：建立反 mock 清单\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#step-3区分-spike-和真实交付的阶段口径\"\u003eStep 3：区分 Spike 和真实交付的阶段口径\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#step-4reviewer-必须读代码不能只看页面\"\u003eStep 4：Reviewer 必须读代码，不能只看页面\u003c/a\u003e\u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#五同一案例contract-first-会拦住什么\"\u003e五、同一案例，Contract First 会拦住什么？\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#六ai-时代的软件工程常识在回归\"\u003e六、AI 时代的软件工程常识在回归\u003c/a\u003e\u003c/li\u003e\n  \u003c/ul\u003e\n\u003c/nav\u003e",
  "isDraft": false
}
