OpenSpec 架构:把 AI 协作从“对话驱动”变成“状态驱动”

OpenSpec 架构

整体架构

可以把它理解成三层:

  • 状态层:仓库目录本身就是状态存储
  • 计算层:schema + dependency graph + validator
  • 交互层:CLI 和 skills,把结构化状态喂给 AI 或人

这套分层很重要,因为它避免了一个常见问题:把“流程”硬编码进 prompt。在 OpenSpec 里,prompt 只是表现层;真正的工作流定义在 schema 中,真正的状态在文件系统里。

OpenSpec 整体架构图(Excalidraw 重绘)

核心对象

OpenSpec 其实有4个核心对象:

  • specs:当前系统行为的 source of truth
  • changes:待合入的变更包
  • schema:工作流定义,决定有哪些 artifact、它们如何依赖
  • archive:变更完成后的历史沉淀

如果第一次使用,你可能会好奇schema是什么?

img.png

在每次变更文件夹中,.openspec.yaml文件中就有 schema字段,默认值为spec-driven。可以在源码中,看到spec-driven定义了产出物(artifacts)的目录、文件名、文件格式、生成Prompt等,以及实施阶段(apply)读取的任务文件和Prompt。 这是OpenSpec预定义的schema,我们也可以自定义schema,对他进行扩展。

img.png

img.png

工作流

如下是OpenSpec默认的工作流,通过schema定义中的requires字段定义依赖关系。

flowchart LR proposal --> specs proposal --> design specs --> tasks design --> tasks tasks --> apply apply --> archive
artifacts:
  - id: proposal
    generates: proposal.md
    requires: []

  - id: specs
    generates: specs/**/*.md
    requires: [proposal]

  - id: design
    generates: design.md
    requires: [proposal]

  - id: tasks
    generates: tasks.md
    requires: [specs, design]
apply:
  requires: [tasks]
  1. 这里的设计哲学:dependency is an enabler, not a gate

也就是说,依赖表示“现在什么是可做的”,而不是“你必须严格按唯一顺序前进”。这和很多传统 spec 流程差异很大:后者把流程建模成 phase,前者把流程建模成 action + dependency。

这是一个非常适合 AI 协作的建模方式,因为真实开发本来就不是线性的。你今天写完 design,明天发现 assumptions 错了,回头改 spec,这很正常。OpenSpec 没有试图消灭这种回流,而是承认它。

  1. 扩展性好。可以很方便的扩展自定义的artifacts

比如,希望添加“test_case”编写环境,只需要按照已有artifacts格式,定义清楚“requires”、“instruction”等信息即可

状态机:blocked / ready / done

以默认schemaspec-driven为例,执行 opsx:propose命令后,artifacts依赖关系如下图:

flowchart TD A[proposal] --> B[specs] A --> C[design] B --> D[tasks] C --> D

那他们是是怎么驱动的呢? OpenSpec 的状态模型定义了 3 个主状态:

stateDiagram-v2 [*] --> ready: 无依赖或依赖已满足 ready --> done: 产出文件存在 [*] --> blocked: 依赖未满足 blocked --> ready: 缺失依赖补齐

一句话,status 决定该不该做。 也就是,specs和design 状态都为done,那么“tasks”才可以执行。从而实现了“状态驱动”。 这里有一个很值得注意的设计选择:OpenSpec 的状态不是“保存在某处”,而是“计算出来的”。这意味着不需要额外的状态存储

这种推导模式,适合轻量状态,也不用考虑状态一致性问题。不太适合复杂的过程型状态,比如,审批流。

动态指令(Prompt)生成:CLI 不是“命令行外壳”,而是 AI 的结构化上下文提供者

在很多工具里,AI 拿到的是一段固定 prompt;但 OpenSpec 的 openspec instructions 做了更有意思的一层:定义标准结构体ArtifactInstructions,根据当前 change 的实时状态,生成一个包含依赖、模板、规则、输出位置的结构化指令包,然后以 JSON 输出给 AI。

如下为源码中Artifact Instructions定义。源码路径:src/core/artifact-graph/instruction-loader.ts

/**
 * Enriched instructions for creating an artifact.
 */
export interface ArtifactInstructions {
    /** Change name */
    changeName: string;
    /** Artifact ID */
    artifactId: string;
    /** Schema name */
    schemaName: string;
    /** Full path to change directory */
    changeDir: string;
    /** Output path pattern (e.g., "proposal.md") */
    outputPath: string;
    /** Artifact description */
    description: string;
    /** Guidance on how to create this artifact (from schema instruction field) */
    instruction: string | undefined;
    /** Project context from config (constraints/background for AI, not to be included in output) */
    context: string | undefined;
    /** Artifact-specific rules from config (constraints for AI, not to be included in output) */
    rules: string[] | undefined;
    /** Template content (structure to follow - this IS the output format) */
    template: string;
    /** Dependencies with completion status and paths */
    dependencies: DependencyInfo[];
    /** Artifacts that become available after completing this one */
    unlocks: string[];
}

定义了几类信息:

  • 当前 artifact 是什么
  • 输出文件应该写到哪里
  • 依赖 artifact 是否已完成
  • 需要先读哪些文件
  • 当前 schema 下的模板内容
  • 项目级 context 和 artifact 级 rules
  • 完成该 artifact 后会解锁哪些下游 artifact

换句话说,OpenSpec 的 CLI 在做的不是“执行命令”,而是在做workflow context serving

这很重要,因为 AI 最怕两件事:

  • 看不到当前状态
  • 看不到当前动作的边界

status + instructions 组合,本质上就是把这两个问题结构化了。

项目特有约束:context 和 rule

context:项目级、全局共享的背景信息,会注入到所有 artifact 的 instructions。适合放所有 artifact 都需要知道的项目事实和长期约束。 当前context限制:

  • 只支持字符串
  • 支持多行
  • 支持特殊字符
  • 最大 50KB
  • 太大会被忽略并报警告

rules:artifact 级、按类型区分的附加规则,只会注入到匹配的 artifact,比如只对 design 或 tasks 生效。

context 和 rules 该怎么分工?一个简单判断方法: 放进 context 的内容 满足下面任一条件,就更适合放 context:

  • 所有 artifact 都应该知道
  • 是稳定的项目事实
  • 是跨阶段都适用的团队约束
  • 更像“项目背景”而不是“这份文档怎么写” 典型内容:
  • 技术栈
  • 目录结构
  • 架构风格
  • 测试/可观测性/安全基线
  • 术语和业务边界
  • 团队通用编码规范

放进 rules 的内容 满足下面任一条件,就更适合放 rules:

  • 只针对某一类 artifact
  • 是输出格式或内容检查点
  • 是“proposal 应该写什么 / design 必须说明什么 / tasks 如何拆” 典型内容:
  • proposal 必须写回滚影响
  • specs 必须用 SHALL/MUST
  • design 必须解释边界与迁移
  • tasks 必须拆到可执行、可验证

OpenSpec是workflow

以 “opsx:propose” 为例。/opsx:propose 负责“编排流程”,依次执行下面的命令:

  1. openspec new change "<name>",创建新的 change
  2. openspec status --change "<name>" --json,计算“下一个生成的 artifact 是谁”?
  3. openspec instructions <artifact-id> --change "<name>" --json,生成 artifact instructions

“opsx:propose” 依次生成4个artifact:proposal、specs、design、tasks

flowchart TD A[proposal] --> B[specs] A --> C[design] B --> D[tasks] C --> D

二、给我们的启示

2.1 把状态外化到仓库,而不是埋在会话里

这是 OpenSpec 最强的一点。

设计解决了什么启示
文件系统承载状态状态可见、可复算、可进入 Git 历史对 AI 工作流来说,外显状态比“更聪明的 prompt”更重要
specs / changes 分离当前事实与待变更解耦,支持并行变更不要让“讨论中的方案”直接污染 source of truth
schema 驱动 artifact graph工作流可定制,不必改代码把流程定义数据化,比把流程写死在代码里更能长期演进
delta spec 合并对 brownfield 修改极友好在存量系统里,差量建模通常比全量建模更实用
CLI 生成结构化 instructions给 AI 明确边界和上下文AI 工具真正需要的不是更多 prompt,而是更好的上下文接口

2.2 “state-first”,而不是“spec-first”

很多人会把 OpenSpec 看成 spec-first 工具,但我觉得更准确的说法是:它是一个 state-first 的 AI 协作框架。

原因很简单:

  • spec 只是 artifact 之一 ,design、tasks、proposal 也都是 artifact
  • 真正驱动流程的不是文档内容本身,而是artifact 之间的依赖关系和当前完成态

这带来一个很实用的启示:

对 AI 协作流程来说,最值钱的不是“把文档写标准”,而是“把下一步动作计算出来”。

一旦系统能稳定回答下面两个问题,协作效率就会明显上升:

  • 我现在处于什么状态?
  • 我下一步最合理的动作是什么?

OpenSpec 的 status / instructions / apply,本质上都在回答这两个问题。

2.3 “迭代”开发,而不是“线性”开发

传统流程工具喜欢 phase gate,因为它好管理;但实际开发中,需求和理解总是在变化,可能需要不断修改设计和实现。

OpenSpec OPSX Workflow :

  • 不强调 phase 强调 action
  • 允许在实现过程中回头改 design / spec / tasks

img.png

例子:需要修改design,并级联更新spec和task,修改对应实现

“由于性能问题,请把我们的分页方案从‘偏移量分页’改为‘游标分页’。请执行以下步骤:1. 更新 design.md; 2. 基于新的设计,同步修改 specs 下的测试用例; 3. 更新 tasks.md,把旧的 API 修改任务替换为新的游标分页任务。”

这是一个非常成熟的 trade-off:

  • 优点:贴近真实开发,尤其适合 agent + 人类的往返协作
  • 缺点:治理更弱,流程纪律更多依赖团队共识,而不是系统强制

这也给团队设计流程一个提醒:

越贴近真实认知过程的流程,往往越不“整齐”;但它通常更高效。

2.4 它把“可扩展性”放在核心层,而不是集成层

系统设计中,像六边形架构、洋葱模型、DDD等,都是将“可扩展性”放在非核心层,通过“Interface”隔离。 OpenSpec 更深一层,它把扩展性放在:

  • 模板可扩展
  • 工作流依赖可扩展
  • artifact 类型可扩展
  • 项目规则可扩展

这比“再适配一个新的外部依赖”有含金量得多。 因为真正昂贵的从来不是接一个新入口,而是让系统核心抽象在新场景下仍成立

三、目前的不足

OpenSpec 的设计方向是对的,但如果站在更严格的工程视角看,它现在也有一些很明显的边界。

3.1 done 的定义过于乐观

当前完成态基本由“产出文件是否存在”决定。

这很优雅,但也很脆弱。因为下面这些情况都会被误判为完成:

  • 文件只是模板骨架,还没填实质内容
  • spec 已经改了,但 tasks 没刷新
  • design 存在,但已经和 proposal 脱节
  • 生成了 tasks.md,但里面没有有效任务

也就是说,OpenSpec 目前更像在追踪artifact existence,而不是 artifact validity / freshness

如果继续演进,我认为最值得补的是一个“脏态”体系,例如:

  • done:存在且通过基础校验
  • stale:上游依赖变化后需要重审
  • invalid:结构存在但不满足 schema / validator

没有这层能力,状态驱动会很容易滑向“文件驱动”。

实际使用中,你也会发先,如果发现代码实现不符合预期,你修改了spec,缺少一种机制同步到task。如果直接改task,task又不能反向更新spec

3.2 依赖图解决了顺序问题,但还没解决“同步失效”问题

当前图模型非常适合表达“谁先于谁”,但不太能表达“谁因为谁变化而失效”。

例如:

  • proposal scope 变了,spec 是否应该自动标记为 stale?
  • spec requirement 改了,tasks 是否需要重新生成?
  • design 改了,apply 阶段是否应该阻塞直到任务同步?

这类问题本质上不是 DAG 的可达性问题,而是变更传播和一致性问题

OpenSpec 现在已经有“dependency as enabler”,下一步更难、也更关键的是“dependency as invalidation source”。

3.3 Delta merge 以 requirement 标题为锚点,足够实用,但不够强壮

OpenSpec 在 archive 时按 requirement block 合并,这是个很好的方向;但它目前主要依赖 requirement header 做匹配。

这会带来几个天然风险:

  • requirement 标题改写后,merge 容易脆弱
  • 大规模编辑时,rename / modify 冲突规则会变复杂
  • 多个变更同时改同一 requirement,冲突解析成本会上升

从工程角度看,这其实意味着它还缺少一个更稳定的逻辑主键,例如 requirement ID。

也就是说,现在的实现更像:

  • 面向人类可读性优化
  • 还没有完全走到面向机器稳定性优化

这是合理的早期 trade-off,但如果要支撑更大规模协作,这一步迟早要补。

3.4 文件系统状态机很轻,但并发与事务语义较弱

文件系统做状态后端的优点很多,但它的短板也很明确:

  • 缺少强事务边界
  • 多人并行编辑时,冲突靠 Git,而不是工作流层解决
  • 很难表达更复杂的审核流、审批流、租约流
  • archive / apply 虽然已经尽量先验证后写入,但仍是多文件操作

所以我会把 OpenSpec 看成一个单仓库、轻协调、Git 友好的工作流系统,而不是一个严肃的流程编排平台。

这不是批评,而是边界判断。

3.5 当前验证更偏“结构正确”,还不够“语义闭环”

OpenSpec 已经有 validator,也有 verify/apply 这类动作,但从整体上看,它现在更擅长检查:

  • 结构是否符合模板
  • delta 是否合法
  • spec 是否能被归档合并

但它还没有真正闭环到:

  • requirement 是否被代码覆盖
  • tasks 是否与实现一致
  • 变更是否满足可测试性与可验证性
  • spec / code / test 三者之间是否能建立稳定 traceability

而这恰恰是下一阶段最值得做的地方。

如果未来能把 requirement、实现、测试、归档历史串成一条可追踪链路,OpenSpec 的价值会从“AI 协作工具”进一步提升成“变更控制基础设施”。

结语

我对 OpenSpec 的整体评价依然很高,它抓住了一个非常正确的方向:

把 AI 协作从“依赖上下文记忆”推进到“依赖可计算状态”。

在我看来,OpenSpec 最有价值的三个架构点是:

  • 把工作流定义从代码里抽成 schema
  • 把协作状态外化到仓库结构里
  • 把 brownfield 变更建模成 delta,而不是全量重写

上一篇从 Vibe Coding 到 SDD:企业级 AI 编程范式的演进与实践

原创声明

本文为博主原创文章,转载请注明出处:https://www.chunshuijiancha.top/posts/llm/xdd/openspec/part-2-architecture/

© 2026 春水煎茶 - 保留所有权利