OpenSpec:可编程AI编程操作系统与契约驱动开发范式
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 语法,而在于你能否把模糊的业务需求,精准地翻译成三类契约:
- 输入契约(Input Contract) :用 JSON Schema 定义“什么数据能进来”。比如设计稿解析 Skill 要求输入必须是 Figma REST API v2 返回的
GET /v2/files/{file_key}/nodes响应体,且nodes.*.type只能是BUTTON、TEXT、FRAME。这比写“请分析设计稿”这样的 prompt 可控一万倍。 - 行为契约(Behavior Contract) :用 YAML 配置定义“AI 应该怎么做”。比如规定“生成 Vue 组件时,props 必须用
defineProps显式声明,禁止any类型,事件名必须用onXxx命名规范”。这不是风格指南,而是编译期强制校验规则。 - 输出契约(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,我们做了三件事:
- 定义业务 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" } }
}
}
}
}
- 开发业务翻译 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)});
}
`;
}
- 让业务方直接编辑 JSON :我们给业务方一个简单的 Web 表单(基于 JSON Schema 生成),他们只需勾选“触发时机”、填写“缺失字段名”、“弹窗文案”,系统自动生成符合
business-requirement.jsonSchema 的 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 的幻觉,只有工程的确定性。
更多推荐



所有评论(0)