openmatrix 0.1.50 → 0.1.52
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/dist/agents/agent-runner.d.ts +1 -26
- package/dist/cli/commands/meeting.js +55 -13
- package/dist/cli/commands/start.js +233 -82
- package/dist/orchestrator/executor.d.ts +2 -1
- package/dist/orchestrator/phase-executor.d.ts +2 -1
- package/dist/orchestrator/task-parser.d.ts +22 -0
- package/dist/orchestrator/task-parser.js +117 -17
- package/dist/orchestrator/task-planner.d.ts +18 -26
- package/dist/orchestrator/task-planner.js +190 -165
- package/dist/storage/state-manager.js +9 -9
- package/package.json +1 -1
- package/skills/approve.md +10 -10
- package/skills/auto.md +137 -187
- package/skills/meeting.md +3 -1
- package/skills/start.md +240 -626
|
@@ -10,9 +10,12 @@ exports.TaskPlanner = void 0;
|
|
|
10
10
|
* 3. 验收标准注入 (从用户回答中提取)
|
|
11
11
|
* 4. 用户上下文注入 (将用户回答注入任务描述)
|
|
12
12
|
* 5. 依赖关系分析 (自动分析任务间依赖)
|
|
13
|
+
* 6. 并行执行 (独立任务互不依赖)
|
|
14
|
+
* 7. 质量级别感知 (根据配置调整测试覆盖率)
|
|
13
15
|
*/
|
|
14
16
|
class TaskPlanner {
|
|
15
17
|
userAnswers;
|
|
18
|
+
taskCounter = 0;
|
|
16
19
|
constructor(userAnswers) {
|
|
17
20
|
this.userAnswers = userAnswers || {};
|
|
18
21
|
}
|
|
@@ -24,29 +27,29 @@ class TaskPlanner {
|
|
|
24
27
|
}
|
|
25
28
|
/**
|
|
26
29
|
* Break down a parsed task into sub-tasks
|
|
27
|
-
*
|
|
28
|
-
* 增强版: 生成更细粒度的任务,包含设计、开发、测试配对
|
|
29
30
|
*/
|
|
30
|
-
breakdown(parsedTask, answers) {
|
|
31
|
+
breakdown(parsedTask, answers, qualityConfig, plan) {
|
|
31
32
|
const breakdowns = [];
|
|
32
33
|
const seenTitles = new Set();
|
|
33
34
|
const userContext = this.extractUserContext(answers);
|
|
34
|
-
//
|
|
35
|
-
|
|
35
|
+
// 确定测试覆盖率
|
|
36
|
+
const coverageTarget = this.getCoverageTarget(qualityConfig, userContext);
|
|
37
|
+
// 构建全局上下文块(注入到每个子任务描述中,供 agent 参考)
|
|
38
|
+
const globalContext = this.buildGlobalContext(parsedTask, userContext, plan);
|
|
39
|
+
// 0. 设计阶段任务 (根据复杂度判断)
|
|
40
|
+
let designTaskId;
|
|
41
|
+
if (this.needsDesignPhase(parsedTask)) {
|
|
42
|
+
designTaskId = this.generateTaskId();
|
|
36
43
|
breakdowns.push({
|
|
37
|
-
taskId:
|
|
44
|
+
taskId: designTaskId,
|
|
38
45
|
title: '架构设计和任务规划',
|
|
39
|
-
description: `分析需求,设计整体架构,规划实现方案
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
## 输出
|
|
48
|
-
- 架构设计文档
|
|
49
|
-
- 接口定义
|
|
46
|
+
description: `分析需求,设计整体架构,规划实现方案
|
|
47
|
+
|
|
48
|
+
${globalContext}
|
|
49
|
+
|
|
50
|
+
## 输出
|
|
51
|
+
- 架构设计文档
|
|
52
|
+
- 接口定义
|
|
50
53
|
- 任务依赖图`,
|
|
51
54
|
priority: 'P0',
|
|
52
55
|
dependencies: [],
|
|
@@ -61,7 +64,7 @@ ${userContext.techStack?.join(', ') || '未指定'}
|
|
|
61
64
|
]
|
|
62
65
|
});
|
|
63
66
|
}
|
|
64
|
-
// 1.
|
|
67
|
+
// 1. 为每个目标创建开发+测试任务(并行,只依赖设计任务)
|
|
65
68
|
const devTaskIds = [];
|
|
66
69
|
for (let i = 0; i < parsedTask.goals.length; i++) {
|
|
67
70
|
const goal = parsedTask.goals[i];
|
|
@@ -70,18 +73,17 @@ ${userContext.techStack?.join(', ') || '未指定'}
|
|
|
70
73
|
continue;
|
|
71
74
|
}
|
|
72
75
|
seenTitles.add(goal);
|
|
73
|
-
// 创建开发任务
|
|
76
|
+
// 创建开发任务 — 所有开发任务并行,仅依赖设计任务
|
|
74
77
|
const devTaskId = this.generateTaskId();
|
|
75
78
|
devTaskIds.push(devTaskId);
|
|
76
79
|
const acceptanceCriteria = this.generateAcceptanceCriteria(goal, userContext);
|
|
77
80
|
breakdowns.push({
|
|
78
81
|
taskId: devTaskId,
|
|
79
82
|
title: `实现: ${goal}`,
|
|
80
|
-
description: this.buildTaskDescription(goal,
|
|
83
|
+
description: this.buildTaskDescription(goal, globalContext),
|
|
81
84
|
priority: this.determinePriority(i),
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
: (i > 0 ? [devTaskIds[i - 1]] : []), // 依赖前一个开发任务
|
|
85
|
+
// 并行: 所有开发任务只依赖设计任务(如果有),互不依赖
|
|
86
|
+
dependencies: designTaskId ? [designTaskId] : [],
|
|
85
87
|
estimatedComplexity: this.estimateComplexity(goal),
|
|
86
88
|
assignedAgent: 'coder',
|
|
87
89
|
phase: 'develop',
|
|
@@ -93,14 +95,14 @@ ${userContext.techStack?.join(', ') || '未指定'}
|
|
|
93
95
|
breakdowns.push({
|
|
94
96
|
taskId: testTaskId,
|
|
95
97
|
title: `测试: ${goal}`,
|
|
96
|
-
description: this.buildTestDescription(goal, devTaskId,
|
|
98
|
+
description: this.buildTestDescription(goal, devTaskId, coverageTarget, globalContext),
|
|
97
99
|
priority: this.determinePriority(i),
|
|
98
|
-
dependencies: [devTaskId], //
|
|
100
|
+
dependencies: [devTaskId], // 测试依赖对应的开发任务
|
|
99
101
|
estimatedComplexity: 'medium',
|
|
100
102
|
assignedAgent: 'tester',
|
|
101
103
|
phase: 'verify',
|
|
102
104
|
acceptanceCriteria: [
|
|
103
|
-
`单元测试覆盖率 >= ${
|
|
105
|
+
`单元测试覆盖率 >= ${coverageTarget}%`,
|
|
104
106
|
'边界情况已测试',
|
|
105
107
|
'异常处理已验证',
|
|
106
108
|
'所有测试通过'
|
|
@@ -114,18 +116,20 @@ ${userContext.techStack?.join(', ') || '未指定'}
|
|
|
114
116
|
breakdowns.push({
|
|
115
117
|
taskId: this.generateTaskId(),
|
|
116
118
|
title: '代码审查',
|
|
117
|
-
description: `对所有开发任务进行代码审查
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
-
|
|
119
|
+
description: `对所有开发任务进行代码审查
|
|
120
|
+
|
|
121
|
+
${globalContext}
|
|
122
|
+
|
|
123
|
+
## 审查范围
|
|
124
|
+
${devTaskIds.map(id => `- ${id}`).join('\n')}
|
|
125
|
+
|
|
126
|
+
## 审查要点
|
|
127
|
+
- 代码质量
|
|
128
|
+
- 安全性
|
|
129
|
+
- 性能
|
|
126
130
|
- 最佳实践`,
|
|
127
131
|
priority: 'P1',
|
|
128
|
-
dependencies: devTaskIds,
|
|
132
|
+
dependencies: devTaskIds, // 审查依赖所有开发任务完成
|
|
129
133
|
estimatedComplexity: 'medium',
|
|
130
134
|
assignedAgent: 'reviewer',
|
|
131
135
|
phase: 'verify',
|
|
@@ -142,14 +146,13 @@ ${devTaskIds.map(id => `- ${id}`).join('\n')}
|
|
|
142
146
|
breakdowns.push({
|
|
143
147
|
taskId: this.generateTaskId(),
|
|
144
148
|
title: '集成测试',
|
|
145
|
-
description: `验证所有交付物正确集成
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
-
|
|
152
|
-
- 端到端流程
|
|
149
|
+
description: `验证所有交付物正确集成
|
|
150
|
+
|
|
151
|
+
${globalContext}
|
|
152
|
+
|
|
153
|
+
## 测试范围
|
|
154
|
+
- 模块间接口
|
|
155
|
+
- 端到端流程
|
|
153
156
|
- 数据流验证`,
|
|
154
157
|
priority: 'P1',
|
|
155
158
|
dependencies: devTaskIds,
|
|
@@ -164,11 +167,10 @@ ${parsedTask.deliverables.map(d => `- ${d}`).join('\n')}
|
|
|
164
167
|
]
|
|
165
168
|
});
|
|
166
169
|
}
|
|
167
|
-
// 4. E2E 测试任务 (
|
|
170
|
+
// 4. E2E 测试任务 (如果启用)
|
|
168
171
|
if (userContext.e2eTests) {
|
|
169
172
|
const e2eTaskId = this.generateTaskId();
|
|
170
173
|
const e2eType = userContext.e2eType || 'web';
|
|
171
|
-
// E2E 测试依赖所有开发任务和单元测试任务
|
|
172
174
|
const allTestDependencies = [...devTaskIds];
|
|
173
175
|
breakdowns.forEach(b => {
|
|
174
176
|
if (b.phase === 'verify' && b.title.startsWith('测试:')) {
|
|
@@ -179,8 +181,8 @@ ${parsedTask.deliverables.map(d => `- ${d}`).join('\n')}
|
|
|
179
181
|
taskId: e2eTaskId,
|
|
180
182
|
title: '端到端(E2E)测试',
|
|
181
183
|
description: this.buildE2ETestDescription(e2eType, parsedTask, userContext),
|
|
182
|
-
priority: 'P0',
|
|
183
|
-
dependencies: allTestDependencies,
|
|
184
|
+
priority: 'P0',
|
|
185
|
+
dependencies: allTestDependencies,
|
|
184
186
|
estimatedComplexity: 'high',
|
|
185
187
|
assignedAgent: 'tester',
|
|
186
188
|
phase: 'verify',
|
|
@@ -198,14 +200,14 @@ ${parsedTask.deliverables.map(d => `- ${d}`).join('\n')}
|
|
|
198
200
|
breakdowns.push({
|
|
199
201
|
taskId: this.generateTaskId(),
|
|
200
202
|
title: '文档编写',
|
|
201
|
-
description: `编写项目文档
|
|
202
|
-
|
|
203
|
-
## 文档级别
|
|
204
|
-
${userContext.documentationLevel}
|
|
205
|
-
|
|
206
|
-
## 文档内容
|
|
207
|
-
- README 更新
|
|
208
|
-
- API 文档
|
|
203
|
+
description: `编写项目文档
|
|
204
|
+
|
|
205
|
+
## 文档级别
|
|
206
|
+
${userContext.documentationLevel}
|
|
207
|
+
|
|
208
|
+
## 文档内容
|
|
209
|
+
- README 更新
|
|
210
|
+
- API 文档
|
|
209
211
|
- 使用说明`,
|
|
210
212
|
priority: 'P2',
|
|
211
213
|
dependencies: devTaskIds,
|
|
@@ -221,6 +223,40 @@ ${userContext.documentationLevel}
|
|
|
221
223
|
}
|
|
222
224
|
return breakdowns;
|
|
223
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* 判断是否需要设计阶段
|
|
228
|
+
*
|
|
229
|
+
* 条件: 多个 goal,或 goal 包含复杂关键词
|
|
230
|
+
*/
|
|
231
|
+
needsDesignPhase(parsedTask) {
|
|
232
|
+
if (parsedTask.goals.length > 1)
|
|
233
|
+
return true;
|
|
234
|
+
// 单 goal 但包含复杂关键词
|
|
235
|
+
const complexKeywords = [
|
|
236
|
+
'系统', '架构', '模块', '集成', '完整', '平台',
|
|
237
|
+
'体系', '框架', '全栈', '端到端', '多个', '一系列',
|
|
238
|
+
'system', 'architecture', 'framework', 'fullstack', 'integration'
|
|
239
|
+
];
|
|
240
|
+
const allText = `${parsedTask.title} ${parsedTask.goals.join(' ')} ${parsedTask.description}`.toLowerCase();
|
|
241
|
+
return complexKeywords.some(kw => allText.includes(kw.toLowerCase()));
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* 获取测试覆盖率目标
|
|
245
|
+
*/
|
|
246
|
+
getCoverageTarget(qualityConfig, userContext) {
|
|
247
|
+
// 优先使用 qualityConfig
|
|
248
|
+
if (qualityConfig) {
|
|
249
|
+
return qualityConfig.minCoverage;
|
|
250
|
+
}
|
|
251
|
+
// 其次使用用户回答
|
|
252
|
+
if (userContext?.testCoverage) {
|
|
253
|
+
const match = userContext.testCoverage.match(/(\d+)/);
|
|
254
|
+
if (match)
|
|
255
|
+
return parseInt(match[1], 10);
|
|
256
|
+
}
|
|
257
|
+
// 默认
|
|
258
|
+
return 60;
|
|
259
|
+
}
|
|
224
260
|
/**
|
|
225
261
|
* 提取用户上下文
|
|
226
262
|
*/
|
|
@@ -237,117 +273,122 @@ ${userContext.documentationLevel}
|
|
|
237
273
|
additionalContext: answers
|
|
238
274
|
};
|
|
239
275
|
}
|
|
240
|
-
/**
|
|
241
|
-
* 解析数组类型的回答
|
|
242
|
-
*/
|
|
243
276
|
parseArrayAnswer(answer) {
|
|
244
277
|
if (!answer)
|
|
245
278
|
return [];
|
|
246
|
-
// 处理逗号分隔或换行分隔的答案
|
|
247
279
|
return answer.split(/[,,\n]/).map(s => s.trim()).filter(Boolean);
|
|
248
280
|
}
|
|
249
281
|
/**
|
|
250
|
-
*
|
|
282
|
+
* 构建全局上下文块(注入到每个子任务描述中)
|
|
251
283
|
*/
|
|
252
|
-
|
|
284
|
+
buildGlobalContext(parsedTask, userContext, plan) {
|
|
253
285
|
const parts = [];
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
286
|
+
if (parsedTask.title) {
|
|
287
|
+
parts.push(`## 整体任务\n${parsedTask.title}`);
|
|
288
|
+
}
|
|
289
|
+
if (parsedTask.description) {
|
|
290
|
+
parts.push(`## 任务描述\n${parsedTask.description}`);
|
|
291
|
+
}
|
|
292
|
+
if (plan) {
|
|
293
|
+
parts.push(`## 执行计划\n${plan}`);
|
|
294
|
+
}
|
|
295
|
+
if (parsedTask.goals.length > 0) {
|
|
296
|
+
parts.push(`## 所有目标\n${parsedTask.goals.map((g, i) => `${i + 1}. ${g}`).join('\n')}`);
|
|
297
|
+
}
|
|
298
|
+
if (parsedTask.constraints.length > 0) {
|
|
299
|
+
parts.push(`## 约束条件\n${parsedTask.constraints.map(c => `- ${c}`).join('\n')}`);
|
|
300
|
+
}
|
|
301
|
+
if (parsedTask.deliverables.length > 0) {
|
|
302
|
+
parts.push(`## 交付物\n${parsedTask.deliverables.map(d => `- ${d}`).join('\n')}`);
|
|
257
303
|
}
|
|
258
304
|
if (userContext.techStack && userContext.techStack.length > 0) {
|
|
259
|
-
parts.push(`##
|
|
305
|
+
parts.push(`## 技术栈\n${userContext.techStack.map(t => `- ${t}`).join('\n')}`);
|
|
260
306
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
307
|
+
if (userContext.additionalContext) {
|
|
308
|
+
const relevantAnswers = Object.entries(userContext.additionalContext).filter(([key]) => !['目标', '技术栈', '测试', '文档', 'objective', 'techStack', 'testCoverage', 'documentationLevel'].includes(key));
|
|
309
|
+
if (relevantAnswers.length > 0) {
|
|
310
|
+
parts.push(`## 其他要求\n${relevantAnswers.map(([k, v]) => `- ${k}: ${v}`).join('\n')}`);
|
|
311
|
+
}
|
|
265
312
|
}
|
|
266
|
-
parts.push(`## 输出要求
|
|
267
|
-
- 完成功能实现
|
|
268
|
-
- 代码可编译
|
|
269
|
-
- 遵循项目规范
|
|
270
|
-
- 添加必要注释`);
|
|
271
313
|
return parts.join('\n');
|
|
272
314
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
${
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
-
|
|
292
|
-
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
-
|
|
315
|
+
buildTaskDescription(goal, globalContext) {
|
|
316
|
+
return `## 当前子任务目标\n${goal}\n\n${globalContext}\n\n## 输出要求
|
|
317
|
+
- 完成功能实现
|
|
318
|
+
- 代码可编译
|
|
319
|
+
- 遵循项目规范
|
|
320
|
+
- 添加必要注释`;
|
|
321
|
+
}
|
|
322
|
+
buildTestDescription(goal, devTaskId, coverageTarget, globalContext) {
|
|
323
|
+
return `## 测试目标
|
|
324
|
+
为 "${goal}" 编写测试用例
|
|
325
|
+
|
|
326
|
+
${globalContext}
|
|
327
|
+
|
|
328
|
+
## 关联开发任务
|
|
329
|
+
${devTaskId}
|
|
330
|
+
|
|
331
|
+
## 测试要求
|
|
332
|
+
- 单元测试覆盖率 >= ${coverageTarget}%
|
|
333
|
+
- 测试正常流程
|
|
334
|
+
- 测试边界情况
|
|
335
|
+
- 测试异常处理
|
|
336
|
+
|
|
337
|
+
## 测试文件
|
|
338
|
+
- 创建 \`.test.ts\` 或 \`.spec.ts\` 文件
|
|
339
|
+
- 放置在与源文件相同目录或 \`tests/\` 目录
|
|
340
|
+
|
|
341
|
+
## 输出
|
|
342
|
+
- 测试文件
|
|
343
|
+
- 测试报告
|
|
297
344
|
- 覆盖率报告`;
|
|
298
345
|
}
|
|
299
|
-
/**
|
|
300
|
-
* 构建 E2E 测试任务描述
|
|
301
|
-
*/
|
|
302
346
|
buildE2ETestDescription(e2eType, parsedTask, userContext) {
|
|
303
347
|
const typeConfig = this.getE2ETypeConfig(e2eType);
|
|
304
|
-
return `## E2E 测试目标
|
|
305
|
-
执行完整的端到端测试,验证关键用户流程
|
|
306
|
-
|
|
307
|
-
## 应用类型
|
|
308
|
-
${typeConfig.description}
|
|
309
|
-
|
|
310
|
-
## 测试框架
|
|
311
|
-
${typeConfig.frameworks.map(f => `- ${f}`).join('\n')}
|
|
312
|
-
|
|
313
|
-
## 测试范围
|
|
314
|
-
${parsedTask.goals.map((g, i) => `${i + 1}. ${g}`).join('\n')}
|
|
315
|
-
|
|
316
|
-
## 关键用户流程
|
|
317
|
-
根据应用功能,测试以下流程:
|
|
318
|
-
${this.generateUserFlows(parsedTask, e2eType)}
|
|
319
|
-
|
|
320
|
-
## 测试环境
|
|
321
|
-
${typeConfig.environments.map(e => `- ${e}`).join('\n')}
|
|
322
|
-
|
|
323
|
-
## 测试要求
|
|
324
|
-
1. **关键路径覆盖**: 所有核心用户流程必须有 E2E 测试
|
|
325
|
-
2. **断言完整**: 每个测试步骤必须有明确的断言
|
|
326
|
-
3. **等待策略**: 使用合理的等待机制,避免硬编码延迟
|
|
327
|
-
4. **数据隔离**: 测试数据独立,不影响其他测试
|
|
328
|
-
5. **清理机制**: 测试后清理创建的数据
|
|
329
|
-
|
|
330
|
-
## 输出要求
|
|
331
|
-
- E2E 测试文件 (tests/e2e/*.spec.ts)
|
|
332
|
-
- 测试执行报告
|
|
333
|
-
- 截图/录像 (失败时)
|
|
334
|
-
- 测试覆盖率报告 (如有)
|
|
335
|
-
|
|
336
|
-
## 运行命令
|
|
337
|
-
\`\`\`bash
|
|
338
|
-
${typeConfig.runCommand}
|
|
339
|
-
\`\`\`
|
|
340
|
-
|
|
341
|
-
## 验收标准
|
|
342
|
-
- [ ] 所有 E2E 测试用例通过
|
|
343
|
-
- [ ] 关键用户流程验证完成
|
|
344
|
-
- [ ] 跨浏览器/设备兼容性验证
|
|
345
|
-
- [ ] E2E 测试报告已生成
|
|
348
|
+
return `## E2E 测试目标
|
|
349
|
+
执行完整的端到端测试,验证关键用户流程
|
|
350
|
+
|
|
351
|
+
## 应用类型
|
|
352
|
+
${typeConfig.description}
|
|
353
|
+
|
|
354
|
+
## 测试框架
|
|
355
|
+
${typeConfig.frameworks.map(f => `- ${f}`).join('\n')}
|
|
356
|
+
|
|
357
|
+
## 测试范围
|
|
358
|
+
${parsedTask.goals.map((g, i) => `${i + 1}. ${g}`).join('\n')}
|
|
359
|
+
|
|
360
|
+
## 关键用户流程
|
|
361
|
+
根据应用功能,测试以下流程:
|
|
362
|
+
${this.generateUserFlows(parsedTask, e2eType)}
|
|
363
|
+
|
|
364
|
+
## 测试环境
|
|
365
|
+
${typeConfig.environments.map(e => `- ${e}`).join('\n')}
|
|
366
|
+
|
|
367
|
+
## 测试要求
|
|
368
|
+
1. **关键路径覆盖**: 所有核心用户流程必须有 E2E 测试
|
|
369
|
+
2. **断言完整**: 每个测试步骤必须有明确的断言
|
|
370
|
+
3. **等待策略**: 使用合理的等待机制,避免硬编码延迟
|
|
371
|
+
4. **数据隔离**: 测试数据独立,不影响其他测试
|
|
372
|
+
5. **清理机制**: 测试后清理创建的数据
|
|
373
|
+
|
|
374
|
+
## 输出要求
|
|
375
|
+
- E2E 测试文件 (tests/e2e/*.spec.ts)
|
|
376
|
+
- 测试执行报告
|
|
377
|
+
- 截图/录像 (失败时)
|
|
378
|
+
- 测试覆盖率报告 (如有)
|
|
379
|
+
|
|
380
|
+
## 运行命令
|
|
381
|
+
\`\`\`bash
|
|
382
|
+
${typeConfig.runCommand}
|
|
383
|
+
\`\`\`
|
|
384
|
+
|
|
385
|
+
## 验收标准
|
|
386
|
+
- [ ] 所有 E2E 测试用例通过
|
|
387
|
+
- [ ] 关键用户流程验证完成
|
|
388
|
+
- [ ] 跨浏览器/设备兼容性验证
|
|
389
|
+
- [ ] E2E 测试报告已生成
|
|
346
390
|
- [ ] 无阻塞级别的缺陷`;
|
|
347
391
|
}
|
|
348
|
-
/**
|
|
349
|
-
* 获取 E2E 测试类型配置
|
|
350
|
-
*/
|
|
351
392
|
getE2ETypeConfig(type) {
|
|
352
393
|
const configs = {
|
|
353
394
|
web: {
|
|
@@ -371,13 +412,9 @@ ${typeConfig.runCommand}
|
|
|
371
412
|
};
|
|
372
413
|
return configs[type];
|
|
373
414
|
}
|
|
374
|
-
/**
|
|
375
|
-
* 生成用户流程测试用例
|
|
376
|
-
*/
|
|
377
415
|
generateUserFlows(parsedTask, type) {
|
|
378
416
|
const flows = [];
|
|
379
417
|
const goals = parsedTask.goals;
|
|
380
|
-
// 根据目标生成用户流程
|
|
381
418
|
goals.forEach((goal, i) => {
|
|
382
419
|
flows.push(`\n### 流程 ${i + 1}: ${goal}`);
|
|
383
420
|
flows.push('```gherkin');
|
|
@@ -391,16 +428,6 @@ ${typeConfig.runCommand}
|
|
|
391
428
|
});
|
|
392
429
|
return flows.join('\n');
|
|
393
430
|
}
|
|
394
|
-
/**
|
|
395
|
-
* 解析覆盖率数值
|
|
396
|
-
*/
|
|
397
|
-
parseCoverage(coverageStr) {
|
|
398
|
-
const match = coverageStr.match(/(\d+)/);
|
|
399
|
-
return match ? parseInt(match[1], 10) : 60;
|
|
400
|
-
}
|
|
401
|
-
/**
|
|
402
|
-
* 生成验收标准
|
|
403
|
-
*/
|
|
404
431
|
generateAcceptanceCriteria(goal, userContext) {
|
|
405
432
|
const criteria = [
|
|
406
433
|
`功能 "${goal}" 已实现`,
|
|
@@ -419,12 +446,10 @@ ${typeConfig.runCommand}
|
|
|
419
446
|
return criteria;
|
|
420
447
|
}
|
|
421
448
|
generateTaskId() {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
return `TASK-${timestamp}${rand}`;
|
|
449
|
+
this.taskCounter++;
|
|
450
|
+
return `TASK-${String(this.taskCounter).padStart(3, '0')}`;
|
|
425
451
|
}
|
|
426
452
|
determinePriority(goalIndex) {
|
|
427
|
-
// First goal is highest priority
|
|
428
453
|
if (goalIndex === 0)
|
|
429
454
|
return 'P1';
|
|
430
455
|
return 'P2';
|
|
@@ -74,7 +74,7 @@ class StateManager {
|
|
|
74
74
|
createdAt: now,
|
|
75
75
|
updatedAt: now
|
|
76
76
|
};
|
|
77
|
-
await this.store.writeJson(`tasks/${taskId}
|
|
77
|
+
await this.store.writeJson(`tasks/${taskId}.json`, task);
|
|
78
78
|
// Update statistics
|
|
79
79
|
const state = await this.getState();
|
|
80
80
|
await this.updateState({
|
|
@@ -87,7 +87,7 @@ class StateManager {
|
|
|
87
87
|
return task;
|
|
88
88
|
}
|
|
89
89
|
async getTask(taskId) {
|
|
90
|
-
return await this.store.readJson(`tasks/${taskId}
|
|
90
|
+
return await this.store.readJson(`tasks/${taskId}.json`);
|
|
91
91
|
}
|
|
92
92
|
async updateTask(taskId, updates) {
|
|
93
93
|
const task = await this.getTask(taskId);
|
|
@@ -99,17 +99,17 @@ class StateManager {
|
|
|
99
99
|
...updates,
|
|
100
100
|
updatedAt: new Date().toISOString()
|
|
101
101
|
};
|
|
102
|
-
await this.store.writeJson(`tasks/${taskId}
|
|
102
|
+
await this.store.writeJson(`tasks/${taskId}.json`, updatedTask);
|
|
103
103
|
// Update statistics if status changed
|
|
104
104
|
if (updates.status && updates.status !== oldStatus) {
|
|
105
105
|
await this.updateTaskStatistics(oldStatus, updates.status);
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
async listTasks() {
|
|
109
|
-
const
|
|
109
|
+
const files = await this.store.listFiles('tasks');
|
|
110
110
|
const tasks = [];
|
|
111
|
-
for (const
|
|
112
|
-
const task = await this.
|
|
111
|
+
for (const file of files) {
|
|
112
|
+
const task = await this.store.readJson(`tasks/${file}`);
|
|
113
113
|
if (task)
|
|
114
114
|
tasks.push(task);
|
|
115
115
|
}
|
|
@@ -144,9 +144,9 @@ class StateManager {
|
|
|
144
144
|
return `run-${date}-${rand}`;
|
|
145
145
|
}
|
|
146
146
|
generateTaskId() {
|
|
147
|
-
const
|
|
148
|
-
const
|
|
149
|
-
return `TASK-${
|
|
147
|
+
const count = this.stateCache?.statistics.totalTasks ?? 0;
|
|
148
|
+
const seq = count + 1;
|
|
149
|
+
return `TASK-${String(seq).padStart(3, '0')}`;
|
|
150
150
|
}
|
|
151
151
|
// ============ Approval Methods ============
|
|
152
152
|
async saveApproval(approval) {
|
package/package.json
CHANGED
package/skills/approve.md
CHANGED
|
@@ -152,7 +152,7 @@ description: 审批待处理项(包括计划、合并、部署、Meeting)
|
|
|
152
152
|
|
|
153
153
|
5. **执行审批**
|
|
154
154
|
```bash
|
|
155
|
-
openmatrix approve <approvalId>
|
|
155
|
+
openmatrix approve <approvalId> -d <approve|reject|modify> [-c "备注"]
|
|
156
156
|
```
|
|
157
157
|
|
|
158
158
|
6. **更新状态**
|
|
@@ -215,17 +215,17 @@ Meeting 审批需要更细致的交互:
|
|
|
215
215
|
|
|
216
216
|
```bash
|
|
217
217
|
# 列出待审批
|
|
218
|
-
openmatrix approve
|
|
218
|
+
openmatrix approve
|
|
219
219
|
|
|
220
220
|
# 处理审批
|
|
221
|
-
openmatrix approve APPR-001
|
|
222
|
-
openmatrix approve APPR-001
|
|
223
|
-
openmatrix approve APPR-001
|
|
224
|
-
|
|
225
|
-
# Meeting 专用
|
|
226
|
-
openmatrix
|
|
227
|
-
openmatrix
|
|
228
|
-
openmatrix
|
|
221
|
+
openmatrix approve APPR-001 -d approve -c "同意此方案"
|
|
222
|
+
openmatrix approve APPR-001 -d reject -c "需要重新设计"
|
|
223
|
+
openmatrix approve APPR-001 -d modify -c "增加测试覆盖率要求"
|
|
224
|
+
|
|
225
|
+
# Meeting 专用 (使用 meeting 命令)
|
|
226
|
+
openmatrix meeting APPR-002 --action provide-info --info "数据库连接字符串是..."
|
|
227
|
+
openmatrix meeting APPR-002 --action skip --message "此任务可选"
|
|
228
|
+
openmatrix meeting APPR-002 --action cancel --message "需求变更,停止执行"
|
|
229
229
|
```
|
|
230
230
|
|
|
231
231
|
## 与执行循环的集成
|