前言
探讨了 Spec-Kit 工具在软件开发中的应用。Spec-Kit 通过结构化的方式帮助开发者与 AI 配对,共同构建复杂功能。它包括规范、规划、执行等步骤,支持多种工具,如 Cursor。作者通过实际案例展示了如何使用 Spec-Kit 和 Cursor 来开发一个照片相册组织应用,包括任务生成、依赖关系管理、测试驱动开发(TDD)等环节。今日前端早读课文章由 @Roy Osherove 分享,@飘飘编译。
译文从这开始~~
【第3588期】基于AI的规范驱动开发:使用全新开源工具包快速上手
自从 vibe-coding 流行起来后,代码的 “劣化”(enshitification)以及随意糊弄的东西变得越来越容易产生。我认为像 Spec-Kit 这样的项目正是为了解决这些问题,而且出现得正是时候。
我相信未来我们会看到越来越多类似的 “提示框架”(prompt-framework),例如 socratic coder、Claude Templates、BMAD-METHOD、ai-rulez 等等。
在这些框架里,Spec-Kit 显得尤其有潜力,也设计得非常周到 —— 你可以把它想象成 Kiro 的开源版本,而且支持多种工具。
我觉得官方文案有点太模糊,如果让我来定义,我会这样描述:
一种结构化的方式来构建由 AI 协作的复杂功能:
把你的 AI 编程助手驯化成一个遵循规范的软件设计流程的伙伴,分步骤完成规格说明、规划、应做和不应做的事项,并让整个团队都能重复使用这个流程。
这些步骤本身其实相当直观:
我个人使用的是 Cursor,它的策略大致是这样的:
【第3558期】谁说前端改动看不出影响范围?用 Cursor 找到了隐藏炸弹
- 使用 Cursor Commands,你可以直接在聊天中输入
/specify
和 /plan
(它会在 .cursor/commands/specify.md
和 plan.md
等文件中生成这些命令)。 - 它会生成一个 CONSTITUTION.md 模板文件,作为 Cursor 命令中提示的指导原则。
- 它会创建一个
.specify
目录,用来存放记忆、脚本和模板,供 Cursor(或 Claude 等)中的智能代理功能使用。这样多个开发者可以共享上下文和工作流。本质上,这里面包含了规则、状态和工具,确保在使用上述命令时,无论是跨会话还是多人协作,都能获得相对一致的体验。
创建一个新功能
你首先从 /specify
开始,然后在操作过程中,智能体会利用命令里的提示来完成一些事情,例如:
在整个流程中,你会感觉它的设计相对成熟。我们都曾在各自的团队里尝试 “重复造轮子”,而现在似乎有了一个(目前算是标准化的,但可能下个月就会改变)较统一的解决方案。
【第3469期】为什么 React 出人意料地成为 LLM 工作流程的最佳模型
当规划阶段完成后,就进入 /tasks
阶段,Cursor 会根据之前的计划生成任务:
在某个阶段,代理卡住或超时了,于是我手动停止,并让它从中断的地方 “继续” 执行 —— 结果运行得很好,这要归功于它的结构所保留的 “记忆”。
任务:相册整理应用
输入:/specs/001-build-an-application/
中的设计文档
前置条件:plan.md
(必需),research.md
,data-model.md
,contracts/
,quickstart.md
执行流程(主线)
1、从功能目录加载 plan.md
- 如果找不到:报错 "No implementation plan found"
2、加载可选设计文档:
- data-model.md:提取实体 → 建模任务
3、按类别生成任务:
4、应用任务规则:
5、按顺序编号任务(T001, T002…)
6、生成依赖关系图
7、创建并行执行示例
8、验证任务完整性:
9、返回:SUCCESS(任务准备就绪)
格式:[ID] [P?] 描述
路径约定
- Web 应用:
backend/src/
,frontend/src/
- 下文路径遵循
plan.md
中的 Web 应用结构
阶段 3.1:初始化
- T001 创建项目结构,包含 backend/ 和 frontend/ 目录
- T002 初始化 Node.js 后端项目,依赖:Express、TypeScript、SQLite
- T003 初始化 React 前端项目,依赖:TypeScript、@dnd-kit、React
- T004 在
backend/.eslintrc.json
配置 ESLint 和 Prettier - T005 在
frontend/.eslintrc.json
配置 ESLint 和 Prettier - T006 在
backend/jest.config.js
设置 Jest 测试框架 - T007 在
frontend/jest.config.js
设置 Jest 和 React Testing Library - T008 在
tests/e2e/playwright.config.ts
配置 Playwright 端到端测试
阶段 3.2:测试优先(TDD)⚠️ 必须在 3.3 之前完成
重要:在做任何实际操作之前,必须先把这些测试写出来,而且一开始测试得是不通过的
合同测试(API 接口)
- T009 GET /albums 接口合同测试 →
tests/contract/test_albums_get.spec.ts
- T010 POST /albums 接口合同测试 →
tests/contract/test_albums_post.spec.ts
- T011 GET /albums/{albumId} 接口合同测试 →
tests/contract/test_albums_get_by_id.spec.ts
- T012 PATCH /albums/{albumId} 接口合同测试 →
tests/contract/test_albums_patch.spec.ts
- T013 POST /albums/reorder 接口合同测试 →
tests/contract/test_albums_reorder.spec.ts
- T014 GET /photos 接口合同测试 →
tests/contract/test_photos_get.spec.ts
- T015 POST /photos 接口合同测试 →
tests/contract/test_photos_post.spec.ts
- T016 GET /photos/{photoId} 接口合同测试 →
tests/contract/test_photos_get_by_id.spec.ts
- T017 DELETE /photos/{photoId} 接口合同测试 →
tests/contract/test_photos_delete.spec.ts
- T018 GET /photos/{photoId}/file 接口合同测试 →
tests/contract/test_photos_file_get.spec.ts
- T019 GET /user/preferences 接口合同测试 →
tests/contract/test_preferences_get.spec.ts
- T020 PATCH /user/preferences 接口合同测试 →
tests/contract/test_preferences_patch.spec.ts
集成测试(用户场景)
- T021 照片上传与自动分组集成测试 →
tests/integration/test_upload_auto_group.spec.ts
- T022 相册拖拽排序集成测试 →
tests/integration/test_album_reorder.spec.ts
- T023 照片缩略图浏览集成测试 →
tests/integration/test_photo_browsing.spec.ts
- T024 无日期照片处理集成测试 →
tests/integration/test_undated_photos.spec.ts
- T025 用户偏好持久化集成测试 →
tests/integration/test_preferences.spec.ts
阶段 3.3:核心实现(仅在测试失败后开始)
数据模型
- T026 照片模型及验证 →
backend/src/models/Photo.ts
- T027 相册模型及验证 →
backend/src/models/Album.ts
- T028 用户偏好模型 →
backend/src/models/UserPreferences.ts
- T029 数据库模式与迁移 →
backend/src/database/schema.sql
- T030 数据库连接设置 →
backend/src/database/connection.ts
核心库(宪法性要求)
- T031 photo-manager 库:EXIF 解析 →
backend/src/lib/photo-manager/exif.ts
- T032 photo-manager 库:缩略图生成 →
backend/src/lib/photo-manager/thumbnails.ts
- T033 photo-manager CLI 接口 →
backend/src/lib/photo-manager/cli.ts
- T034 album-organizer 库:日期分组 →
backend/src/lib/album-organizer/grouping.ts
- T035 album-organizer 库:拖拽排序持久化 →
backend/src/lib/album-organizer/reorder.ts
- T036 album-organizer CLI 接口 →
backend/src/lib/album-organizer/cli.ts
- T037 file-handler 库:上传处理 →
backend/src/lib/file-handler/upload.ts
- T038 file-handler 库:存储管理 →
backend/src/lib/file-handler/storage.ts
- T039 file-handler CLI 接口 →
backend/src/lib/file-handler/cli.ts
服务层
- T040 PhotoService CRUD →
backend/src/services/PhotoService.ts
- T041 AlbumService CRUD 和排序 →
backend/src/services/AlbumService.ts
- T042 UserPreferencesService →
backend/src/services/UserPreferencesService.ts
- T043 FileProcessingService →
backend/src/services/FileProcessingService.ts
API 接口实现
- T044 GET /albums →
backend/src/routes/albums.ts
- T045 POST /albums →
backend/src/routes/albums.ts
- T046 GET /albums/{albumId} →
backend/src/routes/albums.ts
- T047 PATCH /albums/{albumId} →
backend/src/routes/albums.ts
- T048 POST /albums/reorder →
backend/src/routes/albums.ts
- T049 GET /photos →
backend/src/routes/photos.ts
- T050 POST /photos(含文件上传)→
backend/src/routes/photos.ts
- T051 GET /photos/{photoId} →
backend/src/routes/photos.ts
- T052 DELETE /photos/{photoId} →
backend/src/routes/photos.ts
- T053 GET /photos/{photoId}/file →
backend/src/routes/photos.ts
- T054 GET /user/preferences →
backend/src/routes/preferences.ts
- T055 PATCH /user/preferences →
backend/src/routes/preferences.ts
前端组件
- T056 相册网格组件(含拖拽)→
frontend/src/components/AlbumGrid.tsx
- T057 相册卡片组件(含预览)→
frontend/src/components/AlbumCard.tsx
- T058 照片缩略图组件 →
frontend/src/components/PhotoTile.tsx
- T059 照片网格组件(虚拟滚动)→
frontend/src/components/PhotoGrid.tsx
- T060 上传组件(含文件处理)→
frontend/src/components/Upload.tsx
- T061 设置 / 偏好组件 →
frontend/src/components/Settings.tsx
- T062 主页面布局 →
frontend/src/pages/MainPage.tsx
- T063 相册详情页 →
frontend/src/pages/AlbumPage.tsx
- T064 API 服务层 →
frontend/src/services/api.ts
- T065 状态管理(Context)→
frontend/src/context/AppContext.tsx
阶段 3.4:集成
- T066 将服务与数据库连接 →
backend/src/services/
- T067 文件上传中间件配置 →
backend/src/middleware/upload.ts
- T068 错误处理中间件 →
backend/src/middleware/error.ts
- T069 使用 Winston 的日志中间件 →
backend/src/middleware/logging.ts
- T070 CORS 与安全头配置 →
backend/src/middleware/security.ts
- T071 前端 API 集成 →
frontend/src/services/
- T072 前端 Service Worker 缩略图缓存 →
frontend/public/sw.js
阶段 3.5:打磨
- T073 EXIF 解析单元测试 →
tests/unit/photo-manager/test_exif.spec.ts
- T074 缩略图生成单元测试 →
tests/unit/photo-manager/test_thumbnails.spec.ts
- T075 日期分组单元测试 →
tests/unit/album-organizer/test_grouping.spec.ts
- T076 拖拽排序逻辑单元测试 →
tests/unit/album-organizer/test_reorder.spec.ts
- T077 文件处理单元测试 →
tests/unit/file-handler/test_upload.spec.ts
- T078 前端组件单元测试 →
frontend/src/components/__tests__/
- T079 大型照片集性能测试 →
tests/performance/test_large_collection.spec.ts
- T080 端到端用户全流程测试 →
tests/e2e/test_user_workflows.spec.ts
- T082 从 OpenAPI 规范生成 API 文档
- T084 执行
quickstart.md
验证场景
依赖关系
关键依赖(阻塞型):
- 初始化(T001–T008)必须在所有测试和实现之前完成
- 合同测试(T009–T020)必须在对应的接口实现(T044–T055)之前完成
- 模型(T026–T030)必须在服务(T040–T043)之前完成
- 库(T031–T039)必须在服务(T040–T043)之前完成
- 服务(T040–T043)必须在接口实现(T044–T055)之前完成
- API 接口(T044–T055)必须在前端集成(T071)之前完成
具体阻塞关系:
- T026–T028 阻塞 T040–T043(模型 → 服务)
- T031–T039 阻塞 T040–T043(库 → 服务)
- T040–T043 阻塞 T044–T055(服务 → 接口)
- T044–T055 阻塞 T071(API → 前端集成)
- T066–T070 阻塞 T080(中间件 → E2E 测试)
并行执行示例
初始化阶段(T004–T008)
# 同时执行 T004–T008:
任务: "在 backend/.eslintrc.json 配置 ESLint 和 Prettier"
任务: "在 frontend/.eslintrc.json 配置 ESLint 和 Prettier"
任务: "在 backend/jest.config.js 设置 Jest 配置"
任务: "在 frontend/jest.config.js 设置 Jest 和 React Testing Library"
任务: "在 tests/e2e/playwright.config.ts 配置 Playwright E2E 测试"
合同测试阶段(T009–T020)
# 同时执行 T009–T020(所有文件不同):
任务: "GET /albums 接口合同测试 → tests/contract/test_albums_get.spec.ts"
任务: "POST /albums 接口合同测试 → tests/contract/test_albums_post.spec.ts"
任务: "GET /albums/{albumId} 接口合同测试 → tests/contract/test_albums_get_by_id.spec.ts"
# …(12 个合同测试可全部并行运行)
模型阶段(T026–T030)
# 同时执行 T026–T030:
任务: "照片模型 → backend/src/models/Photo.ts"
任务: "相册模型 → backend/src/models/Album.ts"
任务: "用户偏好模型 → backend/src/models/UserPreferences.ts"
任务: "数据库模式与迁移 → backend/src/database/schema.sql"
任务: "数据库连接设置 → backend/src/database/connection.ts"
库阶段(T031–T039)
# 同时执行 T031–T039(所有库互相独立):
任务: "photo-manager 库:EXIF 解析 → backend/src/lib/photo-manager/exif.ts"
任务: "photo-manager 库:缩略图生成 → backend/src/lib/photo-manager/thumbnails.ts"
任务: "photo-manager CLI 接口 → backend/src/lib/photo-manager/cli.ts"
# …(9 个库任务可全部并行运行)
任务生成规则
1、基于合同(api.yaml):
2、基于数据模型:
- 3 个实体(Photo、Album、UserPreferences)→ 3 个模型任务
3、基于宪法性要求:
- 3 个必备库 → 9 个库任务(每个库 3 个文件
4、基于用户故事(quickstart.md):
5、顺序规则:
- 初始化 → 测试 → 模型 → 库 → 服务 → 接口 → 前端 → 打磨
验证清单
检查点:所有项目均已验证
- [x] 所有合同都有对应测试(T009–T020)
- [x] 所有实体都有对应模型任务(T026–T028)
- [x] 所有测试都在实现之前(阶段 3.2 在 3.3 之前)
- [x] 符合宪法性要求(所有功能都以库 + CLI 接口形式实现)
- [x] TDD 流程被严格执行(红 → 绿 → 重构)
请注意,此文件的前 10% 是给代理的指令,最后部分也是给代理的指令。这种结构在各处都存在,我认为这能让代理的体验更加一致。
【第3508期】FunProxy - 使用 Rust 构建跨平台全链路测试抓包代理工具
我很喜欢这里是通过 测试驱动开发(TDD)- 来确保功能真正能跑通的做法。作为一个在合适场景下非常推崇 TDD 的人,我认为对于需要快速建立连续反馈循环的智能代理来说,TDD 再合适不过了 —— 从最终愿景出发,是一种很好地 “奖励” 代理工作的方式,尤其是在它处理大量代码时。
使用 Grok-code-fast 验证
在此之前,我一直用的是 Claude Sonnet 4,但它并不适合这种规划类的任务。我其实心里很清楚,但还是想试试会发生什么。
现在,既然所有的规划产出已经准备好了,我又换成 grok-code-fast-1m- 对所有的计划和任务做了一次检查,结果如下:
实现审计完成 ✅
我对实现计划和相关文档做了一次全面审计。结果发现,最初的 tasks.md
缺少一些关键的实现引用,这会导致开发者难以找到每个任务的详细规格说明。
发现的主要问题
1、缺少实现参考
- 数据模型:任务没有引用
data-model.md
中的实体定义、验证规则和 SQL 模式 - API 接口:任务没有引用
contracts/api.yaml
中的 OpenAPI 规范以及请求 / 响应结构 - 库:任务没有引用
research.md
中的技术选型(Sharp、ExifReader、@dnd-kit) - 业务逻辑:任务没有引用
data-model.md
中的数据流模式和业务规则 - 性能:任务没有引用
plan.md
中的性能目标,以及 research.md
中的优化策略
2、缺少技术实现任务
- 边界情况:没有任务处理损坏的 EXIF 数据、重复照片或 “未知日期” 的相册
- 错误处理:没有针对
spec.md
中边界情况(如错误日期、大型相册)的任务 - 性能:没有对应性能目标的任务(例如加载时间 <2s,支持 1 万 + 张照片)
3、缺少业务逻辑任务
改进措施
✅ 增强任务引用
每个实现任务现在都包含了明确的文档引用:
- 数据模型 → data-model.md(实体、验证、SQL 模式)
- 库 → research.md(Sharp、ExifReader、@dnd-kit 技术选型)
- 服务 → data-model.md(数据流模式、业务规则)
- API 接口 → contracts/api.yaml(OpenAPI 规范)
- 前端 → research.md(技术选型)+
spec.md
(UI 需求)
✅ 新增缺失任务(17 个)
- 边界情况(T079–T082):损坏 EXIF、重复照片、未知日期、性能
- 强化打磨(T086–T089):文档、验证、宪法合规性
✅ 提升任务细化程度
- 技术引用:提及具体库(Sharp、Multer、@dnd-kit)
- 宪法引用:包含 CLI 要求、库文档、TDD 强制性要求
✅优化依赖关系
- 数据库设置:模型阻塞服务(T026–T030 → T040–T043)
- 边界情况:错误处理阻塞验证(T079–T082 → T089)
- 单元测试:阻塞集成测试(T073–T077 → T083–T085)
更新后的任务总数:89 个
结果
更新后的 tasks.md
提供了完整的实现指导,并关联到所有相关设计文档。每个任务足够具体,开发者可以立刻理解:
审计表明,原始任务列表虽然在结构上合理,但缺少至关重要的 “实现细节引用”,这使得任务对遵循 TDD 和宪法原则的开发者来说不够可操作。
💡我觉得在 Cursor 里用 /commands
, 来做这种流程非常有用。
/commands
允许我们创建一些小型的自定义 “向导”,它们比传统脚本更聪明、更实用。传统脚本必须考虑各种用户错误或不同的决策,而命令式的方式只需要:设定目标、提供工具、定义流程,并告诉代理在不同情况下该怎么做。输入依然是自然语言,而且格式可以非常灵活。
我觉得这种方式非常适合用来做设计流程,至少在目前阶段如此。
开始实现
我继续使用 grok-code-fast-1m 并触发了实现:
它一开始忘了把一些内容加到 .gitignore
,但很快修复了。
大约 8 分钟后(grok 确实很快),我收到了提示消息。
我做了回复。
随着对话上下文接近 70%,我结束了本次会话,重新开启了一个新对话,并让代理从功能文件夹的上下文继续执行。
目前为止一切顺利:
大约 15 分钟后,代理宣布一切运行正常。
启动 后端 的确没问题。
前端出现了一些问题,我最终切换到 Claude Opus 来解决(主要是端口配置错误)。但又出现了新的问题。
后来我想起来可以用 Playwright MCP 工具,于是让 Cursor 用它来测试网站:
结果它生成了一堆 Playwright 测试并运行了。很有用!甚至还测试了文件上传等功能。
我采用了 环境变量 的方式:
经过大约 10 分钟的调整,应用运行正常。
- 它默认没有用数据库(如 sqlite),而是采用了内存存储。
但整体上,这是一个相当不错的 概念验证(POC),几乎可以 “开箱即用”,运行效果还挺好。
最大的好处是,底层文件系统、结构和架构总体都不算糟糕。只是因为我没有认真对待 CONSTITUTION.md
文件,所以本可以做得更好。
我还没在遗留系统里试过,但接下来几天或几周会尝试更多工具和方法,到时候再更新。
总结
我喜欢这个想法,我觉得值得长期保留。我会在遗留系统里试试看。它预示着未来的一种趋势,就像当初 Kiro 想做的事情一样。
优点
- 一种结构化、可重复的方法,可以处理复杂的新功能,并需要 “真实世界” 的架构和规范
- 在提示层面强调 TDD,让代理可以更充分地自我验证
- 结合 Cursor 命令、良好的起始规则和记忆文件夹,能预先解决很多反复沟通的问题
- 为每个规格化的功能创建子文件夹,并放入所需上下文,这种方式很强大
- 可跨多个 AI 协作环境使用(Cursor、Claude Code 等)
缺点
关于本文
译者:@飘飘
作者:@Roy Osherove
原文:https://robotpaper.ai/i-tried-out-github-spec-kit-and-all-i-got-was-this-not-terrible-website/
这期前端早读课
对你有帮助,帮” 赞 “一下,
期待下一期,帮” 在看” 一下。