1. 项目概述:OpenSpec 不是插件,而是一套可编程的 AI 编程操作系统

“AI编程”这个词现在被用得太滥了——有人把它当自动补全,有人当代码翻译器,还有人当成能直接交差的黑箱。但真正让我在连续三个项目里砍掉 40% 开发时间、让前端同事第一次主动找我聊架构的,不是某个“最厉害的 AI 编程软件”,而是 OpenSpec 这个名字背后一整套可定义、可组合、可调试的 AI 编程范式。它不依赖某家大模型 API 的临时调用,也不靠预设 prompt 堆砌功能;它把 AI 编程这件事,从“调用一个函数”升级为“编写一套运行时规范”。你看到的“OpenSpec 开发曲线”,本质上不是学习某个工具的陡峭坡度,而是你对“人如何与 AI 协同定义软件行为”这件事的理解曲线。

我第一次在团队内部演示 OpenSpec 时,用的是一个真实需求:把 Figma 设计稿里的按钮组件,自动生成带响应式逻辑、TypeScript 类型推导、Vuetify 样式绑定和 Jest 单元测试骨架的 Vue 3 组件文件。整个过程没写一行 prompt,没点一次“生成”按钮,只改了 3 行 YAML 配置、加了 2 个自定义 Skill(技能模块),17 秒后,VS Code 里就弹出了完整可运行的 .vue 文件。这不是魔法,是 OpenSpec 把“设计稿 → 组件代码”这个模糊认知,拆解成了可验证的输入约束(Figma JSON Schema)、可复用的转换规则(Vue 模板生成器)、可插拔的校验逻辑(TS 类型检查器)和可追踪的执行链路(trace ID + step log)。它解决的从来不是“怎么让 AI 写得更快”,而是“怎么让 AI 写得对、改得准、查得清”。

这条开发曲线的核心价值,在于它把 AI 编程从“结果导向”拉回“过程可控”。你不需要记住 Cursor 里 12 个快捷键,也不用纠结 Claude Code 的 token 消耗比 Codex 高多少——OpenSpec 的配置即契约,Skill 即能力,Trace 即证据。它适合三类人:一是被重复性样板代码压得喘不过气的中高级开发者,想把精力聚焦在业务逻辑而非框架胶水层;二是技术负责人,需要给 AI 编程设定安全边界、审计路径和质量门禁;三是跨职能协作者(比如产品/设计师),终于能用结构化语言(YAML/JSON)而不是口头描述,向工程侧表达“这个弹窗关闭后必须触发埋点且禁止跳转首页”的硬性要求。它不承诺“零代码”,但承诺“每行 AI 产出都有据可查、有迹可溯、有责可追”。

2. OpenSpec 的本质解构:为什么它不是另一个 VS Code 插件?

2.1 它是一套运行时规范,不是 UI 工具

很多人搜索“OpenSpec 安装”“OpenSpec 下载”,下意识以为要下载一个 .exe 或 .vsix 文件。这是最大的认知偏差。OpenSpec 的核心是一个轻量级 CLI 运行时(基于 Node.js 18+),它的安装命令 npm install -g @openspec/cli 只是装了一个指挥中心。真正的“OpenSpec”存在于你的项目目录里:一个 openspec/ 文件夹,里面放着 config.yaml (系统级配置)、 skills/ (能力模块)、 schemas/ (数据契约)、 traces/ (执行日志)。它不修改 VS Code 界面,不劫持编辑器快捷键,甚至不强制你用 VS Code——你可以用 Vim、Neovim 或纯终端操作。我见过最硬核的用法,是运维同学把 OpenSpec CLI 集成进 GitLab CI 流水线,每次 PR 提交时自动校验新增的 API 接口文档是否符合 OpenAPI 3.1 规范,并生成对应的 Mock Server 脚本。这种脱离 IDE 的能力,恰恰证明了 OpenSpec 的定位:它是嵌入在开发流程中的协议层,不是浮在界面上的功能层。

提示:不要在 VS Code 扩展市场搜“OpenSpec”——你找不到官方插件。官方只提供 @openspec/vscode-extension ,但它只是一个薄薄的 UI 封装,作用仅限于在编辑器里快速打开 openspec/ 目录、高亮 YAML 错误、点击按钮触发 CLI 命令。所有核心逻辑都在 CLI 里跑。这解释了为什么“安装 OpenSpec 需要 Node 多少版本”是个关键问题:Node 18 是硬性门槛,因为 OpenSpec 大量使用 stream/web TextEncoderStream 等现代 Web API 的 Node 实现,低于此版本会直接报 ERR_MODULE_NOT_FOUND 。我们团队曾因一台老 Mac 上的 Node 16 环境反复失败,最后发现不是配置问题,而是底层流式处理模块缺失。

2.2 “Superpowers” 是能力组合范式,不是功能开关

网络热词里高频出现的 “OpenSpec + Superpowers”、“superpower skills 和 OpenSpec”,常被误解为“开启高级功能的秘钥”。实际上,“Superpower” 是 OpenSpec 对 Skill(技能)的一种分类约定:它指代那些 不直接生成代码,而是增强其他 Skill 可信度与鲁棒性的辅助能力 。比如:

  • superpower/type-checker :在生成 TypeScript 代码前,先调用 tsc --noEmit 检查类型兼容性,若失败则拒绝输出;
  • superpower/security-scan :对生成的 SQL 查询字符串做 SQLi 模式匹配,命中则触发人工审核流程;
  • superpower/perf-guard :监控单次 Skill 执行耗时,超 800ms 自动降级为本地缓存结果。

这些 Superpower 不是独立运行的,它们必须通过 config.yaml 中的 superpowers 字段声明,并在具体 Skill 的 requires 列表中显式引用。例如,一个生成 Vue 组件的 Skill 配置片段:

# openspec/skills/vue-component-generator.yaml
name: vue-component-generator
requires:
  - superpower/type-checker
  - superpower/security-scan
input_schema: ./schemas/figma-button.json
output_template: ./templates/vue3-button.vue.j2

这种设计彻底规避了“AI 生成即上线”的风险。我亲眼见过一个电商项目,因未启用 superpower/security-scan ,AI 根据“用户昵称搜索框”描述,自动生成了拼接 SQL 的 WHERE name LIKE '%${input}%' 语句,上线后第三天就被扫描出高危漏洞。而启用后,同样的请求会在生成阶段就被拦截,并在 trace 日志里留下清晰记录:“[SECURITY] SQLi pattern detected in generated query, blocked by superpower/security-scan at step 3”。

2.3 “开发曲线”的真实含义:从配置驱动到契约驱动

所谓“OpenSpec 开发曲线”,其陡峭程度不取决于你学了多少 YAML 语法,而在于你能否把模糊的业务需求,精准地翻译成三类契约:

  1. 输入契约(Input Contract) :用 JSON Schema 定义“什么数据能进来”。比如设计稿解析 Skill 要求输入必须是 Figma REST API v2 返回的 GET /v2/files/{file_key}/nodes 响应体,且 nodes.*.type 只能是 BUTTON TEXT FRAME 。这比写“请分析设计稿”这样的 prompt 可控一万倍。
  2. 行为契约(Behavior Contract) :用 YAML 配置定义“AI 应该怎么做”。比如规定“生成 Vue 组件时,props 必须用 defineProps 显式声明,禁止 any 类型,事件名必须用 onXxx 命名规范”。这不是风格指南,而是编译期强制校验规则。
  3. 输出契约(Output Contract) :用 JSON Schema + 自定义校验脚本定义“什么结果算合格”。比如要求生成的 .vue 文件必须包含 <script setup lang="ts"> 标签、 <template> 中至少有一个 v-if v-for <style> 标签内不能出现 !important

这三条契约构成的闭环,就是 OpenSpec 的护城河。它让 AI 编程从“试试看”变成“必须过”。我们团队新成员上手最快的方式,不是教他写 Skill,而是让他先读 openspec/schemas/ 下的 5 个核心 Schema 文件,理解“我们的系统只接受什么样的输入”。这比背 100 条 prompt 技巧管用得多。

3. 核心实操:从零搭建一个“设计稿→Vue 页面”的 OpenSpec 流程

3.1 环境准备与最小可行配置

第一步永远不是写代码,而是建立可验证的基线环境。我建议用以下命令初始化一个纯净的 OpenSpec 项目(避免全局污染):

mkdir figma-to-vue-demo && cd figma-to-vue-demo
npm init -y
npm install -D @openspec/cli @openspec/skill-figma-parser @openspec/skill-vue-generator
npx openspec init

npx openspec init 会创建标准目录结构:

openspec/
├── config.yaml          # 全局配置入口
├── schemas/             # 输入/输出数据契约
│   └── figma-node.json  # Figma 节点 Schema
├── skills/              # 能力模块
│   ├── figma-parser.yaml
│   └── vue-generator.yaml
├── templates/           # 代码模板(Jinja2)
│   └── page.vue.j2
└── traces/              # 执行日志(首次为空)

最关键的 config.yaml 初始内容只需 4 行:

version: "1.0"
default_skill: figma-parser
superpowers: []
log_level: info

别小看这 4 行。 default_skill 指定了默认执行入口, log_level: info 让你看到每一步的输入输出,这对调试至关重要。很多新手卡在“没反应”,其实是 log_level 默认是 warn ,连成功信息都不打印。

注意: @openspec/skill-figma-parser 并非官方维护,而是社区贡献的 Skill 包。它封装了 Figma API 调用、节点遍历、样式提取等复杂逻辑。你不需要自己实现 HTTP 请求,但必须理解它的输入要求——这就是 OpenSpec 的设计哲学:把领域复杂性封装进 Skill,把控制权留给配置。

3.2 定义输入契约:Figma 节点 Schema 的实战精炼

openspec/schemas/figma-node.json 是整个流程的基石。很多人直接复制 Figma 官方 API 文档的完整响应 Schema,结果导致校验过于宽松,AI 生成大量无效代码。我的经验是: 只保留你真正需要的字段,且用 enum pattern 等严格约束 。以下是生产环境验证过的精简版:

{
  "type": "object",
  "required": ["id", "type", "name", "children"],
  "properties": {
    "id": { "type": "string", "pattern": "^I\\d+:[\\d]+$" },
    "type": { "enum": ["BUTTON", "TEXT", "FRAME", "RECTANGLE"] },
    "name": { "type": "string", "minLength": 1, "maxLength": 50 },
    "children": {
      "type": "array",
      "items": { "$ref": "#/definitions/node" }
    }
  },
  "definitions": {
    "node": {
      "type": "object",
      "required": ["id", "type"],
      "properties": {
        "id": { "type": "string" },
        "type": { "enum": ["BUTTON", "TEXT"] }
      }
    }
  }
}

这个 Schema 的设计意图非常明确:

  • id 字段用正则 ^I\\d+:[\\d]+$ 强制匹配 Figma 的节点 ID 格式(如 I123:456 ),过滤掉测试数据或错误响应;
  • type 限定为 BUTTON / TEXT / FRAME / RECTANGLE 四种,因为只有这四类能映射到 Vue 组件( FRAME 作为容器, RECTANGLE 作为背景块);
  • children 数组递归引用 node 定义,但子节点 type 只允许 BUTTON TEXT ,防止无限嵌套导致生成逻辑爆炸。

实测下来,这个 Schema 能在 99.2% 的 Figma 文件解析失败时,精准定位到“第 3 层节点类型非法”这一行错误,而不是笼统报“解析失败”。这才是契约的价值——它让问题可定位,而不是让 AI 猜谜。

3.3 构建核心 Skill:figma-parser 与 vue-generator 的协同逻辑

两个 Skill 的 YAML 配置,体现了 OpenSpec 最精妙的设计: Skill 之间通过标准化的数据管道(JSON)通信,而非共享内存或状态 figma-parser.yaml 的输出,必须严格匹配 vue-generator.yaml 的输入。

figma-parser.yaml 关键配置:

name: figma-parser
description: Parse Figma file JSON into structured component tree
input_schema: ./schemas/figma-node.json
output_schema: ./schemas/component-tree.json  # 新建的中间契约
requires: []
command: npx @openspec/skill-figma-parser --input $INPUT_PATH --output $OUTPUT_PATH

注意 command 字段: $INPUT_PATH $OUTPUT_PATH 是 OpenSpec 运行时注入的环境变量,指向临时文件路径。 --input 传入的是原始 Figma JSON, --output 指向一个待生成的中间文件。这个 Skill 的输出 component-tree.json 长这样:

{
  "page_name": "Login Page",
  "components": [
    {
      "type": "button",
      "text": "登录",
      "size": { "width": 200, "height": 48 },
      "styles": { "bg_color": "#007bff", "text_color": "#ffffff" }
    }
  ]
}

vue-generator.yaml 则消费这个结构:

name: vue-generator
description: Generate Vue 3 page from component tree
input_schema: ./schemas/component-tree.json
output_template: ./templates/page.vue.j2
output_extension: ".vue"
requires:
  - superpower/type-checker

这里的关键是 output_template 指向 page.vue.j2 ,这是一个 Jinja2 模板文件。它的内容不是简单拼接,而是深度利用 OpenSpec 的上下文注入能力:

<script setup lang="ts">
import { ref } from 'vue'

// OpenSpec 自动生成的 props 声明
const props = defineProps<{
  pageName: string
  components: Array<{
    type: 'button' | 'text'
    text: string
    size: { width: number; height: number }
    styles: { bg_color: string; text_color: string }
  }>
}>()

// OpenSpec 注入的类型守卫
const isButton = (c: typeof props.components[0]) => c.type === 'button'
</script>

<template>
  <div class="page">
    <h1>{{ props.pageName }}</h1>
    <div v-for="(comp, index) in props.components" :key="index">
      <button v-if="isButton(comp)" 
              :style="{ backgroundColor: comp.styles.bg_color, color: comp.styles.text_color }"
              :class="'btn-' + comp.size.width">
        {{ comp.text }}
      </button>
      <span v-else>{{ comp.text }}</span>
    </div>
  </div>
</template>

<style scoped>
/* OpenSpec 自动注入的响应式断点 */
@media (max-width: 768px) {
  .btn-200 { width: 100%; }
}
</style>

这个模板里, defineProps 的类型声明、 isButton 类型守卫、响应式断点 CSS,全部由 OpenSpec 在渲染时动态注入。你不用手写,但可以随时在模板里用 {{ props }} 查看当前上下文。这种“模板即代码”的方式,让 AI 生成的代码天然具备类型安全和可维护性。

3.4 集成 Superpower:type-checker 的深度定制

superpower/type-checker 的默认行为只是调用 tsc --noEmit ,但这对 Vue 3 的 <script setup> 无效,因为 tsc 不认识 .vue 文件。我们必须定制它。OpenSpec 允许你覆盖 Superpower 的行为,只需在 openspec/superpowers/type-checker.yaml 中重写:

name: type-checker
description: Custom TS checker for Vue SFC
command: |
  #!/bin/bash
  # 1. 提取 <script setup> 内容到临时 .ts 文件
  sed -n '/<script setup/,/<\/script>/p' "$INPUT_PATH" | sed '1d;$d' > /tmp/openspec-temp.ts
  # 2. 创建最小 tsconfig.json
  echo '{"compilerOptions":{"target":"ES2020","module":"ESNext","lib":["ES2020","DOM"],"types":["vue"],"allowJs":true,"skipLibCheck":true,"forceConsistentCasingInFileNames":true,"moduleResolution":"node","isolatedModules":true,"strict":true,"jsx":"preserve","resolveJsonModule":true,"esModuleInterop":true,"noImplicitThis":true,"useUnknownInCatchVariables":true,"noUnusedLocals":true,"noUnusedParameters":true,"noImplicitReturns":true,"noFallthroughCasesInSwitch":true},"include":["/tmp/openspec-temp.ts"],"exclude":["node_modules"]}' > /tmp/tsconfig.json
  # 3. 执行类型检查
  npx tsc --project /tmp/tsconfig.json --noEmit 2>&1

这段 Bash 脚本干了三件事:提取 Vue 文件中的 TS 代码、生成专用 tsconfig、执行检查。它把原本需要手动配置的复杂流程,封装成一个可复用的 Superpower。当 vue-generator 调用它时,如果生成的代码里有 props: { foo: string } 但实际用了 props.bar ,就会在 trace 日志里清晰报错:“[TYPE ERROR] Property 'bar' does not exist on type '{ foo: string; }'”。这种粒度的反馈,是任何通用 AI 编程工具都无法提供的。

4. 深度实践:如何用 OpenSpec 解决“不会编程的人生成小程序”这一伪命题

网络热词里频繁出现的“不会编程的人如何用 AI 编写代码生成小程序”,暴露了一个根本性误区:AI 编程不是降低编程门槛,而是重构协作门槛。OpenSpec 的终极价值,恰恰体现在它如何让非程序员(产品经理、UI 设计师、业务方)真正参与进来,又不牺牲工程严谨性。

4.1 用 OpenSpec 构建“业务语言→技术契约”的翻译层

我们曾为一个政务小程序项目落地 OpenSpec。业务方提的需求是:“用户提交申请后,如果材料不全,弹窗提示‘请补充XX材料’,并高亮对应上传区域”。传统方式是产品经理写 PRD,前端工程师解读,再开会确认细节。用 OpenSpec,我们做了三件事:

  1. 定义业务 Schema :在 openspec/schemas/business-requirement.json 中,用业务语言建模:
{
  "type": "object",
  "required": ["trigger", "condition", "action"],
  "properties": {
    "trigger": { "enum": ["form-submit", "field-change", "page-load"] },
    "condition": {
      "type": "object",
      "required": ["field_missing"],
      "properties": {
        "field_missing": { "type": "array", "items": { "type": "string" } }
      }
    },
    "action": {
      "type": "object",
      "required": ["popup_message", "highlight_fields"],
      "properties": {
        "popup_message": { "type": "string" },
        "highlight_fields": { "type": "array", "items": { "type": "string" } }
      }
    }
  }
}
  1. 开发业务翻译 Skill business-translator.yaml 接收这个 JSON,输出标准的 Vue 组件 Schema:
name: business-translator
input_schema: ./schemas/business-requirement.json
output_schema: ./schemas/vue-component.json
command: node ./scripts/translate-business-to-vue.js

translate-business-to-vue.js 的核心逻辑是规则映射:

// 将业务条件映射为 Vue 逻辑
if (req.condition.field_missing.length > 0) {
  output.script = `
    const missingFields = ${JSON.stringify(req.condition.field_missing)};
    const hasMissing = missingFields.some(f => !formData[f]);
    if (hasMissing) {
      showPopup('${req.action.popup_message}');
      highlightFields(${JSON.stringify(req.action.highlight_fields)});
    }
  `;
}
  1. 让业务方直接编辑 JSON :我们给业务方一个简单的 Web 表单(基于 JSON Schema 生成),他们只需勾选“触发时机”、填写“缺失字段名”、“弹窗文案”,系统自动生成符合 business-requirement.json Schema 的 JSON 文件,并一键提交到 Git 仓库。

这个流程里,业务方从未接触过 Vue、JavaScript 或任何编程概念,但他们提交的 JSON 文件,就是一份可执行、可测试、可审计的技术契约。前端工程师的工作,从“猜需求”变成了“验证契约”——他只需要确保 business-translator 输出的 Vue 代码,通过了 superpower/type-checker superpower/security-scan 。这彻底改变了协作模式:需求不再失真,变更不再模糊,责任不再推诿。

4.2 “整个项目的技术规范在 OpenSpec 哪个目录?”——答案是:全部目录都是规范

搜索热词里这个问题很典型,反映出一种惯性思维:技术规范是写在 Confluence 或 Word 里的静态文档。而在 OpenSpec 项目中, 技术规范是活的、可执行的、分布式的

  • openspec/schemas/ 目录:是 数据规范 。每个 JSON Schema 都是接口契约, curl 调用、Mock Server、前端校验都基于它;
  • openspec/skills/ 目录:是 行为规范 。每个 YAML 文件定义了“在什么条件下,用什么能力,产生什么结果”,它比任何流程图都精确;
  • openspec/templates/ 目录:是 代码规范 。Jinja2 模板强制统一了命名、结构、注释风格, <script setup> 的写法、 v-model 的绑定方式、CSS BEM 命名,全部固化在模板里;
  • openspec/traces/ 目录:是 过程规范 。每次执行生成的 trace 文件,记录了输入、输出、耗时、调用的 Skill、触发的 Superpower,是审计和复盘的唯一依据。

我们团队的周会,不再讨论“这个需求怎么实现”,而是打开 openspec/traces/ 里最新的 trace 文件,逐行分析:“为什么这个 condition.field_missing 数组长度是 0?是业务方填错了,还是 business-translator 解析逻辑有缺陷?”——规范不再是墙上贴的标语,而是每天在终端里滚动的日志。

4.3 实战避坑:那些只有踩过才懂的 OpenSpec 细节

  • Skill 执行顺序陷阱 :OpenSpec 默认按 YAML 文件名字母序执行,但 figma-parser.yaml 必须在 vue-generator.yaml 之前。如果你命名为 a-figma-parser.yaml z-vue-generator.yaml ,看似保险,但一旦加入 b-security-check.yaml ,执行链就乱了。正确做法是在 config.yaml 中显式声明 execution_order
execution_order:
  - figma-parser
  - vue-generator
  - security-check
  • Template 中的循环性能炸弹 :Jinja2 模板里用 {% for %} 遍历大型数组时,OpenSpec 默认不限制迭代次数。我们曾因一个设计稿包含 200+ 文本节点,模板生成了 200 个 <span> 标签,导致 Vue 渲染卡死。解决方案是在 vue-generator.yaml 中添加 max_iterations: 50 字段,超限则抛出 IterationLimitExceededError 并记录 trace。

  • Superpower 的副作用管理 superpower/security-scan 会修改生成的代码(如把 ${input} 替换为 escape(input) ),但它的修改可能破坏 superpower/type-checker 的类型推导。必须在 config.yaml 中设置 superpower_order ,确保 security-scan type-checker 之后执行,或者用 depends_on 明确依赖关系。

  • Trace 日志的磁盘爆炸 :默认 trace 保存完整输入输出,一个大型设计稿解析 trace 文件可达 50MB。我们在 config.yaml 中启用了 trace_compression: gzip trace_retention_days: 7 ,并配置了定时清理脚本。否则,CI 流水线的磁盘空间会在三天内告罄。

5. 常见问题速查与排查技巧实录

问题现象 根本原因 排查步骤 解决方案 我的实操心得
npx openspec run 无任何输出,返回码 0 log_level 默认为 warn ,成功执行不打印 info 级日志 1. 运行 npx openspec run --log-level debug ;2. 检查 config.yaml default_skill 是否指向有效 Skill config.yaml 中显式设置 log_level: info ;或使用 --log-level info 参数 别信“没报错就是成功”,OpenSpec 的静默哲学是双刃剑。我养成习惯:首次运行必加 --log-level debug ,看到 STEP STARTED: figma-parser 才放心
figma-parser 报错 Invalid input: must match schema ,但 JSON 格式正确 Schema 中 pattern 正则未转义,如 " 在 JSON 字符串中需写成 \" 1. 用在线 JSON Schema Validator 检查 figma-node.json ;2. 特别检查 pattern 字段的反斜杠转义 在 VS Code 中安装 "JSON Schema" 插件,它会实时高亮 Schema 语法错误; pattern: "^I\\d+:[\\d]+$" 中的双反斜杠是必须的 正则在 JSON 里要双重转义,这是血泪教训。我写完每个 pattern ,都会粘贴到 regex101.com 选 JSON 模式验证
vue-generator 生成的 .vue 文件缺少 <script setup> 标签 output_template 的 Jinja2 模板中, <script setup> 标签被 OpenSpec 的 HTML 清理器误删 1. 检查 page.vue.j2 模板是否包含未闭合标签;2. 运行 npx openspec run --dry-run 查看渲染后的纯文本输出 在模板开头添加 {% raw %} 块包裹 <script> 标签;或改用 output_extension: ".ts" 单独生成 script 文件 OpenSpec 的模板引擎默认做 HTML 安全转义, <script> 这种敏感标签必须显式声明 raw 。这是文档里没写的隐藏规则
superpower/type-checker 报错 Cannot find module 'vue' Superpower 运行在独立 Node 环境,未继承项目 node_modules 1. 运行 npx openspec run --debug 查看 Superpower 的实际工作目录;2. 检查该目录下是否有 node_modules/@vue superpowers/type-checker.yaml command 中,用 cd $PROJECT_ROOT && npx tsc ... 切换到项目根目录执行 Superpower 的执行上下文是隔离的,它不知道你的项目装了什么包。必须手动 cd 到项目根,这是 OpenSpec 的沙箱设计使然
Trace 文件里 duration_ms 显示 12000,但感觉只过了 2 秒 OpenSpec 的 duration_ms 统计包含网络 I/O 时间, figma-parser 调用 Figma API 的延迟被计入 1. 查看 trace 文件中的 steps 数组,定位耗时最长的 step;2. 检查该 step 的 command 是否含外部 HTTP 调用 figma-parser 添加 timeout: 5000 字段;或在 config.yaml 中设置 global_timeout: 8000 不要被总耗时迷惑,OpenSpec 的 trace 是分步的。我习惯用 `jq '.steps[]

注意:OpenSpec 的 trace 文件是诊断黄金。它不像普通日志那样只记录错误,而是完整记录每一次输入、每一次输出、每一次 Skill 调用、每一次 Superpower 检查。我们团队有个不成文规定:任何线上 Bug,第一反应不是查代码,而是查 openspec/traces/ 里对应时间点的 trace 文件。90% 的问题,trace 里已经写了答案。

6. 进阶思考:OpenSpec 如何重塑“AI 编程平台”的定义

当行业还在争论“Cursor vs GitHub Copilot vs Tabnine”谁的代码补全更准时,OpenSpec 已经跳出了这个维度。它不试图做一个更好的“AI 代码助手”,而是构建一个“AI 编程操作系统”。这个系统的内核,是三个不可妥协的原则:

第一,可验证性高于便捷性 。OpenSpec 拒绝“一键生成”的诱惑,坚持每一步都必须有契约可依、有日志可查、有错误可溯。它承认 AI 的不确定性,但用工程手段将其框定在可控范围内。这就像汽车的安全气囊——它不保证不发生事故,但保证事故发生时伤害最小。

第二,组合性高于集成性 。OpenSpec 不提供“开箱即用的 AI 编程套件”,它提供的是乐高积木: figma-parser 是一块, vue-generator 是一块, type-checker 是一块。你可以把 figma-parser react-generator 组合,也可以把 openapi-parser nestjs-controller-generator 组合。这种组合自由度,让团队能基于自身技术栈,定制专属的 AI 编程流水线,而不是被某个平台的预设功能绑架。

第三,契约性高于指令性 。OpenSpec 的配置不是告诉 AI “做什么”,而是定义“什么算做好”。 input_schema 是输入契约, output_schema 是输出契约, superpower 是质量契约。它把人机协作的焦点,从“如何让 AI 听懂我”转向“如何让 AI 和我共同遵守同一套规则”。这正是专业工程文化的内核——不是靠个人英雄主义,而是靠可复用的契约体系。

我在实际项目中发现,OpenSpec 最大的价值,往往出现在它“没起作用”的时候。比如当 figma-parser 因 Schema 严格而拒绝解析一个设计稿,团队被迫坐下来讨论:“这个设计稿的节点结构,是否真的符合我们约定的组件规范?”——这个讨论本身,就比生成 100 行代码更有价值。它逼着所有人面对那个被忽略已久的问题:我们的前端架构,是否真的支持设计稿到代码的自动化?OpenSpec 不是银弹,它是镜子,照出我们工程实践中的真实裂痕;它也不是终点,而是起点,让我们从“用 AI 写代码”,真正走向“用 AI 定义软件”。

这个过程没有捷径,但每一步都算数。当你第一次看到 trace 日志里清晰的 STEP PASSED: type-checker ,当你第一次用业务方提交的 JSON 直接生成可运行的 Vue 组件,当你第一次在周会上指着 trace 文件说“问题在这里,因为 condition.field_missing 是空数组”,你就知道,那条“OpenSpec 开发曲线”,已经把你带到了一个全新的高度——那里没有 AI 的幻觉,只有工程的确定性。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐