<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>AI Coding on Orangex-position0的技术博客</title><link>https://Orangex-position0.github.io/tags/ai-coding/</link><description>Recent content in AI Coding on Orangex-position0的技术博客</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Tue, 20 Oct 2026 17:08:55 +0800</lastBuildDate><atom:link href="https://Orangex-position0.github.io/tags/ai-coding/index.xml" rel="self" type="application/rss+xml"/><item><title>AI Coding 之后，spec、plan 和设计文档该怎么留？</title><link>https://Orangex-position0.github.io/posts/ai-coding/ai-coding-design-documents/</link><pubDate>Tue, 20 Oct 2026 17:08:55 +0800</pubDate><guid>https://Orangex-position0.github.io/posts/ai-coding/ai-coding-design-documents/</guid><description>&lt;img src="https://Orangex-position0.github.io/" alt="Featured image of post AI Coding 之后，spec、plan 和设计文档该怎么留？" /&gt;&lt;h1 id="ai-coding-之后哪些设计知识值得留下"&gt;&lt;a href="#ai-coding-%e4%b9%8b%e5%90%8e%e5%93%aa%e4%ba%9b%e8%ae%be%e8%ae%a1%e7%9f%a5%e8%af%86%e5%80%bc%e5%be%97%e7%95%99%e4%b8%8b" class="header-anchor"&gt;&lt;/a&gt;AI Coding 之后，哪些设计知识值得留下？&#10;&lt;/h1&gt;&lt;p&gt;用 AI Coding 和规格驱动开发（SDD）做项目时，我一直有个疑问：功能完成后，&lt;code&gt;spec.md&lt;/code&gt;、&lt;code&gt;plan.md&lt;/code&gt; 这些文档还要留在 Git 仓库里吗？&lt;/p&gt;&#10;&lt;p&gt;实现方案可能在开发过程中发生变化。如果文档没有同步更新，后续 AI 把它当作当前实现的依据，就可能基于过期信息继续修改代码。但直接删除，也可能丢掉有用的需求和设计背景。&lt;/p&gt;&#10;&lt;p&gt;这篇文章讨论这些文档该如何处理，以及哪些设计知识值得依据实际实现整理下来，供后续开发者和 AI 使用。&lt;/p&gt;&#10;&lt;h2 id="一先区分任务记录与长期设计文档"&gt;&lt;a href="#%e4%b8%80%e5%85%88%e5%8c%ba%e5%88%86%e4%bb%bb%e5%8a%a1%e8%ae%b0%e5%bd%95%e4%b8%8e%e9%95%bf%e6%9c%9f%e8%ae%be%e8%ae%a1%e6%96%87%e6%a1%a3" class="header-anchor"&gt;&lt;/a&gt;一、先区分任务记录与长期设计文档&#10;&lt;/h2&gt;&lt;p&gt;需求说明、实现计划和长期设计文档，回答的问题不同。&lt;/p&gt;&#10;&lt;p&gt;本文采用下面这组命名约定。它们不是行业统一标准，实际项目可以使用其他文件名。&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;文档&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;主要回答的问题&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;常见内容&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;spec.md&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;这次准备做什么？&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;需求、行为预期、验收条件&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;plan.md&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;这次准备怎么实现？&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;修改范围、实施步骤、迁移安排&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;design.md&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;系统当前如何工作？修改时需要知道什么？&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;职责边界、运行机制、约束、已确认的设计取舍&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;例如，一个实现计划可能写着：先增加任务表，再实现后台执行器，最后补充重试测试。这能解释开发顺序，却不能直接帮助后续维护者回答：执行器何时领取任务？失败后谁负责重新调度？重复领取会发生什么？&lt;/p&gt;&#10;&lt;p&gt;长期设计文档应该围绕后面这些问题组织，而不是把已经完成的 Checklist 换个标题。&lt;/p&gt;&#10;&lt;p&gt;这也不意味着设计文档只能在实现后编写。它也可以在实现前起草，用于讨论方案；但本文关注的是代码实现完成后的设计文档：哪些设想已经落地，哪些发生了变化，哪些仍然只是计划。&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;如果每次任务都会生成独立的 &lt;code&gt;spec.md&lt;/code&gt; 和 &lt;code&gt;plan.md&lt;/code&gt;，文档可能逐渐积累。对于仅服务单次任务的文档，可以在实现完成、测试通过并合并 PR 后，将仍有价值的信息整理到对应的长期文档中：需求约定保留在持续维护的规格说明中，运行机制写入设计文档，重要决策记入 ADR，再归档或删除原任务文档。仍用于约束后续行为或验收的规格说明应继续维护。是否提交到 Git 仓库，取决于共享和追溯需求，而非文件名。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;h2 id="二什么时候值得单独写一份文档"&gt;&lt;a href="#%e4%ba%8c%e4%bb%80%e4%b9%88%e6%97%b6%e5%80%99%e5%80%bc%e5%be%97%e5%8d%95%e7%8b%ac%e5%86%99%e4%b8%80%e4%bb%bd%e6%96%87%e6%a1%a3" class="header-anchor"&gt;&lt;/a&gt;二、什么时候值得单独写一份文档？&#10;&lt;/h2&gt;&lt;p&gt;独立文档有维护成本。如果一个函数和对应测试就能解释全部行为，再写一遍通常只会增加重复。&lt;/p&gt;&#10;&lt;p&gt;所以在编写前，可以先问三个问题来检查是否需要单独的设计文档。&lt;/p&gt;&#10;&lt;h3 id="1-理解这个功能是否必须跨多个文件"&gt;&lt;a href="#1-%e7%90%86%e8%a7%a3%e8%bf%99%e4%b8%aa%e5%8a%9f%e8%83%bd%e6%98%af%e5%90%a6%e5%bf%85%e9%a1%bb%e8%b7%a8%e5%a4%9a%e4%b8%aa%e6%96%87%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;1. 理解这个功能，是否必须跨多个文件？&#10;&lt;/h3&gt;&lt;p&gt;以异步任务为例，提交入口、任务存储、执行器和失败处理可能分散在不同位置。每个文件都不复杂，但读者需要自己拼出完整流程。&lt;/p&gt;&#10;&lt;p&gt;此时，一份说明组件关系和主要流程的文档，比逐个解释方法名称更有用。&lt;/p&gt;&#10;&lt;h3 id="2-是否存在容易被后续修改破坏的约束"&gt;&lt;a href="#2-%e6%98%af%e5%90%a6%e5%ad%98%e5%9c%a8%e5%ae%b9%e6%98%93%e8%a2%ab%e5%90%8e%e7%bb%ad%e4%bf%ae%e6%94%b9%e7%a0%b4%e5%9d%8f%e7%9a%84%e7%ba%a6%e6%9d%9f" class="header-anchor"&gt;&lt;/a&gt;2. 是否存在容易被后续修改破坏的约束？&#10;&lt;/h3&gt;&lt;p&gt;这里的约束，是指修改设计时&lt;strong&gt;必须保持成立的条件&lt;/strong&gt;，也常被称为&lt;strong&gt;不变量&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;例如：“订单只有在支付确认后才能进入已支付状态。”代码可能通过多个分支和事务操作共同保证这件事，单独看某个方法未必能意识到它的重要性。&lt;/p&gt;&#10;&lt;p&gt;文档需要把约束明确写出来，并指出由什么机制或测试保障。如果目前无法确认实现是否充分保障了它，就应标为待核验，而不是把设计要求写成已经成立的事实。&lt;/p&gt;&#10;&lt;h3 id="3-是否存在代码本身难以解释的取舍"&gt;&lt;a href="#3-%e6%98%af%e5%90%a6%e5%ad%98%e5%9c%a8%e4%bb%a3%e7%a0%81%e6%9c%ac%e8%ba%ab%e9%9a%be%e4%bb%a5%e8%a7%a3%e9%87%8a%e7%9a%84%e5%8f%96%e8%88%8d" class="header-anchor"&gt;&lt;/a&gt;3. 是否存在代码本身难以解释的取舍？&#10;&lt;/h3&gt;&lt;p&gt;代码通常能显示选择的结果，却未必保留选择过程。&lt;/p&gt;&#10;&lt;p&gt;为什么暂时不支持自动恢复？为什么保留一个看似重复的存储层？如果当时确实讨论过多个方案，最终选择及其条件值得留下。否则，后续维护者可能在不知道原有约束的情况下重新作出决定。&lt;/p&gt;&#10;&lt;p&gt;不必机械统计命中了几项。更实用的判断是：&lt;strong&gt;缺少这份说明，下一位维护者是否需要反复跨文件推理，或者容易误改重要机制？&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;文档粒度也应围绕能独立理解的模块或子系统划分。例如，认证、任务调度、文档导入可以分别说明；给任务调度增加一个配置项，通常更新原文档即可，不必每个 Feature 都新建一篇。&lt;/p&gt;&#10;&lt;h2 id="三文档应该写什么从一个教学示例开始"&gt;&lt;a href="#%e4%b8%89%e6%96%87%e6%a1%a3%e5%ba%94%e8%af%a5%e5%86%99%e4%bb%80%e4%b9%88%e4%bb%8e%e4%b8%80%e4%b8%aa%e6%95%99%e5%ad%a6%e7%a4%ba%e4%be%8b%e5%bc%80%e5%a7%8b" class="header-anchor"&gt;&lt;/a&gt;三、文档应该写什么：从一个教学示例开始&#10;&lt;/h2&gt;&lt;p&gt;下面使用一个假设的异步任务模块说明方法。（它不是实际项目复盘，只是一个用于讲述的案例）&lt;/p&gt;&#10;&lt;p&gt;假设我们已经确认了这些实现行为：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;提交入口将任务保存为 &lt;code&gt;pending&lt;/code&gt;。&lt;/li&gt;&#10;&lt;li&gt;Executor 领取任务，将其转为 &lt;code&gt;running&lt;/code&gt; 后处理。&lt;/li&gt;&#10;&lt;li&gt;成功时转为 &lt;code&gt;succeeded&lt;/code&gt;。&lt;/li&gt;&#10;&lt;li&gt;失败后允许额外重试，最多三次；重试耗尽后转为 &lt;code&gt;failed&lt;/code&gt;。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;这里有个问题：这些内容太概括性了。设计文档还应帮助读者建立更多理解，包括但不限于职责边界、运行流程等&lt;/p&gt;&#10;&lt;h3 id="职责和边界"&gt;&lt;a href="#%e8%81%8c%e8%b4%a3%e5%92%8c%e8%be%b9%e7%95%8c" class="header-anchor"&gt;&lt;/a&gt;职责和边界&#10;&lt;/h3&gt;&lt;p&gt;这个模块负责接收任务、调度执行并记录结果；具体业务操作由处理器完成。&lt;/p&gt;&#10;&lt;p&gt;这句话确定了修改入口：调整领取策略，应查看调度部分；增加一种业务任务，应查看处理器扩展方式。边界说明要与实际接口、依赖关系相符，不能只写一段理想中的分层。&lt;/p&gt;&#10;&lt;h3 id="主要运行流程"&gt;&lt;a href="#%e4%b8%bb%e8%a6%81%e8%bf%90%e8%a1%8c%e6%b5%81%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;主要运行流程&#10;&lt;/h3&gt;&lt;p&gt;用一段简短说明串起提交、保存、领取、执行和结果写回，标出关键组件或符号，让读者知道去哪里继续阅读。&lt;/p&gt;&#10;&lt;p&gt;这里值得解释的是组件之间的协作，不是抄写每个方法内部的分支。&lt;/p&gt;&#10;&lt;h3 id="约束及其保障方式"&gt;&lt;a href="#%e7%ba%a6%e6%9d%9f%e5%8f%8a%e5%85%b6%e4%bf%9d%e9%9a%9c%e6%96%b9%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;约束及其保障方式&#10;&lt;/h3&gt;&lt;p&gt;“领取后进入 &lt;code&gt;running&lt;/code&gt;”只是状态变化，还不能证明并发执行器不会领取同一个任务。&lt;/p&gt;&#10;&lt;p&gt;文档需要进一步说明：任务领取是否依赖条件更新、事务或其他机制？这些机制保证了什么，又没有保证什么？&lt;/p&gt;&#10;&lt;p&gt;尤其不能把“同一时刻只有一个执行器领取”直接写成“业务操作恰好执行一次”。如果业务操作已经成功，但结果写回失败，后续重试仍可能重复产生副作用。&lt;/p&gt;&#10;&lt;p&gt;这种跨越多个步骤才能发现的风险，正是文档值得解释的内容。&lt;/p&gt;&#10;&lt;h3 id="失败和恢复边界"&gt;&lt;a href="#%e5%a4%b1%e8%b4%a5%e5%92%8c%e6%81%a2%e5%a4%8d%e8%be%b9%e7%95%8c" class="header-anchor"&gt;&lt;/a&gt;失败和恢复边界&#10;&lt;/h3&gt;&lt;p&gt;有重试次数限制，不等于具备完整恢复能力。还应检查：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;哪些失败允许重试，是否有等待间隔？&lt;/li&gt;&#10;&lt;li&gt;执行器在 &lt;code&gt;running&lt;/code&gt; 状态下崩溃，任务如何处理？&lt;/li&gt;&#10;&lt;li&gt;重试时，已经发生的业务副作用如何处理？&lt;/li&gt;&#10;&lt;li&gt;没有自动恢复时，是否需要人工介入？&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;如果实现尚未覆盖某种情况，就记录为限制或待解决问题。不要为了让文档看起来完整，补上一套代码里不存在的恢复机制。&lt;/p&gt;&#10;&lt;h3 id="已确认的决策理由"&gt;&lt;a href="#%e5%b7%b2%e7%a1%ae%e8%ae%a4%e7%9a%84%e5%86%b3%e7%ad%96%e7%90%86%e7%94%b1" class="header-anchor"&gt;&lt;/a&gt;已确认的决策理由&#10;&lt;/h3&gt;&lt;p&gt;假设代码明确限制最多重试三次，但没有任何记录解释这个数字。&lt;/p&gt;&#10;&lt;p&gt;可以写：&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;当前最多额外重试三次。该次数选择的理由未记录。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;不能直接写：&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;为了平衡成功率与系统负载，系统采用三次重试。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;后一句可能听起来合理，但它只是对实现的解释，不是已经证实的决策理由。若没有当时的讨论、决策记录或负责人确认，就应保留未知。&lt;/p&gt;&#10;&lt;h2 id="四如何让-ai-协助整理而不编造-why"&gt;&lt;a href="#%e5%9b%9b%e5%a6%82%e4%bd%95%e8%ae%a9-ai-%e5%8d%8f%e5%8a%a9%e6%95%b4%e7%90%86%e8%80%8c%e4%b8%8d%e7%bc%96%e9%80%a0-why" class="header-anchor"&gt;&lt;/a&gt;四、如何让 AI 协助整理，而不编造 Why&#10;&lt;/h2&gt;&lt;p&gt;让 AI 读取需求说明和开发对话，然后“总结一份设计文档”，容易把原先的计划写成当前实现。&lt;/p&gt;&#10;&lt;p&gt;更稳妥的方式，是先区分要确认的问题，再找对应证据。下面是本文建议的整理方式，不是某个文档模板规定的统一流程。&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;要确认的问题&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;优先查看的材料&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;需要注意&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;当前实际如何工作&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;当前代码、有效配置、相关测试&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;测试未必覆盖所有路径；默认配置未必等于部署配置&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;预期应该如何工作&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;已接受的需求、接口契约、测试断言&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;与实现有冲突时，需要明确记录差异&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;为什么选择当前方案&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ADR、PR 讨论、明确的决策说明&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;必须确认材料对应的是当前方案，而非已经放弃的设想&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;最初准备怎么做&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;实现计划、开发对话&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;可作背景，但不能单独证明已经落地&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;这比给所有材料排一条绝对优先级更准确。代码适合证明当前行为，决策记录适合解释选择理由；当两者矛盾时，需要调查，而不是简单让其中一方覆盖另一方。（这里推荐人工 Review + AI Review，不要完全交给 AI 来做，避免幻觉）&lt;/p&gt;&#10;&lt;h3 id="第一步先整理事实与缺口"&gt;&lt;a href="#%e7%ac%ac%e4%b8%80%e6%ad%a5%e5%85%88%e6%95%b4%e7%90%86%e4%ba%8b%e5%ae%9e%e4%b8%8e%e7%bc%ba%e5%8f%a3" class="header-anchor"&gt;&lt;/a&gt;第一步：先整理事实与缺口&#10;&lt;/h3&gt;&lt;p&gt;先让 AI 输出主要流程、关键约束、证据位置和无法确认的部分。&lt;/p&gt;&#10;&lt;p&gt;每条重要判断都应能回到对应材料。例如：重试次数来自哪里，领取逻辑由哪个入口触发，某项设计理由记录在哪次讨论中。&lt;/p&gt;&#10;&lt;p&gt;找不到的部分直接标为“未找到证据”或“待确认”。没有找到证据不等于一定没有相关实现，也不等于该设计不存在，不然 AI 可能会编造一个不存在的设计。&lt;/p&gt;&#10;&lt;h3 id="第二步人工核对高风险结论"&gt;&lt;a href="#%e7%ac%ac%e4%ba%8c%e6%ad%a5%e4%ba%ba%e5%b7%a5%e6%a0%b8%e5%af%b9%e9%ab%98%e9%a3%8e%e9%99%a9%e7%bb%93%e8%ae%ba" class="header-anchor"&gt;&lt;/a&gt;第二步：人工核对高风险结论&#10;&lt;/h3&gt;&lt;p&gt;重点核对涉及并发、状态转换、重试、资源释放和权限边界的判断。AI 找到了相关符号，不代表已经完整理解其调用条件。&lt;/p&gt;&#10;&lt;p&gt;对设计理由尤其要谨慎。如果负责人只能给出今天的解释，应标注为当前补充说明，不要伪装成当初已有记录的决策。因为 AI 容易根据代码反推出一个设计理由，这会成为隐患的开端。&lt;/p&gt;&#10;&lt;h3 id="第三步再组织成长期文档"&gt;&lt;a href="#%e7%ac%ac%e4%b8%89%e6%ad%a5%e5%86%8d%e7%bb%84%e7%bb%87%e6%88%90%e9%95%bf%e6%9c%9f%e6%96%87%e6%a1%a3" class="header-anchor"&gt;&lt;/a&gt;第三步：再组织成长期文档&#10;&lt;/h3&gt;&lt;p&gt;确认事实以后，再让 AI 按职责、流程、约束、决策和限制组织内容。下面这段 prompt 作为一个参考模板，各位可自行扩展：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;根据已确认的材料整理模块设计文档：&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. 区分当前实现、预期行为和未来计划。&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. 重要行为和约束注明证据位置。&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. 不根据实现反推并编造设计理由。&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4. 实现与文档不一致时，列出冲突，不自行替双方作决定。&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;5. 缺少理由时标记“原因未记录”；无法确认行为时标记“待核验”。&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;6. 说明失败处理、恢复方式及已知限制，不补写不存在的能力。&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;7. 优先解释跨组件机制，不逐个复述方法。&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="五文档放在哪里才不会越写越乱"&gt;&lt;a href="#%e4%ba%94%e6%96%87%e6%a1%a3%e6%94%be%e5%9c%a8%e5%93%aa%e9%87%8c%e6%89%8d%e4%b8%8d%e4%bc%9a%e8%b6%8a%e5%86%99%e8%b6%8a%e4%b9%b1" class="header-anchor"&gt;&lt;/a&gt;五、文档放在哪里，才不会越写越乱？&#10;&lt;/h2&gt;&lt;p&gt;项目变复杂后，可以把不同层次的信息分开。下面是一种可选的组织方式，也是我正在使用的，不是必须一次建齐的目录标准。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ARCHITECTURE.md&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docs/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── design/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ ├── task-scheduling.md&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ └── authentication.md&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── adr/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── 0001-example-decision.md&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;ARCHITECTURE.md&lt;/code&gt;：这里的架构不是前端或后端的架构，而是一个项目级别的架构地图，主要用于帮助用户快速定位和理解代码。&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;design-xxx.md&lt;/code&gt;：模块级别的长期设计文档&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;adr-xxx.md&lt;/code&gt;：记录重要的架构决策历史&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="项目架构地图帮助定位"&gt;&lt;a href="#%e9%a1%b9%e7%9b%ae%e6%9e%b6%e6%9e%84%e5%9c%b0%e5%9b%be%e5%b8%ae%e5%8a%a9%e5%ae%9a%e4%bd%8d" class="header-anchor"&gt;&lt;/a&gt;项目架构地图：帮助定位&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;ARCHITECTURE.md&lt;/code&gt; 说明项目解决什么问题、主要模块如何组织、边界在哪里，以及有哪些全局约束。&lt;/p&gt;&#10;&lt;p&gt;有一个社区主流的模板你可以参考：就是 matklad 在 &lt;a class="link" href="https://matklad.github.io/2021/02/06/ARCHITECTURE.md.html" target="_blank" rel="noopener"&#10; &gt;ARCHITECTURE.md&lt;/a&gt; 一文中强调保持简短，描述稳定的代码地图和架构不变量，避免深入每个模块的内部细节。&lt;/p&gt;&#10;&lt;p&gt;因此，项目地图不必成为一份随每个函数变化的说明书。上面教学示例的详细重试机制，放在任务模块的文档里更合适。&lt;/p&gt;&#10;&lt;h3 id="模块设计文档解释当前机制"&gt;&lt;a href="#%e6%a8%a1%e5%9d%97%e8%ae%be%e8%ae%a1%e6%96%87%e6%a1%a3%e8%a7%a3%e9%87%8a%e5%bd%93%e5%89%8d%e6%9c%ba%e5%88%b6" class="header-anchor"&gt;&lt;/a&gt;模块设计文档：解释当前机制&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;docs/design/&lt;/code&gt; 下的文档负责解释一个模块的职责、运行流程、约束、失败处理和限制。&lt;/p&gt;&#10;&lt;p&gt;小模块可以只写几段。需要更多结构时，可以借鉴 &lt;a class="link" href="https://arc42.org/overview/" target="_blank" rel="noopener"&#10; &gt;arc42&lt;/a&gt; 并按需裁剪。arc42 提供 12 个章节，但使用它不等于必须填满所有章节，也不局限于大型项目。&lt;/p&gt;&#10;&lt;h3 id="adr保留重要决策"&gt;&lt;a href="#adr%e4%bf%9d%e7%95%99%e9%87%8d%e8%a6%81%e5%86%b3%e7%ad%96" class="header-anchor"&gt;&lt;/a&gt;ADR：保留重要决策&#10;&lt;/h3&gt;&lt;p&gt;ADR（架构决策记录）围绕一次重要选择展开：当时的问题是什么，考虑了哪些方案，最终选了什么，理由和后果是什么。&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://github.com/adr/madr" target="_blank" rel="noopener"&#10; &gt;MADR&lt;/a&gt; 提供了相应模板，其中一些部分是可选的。它适合补充决策历史，不适合独自承担整个模块的运行说明。&lt;/p&gt;&#10;&lt;p&gt;这三类文档允许互相引用，但不必重复粘贴。例如，模块文档简述当前采用的方案，并链接相关 ADR；详细备选方案和当时的权衡留在 ADR 中。&lt;/p&gt;&#10;&lt;h2 id="六如何维护更新机制不重新生成历史"&gt;&lt;a href="#%e5%85%ad%e5%a6%82%e4%bd%95%e7%bb%b4%e6%8a%a4%e6%9b%b4%e6%96%b0%e6%9c%ba%e5%88%b6%e4%b8%8d%e9%87%8d%e6%96%b0%e7%94%9f%e6%88%90%e5%8e%86%e5%8f%b2" class="header-anchor"&gt;&lt;/a&gt;六、如何维护：更新机制，不重新生成历史&#10;&lt;/h2&gt;&lt;p&gt;生成第一版文档只是开始。后续修改代码时，需要检查这次变化影响了哪类知识。&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;变更&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;文档处理方式&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;局部重构，外部行为和设计边界不变&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;通常不需要修改高层文档；若引用的关键符号失效，则修正定位信息&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;模块的数据流、状态转换、失败处理或约束变化&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;更新对应模块文档&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;模块职责、依赖方向或系统边界变化&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;检查项目架构地图及相关模块文档&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;重要方案被替代&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;按项目约定新增决策记录，标明与旧决策的关系，保留旧记录&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;可以把“是否影响设计文档”加入变更检查：不要求每个 PR 都改文档，但需要判断这次修改是否让已有说明失真。&lt;/p&gt;&#10;&lt;p&gt;对于稳定的项目地图，matklad 的建议是定期回顾，而不是追求与代码细节实时同步。模块文档则应在其描述的关键机制变化时校准。两者维护频率不同，不能用同一条规则一概而论。&lt;/p&gt;&#10;&lt;p&gt;如果使用 AI 更新，先让它指出现有文档中受影响的段落，再给出局部修改。整篇重新生成可能抹掉原有约束、已知限制和决策依据，也会增加审查成本。&lt;/p&gt;&#10;&lt;p&gt;当文档开始大量重复代码、读者必须反复修正过期细节时，还应考虑删减，而不只是继续补充。长期维护的目标是保留有用的理解线索，不是保存尽可能多的文字。&lt;/p&gt;&#10;&lt;h2 id="七将文档整理流程封装为-skill"&gt;&lt;a href="#%e4%b8%83%e5%b0%86%e6%96%87%e6%a1%a3%e6%95%b4%e7%90%86%e6%b5%81%e7%a8%8b%e5%b0%81%e8%a3%85%e4%b8%ba-skill" class="header-anchor"&gt;&lt;/a&gt;七、将文档整理流程封装为 Skill&#10;&lt;/h2&gt;&lt;p&gt;如果经常需要整理或更新设计文档，可以把重复使用的流程封装为一个 Skill：模板作为参考文件，&lt;code&gt;SKILL.md&lt;/code&gt; 说明如何查找证据、区分实现与计划，以及更新已有文档。&lt;/p&gt;&#10;&lt;p&gt;前面提到的“不编造设计理由”“标记待核验内容”“优先局部更新”等规则，也可以一起保留。具体的模块结构、运行机制和设计取舍，仍需从当前项目中核对，不能由模板预先填好。&lt;/p&gt;&#10;&lt;p&gt;这样“偷懒”省掉的是每次重新交代整理要求，而不是核对事实和审查文档。&lt;/p&gt;&#10;&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结&#10;&lt;/h2&gt;&lt;p&gt;AI Coding 之后是否需要沉淀设计文档，取决于后续理解和修改所需的知识，而不是这次生成了多少代码。&lt;/p&gt;&#10;&lt;p&gt;如果实现很局部，代码、测试和注释已经能解释清楚，就不必另写一篇。如果理解一个能力需要跨组件推理，或者存在容易误改的约束与重要取舍，就值得留下简短、可核对的说明。&lt;/p&gt;&#10;&lt;p&gt;整理时要分清：代码能确认哪些行为，历史材料记录了哪些理由，还有哪些问题尚未得到解释。可以让 AI 帮忙寻找和组织证据，但缺少理由时，留下“未记录”比补上一段顺畅的解释更可靠。&lt;/p&gt;&#10;&lt;p&gt;从一个最难理解、最担心误改的模块开始即可。先说明它负责什么、如何运转、哪些条件不能破坏，以及已知的限制，再决定是否需要更完整的文档结构。&lt;/p&gt;&#10;&lt;h2 id="references"&gt;&lt;a href="#references" class="header-anchor"&gt;&lt;/a&gt;References&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://matklad.github.io/2021/02/06/ARCHITECTURE.md.html" target="_blank" rel="noopener"&#10; &gt;matklad：ARCHITECTURE.md&lt;/a&gt;：简短的项目架构地图、代码定位、边界和架构不变量。&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://arc42.org/overview/" target="_blank" rel="noopener"&#10; &gt;arc42 官方概览&lt;/a&gt;：可按需裁剪的架构文档模板。&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://github.com/adr/madr" target="_blank" rel="noopener"&#10; &gt;MADR&lt;/a&gt;：Markdown 架构决策记录模板与说明。&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://leanpub.com/documenting-software-architecture/c/free" target="_blank" rel="noopener"&#10; &gt;Simon Brown：The Software Guidebook&lt;/a&gt;：进一步阅读。其书籍介绍与目录涵盖代码之外的补充文档、运行维护和决策记录；本文未对全书作逐章解读。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>什么是 Spec-Driven Development：让 AI 先读懂需求，再开始写代码</title><link>https://Orangex-position0.github.io/posts/ai-coding/spec-driven-development/</link><pubDate>Tue, 15 Sep 2026 00:00:00 +0800</pubDate><guid>https://Orangex-position0.github.io/posts/ai-coding/spec-driven-development/</guid><description>&lt;img src="https://Orangex-position0.github.io/" alt="Featured image of post 什么是 Spec-Driven Development：让 AI 先读懂需求，再开始写代码" /&gt;&lt;p&gt;AI Coding 让“写代码”变快了，但也放大了另一个问题：如果需求本身是模糊的，AI 只会更快地产生一堆看似合理、实际偏题的代码。&lt;/p&gt;&#10;&lt;p&gt;所以我最近在看 SDD，也就是 Spec-Driven Development。它的核心不是多写一份文档，而是把规格说明变成开发流程里的真实源头：先把“要做什么、为什么做、做到什么程度算完成”说清楚，再让 AI 去处理“怎么实现”。&lt;/p&gt;&#10;&lt;p&gt;一句话理解 SDD：&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;先由人定义 What，再让 AI 推导 How。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;你可以从这篇文章了解四件事：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;SDD 到底是什么&lt;/li&gt;&#10;&lt;li&gt;SDD 的标准四阶段流程&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;spec.md&lt;/code&gt;、&lt;code&gt;plan.md&lt;/code&gt;、&lt;code&gt;tasks.md&lt;/code&gt; 三文件体系怎么流转&lt;/li&gt;&#10;&lt;li&gt;一个好的 Spec 应该怎么写&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="1-sdd-是什么"&gt;&lt;a href="#1-sdd-%e6%98%af%e4%bb%80%e4%b9%88" class="header-anchor"&gt;&lt;/a&gt;1. SDD 是什么&#10;&lt;/h2&gt;&lt;p&gt;SDD，全称 Spec-Driven Development，可以翻译为规格驱动开发。&lt;/p&gt;&#10;&lt;p&gt;传统开发里，文档经常只是代码之前的脚手架：需求评审时写一写，开发时参考一下，项目推进后很容易和代码脱节。到了 AI Coding 场景，这个问题会更明显。因为 AI 不是项目成员，它不知道你的历史上下文、团队习惯和隐含边界。你给它一个模糊输入，它就会用自己的默认假设补全空白。&lt;/p&gt;&#10;&lt;p&gt;SDD 的思路是反过来：规格说明不是代码的附属品，而是唯一真实来源。代码、测试、任务拆分和实现计划，都从 Spec 派生出来。&lt;/p&gt;&#10;&lt;p&gt;也就是说，AI 写得好不好，不只取决于模型能力，也取决于 Spec 是否足够清楚。&lt;/p&gt;&#10;&lt;p&gt;可以粗略对比一下：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;开发方式&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;核心输入&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;常见问题&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;直接 Prompt 编程&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;一段自然语言需求&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;AI 容易自由发挥，边界和验收标准不稳定&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;传统文档驱动&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;PRD、设计文档、会议结论&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;文档和代码容易脱节&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;SDD&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;可验证的 Spec + Plan + Tasks&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;前期要花时间迭代 Spec，但后续实现更可控&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;所以 SDD 不是“写更多文档”，而是把需求从“描述性文本”变成“可约束实现的开发输入”。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="Direct Prompt 与 SDD 输入方式对比" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="941" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://Orangex-position0.github.io/posts/ai-coding/spec-driven-development/2.png" srcset="https://Orangex-position0.github.io/posts/ai-coding/spec-driven-development/2_hu_d8e532d42a5af982.png 800w, https://Orangex-position0.github.io/posts/ai-coding/spec-driven-development/2_hu_bcd3f88cb894d86d.png 1600w, https://Orangex-position0.github.io/posts/ai-coding/spec-driven-development/2.png 1672w" width="1672"&gt;&lt;/p&gt;&#10;&lt;h2 id="2-sdd-的四阶段流程"&gt;&lt;a href="#2-sdd-%e7%9a%84%e5%9b%9b%e9%98%b6%e6%ae%b5%e6%b5%81%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;2. SDD 的四阶段流程&#10;&lt;/h2&gt;&lt;p&gt;一个典型的 SDD 流程可以拆成四个阶段：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;阶段&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;主导者&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;核心产出&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;关键动作&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Specify&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;人&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;spec.md&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;定义问题、目标、边界、成功标准&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Plan&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;人 + AI&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;plan.md&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;根据 Spec 生成架构方案、模块划分、接口设计&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Implement&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;AI&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;代码 + 测试&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;按任务逐步实现&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Validate&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;人 + AI&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;测试结果 + Review 结论&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;自动化测试、人工审查、回到 Spec 修正偏差&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;这四步里，最容易被低估的是第一步 Specify。&lt;/p&gt;&#10;&lt;p&gt;很多 AI 编程失败，不是失败在 Implement，而是失败在 Specify。需求里没有说清楚目标边界，AI 就会替你做决定；成功标准没有写成可验证条件，AI 就会用“功能已经完成”这种描述性结论糊过去；Non-Goals 没写清楚，AI 就可能顺手加一个你并不需要的功能。&lt;/p&gt;&#10;&lt;p&gt;SDD 想解决的正是这个问题：在代码生成之前，把关键约束提前落到文档里。这其实和如今（2026年）AI Coding 圈中提到的“关键决策前置”理念类似。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="SDD 四阶段流程：Specify、Plan、Implement、Validate" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="941" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://Orangex-position0.github.io/posts/ai-coding/spec-driven-development/1.png" srcset="https://Orangex-position0.github.io/posts/ai-coding/spec-driven-development/1_hu_549032141da308ac.png 800w, https://Orangex-position0.github.io/posts/ai-coding/spec-driven-development/1_hu_312bc6dd3dfab80b.png 1600w, https://Orangex-position0.github.io/posts/ai-coding/spec-driven-development/1.png 1672w" width="1672"&gt;&lt;/p&gt;&#10;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart LR&#10; A[需求想法] --&gt; B[spec.md&lt;br/&gt;What / Why]&#10; B --&gt; C[plan.md&lt;br/&gt;How]&#10; C --&gt; D[tasks.md&lt;br/&gt;可执行任务]&#10; D --&gt; E[代码与测试]&#10; E --&gt; F[验证与 Review]&#10; F --&gt;|发现偏差| B&lt;/pre&gt;&lt;p&gt;注意最后一条回路：如果验证阶段发现问题，不应该只在代码里打补丁，而是先判断 Spec 是否写错、写漏或写得太模糊。否则下一次让 AI 继续改，很可能又会沿着同一个模糊输入跑偏。&lt;/p&gt;&#10;&lt;h2 id="3-三文件体系specplantasks"&gt;&lt;a href="#3-%e4%b8%89%e6%96%87%e4%bb%b6%e4%bd%93%e7%b3%bbspecplantasks" class="header-anchor"&gt;&lt;/a&gt;3. 三文件体系：Spec、Plan、Tasks&#10;&lt;/h2&gt;&lt;p&gt;GitHub 的 Spec Kit 把 SDD 落成了一套比较清晰的文件流转方式：&lt;code&gt;spec.md&lt;/code&gt;、&lt;code&gt;plan.md&lt;/code&gt;、&lt;code&gt;tasks.md&lt;/code&gt;。&lt;/p&gt;&#10;&lt;p&gt;这三个文件分别回答三个问题：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;文件&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;回答的问题&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;不该承担的职责&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;spec.md&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;做什么，为什么做，怎么验收&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;不写具体技术实现细节&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;plan.md&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;如何实现，架构怎么选，模块怎么拆&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;不重新发明需求&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;tasks.md&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;按什么顺序交付，每一步怎么验证&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;不塞进大段设计讨论&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h3 id="specmd定义-what-和-why"&gt;&lt;a href="#specmd%e5%ae%9a%e4%b9%89-what-%e5%92%8c-why" class="header-anchor"&gt;&lt;/a&gt;spec.md：定义 What 和 Why&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;spec.md&lt;/code&gt; 是 SDD 的起点。它应该回答：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;为什么要做这个功能？&lt;/li&gt;&#10;&lt;li&gt;用户是谁？&lt;/li&gt;&#10;&lt;li&gt;用户在什么场景下使用？&lt;/li&gt;&#10;&lt;li&gt;功能边界在哪里？&lt;/li&gt;&#10;&lt;li&gt;做到什么程度算完成？&lt;/li&gt;&#10;&lt;li&gt;本期明确不做什么？&lt;/li&gt;&#10;&lt;li&gt;有哪些必须遵守的技术或业务约束？&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;这里最重要的一点是：&lt;code&gt;spec.md&lt;/code&gt; 不应该提前写死具体实现。&lt;/p&gt;&#10;&lt;p&gt;比如：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;使用 Redis 分布式锁防止订单重复提交。&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这句话已经进入 How 的范围了。除非“必须使用 Redis 分布式锁”本身就是项目约束，否则它不适合放在 Spec 里。&lt;/p&gt;&#10;&lt;p&gt;更适合作为 Spec 的说法是：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;订单创建接口必须支持幂等：客户端使用同一个 Idempotency-Key 重试请求时，系统最多创建一笔订单，并返回同一个订单编号。&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这句话没有绑定具体技术栈，但它足够约束实现。无论最后用数据库唯一约束、Redis 锁还是其他方案，都必须满足“同一个幂等键最多创建一笔订单”这个可验证标准。&lt;/p&gt;&#10;&lt;p&gt;这里涉及到了如何编写一个“好的 Spec”，后面第四章会有具体说明。&lt;/p&gt;&#10;&lt;h3 id="planmd把需求翻译成方案"&gt;&lt;a href="#planmd%e6%8a%8a%e9%9c%80%e6%b1%82%e7%bf%bb%e8%af%91%e6%88%90%e6%96%b9%e6%a1%88" class="header-anchor"&gt;&lt;/a&gt;plan.md：把需求翻译成方案&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;plan.md&lt;/code&gt; 基于 &lt;code&gt;spec.md&lt;/code&gt; 生成，负责回答“怎么做”。&lt;/p&gt;&#10;&lt;p&gt;这一步可以让 AI 先生成方案，但人必须 review。因为 AI 很容易给出看似完整、实际不适合当前项目的设计，比如：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;引入一个项目里没有的基础设施&lt;/li&gt;&#10;&lt;li&gt;把简单功能拆成过多模块&lt;/li&gt;&#10;&lt;li&gt;忽略现有架构边界&lt;/li&gt;&#10;&lt;li&gt;给出无法测试或无法回滚的方案&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;好的 &lt;code&gt;plan.md&lt;/code&gt; 应该能解释关键设计选择，而不是只列一个技术清单。&lt;/p&gt;&#10;&lt;p&gt;比如：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;选择在 orders 表增加 idempotency_key 字段，并建立 user_id + idempotency_key 唯一索引，而不是引入 Redis 分布式锁。&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;原因：订单创建已经落库在同一个事务中，数据库唯一约束可以直接保证最终一致的去重语义；引入 Redis 锁会增加额外组件依赖和锁过期边界。&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这种说明比“用数据库实现幂等”更有价值，因为它把取舍讲清楚了。&lt;/p&gt;&#10;&lt;h3 id="tasksmd拆成可验证的小任务"&gt;&lt;a href="#tasksmd%e6%8b%86%e6%88%90%e5%8f%af%e9%aa%8c%e8%af%81%e7%9a%84%e5%b0%8f%e4%bb%bb%e5%8a%a1" class="header-anchor"&gt;&lt;/a&gt;tasks.md：拆成可验证的小任务&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;tasks.md&lt;/code&gt; 把 &lt;code&gt;plan.md&lt;/code&gt; 拆成可执行任务。&lt;/p&gt;&#10;&lt;p&gt;任务拆分的关键不是“越细越好”，而是每个任务都应该有独立可验证的交付物。一个任务如果完成后无法检查，就很难交给 AI 稳定执行。&lt;/p&gt;&#10;&lt;p&gt;比如下面这种任务就太模糊：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;完善订单幂等功能。&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;更好的写法是：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- 为 orders 表增加 idempotency_key 字段，并添加 user_id + idempotency_key 唯一索引。&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- 调整订单创建接口：同一用户使用相同 Idempotency-Key 重试时返回已有订单编号。&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- 补充 3 个测试：首次创建订单、相同幂等键重复请求、不同幂等键创建新订单。&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;拆到这个程度，AI 才知道每一步的完成条件是什么，人也更容易 review。&lt;/p&gt;&#10;&lt;h2 id="4-什么是好的-spec"&gt;&lt;a href="#4-%e4%bb%80%e4%b9%88%e6%98%af%e5%a5%bd%e7%9a%84-spec" class="header-anchor"&gt;&lt;/a&gt;4. 什么是好的 Spec&#10;&lt;/h2&gt;&lt;p&gt;我理解一个好的 Spec 至少应该包含六个要素：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;要素&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;作用&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;示例&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Problem Statement&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;定义为什么做&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;当前系统不支持细粒度权限控制，管理员只能使用固定角色&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Success Metrics&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;定义做到什么程度算完成&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;权限判断 P95 小于 50ms，覆盖 20+ 权限类型&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;User Stories&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;定义谁在什么场景下使用&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;作为管理员，我可以创建自定义角色&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Acceptance Criteria&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;定义怎么验收&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;单用户拥有多个角色时，权限结果取并集&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Non-Goals&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;定义本期不做什么&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;本期不支持跨组织权限委托&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Constraints&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;定义必须遵守的约束&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;必须兼容现有 OAuth 2.0 登录流程&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;这里有两个关键词：可验证、有限边界。&lt;/p&gt;&#10;&lt;h3 id="反例看起来像需求其实约束不了实现"&gt;&lt;a href="#%e5%8f%8d%e4%be%8b%e7%9c%8b%e8%b5%b7%e6%9d%a5%e5%83%8f%e9%9c%80%e6%b1%82%e5%85%b6%e5%ae%9e%e7%ba%a6%e6%9d%9f%e4%b8%8d%e4%ba%86%e5%ae%9e%e7%8e%b0" class="header-anchor"&gt;&lt;/a&gt;反例：看起来像需求，其实约束不了实现&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;系统需要一个快速的搜索功能。搜索结果应该相关且准确。界面要美观易用。&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这段话不是完全没用，但它不适合作为给 AI 的 Spec。问题在于：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;“快速”没有指标，无法验证&lt;/li&gt;&#10;&lt;li&gt;“相关且准确”没有定义搜索范围和排序规则&lt;/li&gt;&#10;&lt;li&gt;“美观易用”混入了 UI 评价，但没有交互标准&lt;/li&gt;&#10;&lt;li&gt;没说为什么要做搜索，也没说搜索什么内容&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;如果直接把这段话交给 AI，它只能自行猜测。&lt;/p&gt;&#10;&lt;h3 id="正例把描述变成可验收条件"&gt;&lt;a href="#%e6%ad%a3%e4%be%8b%e6%8a%8a%e6%8f%8f%e8%bf%b0%e5%8f%98%e6%88%90%e5%8f%af%e9%aa%8c%e6%94%b6%e6%9d%a1%e4%bb%b6" class="header-anchor"&gt;&lt;/a&gt;正例：把描述变成可验收条件&#10;&lt;/h3&gt;&lt;p&gt;可以改成这样：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Problem:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;当前文章列表超过 200 篇后，用户只能通过分类和标签查找内容，无法按关键词快速定位文章。&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;User Story:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;作为博客读者，我希望在文章列表页输入关键词后，看到标题或摘要命中的文章列表。&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Acceptance Criteria:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- 搜索范围包括文章标题和 description，不包括正文全文。&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- 搜索大小写不敏感。&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- 无匹配结果时展示空状态，而不是保留旧列表。&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- 在 200 篇文章规模下，搜索结果应在 300ms 内返回。&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Non-Goals:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- 本期不做全文搜索。&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- 本期不做搜索高亮。&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- 本期不引入独立搜索服务。&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这份 Spec 没有告诉 AI 必须用什么技术实现，但它把边界说清楚了。AI 可以自由选择实现方式，但不能偏离验收标准。&lt;/p&gt;&#10;&lt;h2 id="spec-的粒度怎么控制"&gt;&lt;a href="#spec-%e7%9a%84%e7%b2%92%e5%ba%a6%e6%80%8e%e4%b9%88%e6%8e%a7%e5%88%b6" class="header-anchor"&gt;&lt;/a&gt;Spec 的粒度怎么控制&#10;&lt;/h2&gt;&lt;p&gt;Spec 最难的是粒度：写得太粗，AI 会自由发挥；写得太细，又变成伪代码，失去了让 AI 参与方案设计的意义。&lt;/p&gt;&#10;&lt;p&gt;Github spec-kit 提出了一个校验标准：&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;换一种技术栈实现，这份 Spec 是否仍然成立？&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;如果答案是否定的，说明 Spec 里可能混入了太多实现细节。&lt;/p&gt;&#10;&lt;p&gt;比如：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;使用 Redis ZSET 存储排行榜。&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这句话换成不用 Redis 的技术栈就不成立，所以它更像 Plan 里的技术选择。&lt;/p&gt;&#10;&lt;p&gt;再看这句：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;排行榜需要支持实时更新，用户完成一次有效得分后，排名结果应在 1 秒内反映到榜单查询结果中。&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这句话无论用什么技术栈都成立，所以更适合放进 Spec。&lt;/p&gt;&#10;&lt;p&gt;我会把原则总结成一句话：&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;Spec 要精确到能约束实现，但抽象到不依赖具体实现细节。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;h2 id="spec-需要迭代不是一遍写完"&gt;&lt;a href="#spec-%e9%9c%80%e8%a6%81%e8%bf%ad%e4%bb%a3%e4%b8%8d%e6%98%af%e4%b8%80%e9%81%8d%e5%86%99%e5%ae%8c" class="header-anchor"&gt;&lt;/a&gt;Spec 需要迭代，不是一遍写完&#10;&lt;/h2&gt;&lt;p&gt;很多人第一次写 Spec 时，会下意识把它当成一次性文档：写完就交给 AI，然后进入实现。&lt;/p&gt;&#10;&lt;p&gt;但实践里，第一版 Spec 往往都有问题：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;边界条件漏了&lt;/li&gt;&#10;&lt;li&gt;成功标准太模糊&lt;/li&gt;&#10;&lt;li&gt;Non-Goals 不够明确&lt;/li&gt;&#10;&lt;li&gt;用户场景写得太泛&lt;/li&gt;&#10;&lt;li&gt;技术约束没有说清楚&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;根据阿里淘特团队的实践经验，Spec 往往需要 3 到 5 次迭代才会比较稳定。这个成本是值得的，因为改文档通常比改代码便宜得多。&lt;/p&gt;&#10;&lt;p&gt;更重要的是，Spec 的迭代过程会逼着人先想清楚问题本身。AI 可以帮我们写代码，但不应该替我们决定产品边界和工程取舍。&lt;/p&gt;&#10;&lt;h2 id="推荐工具github-spec-kit"&gt;&lt;a href="#%e6%8e%a8%e8%8d%90%e5%b7%a5%e5%85%b7github-spec-kit" class="header-anchor"&gt;&lt;/a&gt;推荐工具：GitHub Spec Kit&#10;&lt;/h2&gt;&lt;p&gt;如果想实际尝试 SDD，可以从 GitHub Spec Kit 开始。&lt;/p&gt;&#10;&lt;p&gt;Spec Kit 提供了一组围绕 SDD 的命令和模板，核心流程是：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/speckit.specify -&amp;gt; /speckit.plan -&amp;gt; /speckit.tasks -&amp;gt; /speckit.implement&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;更完整的流程还可以加入：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/speckit.constitution -&amp;gt; /speckit.specify -&amp;gt; /speckit.clarify -&amp;gt; /speckit.plan -&amp;gt; /speckit.checklist -&amp;gt; /speckit.tasks -&amp;gt; /speckit.analyze -&amp;gt; /speckit.implement&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;其中 &lt;code&gt;constitution.md&lt;/code&gt; 比较有意思。它相当于项目级别的“宪法”，用来定义不可违背的工程约束，比如：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;架构分层原则&lt;/li&gt;&#10;&lt;li&gt;安全要求&lt;/li&gt;&#10;&lt;li&gt;测试要求&lt;/li&gt;&#10;&lt;li&gt;API 设计约束&lt;/li&gt;&#10;&lt;li&gt;代码质量底线&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;有了这些公共约束，每个 Spec 就不需要重复声明“这个项目不允许绕过鉴权”“这个项目必须补测试”之类的基础规则。AI 在生成 Plan 和 Tasks 时，也能对齐项目长期约束。&lt;/p&gt;&#10;&lt;p&gt;不过工具只是辅助。真正重要的还是写 Spec 的习惯：把 What 和 Why 说清楚，把边界写明确，把验收标准变成可验证条件。&lt;/p&gt;&#10;&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结&#10;&lt;/h2&gt;&lt;p&gt;SDD 的价值不在于多产出几个 Markdown 文件，而在于改变 AI Coding 的输入方式。&lt;/p&gt;&#10;&lt;p&gt;直接让 AI 写代码时，Prompt 往往混在一起：需求、实现、约束、偏好、临时想法都塞进一段话里。SDD 则把这些内容拆开：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;spec.md&lt;/code&gt; 负责 What 和 Why&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;plan.md&lt;/code&gt; 负责 How&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;tasks.md&lt;/code&gt; 负责可执行步骤&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;constitution.md&lt;/code&gt; 负责项目级不变量&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;这样做的结果是，AI 不再只是根据一段模糊描述自由发挥，而是在明确边界和验收标准下生成实现。&lt;/p&gt;&#10;&lt;p&gt;对我来说，SDD 最重要的提醒是：AI 编程不是跳过需求分析，而是让需求分析变得更关键。因为代码生成越快，错误需求被放大的速度也越快。&lt;/p&gt;&#10;&lt;p&gt;先写清楚 Spec，再让 AI 动手，可能才是更稳定的 AI Coding 工作流。&lt;/p&gt;&#10;&lt;h2 id="参考资料"&gt;&lt;a href="#%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99" class="header-anchor"&gt;&lt;/a&gt;参考资料&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://github.github.com/spec-kit/" target="_blank" rel="noopener"&#10; &gt;GitHub Spec Kit Documentation&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://github.com/github/spec-kit/blob/main/docs/concepts/sdd.md" target="_blank" rel="noopener"&#10; &gt;GitHub Spec Kit: What is Spec-Driven Development?&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://github.com/github/spec-kit/blob/main/docs/reference/agentic-sdd.md" target="_blank" rel="noopener"&#10; &gt;GitHub Spec Kit: Agentic SDD&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://news.qq.com/rain/a/20260509A01W3100" target="_blank" rel="noopener"&#10; &gt;5 人 7 天干完 20 人数周的活：Spec-Driven Development 如何重新定义 AI 编程_腾讯新闻&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item></channel></rss>