openmatrix 0.1.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.
Files changed (85) hide show
  1. package/README.md +512 -0
  2. package/dist/agents/agent-runner.d.ts +152 -0
  3. package/dist/agents/agent-runner.js +656 -0
  4. package/dist/agents/base-agent.d.ts +46 -0
  5. package/dist/agents/base-agent.js +17 -0
  6. package/dist/agents/impl/coder-agent.d.ts +17 -0
  7. package/dist/agents/impl/coder-agent.js +96 -0
  8. package/dist/agents/impl/executor-agent.d.ts +32 -0
  9. package/dist/agents/impl/executor-agent.js +168 -0
  10. package/dist/agents/impl/index.d.ts +6 -0
  11. package/dist/agents/impl/index.js +17 -0
  12. package/dist/agents/impl/planner-agent.d.ts +24 -0
  13. package/dist/agents/impl/planner-agent.js +126 -0
  14. package/dist/agents/impl/researcher-agent.d.ts +17 -0
  15. package/dist/agents/impl/researcher-agent.js +133 -0
  16. package/dist/agents/impl/reviewer-agent.d.ts +17 -0
  17. package/dist/agents/impl/reviewer-agent.js +120 -0
  18. package/dist/agents/impl/tester-agent.d.ts +17 -0
  19. package/dist/agents/impl/tester-agent.js +110 -0
  20. package/dist/cli/commands/approve.d.ts +2 -0
  21. package/dist/cli/commands/approve.js +87 -0
  22. package/dist/cli/commands/meeting.d.ts +2 -0
  23. package/dist/cli/commands/meeting.js +245 -0
  24. package/dist/cli/commands/report.d.ts +2 -0
  25. package/dist/cli/commands/report.js +202 -0
  26. package/dist/cli/commands/resume.d.ts +2 -0
  27. package/dist/cli/commands/resume.js +104 -0
  28. package/dist/cli/commands/retry.d.ts +2 -0
  29. package/dist/cli/commands/retry.js +79 -0
  30. package/dist/cli/commands/start.d.ts +2 -0
  31. package/dist/cli/commands/start.js +252 -0
  32. package/dist/cli/commands/status.d.ts +2 -0
  33. package/dist/cli/commands/status.js +226 -0
  34. package/dist/cli/index.d.ts +2 -0
  35. package/dist/cli/index.js +26 -0
  36. package/dist/index.d.ts +2 -0
  37. package/dist/index.js +9 -0
  38. package/dist/orchestrator/ai-reviewer.d.ts +50 -0
  39. package/dist/orchestrator/ai-reviewer.js +326 -0
  40. package/dist/orchestrator/approval-manager.d.ts +62 -0
  41. package/dist/orchestrator/approval-manager.js +160 -0
  42. package/dist/orchestrator/executor.d.ts +114 -0
  43. package/dist/orchestrator/executor.js +325 -0
  44. package/dist/orchestrator/full-test-runner.d.ts +122 -0
  45. package/dist/orchestrator/full-test-runner.js +335 -0
  46. package/dist/orchestrator/git-commit-manager.d.ts +75 -0
  47. package/dist/orchestrator/git-commit-manager.js +248 -0
  48. package/dist/orchestrator/interactive-question-generator.d.ts +90 -0
  49. package/dist/orchestrator/interactive-question-generator.js +312 -0
  50. package/dist/orchestrator/meeting-manager.d.ts +85 -0
  51. package/dist/orchestrator/meeting-manager.js +222 -0
  52. package/dist/orchestrator/phase-executor.d.ts +198 -0
  53. package/dist/orchestrator/phase-executor.js +796 -0
  54. package/dist/orchestrator/question-generator.d.ts +22 -0
  55. package/dist/orchestrator/question-generator.js +102 -0
  56. package/dist/orchestrator/retry-manager.d.ts +41 -0
  57. package/dist/orchestrator/retry-manager.js +83 -0
  58. package/dist/orchestrator/scheduler.d.ts +62 -0
  59. package/dist/orchestrator/scheduler.js +148 -0
  60. package/dist/orchestrator/state-machine.d.ts +53 -0
  61. package/dist/orchestrator/state-machine.js +124 -0
  62. package/dist/orchestrator/task-parser.d.ts +7 -0
  63. package/dist/orchestrator/task-parser.js +63 -0
  64. package/dist/orchestrator/task-planner.d.ts +71 -0
  65. package/dist/orchestrator/task-planner.js +316 -0
  66. package/dist/storage/file-store.d.ts +12 -0
  67. package/dist/storage/file-store.js +80 -0
  68. package/dist/storage/state-manager.d.ts +31 -0
  69. package/dist/storage/state-manager.js +202 -0
  70. package/dist/types/index.d.ts +193 -0
  71. package/dist/types/index.js +30 -0
  72. package/dist/utils/logger.d.ts +41 -0
  73. package/dist/utils/logger.js +166 -0
  74. package/dist/utils/progress-reporter.d.ts +116 -0
  75. package/dist/utils/progress-reporter.js +287 -0
  76. package/package.json +50 -0
  77. package/scripts/build-check.js +19 -0
  78. package/scripts/install-skills.js +51 -0
  79. package/skills/approve.md +253 -0
  80. package/skills/meeting.md +346 -0
  81. package/skills/report.md +100 -0
  82. package/skills/resume.md +68 -0
  83. package/skills/retry.md +61 -0
  84. package/skills/start.md +449 -0
  85. package/skills/status.md +46 -0
@@ -0,0 +1,796 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PhaseExecutor = void 0;
4
+ const agent_runner_js_1 = require("../agents/agent-runner.js");
5
+ const git_commit_manager_js_1 = require("./git-commit-manager.js");
6
+ /**
7
+ * PhaseExecutor - 四阶段验证执行器 (增强版)
8
+ *
9
+ * 每个任务经历四个阶段 (TDD 模式):
10
+ * 0. TDD - 先写测试 (可选)
11
+ * 1. Develop - 开发实现
12
+ * 2. Verify - 严格质量门禁 (测试/构建/Lint/安全/验收)
13
+ * 3. Accept - 最终验收
14
+ *
15
+ * 质量级别:
16
+ * - fast: 无质量门禁,最快
17
+ * - balanced: 基础门禁 (60%覆盖率, Lint, 安全扫描)
18
+ * - strict: 严格门禁 (TDD, 80%覆盖率, 严格Lint, 安全扫描)
19
+ *
20
+ * 在 auto 模式下 (isAutoMode=true):
21
+ * - 阶段间自动流转,无需确认
22
+ * - 质量门禁失败时暂停
23
+ * - 仅在失败/异常时暂停
24
+ */
25
+ class PhaseExecutor {
26
+ stateManager;
27
+ approvalManager;
28
+ agentRunner;
29
+ gitCommitManager;
30
+ isAutoMode = false;
31
+ runId = '';
32
+ userContext = {};
33
+ minTestCoverage = 60;
34
+ /** 质量配置 */
35
+ qualityConfig;
36
+ /** 默认质量配置 (balanced) */
37
+ static DEFAULT_QUALITY = {
38
+ tdd: false,
39
+ minCoverage: 60,
40
+ strictLint: true,
41
+ securityScan: true,
42
+ level: 'balanced'
43
+ };
44
+ constructor(stateManager, approvalManager) {
45
+ this.stateManager = stateManager;
46
+ this.approvalManager = approvalManager;
47
+ this.agentRunner = new agent_runner_js_1.AgentRunner(stateManager, approvalManager);
48
+ this.gitCommitManager = new git_commit_manager_js_1.GitCommitManager();
49
+ this.qualityConfig = PhaseExecutor.DEFAULT_QUALITY;
50
+ }
51
+ /**
52
+ * 设置自动模式
53
+ */
54
+ setAutoMode(auto) {
55
+ this.isAutoMode = auto;
56
+ }
57
+ /**
58
+ * 获取自动模式状态
59
+ */
60
+ getAutoMode() {
61
+ return this.isAutoMode;
62
+ }
63
+ /**
64
+ * 设置 Run ID (用于提交信息)
65
+ */
66
+ setRunId(runId) {
67
+ this.runId = runId;
68
+ }
69
+ /**
70
+ * 设置质量配置
71
+ */
72
+ setQualityConfig(config) {
73
+ this.qualityConfig = { ...this.qualityConfig, ...config };
74
+ if (config.minCoverage !== undefined) {
75
+ this.minTestCoverage = config.minCoverage;
76
+ }
77
+ }
78
+ /**
79
+ * 获取质量配置
80
+ */
81
+ getQualityConfig() {
82
+ return this.qualityConfig;
83
+ }
84
+ /**
85
+ * 设置质量级别预设
86
+ */
87
+ setQualityLevel(level) {
88
+ const presets = {
89
+ fast: { tdd: false, minCoverage: 0, strictLint: false, securityScan: false, level: 'fast' },
90
+ balanced: { tdd: false, minCoverage: 60, strictLint: true, securityScan: true, level: 'balanced' },
91
+ strict: { tdd: true, minCoverage: 80, strictLint: true, securityScan: true, level: 'strict' }
92
+ };
93
+ this.qualityConfig = presets[level];
94
+ this.minTestCoverage = this.qualityConfig.minCoverage;
95
+ }
96
+ /**
97
+ * 设置用户上下文
98
+ */
99
+ setUserContext(context) {
100
+ this.userContext = context;
101
+ this.agentRunner.setUserContext(context);
102
+ // 从用户上下文解析覆盖率要求
103
+ if (context.testCoverage) {
104
+ const match = context.testCoverage.match(/(\d+)/);
105
+ if (match) {
106
+ this.minTestCoverage = parseInt(match[1], 10);
107
+ }
108
+ }
109
+ }
110
+ /**
111
+ * 设置最低测试覆盖率
112
+ */
113
+ setMinTestCoverage(coverage) {
114
+ this.minTestCoverage = coverage;
115
+ }
116
+ /**
117
+ * 获取最低测试覆盖率
118
+ */
119
+ getMinTestCoverage() {
120
+ return this.minTestCoverage;
121
+ }
122
+ /**
123
+ * 设置是否启用自动提交
124
+ */
125
+ setAutoCommit(enabled) {
126
+ this.gitCommitManager.setEnabled(enabled);
127
+ }
128
+ /**
129
+ * 获取 GitCommitManager 实例
130
+ */
131
+ getGitCommitManager() {
132
+ return this.gitCommitManager;
133
+ }
134
+ /**
135
+ * 获取任务当前阶段
136
+ */
137
+ getCurrentPhase(task) {
138
+ // TDD 模式: 先写测试
139
+ if (this.qualityConfig.tdd && task.phases.develop.status === 'pending') {
140
+ // 检查是否已有测试文件
141
+ return 'tdd';
142
+ }
143
+ if (task.phases.develop.status !== 'completed')
144
+ return 'develop';
145
+ if (task.phases.verify.status !== 'completed')
146
+ return 'verify';
147
+ return 'accept';
148
+ }
149
+ /**
150
+ * 准备阶段执行的 Subagent 任务
151
+ */
152
+ async preparePhaseExecution(task) {
153
+ const currentPhase = this.getCurrentPhase(task);
154
+ switch (currentPhase) {
155
+ case 'tdd':
156
+ return this.prepareTDDPhase(task);
157
+ case 'develop':
158
+ return this.prepareDevelopPhase(task);
159
+ case 'verify':
160
+ return this.prepareVerifyPhase(task);
161
+ case 'accept':
162
+ return this.prepareAcceptPhase(task);
163
+ default:
164
+ return null;
165
+ }
166
+ }
167
+ /**
168
+ * 准备 TDD 阶段 - 先写测试
169
+ */
170
+ async prepareTDDPhase(task) {
171
+ const prompt = this.buildTDDPrompt(task);
172
+ return {
173
+ subagent_type: 'general-purpose',
174
+ description: `tdd: write tests for ${task.title.slice(0, 30)}`,
175
+ prompt,
176
+ isolation: undefined,
177
+ taskId: task.id,
178
+ agentType: 'tester',
179
+ timeout: task.timeout / 2,
180
+ needsApproval: false
181
+ };
182
+ }
183
+ /**
184
+ * 准备开发阶段
185
+ */
186
+ async prepareDevelopPhase(task) {
187
+ const prompt = this.buildDevelopPrompt(task);
188
+ return {
189
+ subagent_type: this.agentRunner.mapAgentType(task.assignedAgent),
190
+ description: `develop: ${task.title.slice(0, 40)}`,
191
+ prompt,
192
+ isolation: 'worktree',
193
+ taskId: task.id,
194
+ agentType: task.assignedAgent,
195
+ timeout: task.timeout,
196
+ needsApproval: false
197
+ };
198
+ }
199
+ /**
200
+ * 构建 TDD 阶段提示词 - 先写测试
201
+ */
202
+ buildTDDPrompt(task) {
203
+ return `# TDD 阶段 - 先写测试 (Test-First)
204
+
205
+ ## 任务信息
206
+ - ID: ${task.id}
207
+ - 标题: ${task.title}
208
+ - 描述: ${task.description}
209
+
210
+ ## TDD 目标
211
+ 在编写实现代码之前,先编写测试用例。这确保:
212
+ 1. 你理解需求
213
+ 2. 代码可测试
214
+ 3. 有明确的成功标准
215
+
216
+ ## 验收标准 → 测试用例
217
+ ${task.acceptanceCriteria?.map((c, i) => `${i + 1}. ${c}`).join('\n') || '根据任务描述生成测试用例'}
218
+
219
+ ## 测试要求
220
+ 1. **覆盖正常流程** - 主要功能路径
221
+ 2. **覆盖边界情况** - 空值、极值、特殊字符
222
+ 3. **覆盖异常处理** - 错误输入、网络失败
223
+ 4. **AAA 模式** - Arrange, Act, Assert
224
+
225
+ ## 测试框架
226
+ 根据项目选择:
227
+ - TypeScript/JavaScript: Vitest, Jest
228
+ - Python: pytest
229
+ - Go: testing package
230
+
231
+ ## 输出
232
+ 1. 创建测试文件 (\`.test.ts\` 或 \`.spec.ts\`)
233
+ 2. 测试应该**失败** (因为还没实现)
234
+ 3. 输出测试文件路径
235
+
236
+ ## 验证
237
+ 运行 \`npm test\` 确认测试失败 (这是正确的!)
238
+
239
+ ## 输出格式
240
+ \`\`\`
241
+ TDD_TESTS_CREATED
242
+ 测试文件: [路径]
243
+ 测试用例数: [数量]
244
+ 预期: 全部失败 (RED 阶段)
245
+ \`\`\`
246
+ `;
247
+ }
248
+ /**
249
+ * 准备验证阶段
250
+ */
251
+ async prepareVerifyPhase(task) {
252
+ const prompt = this.buildVerifyPrompt(task);
253
+ return {
254
+ subagent_type: 'general-purpose',
255
+ description: `verify: ${task.title.slice(0, 40)}`,
256
+ prompt,
257
+ isolation: undefined, // 验证不需要隔离
258
+ taskId: task.id,
259
+ agentType: 'reviewer',
260
+ timeout: task.timeout / 2, // 验证阶段时间较短
261
+ needsApproval: false
262
+ };
263
+ }
264
+ /**
265
+ * 准备验收阶段
266
+ */
267
+ async prepareAcceptPhase(task) {
268
+ const prompt = this.buildAcceptPrompt(task);
269
+ return {
270
+ subagent_type: 'general-purpose',
271
+ description: `accept: ${task.title.slice(0, 40)}`,
272
+ prompt,
273
+ isolation: undefined,
274
+ taskId: task.id,
275
+ agentType: 'reviewer',
276
+ timeout: 60000, // 验收阶段固定 1 分钟
277
+ needsApproval: true // 验收需要确认
278
+ };
279
+ }
280
+ /**
281
+ * 构建开发阶段提示词 (增强版: 注入验收标准和用户上下文)
282
+ */
283
+ buildDevelopPrompt(task) {
284
+ const parts = [];
285
+ const isTDDMode = this.qualityConfig.tdd;
286
+ parts.push(`# 开发阶段 (Develop Phase)${isTDDMode ? ' - TDD GREEN 阶段' : ''}
287
+
288
+ ## 任务信息
289
+ - ID: ${task.id}
290
+ - 标题: ${task.title}
291
+ - 描述: ${task.description}
292
+ - 优先级: ${task.priority}
293
+ - 质量级别: ${this.qualityConfig.level}`);
294
+ // TDD 模式提示
295
+ if (isTDDMode) {
296
+ parts.push(`
297
+ ## ⚠️ TDD 模式
298
+ 你已经在上一步编写了测试。现在需要:
299
+ 1. 编写最小代码使测试通过
300
+ 2. 不要过度设计
301
+ 3. 测试通过即可 (GREEN 阶段)`);
302
+ }
303
+ // 注入用户上下文
304
+ if (this.userContext.objective) {
305
+ parts.push(`
306
+ ## 整体目标
307
+ ${this.userContext.objective}`);
308
+ }
309
+ if (this.userContext.techStack && this.userContext.techStack.length > 0) {
310
+ parts.push(`
311
+ ## 技术栈要求
312
+ ${this.userContext.techStack.map(t => `- ${t}`).join('\n')}`);
313
+ }
314
+ // 注入验收标准
315
+ if (task.acceptanceCriteria && task.acceptanceCriteria.length > 0) {
316
+ parts.push(`
317
+ ## 验收标准 (必须全部满足)
318
+ ${task.acceptanceCriteria.map((c, i) => `${i + 1}. [ ] ${c}`).join('\n')}`);
319
+ }
320
+ parts.push(`
321
+ ## 开发要求
322
+ 1. 根据任务描述编写代码
323
+ 2. 遵循项目代码规范
324
+ 3. 编写必要的注释
325
+ 4. 处理边界情况和错误
326
+ 5. 确保代码可编译
327
+
328
+ ## 编码规范 (SOLID + Clean Code)
329
+ - **S**ingle Responsibility: 每个函数只做一件事
330
+ - **O**pen/Closed: 对扩展开放,对修改关闭
331
+ - **L**iskov Substitution: 子类可替换父类
332
+ - **I**nterface Segregation: 接口要小而专注
333
+ - **D**ependency Inversion: 依赖抽象而非具体
334
+
335
+ ## 代码质量标准
336
+ - 函数长度: < 30 行
337
+ - 参数数量: < 4 个
338
+ - 嵌套深度: < 3 层
339
+ - 圈复杂度: < 10
340
+
341
+ ## 输出要求
342
+ 完成后,在 \`.openmatrix/tasks/${task.id}/artifacts/\` 目录下创建:
343
+ - \`result.md\` - 实现说明
344
+ - \`changes.txt\` - 变更文件列表
345
+
346
+ ## 完成检查清单
347
+ - [ ] 代码可编译
348
+ - [ ] 边界情况已处理
349
+ - [ ] 错误处理完善
350
+ - [ ] 无安全隐患
351
+ - [ ] 代码风格一致
352
+ - [ ] 验收标准全部满足
353
+ ${isTDDMode ? '- [ ] 所有测试通过 (GREEN)' : ''}
354
+ `);
355
+ return parts.join('\n');
356
+ }
357
+ /**
358
+ * 构建验证阶段提示词 (增强版: 严格质量门禁)
359
+ */
360
+ buildVerifyPrompt(task) {
361
+ const parts = [];
362
+ const qc = this.qualityConfig;
363
+ parts.push(`# 验证阶段 (Verify Phase) - 严格质量门禁
364
+
365
+ ## 任务信息
366
+ - ID: ${task.id}
367
+ - 标题: ${task.title}
368
+ - 质量级别: ${qc.level}
369
+
370
+ ## 🚨 质量门禁 (Quality Gates)
371
+
372
+ | 检查项 | 要求 | 失败后果 |
373
+ |--------|------|----------|
374
+ | 编译 | 无错误 | ❌ 阻止通过 |
375
+ | 测试 | 全部通过 | ❌ 阻止通过 |
376
+ | 覆盖率 | >= ${qc.minCoverage}% | ${qc.minCoverage > 0 ? '❌ 阻止通过' : '⚠️ 仅警告'} |
377
+ | Lint | ${qc.strictLint ? '无 error' : '无严重 error'} | ${qc.strictLint ? '❌ 阻止通过' : '⚠️ 仅警告'} |
378
+ | 安全 | 无高危漏洞 | ${qc.securityScan ? '❌ 阻止通过' : '⏭️ 跳过'} |
379
+ | 验收标准 | 全部满足 | ❌ 阻止通过 |
380
+
381
+ ## 自动化验证命令
382
+
383
+ ### 1. 编译检查 (必须通过)
384
+ \`\`\`bash
385
+ npm run build
386
+ \`\`\`
387
+ **预期**: 无编译错误
388
+ **失败后果**: ❌ VERIFY_FAILED
389
+
390
+ ### 2. 测试运行 (必须通过)
391
+ \`\`\`bash
392
+ npm test
393
+ \`\`\`
394
+ **预期**: 所有测试通过
395
+ **失败后果**: ❌ VERIFY_FAILED
396
+
397
+ ### 3. 覆盖率检查
398
+ \`\`\`bash
399
+ npm test -- --coverage 2>/dev/null || npm run test:coverage 2>/dev/null || echo "Coverage check skipped"
400
+ \`\`\`
401
+ **最低覆盖率**: ${qc.minCoverage}%
402
+ **失败后果**: ${qc.minCoverage > 0 ? '❌ VERIFY_FAILED' : '⚠️ 警告'}
403
+
404
+ ### 4. Lint 检查
405
+ \`\`\`bash
406
+ npm run lint || echo "No lint script configured"
407
+ \`\`\`
408
+ **要求**: ${qc.strictLint ? '无 error' : '无严重 error'}
409
+ **失败后果**: ${qc.strictLint ? '❌ VERIFY_FAILED' : '⚠️ 警告'}
410
+
411
+ ### 5. 安全扫描
412
+ ${qc.securityScan ? `\`\`\`bash
413
+ npm audit --audit-level=high || echo "Security scan skipped"
414
+ \`\`\`
415
+ **要求**: 无 high/critical 漏洞
416
+ **失败后果**: ❌ VERIFY_FAILED` : '⏭️ 已禁用'}
417
+
418
+ ### 6. 验收标准验证`);
419
+ // 注入验收标准
420
+ if (task.acceptanceCriteria && task.acceptanceCriteria.length > 0) {
421
+ parts.push(`
422
+ 逐项检查以下标准:
423
+ ${task.acceptanceCriteria.map((c, i) => `${i + 1}. [ ] ${c}`).join('\n')}
424
+ **失败后果**: ❌ VERIFY_FAILED`);
425
+ }
426
+ else {
427
+ parts.push(`
428
+ ⏭️ 无验收标准定义`);
429
+ }
430
+ parts.push(`
431
+
432
+ ## 📊 质量报告格式
433
+
434
+ 在 \`.openmatrix/tasks/${task.id}/artifacts/\` 目录下创建 \`quality-report.json\`:
435
+
436
+ \`\`\`json
437
+ {
438
+ "taskId": "${task.id}",
439
+ "timestamp": "[ISO时间]",
440
+ "tests": {
441
+ "passed": 0,
442
+ "failed": 0,
443
+ "skipped": 0,
444
+ "coverage": 0,
445
+ "status": "pass|fail"
446
+ },
447
+ "build": {
448
+ "success": true,
449
+ "errors": [],
450
+ "status": "pass|fail"
451
+ },
452
+ "lint": {
453
+ "errors": 0,
454
+ "warnings": 0,
455
+ "status": "pass|fail|warning"
456
+ },
457
+ "security": {
458
+ "vulnerabilities": [],
459
+ "status": "pass|fail"
460
+ },
461
+ "acceptance": {
462
+ "total": ${task.acceptanceCriteria?.length || 0},
463
+ "met": 0,
464
+ "details": [],
465
+ "status": "pass|fail"
466
+ },
467
+ "overall": "pass|fail|warning"
468
+ }
469
+ \`\`\`
470
+
471
+ ## 最终输出
472
+
473
+ ✅ **所有门禁通过**:
474
+ \`\`\`
475
+ VERIFY_PASSED
476
+ Quality Score: [A/B/C/D/F]
477
+ - Tests: ✅ X/X passed, Y% coverage
478
+ - Build: ✅ Success
479
+ - Lint: ✅ No errors
480
+ - Security: ✅ No vulnerabilities
481
+ - Acceptance: ✅ N/M criteria met
482
+ \`\`\`
483
+
484
+ ❌ **门禁失败**:
485
+ \`\`\`
486
+ VERIFY_FAILED
487
+ Failed Gates:
488
+ 1. [检查项]: [失败原因]
489
+ 2. [检查项]: [失败原因]
490
+
491
+ Fix Required:
492
+ 1. [修复建议]
493
+ 2. [修复建议]
494
+ \`\`\`
495
+
496
+ ## ⚠️ 重要提示
497
+ - **不要跳过任何检查**
498
+ - **不要伪造通过结果**
499
+ - 如果项目没有某个脚本,标记为 "⏭️ Skipped" 而非 "❌ Failed"
500
+ - 所有检查结果必须基于实际命令输出
501
+ `);
502
+ return parts.join('\n');
503
+ }
504
+ /**
505
+ * 构建验收阶段提示词 (增强版: 验收标准检查)
506
+ */
507
+ buildAcceptPrompt(task) {
508
+ const parts = [];
509
+ parts.push(`# 验收阶段 (Accept Phase)
510
+
511
+ ## 任务信息
512
+ - ID: ${task.id}
513
+ - 标题: ${task.title}
514
+ - 描述: ${task.description}`);
515
+ // 注入验收标准
516
+ if (task.acceptanceCriteria && task.acceptanceCriteria.length > 0) {
517
+ parts.push(`
518
+ ## 验收标准 (必须全部满足)
519
+ ${task.acceptanceCriteria.map((c, i) => `${i + 1}. [ ] ${c}`).join('\n')}`);
520
+ }
521
+ parts.push(`
522
+ ## 验收检查清单
523
+ - [ ] 功能演示/验证
524
+ - [ ] 测试报告 (verify-report.md 已生成)
525
+ - [ ] 代码审查通过
526
+ - [ ] 文档已更新 (如需要)
527
+ - [ ] 所有验收标准已满足
528
+
529
+ ## 验收流程
530
+
531
+ ### 1. 检查验证阶段结果
532
+ 读取 \`.openmatrix/tasks/${task.id}/artifacts/verify-report.md\`
533
+ 确认所有检查项已通过
534
+
535
+ ### 2. 验证验收标准
536
+ 逐项检查验收标准是否满足
537
+
538
+ ### 3. 最终确认
539
+ - 确认代码可以合并
540
+ - 确认无遗留问题
541
+
542
+ ## 输出要求
543
+ 在 \`.openmatrix/tasks/${task.id}/artifacts/\` 目录下创建:
544
+ - \`accept-report.md\` - 验收报告
545
+
546
+ ## 结果格式
547
+ 如果验收通过,输出:
548
+ \`\`\`
549
+ ACCEPT_PASSED
550
+ \`\`\`
551
+
552
+ 如果需要修改,输出:
553
+ \`\`\`
554
+ ACCEPT_NEEDS_MODIFICATION
555
+ 修改建议:
556
+ 1. [建议]
557
+ 2. [建议]
558
+ \`\`\`
559
+
560
+ 如果验收失败,输出:
561
+ \`\`\`
562
+ ACCEPT_FAILED
563
+ 失败原因:
564
+ 1. [原因]
565
+ \`\`\`
566
+ `);
567
+ return parts.join('\n');
568
+ }
569
+ /**
570
+ * 处理阶段结果
571
+ *
572
+ * 在 auto 模式下:
573
+ * - 自动进入下一阶段,needsApproval = false
574
+ * - 仅在失败时暂停
575
+ * - 自动提交代码 (如果启用)
576
+ */
577
+ async processPhaseResult(task, phase, result) {
578
+ const now = new Date().toISOString();
579
+ if (result.success) {
580
+ // 更新阶段状态
581
+ const updates = {
582
+ phases: {
583
+ ...task.phases,
584
+ [phase]: {
585
+ status: 'completed',
586
+ duration: 0,
587
+ completedAt: now
588
+ }
589
+ }
590
+ };
591
+ // 设置下一阶段
592
+ let nextPhase;
593
+ // auto 模式下不需要审批,仅在 accept 阶段且非 auto 模式时需要
594
+ let needsApproval = false;
595
+ if (phase === 'develop') {
596
+ nextPhase = 'verify';
597
+ updates.phases.verify = {
598
+ status: 'pending',
599
+ duration: null,
600
+ startedAt: now
601
+ };
602
+ updates.status = 'verify';
603
+ }
604
+ else if (phase === 'verify') {
605
+ nextPhase = 'accept';
606
+ updates.phases.accept = {
607
+ status: 'pending',
608
+ duration: null,
609
+ startedAt: now
610
+ };
611
+ updates.status = 'accept';
612
+ // 仅在非 auto 模式下需要审批
613
+ needsApproval = !this.isAutoMode;
614
+ }
615
+ else if (phase === 'accept') {
616
+ updates.status = 'completed';
617
+ }
618
+ await this.stateManager.updateTask(task.id, updates);
619
+ // 自动提交代码
620
+ if (this.runId) {
621
+ try {
622
+ const commitResult = await this.gitCommitManager.commit({
623
+ taskId: task.id,
624
+ taskTitle: task.title,
625
+ runId: this.runId,
626
+ phase,
627
+ changes: [],
628
+ impactScope: []
629
+ });
630
+ if (commitResult.success) {
631
+ console.log(`✅ Git 提交成功: ${commitResult.commitHash}`);
632
+ }
633
+ else if (commitResult.message !== 'No changes to commit') {
634
+ console.log(`⚠️ Git 提交跳过: ${commitResult.message || commitResult.error}`);
635
+ }
636
+ }
637
+ catch (error) {
638
+ console.error(`❌ Git 提交失败: ${error}`);
639
+ }
640
+ }
641
+ return {
642
+ phase,
643
+ success: true,
644
+ output: result.output,
645
+ duration: 0,
646
+ artifacts: [],
647
+ nextPhase,
648
+ needsApproval
649
+ };
650
+ }
651
+ else {
652
+ // 阶段失败
653
+ await this.stateManager.updateTask(task.id, {
654
+ status: 'failed',
655
+ error: result.error || `${phase} phase failed`
656
+ });
657
+ return {
658
+ phase,
659
+ success: false,
660
+ error: result.error,
661
+ duration: 0,
662
+ artifacts: [],
663
+ // 失败时总是需要审批/确认
664
+ needsApproval: true
665
+ };
666
+ }
667
+ }
668
+ /**
669
+ * 检查 Build 测试结果
670
+ */
671
+ parseBuildTestResult(output) {
672
+ const result = {
673
+ compile: false,
674
+ staticAnalysis: false,
675
+ dependencies: false,
676
+ package: false,
677
+ errors: []
678
+ };
679
+ // 解析编译结果
680
+ if (output.includes('npm run build') && !output.includes('error')) {
681
+ result.compile = true;
682
+ }
683
+ // 解析 lint 结果
684
+ if (output.includes('npm run lint')) {
685
+ result.staticAnalysis = !output.includes('error') && !output.includes('warning');
686
+ }
687
+ else {
688
+ result.staticAnalysis = true; // 没有 lint 脚本视为通过
689
+ }
690
+ // 解析依赖检查
691
+ if (output.includes('npm ci') || output.includes('npm install')) {
692
+ result.dependencies = !output.includes('ERR!');
693
+ }
694
+ // 解析测试结果
695
+ if (output.includes('npm test')) {
696
+ result.package = output.includes('passed') || output.includes('PASS');
697
+ }
698
+ // 收集错误
699
+ const errorLines = output.split('\n').filter(line => line.toLowerCase().includes('error') ||
700
+ line.toLowerCase().includes('failed') ||
701
+ line.toLowerCase().includes('fail'));
702
+ result.errors = errorLines;
703
+ return result;
704
+ }
705
+ /**
706
+ * 解析质量报告
707
+ */
708
+ parseQualityReport(output) {
709
+ const result = {
710
+ passed: false,
711
+ tests: { passed: 0, failed: 0, coverage: 0 },
712
+ build: { success: false, errors: [] },
713
+ lint: { errors: 0, warnings: 0 },
714
+ security: { vulnerabilities: 0 },
715
+ acceptance: { met: 0, total: 0 }
716
+ };
717
+ // 解析测试结果
718
+ const testMatch = output.match(/(\d+)\s*(?:passed|passing)/i);
719
+ if (testMatch)
720
+ result.tests.passed = parseInt(testMatch[1], 10);
721
+ const failMatch = output.match(/(\d+)\s*(?:failed|failing)/i);
722
+ if (failMatch)
723
+ result.tests.failed = parseInt(failMatch[1], 10);
724
+ const coverageMatch = output.match(/(?:coverage|covered).*?(\d+)%/i);
725
+ if (coverageMatch)
726
+ result.tests.coverage = parseInt(coverageMatch[1], 10);
727
+ // 解析构建结果
728
+ result.build.success = output.includes('VERIFY_PASSED') ||
729
+ (output.includes('npm run build') && !output.includes('error'));
730
+ // 解析 Lint 结果
731
+ const lintErrorMatch = output.match(/(\d+)\s*error/i);
732
+ if (lintErrorMatch)
733
+ result.lint.errors = parseInt(lintErrorMatch[1], 10);
734
+ const lintWarnMatch = output.match(/(\d+)\s*warning/i);
735
+ if (lintWarnMatch)
736
+ result.lint.warnings = parseInt(lintWarnMatch[1], 10);
737
+ // 解析安全漏洞
738
+ const vulnMatch = output.match(/(\d+)\s*(?:vulnerabilities|vulnerable)/i);
739
+ if (vulnMatch)
740
+ result.security.vulnerabilities = parseInt(vulnMatch[1], 10);
741
+ // 判断是否通过
742
+ const qc = this.qualityConfig;
743
+ const testsPassed = result.tests.failed === 0;
744
+ const coverageOk = result.tests.coverage >= qc.minCoverage;
745
+ const lintOk = qc.strictLint ? result.lint.errors === 0 : true;
746
+ const buildOk = result.build.success;
747
+ result.passed = testsPassed && coverageOk && lintOk && buildOk;
748
+ return result;
749
+ }
750
+ /**
751
+ * 生成质量报告 JSON
752
+ */
753
+ generateQualityReport(task, gateResult) {
754
+ const qc = this.qualityConfig;
755
+ return {
756
+ taskId: task.id,
757
+ timestamp: new Date().toISOString(),
758
+ tests: {
759
+ passed: gateResult.tests.passed,
760
+ failed: gateResult.tests.failed,
761
+ skipped: 0,
762
+ coverage: gateResult.tests.coverage,
763
+ status: gateResult.tests.failed === 0 ? 'pass' : 'fail'
764
+ },
765
+ build: {
766
+ success: gateResult.build.success,
767
+ errors: gateResult.build.errors,
768
+ status: gateResult.build.success ? 'pass' : 'fail'
769
+ },
770
+ lint: {
771
+ errors: gateResult.lint.errors,
772
+ warnings: gateResult.lint.warnings,
773
+ status: qc.strictLint && gateResult.lint.errors > 0 ? 'fail' :
774
+ gateResult.lint.warnings > 0 ? 'warning' : 'pass'
775
+ },
776
+ security: {
777
+ vulnerabilities: [],
778
+ status: gateResult.security.vulnerabilities === 0 ? 'pass' : 'fail'
779
+ },
780
+ acceptance: {
781
+ total: task.acceptanceCriteria?.length || 0,
782
+ met: gateResult.acceptance.met,
783
+ details: [],
784
+ status: gateResult.acceptance.met >= (task.acceptanceCriteria?.length || 0) ? 'pass' : 'fail'
785
+ },
786
+ overall: gateResult.passed ? 'pass' : 'fail'
787
+ };
788
+ }
789
+ /**
790
+ * 获取 AgentRunner 实例
791
+ */
792
+ getAgentRunner() {
793
+ return this.agentRunner;
794
+ }
795
+ }
796
+ exports.PhaseExecutor = PhaseExecutor;