sdd-skills 1.1.10 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -20,8 +20,7 @@ sdd-skills
20
20
  | Skill | 角色 | 职责 |
21
21
  |-------|------|------|
22
22
  | **sae** | 架构师 | 需求分析、架构设计、技术方案 |
23
- | **backend-engineer** | Golang 后端工程师 | API 设计、数据库、业务逻辑实现 |
24
- | **frontend-engineer** | Vue 前端工程师 | 组件开发、状态管理、用户交互 |
23
+ | **developer** | 研发工程师 | 前后端代码实现(Go后端、Vue/React前端) |
25
24
  | **tester** | 测试工程师 | 单元测试、E2E 测试、质量保障 |
26
25
  | **code-reviewer** | 代码审查专家 | 代码质量、安全审查、规范检查 |
27
26
  | **git-engineer** | Git 工程师 | 预检测、提交规范、MR 创建 |
@@ -34,8 +33,7 @@ sdd-skills
34
33
 
35
34
  🗣️ Pre-Execution Review(多角色讨论)
36
35
  ├─ SAE 角度:需求清晰度、架构复杂度
37
- ├─ Backend Engineer 角度:技术可行性、性能评估
38
- ├─ Frontend Engineer 角度:用户体验、组件设计
36
+ ├─ Developer 角度:技术可行性、性能评估
39
37
  ├─ Tester 角度:测试策略、环境需求
40
38
  ├─ Code Reviewer 角度:潜在风险、安全关注
41
39
  └─ Git Engineer 角度:CI/CD 兼容性
@@ -44,17 +42,16 @@ sdd-skills
44
42
 
45
43
  📐 SAE → 需求规格文档
46
44
 
47
- 👨‍💻 Backend Engineer 后端 OpenSpec → 代码实现
48
- 👩‍💻 Frontend Engineer → 前端 OpenSpec → 代码实现
45
+ 👨‍💻 Developer → OpenSpec → 代码实现(后端 + 前端)
49
46
 
50
47
  🧪 Tester → 测试验证
51
- ├─ 失败 → 📢 钉钉通知 → 返回开发
48
+ ├─ 失败 → 📢 钉钉通知 → 返回 Developer 修复
52
49
  └─ 成功 ↓
53
50
  👀 Code Reviewer → 代码审查
54
- ├─ 失败 → 📢 钉钉通知 → 返回开发
51
+ ├─ 失败 → 📢 钉钉通知 → 返回 Developer 修复
55
52
  └─ 成功 ↓
56
53
  🚀 Git Engineer → 预检测 + 提交 + MR
57
- ├─ 失败 → 📢 钉钉通知 → 返回开发
54
+ ├─ 失败 → 📢 钉钉通知 → 返回 Developer 修复
58
55
  └─ 成功 ↓
59
56
  ✅ 完成(等待 MR 批准)
60
57
  ```
@@ -96,7 +93,7 @@ Claude (SAE Skill):
96
93
  - 工作流: user-login
97
94
  - 失败阶段: Tester
98
95
  - 错误信息: 3/10 测试用例失败
99
- - 建议操作: 返回 Backend Engineer 修复
96
+ - 建议操作: 返回 Developer 修复
100
97
 
101
98
  🕐 时间: 2026-01-06 14:30:00
102
99
  ```
@@ -143,14 +140,16 @@ npm unlink -g sdd-skills
143
140
 
144
141
  ## 📚 技术栈说明
145
142
 
146
- ### Backend Engineer Skill
143
+ ### Developer Skill (研发工程师)
144
+
145
+ **后端技术栈**:
147
146
  - **语言**: Go 1.21+
148
147
  - **框架**: Gin / Echo / Fiber
149
148
  - **数据库**: PostgreSQL, MySQL, Redis
150
149
  - **测试**: go test, testify, gomock
151
150
  - **覆盖率要求**: >= 90%
152
151
 
153
- ### Frontend Engineer Skill
152
+ **前端技术栈**:
154
153
  - **框架**: Vue 3 / React 18+ (支持多框架)
155
154
  - **状态管理**: Pinia / Redux Toolkit / Zustand
156
155
  - **构建工具**: Vite
package/install.js CHANGED
@@ -7,7 +7,7 @@
7
7
  * to Claude Code's skills directory.
8
8
  */
9
9
 
10
- import { readFileSync, existsSync, mkdirSync, writeFileSync, cpSync } from 'fs';
10
+ import { readFileSync, existsSync, mkdirSync, writeFileSync, cpSync, rmSync } from 'fs';
11
11
  import { join, dirname } from 'path';
12
12
  import { homedir } from 'os';
13
13
  import { fileURLToPath } from 'url';
@@ -32,6 +32,9 @@ const GLOBAL_SKILLS_DIR = join(homedir(), '.claude', 'skills');
32
32
  const LOCAL_SKILLS_DIR = join(process.cwd(), '.claude', 'skills');
33
33
  const SOURCE_SKILLS_DIR = join(__dirname, 'skills');
34
34
 
35
+ // Deprecated skills to clean up on upgrade
36
+ const DEPRECATED_SKILLS = ['backend-engineer', 'frontend-engineer'];
37
+
35
38
  /**
36
39
  * Display welcome banner
37
40
  */
@@ -133,6 +136,26 @@ async function promptInstallation() {
133
136
  return answers;
134
137
  }
135
138
 
139
+ /**
140
+ * Clean up deprecated skills from previous installations
141
+ */
142
+ function cleanupDeprecatedSkills(targetDir) {
143
+ let removedCount = 0;
144
+ for (const skill of DEPRECATED_SKILLS) {
145
+ const skillDir = join(targetDir, skill);
146
+ if (existsSync(skillDir)) {
147
+ try {
148
+ rmSync(skillDir, { recursive: true });
149
+ console.log(chalk.yellow(` ⚠ Removed deprecated: ${skill}`));
150
+ removedCount++;
151
+ } catch (error) {
152
+ console.log(chalk.red(` ✗ Failed to remove ${skill}: ${error.message}`));
153
+ }
154
+ }
155
+ }
156
+ return removedCount;
157
+ }
158
+
136
159
  /**
137
160
  * Install Skills to target directory
138
161
  */
@@ -145,11 +168,16 @@ function installSkills(targetDir) {
145
168
  console.log(chalk.gray(` Created directory: ${targetDir}`));
146
169
  }
147
170
 
171
+ // Clean up deprecated skills first
172
+ const removedCount = cleanupDeprecatedSkills(targetDir);
173
+ if (removedCount > 0) {
174
+ console.log('');
175
+ }
176
+
148
177
  // Get list of skills
149
178
  const skills = [
150
179
  'sae',
151
- 'backend-engineer',
152
- 'frontend-engineer',
180
+ 'developer',
153
181
  'tester',
154
182
  'code-reviewer',
155
183
  'git-engineer',
@@ -213,7 +241,7 @@ function displaySummary(location) {
213
241
  console.log(chalk.bold.green('\n✨ Installation Complete!\n'));
214
242
  console.log(chalk.bold('📋 Summary:\n'));
215
243
  console.log(` ${chalk.gray('Location:')} ${chalk.cyan(skillsPath)}`);
216
- console.log(` ${chalk.gray('Skills:')} ${chalk.cyan('7')} (SAE, Backend, Frontend, Tester, Reviewer, Git, Notifier)`);
244
+ console.log(` ${chalk.gray('Skills:')} ${chalk.cyan('6')} (SAE, Developer, Tester, Reviewer, Git, Notifier)`);
217
245
 
218
246
  console.log(chalk.bold('\n🚀 Getting Started:\n'));
219
247
  console.log(' 1. Open Claude Code');
@@ -246,7 +274,7 @@ async function install() {
246
274
  console.log(chalk.bold('\n📋 Installation Summary:\n'));
247
275
  console.log(` ${chalk.gray('Location:')} ${chalk.cyan(answers.location === 'global' ? 'Global' : 'Local (Current Project)')}`);
248
276
  console.log(` ${chalk.gray('Install to:')} ${chalk.cyan(targetDir)}`);
249
- console.log(` ${chalk.gray('Skills:')} ${chalk.cyan('7')} (SAE, Backend, Frontend, Tester, Reviewer, Git, Notifier)`);
277
+ console.log(` ${chalk.gray('Skills:')} ${chalk.cyan('6')} (SAE, Developer, Tester, Reviewer, Git, Notifier)`);
250
278
  if (answers.configureDingTalk) {
251
279
  console.log(` ${chalk.gray('DingTalk:')} ${chalk.cyan('Enabled')}`);
252
280
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sdd-skills",
3
- "version": "1.1.10",
3
+ "version": "1.2.0",
4
4
  "description": "Spec-Driven Development Skills for Claude Code - SAE/ADE workflow automation",
5
5
  "type": "module",
6
6
  "main": "install.js",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: code-reviewer
3
- description: 代码审查专家,负责代码质量、安全审查和规范检查。当代码实现完成需要代码审查时激活。检查代码风格、最佳实践、安全漏洞、性能问题,审查不通过时触发钉钉通知。
3
+ description: 代码审查专家,负责代码质量、安全审查、接口一致性和规范检查。当代码实现完成需要代码审查时激活。检查代码风格、最佳实践、安全漏洞、性能问题、前后端接口一致性,审查不通过时触发钉钉通知。
4
4
  ---
5
5
 
6
6
  # Code Reviewer
@@ -163,7 +163,127 @@ const localUserId = ref(props.userId)
163
163
  - 使用白名单而非黑名单
164
164
  - 文件上传有大小和类型限制
165
165
 
166
- #### 3. 性能审查
166
+ #### 3. 接口一致性审查
167
+
168
+ **重要**:当涉及前后端接口、gRPC、WebSocket 等通信时,必须确保接口定义与实际使用完全一致。
169
+
170
+ ✅ **检查点**:
171
+ - [ ] 接口地址(URL/路径)前后端一致
172
+ - [ ] 请求方法(GET/POST/PUT/DELETE)一致
173
+ - [ ] 请求参数名称、类型、必填性一致
174
+ - [ ] 响应字段名称、类型与前端绑定一致
175
+ - [ ] 错误码和错误消息格式一致
176
+ - [ ] 分页参数(page/pageSize/offset/limit)一致
177
+ - [ ] 日期时间格式一致(时间戳 vs ISO 8601)
178
+
179
+ **HTTP API 检查**:
180
+ ```go
181
+ // 后端定义 (Go/Gin)
182
+ type LoginRequest struct {
183
+ Email string `json:"email" binding:"required,email"`
184
+ Password string `json:"password" binding:"required,min=8"`
185
+ }
186
+
187
+ type LoginResponse struct {
188
+ Token string `json:"token"`
189
+ ExpiresAt int64 `json:"expires_at"` // 注意:前端需要使用相同字段名
190
+ User User `json:"user"`
191
+ }
192
+
193
+ // API 路由
194
+ r.POST("/api/v1/auth/login", handler.Login)
195
+ ```
196
+
197
+ ```typescript
198
+ // 前端调用 (Vue/TypeScript)
199
+ interface LoginRequest {
200
+ email: string // ✅ 与后端一致
201
+ password: string // ✅ 与后端一致
202
+ }
203
+
204
+ interface LoginResponse {
205
+ token: string
206
+ expires_at: number // ✅ 与后端一致(注意下划线命名)
207
+ user: User
208
+ }
209
+
210
+ // API 调用
211
+ const response = await axios.post<LoginResponse>(
212
+ '/api/v1/auth/login', // ✅ 路径与后端一致
213
+ loginRequest
214
+ )
215
+
216
+ // 页面绑定
217
+ const token = ref(response.data.token) // ✅ 字段名一致
218
+ const expiresAt = ref(response.data.expires_at) // ✅ 字段名一致
219
+ ```
220
+
221
+ ❌ **常见问题**:
222
+
223
+ ```typescript
224
+ // ❌ 错误:字段名不一致
225
+ interface LoginResponse {
226
+ accessToken: string // 后端是 token
227
+ expiresAt: number // 后端是 expires_at(下划线)
228
+ }
229
+
230
+ // ❌ 错误:路径不一致
231
+ axios.post('/api/auth/login', ...) // 后端是 /api/v1/auth/login
232
+
233
+ // ❌ 错误:参数名不一致
234
+ const params = {
235
+ userName: 'test', // 后端期望 email
236
+ pwd: '123456' // 后端期望 password
237
+ }
238
+ ```
239
+
240
+ **gRPC 检查**:
241
+ ```protobuf
242
+ // proto 定义
243
+ message CreateUserRequest {
244
+ string email = 1;
245
+ string password = 2;
246
+ optional string nickname = 3;
247
+ }
248
+
249
+ message CreateUserResponse {
250
+ int64 user_id = 1;
251
+ string created_at = 2;
252
+ }
253
+ ```
254
+
255
+ ```typescript
256
+ // 前端调用必须与 proto 定义一致
257
+ const request: CreateUserRequest = {
258
+ email: 'test@example.com',
259
+ password: 'password123',
260
+ nickname: 'Test User' // optional 字段
261
+ }
262
+
263
+ // 响应字段绑定
264
+ const userId = ref(response.userId) // ✅ proto: user_id -> camelCase
265
+ const createdAt = ref(response.createdAt) // ✅ proto: created_at -> camelCase
266
+ ```
267
+
268
+ **接口一致性审查清单**:
269
+
270
+ | 检查项 | 后端定义 | 前端使用 | 是否一致 |
271
+ |--------|----------|----------|----------|
272
+ | API 路径 | `/api/v1/users` | `/api/v1/users` | ✅ |
273
+ | 请求方法 | `POST` | `POST` | ✅ |
274
+ | 请求参数 | `email`, `password` | `email`, `password` | ✅ |
275
+ | 响应字段 | `token`, `expires_at` | `token`, `expires_at` | ✅ |
276
+ | 错误格式 | `{code, message}` | `{code, message}` | ✅ |
277
+
278
+ **OpenSpec 交叉验证**:
279
+
280
+ 审查时应对照 OpenSpec 中的接口定义:
281
+ - 后端 OpenSpec: `openspec/changes/[feature]/backend-spec.md`
282
+ - 前端 OpenSpec: `openspec/changes/[feature]/frontend-spec.md`
283
+
284
+ 确保两份规格中定义的接口完全匹配。
285
+
286
+ #### 4. 性能审查
167
287
 
168
288
  **后端性能**:
169
289
  - [ ] 避免 N+1 查询问题
@@ -204,7 +324,7 @@ const HeavyComponent = defineAsyncComponent(() =>
204
324
  </script>
205
325
  ```
206
326
 
207
- #### 4. 可维护性审查
327
+ #### 5. 可维护性审查
208
328
 
209
329
  - [ ] 代码结构清晰,模块划分合理
210
330
  - [ ] 函数/方法职责单一,长度适中(< 50 行)
@@ -273,6 +393,7 @@ npm audit
273
393
  - 审查文件数:15 个
274
394
  - 代码质量:✅ 优秀
275
395
  - 安全检查:✅ 无安全问题
396
+ - 接口一致性:✅ 前后端接口匹配
276
397
  - 性能审查:✅ 无性能隐患
277
398
  - 可维护性:✅ 结构清晰
278
399
 
@@ -280,6 +401,7 @@ npm audit
280
401
  1. 错误处理完善,使用了 context 传递
281
402
  2. 数据库查询使用了预加载,避免 N+1 问题
282
403
  3. 前端组件设计合理,可复用性强
404
+ 4. API 接口定义与前端调用完全一致
283
405
 
284
406
  下一步请 Tester 进行测试验证。
285
407
  ```
@@ -298,16 +420,20 @@ npm audit
298
420
  - 问题:N+1 查询
299
421
  - 修复建议:使用 Preload 预加载关联数据
300
422
 
301
- 3. 【中等】代码质量 (frontend/src/components/UserList.vue:89)
423
+ 3. 【严重】接口不一致 (frontend/src/api/user.ts:23 vs backend/api/user_handler.go:45)
424
+ - 问题:前端使用 `expiresAt`,后端返回 `expires_at`
425
+ - 修复建议:前端字段名改为 `expires_at` 或后端改为 camelCase
426
+
427
+ 4. 【中等】代码质量 (frontend/src/components/UserList.vue:89)
302
428
  - 问题:未定义 Props 类型
303
429
  - 修复建议:使用 TypeScript 接口定义 Props
304
430
 
305
- 4. 【轻微】可维护性 (backend/utils/helper.go:23)
431
+ 5. 【轻微】可维护性 (backend/utils/helper.go:23)
306
432
  - 问题:魔法数字 100
307
433
  - 修复建议:定义为常量 MaxPageSize
308
434
 
309
435
  📊 问题统计:
310
- - 严重问题:2
436
+ - 严重问题:3
311
437
  - 中等问题:1 个
312
438
  - 轻微问题:1 个
313
439
 
@@ -339,6 +465,14 @@ npm audit
339
465
  - [ ] CORS 配置正确
340
466
  - [ ] 敏感信息不泄露(日志、错误消息)
341
467
 
468
+ ## 接口一致性
469
+ - [ ] API 路径与前端调用一致
470
+ - [ ] 请求参数名称与前端一致(注意命名风格:snake_case vs camelCase)
471
+ - [ ] 响应字段名称与前端绑定一致
472
+ - [ ] 错误码和错误消息格式与前端处理一致
473
+ - [ ] 分页参数规范一致(page/pageSize 或 offset/limit)
474
+ - [ ] 日期时间格式一致(时间戳或 ISO 8601)
475
+
342
476
  ## 性能
343
477
  - [ ] 无 N+1 查询问题
344
478
  - [ ] 数据库索引合理
@@ -373,6 +507,14 @@ npm audit
373
507
  - [ ] Token 管理安全(存储、刷新、失效处理)
374
508
  - [ ] 表单输入验证完善
375
509
 
510
+ ## 接口一致性
511
+ - [ ] API 路径与后端路由一致
512
+ - [ ] 请求参数名称与后端一致(注意命名风格转换)
513
+ - [ ] 响应字段绑定与后端返回一致
514
+ - [ ] TypeScript 接口定义与后端结构体一致
515
+ - [ ] 错误处理与后端错误格式匹配
516
+ - [ ] 分页参数与后端规范一致
517
+
376
518
  ## 性能
377
519
  - [ ] 组件懒加载
378
520
  - [ ] 图片懒加载
@@ -404,7 +546,7 @@ npm audit
404
546
  "msgtype": "markdown",
405
547
  "markdown": {
406
548
  "title": "SDD 工作流失败",
407
- "text": "❌ **SDD 代码审查不通过**\n\n- **工作流**: user-login\n- **失败阶段**: Code Reviewer\n- **问题数量**: 严重 2 个,中等 1 个,轻微 1 个\n- **主要问题**:\n - 密码明文存储(严重)\n - N+1 查询问题(严重)\n- **建议操作**: 返回 Backend Engineer 修复\n\n🕐 **时间**: 2026-01-06 15:00:00"
549
+ "text": "❌ **SDD 代码审查不通过**\n\n- **工作流**: user-login\n- **失败阶段**: Code Reviewer\n- **问题数量**: 严重 2 个,中等 1 个,轻微 1 个\n- **主要问题**:\n - 密码明文存储(严重)\n - N+1 查询问题(严重)\n- **建议操作**: 返回 Developer 修复\n\n🕐 **时间**: 2026-01-06 15:00:00"
408
550
  }
409
551
  }
410
552
  ```
@@ -413,10 +555,10 @@ npm audit
413
555
 
414
556
  ## 与其他 Skills 的协作
415
557
 
416
- 1. **上游**: 接收 Backend Engineer 和 Frontend Engineer 的代码实现
558
+ 1. **上游**: 接收 Developer 的代码实现
417
559
  2. **下游**:
418
560
  - 审查通过 → 交给 Tester 进行测试验证
419
- - 审查不通过 → **自动调用** 对应 Engineer 修复 → 重新审查
561
+ - 审查不通过 → **自动调用** Developer 修复 → 重新审查
420
562
  3. **并行**: 无
421
563
 
422
564
  ## 会话管理
@@ -460,6 +602,7 @@ npm audit
460
602
  - frontend/src/views/LoginView.vue
461
603
  - frontend/src/components/LoginForm.vue
462
604
  - frontend/src/stores/authStore.ts
605
+ - frontend/src/api/auth.ts
463
606
 
464
607
  🔍 自动化检查:
465
608
  - golangci-lint:✅ 通过
@@ -467,6 +610,12 @@ npm audit
467
610
  - ESLint:✅ 通过
468
611
  - npm audit:✅ 无安全漏洞
469
612
 
613
+ 🔍 接口一致性检查:
614
+ - 后端 API: POST /api/v1/auth/login
615
+ - 前端调用: POST /api/v1/auth/login ✅
616
+ - 请求参数: email, password ✅
617
+ - 响应字段: ❌ 不一致(见下方详情)
618
+
470
619
  ❌ 代码审查不通过
471
620
 
472
621
  问题详情:
@@ -481,7 +630,22 @@ npm audit
481
630
  user.Password = string(hashedPassword)
482
631
  ```
483
632
 
484
- 2. 【严重】性能问题 (backend/service/user_service.go:45)
633
+ 2. 【严重】接口不一致 (frontend/src/api/auth.ts:15 vs backend/api/auth_handler.go:32)
634
+ ```typescript
635
+ // 前端定义(错误)
636
+ interface LoginResponse {
637
+ accessToken: string // ❌ 后端返回 token
638
+ expiresAt: number // ❌ 后端返回 expires_at
639
+ }
640
+
641
+ // 建议修复
642
+ interface LoginResponse {
643
+ token: string // ✅ 与后端一致
644
+ expires_at: number // ✅ 与后端一致
645
+ }
646
+ ```
647
+
648
+ 3. 【严重】性能问题 (backend/service/user_service.go:45)
485
649
  ```go
486
650
  // 当前代码(N+1 查询)
487
651
  for _, user := range users {
@@ -492,7 +656,7 @@ npm audit
492
656
  db.Preload("Orders").Find(&users)
493
657
  ```
494
658
 
495
- 3. 【中等】类型安全 (frontend/src/components/LoginForm.vue:12)
659
+ 4. 【中等】类型安全 (frontend/src/components/LoginForm.vue:12)
496
660
  ```vue
497
661
  <!-- 当前代码(缺少类型定义) -->
498
662
  <script setup>
@@ -509,21 +673,23 @@ npm audit
509
673
  ```
510
674
 
511
675
  建议操作:
512
- 🔄 自动调用 /backend-engineer 修复密码加密和 N+1 查询问题
513
- 🔄 自动调用 /frontend-engineer 添加 TypeScript 类型定义
676
+ 🔄 自动调用 /developer 修复密码加密和 N+1 查询问题
677
+ 🔄 自动调用 /developer 修复前端接口定义与后端一致
678
+ 🔄 自动调用 /developer 添加 TypeScript 类型定义
514
679
 
515
680
  📢 已发送钉钉通知(审查不通过)
516
681
 
517
- [Backend Engineer 和 Frontend Engineer 修复后重新提交审查]
682
+ [Developer 修复后重新提交审查]
518
683
 
519
684
  重新审查...
520
685
 
521
686
  ✅ 代码审查通过
522
687
 
523
688
  📋 审查统计:
524
- - 审查文件数:6
689
+ - 审查文件数:7
525
690
  - 代码质量:✅ 优秀
526
691
  - 安全检查:✅ 无安全问题
692
+ - 接口一致性:✅ 前后端接口匹配
527
693
  - 性能审查:✅ 无性能隐患
528
694
  - 可维护性:✅ 结构清晰
529
695
 
@@ -531,6 +697,7 @@ npm audit
531
697
  1. 密码使用 bcrypt 加密,安全性强
532
698
  2. 数据库查询优化到位,使用了预加载
533
699
  3. TypeScript 类型定义完整,类型安全
700
+ 4. 前后端接口定义一致,字段名完全匹配
534
701
 
535
702
  下一步请 Tester 进行测试验证。
536
703
  ```