尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

OpenSpec目录结构全解析:规范即代码的AI协作工作流

OpenSpec目录结构全解析:规范即代码的AI协作工作流 看到不少人拿到 OpenSpec 的第一反应是打开 GitHub 仓库然后盯着目录结构发呆。这个项目最近在 AI 辅助开发圈子里讨论度很高核心思路是用 Markdown 文件把规范、变更、任务全部纳入版本控制让 AI Agent 和人在同一套文件系统里协作。但 OpenSpec 的目录结构不像普通开源项目那样一眼能看懂它既不是传统的 src / docs / tests 布局也不是简单的“放几个 md 文件完事”。这篇就来把 openspec/ 目录从顶层到内部文件完整过一遍讲清楚每个目录和文件是干什么的、什么内容该放哪、以及实际用起来有哪些坑。这篇内容适合两类人看一类是刚接触 OpenSpec、准备在团队里引入这套规范工作流的技术负责人另一类是已经在用 AI 编程助手干活、但总觉得 AI 对项目上下文理解不够深的人。看完你就能理解为什么 OpenSpec 要把目录结构设计成“规范即代码”的样子以及这套结构到底是怎么让 AI 和人类在同一套认知体系里协作的。1. 内容整体设计与思路拆解1.1 OpenSpec 为什么把目录结构当成核心竞争力先说说 OpenSpec 这个项目到底在解决什么问题。传统软件开发里规范和代码是脱节的PR 描述里写了一堆改动原因issue 里挂着需求背景Notion 里躺着架构设计文档README 里只有使用说明。这些东西散落在不同平台人和 AI 都很难把它们关联起来。OpenSpec 的思路是把这些全部拉回仓库里用一套严格定义的目录结构来承载“规范”这件事。目录结构在这里不是简单的文件分类而是整个工作流的地基。OpenSpec 的核心理念是“规范即代码”意思是规范文档要像代码一样走评审、合并、版本控制。那评审和合并的基础是什么是 PR是 diff是 Git 历史。如果规范文件散落各处、命名随意、层级混乱这套流程根本跑不起来。所以 OpenSpec 把目录结构设计得非常严格每个目录放什么、每个文件叫什么、文件里写什么格式的内容都有明确约定。这样一来好处就出来了人和 AI 看到同一套目录就能快速建立起对项目规范的全局认知。AI Agent 读一遍 openspec/ 目录就知道这个项目有哪些已接受的规范、正在推进哪些变更、任务怎么拆解、验收标准是什么。这比让 AI 去读十几个分散的文档要高效得多。1.2 这套目录结构到底解决了什么问题用一句话概括OpenSpec 的目录结构解决的是“规范文档与代码变更脱节”这个老大难问题。举个例子很多团队在 GitHub 上开 issue 记录需求开 PR 实现功能PR 描述里写“closes #123”。看起来有关联但实际上 issue 里的需求细节和 PR 里的代码实现之间没有一个结构化的、可追踪的中间层。三个月后回来看当初为什么做这个功能、设计了哪些方案、放弃了哪些路线全都散落在评论区和聊天记录里。OpenSpec 的目录结构把这个问题拆成了三层来解决。第一层是 specs/存放已经确定下来的规范相当于项目的“宪法”第二层是 changes/存放正在进行的变更提案和实施计划相当于“议案”第三层是 backlog/存放还没排期的需求想法相当于“待办池”。这三层构成了一个清晰的流转路径想法先进 backlog启动后变成 change评审通过后合并进 specs或者被否掉进 archive。更关键的是这套目录结构是给 AI 看的。OpenSpec 从一开始就考虑了 AI Agent 的参与它的目录设计让 AI 能通过文件系统快速理解项目状态。比如 AI 想知道“这个项目接受过哪些重要的技术决策”直接看 specs/ 下每个目录里的 decisions.md 就行想知道“现在有哪些变更在进行”扫一眼 changes/ 目录就知道。1.3 这篇内容能给你带来什么这篇会带着你把 OpenSpec 的目录结构完整过一遍从顶层目录到内部文件从设计理念到实操细节。我会先给你一张顶层目录的全景图然后拆开 specs/ 目录看看里面一个规范目录内部的完整文件组成再讲 changes/ 目录怎么配合变更工作流运作最后聊聊 AI Agent 是怎么利用这套目录结构工作的以及我在实际使用中踩过的坑。2. 第一次打开 openspec/顶层目录速览2.1 用一条命令看全貌先直观感受一下。在一个初始化好的 OpenSpec 仓库里openspec/ 目录的顶层结构大概是这样的openspec/ ├── project.md ├── specs/ ├── changes/ ├── backlog/ ├── templates/ ├── archive/ └── ai/看起来很简单但每个目录背后都有一套逻辑。我第一次用的时候觉得“就这”真正开始写内容才发现怎么给一个变更起名、proposal 里该写多细、什么时候该动 archive/这些全都有讲究。先看 project.md这个文件在顶层不在任何子目录里因为它描述的是项目全局的规范和信息包括项目定位、技术栈、架构约束、编码风格约定以及如果 AI Agent 参与开发它在修改这个项目时需要遵守的基本原则。它的作用类似一个给人和 AI 看的“项目总纲”。我见过一些团队把非常详细的架构文档都塞进 project.md这其实没必要这里应该放稳定的、全局性的信息细节放到对应的 spec 里。2.2 核心目录职责速查表下面这张表整理了顶层目录各自的职责方便你快速对照目录/文件职责内容示例变更频率project.md项目全局规范总纲项目定位、架构约束、AI 协作原则低specs/已接受并生效的规范认证流程规范、API 设计规范低changes/正在推进的变更提案与任务新增某个功能、重构某个模块高backlog/未排期的需求与想法池子待评估的功能想法、优化方向中templates/新变更、新规范的标准模板变更模板、规范模板、任务模板低archive/已过时、被替换或未通过的规范废弃的旧版本规范低ai/存放 AI 生成或读取的辅助信息AI 记忆文件、任务分解草稿中这个表看下来其实能发现一个规律整个 OpenSpec 目录是围绕“规范的演进”来设计的。specs/ 是稳定态changes/ 是活跃态backlog/ 是暂存态archive/ 是终态。这种设计把规范的整个生命周期都纳入了版本管理任何一次变更都有迹可循。2.3 哪些目录由人工维护哪些交给工具用的时候不用每个目录都手动建。OpenSpec 提供了 CLI 工具执行openspec init会生成整套目录骨架以及 templates/ 下的标准模板执行openspec change new 名称会按模板在 changes/ 下创建新的变更目录。所以我建议初始阶段把目录骨架和模板生成交给 CLI人工只需要往模板里填内容。ai/ 这个目录我单独说一下。在团队协作场景下AI Agent 往往会在这个过程中生成一些过程性文件比如把一个 issue 拆解成若干个任务、产生一个临时的重构方案。这些内容放哪如果直接混在 changes/ 里会让变更目录变得臃肿如果放仓库外AI 下次就读不到了。OpenSpec 的 ai/ 目录就是为了承接这种 AI 生成的过程性信息。这个目录里的内容更新频率比较高我一般会告诉 AI“过程草稿可以写进 ai/但最终结论一定要落到 changes/ 或 specs/”。3. 一个 spec 目录的内部文件拆解3.1 specs/ 目录下到底有什么打开 specs/里面不是一堆散落的 Markdown 文件而是按规范名组织的子目录每个子目录代表一个已经生效的规范。比如一个 Web 后端项目可能长这样specs/ ├── authentication/ │ ├── proposal.md │ ├── design.md │ ├── tasks.md │ ├── checklist.md │ ├── changelog.md │ └── decisions.md ├── api-pagination/ │ ├── proposal.md │ ├── design.md │ └── ... └── error-handling/ ├── proposal.md └── ...也就是说每个规范目录内部有一套固定的文件结构。这套结构是 OpenSpec 的核心设计它把一个规范从“为什么做”到“怎么做”到“怎么验收”全部结构化。下面逐个拆解。3.2 proposal.md规范为什么存在proposal.md 回答的是“为什么需要这个规范”。它要写清楚背景、动机、要解决的问题、适用范围以及提案的状态。这份文件是整个规范目录的入口也是评审时最先看的内容。我写 proposal.md 的习惯是先写“现状痛点”再写“目标”再写“非目标”。比如之前给一个项目写 API 错误处理规范痛点就是各个模块报错格式不统一、前端解析困难目标就是统一错误响应结构非目标写清楚这次不涉及日志采集、不涉及监控告警。写“非目标”非常重要它能防止规范在执行过程中被无限扩大这一点是我在实际中踩过坑才总结出来的。3.3 design.md技术方案与决策记录design.md 是技术设计文档描述规范具体怎么落地。它通常包括方案概述、关键流程、数据模型、接口定义、兼容性考虑等。design.md 是规范里最容易写成长的因为它承载了所有技术细节。我的建议是design.md 里放“方案级”的信息而不是“代码级”的信息。比如 API 规范在 design.md 里定义好状态码统一规则、错误响应字段结构就够了不需要贴出一整段 Controller 代码。代码细节留给实现时去看 tasks.md 和执行代码。design.md 还有一个隐藏作用它是 AI Agent 实现功能时的“施工蓝图”。AI 读 design.md 能知道用什么思路实现避免在实现阶段大幅偏离既定方案。所以我写 design.md 时会尽量把边界条件、异常处理策略写清楚这些是 AI 最容易自由发挥、也最容易跑偏的地方。3.4 tasks.md 与 checklist.md从设计到验收tasks.md 是任务分解清单把规范落地需要做的事拆成一个个可执行的任务。任务要写清楚描述、优先级和依赖关系。checklist.md 是验收清单用来确认规范是否真正落地包括功能验证点、代码层面的检查项、文档是否更新等。tasks.md 和 checklist.md 的区别常常被忽略。tasks.md 是“要做的事”偏执行checklist.md 是“做完没做完”偏验收。在 AI 协作的场景下tasks.md 是给 AI 的待办列表checklist.md 是 AI 交付前的自检清单。我一般要求 AI 在完成 tasks.md 里所有任务后必须逐条过一遍 checklist.md并在每一项后面标注验证方式和结果这样可以显著减少 AI 交付时“我以为实现了”的情况。3.5 changelog.md 与 decisions.md记录演进痕迹changelog.md 记录规范自身的变更历史。规范的任何一次修订都应该在这里追加记录包括变更时间、变更内容、变更原因。decisions.md 记录规范制定过程中的关键决策包括有哪些可选方案、为什么选这个不选那个。这两个文件是我见过的团队最容易忽略的但它们恰恰是 OpenSpec 目录结构里最有长期价值的部分。三个月前定的一个技术决策当时觉得理所当然三个月后回来看可能已经不适应新情况了。没有 decisions.md后人或者未来的你就只能靠猜有了 decisions.md就能知道当初的权衡逻辑判断现在的条件是否已经变化。写 decisions.md 有一个小技巧每个决策只写三部分背景、方案对比、结论。背景说明当时的情况方案对比列两到三个可行方案及各自的优劣结论说最终选哪个以及核心原因。控制在一屏内能看完的长度维护成本低信息密度高。4. changes/ 变更目录与完整工作流4.1 change 是这套体系的最小原子如果说 specs/ 是项目的静态规范库changes/ 就是动态的工作区。Change 是 OpenSpec 工作流里最小、最原子的变更单元一个 change 对应一个明确的目标、一份提案和一组任务。Change 和 Issue 或者 PR 不一样。Issue 只描述问题PR 只包含代码 diffchange 则包含完整闭环为什么改proposal、怎么改设计、具体做什么tasks、怎么算完成checklist。所以 change 更像是 Issue、设计文档和 PR 描述的组合体而且是结构化的组合体。创建 change 时CLI 会基于模板生成一个目录changes/ └── add-user-profile/ ├── proposal.md └── tasks.md初始状态只有这两个文件。随着变更推进proposal.md 里的状态字段会变化tasks.md 里的任务会被逐步勾选可能还会补充 design.md 和 checklist.md。4.2 一次完整的变更生命周期一个 change 的完整生命周期大概是这样的在 backlog/ 里确认或新增一条需求想法。执行openspec change new 变更名创建变更目录。在 proposal.md 里写清楚背景、动机、目标和范围。在 tasks.md 里拆解任务标注每个任务的完成状态。方案比较复杂时补充 design.md 记录技术设计。完成实现后填写 checklist.md 做验收确认。变更评审通过后执行openspec spec accept 变更名将变更归档为正式规范或者执行openspec change archive 变更名归档未通过的变更。从这个流程能看出OpenSpec 里“变更归档成规范”这个动作是核心节点。归档时CLI 会把 changes/ 下的变更目录迁移到 specs/ 下生成规范目录。这意味着一个规范的生命起点就是一次变更是经过任务分解和评审的它不会凭空出现。4.3 命名规范与常见误区变更目录的命名有讲究。OpenSpec 约定使用 kebab-case小写字母加连字符例如 add-user-profile、fix-rate-limit 这类命名。命名要能清晰地表达变更意图避免使用 add、update、fix 这种单独出现的宽泛动词因为这类命名无法让读者和 AI 快速理解变更范围。我见过一个团队把变更命名为 “update”结果过了一周这个目录里有五六个不同方向的改动描述彻底变成了一个杂物箱。好的命名应该是一个短语能直接看出要做什么。比如 refactor-auth-middleware 比 update-auth 清晰得多migrate-db-to-postgres 比 change-db 明确得多。另外一个常见误区是试图在一个 change 里塞下多个不相关的事情。比如“新增用户导出功能顺便重构一下登录流程”这种变更会让评审变得很痛苦也让 AI Agent 在实现时抓不住重点。OpenSpec 的设计哲学是一个 change 只做一件事如果确实有多个方向的事情应该拆分多个 change 并行推进。5. 目录结构与 AI Agent 的协作逻辑5.1 为什么 AI 喜欢这种扁平文件系统OpenSpec 的目录设计对 AI Agent 非常友好核心原因在于它把信息组织成了 AI 最容易处理的“小文件多层级”结构而不是“大文件单文档”结构。当前主流的大语言模型在处理上下文时输入长度有限而且输入越长对关键信息的注意力越容易被稀释。如果一个项目的规范全堆在一个几千行的文档里AI 要么截断要么忽略中间的细节。但 OpenSpec 把信息拆成了小粒度的文件每个规范单独一个目录每个文件只承载一个维度的信息。AI 按需读取不用一次吃掉整个知识库。这种设计还有一个好处就是局部修改导致的 diff 更小。AI 更新一个任务状态只需要改动 tasks.md 里的一行Git 历史非常干净。相比之下如果所有信息都在一个超大文档里AI 改一次就要重写整个文件diff 没法看。5.2 AI 在目录里的“读写路径”我总结了 AI Agent 在 OpenSpec 目录结构下的典型工作路径分三步。第一步是读全局。AI 开始工作前先读 openspec/project.md了解项目定位和约束再扫一眼 openspec/specs/知道有哪些已经生效的规范。这个过程相当于给 AI 做一个“上岗培训”。第二步是读变更上下文。AI 被指派处理某个变更时进入对应的 changes/变更名/ 目录读 proposal.md 明确目标读 tasks.md 确定任务列表看看 design.md 里有没有技术约束。第三步是写执行结果。AI 完成某个任务后更新 tasks.md 的勾选状态完成所有任务后填写 checklist.md 的验证结果如果实现过程中发现了没想到的问题记录到 decisions.md 或者补充到 proposal.md 的备注部分。这个路径之所以顺畅完全依赖于目录结构的一致性。每个变更目录都长一样AI 不需要摸索就能知道信息在哪、该往哪里写。5.3 结合 CLI 与 CI 的落地实践OpenSpec 的命令行工具让这套目录结构变成了一个可执行的工作流。我常用的几个命令命令作用使用场景openspec init初始化 OpenSpec 目录骨架与模板新项目接入时openspec change new 名称基于模板创建新变更目录启动一个新变更时openspec spec accept 名称将变更归档为正式规范变更评审通过后openspec change archive 名称归档未通过的变更变更被否掉或废弃时openspec validate校验变更内容的完整性和格式提交前检查这些命令的实际价值是强制把规范性流程固化到工具层。比如openspec validate会检查 proposal.md 是否填写了必要的字段、tasks.md 是否有未标记完成的任务、引用的文件是否存在等。这相当于在 Git 提交前加了一道格式闸门避免“目录结构是对的但里面内容写得不合规范”的情况。在 CI 里我还建议加一步自动校验每次 push 时执行openspec validate如果校验失败CI 直接红掉强迫团队保持变更内容的质量。这也是“规范即代码”的体现规范不只是文档还要接受自动化检查。6. 实操踩坑与问题排查实录6.1 文件放错位置导致流程中断我最初用 OpenSpec 时把一份还没评审通过的设计文档直接放进了 specs/ 目录结果导致项目状态失真specs/ 本应只放已生效的规范未通过的方案应该留在 changes/ 里等待评审。AI 在读取全局信息时把它当成了正式生效的规范后续生成的代码全都围绕这个未定稿方案展开造成返工。后来我养成了一个习惯每次要新建文档时先问一句“这个文件属于规范的哪个生命周期阶段”。想法阶段放 backlog/实施阶段放 changes/定稿阶段才放 specs/废弃的放 archive/。这个判断只需要十秒钟但能避免非常多的混乱。6.2 命名不一致的连锁问题变更目录命名看起来是小事但影响范围很大。我之前有一次用 create-user-api 做变更名另一位同事却用了 user-endpoint-update 来描述同一件事结果两个人各建了一个变更目录责任边界变得模糊合并时非常痛苦。两个人做的还是同一个功能浪费了一倍的时间。OpenSpec 的变更是归入 changes/ 后其目录名会成为规范的最终名称的一部分命名不一致会直接导致历史记录混乱。现在我和团队约定每个变更的命名必须在启动前过一遍保证使用 kebab-case 且能清晰表达意图。宁可多花一分钟确认。6.3 忘记维护 changelog 和 decisions这是最常见的“用着用着就变形”的问题。刚开始大家都老老实实维护 changelog.md 和 decisions.md项目一忙起来第一个被放弃的就是这两个文件。短时间看影响不大但两个月后做架构回溯时没有 decisions.md 的规范目录基本等于没有灵魂根本不知道当初为什么弃用方案 A 而选方案 B。我现在要求的底线是decisions.md 可以晚点写但不能不写至少在变更归档成正式规范之前一定要补上关键决策的简略记录。而且写的时候用固定格式背景一行、对比两行、结论两行不追求文采只追求可追溯。6.4 团队协作时的目录职责边界多人协作时最容易出现的是边界松散。有人习惯在 project.md 里堆砌零碎的项目实时状态有人在 backlog/ 里放已经启动的变更任务。这些偏差看似微小但时间长了会让整个目录结构失去可信度AI 和新人都会养成“文件内容仅供参考”的习惯这套体系的价值就崩了。我的经验是团队接入 OpenSpec 的第一周就明确三个边界project.md 只放稳定的全局信息backlog/ 只放未启动的想法正在做的事一律进 changes/。这三个边界守住目录结构就能长期保持清晰。碰到拿不准放哪的内容宁可先建一个临时说明也不要随意塞进已有文件里破坏结构。6.5 常见问题速查表现象可能原因解决办法变更目录里缺少 design.md方案较简单没有单独写设计在 proposal.md 中增加“方案概述”一节AI 无视已生效规范project.md 和 specs/ 内容过于零散在 project.md 中明确列出 AI 必须阅读的规范清单归档后规范找不到来源变更没有在 proposal.md 中记录来源 change归档前在 proposal.md 里补充关联的变更记录changes/ 目录越来越乱变更没有及时推进或归档每周清理一次 changes/完成或废弃的及时归档task 状态与代码不一致只更新代码忘记更新 tasks.md 勾选状态在 CI 中校验变更目录要求任务完成后再合并代码最后说两句实在话OpenSpec 这套目录结构单独看每个文件都不复杂但组合起来它实际上把一个团队最宝贵的“共识”给结构化了。规范不再存在于某个人的脑子里或者某篇没人看的文档里而是变成了仓库里实实在在的文件人和 AI 都能读、都能改、都能追踪。我在实际使用中最深的体会是这套体系真正起作用的前提是目录干净、文件职责清晰。一旦某个人开始随手放文件、随便命名整个结构很快就会被侵蚀AI 的输出质量也会跟着下降。最后分享一个小技巧如果你刚接触 OpenSpec不用急着把历史文档一次性迁移过来。先在 openspec/ 下建好骨架从当前正在推进的一个小需求开始写第一个 change走完一遍从创建到归档的流程。跑通一次全流程你对这套目录结构的理解会比看任何文档都深刻。
返回列表