openmatrix 0.1.63 → 0.1.65

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.
@@ -202,62 +202,62 @@ class PhaseExecutor {
202
202
  */
203
203
  buildTDDPrompt(task) {
204
204
  const parts = [];
205
- parts.push(`# TDD 阶段 - 先写测试 (Test-First)
206
-
207
- ## 任务信息
208
- - ID: ${task.id}
209
- - 标题: ${task.title}
210
- - 描述: ${task.description}
211
-
212
- ## TDD 目标
213
- 在编写实现代码之前,先编写测试用例。这确保:
214
- 1. 你理解需求
215
- 2. 代码可测试
216
- 3. 有明确的成功标准
217
-
218
- ## 验收标准 → 测试用例
219
- ${task.acceptanceCriteria?.map((c, i) => `${i + 1}. ${c}`).join('\n') || '根据任务描述生成测试用例'}
220
-
221
- ## 测试要求
222
- 1. **覆盖正常流程** - 主要功能路径
223
- 2. **覆盖边界情况** - 空值、极值、特殊字符
224
- 3. **覆盖异常处理** - 错误输入、网络失败
225
- 4. **AAA 模式** - Arrange, Act, Assert
226
-
227
- ## 测试框架
228
- 根据项目选择:
229
- - TypeScript/JavaScript: Vitest, Jest
230
- - Python: pytest
205
+ parts.push(`# TDD 阶段 - 先写测试 (Test-First)
206
+
207
+ ## 任务信息
208
+ - ID: ${task.id}
209
+ - 标题: ${task.title}
210
+ - 描述: ${task.description}
211
+
212
+ ## TDD 目标
213
+ 在编写实现代码之前,先编写测试用例。这确保:
214
+ 1. 你理解需求
215
+ 2. 代码可测试
216
+ 3. 有明确的成功标准
217
+
218
+ ## 验收标准 → 测试用例
219
+ ${task.acceptanceCriteria?.map((c, i) => `${i + 1}. ${c}`).join('\n') || '根据任务描述生成测试用例'}
220
+
221
+ ## 测试要求
222
+ 1. **覆盖正常流程** - 主要功能路径
223
+ 2. **覆盖边界情况** - 空值、极值、特殊字符
224
+ 3. **覆盖异常处理** - 错误输入、网络失败
225
+ 4. **AAA 模式** - Arrange, Act, Assert
226
+
227
+ ## 测试框架
228
+ 根据项目选择:
229
+ - TypeScript/JavaScript: Vitest, Jest
230
+ - Python: pytest
231
231
  - Go: testing package`);
232
232
  // Auto 模式提示 - 不要停下来询问用户
233
233
  if (this.isAutoMode) {
234
- parts.push(`
235
-
236
- ## ⚠️ 全自动执行模式
237
- **重要**: 此任务在全自动模式下执行,必须遵守以下规则:
238
- - **不要停下来询问用户确认** - 直接创建测试文件
239
- - **不要输出"继续..."或等待用户回复** - 完成后直接返回结果
240
- - **不要询问"是否需要..."** - 根据验收标准自动生成测试
241
- - 测试应该失败 (RED 阶段),这是正确的
234
+ parts.push(`
235
+
236
+ ## ⚠️ 全自动执行模式
237
+ **重要**: 此任务在全自动模式下执行,必须遵守以下规则:
238
+ - **不要停下来询问用户确认** - 直接创建测试文件
239
+ - **不要输出"继续..."或等待用户回复** - 完成后直接返回结果
240
+ - **不要询问"是否需要..."** - 根据验收标准自动生成测试
241
+ - 测试应该失败 (RED 阶段),这是正确的
242
242
  - 完成后直接输出结果,不要等待任何确认`);
243
243
  }
244
- parts.push(`
245
-
246
- ## 输出
247
- 1. 创建测试文件 (\`.test.ts\` 或 \`.spec.ts\`)
248
- 2. 测试应该**失败** (因为还没实现)
249
- 3. 输出测试文件路径
250
-
251
- ## 验证
252
- 运行 \`npm test\` 确认测试失败 (这是正确的!)
253
-
254
- ## 输出格式
255
- \`\`\`
256
- TDD_TESTS_CREATED
257
- 测试文件: [路径]
258
- 测试用例数: [数量]
259
- 预期: 全部失败 (RED 阶段)
260
- \`\`\`
244
+ parts.push(`
245
+
246
+ ## 输出
247
+ 1. 创建测试文件 (\`.test.ts\` 或 \`.spec.ts\`)
248
+ 2. 测试应该**失败** (因为还没实现)
249
+ 3. 输出测试文件路径
250
+
251
+ ## 验证
252
+ 运行 \`npm test\` 确认测试失败 (这是正确的!)
253
+
254
+ ## 输出格式
255
+ \`\`\`
256
+ TDD_TESTS_CREATED
257
+ 测试文件: [路径]
258
+ 测试用例数: [数量]
259
+ 预期: 全部失败 (RED 阶段)
260
+ \`\`\`
261
261
  `);
262
262
  return parts.join('\n');
263
263
  }
@@ -299,86 +299,86 @@ TDD_TESTS_CREATED
299
299
  buildDevelopPrompt(task) {
300
300
  const parts = [];
301
301
  const isTDDMode = this.qualityConfig.tdd;
302
- parts.push(`# 开发阶段 (Develop Phase)${isTDDMode ? ' - TDD GREEN 阶段' : ''}
303
-
304
- ## 任务信息
305
- - ID: ${task.id}
306
- - 标题: ${task.title}
307
- - 描述: ${task.description}
308
- - 优先级: ${task.priority}
302
+ parts.push(`# 开发阶段 (Develop Phase)${isTDDMode ? ' - TDD GREEN 阶段' : ''}
303
+
304
+ ## 任务信息
305
+ - ID: ${task.id}
306
+ - 标题: ${task.title}
307
+ - 描述: ${task.description}
308
+ - 优先级: ${task.priority}
309
309
  - 质量级别: ${this.qualityConfig.level}`);
310
310
  // Auto 模式提示 - 不要停下来询问用户
311
311
  if (this.isAutoMode) {
312
- parts.push(`
313
-
314
- ## ⚠️ 全自动执行模式
315
- **重要**: 此任务在全自动模式下执行,必须遵守以下规则:
316
- - **不要停下来询问用户确认** - 直接执行所有操作
317
- - **不要输出"继续..."或等待用户回复** - 完成任务后直接返回结果
318
- - **不要询问"是否需要..."** - 自动做出合理决策
319
- - 如果遇到阻塞问题,记录到 Meeting 并继续执行其他任务
312
+ parts.push(`
313
+
314
+ ## ⚠️ 全自动执行模式
315
+ **重要**: 此任务在全自动模式下执行,必须遵守以下规则:
316
+ - **不要停下来询问用户确认** - 直接执行所有操作
317
+ - **不要输出"继续..."或等待用户回复** - 完成任务后直接返回结果
318
+ - **不要询问"是否需要..."** - 自动做出合理决策
319
+ - 如果遇到阻塞问题,记录到 Meeting 并继续执行其他任务
320
320
  - 完成后直接输出结果,不要等待任何确认`);
321
321
  }
322
322
  // TDD 模式提示
323
323
  if (isTDDMode) {
324
- parts.push(`
325
- ## ⚠️ TDD 模式
326
- 你已经在上一步编写了测试。现在需要:
327
- 1. 编写最小代码使测试通过
328
- 2. 不要过度设计
324
+ parts.push(`
325
+ ## ⚠️ TDD 模式
326
+ 你已经在上一步编写了测试。现在需要:
327
+ 1. 编写最小代码使测试通过
328
+ 2. 不要过度设计
329
329
  3. 测试通过即可 (GREEN 阶段)`);
330
330
  }
331
331
  // 注入用户上下文
332
332
  if (this.userContext.objective) {
333
- parts.push(`
334
- ## 整体目标
333
+ parts.push(`
334
+ ## 整体目标
335
335
  ${this.userContext.objective}`);
336
336
  }
337
337
  if (this.userContext.techStack && this.userContext.techStack.length > 0) {
338
- parts.push(`
339
- ## 技术栈要求
338
+ parts.push(`
339
+ ## 技术栈要求
340
340
  ${this.userContext.techStack.map(t => `- ${t}`).join('\n')}`);
341
341
  }
342
342
  // 注入验收标准
343
343
  if (task.acceptanceCriteria && task.acceptanceCriteria.length > 0) {
344
- parts.push(`
345
- ## 验收标准 (必须全部满足)
344
+ parts.push(`
345
+ ## 验收标准 (必须全部满足)
346
346
  ${task.acceptanceCriteria.map((c, i) => `${i + 1}. [ ] ${c}`).join('\n')}`);
347
347
  }
348
- parts.push(`
349
- ## 开发要求
350
- 1. 根据任务描述编写代码
351
- 2. 遵循项目代码规范
352
- 3. 编写必要的注释
353
- 4. 处理边界情况和错误
354
- 5. 确保代码可编译
355
-
356
- ## 编码规范 (SOLID + Clean Code)
357
- - **S**ingle Responsibility: 每个函数只做一件事
358
- - **O**pen/Closed: 对扩展开放,对修改关闭
359
- - **L**iskov Substitution: 子类可替换父类
360
- - **I**nterface Segregation: 接口要小而专注
361
- - **D**ependency Inversion: 依赖抽象而非具体
362
-
363
- ## 代码质量标准
364
- - 函数长度: < 30 行
365
- - 参数数量: < 4 个
366
- - 嵌套深度: < 3 层
367
- - 圈复杂度: < 10
368
-
369
- ## 输出要求
370
- 完成后,在 \`.openmatrix/tasks/${task.id}/artifacts/\` 目录下创建:
371
- - \`result.md\` - 实现说明
372
- - \`changes.txt\` - 变更文件列表
373
-
374
- ## 完成检查清单
375
- - [ ] 代码可编译
376
- - [ ] 边界情况已处理
377
- - [ ] 错误处理完善
378
- - [ ] 无安全隐患
379
- - [ ] 代码风格一致
380
- - [ ] 验收标准全部满足
381
- ${isTDDMode ? '- [ ] 所有测试通过 (GREEN)' : ''}
348
+ parts.push(`
349
+ ## 开发要求
350
+ 1. 根据任务描述编写代码
351
+ 2. 遵循项目代码规范
352
+ 3. 编写必要的注释
353
+ 4. 处理边界情况和错误
354
+ 5. 确保代码可编译
355
+
356
+ ## 编码规范 (SOLID + Clean Code)
357
+ - **S**ingle Responsibility: 每个函数只做一件事
358
+ - **O**pen/Closed: 对扩展开放,对修改关闭
359
+ - **L**iskov Substitution: 子类可替换父类
360
+ - **I**nterface Segregation: 接口要小而专注
361
+ - **D**ependency Inversion: 依赖抽象而非具体
362
+
363
+ ## 代码质量标准
364
+ - 函数长度: < 30 行
365
+ - 参数数量: < 4 个
366
+ - 嵌套深度: < 3 层
367
+ - 圈复杂度: < 10
368
+
369
+ ## 输出要求
370
+ 完成后,在 \`.openmatrix/tasks/${task.id}/artifacts/\` 目录下创建:
371
+ - \`result.md\` - 实现说明
372
+ - \`changes.txt\` - 变更文件列表
373
+
374
+ ## 完成检查清单
375
+ - [ ] 代码可编译
376
+ - [ ] 边界情况已处理
377
+ - [ ] 错误处理完善
378
+ - [ ] 无安全隐患
379
+ - [ ] 代码风格一致
380
+ - [ ] 验收标准全部满足
381
+ ${isTDDMode ? '- [ ] 所有测试通过 (GREEN)' : ''}
382
382
  `);
383
383
  return parts.join('\n');
384
384
  }
@@ -388,189 +388,208 @@ ${isTDDMode ? '- [ ] 所有测试通过 (GREEN)' : ''}
388
388
  buildVerifyPrompt(task) {
389
389
  const parts = [];
390
390
  const qc = this.qualityConfig;
391
- parts.push(`# 验证阶段 (Verify Phase) - 严格质量门禁
392
-
393
- ## 任务信息
394
- - ID: ${task.id}
395
- - 标题: ${task.title}
396
- - 质量级别: ${qc.level}
397
-
398
- ## 🚨 质量门禁 (Quality Gates)
399
-
400
- | 检查项 | 要求 | 失败后果 |
401
- |--------|------|----------|
402
- | 编译 | 无错误 | ❌ 阻止通过 |
403
- | 测试 | 全部通过 | ❌ 阻止通过 |
404
- | 覆盖率 | >= ${qc.minCoverage}% | ${qc.minCoverage > 0 ? '❌ 阻止通过' : '⚠️ 仅警告'} |
405
- | Lint | ${qc.strictLint ? '无 error' : '无严重 error'} | ${qc.strictLint ? '❌ 阻止通过' : '⚠️ 仅警告'} |
406
- | 安全 | 无高危漏洞 | ${qc.securityScan ? '❌ 阻止通过' : '⏭️ 跳过'} |
407
- | E2E | 全部通过 | ${qc.e2eTests ? '❌ 阻止通过' : '⏭️ 跳过'} |
391
+ parts.push(`# 验证阶段 (Verify Phase) - 严格质量门禁
392
+
393
+ ## 任务信息
394
+ - ID: ${task.id}
395
+ - 标题: ${task.title}
396
+ - 质量级别: ${qc.level}
397
+
398
+ ## 🚨 质量门禁 (Quality Gates)
399
+
400
+ | 检查项 | 要求 | 失败后果 |
401
+ |--------|------|----------|
402
+ | 编译 | 无错误 | ❌ 阻止通过 |
403
+ | 测试 | 全部通过 | ❌ 阻止通过 |
404
+ | 覆盖率 | >= ${qc.minCoverage}% | ${qc.minCoverage > 0 ? '❌ 阻止通过' : '⚠️ 仅警告'} |
405
+ | Lint | ${qc.strictLint ? '无 error' : '无严重 error'} | ${qc.strictLint ? '❌ 阻止通过' : '⚠️ 仅警告'} |
406
+ | 安全 | 无高危漏洞 | ${qc.securityScan ? '❌ 阻止通过' : '⏭️ 跳过'} |
407
+ | E2E | 全部通过 | ${qc.e2eTests ? '❌ 阻止通过' : '⏭️ 跳过'} |
408
408
  | 验收标准 | 全部满足 | ❌ 阻止通过 |`);
409
409
  // Auto 模式提示 - 不要停下来询问用户
410
410
  if (this.isAutoMode) {
411
- parts.push(`
412
-
413
- ## ⚠️ 全自动执行模式
414
- **重要**: 此任务在全自动模式下执行,必须遵守以下规则:
415
- - **不要停下来询问用户确认** - 直接执行所有验证命令
416
- - **不要输出"继续..."或等待用户回复** - 完成验证后直接返回结果
417
- - **不要询问"是否需要..."** - 根据质量门禁配置自动执行
418
- - 如果质量门禁失败,记录失败原因并返回结果
411
+ parts.push(`
412
+
413
+ ## ⚠️ 全自动执行模式
414
+ **重要**: 此任务在全自动模式下执行,必须遵守以下规则:
415
+ - **不要停下来询问用户确认** - 直接执行所有验证命令
416
+ - **不要输出"继续..."或等待用户回复** - 完成验证后直接返回结果
417
+ - **不要询问"是否需要..."** - 根据质量门禁配置自动执行
418
+ - 如果质量门禁失败,记录失败原因并返回结果
419
419
  - 完成后直接输出结果,不要等待任何确认`);
420
420
  }
421
- parts.push(`
422
-
423
- ## 自动化验证命令
424
-
425
- ### 1. 编译检查 (必须通过)
426
- \`\`\`bash
427
- npm run build
428
- \`\`\`
429
- **预期**: 无编译错误
430
- **失败后果**: ❌ VERIFY_FAILED
431
-
432
- ### 2. 测试运行 (必须通过)
433
- \`\`\`bash
434
- npm test
435
- \`\`\`
436
- **预期**: 所有测试通过
437
- **失败后果**: ❌ VERIFY_FAILED
438
-
439
- ### 3. 覆盖率检查
440
- \`\`\`bash
441
- npm test -- --coverage 2>/dev/null || npm run test:coverage 2>/dev/null || echo "Coverage check skipped"
442
- \`\`\`
443
- **最低覆盖率**: ${qc.minCoverage}%
444
- **失败后果**: ${qc.minCoverage > 0 ? '❌ VERIFY_FAILED' : '⚠️ 警告'}
445
-
446
- ### 4. Lint 检查
447
- \`\`\`bash
448
- # 先检查是否有 lint 脚本
449
- npm run lint 2>&1 || echo "EXIT_CODE: $?"
450
- \`\`\`
451
- **重要**: 如果 lint 命令返回非零退出码且有 errors,必须报告为 VERIFY_FAILED。
452
- 如果项目没有 lint 脚本(显示 "missing script"),标记为 ⏭️ Skipped。
453
- **要求**: ${qc.strictLint ? '无 error' : '无严重 error'}
454
- **失败后果**: ${qc.strictLint ? '❌ VERIFY_FAILED' : '⚠️ 警告'}
455
-
456
- ### 5. 安全扫描
457
- ${qc.securityScan ? `\`\`\`bash
458
- npm audit --audit-level=high || echo "Security scan skipped"
459
- \`\`\`
460
- **要求**: 无 high/critical 漏洞
461
- **失败后果**: ❌ VERIFY_FAILED` : '⏭️ 已禁用'}
462
-
463
- ### 6. E2E 测试 (端到端测试)
464
- ${qc.e2eTests ? `\`\`\`bash
465
- # Web 应用: Playwright / Cypress
466
- npx playwright test || npx cypress run
467
-
468
- # 移动端: Appium / Detox
469
- npx appium ... || npx detox test
470
-
471
- # GUI 桌面应用: 根据项目配置
472
- npm run test:e2e
473
- \`\`\`
474
- **要求**: 所有 E2E 测试通过
475
- **失败后果**: ❌ VERIFY_FAILED` : '⏭️ 已禁用'}
476
-
421
+ parts.push(`
422
+
423
+ ## 自动化验证命令
424
+
425
+ ### 1. 编译检查 (必须通过)
426
+ \`\`\`bash
427
+ npm run build
428
+ \`\`\`
429
+ **预期**: 无编译错误
430
+ **失败后果**: ❌ VERIFY_FAILED
431
+
432
+ ### 2. 测试运行 (必须通过)
433
+ \`\`\`bash
434
+ npm test
435
+ \`\`\`
436
+ **预期**: 所有测试通过
437
+ **失败后果**: ❌ VERIFY_FAILED
438
+
439
+ ### 3. 覆盖率检查
440
+ \`\`\`bash
441
+ npm test -- --coverage 2>/dev/null || npm run test:coverage 2>/dev/null || echo "Coverage check skipped"
442
+ \`\`\`
443
+ **最低覆盖率**: ${qc.minCoverage}%
444
+ **失败后果**: ${qc.minCoverage > 0 ? '❌ VERIFY_FAILED' : '⚠️ 警告'}
445
+
446
+ ### 4. Lint 检查
447
+ \`\`\`bash
448
+ # 先检查是否有 lint 脚本
449
+ npm run lint 2>&1 || echo "EXIT_CODE: $?"
450
+ \`\`\`
451
+ **重要**: 如果 lint 命令返回非零退出码且有 errors,必须报告为 VERIFY_FAILED。
452
+ 如果项目没有 lint 脚本(显示 "missing script"),标记为 ⏭️ Skipped。
453
+ **要求**: ${qc.strictLint ? '无 error' : '无严重 error'}
454
+ **失败后果**: ${qc.strictLint ? '❌ VERIFY_FAILED' : '⚠️ 警告'}
455
+
456
+ ### 5. 安全扫描
457
+ ${qc.securityScan ? `\`\`\`bash
458
+ npm audit --audit-level=high || echo "Security scan skipped"
459
+ \`\`\`
460
+ **要求**: 无 high/critical 漏洞
461
+ **失败后果**: ❌ VERIFY_FAILED` : '⏭️ 已禁用'}
462
+
463
+ ### 6. E2E 测试 (端到端测试)
464
+ ${qc.e2eTests ? `\`\`\`bash
465
+ # 首先检查 E2E 测试工具是否可用
466
+ # 不要直接运行测试 - 先检查工具是否存在
467
+
468
+ # 检查 Playwright
469
+ if command -v npx &> /dev/null && npx playwright --version 2>/dev/null; then
470
+ echo "✅ Playwright available"
471
+ npx playwright test
472
+ elif command -v npx &> /dev/null && npx cypress --version 2>/dev/null; then
473
+ echo "✅ Cypress available"
474
+ npx cypress run
475
+ # 检查移动端工具
476
+ elif command -v appium &> /dev/null; then
477
+ echo "✅ Appium available"
478
+ npx appium ...
479
+ elif command -v detox &> /dev/null; then
480
+ echo "✅ Detox available"
481
+ npx detox test
482
+ # 检查项目自定义脚本
483
+ elif npm run | grep -q "test:e2e"; then
484
+ echo "✅ Using project e2e script"
485
+ npm run test:e2e
486
+ else
487
+ echo "⚠️ No E2E test tool found - skipping E2E tests"
488
+ echo "Install Playwright: npm install -D @playwright/test"
489
+ echo "Or Cypress: npm install -D cypress"
490
+ exit 0
491
+ fi
492
+ \`\`\`
493
+ **要求**: 所有 E2E 测试通过(如果工具可用)
494
+ **失败后果**: ❌ VERIFY_FAILED (工具可用但未通过) / ⏭️ Skipped (工具不可用)` : '⏭️ 已禁用'}
495
+
477
496
  ### 7. 验收标准验证`);
478
497
  // 注入验收标准
479
498
  if (task.acceptanceCriteria && task.acceptanceCriteria.length > 0) {
480
- parts.push(`
481
- 逐项检查以下标准:
482
- ${task.acceptanceCriteria.map((c, i) => `${i + 1}. [ ] ${c}`).join('\n')}
499
+ parts.push(`
500
+ 逐项检查以下标准:
501
+ ${task.acceptanceCriteria.map((c, i) => `${i + 1}. [ ] ${c}`).join('\n')}
483
502
  **失败后果**: ❌ VERIFY_FAILED`);
484
503
  }
485
504
  else {
486
- parts.push(`
505
+ parts.push(`
487
506
  ⏭️ 无验收标准定义`);
488
507
  }
489
- parts.push(`
490
-
491
- ## 📊 质量报告格式
492
-
493
- 在 \`.openmatrix/tasks/${task.id}/artifacts/\` 目录下创建 \`quality-report.json\`:
494
-
495
- \`\`\`json
496
- {
497
- "taskId": "${task.id}",
498
- "timestamp": "[ISO时间]",
499
- "tests": {
500
- "passed": 0,
501
- "failed": 0,
502
- "skipped": 0,
503
- "coverage": 0,
504
- "status": "pass|fail"
505
- },
506
- "build": {
507
- "success": true,
508
- "errors": [],
509
- "status": "pass|fail"
510
- },
511
- "lint": {
512
- "errors": 0,
513
- "warnings": 0,
514
- "status": "pass|fail|warning"
515
- },
516
- "security": {
517
- "vulnerabilities": [],
518
- "status": "pass|fail"
519
- },
520
- "e2e": {
521
- "passed": 0,
522
- "failed": 0,
523
- "skipped": 0,
524
- "duration": 0,
525
- "status": "pass|fail|skipped"
526
- },
527
- "acceptance": {
528
- "total": ${task.acceptanceCriteria?.length || 0},
529
- "met": 0,
530
- "details": [],
531
- "status": "pass|fail"
532
- },
533
- "overall": "pass|fail|warning"
534
- }
535
- \`\`\`
536
-
537
- ## 最终输出
538
-
539
- ✅ **所有门禁通过**:
540
- \`\`\`
541
- VERIFY_PASSED
542
- Quality Score: [A/B/C/D/F]
543
- - Tests: ✅ X/X passed, Y% coverage
544
- - Build: ✅ Success
545
- - Lint: ✅ No errors
546
- - Security: ✅ No vulnerabilities
547
- ${qc.e2eTests ? '- E2E: ✅ X/X passed' : ''}
548
- - Acceptance: ✅ N/M criteria met
549
- \`\`\`
550
-
551
- ❌ **门禁失败**:
552
- \`\`\`
553
- VERIFY_FAILED
554
- Failed Gates:
555
- 1. [检查项]: [失败原因]
556
- 2. [检查项]: [失败原因]
557
-
558
- Fix Required:
559
- 1. [修复建议]
560
- 2. [修复建议]
561
- \`\`\`
562
-
563
- ## ⚠️ 重要提示
564
- - **不要跳过任何检查**
565
- - **不要伪造通过结果**
566
- - 如果项目没有某个脚本,标记为 "⏭️ Skipped" 而非 "❌ Failed"
567
- - 所有检查结果必须基于实际命令输出
568
-
569
- ## 🔧 配置检查 (可选但推荐)
570
- 检查以下常见配置问题:
571
- - **Vitest 配置**: 如果存在 \`e2e/\` 目录,确保 \`vite.config.ts\` 的 \`test.exclude\` 包含 \`e2e\`
572
- - **测试框架冲突**: 确保 Vitest 不运行 Playwright/Cypress 测试文件
573
- - 如果发现配置问题,记录到报告中但不要阻止通过
508
+ parts.push(`
509
+
510
+ ## 📊 质量报告格式
511
+
512
+ 在 \`.openmatrix/tasks/${task.id}/artifacts/\` 目录下创建 \`quality-report.json\`:
513
+
514
+ \`\`\`json
515
+ {
516
+ "taskId": "${task.id}",
517
+ "timestamp": "[ISO时间]",
518
+ "tests": {
519
+ "passed": 0,
520
+ "failed": 0,
521
+ "skipped": 0,
522
+ "coverage": 0,
523
+ "status": "pass|fail"
524
+ },
525
+ "build": {
526
+ "success": true,
527
+ "errors": [],
528
+ "status": "pass|fail"
529
+ },
530
+ "lint": {
531
+ "errors": 0,
532
+ "warnings": 0,
533
+ "status": "pass|fail|warning"
534
+ },
535
+ "security": {
536
+ "vulnerabilities": [],
537
+ "status": "pass|fail"
538
+ },
539
+ "e2e": {
540
+ "passed": 0,
541
+ "failed": 0,
542
+ "skipped": 0,
543
+ "duration": 0,
544
+ "status": "pass|fail|skipped"
545
+ },
546
+ "acceptance": {
547
+ "total": ${task.acceptanceCriteria?.length || 0},
548
+ "met": 0,
549
+ "details": [],
550
+ "status": "pass|fail"
551
+ },
552
+ "overall": "pass|fail|warning"
553
+ }
554
+ \`\`\`
555
+
556
+ ## 最终输出
557
+
558
+ ✅ **所有门禁通过**:
559
+ \`\`\`
560
+ VERIFY_PASSED
561
+ Quality Score: [A/B/C/D/F]
562
+ - Tests: ✅ X/X passed, Y% coverage
563
+ - Build: ✅ Success
564
+ - Lint: ✅ No errors
565
+ - Security: ✅ No vulnerabilities
566
+ ${qc.e2eTests ? '- E2E: ✅ X/X passed' : ''}
567
+ - Acceptance: ✅ N/M criteria met
568
+ \`\`\`
569
+
570
+ ❌ **门禁失败**:
571
+ \`\`\`
572
+ VERIFY_FAILED
573
+ Failed Gates:
574
+ 1. [检查项]: [失败原因]
575
+ 2. [检查项]: [失败原因]
576
+
577
+ Fix Required:
578
+ 1. [修复建议]
579
+ 2. [修复建议]
580
+ \`\`\`
581
+
582
+ ## ⚠️ 重要提示
583
+ - **不要跳过任何检查**
584
+ - **不要伪造通过结果**
585
+ - 如果项目没有某个脚本,标记为 "⏭️ Skipped" 而非 "❌ Failed"
586
+ - 所有检查结果必须基于实际命令输出
587
+
588
+ ## 🔧 配置检查 (可选但推荐)
589
+ 检查以下常见配置问题:
590
+ - **Vitest 配置**: 如果存在 \`e2e/\` 目录,确保 \`vite.config.ts\` 的 \`test.exclude\` 包含 \`e2e\`
591
+ - **测试框架冲突**: 确保 Vitest 不运行 Playwright/Cypress 测试文件
592
+ - 如果发现配置问题,记录到报告中但不要阻止通过
574
593
  `);
575
594
  return parts.join('\n');
576
595
  }
@@ -579,76 +598,76 @@ Fix Required:
579
598
  */
580
599
  buildAcceptPrompt(task) {
581
600
  const parts = [];
582
- parts.push(`# 验收阶段 (Accept Phase)
583
-
584
- ## 任务信息
585
- - ID: ${task.id}
586
- - 标题: ${task.title}
601
+ parts.push(`# 验收阶段 (Accept Phase)
602
+
603
+ ## 任务信息
604
+ - ID: ${task.id}
605
+ - 标题: ${task.title}
587
606
  - 描述: ${task.description}`);
588
607
  // Auto 模式提示 - 不要停下来询问用户
589
608
  if (this.isAutoMode) {
590
- parts.push(`
591
-
592
- ## ⚠️ 全自动执行模式
593
- **重要**: 此任务在全自动模式下执行,必须遵守以下规则:
594
- - **不要停下来询问用户确认** - 直接执行所有验收检查
595
- - **不要输出"继续..."或等待用户回复** - 完成验收后直接返回结果
596
- - **不要询问"是否通过..."** - 根据验收标准自动判断
597
- - 如果验收标准全部满足,直接输出 ACCEPT_PASSED
609
+ parts.push(`
610
+
611
+ ## ⚠️ 全自动执行模式
612
+ **重要**: 此任务在全自动模式下执行,必须遵守以下规则:
613
+ - **不要停下来询问用户确认** - 直接执行所有验收检查
614
+ - **不要输出"继续..."或等待用户回复** - 完成验收后直接返回结果
615
+ - **不要询问"是否通过..."** - 根据验收标准自动判断
616
+ - 如果验收标准全部满足,直接输出 ACCEPT_PASSED
598
617
  - 完成后直接输出结果,不要等待任何确认`);
599
618
  }
600
619
  // 注入验收标准
601
620
  if (task.acceptanceCriteria && task.acceptanceCriteria.length > 0) {
602
- parts.push(`
603
-
604
- ## 验收标准 (必须全部满足)
621
+ parts.push(`
622
+
623
+ ## 验收标准 (必须全部满足)
605
624
  ${task.acceptanceCriteria.map((c, i) => `${i + 1}. [ ] ${c}`).join('\n')}`);
606
625
  }
607
- parts.push(`
608
- ## 验收检查清单
609
- - [ ] 功能演示/验证
610
- - [ ] 测试报告 (verify-report.md 已生成)
611
- - [ ] 代码审查通过
612
- - [ ] 文档已更新 (如需要)
613
- - [ ] 所有验收标准已满足
614
-
615
- ## 验收流程
616
-
617
- ### 1. 检查验证阶段结果
618
- 读取 \`.openmatrix/tasks/${task.id}/artifacts/verify-report.md\`
619
- 确认所有检查项已通过
620
-
621
- ### 2. 验证验收标准
622
- 逐项检查验收标准是否满足
623
-
624
- ### 3. 最终确认
625
- - 确认代码可以合并
626
- - 确认无遗留问题
627
-
628
- ## 输出要求
629
- 在 \`.openmatrix/tasks/${task.id}/artifacts/\` 目录下创建:
630
- - \`accept-report.md\` - 验收报告
631
-
632
- ## 结果格式
633
- 如果验收通过,输出:
634
- \`\`\`
635
- ACCEPT_PASSED
636
- \`\`\`
637
-
638
- 如果需要修改,输出:
639
- \`\`\`
640
- ACCEPT_NEEDS_MODIFICATION
641
- 修改建议:
642
- 1. [建议]
643
- 2. [建议]
644
- \`\`\`
645
-
646
- 如果验收失败,输出:
647
- \`\`\`
648
- ACCEPT_FAILED
649
- 失败原因:
650
- 1. [原因]
651
- \`\`\`
626
+ parts.push(`
627
+ ## 验收检查清单
628
+ - [ ] 功能演示/验证
629
+ - [ ] 测试报告 (verify-report.md 已生成)
630
+ - [ ] 代码审查通过
631
+ - [ ] 文档已更新 (如需要)
632
+ - [ ] 所有验收标准已满足
633
+
634
+ ## 验收流程
635
+
636
+ ### 1. 检查验证阶段结果
637
+ 读取 \`.openmatrix/tasks/${task.id}/artifacts/verify-report.md\`
638
+ 确认所有检查项已通过
639
+
640
+ ### 2. 验证验收标准
641
+ 逐项检查验收标准是否满足
642
+
643
+ ### 3. 最终确认
644
+ - 确认代码可以合并
645
+ - 确认无遗留问题
646
+
647
+ ## 输出要求
648
+ 在 \`.openmatrix/tasks/${task.id}/artifacts/\` 目录下创建:
649
+ - \`accept-report.md\` - 验收报告
650
+
651
+ ## 结果格式
652
+ 如果验收通过,输出:
653
+ \`\`\`
654
+ ACCEPT_PASSED
655
+ \`\`\`
656
+
657
+ 如果需要修改,输出:
658
+ \`\`\`
659
+ ACCEPT_NEEDS_MODIFICATION
660
+ 修改建议:
661
+ 1. [建议]
662
+ 2. [建议]
663
+ \`\`\`
664
+
665
+ 如果验收失败,输出:
666
+ \`\`\`
667
+ ACCEPT_FAILED
668
+ 失败原因:
669
+ 1. [原因]
670
+ \`\`\`
652
671
  `);
653
672
  return parts.join('\n');
654
673
  }
@@ -805,6 +824,9 @@ ACCEPT_FAILED
805
824
  }
806
825
  /**
807
826
  * 解析质量报告
827
+ *
828
+ * 策略:优先解析 JSON 格式,失败时使用正则表达式回退
829
+ * 支持多种测试框架输出格式(Vitest, Jest, Mocha, Tape)
808
830
  */
809
831
  parseQualityReport(output) {
810
832
  const result = {
@@ -816,13 +838,87 @@ ACCEPT_FAILED
816
838
  e2e: { passed: 0, failed: 0, skipped: 0, duration: 0 },
817
839
  acceptance: { met: 0, total: 0 }
818
840
  };
819
- // 解析测试结果
820
- const testMatch = output.match(/(\d+)\s*(?:passed|passing)/i);
821
- if (testMatch)
822
- result.tests.passed = parseInt(testMatch[1], 10);
823
- const failMatch = output.match(/(\d+)\s*(?:failed|failing)/i);
824
- if (failMatch)
825
- result.tests.failed = parseInt(failMatch[1], 10);
841
+ // 策略 1: 尝试解析 JSON 格式(质量门禁首选)
842
+ const jsonMatch = output.match(/```(?:json)?\s*\{[\s\S]*?"tests":\s*\{[\s\S]*?\}[\s\S]*?\}\s*```/);
843
+ if (jsonMatch) {
844
+ try {
845
+ const jsonStr = jsonMatch[0].replace(/```(?:json)?/g, '').replace(/```/g, '').trim();
846
+ const jsonReport = JSON.parse(jsonStr);
847
+ // 解析 tests
848
+ if (jsonReport.tests) {
849
+ result.tests.passed = jsonReport.tests.passed ?? 0;
850
+ result.tests.failed = jsonReport.tests.failed ?? 0;
851
+ result.tests.coverage = jsonReport.tests.coverage ?? 0;
852
+ }
853
+ // 解析 build
854
+ if (jsonReport.build) {
855
+ result.build.success = jsonReport.build.success ?? false;
856
+ result.build.errors = jsonReport.build.errors ?? [];
857
+ }
858
+ // 解析 lint
859
+ if (jsonReport.lint) {
860
+ result.lint.errors = jsonReport.lint.errors ?? 0;
861
+ result.lint.warnings = jsonReport.lint.warnings ?? 0;
862
+ }
863
+ // 解析 security
864
+ if (jsonReport.security) {
865
+ result.security.vulnerabilities = jsonReport.security.vulnerabilities?.length ?? 0;
866
+ }
867
+ // 解析 e2e
868
+ if (jsonReport.e2e) {
869
+ result.e2e.passed = jsonReport.e2e.passed ?? 0;
870
+ result.e2e.failed = jsonReport.e2e.failed ?? 0;
871
+ result.e2e.skipped = jsonReport.e2e.skipped ?? 0;
872
+ result.e2e.duration = jsonReport.e2e.duration ?? 0;
873
+ }
874
+ // 解析 acceptance
875
+ if (jsonReport.acceptance) {
876
+ result.acceptance.total = jsonReport.acceptance.total ?? 0;
877
+ result.acceptance.met = jsonReport.acceptance.met ?? 0;
878
+ }
879
+ // 判断是否通过
880
+ const qc = this.qualityConfig;
881
+ const testsPassed = result.tests.failed === 0;
882
+ const coverageOk = result.tests.coverage >= qc.minCoverage;
883
+ const lintOk = qc.strictLint ? result.lint.errors === 0 : true;
884
+ const buildOk = result.build.success;
885
+ const e2eOk = qc.e2eTests ? result.e2e.failed === 0 : true;
886
+ result.passed = testsPassed && coverageOk && lintOk && buildOk && e2eOk;
887
+ return result;
888
+ }
889
+ catch (e) {
890
+ console.debug('JSON report parse failed, falling back to regex:', e);
891
+ }
892
+ }
893
+ // 策略 2: 正则表达式回退 - 支持多种测试框架输出格式
894
+ // Vitest: "✓ 10 tests | 10 passed"
895
+ // Jest: "Tests: 10 passed, 10 total"
896
+ // Mocha: "10 passing"
897
+ // Tape: "# tests 10\n# ok\n# pass 10"
898
+ const testPatterns = [
899
+ /✓\s*(\d+)\s*tests.*?\|\s*(\d+)\s*passed/i, // Vitest
900
+ /Tests?:\s*(\d+)\s*passed/i, // Jest
901
+ /(\d+)\s*(?:passed|passing)/i, // Mocha/Tape
902
+ ];
903
+ for (const pattern of testPatterns) {
904
+ const match = output.match(pattern);
905
+ if (match) {
906
+ result.tests.passed = parseInt(match[1], 10);
907
+ break;
908
+ }
909
+ }
910
+ const failPatterns = [
911
+ /✗\s*(\d+)\s*tests/i, // Vitest
912
+ /Tests?:\s*(\d+)\s*failed/i, // Jest
913
+ /(\d+)\s*(?:failed|failing)/i, // Mocha/Tape
914
+ ];
915
+ for (const pattern of failPatterns) {
916
+ const match = output.match(pattern);
917
+ if (match) {
918
+ result.tests.failed = parseInt(match[1], 10);
919
+ break;
920
+ }
921
+ }
826
922
  const coverageMatch = output.match(/(?:coverage|covered).*?(\d+)%/i);
827
923
  if (coverageMatch)
828
924
  result.tests.coverage = parseInt(coverageMatch[1], 10);