
🚩 2026 年「术哥无界」系列实战文档 X 篇原创计划 第 115 篇,OpenSpec 项目实战「2026」系列第 5 篇
大家好,欢迎来到 术哥无界 | ShugeX | 运维有术。
我是术哥,一名专注于 AI 编程、AI 智能体、Agent Skills、MCP、云原生、AIOps、Milvus 向量数据库的技术实践者与开源布道者!
Talk is cheap, let's explore。无界探索,有术而行。

封面:UI 视觉打磨 + 改 template 让 AI 写出规范任务
说明:本文内容基于 OpenSpec(Fission-AI/OpenSpec)v1.3.1 和 React 19 + TypeScript + Tailwind CSS v4 的实际操作记录整理而成。文中的配置模板和参数建议仅供参考,实际效果请以你的业务数据和环境测试结果为准。如果有实际使用经验,欢迎在评论区分享交流。
第 4 期做了布局骨架。首页有了 Tab 分类导航,5 个工具、4 个分类,点 Tab 切分类,不用再在长列表里滚来滚去。
但页面打开一看——灰白一片。品牌色是 Tailwind 默认蓝(#3B82F6),没有图标,卡片和导航样式单调,没有动效。说好听叫「简洁」,说直白就是「没做完」。
这期做两件事。
第一件:视觉层真正的升级。基于第 3 期搭好的 CSS 变量体系和第 4 期的布局骨架,把配色、组件样式、图标、动效做上去,让页面从「脚手架」变成「产品」。change name: ui-visual-polish。
第二件更重要,也是这期文章的重点。前 4 期的 tasks.md 格式一直有问题——schema instruction 里明明要求用 ### 任务 N:[名称] + 涉及文件 + TDD 五步结构,但 AI 每次生成的都是 ## 1. 任务名称 + - [ ] 1.1 这种格式。改了好几次 instruction,没用。
后来读了 OpenSpec 源码,找到根因:template 的优先级高于 instruction。旧 template 用 ## 1. 格式,LLM 就跟 template 走。这期把 template 改了,今天是第一次验证效果。
完整流程不变:

先看问题。第 1 期到第 4 期的 tasks.md 开头长这样。
第 1 期(project-init):
## 1. 项目脚手架初始化
- [x] 1.1 使用 Vite 初始化 React + TypeScript 项目
命令:`npx create-vite@latest . --template react-ts --yes`
预期:项目文件生成第 2 期(tool-registry):
## 1. 更新 catalog.ts(添加 stage 字段和初始工具数据)
**涉及文件:**
- 修改:`src/tool-registry/catalog.ts`
- [x] **1.1:更新 ToolManifest 接口**第 3 期(ui-redesign):
## 1. 设计系统基础
- [x] 1.1 创建 design-tokens.css 文件第 4 期(layout-restructure):
## 1. Tab 导航组件测试
- [ ] 1.1 编写 Tab 导航组件测试看到了吗?全部都是 ## 1. + - [x] 1.1 格式。4 期文章、4 个不同的 change、几十个任务,没有一次出现 ### 任务 N 的格式。
再来看 instruction 里写了什么。逐字引用 openspec/schemas/with-review/schema.yaml 中 tasks 的 instruction 部分(截取关键段落):
- id: tasks
generates: tasks.md
description: Implementation checklist with trackable tasks
template: tasks.md
instruction: |
创建细粒度的实现计划。每个任务的工作量应在 2-5 分钟之间。
## 任务格式(必须严格遵守)
每个任务必须遵循以下格式:
### 任务 N:[组件名称]
**涉及文件:**
- 新建/修改:exact/path/to/file
- 测试:tests/exact/path/to/test
- [ ] **第 1 步:写失败测试**
- [ ] **第 2 步:运行测试——确认失败**
- [ ] **第 3 步:写最小实现**
- [ ] **第 4 步:运行测试——确认通过**
- [ ] **第 5 步:提交**
## 禁止事项(出现即视为计划不合格)
- 「TBD」「TODO」「implement later」「fill in details」instruction 里写得清清楚楚:### 任务 N:[组件名称],涉及文件列表,TDD 五步。甚至用了「必须严格遵守」这种措辞。
但 AI 一次都没遵守。
第 2 期稍微好一点,出现了「涉及文件」这一行,但标题还是 ## 1.,步骤还是 - [x] 1.1。第 3 期和第 4 期连涉及文件都没有了。
这不是偶然。4 期都是同一个模式,说明不是某次生成时的随机偏差,而是有系统性的原因。
OpenSpec 生成工件时,同时读取两个输入:template(模板文件,在 schemas/with-review/templates/ 目录下)和 instruction(指令文本,在 schema.yaml 的 instruction 字段里)。
LLM 面对这两个输入时的行为模式是:template 提供具体的格式示例,instruction 提供文字描述。当两者格式冲突时,LLM 倾向于跟 template 走。
这个判断来自对 OpenSpec 源码的调研。生成工件时,template 的内容被作为「参考格式」先展示给 LLM,instruction 作为「补充说明」跟在后面。顺序上的差异导致 template 的格式暗示更强——LLM 会把 template 当作「你应该长成这样」的范本,把 instruction 当作「内容上注意这些」的建议。
旧 template 的格式是这样的:
## 1. <!-- Task Group Name -->
- [ ] 1.1 <!-- Step description -->
- [ ] 1.2 <!-- Step description -->AI 看到这个模板,脑子里形成了一个框架:「标题用 ## 1.,步骤用 - [ ] 1.1」。然后 instruction 说「用 ### 任务 N」,但它已经被 template 的格式锚定了,改不过来。
这就像你让一个人照着模板写公文,模板是表格格式的,你在旁边说「请用列表格式」,他大概率还是照着模板写表格。不是因为不听,而是模板的视觉暗示太强了。
既然 instruction 管不了格式,那就改 template。逐字引用改造后的 openspec/schemas/with-review/templates/tasks.md:
### 任务 1:<!-- Task Group Name -->
**涉及文件:**
- 新建/修改:exact/path/to/file
- 测试:tests/exact/path/to/test
- [ ] 1.1 **写失败测试**
``typescript
// test code here
``
- [ ] 1.2 **运行测试——确认失败**
命令:`npx vitest run tests/path/test.ts`
预期:FAIL — <!-- expected error -->
- [ ] 1.3 **写最小实现**
``typescript
// implementation code here
``
- [ ] 1.4 **运行测试——确认通过**
命令:`npx vitest run tests/path/test.ts`
预期:PASS
- [ ] 1.5 **提交**
``bash
git add path/to/files
git commit -m "feat: description"
``
### 任务 2:<!-- Task Group Name -->
**涉及文件:**
- 新建/修改:exact/path/to/file
- 测试:tests/exact/path/to/test
- [ ] 2.1 <!-- Continue with the same pattern -->改动点很明确:
维度 | 旧 template | 新 template |
|---|---|---|
标题格式 |
|
|
涉及文件 | 无 |
|
步骤结构 |
| TDD 五步(写失败测试 → 确认失败 → 写实现 → 确认通过 → 提交) |
代码占位 | 无 | 每步都有代码块或命令行 |
第二个任务 | 同上 | 重复模板结构 |
从 ## 1. 变成 ### 任务 1:,看起来只是标记层级和命名方式的变化,但对 LLM 来说,这个格式改变会产生不同的输出模式。加了「涉及文件」列表,AI 就会习惯性地列出每个任务涉及的文件。加了 TDD 五步结构,AI 就会按这个节奏组织每个任务。
本期 ui-visual-polish change 是改造 template 后的第一次验证。
如果 AI 跟新 template 走了,tasks.md 的格式就会变成 ### 任务 N + 涉及文件 + TDD 五步。如果还是 ## 1. 格式,说明问题不止在 template,需要进一步排查。
顺便说明一下本期开始前的项目状态。
逐字引用 src/theme/tokens.css(第 3 期产出,77 行):
:root {
/* 品牌色板 - 冷色系 */
--color-primary-500: #3B82F6;
--color-primary-600: #2563EB;
--color-primary-700: #1D4ED8;
/* 强调色 - 琥珀色 */
--color-accent-500: #F59E0B;
--color-accent-600: #D97706;
/* 中性色 - 冷灰 */
--color-neutral-50: #F8FAFC;
--color-neutral-200: #E2E8F0;
--color-neutral-500: #64748B;
--color-neutral-900: #0F172A;
/* ... 字体、间距、圆角等 */
}CSS 变量体系有了,但 Home 页面的 ToolCard 组件大量使用 inline style,没有充分复用这些变量。TopNav 也很基础——一个 logo + 一个「首页」链接。配色是 Tailwind 默认蓝,没有品牌辨识度。
这些就是本期视觉升级的起点。
这期有个重要发现:Explore 和 Propose 不是两个独立步骤,而是连续流程。执行 /opsx:explore,多轮对话确认方向后,AI 输出 Design Doc,确认后直接自动创建 change 并生成全部 5 个工件——中间没有单独的 /opsx:propose 步骤。
以下是完整交互过程。
执行 /opsx:explore,AI 先问了一句:
AI:What's on your mind? An idea, a problem, a comparison — or just wander?输入本期需求:
用户:本期做一个 ui-visual-polish 变更。当前页面的 CSS 变量体系已搭好但未充分使用,配色是默认蓝没有辨识度,没有图标系统,卡片和导航样式单调。需要全面升级视觉层——配色、图标、动效,让页面从脚手架变成产品。AI 读了一遍源码,做了一轮 Gap 分析:
AI:{读源码,做 Gap 分析}
现状梳理:
Primary (蓝): 50→700 ← 几乎未使用
Accent (琥珀): 50→600 ← Beta/Planned badge,active tab border
Neutral (冷灰): 50→900 ← 大量使用
Semantic: success/warning/error ← 未使用
Gap 分析:
| 维度 | 现状 | 问题 |
|------|------|------|
| 配色 | 变量定义好了,但只用 neutral | 蓝得很默认,缺乏辨识度 |
| 图标 | 仅有一个 ⏳ emoji | 分类/Tab/卡片均无图标 |
| 动效 | 仅 transition-colors,hover:shadow-md | 没有微交互 |
| 卡片 | 纯 flat border + opacity | 没有层次感 |
| 导航 | border-b-2 amber 作为 active indicator | 与品牌蓝不一致 |
几个思考方向:1. 配色策略 2. 图标系统 3. 动效深度 4. 视觉锚点。你倾向于先攻哪个方向?或者想先聊聊整体的设计语言定位再动手?Gap 分析很准确——变量体系搭好了但几乎没用上,中性灰堆满了整个页面。一口气给 4 个方向都定了:
用户:1. 配色:换掉默认蓝,选一个有辨识度的品牌色。primary 做交互色,accent 保持琥珀做功能区分。具体的色值你来定,不要用 Tailwind 默认蓝。2. 图标:用 Lucide,每个 category 配一个 icon,badge 用小图标辅助(Beta 用 🧪 / Planned 用 📋)。3. 动效:做到中等——卡片 hover scale + shadow + stagger 入场动画,tab 切换加滑动指示器。不需要 page transition。4. Header:保持纯文字,但加一个简洁的 icon 或 logo mark,背景用微渐变提升层次。整体方向:干净、专业、有品牌感,不要花哨。参考 Linear 或 Vercel 的设计风格。AI 又追问了 4 个关键问题:
AI:方向清晰了。再摸几个关键问题:
1. **品牌色定位** — 推荐蓝紫(blue-violet),比纯蓝更有辨识度,比纯紫更稳。你接受吗?
2. **Lucide React 安装了吗?**
3. **背景渐变** — 浅色 header + subtle gradient 还是深色 header?
4. **动效节奏** — 快速连续(30-50ms)还是柔和错落(80-120ms)?用户:1. 蓝紫方向接受,你来定具体色值。2. Lucide 没装,本期 install 进去。3. 浅色 header + subtle gradient,保持整体 light theme 基调。4. 柔和错落 80-120ms,偏产品感。接下来是图标分配和 Badge 方案:
AI:好,我来分配图标,附上理由:
- 文本处理 → Type ← 文字输入/编辑感
- 数据转换 → RefreshCw ← 转换/循环感
- 开发工具 → Code2 ← 开发者身份明确
- 内容创作 → Feather ← 创作、手写感
Badge: Beta → Flask, Planned → ClipboardList。确认这 6 个 icon 分配?用户:确认AI:最后确认——Badge 的 emoji 方案:纯图标 vs 图标+emoji 混搭?用户:纯图标到这里所有细节都定了。AI 输出完整 Design Doc。
AI 输出的 Design Doc 关键内容:
AI:{输出完整 Design Doc}
## UI Visual Polish — Design Doc
### 1. 配色体系
品牌色:蓝紫 (Blue-Violet)
Primary (蓝紫) Accent (琥珀) Semantic
───────────────── ───────────────── ────────
50: #F5F3FF 极浅紫 50: #FFFBEB success: #10B981
100: #EDE9FE 100: #FEF3C7 warning: #F59E0B
200: #DDD6FE 200: #FDE68A error: #EF4444
300: #C4B5FD 300: #FCD34D
400: #A78BFA 400: #FBBF24
500: #8B5CF6 ← 品牌主色 500: #F59E0B
600: #7C3AED ← 深色交互 600: #D97706
700: #6D28D9 ← 强调/hover
语义映射:交互色 primary-500, Beta badge accent-500, Active tab indicator primary-500
### 2. 图标系统
Category Icons: 文本处理→Type, 数据转换→RefreshCw, 开发工具→Code2, 内容创作→Feather
Badge Icons: Beta→Flask(替代🧪), Planned→ClipboardList(替代📋)
### 3. 动效
卡片 Hover: scale 1.02, shadow rgba(139,92,246,0.15), 200ms ease-out
Stagger: fadeInUp 400ms, cubic-bezier(0.22,1,0.36,1), 100ms stagger
Tab 指示器: JS left/width, 250ms cubic-bezier(0.4,0,0.2,1)
### 4. Header
background: linear-gradient(135deg, neutral-50 → primary-50)
标题左侧: Wand2 icon + "shuge AI Toolbox"
### 5. 修改文件清单
tokens.css, index.css, Home.tsx, NotFound.tsx, PlaceholderPage.tsx, package.json
Design Doc 确认吗?可以的话我们开 change 了。确认后,AI 直接自动执行 openspec new change "ui-visual-polish" 并生成全部 5 个工件,没有等用户再去执行什么 propose 命令:
用户:确认AI:{自动执行 openspec new change "ui-visual-polish",生成 5 个工件}
Change `ui-visual-polish` 创建完成。所有 artifacts 位于 `openspec/changes/ui-visual-polish/`:
| Artifact | 说明 |
|----------|------|
| proposal.md | 变更动机 + 影响范围 |
| design.md | 蓝紫色值决策、Lucide 选型、Stagger/Tab 指示器实现方案对比 |
| specs/visual-identity/spec.md | 4 个 capability 的场景定义(配色/图标/动效/Header) |
| review.md | 5 维度审查,重点关注任务粒度和测试覆盖 |
| tasks.md | 9 个任务组,涵盖安装依赖 → 配色 → 4 类图标 → stagger → tab 指示器 → header → NotFound → Placeholder → 提交 |
下一步:运行 `/opsx:apply` 开始实现。这是本期最有价值的观察点。直接看 tasks.md 实际生成的第一个任务组:
### 任务 1:安装 lucide-react + 重建 tokens.css 配色
**涉及文件:**
- 修改:`package.json`
- 修改:`src/theme/tokens.css`
- [ ] 1.1 **安装 lucide-react**
``bash
npm install lucide-react
``
- [ ] 1.2 **更新 package.json 并验证 lockfile**
``bash
cat package.json | grep lucide-react
``
预期:`"lucide-react": "^0.468.0"`(或当前最新版本)
- [ ] 1.3 **重建 tokens.css 的 primary 色板为蓝紫系**
``css
/* 品牌色板 - 蓝紫 (Blue-Violet) */
--color-primary-50: #F5F3FF;
--color-primary-100: #EDE9FE;
--color-primary-200: #DDD6FE;
--color-primary-300: #C4B5FD;
--color-primary-400: #A78BFA;
--color-primary-500: #8B5CF6;
--color-primary-600: #7C3AED;
--color-primary-700: #6D28D9;
``
- [ ] 1.4 **运行测试——确认 CSS 变量正确**
``bash
npx vitest run
``
预期:PASS对比改造前:
## 1. 任务名称
- [x] 1.1 步骤描述
- [x] 1.2 步骤描述结论很清晰:标题从 ## 1. 变成了 ### 任务 1:,涉及文件列表成了标配,每个步骤都有代码块。 改 template 确实生效了。
9 个任务组里 8 个都有涉及文件列表,代码块总共 34 个,是前 4 期的历史高点。
不过也有一个没完全到位的地方:TDD 五步(写失败测试→确认失败→写实现→确认通过→提交)没有严格遵循。实际更接近「改代码 → 运行测试确认没坏」的回归测试模式。review.md 也指出了这个问题,标了 ⚠️ 警告:视觉类任务难以按 TDD 节奏严格拆分。这个观察很重要,后面回顾章节会展开。
执行 /opsx:apply,AI 开始逐任务执行。
AI:Using change: **ui-visual-polish** (schema: with-review). Reading context files...
AI:Implementing: ui-visual-polish (schema: with-review). Progress: 0/33 tasks complete. Working on Task 1/9: 安装 lucide-react + 重建 tokens.css 配色33 个步骤,9 个任务组,AI 一路往下跑。
执行过程中出现了三个有意思的问题,AI 都自行发现并修复了。
插曲 1:Flask 图标不存在,改用 Beaker
Explore 阶段 Design Doc 规划了 Beta badge 用 Flask 图标。但 apply 执行时,AI 发现 lucide-react 里根本没有 Flask 这个组件,自动改用了 Beaker。
规划时选了 Flask,实际发现 lucide-react 没有 Flask,改用了 Beaker——这种规划→执行的偏差在真实项目里很常见。AI 编程助手在执行时的这种自适应能力,是它比纯脚本自动化更有价值的地方。
插曲 2:index.css 内容被意外覆盖
AI:我发现一个问题——我把 index.css 的原有内容(imports)覆盖了。需要补回来。AI 在编辑 index.css 时不小心覆盖了原有 imports 内容,随即自己发现并补回。这种自我修复是 AI 编程助手的常见行为——它会犯错,但也会监控自己的输出并在发现问题时立即修正。
插曲 3:NotFound.tsx 不需要改
AI:NotFound.tsx already uses `var(--color-primary-500)` — no changes needed.tasks.md 任务 7 规划了 NotFound 配色更新。但 apply 时 AI 发现 NotFound.tsx 已经使用了 var(--color-primary-500) CSS 变量——tokens.css 的 primary 色值从 #3B82F6 改为 #8B5CF6 后,404 页面的颜色自动跟随变化,不需要改代码。
这就是使用 CSS 变量的好处:一处修改,全局生效。
另外还有一个 bug 修复:AI 使用了 React.createElement 但没导入 React,测试失败后快速定位并添加了 import React。
AI:## Implementation Complete
**Change:** `ui-visual-polish`
**Schema:** `with-review`
**Progress:** 33/33 tasks complete ✓
### Completed This Session
- Task 1: npm install lucide-react + tokens.css primary 色板重建为蓝紫系
- Task 2: index.css 添加 fadeInUp keyframes + .animate-fadeInUp class
- Task 3: Home.tsx 导入 Lucide 图标 + categoryIcon 映射 + Badge Lucide 图标 + Category 图标
- Task 4: Home.tsx stagger 入场动画 + hover scale/shadow 效果
- Task 5: Home.tsx Tab 滑动指示器 (JS ref + CSS transition)
- Task 6: Home.tsx Header Wand2 icon + 135deg 微渐变
- Task 7: NotFound.tsx 配色确认(已是 primary-500)
- Task 8: PlaceholderPage.tsx ⏳ → Clock icon
- Task 9: 全量测试 PASS + commit
### 发现并解决的问题
- Flask 在 lucide-react 中不存在 → 改用 Beaker
- Tab 指示器高亮从 className border-b-2 改为 style.borderColor(无侵入)
- Active Tab 样式用 inline style 替代 class 注入(避免 CSS 类名测试失效)
### Bug 修复
- React.createElement 未导入 React → 添加 import React
所有 30 个测试全部通过。变更已提交。可以 `/opsx:archive` 归档。不多贴代码,说几个关键变化。
tokens.css:primary 色板从默认蓝换成蓝紫。
/* Before */
--color-primary-500: #3B82F6;
--color-primary-600: #2563EB;
--color-primary-700: #1D4ED8;
/* After */
--color-primary-500: #8B5CF6;
--color-primary-600: #7C3AED;
--color-primary-700: #6D28D9;Home.tsx:从 146 行增加到 210 行,新增了 7 个 Lucide 图标导入、categoryIcons 映射、stagger 入场动画(useEffect + CSS 变量注入)、Tab 滑动指示器(ref + indicator state + resize 监听)、Header 的 Wand2 图标 + 135deg 微渐变背景。Badge 从纯文字变成了图标+文字(Beaker / ClipboardList)。
PlaceholderPage.tsx:⏳ emoji 替换为 <Clock size={16}> 图标。
Apply 后跑了一遍构建:
> shuge-ai-toolbox@0.0.0 build
> tsc -b && vite build
vite v8.0.12 building client environment for production...
✓ 1753 modules transformed.
rendering chunks...
computing gzip size...
dist/index.html 0.46 kB │ gzip: 0.30 kB
dist/assets/index-DfrT9w8n.css 19.57 kB │ gzip: 4.67 kB
dist/assets/index-UZjH-ntc.js 295.01 kB │ gzip: 94.25 kB
✓ built in 306ms一个细节:1753 modules。引入 lucide-react 之前是 31 个模块,引入后暴增到 1753 个——图标库的 tree-shaking 确实在工作,但 lucide-react 的总量还是不小。
再跑测试:
> shuge-ai-toolbox@0.0.0 test
> vitest run
✓ src/router/index.test.tsx (3 tests) 2ms
✓ src/tool-registry/catalog.test.ts (7 tests) 7ms
✓ src/layout/TopNav.test.tsx (3 tests) 31ms
✓ src/layout/Layout.test.tsx (2 tests) 34ms
✓ src/app/views/PlaceholderPage.test.tsx (5 tests) 82ms
✓ src/app/views/Home.test.tsx (10 tests) 205ms
Test Files 6 passed (6)
Tests 30 passed (30)
Start at 11:41:23
Duration 1.15s30 个测试全部通过,说明视觉变更没有破坏任何功能。
视觉变更,截图比代码更有说服力。
首页 Before:

视觉升级前——Tailwind 默认蓝、无图标、灰白色调
首页 After:

视觉升级后——蓝紫品牌色、Lucide 图标、Header 微渐变、Tab 滑动指示器、分类图标
变化很明显:Header 有了 Wand2 图标和蓝紫微渐变背景,Tab 栏有了滑动指示器,每个分类标题前有了 Lucide 图标,卡片有了 hover scale + shadow 效果和 stagger 入场动画,Beta 和 Planned badge 从纯文字变成了图标+文字。
占位页 Before / After:

升级前——⏳ emoji 提示

升级后——Clock 图标替代 emoji
404 页 Before / After:

升级前——默认蓝数字

升级后——品牌色自动跟随 tokens.css 变更(没改一行代码)
404 页这个对比值得多说一句:NotFound.tsx 一行代码都没改,但颜色从默认蓝变成了品牌蓝紫。原因就是它用了 var(--color-primary-500) 这个 CSS 变量,tokens.css 里换了色值,404 页自动跟着变。这就是第 3 期搭 CSS 变量体系时埋下的福利。
执行 /opsx:archive:
AI:Delta specs exist for a new capability (`visual-identity`) — no main spec exists yet. This is a pure ADD, so syncing will create `openspec/specs/visual-identity/spec.md` for the first time.
Sync needed: visual-identity (new) — no main spec exists
→ Will create: openspec/specs/visual-identity/spec.mdAI:## Archive Complete
**Change:** `ui-visual-polish`
**Archived to:** `openspec/changes/archive/2026-05-17-ui-visual-polish/`
**Specs:** Synced to main specs (`openspec/specs/visual-identity/spec.md`)
All artifacts complete. All tasks complete.一个值得记录的点:delta specs 的同步。本期新增了 visual-identity 这个 capability,归档时 OpenSpec 自动检测到主 specs 目录下还没有对应的 spec 文件,于是创建了 openspec/specs/visual-identity/spec.md。这个自动同步省去了手动搬运的麻烦。
另外,第 4 期 archive 报了成功但文件实际没移走。这期归档前特意 ls openspec/changes/ 确认了一下——目录下只剩 archive/,坑已填。
推送环节很简单,自然语言指令触发:
用户:请帮我推送到远程仓库AI:已推送。从 `229e2a0` 到 `423723b`,main 分支已更新。先说结论:template 改造确实解决了格式问题。 标题、涉及文件、步骤描述都变了。
但比预期多了一个发现:TDD 五步的严格执行取决于变更类型。本期是视觉类变更,9 个任务组里没有一个是严格的「写失败测试 → 确认失败 → 写最小实现 → 确认通过 → 提交」循环。实际更接近「改代码 → 跑测试确认没坏」的回归测试模式。review.md 也指出了这一点,标了 ⚠️。
所以更精确的结论是:template 管格式不管颗粒度。 格式是结构性的,可以靠 template 解决——从 ## 1. 变成 ### 任务 N:、加上涉及文件列表、给每个步骤配代码块,这些 template 一改就生效。但颗粒度是内容性的,取决于你改什么——视觉类变更天然难以拆出独立的「失败测试」,而纯逻辑变更(比如第 2 期的工具注册中心)就更适合走 TDD 节奏。
这对前传说过的「2/8 法则」是一个重要补充。改 instruction 占 20% 投入获 80% 质量提升,解决的是内容层面的问题——任务描述更具体了,占位符少了,代码块完整了。但那 80% 的质量提升里可能有结构性缺陷——格式始终不对。改 template 是补上这一块的正确手段。
说得更直白:你在 schema.yaml 里写的 instruction,AI 看了。但它身边的 template 格式暗示更强,AI 跟 template 走了。 这不是 bug,是 LLM 的特性——对具体示例的遵循度高于对文字描述的遵循度。
这个结论不仅适用于 OpenSpec,也适用于任何「prompt + template」模式的 AI 工具。你在设计配置的时候,template 和 instruction 要对齐——你想让 AI 输出什么格式,template 就长什么样。
配色从 Tailwind 默认蓝 #3B82F6 换成了蓝紫 #8B5CF6,辨识度高了不少。图标系统用 Lucide 搭好了,4 个分类各有专属图标,badge 从纯文字变成图标+文字。Header 有了微渐变和 Wand2 图标。Tab 有了滑动指示器。卡片有了 hover scale + shadow + stagger 入场动画。
整体从「脚手架」升级到了有品牌感的「产品」。第 3 期搭的 CSS 变量体系和第 4 期搭的布局骨架,在这期真正发挥了作用——变量体系让换色变成改一行值的事,布局骨架让新增 UI 层不需要动结构。
如果你也在用 OpenSpec,而且发现改了 instruction 但 AI 产出的格式始终没变,检查一下 template。template 文件在 openspec/schemas/<schema-name>/templates/ 目录下,每个工件类型都有一个对应的 .md 文件。改 instruction 管内容,改 template 管格式——这两件事是独立的。
你有没有遇到过类似的情况——改了配置但 AI 就是不听?评论区说说,看看是不是同一个原因。
根据系列规划,第 6 期主题是「工具市场 + 搜索/筛选」。
如果本期 template 改造效果明显,第 6 期会是第二次验证——连续两期都用新 template 生成 tasks.md,看效果是否稳定。一次生效可能是巧合,两次都生效才能说明改 template 是可靠的策略。
视觉层面,本期做完后页面已经从「脚手架」升级到有品牌感的「产品」。第 6 期可以聚焦功能层——给工具列表加上搜索和筛选,让用户不只是按分类浏览,还能按关键词快速找到目标工具。
相关资源
OpenSpec GitHub:https://github.com/shuge-x/shuge-ai-toolbox
好啦,谢谢你观看我的文章,如果喜欢可以点赞转发给需要的朋友,我们下一期再见!敬请期待!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。